Compare commits

...

2 Commits

Author SHA1 Message Date
Flatlogic Bot
d9ae8f552d v3 2025-10-16 12:45:17 +00:00
Flatlogic Bot
0e7e15ad6d v1 2025-10-16 12:24:26 +00:00
13 changed files with 2627 additions and 155 deletions

332
bunks.php Normal file
View File

@ -0,0 +1,332 @@
<?php
session_start();
require_once 'db/config.php';
$notification = null;
// Handle Add, Edit, Delete actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$db = db();
// Add Bunk
if (isset($_POST['add_bunk'])) {
$name = trim($_POST['name']);
$owner = trim($_POST['owner']);
$contact = trim($_POST['contact']);
$location = trim($_POST['location']);
if (!empty($name)) {
try {
$stmt = $db->prepare("INSERT INTO bunks (name, owner, contact, location) VALUES (?, ?, ?, ?)");
$stmt->execute([$name, $owner, $contact, $location]);
$_SESSION['notification'] = ['text' => 'Bunk added successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error adding bunk: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Bunk name is required.', 'type' => 'warning'];
}
}
// Edit Bunk
elseif (isset($_POST['edit_bunk'])) {
$id = $_POST['bunk_id'];
$name = trim($_POST['name']);
$owner = trim($_POST['owner']);
$contact = trim($_POST['contact']);
$location = trim($_POST['location']);
if (!empty($name) && !empty($id)) {
try {
$stmt = $db->prepare("UPDATE bunks SET name = ?, owner = ?, contact = ?, location = ? WHERE id = ?");
$stmt->execute([$name, $owner, $contact, $location, $id]);
$_SESSION['notification'] = ['text' => 'Bunk updated successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error updating bunk: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Bunk name and ID are required.', 'type' => 'warning'];
}
}
header("Location: bunks.php");
exit;
}
// Delete Bunk
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
try {
$db = db();
$stmt = $db->prepare("DELETE FROM bunks WHERE id = ?");
$stmt->execute([$_GET['id']]);
$_SESSION['notification'] = ['text' => 'Bunk deleted successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error deleting bunk: ' . $e->getMessage(), 'type' => 'danger'];
}
header("Location: bunks.php");
exit;
}
if (isset($_SESSION['notification'])) {
$notification = $_SESSION['notification'];
unset($_SESSION['notification']);
}
try {
$db = db();
$stmt = $db->query("SELECT id, name, owner, contact, location, created_at FROM bunks ORDER BY created_at DESC");
$bunks = $stmt->fetchAll();
} catch (PDOException $e) {
$bunks = [];
$notification = ['text' => 'Error fetching bunks: ' . $e->getMessage(), 'type' => 'danger'];
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bunk Management</title>
<meta name="description" content="Manage your fuel bunks efficiently. Built with Flatlogic Generator.">
<meta name="keywords" content="fuel bunk management, petrol pump software, inventory, sales tracking, flatlogic">
<meta property="og:title" content="Bunk Management">
<meta property="og:description" content="Manage your fuel bunks efficiently. Built with Flatlogic Generator.">
<meta property="og:image" content="">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
<style>
body {
background-color: #f8f9fa;
}
.navbar {
background: linear-gradient(to right, #0d6efd, #0dcaf0);
}
.toast-container {
z-index: 1080;
}
</style>
</head>
<body>
<?php include 'includes/header.php'; ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1 class="h2">Bunk Management</h1>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addBunkModal">
<i class="bi bi-plus-circle me-1"></i> Add New Bunk
</button>
</div>
<div class="card shadow-sm">
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th>Name</th>
<th>Owner</th>
<th>Contact</th>
<th>Location</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($bunks)): ?>
<tr>
<td colspan="6" class="text-center text-muted">No bunks found. Add one to get started!</td>
</tr>
<?php else: ?>
<?php foreach ($bunks as $bunk): ?>
<tr>
<td><?= htmlspecialchars($bunk['name']) ?></td>
<td><?= htmlspecialchars($bunk['owner']) ?></td>
<td><?= htmlspecialchars($bunk['contact']) ?></td>
<td><?= htmlspecialchars($bunk['location']) ?></td>
<td><?= date('d M, Y', strtotime($bunk['created_at'])) ?></td>
<td>
<button type="button" class="btn btn-sm btn-outline-secondary edit-btn"
data-bs-toggle="modal" data-bs-target="#editBunkModal"
data-id="<?= $bunk['id'] ?>"
data-name="<?= htmlspecialchars($bunk['name']) ?>"
data-owner="<?= htmlspecialchars($bunk['owner']) ?>"
data-contact="<?= htmlspecialchars($bunk['contact']) ?>"
data-location="<?= htmlspecialchars($bunk['location']) ?>">
<i class="bi bi-pencil"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
data-bs-toggle="modal" data-bs-target="#deleteConfirmModal"
data-id="<?= $bunk['id'] ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Add Bunk Modal -->
<div class="modal fade" id="addBunkModal" tabindex="-1" aria-labelledby="addBunkModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form action="bunks.php" method="POST">
<div class="modal-header">
<h5 class="modal-title" id="addBunkModalLabel">Add New Bunk</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="name" class="form-label">Bunk Name*</label>
<input type="text" class="form-control" id="name" name="name" required>
</div>
<div class="mb-3">
<label for="owner" class="form-label">Owner</label>
<input type="text" class="form-control" id="owner" name="owner">
</div>
<div class="mb-3">
<label for="contact" class="form-label">Contact</label>
<input type="text" class="form-control" id="contact" name="contact">
</div>
<div class="mb-3">
<label for="location" class="form-label">Location</label>
<textarea class="form-control" id="location" name="location" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="add_bunk" class="btn btn-primary">Save Bunk</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Bunk Modal -->
<div class="modal fade" id="editBunkModal" tabindex="-1" aria-labelledby="editBunkModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form action="bunks.php" method="POST">
<input type="hidden" name="bunk_id" id="edit_bunk_id">
<div class="modal-header">
<h5 class="modal-title" id="editBunkModalLabel">Edit Bunk</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="edit_name" class="form-label">Bunk Name*</label>
<input type="text" class="form-control" id="edit_name" name="name" required>
</div>
<div class="mb-3">
<label for="edit_owner" class="form-label">Owner</label>
<input type="text" class="form-control" id="edit_owner" name="owner">
</div>
<div class="mb-3">
<label for="edit_contact" class="form-label">Contact</label>
<input type="text" class="form-control" id="edit_contact" name="contact">
</div>
<div class="mb-3">
<label for="edit_location" class="form-label">Location</label>
<textarea class="form-control" id="edit_location" name="location" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="edit_bunk" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1" aria-labelledby="deleteConfirmModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteConfirmModalLabel">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Are you sure you want to delete this bunk? This action cannot be undone.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a href="#" id="delete-confirm-btn" class="btn btn-danger">Delete</a>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div class="position-fixed bottom-0 end-0 p-3 toast-container">
<div id="notificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">Notification</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Toast notification
<?php if ($notification): ?>
const toastEl = document.getElementById('notificationToast');
const toastBody = toastEl.querySelector('.toast-body');
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning');
toastEl.classList.add('bg-<?= $notification['type'] ?>', 'text-white');
toastBody.textContent = '<?= addslashes(htmlspecialchars($notification['text'])) ?>';
const toast = new bootstrap.Toast(toastEl);
toast.show();
<?php endif; ?>
// Edit modal handler
const editBunkModal = document.getElementById('editBunkModal');
editBunkModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
const name = button.getAttribute('data-name');
const owner = button.getAttribute('data-owner');
const contact = button.getAttribute('data-contact');
const location = button.getAttribute('data-location');
const modalTitle = editBunkModal.querySelector('.modal-title');
const modalBodyInputId = editBunkModal.querySelector('#edit_bunk_id');
const modalBodyInputName = editBunkModal.querySelector('#edit_name');
const modalBodyInputOwner = editBunkModal.querySelector('#edit_owner');
const modalBodyInputContact = editBunkModal.querySelector('#edit_contact');
const modalBodyInputLocation = editBunkModal.querySelector('#edit_location');
modalTitle.textContent = 'Edit Bunk: ' + name;
modalBodyInputId.value = id;
modalBodyInputName.value = name;
modalBodyInputOwner.value = owner;
modalBodyInputContact.value = contact;
modalBodyInputLocation.value = location;
});
// Delete confirmation handler
const deleteConfirmModal = document.getElementById('deleteConfirmModal');
deleteConfirmModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
const deleteBtn = deleteConfirmModal.querySelector('#delete-confirm-btn');
deleteBtn.href = 'bunks.php?action=delete&id=' + id;
});
});
</script>
</body>
</html>

