AT opmaak dashboard

This commit is contained in:
Anh-Thy04
2025-05-23 12:54:42 +02:00
parent 2f7a499c91
commit f77c3c523b
4 changed files with 202 additions and 35 deletions

View File

@@ -1,18 +1,27 @@
{%extends 'base.html' %}
{% block content %}
<div class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="display-4 fw-bold" style="color: #313A4D;">Numberplate</h1>
</div>
<div class="col-md-12">
<div class="card mb-4">
</div>
</div>
<div class="col-md-12">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title fs-4">Add numberplate</h5>
<div class="log-container" style="max-height: 250px; overflow-y: auto;">
<form method="POST" class="contact-form">
<form method="POST" class="contact-form" id="numberplateForm">
{{ form.hidden_tag() }}
<div class="form-field">
{{ form.numberplate.label }} {{ form.numberplate(class="form-input") }}
{{ form.numberplate(class="form-input",style="width: 200px; height: 40px;") }}
</div>
<div class="button-container">
{{ form.submit(class="submit-btn") }}
<div class="button-container" style="margin-top: 15px;">
{{ form.submit(class="btn btn-sm btn-dark", style="width: 200px;") }}
</div>
</form>
</div>
@@ -20,4 +29,59 @@
</div>
</div>
<div class="col-md-12">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title fs-4">Numberplates</h5>
<div class="log-container" style="max-height: 250px; overflow-y: auto;">
<table class="table table-sm table-hover" id="numberplatesTable">
<thead>
<tr>
<th scope="col" class="fs-5">ID</th>
<th scope="col" class="fs-5">Numberplate</th>
</tr>
</thead>
<tbody id="numberplatesBody">
{% for plate in plates %}
<tr>
<td><small class="fs-6">{{ plate.id }}</small></td>
<td><small class="fs-6">{{ plate.plate }}</small></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
document.getElementById('numberplateForm').addEventListener('submit', async function(e) {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const response = await fetch(form.action || window.location.pathname, {
method: 'POST',
body: formData,
headers: {'X-Requested-With': 'XMLHttpRequest'}
});
if (response.ok) {
const data = await response.json();
// Update the table body
const tbody = document.getElementById('numberplatesBody');
tbody.innerHTML = '';
data.plates.forEach(plate => {
tbody.innerHTML += `<tr>
<td><small class="fs-6">${plate.id}</small></td>
<td><small class="fs-6">${plate.plate}</small></td>
</tr>`;
});
form.reset();
} else {
alert('Failed to add numberplate.');
}
});
</script>
{% endblock %}

View File

@@ -6,6 +6,57 @@
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Admin Dashboard</title>
<script defer src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/js/bootstrap.bundle.min.js"></script>
<style>
body.dark-mode {
background-color: #181a1b !important;
color: #e0e0e0 !important;
}
.dark-mode .card,
.dark-mode .table {
background-color: #23272b !important;
color: #e0e0e0 !important;
}
.dark-mode .table thead,
.dark-mode .table tbody,
.dark-mode .table th,
.dark-mode .table td,
.dark-mode .table tr {
background-color: #23272b !important;
color: #e0e0e0 !important;
border-color: #444 !important;
}
.dark-mode .card-title,
.dark-mode .display-4,
.dark-mode h5 {
color: #e0e0e0 !important;
}
.dark-mode input {
background-color: #23272b !important;
color: #e0e0e0 !important;
border: 1px solid #444 !important;
}
.dark-mode .btn {
background-color: #444 !important;
color: #e0e0e0 !important;
border-color: #666 !important;
}
.dark-mode .btn:hover {
background-color: #222 !important;
color: #fff !important;
}
.dark-mode .logout-btn {
background-color: #212529 !important;
color: #fff !important;
border-color: #212529 !important;
}
.dark-mode .logout-btn:hover {
background-color: #353738 !important;
color: #fff !important;
}
</style>
</head>
<body>
<div class="container-fluid">
@@ -21,30 +72,40 @@
<a class="nav-link active text-white" href="/dash/dashboard">
Dashboard
</a>
<a class="nav-link active text-white" href="/dash/logs">
Logs
</a>
<a class="nav-link active text-white" href="/dash/add">
Add numberplate
</a>
</li>
</ul>
<div class="d-flex justify-content-center mt-3">
<a href="/login" class="btn btn-sm btn-dark" style="width: 200px;">Logout</a>
<a href="/auth/demo" class="btn btn-sm btn-dark logout-btn" style="width: 200px;">Logout</a>
<button id="darkModeToggle" class="btn btn-secondary btn-sm" style="position: fixed; top: 10px; right: 10px; z-index: 9999;">
Toggle Theme
</button>
</div>
</div>
</div>
<div class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="display-4 fw-bold" style="color: #313A4D;">Dashboard</h1>
</div>
{%block content%}
{% endblock %}
</div>
</div>
</div>
<script>
document.getElementById('darkModeToggle').onclick = function() {
document.body.classList.toggle('dark-mode');
if(document.body.classList.contains('dark-mode')) {
localStorage.setItem('darkMode', 'enabled');
} else {
localStorage.setItem('darkMode', 'disabled');
}
};
if(localStorage.getItem('darkMode') === 'enabled') {
document.body.classList.add('dark-mode');
}
</script>
</body>
</html>

