final version, submitted to teacher

This commit is contained in:
2024-12-24 17:34:52 +01:00
parent c0528a2488
commit 46a42c99c2
16 changed files with 394 additions and 105 deletions

View File

@@ -1,10 +1,9 @@
from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify
import logging
from datetime import datetime
from werkzeug.security import check_password_hash, generate_password_hash
from db import get_db_connection, fetch_users, fetch_orders, fetch_roles, fetch_repairs, fetch_employees, fetch_products, update_product, add_product_stock
from auth import encrypt_password, check_password
import random
import sqlite3
app = Flask(__name__)
app.secret_key = 'e462a50b0401f495cfb5c67c3871fe4b'
@@ -20,14 +19,20 @@ werkzeug_logger.setLevel(logging.ERROR)
# Log client IP before each request
@app.before_request
def log_client_ip():
client_ip = request.headers.get('X-Forwarded-For', request.remote_addr)
if request.remote_addr == '127.0.0.1':
client_ip = request.headers.get('CF-Connecting-IP', request.headers.get('X-Forwarded-For', request.remote_addr))
else:
client_ip = request.remote_addr
client_ip = client_ip.split(',')[0] # Get the first IP if it's a forwarded request
request.client_ip = client_ip # Store the client IP in the request context
# Override werkzeug's default logging to show client IP in the access log
@app.after_request
def log_request(response):
client_ip = request.headers.get('X-Forwarded-For', request.remote_addr)
if request.remote_addr == '127.0.0.1':
client_ip = request.headers.get('CF-Connecting-IP', request.headers.get('X-Forwarded-For', request.remote_addr))
else:
client_ip = request.remote_addr
client_ip = client_ip.split(',')[0] # Get the first IP if it's a forwarded request
app.logger.info(f"{client_ip} - - [{request.date}] \"{request.method} {request.full_path} {request.environ.get('SERVER_PROTOCOL')}\" {response.status_code}")
return response
@@ -39,6 +44,7 @@ def logout():
session.pop('logged_in', None)
session.pop('role_id', None)
session.pop('username', None)
session.pop('user_id', None)
return '''
<script>
alert('Úspěšně odhlášen.');
@@ -52,6 +58,10 @@ def login():
flash('Již jste přihlášen.', 'info')
if session.get('role_id') == 1:
return redirect(url_for('administrator'))
elif session.get('role_id') == 2:
return redirect(url_for('managers'))
elif session.get('role_id') == 3:
return redirect(url_for('repairs'))
else:
return redirect(url_for('home'))
@@ -64,11 +74,17 @@ def login():
conn.close()
if user is None or not check_password(user['heslo'], password):
flash('Nesprávné uživatelské jméno nebo heslo.', 'error')
return '''
<script>
alert('Nesprávné uživatelské jméno nebo heslo.');
window.location.href = '/login';
</script>
'''
else:
session['logged_in'] = True
session['role_id'] = user['Role_ID']
session['username'] = user['Username'] # Store username in session
session['username'] = user['Username']
session['user_id'] = user['ID_Uzivatele']
flash('Úspěšně přihlášen.', 'success')
if user['Role_ID'] == 1:
return redirect(url_for('administrator'))
@@ -104,7 +120,7 @@ def administrator():
@app.route('/managers')
def managers():
if not session.get('logged_in') or session.get('role_id') != 2:
if not session.get('logged_in') or session.get('role_id') not in [1, 2]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
users = fetch_users(session.get('role_id'))
@@ -114,7 +130,7 @@ def managers():
@app.route('/create_user', methods=['GET', 'POST'])
def create_user():
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 2]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -148,7 +164,7 @@ def create_user():
@app.route('/edit_user/<int:user_id>', methods=['GET', 'POST'])
def edit_user(user_id):
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 2]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -182,7 +198,7 @@ def edit_user(user_id):
@app.route('/delete_user/<int:user_id>', methods=['POST'])
def delete_user(user_id):
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 2]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -201,7 +217,7 @@ def delete_user(user_id):
@app.route('/edit_order/<int:order_id>', methods=['GET', 'POST'])
def edit_order(order_id):
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 2, 3]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -229,7 +245,7 @@ def edit_order(order_id):
@app.route('/delete_order/<int:order_id>', methods=['POST'])
def delete_order(order_id):
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 2, 3]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -243,7 +259,7 @@ def delete_order(order_id):
@app.route('/repairs')
def repairs():
if not session.get('logged_in'):
if not session.get('logged_in') or session.get('role_id') not in [1, 3]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
repairs = fetch_repairs()
@@ -253,7 +269,7 @@ def repairs():
@app.route('/create_repair', methods=['GET', 'POST'])
def create_repair():
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') and session.get('role_id') != 1 or session.get('role_id') not in [1, 3]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -261,51 +277,102 @@ def create_repair():
id_zamestnance = request.form['id_zamestnance']
nazev = request.form['nazev']
popis = request.form['popis']
products = [{'id': pid, 'quantity': qty} for pid, qty in zip(request.form.getlist('products[0][id]'), request.form.getlist('products[0][quantity]'))]
app.logger.debug(f"Received id_zamestnance: {id_zamestnance}")
app.logger.debug(f"Received nazev: {nazev}")
app.logger.debug(f"Received popis: {popis}")
app.logger.debug(f"Received products: {products}")
conn = get_db_connection()
try:
conn.execute('INSERT INTO Opravy (ID_Zamestnance, Nazev, Popis) VALUES (?, ?, ?)',
(id_zamestnance, nazev, popis))
conn.execute('BEGIN')
sql_insert_repair = 'INSERT INTO Opravy (ID_Zamestnance, Nazev, Popis) VALUES (?, ?, ?)'
app.logger.debug(f"Executing SQL: {sql_insert_repair} with values ({id_zamestnance}, {nazev}, {popis})")
conn.execute(sql_insert_repair, (id_zamestnance, nazev, popis))
repair_id = conn.execute('SELECT last_insert_rowid()').fetchone()[0]
debug_info = f"Inserted Repair ID: {repair_id}\n"
for product in products:
product_id = product['id']
quantity = product['quantity']
app.logger.debug(f"Inserting product {product_id} with quantity {quantity} for repair {repair_id}")
if quantity and int(quantity) > 0:
conn.execute('INSERT INTO Pouzite_Produkty (ID_Opravy, ID_Produktu, Pocet_Produktu) VALUES (?, ?, ?)',
(repair_id, product_id, quantity))
debug_info += f"Inserted Product ID: {product_id}, Quantity: {quantity}\n"
conn.commit()
session['debug'] = debug_info
flash('Nová oprava byla úspěšně vytvořena.', 'success')
return redirect(url_for('repairs'))
except sqlite3.Error as e:
conn.rollback()
app.logger.error(f"Error creating repair: {e}")
flash(f'Chyba při vytváření opravy: {e}', 'error')
finally:
conn.close()
employees = fetch_employees()
return render_template('create_repair.html', employees=employees)
products = fetch_products()
return render_template('create_repair.html', employees=employees, products=products)
@app.route('/edit_repair/<int:repair_id>', methods=['GET', 'POST'])
def edit_repair(repair_id):
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 3]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
conn = get_db_connection()
repair = conn.execute('SELECT * FROM Opravy WHERE ID_Opravy = ?', (repair_id,)).fetchone()
repair = dict(repair)
if request.method == 'POST':
id_zamestnance = request.form['id_zamestnance']
nazev = request.form['nazev']
popis = request.form['popis']
products = [{'id': pid, 'quantity': qty} for pid, qty in zip(request.form.getlist('products[][id]'), request.form.getlist('products[][quantity]'))]
conn.execute('UPDATE Opravy SET ID_Zamestnance = ?, Nazev = ?, Popis = ? WHERE ID_Opravy = ?',
(id_zamestnance, nazev, popis, repair_id))
conn.commit()
conn.close()
conn.execute('BEGIN')
try:
conn.execute('UPDATE Opravy SET ID_Zamestnance = ?, Nazev = ?, Popis = ? WHERE ID_Opravy = ?',
(id_zamestnance, nazev, popis, repair_id))
conn.execute('DELETE FROM Pouzite_Produkty WHERE ID_Opravy = ?', (repair_id,))
for product in products:
product_id = product['id']
quantity = product['quantity']
if quantity and int(quantity) > 0:
conn.execute('INSERT INTO Pouzite_Produkty (ID_Opravy, ID_Produktu, Pocet_Produktu) VALUES (?, ?, ?)',
(repair_id, product_id, quantity))
conn.commit()
flash('Oprava byla úspěšně aktualizována.')
except sqlite3.Error as e:
conn.rollback()
app.logger.error(f"Error updating repair: {e}")
flash(f'Chyba při aktualizaci opravy: {e}', 'error')
finally:
conn.close()
flash('Oprava byla úspěšně aktualizována.')
return redirect(url_for('repairs'))
employees = fetch_employees()
products = fetch_products()
repair['products'] = [dict(row) for row in conn.execute('''
SELECT Produkty.ID_Produktu, Produkty.Nazev, Pouzite_Produkty.Pocet_Produktu
FROM Pouzite_Produkty
JOIN Produkty ON Pouzite_Produkty.ID_Produktu = Produkty.ID_Produktu
WHERE Pouzite_Produkty.ID_Opravy = ?
''', (repair_id,)).fetchall()]
conn.close()
return render_template('edit_repair.html', repair=repair, employees=employees)
return render_template('edit_repair.html', repair=repair, employees=employees, products=products)
@app.route('/delete_repair/<int:repair_id>', methods=['POST'])
def delete_repair(repair_id):
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 2, 3]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -326,12 +393,12 @@ def create_reservation():
conn = get_db_connection()
try:
# Fetch a random user with role_id 2
user = conn.execute('SELECT ID_Uzivatele FROM Zamestnanci WHERE Role_ID = 2 ORDER BY RANDOM() LIMIT 1').fetchone()
# Fetch a random user with role_id 3
user = conn.execute('SELECT ID_Uzivatele FROM Zamestnanci WHERE Role_ID = 3 ORDER BY RANDOM() LIMIT 1').fetchone()
if user:
user_id = user['ID_Uzivatele']
else:
user_id = 1 # Fallback to a default user ID if no user with role_id 2 is found
user_id = 1 # Fallback to a default user ID if no user with role_id 3 is found
conn.execute('INSERT INTO Objednavky (Stav, ID_Zamestnance, Popis, ID_Vozidla, Datum_Zacatku, Datum_Konce, Cena) VALUES (?, ?, ?, ?, ?, ?, ?)',
('Nová', user_id, description, 1, datetime.now().strftime('%Y-%m-%d'), datum_konce, 0.0)) # Use the current date for Datum_Zacatku
@@ -342,11 +409,16 @@ def create_reservation():
finally:
conn.close()
return redirect(url_for('home'))
return '''
<script>
alert('Rezervace byla úspěšně vytvořena.');
window.location.href = '/';
</script>
'''
@app.route('/edit_product/<int:product_id>', methods=['GET', 'POST'])
def edit_product(product_id):
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 2]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -369,7 +441,7 @@ def edit_product(product_id):
@app.route('/add_product_stock/<int:product_id>', methods=['GET', 'POST'])
def add_product_stock(product_id):
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 2]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -389,7 +461,7 @@ def add_product_stock(product_id):
@app.route('/create_product', methods=['GET', 'POST'])
def create_product():
if not session.get('logged_in') or session.get('role_id') != 1:
if not session.get('logged_in') or session.get('role_id') not in [1, 2]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
@@ -411,10 +483,16 @@ def create_product():
finally:
conn.close()
return render_template('create_product.html')
@app.route('/statistics')
def statistics():
if not session.get('logged_in') or session.get('role_id') not in [1, 2]:
flash('Nemáte oprávnění k přístupu na tuto stránku.', 'error')
return redirect(url_for('login'))
conn = get_db_connection()
repairs_data = conn.execute('''
SELECT Zamestnanci.Jmeno || ' ' || Zamestnanci.Prijmeni AS employee, COUNT(Opravy.ID_Opravy) AS count