View File

@ -1,17 +1,31 @@
<?php
// Generated by setup_mariadb_project.sh — edit as needed.
define('DB_HOST', '127.0.0.1');
define('DB_NAME', 'app_30953');
define('DB_USER', 'app_30953');
define('DB_PASS', 'e45f2778-db1f-450c-99c6-29efb4601472');
define('PROJECT_ROOT', dirname(__DIR__));
function db() {
static $pdo;
if (!$pdo) {
$pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8mb4', DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
return $pdo;
static $pdo;
if ($pdo) {
return $pdo;
}
$host = getenv('DB_HOST') ?: '127.0.0.1';
$port = getenv('DB_PORT') ?: '3306';
$dbname = getenv('DB_NAME') ?: 'app';
$user = getenv('DB_USER') ?: 'app';
$pass = getenv('DB_PASS') ?: 'app';
$dsn = "mysql:host={$host};port={$port};dbname={$dbname};charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
return $pdo;
} catch (PDOException $e) {
throw new PDOException($e->getMessage(), (int)$e->getCode());
}
}

View File

@ -0,0 +1,149 @@
-- Bunks
CREATE TABLE IF NOT EXISTS bunks (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
owner VARCHAR(255),
contact VARCHAR(50),
location TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Users and Roles
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role ENUM('Superadmin', 'Manager', 'Attendant', 'Accountant') NOT NULL,
bunk_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (bunk_id) REFERENCES bunks(id) ON DELETE SET NULL
);
-- Fuel Types
CREATE TABLE IF NOT EXISTS fuel_types (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE,
unit VARCHAR(20) DEFAULT 'Litre'
);
-- Tanks
CREATE TABLE IF NOT EXISTS tanks (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
bunk_id INT NOT NULL,
fuel_type_id INT NOT NULL,
capacity DECIMAL(10,2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (bunk_id) REFERENCES bunks(id) ON DELETE CASCADE,
FOREIGN KEY (fuel_type_id) REFERENCES fuel_types(id)
);
-- Pumps
CREATE TABLE IF NOT EXISTS pumps (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
bunk_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (bunk_id) REFERENCES bunks(id) ON DELETE CASCADE
);
-- Nozzles (each nozzle belongs to a pump and draws from a tank)
CREATE TABLE IF NOT EXISTS nozzles (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
pump_id INT NOT NULL,
tank_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (pump_id) REFERENCES pumps(id) ON DELETE CASCADE,
FOREIGN KEY (tank_id) REFERENCES tanks(id) ON DELETE CASCADE
);
-- Price History (fuel pricing)
CREATE TABLE IF NOT EXISTS price_history (
id INT AUTO_INCREMENT PRIMARY KEY,
fuel_type_id INT NOT NULL,
bunk_id INT NOT NULL,
price DECIMAL(10,2) NOT NULL,
date DATE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY bunk_fuel_date (bunk_id, fuel_type_id, date),
FOREIGN KEY (fuel_type_id) REFERENCES fuel_types(id),
FOREIGN KEY (bunk_id) REFERENCES bunks(id) ON DELETE CASCADE
);
-- Tank Readings (daily, per tank, unique per date)
CREATE TABLE IF NOT EXISTS tank_readings (
id INT AUTO_INCREMENT PRIMARY KEY,
tank_id INT NOT NULL,
date DATE NOT NULL,
opening DECIMAL(10,2) NOT NULL,
receipts DECIMAL(10,2) DEFAULT 0,
closing DECIMAL(10,2) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY tank_date_unique (tank_id, date),
FOREIGN KEY (tank_id) REFERENCES tanks(id) ON DELETE CASCADE
);
-- Daily Sales (per nozzle)
CREATE TABLE IF NOT EXISTS day_sales (
id INT AUTO_INCREMENT PRIMARY KEY,
nozzle_id INT NOT NULL,
bunk_id INT NOT NULL,
date DATE NOT NULL,
opening_reading DECIMAL(10,2) NOT NULL,
closing_reading DECIMAL(10,2) NOT NULL,
testing DECIMAL(10,2) DEFAULT 0,
net_sale DECIMAL(10,2) GENERATED ALWAYS AS (closing_reading - opening_reading - testing) STORED,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY nozzle_date_unique (nozzle_id, date),
FOREIGN KEY (nozzle_id) REFERENCES nozzles(id) ON DELETE CASCADE,
FOREIGN KEY (bunk_id) REFERENCES bunks(id) ON DELETE CASCADE
);
-- Fuel Purchases / Receipts
CREATE TABLE IF NOT EXISTS fuel_receipts (
id INT AUTO_INCREMENT PRIMARY KEY,
bunk_id INT NOT NULL,
supplier VARCHAR(255),
invoice_number VARCHAR(100),
fuel_type_id INT NOT NULL,
quantity DECIMAL(10,2) NOT NULL,
rate DECIMAL(10,2) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
date DATE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (bunk_id) REFERENCES bunks(id) ON DELETE CASCADE,
FOREIGN KEY (fuel_type_id) REFERENCES fuel_types(id)
);
-- Credit Customers
CREATE TABLE IF NOT EXISTS credit_customers (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
contact VARCHAR(50),
bunk_id INT NOT NULL,
credit_limit DECIMAL(10,2) DEFAULT 0,
outstanding_balance DECIMAL(10,2) DEFAULT 0,
FOREIGN KEY (bunk_id) REFERENCES bunks(id) ON DELETE CASCADE
);
-- Credit Sales
CREATE TABLE IF NOT EXISTS credit_sales (
id INT AUTO_INCREMENT PRIMARY KEY,
bunk_id INT NOT NULL,
customer_id INT NOT NULL,
date DATE NOT NULL,
fuel_type_id INT NOT NULL,
quantity DECIMAL(10,2) NOT NULL,
rate DECIMAL(10,2) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (bunk_id) REFERENCES bunks(id) ON DELETE CASCADE,
FOREIGN KEY (customer_id) REFERENCES credit_customers(id),
FOREIGN KEY (fuel_type_id) REFERENCES fuel_types(id)
);
-- Expenses
CREATE TABLE IF NOT EXISTS expenses (
id INT AUTO_INCREMENT PRIMARY KEY,
bunk_id INT NOT NULL,
category VARCHAR(100) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
description TEXT,
payment_mode VARCHAR(50),
date DATE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (bunk_id) REFERENCES bunks(id) ON DELETE CASCADE
);
-- Add a Superadmin User
INSERT IGNORE INTO users (name, email, password, role) VALUES
('Superadmin', 'admin@example.com', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'Superadmin'); -- password = "password"

11
db/setup.php Normal file
View File

@ -0,0 +1,11 @@
<?php
require_once __DIR__ . '/config.php';
try {
$db = db();
$sql = file_get_contents(__DIR__ . '/migrations/001_initial_schema.sql');
$db->exec($sql);
echo "Database schema created successfully.";
} catch (PDOException $e) {
die("Database setup failed: " . $e->getMessage());
}

238
fuel_types.php Normal file
View File

@ -0,0 +1,238 @@
<?php
session_start();
require_once 'db/config.php';
$notification = null;
// Handle Add, Edit, Delete actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$db = db();
// Add Fuel Type
if (isset($_POST['add_fuel_type'])) {
$name = trim($_POST['name']);
if (!empty($name)) {
try {
$stmt = $db->prepare("INSERT INTO fuel_types (name) VALUES (?)");
$stmt->execute([$name]);
$_SESSION['notification'] = ['text' => 'Fuel type added successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error adding fuel type: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Fuel type name is required.', 'type' => 'warning'];
}
}
// Edit Fuel Type
elseif (isset($_POST['edit_fuel_type'])) {
$id = $_POST['fuel_type_id'];
$name = trim($_POST['name']);
if (!empty($name) && !empty($id)) {
try {
$stmt = $db->prepare("UPDATE fuel_types SET name = ? WHERE id = ?");
$stmt->execute([$name, $id]);
$_SESSION['notification'] = ['text' => 'Fuel type updated successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error updating fuel type: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Fuel type name and ID are required.', 'type' => 'warning'];
}
}
header("Location: fuel_types.php");
exit;
}
// Delete Fuel Type
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
try {
$db = db();
$stmt = $db->prepare("SELECT COUNT(*) FROM tanks WHERE fuel_type_id = ?");
$stmt->execute([$_GET['id']]);
if ($stmt->fetchColumn() > 0) {
$_SESSION['notification'] = ['text' => 'Cannot delete. This fuel type is in use by one or more tanks.', 'type' => 'warning'];
} else {
$stmt = $db->prepare("DELETE FROM fuel_types WHERE id = ?");
$stmt->execute([$_GET['id']]);
$_SESSION['notification'] = ['text' => 'Fuel type deleted successfully!', 'type' => 'success'];
}
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error deleting fuel type: ' . $e->getMessage(), 'type' => 'danger'];
}
header("Location: fuel_types.php");
exit;
}
if (isset($_SESSION['notification'])) {
$notification = $_SESSION['notification'];
unset($_SESSION['notification']);
}
$fuel_types = db()->query("SELECT * FROM fuel_types ORDER BY name ASC")->fetchAll(PDO::FETCH_ASSOC);
$page_title = "Fuel Type Management";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($page_title) ?> - Petrol Pump Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
</head>
<body>
<?php include 'includes/header.php'; ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1><i class="bi bi-fuel-pump"></i> <?= htmlspecialchars($page_title) ?></h1>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addFuelTypeModal">
<i class="bi bi-plus-circle"></i> Add New Fuel Type
</button>
</div>
<div class="card">
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($fuel_types as $type): ?>
<tr>
<td><?= htmlspecialchars($type['id']) ?></td>
<td><?= htmlspecialchars($type['name']) ?></td>
<td>
<button type="button" class="btn btn-sm btn-outline-secondary edit-btn"
data-bs-toggle="modal" data-bs-target="#editFuelTypeModal"
data-id="<?= $type['id'] ?>"
data-name="<?= htmlspecialchars($type['name']) ?>">
<i class="bi bi-pencil"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
data-bs-toggle="modal" data-bs-target="#deleteConfirmModal"
data-id="<?= $type['id'] ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Add Fuel Type Modal -->
<div class="modal fade" id="addFuelTypeModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<div class="modal-header">
<h5 class="modal-title">Add Fuel Type</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="name" class="form-label">Fuel Type Name*</label>
<input type="text" class="form-control" name="name" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="add_fuel_type" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Fuel Type Modal -->
<div class="modal fade" id="editFuelTypeModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<input type="hidden" name="fuel_type_id" id="edit_fuel_type_id">
<div class="modal-header">
<h5 class="modal-title">Edit Fuel Type</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="edit_name" class="form-label">Fuel Type Name*</label>
<input type="text" class="form-control" id="edit_name" name="name" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="edit_fuel_type" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">Are you sure you want to delete this fuel type?</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a href="#" id="delete-confirm-btn" class="btn btn-danger">Delete</a>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
<div id="notificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"></div>
<div class="toast-body"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const notification = <?php echo json_encode($notification); ?>;
if (notification) {
const toastEl = document.getElementById('notificationToast');
const toastHeader = toastEl.querySelector('.toast-header');
const toastBody = toastEl.querySelector('.toast-body');
toastHeader.innerHTML = `<strong class="me-auto">Notification</strong><button type="button" class="btn-close" data-bs-dismiss="toast"></button>`;
toastBody.textContent = notification.text;
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning');
toastEl.classList.add('bg-' + notification.type, 'text-white');
new bootstrap.Toast(toastEl).show();
}
const editModal = document.getElementById('editFuelTypeModal');
editModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
const name = button.getAttribute('data-name');
editModal.querySelector('#edit_fuel_type_id').value = id;
editModal.querySelector('#edit_name').value = name;
});
const deleteModal = document.getElementById('deleteConfirmModal');
deleteModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
deleteModal.querySelector('#delete-confirm-btn').href = 'fuel_types.php?action=delete&id=' + id;
});
});
</script>
</body>
</html>

