Dự án thứ hai: dựng giao diện trang quản trị gồm sidebar thu gọn, thanh trên, thẻ số liệu, bảng dữ liệu có tìm kiếm và modal thêm mới; sau đó ghép với PHP và MySQL để thành trang quản lý sinh viên thật.
- Dựng bố cục dashboard: sidebar + nội dung
- Dùng offcanvas-lg cho sidebar responsive
- Hiển thị thẻ số liệu, bảng, modal form
- Ghép giao diện với PHP (loạt PHP và MySQL)
Một số khái niệm
Bootstrap 5.3 có offcanvas-lg: trên màn hình lớn hiển thị như sidebar cố định, trên màn hình nhỏ tự biến thành menu trượt. Đây là cách làm sidebar responsive chỉ bằng class.
Khung dashboard
<div class="d-flex" style="min-height:420px">
<aside class="offcanvas-lg offcanvas-start bg-dark text-white p-3" id="sb" style="width:200px" data-bs-theme="dark">
<div class="offcanvas-header p-0 mb-3"><strong><i class="bi bi-mortarboard"></i> QLSV</strong><button class="btn-close d-lg-none" data-bs-dismiss="offcanvas" data-bs-target="#sb"></button></div>
<nav class="nav nav-pills flex-column gap-1 small"><a class="nav-link active" href="#"><i class="bi bi-speedometer2 me-2"></i>Tổng quan</a><a class="nav-link text-white" href="#"><i class="bi bi-people me-2"></i>Sinh viên</a><a class="nav-link text-white" href="#"><i class="bi bi-journal me-2"></i>Điểm</a></nav>
</aside>
<main class="flex-fill p-3 bg-body-tertiary">
<div class="d-flex align-items-center mb-3"><button class="btn btn-outline-secondary btn-sm d-lg-none me-2" data-bs-toggle="offcanvas" data-bs-target="#sb"><i class="bi bi-list"></i></button><h5 class="mb-0">Tổng quan</h5><button class="btn btn-success btn-sm ms-auto" data-bs-toggle="modal" data-bs-target="#them"><i class="bi bi-plus"></i> Thêm</button></div>
<div class="row g-2 mb-3"><div class="col-6 col-md-3"><div class="card"><div class="card-body py-2"><small class="text-body-secondary">Sinh viên</small><div class="fs-4 fw-bold">1.250</div></div></div></div><div class="col-6 col-md-3"><div class="card"><div class="card-body py-2"><small class="text-body-secondary">Lớp</small><div class="fs-4 fw-bold">36</div></div></div></div><div class="col-6 col-md-3"><div class="card"><div class="card-body py-2"><small class="text-body-secondary">Điểm TB</small><div class="fs-4 fw-bold text-success">7,6</div></div></div></div><div class="col-6 col-md-3"><div class="card"><div class="card-body py-2"><small class="text-body-secondary">Cảnh báo</small><div class="fs-4 fw-bold text-danger">12</div></div></div></div></div>
<div class="card"><div class="card-body p-2"><input class="form-control form-control-sm mb-2" placeholder="Tìm theo tên..."><table class="table table-sm table-hover mb-0 small"><thead><tr><th>Mã</th><th>Họ tên</th><th>Lớp</th><th></th></tr></thead><tbody><tr><td>SV001</td><td>Lò Văn An</td><td>K66</td><td class="text-end"><button class="btn btn-sm btn-outline-primary py-0">Sửa</button></td></tr><tr><td>SV002</td><td>Cầm Thị Bình</td><td>K66</td><td class="text-end"><button class="btn btn-sm btn-outline-primary py-0">Sửa</button></td></tr></tbody></table></div></div>
</main>
</div>
<div class="modal fade" id="them" tabindex="-1"><div class="modal-dialog"><form class="modal-content" onsubmit="return false"><div class="modal-header"><h5 class="modal-title">Thêm sinh viên</h5><button class="btn-close" data-bs-dismiss="modal" type="button"></button></div><div class="modal-body"><input class="form-control mb-2" placeholder="Mã SV"><input class="form-control" placeholder="Họ tên"></div><div class="modal-footer"><button class="btn btn-success">Lưu</button></div></form></div></div>Khung kết quả hẹp nên sidebar đã chuyển thành menu trượt (bấm nút ☰); trên màn hình rộng sidebar luôn hiện.
Ghép với PHP
<?php require 'bootstrap.php'; [$ds, $tong] = $repo->timKiem($_GET['q'] ?? '', 1); ?>
<tbody>
<?php foreach ($ds as $sv): ?>
<tr>
<td><?= e($sv['ma_sv']) ?></td><td><?= e($sv['ho_ten']) ?></td><td><?= e($sv['ten_lop']) ?></td>
<td class="text-end"><a class="btn btn-sm btn-outline-primary" href="/form.php?id=<?= $sv['id'] ?>">Sửa</a></td>
</tr>
<?php endforeach; ?>
</tbody>Phần PHP, CSDL, Repository xem loạt PHP và MySQL, Bài 6. Giao diện Bootstrap chỉ thay thế phần HTML hiển thị.
Thêm biểu đồ bằng thư viện Chart.js vào thẻ số liệu để dashboard sinh động hơn.
Trang quản trị phải yêu cầu đăng nhập và kiểm tra quyền ở máy chủ; ẩn nút trên giao diện không phải là bảo mật.
- Dựng khung dashboard với sidebar offcanvas-lg.
- Thêm 4 thẻ số liệu lấy từ CSDL bằng COUNT, AVG.
- Ghép bảng sinh viên có tìm kiếm, phân trang từ PHP.
- Thêm modal thêm/sửa sinh viên gửi bằng fetch và hiện toast.
- offcanvas-lg: sidebar cố định trên máy tính, trượt trên điện thoại.
- card số liệu, bảng, modal form.
- Giao diện Bootstrap + dữ liệu PHP/MySQL.
- Bảo mật xử lý ở máy chủ.