View File

@@ -1,5 +1,6 @@
import sqlite3
from flask import current_app as app
import time
def get_db_connection():
conn = sqlite3.connect('./static/db/db.sqlite')
@@ -9,6 +10,21 @@ def get_db_connection():
def dict_from_row(row):
return {key: row[key] for key in row.keys()}
def execute_with_retry(conn, query, params=(), retries=5, delay=0.1):
for attempt in range(retries):
try:
conn.execute(query, params)
conn.commit()
return
except sqlite3.OperationalError as e:
if "database is locked" in str(e):
if attempt < retries - 1:
time.sleep(delay)
else:
raise
else:
raise
def fetch_users(role_id):
conn = get_db_connection()
users = conn.execute('SELECT * FROM Zamestnanci WHERE Role_ID >= ?', (role_id,)).fetchall()
@@ -73,29 +89,39 @@ def fetch_products():
def update_product(product_id, nazev, popis, momentalni_zasoba, minimalni_zasoba):
conn = get_db_connection()
conn.execute('''
execute_with_retry(conn, '''
UPDATE Produkty
SET Nazev = ?, Popis = ?, Momentalni_Zasoba = ?, Minimalni_Zasoba = ?
WHERE ID_Produktu = ?
''', (nazev, popis, momentalni_zasoba, minimalni_zasoba, product_id))
conn.commit()
conn.close()
def add_product_stock(product_id, quantity):
conn = get_db_connection()
conn.execute('''
execute_with_retry(conn, '''
UPDATE Produkty
SET Momentalni_Zasoba = Momentalni_Zasoba + ?
WHERE ID_Produktu = ?
''', (quantity, product_id))
conn.commit()
conn.close()
def create_product(nazev, popis, momentalni_zasoba, minimalni_zasoba):
conn = get_db_connection()
conn.execute('''
execute_with_retry(conn, '''
INSERT INTO Produkty (Nazev, Popis, Momentalni_Zasoba, Minimalni_Zasoba)
VALUES (?, ?, ?, ?)
''', (nazev, popis, momentalni_zasoba, minimalni_zasoba))
conn.commit()
conn.close()
def insert_used_products(repair_id, products):
conn = get_db_connection()
try:
for product in products:
product_id = product['id']
quantity = product['quantity']
app.logger.debug(f"Inserting product {product_id} with quantity {quantity} for repair {repair_id}")
if quantity and int(quantity) > 0:
execute_with_retry(conn, 'INSERT INTO Pouzite_Produkty (ID_Opravy, ID_Produktu, Pocet_Produktu) VALUES (?, ?, ?)',
(repair_id, product_id, quantity))
finally:
conn.close()

View File

@@ -241,20 +241,43 @@ footer {
/* Reviews section */
.reviews {
margin: 20px 0;
padding: 15px;
background-color: #222;
border: 1px solid #555;
color: white;
border-radius: 1em;
text-align: center;
}
.reviews-header {
margin-bottom: 20px;
}
.review-list {
display: flex;
justify-content: space-around;
margin: 20px;
flex-wrap: wrap;
}
.review-box {
flex: 1 1 200px;
background-color: #333;
width: 200px;
min-height: 100px;
background-color: #444;
border: 1px solid #555;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: transform 0.3s, box-shadow 0.3s;
margin: 10px;
padding: 10px;
text-align: center;
transition: transform 0.3s, box-shadow 0.3s;
color: white;
}
.review-box:hover {
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
/* Text alignment for Directions */
@@ -413,19 +436,29 @@ table tr:hover {
/* Media queries for mobile responsiveness */
@media (max-width: 768px) {
.navbar, .container, .about, .map, .service-info, .photos, .directions, .services, .service-item, .review-box {
header, footer, .navbar, .container, .about, .map, .service-info, .photos, .directions, .services, .service-item, .review-box {
width: 100%;
border-radius: 0.5em;
}
.header, .buttons {
flex-direction: column;
align-items: center;
}
.header .contact-info, .header .nazev, .header .buttons {
text-align: center;
margin: 10px 0;
}
.navbar {
flex-direction: column;
align-items: center;
}
.navbar a {
padding: 10px;
.navbar button {
width: 100%;
text-align: center;
margin: 5px 0;
}
.content {
@@ -474,6 +507,19 @@ table tr:hover {
.form-container {
width: 90%;
}
.user-info {
width: 100%;
text-align: center;
}
table {
font-size: 14px;
}
table th, table td {
padding: 8px 10px;
}
}
/* Button link styles */
@@ -619,3 +665,52 @@ canvas {
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.partners {
margin: 20px 0;
padding: 15px;
background-color: #222;
border: 1px solid #555;
color: white;
border-radius: 1em;
}
.partner-list {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.partner-item {
flex: 1 1 200px;
width: 200px;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
transition: transform 0.3s, box-shadow 0.3s;
margin: 10px;
}
.partner-item img {
width: 10em;
height: auto;
border-radius: 10em;
}
.partner-item:hover {
transform: scale(1.5);
}
.partner-logos {
display: flex;
justify-content: space-around;
align-items: center;
margin: 20px 0;
}
.partner-logos img {
width: var(--partner-logo-width, 100px);
height: var(--partner-logo-height, auto);
margin: 0 10px;
}

Binary file not shown.

BIN
web/static/img/partner1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

BIN
web/static/img/partner2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

BIN
web/static/img/partner3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

BIN
web/static/img/partner4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

View File

@@ -0,0 +1,29 @@
let productCount = document.querySelectorAll('.product-item').length;
function addProduct() {
const container = document.getElementById('product-container');
const newProduct = document.createElement('div');
newProduct.classList.add('product-item');
newProduct.id = `product-item-${productCount}`;
newProduct.innerHTML = `
<label for="product_${productCount}">Produkt:</label>
<select id="product_${productCount}" name="products[${productCount}][id]" required>
<option value="" disabled selected>Vyberte produkt</option>
{% for product in products %}
<option value="{{ product['ID_Produktu'] }}">{{ product['Nazev'] }}</option>
{% endfor %}
</select>
<label for="quantity_${productCount}">Množství:</label>
<input type="number" id="quantity_${productCount}" name="products[${productCount}][quantity]" value="0" min="0" required>
<button type="button" onclick="removeProduct(${productCount})">Odstranit</button>
`;
container.appendChild(newProduct);
productCount++;
}
function removeProduct(index) {
const productItem = document.getElementById(`product-item-${index}`);
if (productItem) {
productItem.remove();
}
}

View File

@@ -30,15 +30,8 @@
</div>
</header>
<div class="container">
<div class="content">
{% if not session.get('logged_in') %}
<p>Musíte se přihlásit, abyste mohli zobrazit tuto stránku.</p>
{% elif session.get('role_id') != 1 %}
<p>Nemáte oprávnění zobrazit tuto stránku.</p>
{% else %}
<div class="user-table">
<nav class="table-header">
<h2 id="users-table">Správa Uživatelů</h2>
@@ -148,19 +141,19 @@
<th>ID</th>
<th>Název</th>
<th>Popis</th>
<th>Momentální Zásoba</th>
<th>Minimální Zásoba</th>
<th>Momentální Zásoba</th>
<th>Akce</th>
</tr>
</thead>
<tbody>
{% for product in products %}
<tr style="text-align: center;">
<tr>
<td>{{ product['ID_Produktu'] }}</td>
<td>{{ product['Nazev'] }}</td>
<td>{{ product['Popis'] }}</td>
<td>{{ product['Momentalni_Zasoba'] }}</td>
<td>{{ product['Minimalni_Zasoba'] }}</td>
<td>{{ product['Momentalni_Zasoba'] }}</td>
<td>
<a href="{{ url_for('edit_product', product_id=product['ID_Produktu']) }}">Edit</a> /
<a href="{{ url_for('add_product_stock', product_id=product['ID_Produktu']) }}">Add</a>
@@ -171,14 +164,13 @@
</table>
{% else %}
<table>
<tr style="text-align: center;">
<tr>
<td colspan="6">Nenalezeny žádné produkty k zobrazení.</td>
</tr>
</table>
{% endif %}
</div>
{% endif %}
</div>
</div>
</div>
<footer class="footer">
<div>Made by Hrachovina</div>

View File

@@ -30,6 +30,23 @@
<label for="popis">Popis:</label>
<textarea id="popis" name="popis" required></textarea>
<h3>Použité Produkty</h3>
<div id="product-container">
<div class="product-item" id="product-item-0">
<label for="product_0">Produkt:</label>
<select id="product_0" name="products[0][id]" required>
<option value="" disabled selected>Vyberte produkt</option>
{% for product in products %}
<option value="{{ product['ID_Produktu'] }}">{{ product['Nazev'] }}</option>
{% endfor %}
</select>
<label for="quantity_0">Množství:</label>
<input type="number" id="quantity_0" name="products[0][quantity]" value="0" min="0" required>
<button type="button" onclick="removeProduct(0)">Odstranit</button>
</div>
</div>
<button type="button" onclick="addProduct()">Přidat Produkt</button>
<button type="submit" class="button">Vytvořit</button>
</form>
</div>
@@ -38,5 +55,7 @@
<div>Made by Hrachovina</div>
</footer>
<script src="{{ url_for('static', filename='scripts/products.js') }}"></script>
</body>
</html>

View File

@@ -29,9 +29,6 @@
<div class="container">
<div class="content">
{% if not session.get('logged_in') or session.get('role_id') != 1 %}
<p>Nemáte oprávnění k přístupu na tuto stránku.</p>
{% else %}
<form action="{{ url_for('create_user') }}" method="post" class="form-container" onsubmit="handleCreateUser(event)">
<label for="jmeno">Jméno:</label>
<input type="text" id="jmeno" name="jmeno" required>
@@ -57,7 +54,6 @@
<button type="submit" class="button">Vytvořit</button>
</form>
{% endif %}
</div>
</div>

View File

@@ -42,14 +42,35 @@
<label for="popis">Popis:</label>
<textarea id="popis" name="popis" required>{{ repair['Popis'] }}</textarea>
<h3>Použité Produkty</h3>
<div id="product-container">
{% for product in repair['products'] %}
<div class="product-item" id="product-item-{{ loop.index0 }}">
<label for="product_{{ loop.index0 }}">Produkt:</label>
<select id="product_{{ loop.index0 }}" name="products[{{ loop.index0 }}][id]" required>
<option value="" disabled>Vyberte produkt</option>
{% for p in products %}
<option value="{{ p['ID_Produktu'] }}" {% if p['ID_Produktu'] == product['ID_Produktu'] %}selected{% endif %}>{{ p['Nazev'] }}</option>
{% endfor %}
</select>
<label for="quantity_{{ loop.index0 }}">Množství:</label>
<input type="number" id="quantity_{{ loop.index0 }}" name="products[{{ loop.index0 }}][quantity]" value="{{ product['Pocet_Produktu'] }}" min="0" required>
<button type="button" style="margin-top: -5px;" onclick="removeProduct({{ loop.index0 }})">Odstranit</button>
</div>
{% endfor %}
</div>
<button type="button" onclick="addProduct()">Přidat Produkt</button>
<button type="submit" class="button">Aktualizovat</button>
</form>
</div>
</div>
<footer class="footer" id="kontakt">
<div>Made by Hrachovina</div>
<div>Made by Hrachovina and Kirsch </div>
</footer>
<script src="{{ url_for('static', filename='scripts/products.js') }}"></script>
</body>
</html>

View File

@@ -51,6 +51,7 @@
<button class="button" onclick="location.href='#directions'">K nám</button>
<button class="button" onclick="location.href='#nabidka-sluzeb'">Služby</button>
<button class="button" onclick="location.href='#recenze'">Recenze</button>
<button class="button" onclick="location.href='#partners'">Partneři</button>
</nav>
<div class="container">
@@ -105,27 +106,49 @@
</div>
<div class="reviews" id="recenze">
<div class="review-box">
<p>Skvělý servis! Rychlá a profesionální oprava.</p>
<p>⭐⭐⭐⭐</p>
<p>- Jan Novák</p>
</div>
<div class="review-box">
<p>Velmi přátelský personál a kvalitní služby.</p>
<p>⭐⭐⭐⭐⭐</p>
<p>- Petra Svobodová</p>
</div>
<div class="review-box">
<p>Oprava byla hotová dříve, než jsem očekával.</p>
<p>⭐⭐⭐</p>
<p>- Martin Dvořák</p>
</div>
<div class="review-box">
<p>Výborná komunikace a skvělé ceny. Určitě se vrátím.</p>
<p>⭐⭐⭐⭐⭐</p>
<p>- Eva Černá</p>
<h2 class="reviews-header">Recenze</h2>
<div class="review-list">
<div class="review-box">
<p>Skvělý servis! Rychlá a profesionální oprava.</p>
<p>⭐⭐⭐⭐</p>
<p>- Jan Novák</p>
</div>
<div class="review-box">
<p>Velmi přátelský personál a kvalitní služby.</p>
<p>⭐⭐⭐⭐⭐</p>
<p>- Petra Svobodová</p>
</div>
<div class="review-box">
<p>Oprava byla hotová dříve, než jsem očekával.</p>
<p>⭐⭐⭐</p>
<p>- Martin Dvořák</p>
</div>
<div class="review-box">
<p>Výborná komunikace a skvělé ceny. Určitě se vrátím.</p>
<p>⭐⭐⭐⭐⭐</p>
<p>- Eva Černá</p>
</div>
</div>
</div>
<div class="partners" id="partners">
<h2>Naši partneři</h2>
<div class="partner-list">
<div class="partner-item">
<img src="{{url_for('static', filename='img/partner1.png')}}" alt="Partner 1">
</div>
<div class="partner-item">
<img src="{{url_for('static', filename='img/partner2.png')}}" alt="Partner 2">
</div>
<div class="partner-item">
<img src="{{url_for('static', filename='img/partner3.png')}}" alt="Partner 3">
</div>
<div class="partner-item">
<img src="{{url_for('static', filename='img/partner4.png')}}" alt="Partner 4">
</div>
</div>
</div>
</div>
<footer class="footer">
<div>Made by Hrachovina and Kirsch</div>
@@ -150,6 +173,24 @@
</div>
</div>
<script src="{{url_for('static', filename='scripts/home.js')}}"></script>
<script>
function openReservationForm() {
const now = new Date();
const minDate = new Date();
minDate.setDate(now.getDate() + 3); // Exclude today and the next 2 days
const formattedMinDate = minDate.toISOString().split('T')[0];
document.getElementById('datum_konce').setAttribute('min', formattedMinDate);
document.getElementById('reservationForm').style.display = 'block';
}
function closeReservationForm() {
document.getElementById('reservationForm').style.display = 'none';
}
function showReservationSuccess() {
alert('Rezervace byla úspěšně vytvořena.');
}
</script>
</body>
</html>

View File

@@ -6,7 +6,7 @@
<title>Správa Manažerů</title>
<link rel="icon" href="{{url_for('static', filename='img/logo.webp')}}" type="image/x-icon">
<link rel="stylesheet" href="{{url_for('static', filename='css/style.css')}}">
<script src="{{url_for('static', filename='scripts/user_table.js')}}"></script>
<!-- <script src="{{url_for('static', filename='scripts/user_table.js')}}"></script> -->
</head>
<body>
@@ -31,11 +31,6 @@
<div class="container">
<div class="content">
{% if not session.get('logged_in') %}
<p>Musíte se přihlásit, abyste mohli zobrazit tuto stránku.</p>
{% elif session.get('role_id') not in [1, 2] %}
<p>Nemáte oprávnění zobrazit tuto stránku.</p>
{% else %}
<div class="user-table">
<nav class="table-header">
<h2 id="users-table">Správa Uživatelů</h2>
@@ -69,11 +64,13 @@
</td>
<td>{{ user['Username'] }}</td>
<td>
<a href="{{ url_for('edit_user', user_id=user['ID_Uzivatele']) }}">Edit</a>
{% if user['Role_ID'] > session.get('role_id') %}
/ <form action="{{ url_for('delete_user', user_id=user['ID_Uzivatele']) }}" method="post" style="display:inline;" onsubmit="return confirm('Opravdu chcete smazat tohoto uživatele?');">
<button type="submit" class="button-link">Delete</button>
</form>
{% if user['Role_ID'] > session.get('role_id') or user['ID_Uzivatele'] == session.get('user_id') %}
<a href="{{ url_for('edit_user', user_id=user['ID_Uzivatele']) }}">Edit</a>
{% if user['Role_ID'] > session.get('role_id') %}
/ <form action="{{ url_for('delete_user', user_id=user['ID_Uzivatele']) }}" method="post" style="display:inline;" onsubmit="return confirm('Opravdu chcete smazat tohoto uživatele?');">
<button type="submit" class="button-link">Delete</button>
</form>
{% endif %}
{% endif %}
</td>
</tr>
@@ -134,7 +131,6 @@
</table>
{% endif %}
</div>
{% endif %}
</div>
</div>

View File

@@ -29,9 +29,6 @@
<div class="container">
<div class="content">
{% if not session.get('logged_in') %}
<p>Musíte se přihlásit, abyste mohli zobrazit tuto stránku.</p>
{% else %}
<div class="user-table">
<nav class="table-header">
<h2 id="users-table">Správa Oprav</h2>
@@ -61,7 +58,7 @@
{% endfor %}
</td>
<td>
<a href="{{ url_for('edit_repair', repair_id=repair['ID_Opravy']) }}" class="button-link">Edit</a>
<a href="{{ url_for('edit_repair', repair_id=repair['ID_Opravy']) }}" class="button-link">Edit</a> /
<form action="{{ url_for('delete_repair', repair_id=repair['ID_Opravy']) }}" method="post" style="display:inline;" onsubmit="return confirm('Opravdu chcete smazat tuto opravu?');">
<button type="submit" class="button-link">Delete</button>
</form>
@@ -94,7 +91,7 @@
</thead>
<tbody>
{% for order in orders %}
<tr style="text-align: center;">
<tr>
<td>{{ order['ID_Objednavky'] }}</td>
<td>{{ order['Datum_Zacatku'] }}</td>
<td>{{ order['Datum_Konce'] }}</td>
@@ -119,13 +116,12 @@
</table>
{% else %}
<table>
<tr style="text-align: center;">
<tr>
<td colspan="7">Nenalezeny žádné objednávky k zobrazení.</td>
</tr>
</table>
{% endif %}
</div>
{% endif %}
</div>
</div>