50
includes/header.php Normal file
View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Petrol Pump Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="index.php">Petrol Pump</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="index.php">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="bunks.php">Bunks</a>
</li>
<li class="nav-item">
<a class="nav-link" href="users.php">Users</a>
</li>
<li class="nav-item">
<a class="nav-link" href="roles.php">Roles</a>
</li>
<li class="nav-item">
<a class="nav-link" href="tanks.php">Tanks</a>
</li>
<li class="nav-item">
<a class="nav-link" href="fuel_types.php">Fuel Types</a>
</li>
<li class="nav-item">
<a class="nav-link" href="pumps.php">Pumps</a>
</li>
<li class="nav-item">
<a class="nav-link" href="nozzles.php">Nozzles</a>
</li>
<li class="nav-item">
<a class="nav-link" href="prices.php">Prices</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-4">

247
index.php
View File

@ -1,150 +1,115 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
require_once 'db/config.php';
?>
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title>
<?php
// Read project preview data from environment
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>
<?php if ($projectDescription): ?>
<!-- Meta description -->
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
<!-- Open Graph meta tags -->
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<!-- Twitter meta tags -->
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bunk Admin Dashboard</title>
<meta name="description" content="Admin dashboard for fuel bunk management. Built with Flatlogic Generator.">
<meta name="keywords" content="dashboard, fuel bunk, admin panel, flatlogic">
<meta property="og:title" content="Bunk Admin Dashboard">
<meta property="og:description" content="Admin dashboard for fuel bunk management. Built with Flatlogic Generator.">
<meta property="og:image" content="">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
<style>
body {
background-color: #f8f9fa;
}
.navbar {
background: linear-gradient(to right, #0d6efd, #0dcaf0);
}
.card-icon {
font-size: 3rem;
opacity: 0.6;
}
</style>
</head>
<body>
<main>
<div class="card">
<h1>Analyzing your requirements and generating your website…</h1>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
</div>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will update automatically as the plan is implemented.</p>
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
<?php include 'includes/header.php'; ?>
<div class="container mt-4">
<h1 class="h2 mb-3">Dashboard</h1>
<div class="row g-4">
<div class="col-md-4">
<div class="card text-center shadow-sm h-100">
<div class="card-body">
<i class="bi bi-fuel-pump card-icon"></i>
<h5 class="card-title mt-3">Bunk Management</h5>
<p class="card-text">Add, edit, and manage your fuel bunks.</p>
<a href="bunks.php" class="btn btn-primary">Go to Bunks</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center shadow-sm h-100">
<div class="card-body">
<i class="bi bi-people card-icon"></i>
<h5 class="card-title mt-3">User Management</h5>
<p class="card-text">Manage users and roles.</p>
<a href="users.php" class="btn btn-primary">Go to Users</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center shadow-sm h-100">
<div class="card-body">
<i class="bi bi-shield-lock card-icon"></i>
<h5 class="card-title mt-3">Role Management</h5>
<p class="card-text">Define user roles and permissions.</p>
<a href="roles.php" class="btn btn-primary">Go to Roles</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center shadow-sm h-100">
<div class="card-body">
<i class="bi bi-inboxes card-icon"></i>
<h5 class="card-title mt-3">Tank Management</h5>
<p class="card-text">Manage fuel tanks and inventory.</p>
<a href="tanks.php" class="btn btn-primary">Go to Tanks</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center shadow-sm h-100">
<div class="card-body">
<i class="bi bi-ev-station card-icon"></i>
<h5 class="card-title mt-3">Pump Management</h5>
<p class="card-text">Manage fuel pumps.</p>
<a href="pumps.php" class="btn btn-primary">Go to Pumps</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center shadow-sm h-100">
<div class="card-body">
<i class="bi bi-cone-striped card-icon"></i>
<h5 class="card-title mt-3">Nozzle Management</h5>
<p class="card-text">Manage fuel nozzles.</p>
<a href="nozzles.php" class="btn btn-primary">Go to Nozzles</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center text-secondary bg-light shadow-sm h-100">
<div class="card-body">
<i class="bi bi-graph-up card-icon"></i>
<h5 class="card-title mt-3">Sales Reports</h5>
<p class="card-text">View daily and monthly sales data (coming soon).</p>
<a href="#" class="btn btn-secondary disabled">Go to Reports</a>
</div>
</div>
</div>
</div>
</div>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

280
nozzles.php Normal file
View File

@ -0,0 +1,280 @@
<?php
session_start();
require_once 'db/config.php';
$notification = null;
// Handle Add, Edit, Delete actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$db = db();
// Add Nozzle
if (isset($_POST['add_nozzle'])) {
$name = trim($_POST['name']);
$pump_id = $_POST['pump_id'];
$tank_id = $_POST['tank_id'];
if (!empty($name) && !empty($pump_id) && !empty($tank_id)) {
try {
$stmt = $db->prepare("INSERT INTO nozzles (name, pump_id, tank_id) VALUES (?, ?, ?)");
$stmt->execute([$name, $pump_id, $tank_id]);
$_SESSION['notification'] = ['text' => 'Nozzle added successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error adding nozzle: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'All fields are required.', 'type' => 'warning'];
}
}
// Edit Nozzle
elseif (isset($_POST['edit_nozzle'])) {
$id = $_POST['nozzle_id'];
$name = trim($_POST['name']);
$pump_id = $_POST['pump_id'];
$tank_id = $_POST['tank_id'];
if (!empty($name) && !empty($pump_id) && !empty($tank_id) && !empty($id)) {
try {
$stmt = $db->prepare("UPDATE nozzles SET name = ?, pump_id = ?, tank_id = ? WHERE id = ?");
$stmt->execute([$name, $pump_id, $tank_id, $id]);
$_SESSION['notification'] = ['text' => 'Nozzle updated successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error updating nozzle: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'All fields and ID are required.', 'type' => 'warning'];
}
}
header("Location: nozzles.php");
exit;
}
// Soft Delete Nozzle
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
try {
$db = db();
$stmt = $db->prepare("UPDATE nozzles SET deleted_at = NOW() WHERE id = ?");
$stmt->execute([$_GET['id']]);
$_SESSION['notification'] = ['text' => 'Nozzle deleted successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error deleting nozzle: ' . $e->getMessage(), 'type' => 'danger'];
}
header("Location: nozzles.php");
exit;
}
if (isset($_SESSION['notification'])) {
$notification = $_SESSION['notification'];
unset($_SESSION['notification']);
}
$db = db();
$nozzles = $db->query("SELECT n.*, p.name as pump_name, t.name as tank_name FROM nozzles n JOIN pumps p ON n.pump_id = p.id JOIN tanks t ON n.tank_id = t.id WHERE n.deleted_at IS NULL ORDER BY n.created_at DESC")->fetchAll(PDO::FETCH_ASSOC);
$pumps = $db->query("SELECT * FROM pumps WHERE deleted_at IS NULL")->fetchAll(PDO::FETCH_ASSOC);
$tanks = $db->query("SELECT * FROM tanks")->fetchAll(PDO::FETCH_ASSOC);
$page_title = "Nozzle Management";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($page_title) ?> - Petrol Pump Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
</head>
<body>
<?php include 'includes/header.php'; ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1><i class="bi bi-cone-striped"></i> <?= htmlspecialchars($page_title) ?></h1>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addNozzleModal">
<i class="bi bi-plus-circle"></i> Add New Nozzle
</button>
</div>
<div class="card">
<div class="card-body">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Pump</th>
<th>Tank</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($nozzles as $nozzle): ?>
<tr>
<td><?= htmlspecialchars($nozzle['name']) ?></td>
<td><?= htmlspecialchars($nozzle['pump_name']) ?></td>
<td><?= htmlspecialchars($nozzle['tank_name']) ?></td>
<td><?= date('d M, Y', strtotime($nozzle['created_at'])) ?></td>
<td>
<button type="button" class="btn btn-sm btn-outline-primary edit-btn"
data-bs-toggle="modal" data-bs-target="#editNozzleModal"
data-id="<?= $nozzle['id'] ?>"
data-name="<?= htmlspecialchars($nozzle['name']) ?>"
data-pump-id="<?= $nozzle['pump_id'] ?>"
data-tank-id="<?= $nozzle['tank_id'] ?>">
<i class="bi bi-pencil-square"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
data-bs-toggle="modal" data-bs-target="#deleteConfirmModal"
data-id="<?= $nozzle['id'] ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Add Nozzle Modal -->
<div class="modal fade" id="addNozzleModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<div class="modal-header">
<h5 class="modal-title">Add New Nozzle</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Nozzle Name*</label>
<input type="text" class="form-control" name="name" required>
</div>
<div class="mb-3">
<label class="form-label">Pump*</label>
<select class="form-select" name="pump_id" required>
<option value="">Select Pump</option>
<?php foreach ($pumps as $pump): ?>
<option value="<?= $pump['id'] ?>"><?= htmlspecialchars($pump['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Tank*</label>
<select class="form-select" name="tank_id" required>
<option value="">Select Tank</option>
<?php foreach ($tanks as $tank): ?>
<option value="<?= $tank['id'] ?>"><?= htmlspecialchars($tank['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="add_nozzle" class="btn btn-primary">Save Nozzle</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Nozzle Modal -->
<div class="modal fade" id="editNozzleModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<input type="hidden" name="nozzle_id" id="edit_nozzle_id">
<div class="modal-header">
<h5 class="modal-title">Edit Nozzle</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Nozzle Name*</label>
<input type="text" class="form-control" id="edit_name" name="name" required>
</div>
<div class="mb-3">
<label class="form-label">Pump*</label>
<select class="form-select" id="edit_pump_id" name="pump_id" required>
<?php foreach ($pumps as $pump): ?>
<option value="<?= $pump['id'] ?>"><?= htmlspecialchars($pump['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Tank*</label>
<select class="form-select" id="edit_tank_id" name="tank_id" required>
<?php foreach ($tanks as $tank): ?>
<option value="<?= $tank['id'] ?>"><?= htmlspecialchars($tank['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="edit_nozzle" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">Are you sure you want to delete this nozzle?</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a href="#" id="delete-confirm-btn" class="btn btn-danger">Delete</a>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
<div id="notificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"></div>
<div class="toast-body"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const notification = <?php echo json_encode($notification); ?>;
if (notification) {
const toastEl = document.getElementById('notificationToast');
const toastHeader = toastEl.querySelector('.toast-header');
const toastBody = toastEl.querySelector('.toast-body');
toastHeader.innerHTML = `<strong class="me-auto">Notification</strong><button type="button" class="btn-close" data-bs-dismiss="toast"></button>`;
toastBody.textContent = notification.text;
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning');
toastEl.classList.add('bg-' + notification.type, 'text-white');
new bootstrap.Toast(toastEl).show();
}
const editModal = document.getElementById('editNozzleModal');
editModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
editModal.querySelector('#edit_nozzle_id').value = id;
editModal.querySelector('#edit_name').value = button.getAttribute('data-name');
editModal.querySelector('#edit_pump_id').value = button.getAttribute('data-pump-id');
editModal.querySelector('#edit_tank_id').value = button.getAttribute('data-tank-id');
});
const deleteModal = document.getElementById('deleteConfirmModal');
deleteModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
deleteModal.querySelector('#delete-confirm-btn').href = 'nozzles.php?action=delete&id=' + id;
});
});
</script>
</body>
</html>

268
prices.php Normal file
View File

@ -0,0 +1,268 @@
<?php
session_start();
require_once 'db/config.php';
$notification = null;
// Handle Add, Edit, Delete actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$db = db();
// Add Price
if (isset($_POST['add_price'])) {
$tank_id = $_POST['tank_id'];
$price = $_POST['price'];
$effective_date = $_POST['effective_date'];
if (!empty($tank_id) && !empty($price) && !empty($effective_date)) {
try {
$stmt = $db->prepare("INSERT INTO prices (tank_id, price, effective_date) VALUES (?, ?, ?)");
$stmt->execute([$tank_id, $price, $effective_date]);
$_SESSION['notification'] = ['text' => 'Price added successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error adding price: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'All fields are required.', 'type' => 'warning'];
}
}
// Edit Price
elseif (isset($_POST['edit_price'])) {
$id = $_POST['price_id'];
$tank_id = $_POST['tank_id'];
$price = $_POST['price'];
$effective_date = $_POST['effective_date'];
if (!empty($tank_id) && !empty($price) && !empty($effective_date) && !empty($id)) {
try {
$stmt = $db->prepare("UPDATE prices SET tank_id = ?, price = ?, effective_date = ? WHERE id = ?");
$stmt->execute([$tank_id, $price, $effective_date, $id]);
$_SESSION['notification'] = ['text' => 'Price updated successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error updating price: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'All fields and ID are required.', 'type' => 'warning'];
}
}
header("Location: prices.php");
exit;
}
// Soft Delete Price
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
try {
$db = db();
$stmt = $db->prepare("UPDATE prices SET deleted_at = NOW() WHERE id = ?");
$stmt->execute([$_GET['id']]);
$_SESSION['notification'] = ['text' => 'Price deleted successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error deleting price: ' . $e->getMessage(), 'type' => 'danger'];
}
header("Location: prices.php");
exit;
}
if (isset($_SESSION['notification'])) {
$notification = $_SESSION['notification'];
unset($_SESSION['notification']);
}
$db = db();
$prices = $db->query("SELECT pr.*, t.name as tank_name, ft.name as fuel_type_name FROM prices pr JOIN tanks t ON pr.tank_id = t.id JOIN fuel_types ft ON t.fuel_type_id = ft.id WHERE pr.deleted_at IS NULL ORDER BY pr.effective_date DESC")->fetchAll(PDO::FETCH_ASSOC);
$tanks = $db->query("SELECT t.id, t.name, ft.name as fuel_type_name FROM tanks t JOIN fuel_types ft ON t.fuel_type_id = ft.id WHERE t.deleted_at IS NULL")->fetchAll(PDO::FETCH_ASSOC);
$page_title = "Price Management";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($page_title) ?> - Petrol Pump Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
</head>
<body>
<?php include 'includes/header.php'; ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1><i class="bi bi-tags-fill"></i> <?= htmlspecialchars($page_title) ?></h1>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addPriceModal">
<i class="bi bi-plus-circle"></i> Add New Price
</button>
</div>
<div class="card">
<div class="card-body">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Tank</th>
<th>Price</th>
<th>Effective Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($prices as $price): ?>
<tr>
<td><?= htmlspecialchars($price['tank_name'] . ' (' . $price['fuel_type_name'] . ')') ?></td>
<td> <?= htmlspecialchars(number_format($price['price'], 2)) ?></td>
<td><?= date('d M, Y', strtotime($price['effective_date'])) ?></td>
<td>
<button type="button" class="btn btn-sm btn-outline-primary edit-btn"
data-bs-toggle="modal" data-bs-target="#editPriceModal"
data-id="<?= $price['id'] ?>"
data-tank-id="<?= $price['tank_id'] ?>"
data-price="<?= htmlspecialchars($price['price']) ?>"
data-effective-date="<?= htmlspecialchars($price['effective_date']) ?>">
<i class="bi bi-pencil-square"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
data-bs-toggle="modal" data-bs-target="#deleteConfirmModal"
data-id="<?= $price['id'] ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Add Price Modal -->
<div class="modal fade" id="addPriceModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<div class="modal-header">
<h5 class="modal-title">Add New Price</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Tank*</label>
<select class="form-select" name="tank_id" required>
<option value="">Select Tank</option>
<?php foreach ($tanks as $tank): ?>
<option value="<?= $tank['id'] ?>"><?= htmlspecialchars($tank['name'] . ' (' . $tank['fuel_type_name'] . ')') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Price*</label>
<input type="number" step="0.01" class="form-control" name="price" required>
</div>
<div class="mb-3">
<label class="form-label">Effective Date*</label>
<input type="date" class="form-control" name="effective_date" value="<?= date('Y-m-d') ?>" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="add_price" class="btn btn-primary">Save Price</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Price Modal -->
<div class="modal fade" id="editPriceModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<input type="hidden" name="price_id" id="edit_price_id">
<div class="modal-header">
<h5 class="modal-title">Edit Price</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Tank*</label>
<select class="form-select" id="edit_tank_id" name="tank_id" required>
<?php foreach ($tanks as $tank): ?>
<option value="<?= $tank['id'] ?>"><?= htmlspecialchars($tank['name'] . ' (' . $tank['fuel_type_name'] . ')') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Price*</label>
<input type="number" step="0.01" class="form-control" id="edit_price" name="price" required>
</div>
<div class="mb-3">
<label class="form-label">Effective Date*</label>
<input type="date" class="form-control" id="edit_effective_date" name="effective_date" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="edit_price" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">Are you sure you want to delete this price record? This is a soft delete.</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a href="#" id="delete-confirm-btn" class="btn btn-danger">Delete</a>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
<div id="notificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"></div>
<div class="toast-body"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const notification = <?php echo json_encode($notification); ?>;
if (notification) {
const toastEl = document.getElementById('notificationToast');
const toastHeader = toastEl.querySelector('.toast-header');
const toastBody = toastEl.querySelector('.toast-body');
toastHeader.innerHTML = `<strong class="me-auto">Notification</strong><button type="button" class="btn-close" data-bs-dismiss="toast"></button>`;
toastBody.textContent = notification.text;
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning');
toastEl.classList.add('bg-' + notification.type, 'text-white');
new bootstrap.Toast(toastEl).show();
}
const editModal = document.getElementById('editPriceModal');
editModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
editModal.querySelector('#edit_price_id').value = id;
editModal.querySelector('#edit_tank_id').value = button.getAttribute('data-tank-id');
editModal.querySelector('#edit_price').value = button.getAttribute('data-price');
editModal.querySelector('#edit_effective_date').value = button.getAttribute('data-effective-date');
});
const deleteModal = document.getElementById('deleteConfirmModal');
deleteModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
deleteModal.querySelector('#delete-confirm-btn').href = 'prices.php?action=delete&id=' + id;
});
});
</script>
</body>
</html>

256
pumps.php Normal file
View File

@ -0,0 +1,256 @@
<?php
session_start();
require_once 'db/config.php';
$notification = null;
// Handle Add, Edit, Delete actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$db = db();
// Add Pump
if (isset($_POST['add_pump'])) {
$name = trim($_POST['name']);
$bunk_id = $_POST['bunk_id'];
if (!empty($name) && !empty($bunk_id)) {
try {
$stmt = $db->prepare("INSERT INTO pumps (name, bunk_id) VALUES (?, ?)");
$stmt->execute([$name, $bunk_id]);
$_SESSION['notification'] = ['text' => 'Pump added successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error adding pump: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Pump name and bunk are required.', 'type' => 'warning'];
}
}
// Edit Pump
elseif (isset($_POST['edit_pump'])) {
$id = $_POST['pump_id'];
$name = trim($_POST['name']);
$bunk_id = $_POST['bunk_id'];
if (!empty($name) && !empty($bunk_id) && !empty($id)) {
try {
$stmt = $db->prepare("UPDATE pumps SET name = ?, bunk_id = ? WHERE id = ?");
$stmt->execute([$name, $bunk_id, $id]);
$_SESSION['notification'] = ['text' => 'Pump updated successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error updating pump: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Pump name, bunk and ID are required.', 'type' => 'warning'];
}
}
header("Location: pumps.php");
exit;
}
// Soft Delete Pump
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
try {
$db = db();
$stmt = $db->prepare("UPDATE pumps SET deleted_at = NOW() WHERE id = ?");
$stmt->execute([$_GET['id']]);
$_SESSION['notification'] = ['text' => 'Pump deleted successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error deleting pump: ' . $e->getMessage(), 'type' => 'danger'];
}
header("Location: pumps.php");
exit;
}
if (isset($_SESSION['notification'])) {
$notification = $_SESSION['notification'];
unset($_SESSION['notification']);
}
$db = db();
$pumps = $db->query("SELECT p.*, b.name as bunk_name FROM pumps p JOIN bunks b ON p.bunk_id = b.id WHERE p.deleted_at IS NULL ORDER BY p.created_at DESC")->fetchAll(PDO::FETCH_ASSOC);
$bunks = $db->query("SELECT * FROM bunks WHERE deleted_at IS NULL")->fetchAll(PDO::FETCH_ASSOC);
$page_title = "Pump Management";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($page_title) ?> - Petrol Pump Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
</head>
<body>
<?php include 'includes/header.php'; ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1><i class="bi bi-ev-station-fill"></i> <?= htmlspecialchars($page_title) ?></h1>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addPumpModal">
<i class="bi bi-plus-circle"></i> Add New Pump
</button>
</div>
<div class="card">
<div class="card-body">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Bunk</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($pumps as $pump): ?>
<tr>
<td><?= htmlspecialchars($pump['name']) ?></td>
<td><?= htmlspecialchars($pump['bunk_name']) ?></td>
<td><?= date('d M, Y', strtotime($pump['created_at'])) ?></td>
<td>
<button type="button" class="btn btn-sm btn-outline-primary edit-btn"
data-bs-toggle="modal" data-bs-target="#editPumpModal"
data-id="<?= $pump['id'] ?>"
data-name="<?= htmlspecialchars($pump['name']) ?>"
data-bunk-id="<?= $pump['bunk_id'] ?>">
<i class="bi bi-pencil-square"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
data-bs-toggle="modal" data-bs-target="#deleteConfirmModal"
data-id="<?= $pump['id'] ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Add Pump Modal -->
<div class="modal fade" id="addPumpModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<div class="modal-header">
<h5 class="modal-title">Add New Pump</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Pump Name*</label>
<input type="text" class="form-control" name="name" required>
</div>
<div class="mb-3">
<label class="form-label">Bunk*</label>
<select class="form-select" name="bunk_id" required>
<option value="">Select Bunk</option>
<?php foreach ($bunks as $bunk): ?>
<option value="<?= $bunk['id'] ?>"><?= htmlspecialchars($bunk['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="add_pump" class="btn btn-primary">Save Pump</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Pump Modal -->
<div class="modal fade" id="editPumpModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<input type="hidden" name="pump_id" id="edit_pump_id">
<div class="modal-header">
<h5 class="modal-title">Edit Pump</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Pump Name*</label>
<input type="text" class="form-control" id="edit_name" name="name" required>
</div>
<div class="mb-3">
<label class="form-label">Bunk*</label>
<select class="form-select" id="edit_bunk_id" name="bunk_id" required>
<?php foreach ($bunks as $bunk): ?>
<option value="<?= $bunk['id'] ?>"><?= htmlspecialchars($bunk['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="edit_pump" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">Are you sure you want to delete this pump?</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a href="#" id="delete-confirm-btn" class="btn btn-danger">Delete</a>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
<div id="notificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"></div>
<div class="toast-body"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const notification = <?php echo json_encode($notification); ?>;
if (notification) {
const toastEl = document.getElementById('notificationToast');
const toastHeader = toastEl.querySelector('.toast-header');
const toastBody = toastEl.querySelector('.toast-body');
toastHeader.innerHTML = `<strong class="me-auto">Notification</strong><button type="button" class="btn-close" data-bs-dismiss="toast"></button>`;
toastBody.textContent = notification.text;
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning');
toastEl.classList.add('bg-' + notification.type, 'text-white');
new bootstrap.Toast(toastEl).show();
}
const editModal = document.getElementById('editPumpModal');
editModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
editModal.querySelector('#edit_pump_id').value = id;
editModal.querySelector('#edit_name').value = button.getAttribute('data-name');
editModal.querySelector('#edit_bunk_id').value = button.getAttribute('data-bunk-id');
});
const deleteModal = document.getElementById('deleteConfirmModal');
deleteModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
deleteModal.querySelector('#delete-confirm-btn').href = 'pumps.php?action=delete&id=' + id;
});
});
</script>
</body>
</html>

