login and dashboard pages
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
recticel/
|
||||||
10
py_app/app/__init__.py
Normal file
10
py_app/app/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
def create_app():
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config['SECRET_KEY'] = 'Recticel a plecat Aquinos a falimentat Innofa a venit'
|
||||||
|
|
||||||
|
from .routes import bp
|
||||||
|
app.register_blueprint(bp)
|
||||||
|
|
||||||
|
return app
|
||||||
BIN
py_app/app/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
py_app/app/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
py_app/app/__pycache__/routes.cpython-311.pyc
Normal file
BIN
py_app/app/__pycache__/routes.cpython-311.pyc
Normal file
Binary file not shown.
33
py_app/app/routes.py
Normal file
33
py_app/app/routes.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
from flask import Blueprint, render_template, redirect, url_for, request, flash, session
|
||||||
|
|
||||||
|
bp = Blueprint('main', __name__)
|
||||||
|
|
||||||
|
# Dummy user data
|
||||||
|
users = {"admin@home.com": "1234"}
|
||||||
|
|
||||||
|
@bp.route('/login', methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if request.method == 'POST':
|
||||||
|
email = request.form['email']
|
||||||
|
password = request.form['password']
|
||||||
|
if email in users and users[email] == password:
|
||||||
|
session['user'] = email
|
||||||
|
return redirect(url_for('main.dashboard'))
|
||||||
|
else:
|
||||||
|
flash('Invalid credentials. Please try again.')
|
||||||
|
return render_template('login.html')
|
||||||
|
|
||||||
|
@bp.route('/dashboard')
|
||||||
|
def dashboard():
|
||||||
|
if 'user' not in session:
|
||||||
|
return redirect(url_for('main.login'))
|
||||||
|
return render_template('dashboard.html')
|
||||||
|
|
||||||
|
@bp.route('/logout')
|
||||||
|
def logout():
|
||||||
|
session.pop('user', None)
|
||||||
|
return redirect(url_for('main.login'))
|
||||||
|
|
||||||
|
@bp.route('/settings')
|
||||||
|
def settings():
|
||||||
|
return render_template('settings.html')
|
||||||
BIN
py_app/app/static/logo_login.jpg
Normal file
BIN
py_app/app/static/logo_login.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 202 KiB |
BIN
py_app/app/static/scan_me.jpg
Normal file
BIN
py_app/app/static/scan_me.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
34
py_app/app/static/script.js
Normal file
34
py_app/app/static/script.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const themeToggle = document.getElementById('theme-toggle');
|
||||||
|
const body = document.body;
|
||||||
|
|
||||||
|
// Check for saved theme in localStorage
|
||||||
|
const savedTheme = localStorage.getItem('theme');
|
||||||
|
if (savedTheme) {
|
||||||
|
body.className = savedTheme;
|
||||||
|
updateButtonText();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle theme on button click
|
||||||
|
if (themeToggle) {
|
||||||
|
themeToggle.addEventListener('click', () => {
|
||||||
|
if (body.classList.contains('light-mode')) {
|
||||||
|
body.className = 'dark-mode';
|
||||||
|
localStorage.setItem('theme', 'dark-mode');
|
||||||
|
} else {
|
||||||
|
body.className = 'light-mode';
|
||||||
|
localStorage.setItem('theme', 'light-mode');
|
||||||
|
}
|
||||||
|
updateButtonText();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to update the button text
|
||||||
|
function updateButtonText() {
|
||||||
|
if (body.classList.contains('light-mode')) {
|
||||||
|
themeToggle.textContent = 'Change to dark theme';
|
||||||
|
} else {
|
||||||
|
themeToggle.textContent = 'Change to light theme';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
264
py_app/app/static/style.css
Normal file
264
py_app/app/static/style.css
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background-color: #f4f4f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 98%;
|
||||||
|
margin: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0; /* Remove padding */
|
||||||
|
background: none; /* Remove white background */
|
||||||
|
border-radius: 0; /* Remove rounded corners */
|
||||||
|
box-shadow: none; /* Remove shadow */
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-page {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #f4f4f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding: 10px 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-header .logo {
|
||||||
|
width: 60px; /* Increased from 50px to 60px (20% larger) */
|
||||||
|
height: auto;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-header .page-title {
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-header .user-info {
|
||||||
|
margin-right: 15px;
|
||||||
|
font-size: 1em;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-header .logout-button {
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 1em;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-header .logout-button:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
width: 100%; /* Full width */
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 10px; /* Reduce padding between logo and login container */
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-logo {
|
||||||
|
max-height: 90vh; /* Scale the logo to fit the page height */
|
||||||
|
width: auto; /* Maintain aspect ratio */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container {
|
||||||
|
width: 600px; /* Set a fixed width for the login container */
|
||||||
|
background: #fff;
|
||||||
|
padding: 15px 30px 15px 15px; /* Add 30px padding to the right */
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
margin: 0 0 0 20px; /* Move the container closer to the picture */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container h2 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 15px; /* Reduce spacing below the title */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container label {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container input {
|
||||||
|
margin-bottom: 10px; /* Reduce spacing between inputs */
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 1em;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container button {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 1em;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container button:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode styles */
|
||||||
|
body.light-mode {
|
||||||
|
background-color: #f4f4f9;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.light-mode {
|
||||||
|
background-color: #f4f4f9;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode styles for user info */
|
||||||
|
body.light-mode .user-info {
|
||||||
|
color: #333; /* Darker text for light mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode styles */
|
||||||
|
body.dark-mode {
|
||||||
|
background-color: #121212;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.dark-mode {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode styles for user info */
|
||||||
|
body.dark-mode .user-info {
|
||||||
|
color: #ccc; /* Lighter text for dark mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide the header only on the login page */
|
||||||
|
body.light-mode.login-page header,
|
||||||
|
body.dark-mode.login-page header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the header is displayed on other pages */
|
||||||
|
body.light-mode header,
|
||||||
|
body.dark-mode header {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Common styles */
|
||||||
|
.theme-toggle {
|
||||||
|
margin-right: 15px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 1em;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-button {
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 1em;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-button:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card styles for light mode */
|
||||||
|
body.light-mode .card {
|
||||||
|
background: #fff;
|
||||||
|
color: #000;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card styles for dark mode */
|
||||||
|
body.dark-mode .card {
|
||||||
|
background: #1e1e1e;
|
||||||
|
color: #fff;
|
||||||
|
border: 1px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Common card styles */
|
||||||
|
.card {
|
||||||
|
width: 400px; /* Fixed width */
|
||||||
|
height: 150px; /* Fixed height */
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
margin: 20px auto; /* Center the card horizontally */
|
||||||
|
text-align: center;
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease, border 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card h3 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card p {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: inherit; /* Inherit text color from the card */
|
||||||
|
}
|
||||||
|
|
||||||
|
.card .btn {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 1em;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #007bff;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card .btn:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
34
py_app/app/templates/base.html
Normal file
34
py_app/app/templates/base.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{% block title %}Flask App{% endblock %}</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||||
|
</head>
|
||||||
|
<body class="light-mode">
|
||||||
|
{% if request.endpoint != 'main.login' %}
|
||||||
|
<header>
|
||||||
|
<div class="header-content">
|
||||||
|
<div class="left-header">
|
||||||
|
<img src="{{ url_for('static', filename='scan_me.jpg') }}" alt="Logo" class="logo">
|
||||||
|
{% if request.endpoint == 'main.dashboard' %}
|
||||||
|
<span class="page-title">Welcome to Dashboard</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="right-header">
|
||||||
|
<button id="theme-toggle" class="theme-toggle">Change to dark theme</button>
|
||||||
|
{% if 'user' in session %}
|
||||||
|
<span class="user-info">You are logged in as {{ session['user'] }}</span>
|
||||||
|
<a href="{{ url_for('main.logout') }}" class="logout-button">Logout</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
{% endif %}
|
||||||
|
<div class="container">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
<script src="{{ url_for('static', filename='script.js') }}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
11
py_app/app/templates/dashboard.html
Normal file
11
py_app/app/templates/dashboard.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Dashboard{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="card">
|
||||||
|
<h3>Manage Settings</h3>
|
||||||
|
<p>Access and manage application settings.</p>
|
||||||
|
<a href="{{ url_for('main.settings') }}" class="btn">Access Settings Page</a>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
21
py_app/app/templates/login.html
Normal file
21
py_app/app/templates/login.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Login{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="login-page">
|
||||||
|
<div class="logo-container">
|
||||||
|
<img src="{{ url_for('static', filename='logo_login.jpg') }}" alt="Login Logo" class="login-logo">
|
||||||
|
</div>
|
||||||
|
<div class="form-container">
|
||||||
|
<h2>Login</h2>
|
||||||
|
<form method="POST">
|
||||||
|
<label for="email">Email:</label>
|
||||||
|
<input type="email" name="email" required>
|
||||||
|
<label for="password">Password:</label>
|
||||||
|
<input type="password" name="password" required>
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
8
py_app/app/templates/settings.html
Normal file
8
py_app/app/templates/settings.html
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Settings{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>Settings Page</h2>
|
||||||
|
<p>This is the settings page. Add your settings here.</p>
|
||||||
|
{% endblock %}
|
||||||
4
py_app/requirements.txt
Normal file
4
py_app/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
Flask==2.2.2
|
||||||
|
Flask-SSLify==0.1.5
|
||||||
|
Werkzeug==2.2.2
|
||||||
|
gunicorn==20.1.0
|
||||||
6
py_app/run.py
Normal file
6
py_app/run.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from app import create_app
|
||||||
|
|
||||||
|
app = create_app()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True)
|
||||||
Reference in New Issue
Block a user