View File

@@ -1,21 +1,37 @@
{%extends 'base.html' %}
{% block content %}
<div class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="display-4 fw-bold" style="color: #313A4D;">Dashboard</h1>
</div>
<div class="col-md-12">
<div class="card mb-4">
</div>
</div>
<div class="col-md-12">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title fs-4">Registered Numberplates</h5>
<h5 class="card-title fs-4">Logs</h5>
<div class="log-container" style="max-height: 250px; overflow-y: auto;">
<table class="table table-sm table-hover">
<thead>
<tr>
<tr>
<th scope="col" class="fs-5">Time</th>
<th scope="col" class="fs-5">Numberplate</th>
<th scope="col" class="fs-5">Gate Status</th>
</tr>
</thead>
<tbody>
{% for Plates in AllowedPlates %}
{% for form in recent_logs %}
<tr>
<td>{{Plates.plate}}</td>
<td><small class="fs-6">{{ form.timestamp.strftime('%H:%M:%S') }}</small></td>
<td><small class="fs-6">{{ plate.plate }}</small></td>
<td>
<span class="badge {% if log.status == 'success' %}bg-success{% elif log.status == 'warning' %}bg-warning{% elif log.status == 'error' %}bg-danger{% else %}bg-secondary{% endif %} fs-6">
{{ form.allowed }}
</span>
</td>
</tr>
{% endfor %}
</tbody>
@@ -25,4 +41,32 @@
</div>
</div>
{% endblock %}
<div class="col-md-12">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title fs-4">Numberplates</h5>
<div class="log-container" style="max-height: 250px; overflow-y: auto;">
<table class="table table-sm table-hover">
<thead>
<tr>
<th scope="col" class="fs-5">ID</th>
<th scope="col" class="fs-5">Numberplate</th>
</tr>
</thead>
<tbody>
{% for plate in plates %}
<tr>
<td><small class="fs-6">{{ plate.id }}</small></td>
<td><small class="fs-6">{{ plate.plate }}</small></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,4 +1,4 @@
from flask import Blueprint, render_template
from flask import Blueprint, render_template, request, jsonify
from flask_login import login_required
from application.dashboard.models import AllowedPlate, LoggedItem
from application import db, app
@@ -11,32 +11,30 @@ dash_blueprint = Blueprint("dash", __name__, template_folder="templates")
@dash_blueprint.route('/dashboard')
#@login_required
def dashboard():
#print("test123")
#with app.app_context():
Plates = AllowedPlate.query.all()
print(Plates)
return render_template("dashboard.html", AllowedPlates = Plates)
recent_logs = LoggedItem.query.order_by(LoggedItem.dateLogged.desc()).limit(50).all()
return render_template("dashboard.html", plates=Plates, recent_logs=recent_logs)
@dash_blueprint.route('/add', methods=['GET', 'POST'])
#@login_required
def add():
Plates = AllowedPlate.query.all()
form = npForm()
if form.validate_on_submit():
if form.numberplate.data:
print(form.numberplate.data)
ap = AllowedPlate(plate=form.numberplate.data)
db.session.add(ap)
db.session.commit()
# AJAX response
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
plates = AllowedPlate.query.order_by(AllowedPlate.id).all()
return jsonify({
'plates': [{'id': p.id, 'plate': p.plate} for p in plates]
})
# Normal GET or failed POST
Plates = AllowedPlate.query.order_by(AllowedPlate.id).all()
return render_template("add.html", form=form, plates=Plates)
return render_template("add.html", form=form)
@dash_blueprint.route('/logs', methods=['GET', 'POST'])
#@login_required
def logs():
form = LoggedItem.query.all()
return render_template("logs.html", form=form)