286
roles.php Normal file
View File

@ -0,0 +1,286 @@
<?php
session_start();
require_once 'db/config.php';
$notification = null;
// Handle Add, Edit, Delete actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$db = db();
// Add Role
if (isset($_POST['add_role'])) {
$name = trim($_POST['name']);
$description = trim($_POST['description']);
if (!empty($name)) {
try {
$stmt = $db->prepare("INSERT INTO roles (name, description) VALUES (?, ?)");
$stmt->execute([$name, $description]);
$_SESSION['notification'] = ['text' => 'Role added successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error adding role: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Role name is required.', 'type' => 'warning'];
}
}
// Edit Role
elseif (isset($_POST['edit_role'])) {
$id = $_POST['role_id'];
$name = trim($_POST['name']);
$description = trim($_POST['description']);
if (!empty($name) && !empty($id)) {
try {
$stmt = $db->prepare("UPDATE roles SET name = ?, description = ? WHERE id = ?");
$stmt->execute([$name, $description, $id]);
$_SESSION['notification'] = ['text' => 'Role updated successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error updating role: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Role name and ID are required.', 'type' => 'warning'];
}
}
header("Location: roles.php");
exit;
}
// Delete Role
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
try {
$db = db();
// Check if any user is assigned this role
$stmt = $db->prepare("SELECT COUNT(*) FROM users WHERE role_id = ?");
$stmt->execute([$_GET['id']]);
if ($stmt->fetchColumn() > 0) {
$_SESSION['notification'] = ['text' => 'Cannot delete role. It is currently assigned to one or more users.', 'type' => 'warning'];
} else {
$stmt = $db->prepare("DELETE FROM roles WHERE id = ?");
$stmt->execute([$_GET['id']]);
$_SESSION['notification'] = ['text' => 'Role deleted successfully!', 'type' => 'success'];
}
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error deleting role: ' . $e->getMessage(), 'type' => 'danger'];
}
header("Location: roles.php");
exit;
}
if (isset($_SESSION['notification'])) {
$notification = $_SESSION['notification'];
unset($_SESSION['notification']);
}
try {
$db = db();
$stmt = $db->query("SELECT id, name, description, created_at FROM roles ORDER BY name ASC");
$roles = $stmt->fetchAll();
} catch (PDOException $e) {
$roles = [];
$notification = ['text' => 'Error fetching roles: ' . $e->getMessage(), 'type' => 'danger'];
}
$page_title = "Role Management";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($page_title) ?> - Petrol Pump Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
</head>
<body>
<?php include 'includes/header.php'; ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1><i class="bi bi-person-badge"></i> <?= htmlspecialchars($page_title) ?></h1>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addRoleModal">
<i class="bi bi-plus-circle"></i> Add New Role
</button>
</div>
<div class="card">
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($roles)): ?>
<tr>
<td colspan="4" class="text-center">No roles found.</td>
</tr>
<?php else: ?>
<?php foreach ($roles as $role): ?>
<tr>
<td><span class="badge bg-primary"><?= htmlspecialchars($role['name']) ?></span></td>
<td><?= htmlspecialchars($role['description']) ?></td>
<td><?= date('d M, Y', strtotime($role['created_at'])) ?></td>
<td>
<button type="button" class="btn btn-sm btn-outline-secondary edit-btn"
data-bs-toggle="modal" data-bs-target="#editRoleModal"
data-id="<?= $role['id'] ?>"
data-name="<?= htmlspecialchars($role['name']) ?>"
data-description="<?= htmlspecialchars($role['description']) ?>">
<i class="bi bi-pencil"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
data-bs-toggle="modal" data-bs-target="#deleteConfirmModal"
data-id="<?= $role['id'] ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Add Role Modal -->
<div class="modal fade" id="addRoleModal" tabindex="-1" aria-labelledby="addRoleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form action="roles.php" method="POST">
<div class="modal-header">
<h5 class="modal-title" id="addRoleModalLabel">Add New Role</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="name" class="form-label">Role Name*</label>
<input type="text" class="form-control" id="name" name="name" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="add_role" class="btn btn-primary">Save Role</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Role Modal -->
<div class="modal fade" id="editRoleModal" tabindex="-1" aria-labelledby="editRoleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form action="roles.php" method="POST">
<input type="hidden" name="role_id" id="edit_role_id">
<div class="modal-header">
<h5 class="modal-title" id="editRoleModalLabel">Edit Role</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="edit_name" class="form-label">Role Name*</label>
<input type="text" class="form-control" id="edit_name" name="name" required>
</div>
<div class="mb-3">
<label for="edit_description" class="form-label">Description</label>
<textarea class="form-control" id="edit_description" name="description" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="edit_role" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1" aria-labelledby="deleteConfirmModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteConfirmModalLabel">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Are you sure you want to delete this role? This action cannot be undone.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a href="#" id="delete-confirm-btn" class="btn btn-danger">Delete</a>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
<div id="notificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">Notification</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Toast notification
<?php if ($notification): ?>
const toastEl = document.getElementById('notificationToast');
const toastBody = toastEl.querySelector('.toast-body');
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning');
toastEl.classList.add('bg-<?= $notification['type'] ?>', 'text-white');
toastBody.textContent = '<?= addslashes(htmlspecialchars($notification['text'])) ?>';
const toast = new bootstrap.Toast(toastEl);
toast.show();
<?php endif; ?>
// Edit modal handler
const editRoleModal = document.getElementById('editRoleModal');
editRoleModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
const name = button.getAttribute('data-name');
const description = button.getAttribute('data-description');
const modalTitle = editRoleModal.querySelector('.modal-title');
const modalBodyInputId = editRoleModal.querySelector('#edit_role_id');
const modalBodyInputName = editRoleModal.querySelector('#edit_name');
const modalBodyInputDescription = editRoleModal.querySelector('#edit_description');
modalTitle.textContent = 'Edit Role: ' + name;
modalBodyInputId.value = id;
modalBodyInputName.value = name;
modalBodyInputDescription.value = description;
});
// Delete confirmation handler
const deleteConfirmModal = document.getElementById('deleteConfirmModal');
deleteConfirmModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
const deleteBtn = deleteConfirmModal.querySelector('#delete-confirm-btn');
deleteBtn.href = 'roles.php?action=delete&id=' + id;
});
});
</script>
</body>
</html>

294
tanks.php Normal file
View File

@ -0,0 +1,294 @@
<?php
session_start();
require_once 'db/config.php';
$notification = null;
// Handle Add, Edit, Delete actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$db = db();
// Add Tank
if (isset($_POST['add_tank'])) {
$name = trim($_POST['name']);
$bunk_id = $_POST['bunk_id'];
$fuel_type_id = $_POST['fuel_type_id'];
$capacity = $_POST['capacity'];
if (!empty($name) && !empty($bunk_id) && !empty($fuel_type_id) && !empty($capacity)) {
try {
$stmt = $db->prepare("INSERT INTO tanks (name, bunk_id, fuel_type_id, capacity) VALUES (?, ?, ?, ?)");
$stmt->execute([$name, $bunk_id, $fuel_type_id, $capacity]);
$_SESSION['notification'] = ['text' => 'Tank added successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error adding tank: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'All fields are required.', 'type' => 'warning'];
}
}
// Edit Tank
elseif (isset($_POST['edit_tank'])) {
$id = $_POST['tank_id'];
$name = trim($_POST['name']);
$bunk_id = $_POST['bunk_id'];
$fuel_type_id = $_POST['fuel_type_id'];
$capacity = $_POST['capacity'];
if (!empty($name) && !empty($bunk_id) && !empty($fuel_type_id) && !empty($capacity) && !empty($id)) {
try {
$stmt = $db->prepare("UPDATE tanks SET name = ?, bunk_id = ?, fuel_type_id = ?, capacity = ? WHERE id = ?");
$stmt->execute([$name, $bunk_id, $fuel_type_id, $capacity, $id]);
$_SESSION['notification'] = ['text' => 'Tank updated successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error updating tank: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'All fields are required.', 'type' => 'warning'];
}
}
header("Location: tanks.php");
exit;
}
// Delete Tank
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
try {
$db = db();
$stmt = $db->prepare("DELETE FROM tanks WHERE id = ?");
$stmt->execute([$_GET['id']]);
$_SESSION['notification'] = ['text' => 'Tank deleted successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error deleting tank: ' . $e->getMessage(), 'type' => 'danger'];
}
header("Location: tanks.php");
exit;
}
if (isset($_SESSION['notification'])) {
$notification = $_SESSION['notification'];
unset($_SESSION['notification']);
}
$db = db();
$tanks = $db->query("SELECT t.*, b.name as bunk_name, ft.name as fuel_type_name FROM tanks t JOIN bunks b ON t.bunk_id = b.id JOIN fuel_types ft ON t.fuel_type_id = ft.id ORDER BY t.created_at DESC")->fetchAll(PDO::FETCH_ASSOC);
$bunks = $db->query("SELECT * FROM bunks")->fetchAll(PDO::FETCH_ASSOC);
$fuel_types = $db->query("SELECT * FROM fuel_types")->fetchAll(PDO::FETCH_ASSOC);
$page_title = "Tank Management";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($page_title) ?> - Petrol Pump Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
</head>
<body>
<?php include 'includes/header.php'; ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1><i class="bi bi-inboxes-fill"></i> <?= htmlspecialchars($page_title) ?></h1>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addTankModal">
<i class="bi bi-plus-circle"></i> Add New Tank
</button>
</div>
<div class="card">
<div class="card-body">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Bunk</th>
<th>Fuel Type</th>
<th>Capacity (L)</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($tanks as $tank): ?>
<tr>
<td><?= htmlspecialchars($tank['name']) ?></td>
<td><?= htmlspecialchars($tank['bunk_name']) ?></td>
<td><?= htmlspecialchars($tank['fuel_type_name']) ?></td>
<td><?= htmlspecialchars(number_format($tank['capacity'])) ?></td>
<td>
<button type="button" class="btn btn-sm btn-outline-primary edit-btn"
data-bs-toggle="modal" data-bs-target="#editTankModal"
data-id="<?= $tank['id'] ?>"
data-name="<?= htmlspecialchars($tank['name']) ?>"
data-bunk-id="<?= $tank['bunk_id'] ?>"
data-fuel-type-id="<?= $tank['fuel_type_id'] ?>"
data-capacity="<?= htmlspecialchars($tank['capacity']) ?>">
<i class="bi bi-pencil-square"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
data-bs-toggle="modal" data-bs-target="#deleteConfirmModal"
data-id="<?= $tank['id'] ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Add Tank Modal -->
<div class="modal fade" id="addTankModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<div class="modal-header">
<h5 class="modal-title">Add New Tank</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Tank Name*</label>
<input type="text" class="form-control" name="name" required>
</div>
<div class="mb-3">
<label class="form-label">Bunk*</label>
<select class="form-select" name="bunk_id" required>
<option value="">Select Bunk</option>
<?php foreach ($bunks as $bunk): ?>
<option value="<?= $bunk['id'] ?>"><?= htmlspecialchars($bunk['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Fuel Type*</label>
<select class="form-select" name="fuel_type_id" required>
<option value="">Select Fuel Type</option>
<?php foreach ($fuel_types as $type): ?>
<option value="<?= $type['id'] ?>"><?= htmlspecialchars($type['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Capacity (Litres)*</label>
<input type="number" class="form-control" name="capacity" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="add_tank" class="btn btn-primary">Save Tank</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Tank Modal -->
<div class="modal fade" id="editTankModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<input type="hidden" name="tank_id" id="edit_tank_id">
<div class="modal-header">
<h5 class="modal-title">Edit Tank</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Tank Name*</label>
<input type="text" class="form-control" id="edit_name" name="name" required>
</div>
<div class="mb-3">
<label class="form-label">Bunk*</label>
<select class="form-select" id="edit_bunk_id" name="bunk_id" required>
<?php foreach ($bunks as $bunk): ?>
<option value="<?= $bunk['id'] ?>"><?= htmlspecialchars($bunk['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Fuel Type*</label>
<select class="form-select" id="edit_fuel_type_id" name="fuel_type_id" required>
<?php foreach ($fuel_types as $type): ?>
<option value="<?= $type['id'] ?>"><?= htmlspecialchars($type['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Capacity (Litres)*</label>
<input type="number" class="form-control" id="edit_capacity" name="capacity" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="edit_tank" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">Are you sure you want to delete this tank?</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a href="#" id="delete-confirm-btn" class="btn btn-danger">Delete</a>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
<div id="notificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"></div>
<div class="toast-body"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const notification = <?php echo json_encode($notification); ?>;
if (notification) {
const toastEl = document.getElementById('notificationToast');
const toastHeader = toastEl.querySelector('.toast-header');
const toastBody = toastEl.querySelector('.toast-body');
toastHeader.innerHTML = `<strong class="me-auto">Notification</strong><button type="button" class="btn-close" data-bs-dismiss="toast"></button>`;
toastBody.textContent = notification.text;
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning');
toastEl.classList.add('bg-' + notification.type, 'text-white');
new bootstrap.Toast(toastEl).show();
}
const editModal = document.getElementById('editTankModal');
editModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
editModal.querySelector('#edit_tank_id').value = id;
editModal.querySelector('#edit_name').value = button.getAttribute('data-name');
editModal.querySelector('#edit_bunk_id').value = button.getAttribute('data-bunk-id');
editModal.querySelector('#edit_fuel_type_id').value = button.getAttribute('data-fuel-type-id');
editModal.querySelector('#edit_capacity').value = button.getAttribute('data-capacity');
});
const deleteModal = document.getElementById('deleteConfirmModal');
deleteModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
deleteModal.querySelector('#delete-confirm-btn').href = 'tanks.php?action=delete&id=' + id;
});
});
</script>
</body>
</html>

329
users.php Normal file
View File

@ -0,0 +1,329 @@
<?php
session_start();
require_once 'db/config.php';
$notification = null;
// Handle Add, Edit, Delete actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$db = db();
// Add User
if (isset($_POST['add_user'])) {
$username = trim($_POST['username']);
$password = $_POST['password'];
$role_id = $_POST['role_id'];
$bunk_id = !empty($_POST['bunk_id']) ? $_POST['bunk_id'] : null;
if (!empty($username) && !empty($password) && !empty($role_id)) {
try {
$hashed_password = password_hash($password, PASSWORD_BCRYPT);
$stmt = $db->prepare("INSERT INTO users (username, password, role_id, bunk_id) VALUES (?, ?, ?, ?)");
$stmt->execute([$username, $hashed_password, $role_id, $bunk_id]);
$_SESSION['notification'] = ['text' => 'User added successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error adding user: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Username, password, and role are required.', 'type' => 'warning'];
}
}
// Edit User
elseif (isset($_POST['edit_user'])) {
$id = $_POST['user_id'];
$username = trim($_POST['username']);
$role_id = $_POST['role_id'];
$bunk_id = !empty($_POST['bunk_id']) ? $_POST['bunk_id'] : null;
$password = $_POST['password'];
if (!empty($username) && !empty($role_id) && !empty($id)) {
try {
if (!empty($password)) {
$hashed_password = password_hash($password, PASSWORD_BCRYPT);
$stmt = $db->prepare("UPDATE users SET username = ?, role_id = ?, bunk_id = ?, password = ? WHERE id = ?");
$stmt->execute([$username, $role_id, $bunk_id, $hashed_password, $id]);
} else {
$stmt = $db->prepare("UPDATE users SET username = ?, role_id = ?, bunk_id = ? WHERE id = ?");
$stmt->execute([$username, $role_id, $bunk_id, $id]);
}
$_SESSION['notification'] = ['text' => 'User updated successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error updating user: ' . $e->getMessage(), 'type' => 'danger'];
}
} else {
$_SESSION['notification'] = ['text' => 'Username, role, and ID are required.', 'type' => 'warning'];
}
}
header("Location: users.php");
exit;
}
// Delete User (Soft Delete)
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
try {
$db = db();
$stmt = $db->prepare("UPDATE users SET deleted_at = NOW() WHERE id = ?");
$stmt->execute([$_GET['id']]);
$_SESSION['notification'] = ['text' => 'User deleted successfully!', 'type' => 'success'];
} catch (PDOException $e) {
$_SESSION['notification'] = ['text' => 'Error deleting user: ' . $e->getMessage(), 'type' => 'danger'];
}
header("Location: users.php");
exit;
}
if (isset($_SESSION['notification'])) {
$notification = $_SESSION['notification'];
unset($_SESSION['notification']);
}
// Fetch roles and bunks for dropdowns
$roles = db()->query("SELECT * FROM roles")->fetchAll(PDO::FETCH_ASSOC);
$bunks = db()->query("SELECT * FROM bunks WHERE deleted_at IS NULL")->fetchAll(PDO::FETCH_ASSOC);
$users = db()->query("SELECT u.*, r.name as role_name, b.name as bunk_name FROM users u JOIN roles r ON u.role_id = r.id LEFT JOIN bunks b ON u.bunk_id = b.id WHERE u.deleted_at IS NULL ORDER BY u.created_at DESC")->fetchAll(PDO::FETCH_ASSOC);
$page_title = "User Management";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($page_title) ?> - Petrol Pump Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
</head>
<body>
<?php include 'includes/header.php'; ?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1><i class="bi bi-people-fill"></i> <?= htmlspecialchars($page_title) ?></h1>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addUserModal">
<i class="bi bi-plus-circle"></i> Add New User
</button>
</div>
<div class="card">
<div class="card-body">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>ID</th>
<th>Username</th>
<th>Role</th>
<th>Assigned Bunk</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($users)): ?>
<tr>
<td colspan="6" class="text-center">No users found.</td>
</tr>
<?php else: ?>
<?php foreach ($users as $user): ?>
<tr>
<td><?= htmlspecialchars($user['id']) ?></td>
<td><?= htmlspecialchars($user['username']) ?></td>
<td><span class="badge bg-secondary"><?= htmlspecialchars($user['role_name']) ?></span></td>
<td><?= htmlspecialchars($user['bunk_name'] ?? 'N/A') ?></td>
<td><?= htmlspecialchars(date('Y-m-d H:i', strtotime($user['created_at']))) ?></td>
<td>
<button type="button" class="btn btn-sm btn-outline-primary edit-btn"
data-bs-toggle="modal" data-bs-target="#editUserModal"
data-id="<?= $user['id'] ?>"
data-username="<?= htmlspecialchars($user['username']) ?>"
data-role-id="<?= $user['role_id'] ?>"
data-bunk-id="<?= $user['bunk_id'] ?>">
<i class="bi bi-pencil-square"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-danger delete-btn"
data-bs-toggle="modal" data-bs-target="#deleteConfirmModal"
data-id="<?= $user['id'] ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Add User Modal -->
<div class="modal fade" id="addUserModal" tabindex="-1" aria-labelledby="addUserModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addUserModalLabel">Add New User</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST">
<div class="modal-body">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="mb-3">
<label for="role_id" class="form-label">Role</label>
<select class="form-select" id="role_id" name="role_id" required>
<option value="">Select Role</option>
<?php foreach ($roles as $role): ?>
<option value="<?= $role['id'] ?>"><?= htmlspecialchars($role['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="bunk_id" class="form-label">Assign to Bunk (Optional)</label>
<select class="form-select" id="bunk_id" name="bunk_id">
<option value="">Select Bunk</option>
<?php foreach ($bunks as $bunk): ?>
<option value="<?= $bunk['id'] ?>"><?= htmlspecialchars($bunk['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="add_user" class="btn btn-primary">Save User</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit User Modal -->
<div class="modal fade" id="editUserModal" tabindex="-1" aria-labelledby="editUserModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<input type="hidden" name="user_id" id="edit_user_id">
<div class="modal-header">
<h5 class="modal-title" id="editUserModalLabel">Edit User</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="edit_username" class="form-label">Username</label>
<input type="text" class="form-control" id="edit_username" name="username" required>
</div>
<div class="mb-3">
<label for="edit_password" class="form-label">New Password (optional)</label>
<input type="password" class="form-control" id="edit_password" name="password">
</div>
<div class="mb-3">
<label for="edit_role_id" class="form-label">Role</label>
<select class="form-select" id="edit_role_id" name="role_id" required>
<option value="">Select Role</option>
<?php foreach ($roles as $role): ?>
<option value="<?= $role['id'] ?>"><?= htmlspecialchars($role['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="edit_bunk_id" class="form-label">Assign to Bunk (Optional)</label>
<select class="form-select" id="edit_bunk_id" name="bunk_id">
<option value="">Select Bunk</option>
<?php foreach ($bunks as $bunk): ?>
<option value="<?= $bunk['id'] ?>"><?= htmlspecialchars($bunk['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" name="edit_user" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1" aria-labelledby="deleteConfirmModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteConfirmModalLabel">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Are you sure you want to delete this user? This action cannot be undone.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a href="#" id="delete-confirm-btn" class="btn btn-danger">Delete</a>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div class="position-fixed bottom-0 end-0 p-3 toast-container">
<div id="notificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">Notification</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Toast notification
<?php if ($notification): ?>
const toastEl = document.getElementById('notificationToast');
const toastBody = toastEl.querySelector('.toast-body');
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning');
toastEl.classList.add('bg-<?= $notification["type"] ?>', 'text-white');
toastBody.textContent = '<?= addslashes(htmlspecialchars($notification["text"])) ?>';
const toast = new bootstrap.Toast(toastEl);
toast.show();
<?php endif; ?>
// Edit modal handler
const editUserModal = document.getElementById('editUserModal');
editUserModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
const username = button.getAttribute('data-username');
const roleId = button.getAttribute('data-role-id');
const bunkId = button.getAttribute('data-bunk-id');
const modalTitle = editUserModal.querySelector('.modal-title');
const modalBodyInputId = editUserModal.querySelector('#edit_user_id');
const modalBodyInputUsername = editUserModal.querySelector('#edit_username');
const modalBodyInputRoleId = editUserModal.querySelector('#edit_role_id');
const modalBodyInputBunkId = editUserModal.querySelector('#edit_bunk_id');
modalTitle.textContent = 'Edit User: ' + username;
modalBodyInputId.value = id;
modalBodyInputUsername.value = username;
modalBodyInputRoleId.value = roleId;
modalBodyInputBunkId.value = bunkId;
});
// Delete confirmation handler
const deleteConfirmModal = document.getElementById('deleteConfirmModal');
deleteConfirmModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const id = button.getAttribute('data-id');
const deleteBtn = deleteConfirmModal.querySelector('#delete-confirm-btn');
deleteBtn.href = 'users.php?action=delete&id=' + id;
});
});
</script>
</body>
</html>