Compare commits

...

1 Commits

Author SHA1 Message Date
Flatlogic Bot
6c14b2436f 2.0 2025-12-18 09:40:37 +00:00
55 changed files with 3126 additions and 146 deletions

74
add_shipment_details.php Normal file
View File

@ -0,0 +1,74 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id']) || (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) && empty($_SESSION['dealer_id'])) {
header('Location: login.php');
exit;
}
$request_id = null;
if (isset($_GET['request_id'])) {
$request_id = $_GET['request_id'];
} elseif (isset($_POST['request_id'])) {
$request_id = $_POST['request_id'];
}
if ($request_id === null) {
header('Location: service_requests.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$carrier = $_POST['carrier'];
$tracking_number = $_POST['tracking_number'];
$shipment_date = $_POST['shipment_date'];
try {
$pdo = db();
$sql = "INSERT INTO shipment_details (service_request_id, carrier, tracking_number, shipment_date) VALUES (?, ?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$request_id, $carrier, $tracking_number, $shipment_date]);
header('Location: service_request_details.php?id=' . $request_id);
exit;
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
}
?>
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h1 class="h3 mb-0">Add Shipment Details</h1>
</div>
<div class="card-body">
<form action="add_shipment_details.php" method="POST">
<input type="hidden" name="request_id" value="<?php echo htmlspecialchars($request_id); ?>">
<div class="mb-3">
<label for="carrier" class="form-label">Carrier</label>
<input type="text" class="form-control" id="carrier" name="carrier" required>
</div>
<div class="mb-3">
<label for="tracking_number" class="form-label">Tracking Number</label>
<input type="text" class="form-control" id="tracking_number" name="tracking_number" required>
</div>
<div class="mb-3">
<label for="shipment_date" class="form-label">Shipment Date</label>
<input type="date" class="form-control" id="shipment_date" name="shipment_date" required>
</div>
<button type="submit" class="btn btn-primary">Add Shipment</button>
<a href="service_request_details.php?id=<?php echo htmlspecialchars($request_id); ?>" class="btn btn-secondary">Cancel</a>
</form>
</div>
</div>
</div>
</div>
<?php
require_once 'includes/footer.php';
?>

52
admin/add_dealer.php Normal file
View File

@ -0,0 +1,52 @@
<?php
require_once __DIR__ . '/../includes/header.php';
require_once __DIR__ . '/../db/config.php';
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: /login.php');
exit;
}
$error = '';
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
if (empty($name) || empty($email)) {
$error = 'Name and email are required.';
} else {
$pdo = db();
$stmt = $pdo->prepare("INSERT INTO dealers (name, email) VALUES (?, ?)");
if ($stmt->execute([$name, $email])) {
$success = 'Dealer added successfully.';
} else {
$error = 'Failed to add dealer.';
}
}
}
?>
<div class="container">
<h1 class="mt-5">Add Dealer</h1>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?php echo $success; ?></div>
<?php endif; ?>
<form method="POST" action="add_dealer.php">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<button type="submit" class="btn btn-primary">Add Dealer</button>
</form>
</div>
<?php require_once __DIR__ . '/../includes/footer.php'; ?>

47
admin/delete_dealer.php Normal file
View File

@ -0,0 +1,47 @@
<?php
require_once __DIR__ . '/../includes/header.php';
require_once __DIR__ . '/../db/config.php';
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: /login.php');
exit;
}
$dealer_id = $_GET['id'] ?? null;
if (!$dealer_id) {
header('Location: manage_dealers.php');
exit;
}
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['confirm'])) {
$stmt = $pdo->prepare("DELETE FROM dealers WHERE id = ?");
$stmt->execute([$dealer_id]);
}
header('Location: manage_dealers.php');
exit;
}
$stmt = $pdo->prepare("SELECT * FROM dealers WHERE id = ?");
$stmt->execute([$dealer_id]);
$dealer = $stmt->fetch();
if (!$dealer) {
header('Location: manage_dealers.php');
exit;
}
?>
<div class="container">
<h1 class="mt-5">Delete Dealer</h1>
<p>Are you sure you want to delete the dealer "<?php echo htmlspecialchars($dealer['name']); ?>"?</p>
<form method="POST" action="delete_dealer.php?id=<?php echo $dealer_id; ?>">
<button type="submit" name="confirm" class="btn btn-danger">Yes, Delete</button>
<a href="manage_dealers.php" class="btn btn-secondary">No, Cancel</a>
</form>
</div>
<?php require_once __DIR__ . '/../includes/footer.php'; ?>

68
admin/edit_dealer.php Normal file
View File

@ -0,0 +1,68 @@
<?php
require_once __DIR__ . '/../includes/header.php';
require_once __DIR__ . '/../db/config.php';
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: /login.php');
exit;
}
$error = '';
$success = '';
$dealer_id = $_GET['id'] ?? null;
if (!$dealer_id) {
header('Location: manage_dealers.php');
exit;
}
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
if (empty($name) || empty($email)) {
$error = 'Name and email are required.';
} else {
$stmt = $pdo->prepare("UPDATE dealers SET name = ?, email = ? WHERE id = ?");
if ($stmt->execute([$name, $email, $dealer_id])) {
$success = 'Dealer updated successfully.';
} else {
$error = 'Failed to update dealer.';
}
}
}
$stmt = $pdo->prepare("SELECT * FROM dealers WHERE id = ?");
$stmt->execute([$dealer_id]);
$dealer = $stmt->fetch();
if (!$dealer) {
header('Location: manage_dealers.php');
exit;
}
?>
<div class="container">
<h1 class="mt-5">Edit Dealer</h1>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?php echo $success; ?></div>
<?php endif; ?>
<form method="POST" action="edit_dealer.php?id=<?php echo $dealer_id; ?>">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($dealer['name']); ?>" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" id="email" name="email" value="<?php echo htmlspecialchars($dealer['email']); ?>" required>
</div>
<button type="submit" class="btn btn-primary">Update Dealer</button>
</form>
</div>
<?php require_once __DIR__ . '/../includes/footer.php'; ?>

61
admin/import_products.php Normal file
View File

@ -0,0 +1,61 @@
<?php
require_once '../includes/header.php';
require_once '../db/config.php';
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: ../login.php');
exit;
}
$message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['product_csv'])) {
$file = $_FILES['product_csv']['tmp_name'];
if (($handle = fopen($file, 'r')) !== FALSE) {
$pdo = db();
$pdo->beginTransaction();
try {
$stmt = $pdo->prepare("INSERT INTO products (name, model_number, description, image_url, price, category_id, features, sample_type, measurement_parameters, result_speed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
fgetcsv($handle); // Skip header row
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
//Pad the array with nulls if it doesn't have enough elements
$data = array_pad($data, 10, null);
$stmt->execute($data);
}
$pdo->commit();
$message = "<div class='alert alert-success'>Products imported successfully.</div>";
} catch (Exception $e) {
$pdo->rollBack();
$message = "<div class='alert alert-danger'>Error importing products: " . $e->getMessage() . "</div>";
}
fclose($handle);
} else {
$message = "<div class='alert alert-danger'>Error opening the CSV file.</div>";
}
}
?>
<h1 class="mb-4">Import Products from CSV</h1>
<?php echo $message; ?>
<p>Upload a CSV file with the following columns: `name`, `model_number`, `description`, `image_url`, `price`, `category_id`, `features`, `sample_type`, `measurement_parameters`, `result_speed`.</p>
<p>The `category_id` should correspond to an existing ID in the `product_categories` table.</p>
<form action="import_products.php" method="post" enctype="multipart/form-data">
<div class="mb-3">
<label for="product_csv" class="form-label">Product CSV File</label>
<input class="form-control" type="file" id="product_csv" name="product_csv" accept=".csv" required>
</div>
<button type="submit" class="btn btn-primary">Import Products</button>
</form>
<p class="mt-4"><a href="index.php">Back to Admin</a></p>
<?php require_once '../includes/footer.php'; ?>

23
admin/index.php Normal file
View File

@ -0,0 +1,23 @@
<?php
require_once __DIR__ . '/../includes/header.php';
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
// Redirect non-admin users to the login page
header('Location: /login.php');
exit;
}
// Admin dashboard content goes here
?>
<div class="container">
<h1 class="mt-5">Admin Panel</h1>
<p class="lead">Welcome to the admin panel. Here you can manage users, products, and other settings.</p>
<a href="manage_dealers.php" class="btn btn-primary">Manage Dealers</a>
<a href="reports.php" class="btn btn-info">Reports</a>
<a href="import_products.php" class="btn btn-success">Import Products</a>
</div>
<?php
require_once __DIR__ . '/../includes/footer.php';
?>

47
admin/manage_dealers.php Normal file
View File

@ -0,0 +1,47 @@
<?php
require_once __DIR__ . '/../includes/header.php';
require_once __DIR__ . '/../db/config.php';
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
// Redirect non-admin users to the login page
header('Location: /login.php');
exit;
}
$pdo = db();
$stmt = $pdo->query("SELECT * FROM dealers");
$dealers = $stmt->fetchAll();
?>
<div class="container">
<h1 class="mt-5">Manage Dealers</h1>
<a href="add_dealer.php" class="btn btn-primary mb-3">Add Dealer</a>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($dealers as $dealer): ?>
<tr>
<td><?php echo htmlspecialchars($dealer['id']); ?></td>
<td><?php echo htmlspecialchars($dealer['name']); ?></td>
<td><?php echo htmlspecialchars($dealer['email']); ?></td>
<td>
<a href="edit_dealer.php?id=<?php echo $dealer['id']; ?>" class="btn btn-sm btn-info">Edit</a>
<a href="delete_dealer.php?id=<?php echo $dealer['id']; ?>" class="btn btn-sm btn-danger">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
require_once __DIR__ . '/../includes/footer.php';
?>

113
admin/reports.php Normal file
View File

@ -0,0 +1,113 @@
<?php
require_once __DIR__ . '/../includes/header.php';
require_once __DIR__ . '/../db/config.php';
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: /login.php');
exit;
}
$pdo = db();
// Fetch dealers for the filter dropdown
$stmt_dealers = $pdo->query("SELECT id, name FROM dealers ORDER BY name ASC");
$dealers = $stmt_dealers->fetchAll();
// Get filter values
$status_filter = $_GET['status'] ?? '';
$dealer_filter = $_GET['dealer_id'] ?? '';
$sql = "SELECT sr.*, p.name as product_name, d.name as dealer_name
FROM service_requests sr
JOIN products p ON sr.product_id = p.id
JOIN dealers d ON sr.dealer_id = d.id";
$where_clauses = [];
$params = [];
if (!empty($status_filter)) {
$where_clauses[] = "sr.status = ?";
$params[] = $status_filter;
}
if (!empty($dealer_filter)) {
$where_clauses[] = "sr.dealer_id = ?";
$params[] = $dealer_filter;
}
if (!empty($where_clauses)) {
$sql .= " WHERE " . implode(" AND ", $where_clauses);
}
$sql .= " ORDER BY sr.created_at DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$service_requests = $stmt->fetchAll();
?>
<div class="container">
<h1 class="mt-5">Service Request Report</h1>
<form method="GET" class="mb-4">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label for="status">Filter by Status</label>
<select name="status" id="status" class="form-control">
<option value="">All</option>
<option value="pending" <?php echo ($status_filter === 'pending') ? 'selected' : ''; ?>>Pending</option>
<option value="in_progress" <?php echo ($status_filter === 'in_progress') ? 'selected' : ''; ?>>In Progress</option>
<option value="resolved" <?php echo ($status_filter === 'resolved') ? 'selected' : ''; ?>>Resolved</option>
<option value="closed" <?php echo ($status_filter === 'closed') ? 'selected' : ''; ?>>Closed</option>
</select>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="dealer_id">Filter by Dealer</label>
<select name="dealer_id" id="dealer_id" class="form-control">
<option value="">All</option>
<?php foreach ($dealers as $dealer): ?>
<option value="<?php echo $dealer['id']; ?>" <?php echo ($dealer_filter == $dealer['id']) ? 'selected' : ''; ?>><?php echo htmlspecialchars($dealer['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>&nbsp;</label>
<button type="submit" class="btn btn-primary btn-block">Filter</button>
</div>
</div>
</div>
</form>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Dealer</th>
<th>Product</th>
<th>Serial</th>
<th>Status</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<?php foreach ($service_requests as $request): ?>
<tr>
<td><?php echo $request['id']; ?></td>
<td><?php echo htmlspecialchars($request['dealer_name']); ?></td>
<td><?php echo htmlspecialchars($request['product_name']); ?></td>
<td><a href="../service_request_details.php?id=<?php echo $request['id']; ?>"><?php echo htmlspecialchars($request['serial_number']); ?></a></td>
<td><span class="badge bg-warning text-dark"><?php echo htmlspecialchars(ucfirst($request['status'])); ?></span></td>
<td><?php echo date('M j, Y', strtotime($request['created_at'])); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php require_once __DIR__ . '/../includes/footer.php'; ?>

View File

@ -0,0 +1,32 @@
<?php
require_once '../db/config.php';
if (isset($_GET['sold_serial_id'])) {
$sold_serial_id = $_GET['sold_serial_id'];
try {
$pdo = db();
$stmt = $pdo->prepare(
"SELECT p.name, p.model_number, p.part_number, p.description, p.image_url
FROM products p
JOIN sold_serials ss ON p.id = ss.product_id
WHERE ss.id = ?"
);
$stmt->execute([$sold_serial_id]);
$product = $stmt->fetch();
if ($product) {
header('Content-Type: application/json');
echo json_encode($product);
} else {
header("HTTP/1.0 404 Not Found");
echo json_encode(['error' => 'Product not found']);
}
} catch (PDOException $e) {
header("HTTP/1.0 500 Internal Server Error");
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
}
} else {
header("HTTP/1.0 400 Bad Request");
echo json_encode(['error' => 'No serial ID provided']);
}

23
assets/css/custom.css Normal file
View File

@ -0,0 +1,23 @@
body {
background-color: #f8f9fa;
}
.navbar {
box-shadow: 0 2px 4px rgba(0,0,0,.1);
}
.card {
border-radius: 0.375rem;
box-shadow: 0 4px 6px rgba(0,0,0,.05);
}
.btn-primary {
background-color: #0d6efd;
border: none;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

180
cart.php Normal file
View File

@ -0,0 +1,180 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
// Initialize cart if it doesn't exist
if (!isset($_SESSION['cart'])) {
$_SESSION['cart'] = [];
}
$pdo = db();
$action = $_GET['action'] ?? '';
switch ($action) {
case 'add':
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['product_id'])) {
$product_id = $_POST['product_id'];
$quantity = (int)($_POST['quantity'] ?? 1);
if ($quantity > 0) {
if (isset($_SESSION['cart'][$product_id])) {
$_SESSION['cart'][$product_id] += $quantity;
} else {
$_SESSION['cart'][$product_id] = $quantity;
}
}
}
header('Location: products.php');
exit;
case 'update':
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['quantities'])) {
foreach ($_POST['quantities'] as $product_id => $quantity) {
$quantity = (int)$quantity;
if ($quantity > 0) {
$_SESSION['cart'][$product_id] = $quantity;
} else {
unset($_SESSION['cart'][$product_id]);
}
}
}
header('Location: cart.php');
exit;
case 'place_order':
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_SESSION['cart'])) {
$total_amount = 0;
$cart_products = [];
$product_ids = array_keys($_SESSION['cart']);
if (empty($product_ids)) {
header('Location: cart.php');
exit;
}
$sql = "SELECT * FROM products WHERE id IN (" . implode(',', array_fill(0, count($product_ids), '?')) . ")";
$stmt = $pdo->prepare($sql);
$stmt->execute($product_ids);
$products_array = $stmt->fetchAll(PDO::FETCH_ASSOC);
$products = [];
foreach ($products_array as $product) {
$products[$product['id']] = $product;
}
// Debug: Dump products array
// var_dump($products);
foreach ($_SESSION['cart'] as $product_id => $quantity) {
if (isset($products[$product_id])) {
$product = $products[$product_id];
$price = $product['price'] ?? 0;
$total_amount += $price * $quantity;
$cart_products[] = ['product' => $product, 'quantity' => $quantity];
}
}
// Debug: Dump total amount
// var_dump($total_amount);
if ($total_amount > 0) {
$pdo->beginTransaction();
try {
$sql = 'INSERT INTO orders (user_id, total_amount, status) VALUES (?, ?, ?)';
$stmt = $pdo->prepare($sql);
$stmt->execute([$_SESSION['user_id'], $total_amount, 'Pending']);
$order_id = $pdo->lastInsertId();
$sql = 'INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)';
$stmt = $pdo->prepare($sql);
foreach ($cart_products as $item) {
// Use the price from the database, not the one from the session/cart loop
$product_price = $products[$item['product']['id']]['price'] ?? 0;
$stmt->execute([$order_id, $item['product']['id'], $item['quantity'], $product_price]);
}
$pdo->commit();
$_SESSION['cart'] = [];
header('Location: order_details.php?id=' . $order_id);
exit;
} catch (Exception $e) {
$pdo->rollBack();
// Debug: Log exception
error_log($e->getMessage());
header('Location: cart.php?error=place_order_failed');
exit;
}
} else {
header('Location: cart.php?error=zero_total');
exit;
}
}
header('Location: cart.php');
exit;
}
// Display Cart
$cart_items = [];
$total_price = 0;
if (!empty($_SESSION['cart'])) {
$product_ids = array_keys($_SESSION['cart']);
$sql = "SELECT * FROM products WHERE id IN (" . implode(',', array_fill(0, count($product_ids), '?')) . ")";
$stmt = $pdo->prepare($sql);
$stmt->execute($product_ids);
$products = $stmt->fetchAll();
foreach ($products as $product) {
$product_id = $product['id'];
$quantity = $_SESSION['cart'][$product_id];
$price = $product['price'] ?? 0;
$cart_items[] = ['product' => $product, 'quantity' => $quantity, 'price' => $price];
$total_price += $price * $quantity;
}
}
?>
<h1 class="mb-4">Shopping Cart</h1>
<?php if (empty($cart_items)) : ?>
<div class="alert alert-info">Your cart is empty.</div>
<?php else : ?>
<form action="cart.php?action=update" method="post">
<table class="table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($cart_items as $item) : ?>
<tr>
<td><?php echo htmlspecialchars($item['product']['name']); ?></td>
<td>$<?php echo number_format($item['price'], 2); ?></td>
<td>
<input type="number" name="quantities[<?php echo $item['product']['id']; ?>]" value="<?php echo $item['quantity']; ?>" min="1" class="form-control" style="width: 80px;">
</td>
<td>$<?php echo number_format($item['price'] * $item['quantity'], 2); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="d-flex justify-content-between align-items-center mb-3">
<button type="submit" class="btn btn-secondary">Update Cart</button>
<h4>Total: $<?php echo number_format($total_price, 2); ?></h4>
</div>
</form>
<form action="cart.php?action=place_order" method="post" class="text-end">
<button type="submit" class="btn btn-primary">Place Order</button>
</form>
<?php endif; ?>
<?php require_once 'includes/footer.php'; ?>

View File

@ -0,0 +1,19 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = "
CREATE TABLE IF NOT EXISTS warranty_registrations (
id INT AUTO_INCREMENT PRIMARY KEY,
serial_number VARCHAR(255) NOT NULL,
customer_name VARCHAR(255) NOT NULL,
installation_date DATE NOT NULL,
registration_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);";
$pdo->exec($sql);
echo "Table 'warranty_registrations' created successfully." . PHP_EOL;
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}
?>

View File

@ -0,0 +1,18 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
model_number VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
SQL;
$pdo->exec($sql);
echo "Table 'products' created successfully." . PHP_EOL;
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

View File

@ -0,0 +1,18 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS dealers (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
SQL;
$pdo->exec($sql);
echo "Table 'dealers' created successfully." . PHP_EOL;
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

View File

@ -0,0 +1,22 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS sold_serials (
id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
dealer_id INT NOT NULL,
serial_number VARCHAR(255) UNIQUE NOT NULL,
is_activated BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE,
FOREIGN KEY (dealer_id) REFERENCES dealers(id) ON DELETE CASCADE
);
SQL;
$pdo->exec($sql);
echo "Table 'sold_serials' created successfully." . PHP_EOL;
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

View File

@ -0,0 +1,22 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
// Add sold_serial_id column
$sql_add_column = "ALTER TABLE warranty_registrations ADD COLUMN sold_serial_id INT NULL AFTER serial_number";
$pdo->exec($sql_add_column);
// Add foreign key constraint
$sql_add_fk = "ALTER TABLE warranty_registrations ADD CONSTRAINT fk_sold_serial FOREIGN KEY (sold_serial_id) REFERENCES sold_serials(id) ON DELETE SET NULL";
$pdo->exec($sql_add_fk);
echo "Table 'warranty_registrations' modified successfully." . PHP_EOL;
} catch (PDOException $e) {
// Check if column already exists to avoid fatal error on re-run
if (strpos($e->getMessage(), 'Duplicate column name') === false) {
die("DB ERROR: " . $e->getMessage());
}
echo "Column 'sold_serial_id' already exists in 'warranty_registrations'." . PHP_EOL;
}

View File

@ -0,0 +1,21 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
dealer_id INT NOT NULL,
username VARCHAR(255) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (dealer_id) REFERENCES dealers(id) ON DELETE CASCADE
);
SQL;
$pdo->exec($sql);
echo "Migration for users table applied successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage());
}

View File

@ -0,0 +1,15 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
ALTER TABLE products
ADD COLUMN description TEXT NULL,
ADD COLUMN image_url VARCHAR(255) NULL;
SQL;
$pdo->exec($sql);
echo "Migration to add description and image_url to products table applied successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage());
}

View File

@ -0,0 +1,24 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS service_requests (
id INT AUTO_INCREMENT PRIMARY KEY,
dealer_id INT NOT NULL,
product_id INT NOT NULL,
serial_number VARCHAR(255) NOT NULL,
issue_description TEXT NOT NULL,
status VARCHAR(50) NOT NULL DEFAULT 'pending', -- e.g., pending, in_progress, resolved, closed
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (dealer_id) REFERENCES dealers(id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
);
SQL;
$pdo->exec($sql);
echo "Migration for service_requests table applied successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage());
}

View File

@ -0,0 +1,21 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS service_request_comments (
id INT AUTO_INCREMENT PRIMARY KEY,
service_request_id INT NOT NULL,
user_id INT NOT NULL,
comment TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (service_request_id) REFERENCES service_requests(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
SQL;
$pdo->exec($sql);
echo "Migration for service_request_comments table applied successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage());
}

View File

@ -0,0 +1,11 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = "ALTER TABLE users ADD COLUMN is_admin BOOLEAN NOT NULL DEFAULT FALSE";
$pdo->exec($sql);
echo "Migration to add is_admin to users table applied successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage());
}

View File

@ -0,0 +1,11 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = "ALTER TABLE service_requests ADD COLUMN file_path VARCHAR(255) DEFAULT NULL";
$pdo->exec($sql);
echo "Migration to add file_path to service_requests table applied successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage());
}

View File

@ -0,0 +1,22 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS notifications (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
service_request_id INT NOT NULL,
message VARCHAR(255) NOT NULL,
is_read BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (service_request_id) REFERENCES service_requests(id) ON DELETE CASCADE
);
SQL;
$pdo->exec($sql);
echo "Migration for notifications table applied successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage());
}

View File

@ -0,0 +1,13 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = "ALTER TABLE service_requests ADD COLUMN user_id INT NOT NULL AFTER dealer_id";
$pdo->exec($sql);
$sql_fk = "ALTER TABLE service_requests ADD FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE";
$pdo->exec($sql_fk);
echo "Migration to add user_id to service_requests table applied successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage());
}

View File

@ -0,0 +1,19 @@
<?php
require_once 'config.php';
try {
$db = db();
$sql = "
CREATE TABLE IF NOT EXISTS `product_categories` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`description` TEXT,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
";
$db->exec($sql);
echo "Table 'product_categories' created successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Error creating table: " . $e->getMessage());
}
?>

View File

@ -0,0 +1,20 @@
<?php
require_once 'config.php';
try {
$db = db();
$sql = "
ALTER TABLE `products`
ADD COLUMN `category_id` INT NULL,
ADD COLUMN `features` TEXT NULL,
ADD COLUMN `sample_type` VARCHAR(255) NULL,
ADD COLUMN `measurement_parameters` TEXT NULL,
ADD COLUMN `result_speed` VARCHAR(255) NULL,
ADD CONSTRAINT `fk_products_category_id` FOREIGN KEY (`category_id`) REFERENCES `product_categories`(`id`) ON DELETE SET NULL;
";
$db->exec($sql);
echo "Table 'products' altered successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Error altering table: " . $e->getMessage());
}
?>

View File

@ -0,0 +1,21 @@
<?php
require_once 'config.php';
try {
$db = db();
$sql = "
CREATE TABLE IF NOT EXISTS `orders` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`user_id` INT NOT NULL,
`total_amount` DECIMAL(10, 2) NOT NULL,
`status` VARCHAR(50) NOT NULL DEFAULT 'Pending',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
);
";
$db->exec($sql);
echo "Table 'orders' created successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Error creating table: " . $e->getMessage());
}
?>

View File

@ -0,0 +1,23 @@
<?php
require_once 'config.php';
try {
$db = db();
$sql = "
CREATE TABLE IF NOT EXISTS `order_items` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`order_id` INT NOT NULL,
`product_id` INT NOT NULL,
`quantity` INT NOT NULL,
`price` DECIMAL(10, 2) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`order_id`) REFERENCES `orders`(`id`),
FOREIGN KEY (`product_id`) REFERENCES `products`(`id`)
);
";
$db->exec($sql);
echo "Table 'order_items' created successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Error creating table: " . $e->getMessage());
}
?>

View File

@ -0,0 +1,17 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
ALTER TABLE dealers
ADD COLUMN target DECIMAL(10, 2) DEFAULT 0.00,
ADD COLUMN achievement DECIMAL(10, 2) DEFAULT 0.00,
ADD COLUMN credit_limit DECIMAL(10, 2) DEFAULT 0.00,
ADD COLUMN credit_limit_utilisation DECIMAL(10, 2) DEFAULT 0.00;
SQL;
$pdo->exec($sql);
echo "Table 'dealers' updated successfully." . PHP_EOL;
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

View File

@ -0,0 +1,14 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$sql = <<<SQL
ALTER TABLE invoices
ADD COLUMN paid_amount DECIMAL(10, 2) DEFAULT 0.00;
SQL;
$pdo->exec($sql);
echo "Table 'invoices' updated successfully." . PHP_EOL;
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

View File

@ -0,0 +1,38 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$pdo->exec("SET FOREIGN_KEY_CHECKS=0;");
$sql = <<<SQL
ALTER TABLE orders
ADD COLUMN dealer_id INT NULL AFTER user_id;
SQL;
$pdo->exec($sql);
$sql_update = <<<SQL
UPDATE orders o
JOIN users u ON o.user_id = u.id
SET o.dealer_id = u.dealer_id;
SQL;
$pdo->exec($sql_update);
$sql_alter = <<<SQL
ALTER TABLE orders
MODIFY COLUMN dealer_id INT NOT NULL;
SQL;
$pdo->exec($sql_alter);
$sql_fk = <<<SQL
ALTER TABLE orders
ADD FOREIGN KEY (dealer_id) REFERENCES dealers(id);
SQL;
$pdo->exec($sql_fk);
$pdo->exec("SET FOREIGN_KEY_CHECKS=1;");
echo "Table 'orders' updated successfully." . PHP_EOL;
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

View File

@ -0,0 +1,26 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$pdo->exec("SET FOREIGN_KEY_CHECKS=0;");
$sql_update = <<<SQL
UPDATE orders o
JOIN users u ON o.user_id = u.id
SET o.dealer_id = u.dealer_id;
SQL;
$pdo->exec($sql_update);
$sql_fk = <<<SQL
ALTER TABLE orders
ADD FOREIGN KEY (dealer_id) REFERENCES dealers(id);
SQL;
$pdo->exec($sql_fk);
$pdo->exec("SET FOREIGN_KEY_CHECKS=1;");
echo "Table 'orders' fixed successfully." . PHP_EOL;
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

74
db/seed_data.php Normal file
View File

@ -0,0 +1,74 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
// Truncate tables to reset data
$pdo->exec("SET FOREIGN_KEY_CHECKS = 0;");
$pdo->exec("TRUNCATE TABLE order_items;");
$pdo->exec("TRUNCATE TABLE orders;");
$pdo->exec("TRUNCATE TABLE notifications;");
$pdo->exec("TRUNCATE TABLE service_request_comments;");
$pdo->exec("TRUNCATE TABLE service_requests;");
$pdo->exec("TRUNCATE TABLE sold_serials;");
$pdo->exec("TRUNCATE TABLE warranty_registrations;");
$pdo->exec("TRUNCATE TABLE users;");
$pdo->exec("TRUNCATE TABLE dealers;");
$pdo->exec("TRUNCATE TABLE products;");
$pdo->exec("TRUNCATE TABLE product_categories;");
$pdo->exec("SET FOREIGN_KEY_CHECKS = 1;");
echo "Tables truncated successfully.\n";
// Seed Dealers
$dealers = [
['Dealer One', 'contact1@dealerone.com'],
['Dealer Two', 'contact2@dealertwo.com'],
];
$stmt = $pdo->prepare("INSERT INTO dealers (name, email) VALUES (?, ?)");
foreach ($dealers as $dealer) {
$stmt->execute($dealer);
}
echo "Dealers seeded successfully.\n";
// Get Dealer One ID
$stmt = $pdo->prepare("SELECT id FROM dealers WHERE name = ?");
$stmt->execute(['Dealer One']);
$dealer1_id = $stmt->fetchColumn();
// Seed Users
$users = [
['dealer', password_hash('password', PASSWORD_DEFAULT), $dealer1_id, 0],
['admin', password_hash('admin', PASSWORD_DEFAULT), null, 1],
];
$stmt = $pdo->prepare("INSERT INTO users (username, password_hash, dealer_id, is_admin) VALUES (?, ?, ?, ?)");
foreach ($users as $user) {
$stmt->execute($user);
}
echo "Users seeded successfully.\n";
// Seed Product Categories
$categories = ['Analyzers', 'Reagents', 'Consumables'];
$stmt = $pdo->prepare("INSERT INTO product_categories (name) VALUES (?)");
foreach ($categories as $category) {
$stmt->execute([$category]);
}
echo "Product categories seeded successfully.\n";
// Seed Products
$products = [
['Sensa-100 Analyzer', 'SENSA-100', 'Advanced blood gas analyzer.', 'assets/images/products/sensa-100.jpg', 1, 15000.00, 'features of Sensa-100'],
['Sensa-200 Electrolyte Analyzer', 'SENSA-200', 'Automated electrolyte analysis.', 'assets/images/products/sensa-200.jpg', 1, 25000.00, 'features of Sensa-200'],
['Blood Gas Reagent Kit', 'REAGENT-BG', 'Reagent kit for Sensa-100.', 'assets/images/products/reagent-bg.jpg', 2, 500.00, 'features of Reagent-BG'],
['Replacement Electrode', 'CONSUME-ELECTRODE', 'Replacement electrode for analyzers.', 'assets/images/products/electrode.jpg', 3, 250.00, 'features of Electrode']
];
$stmt = $pdo->prepare("INSERT INTO products (name, model_number, description, image_url, category_id, price, features) VALUES (?, ?, ?, ?, ?, ?, ?)");
foreach ($products as $product) {
$stmt->execute($product);
}
echo "Products seeded successfully.\n";
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

59
db/seed_invoices.php Normal file
View File

@ -0,0 +1,59 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
// Check for users
$stmt = $pdo->query("SELECT id, dealer_id FROM users WHERE dealer_id IS NOT NULL AND dealer_id != 0 LIMIT 1");
$user = $stmt->fetch();
if (!$user) {
// Create a dealer
$stmt = $pdo->prepare("INSERT INTO dealers (name, email) VALUES (?, ?)");
$stmt->execute(['Dummy Dealer', 'dummy@dealer.com']);
$dealer_id = $pdo->lastInsertId();
// Create a user
$stmt = $pdo->prepare("INSERT INTO users (dealer_id, username, password_hash) VALUES (?, ?, ?)");
$stmt->execute([$dealer_id, 'dummyuser', password_hash('password', PASSWORD_DEFAULT)]);
$user_id = $pdo->lastInsertId();
} else {
$user_id = $user['id'];
$dealer_id = $user['dealer_id'];
}
// Check for orders
$stmt = $pdo->prepare("SELECT id FROM orders WHERE user_id = ? LIMIT 5");
$stmt->execute([$user_id]);
$orders = $stmt->fetchAll(PDO::FETCH_COLUMN);
if (count($orders) < 5) {
// Create some orders if there aren't enough
$stmt = $pdo->prepare("INSERT INTO orders (user_id, dealer_id, total_amount, status) VALUES (?, ?, ?, ?)");
for ($i = 0; $i < 5; $i++) {
$total_amount = rand(100, 1000);
$stmt->execute([$user_id, $dealer_id, $total_amount, 'Completed']);
}
$stmt = $pdo->prepare("SELECT id FROM orders WHERE user_id = ? LIMIT 5");
$stmt->execute([$user_id]);
$orders = $stmt->fetchAll(PDO::FETCH_COLUMN);
}
$stmt = $pdo->prepare("INSERT INTO invoices (dealer_id, order_id, invoice_date, due_date, total_amount, status, paid_amount) VALUES (?, ?, ?, ?, ?, ?, ?)");
foreach ($orders as $order_id) {
$invoice_date = date('Y-m-d', strtotime('-' . rand(1, 30) . ' days'));
$due_date = date('Y-m-d', strtotime($invoice_date . ' +30 days'));
$total_amount = rand(100, 1000);
$paid_amount = rand(0, $total_amount);
$status = ($paid_amount == $total_amount) ? 'paid' : 'pending';
$stmt->execute([$dealer_id, $order_id, $invoice_date, $due_date, $total_amount, $status, $paid_amount]);
}
echo "Dummy invoices created successfully." . PHP_EOL;
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

View File

@ -0,0 +1,36 @@
<?php
require_once 'db/config.php';
session_start();
if (!isset($_SESSION['user_id']) || (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) && empty($_SESSION['dealer_id'])) {
header('Location: login.php');
exit;
}
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
header('Location: service_requests.php');
exit;
}
$shipment_id = $_GET['id'];
try {
$pdo = db();
// Get the service_request_id before deleting
$stmt_get_id = $pdo->prepare("SELECT service_request_id FROM shipment_details WHERE id = ?");
$stmt_get_id->execute([$shipment_id]);
$service_request_id = $stmt_get_id->fetchColumn();
if ($service_request_id) {
$stmt_delete = $pdo->prepare("DELETE FROM shipment_details WHERE id = ?");
$stmt_delete->execute([$shipment_id]);
header("Location: service_request_details.php?id=$service_request_id");
} else {
header('Location: service_requests.php');
}
exit;
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}

87
edit_shipment_details.php Normal file
View File

@ -0,0 +1,87 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id']) || (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) && empty($_SESSION['dealer_id'])) {
header('Location: login.php');
exit;
}
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
header('Location: service_requests.php');
exit;
}
$shipment_id = $_GET['id'];
try {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM shipment_details WHERE id = ?");
$stmt->execute([$shipment_id]);
$shipment = $stmt->fetch();
if (!$shipment) {
header('Location: service_requests.php');
exit;
}
$service_request_id = $shipment['service_request_id'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$carrier = trim($_POST['carrier']);
$tracking_number = trim($_POST['tracking_number']);
$shipment_date = trim($_POST['shipment_date']);
if (empty($carrier) || empty($tracking_number) || empty($shipment_date)) {
$error_message = "All fields are required.";
} else {
$stmt_update = $pdo->prepare(
"UPDATE shipment_details SET carrier = ?, tracking_number = ?, shipment_date = ? WHERE id = ?"
);
$stmt_update->execute([$carrier, $tracking_number, $shipment_date, $shipment_id]);
header("Location: service_request_details.php?id=$service_request_id");
exit;
}
}
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
?>
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h1 class="h3 mb-0">Edit Shipment Details</h1>
</div>
<div class="card-body">
<?php if (!empty($error_message)): ?>
<div class="alert alert-danger" role="alert">
<?php echo $error_message; ?>
</div>
<?php endif; ?>
<form action="edit_shipment_details.php?id=<?php echo $shipment_id; ?>" method="POST">
<div class="mb-3">
<label for="carrier" class="form-label">Carrier</label>
<input type="text" class="form-control" id="carrier" name="carrier" value="<?php echo htmlspecialchars($shipment['carrier']); ?>" required>
</div>
<div class="mb-3">
<label for="tracking_number" class="form-label">Tracking Number</label>
<input type="text" class="form-control" id="tracking_number" name="tracking_number" value="<?php echo htmlspecialchars($shipment['tracking_number']); ?>" required>
</div>
<div class="mb-3">
<label for="shipment_date" class="form-label">Shipment Date</label>
<input type="date" class="form-control" id="shipment_date" name="shipment_date" value="<?php echo htmlspecialchars($shipment['shipment_date']); ?>" required>
</div>
<button type="submit" class="btn btn-primary">Update Shipment</button>
<a href="service_request_details.php?id=<?php echo $service_request_id; ?>" class="btn btn-secondary">Cancel</a>
</form>
</div>
</div>
</div>
</div>
<?php
require_once 'includes/footer.php';
?>

11
includes/footer.php Normal file
View File

@ -0,0 +1,11 @@
</div> <!-- /container -->
<footer class="footer mt-auto py-3 bg-light">
<div class="container text-center">
<span class="text-muted">© 2025 Sensa Core. All rights reserved.</span>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

100
includes/header.php Normal file
View File

@ -0,0 +1,100 @@
<?php session_start(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sensa Core Dealer Portal</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/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">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="index.php">Sensa Core</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 me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="index.php">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="warranty_registration.php">Warranty Registration</a>
</li>
<li class="nav-item">
<a class="nav-link" href="products.php">Product Catalog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="service_requests.php">Service Requests</a>
</li>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
<li class="nav-item">
<a class="nav-link" href="admin/index.php">Admin</a>
</li>
<?php endif; ?>
</ul>
<ul class="navbar-nav">
<?php if (isset($_SESSION['user_id'])): ?>
<?php
require_once __DIR__ . '/../db/config.php';
$pdo = db();
$stmt_unread = $pdo->prepare("SELECT COUNT(*) as count FROM notifications WHERE user_id = ? AND is_read = 0");
$stmt_unread->execute([$_SESSION['user_id']]);
$unread_count = $stmt_unread->fetchColumn();
$stmt_notifications = $pdo->prepare("SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC LIMIT 5");
$stmt_notifications->execute([$_SESSION['user_id']]);
$notifications = $stmt_notifications->fetchAll();
?>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-bell"></i>
<?php if ($unread_count > 0): ?>
<span class="badge bg-danger"><?php echo $unread_count; ?></span>
<?php endif; ?>
</a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<?php if (empty($notifications)): ?>
<li><a class="dropdown-item" href="#">No notifications</a></li>
<?php else: ?>
<?php foreach ($notifications as $notification): ?>
<li><a class="dropdown-item <?php echo $notification['is_read'] ? '' : 'fw-bold'; ?>" href="service_request_details.php?id=<?php echo $notification['service_request_id']; ?>"><?php echo htmlspecialchars($notification['message']); ?></a></li>
<?php endforeach; ?>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-center" href="notifications.php">View all notifications</a></li>
<?php endif; ?>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" href="cart.php"><i class="bi bi-cart"></i> Cart</a>
</li>
<li class="nav-item">
<a class="nav-link" href="orders.php">My Orders</a>
</li>
<li class="nav-item">
<a class="nav-link" href="invoices.php">Invoices</a>
</li>
<li class="nav-item">
<a class="nav-link" href="targets.php">Targets</a>
</li>
<li class="nav-item">
<a class="nav-link" href="profile.php">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" href="logout.php">Logout</a>
</li>
<?php else: ?>
<li class="nav-item">
<a class="nav-link" href="login.php">Login</a>
</li>
<?php endif; ?>
</ul>
</div>
</div>
</nav>
<div class="container mt-4">

254
index.php
View File

@ -1,150 +1,114 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
require_once __DIR__ . '/includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$dealer_id = $_SESSION['dealer_id'];
try {
$pdo = db();
// Fetch pending service requests
$stmt_pending_requests = $pdo->prepare("SELECT COUNT(*) FROM service_requests WHERE dealer_id = ? AND status = 'pending'");
$stmt_pending_requests->execute([$dealer_id]);
$pending_requests_count = $stmt_pending_requests->fetchColumn();
// Fetch unactivated warranties
$stmt_unactivated_warranties = $pdo->prepare("SELECT COUNT(*) FROM sold_serials WHERE dealer_id = ? AND is_activated = FALSE");
$stmt_unactivated_warranties->execute([$dealer_id]);
$unactivated_warranties_count = $stmt_unactivated_warranties->fetchColumn();
// Fetch total products
$stmt_products = $pdo->query("SELECT COUNT(*) FROM products");
$products_count = $stmt_products->fetchColumn();
} catch (PDOException $e) {
// For simplicity, we'll just display 0 if there's a db error.
$pending_requests_count = 0;
$unactivated_warranties_count = 0;
$products_count = 0;
$open_invoices_count = 0;
$total_due = 0;
}
// Fetch open invoices summary
try {
$user_id = $_SESSION['user_id'];
$is_admin = $_SESSION['is_admin'] ?? false;
$sql = "SELECT COUNT(*) as count, SUM(total_amount) as total FROM invoices WHERE status = 'open'";
$params = [];
if (!$is_admin) {
$sql .= " AND dealer_id = ?";
$params[] = $user_id;
}
$stmt_invoices = $pdo->prepare($sql);
$stmt_invoices->execute($params);
$invoices_summary = $stmt_invoices->fetch();
$open_invoices_count = $invoices_summary['count'] ?? 0;
$total_due = $invoices_summary['total'] ?? 0;
} catch (PDOException $e) {
$open_invoices_count = 0;
$total_due = 0;
}
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title>
<div class="row mb-4">
<div class="col-md-4">
<div class="card text-white bg-warning">
<div class="card-body">
<h5 class="card-title"><i class="bi bi-clock-history"></i> Pending Service Requests</h5>
<p class="card-text display-4"><?php echo $pending_requests_count; ?></p>
<a href="service_requests.php" class="text-white">View Details <i class="bi bi-arrow-right-circle"></i></a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-white bg-info">
<div class="card-body">
<h5 class="card-title"><i class="bi bi-shield-exclamation"></i> Unactivated Warranties</h5>
<p class="card-text display-4"><?php echo $unactivated_warranties_count; ?></p>
<a href="warranty_registration.php" class="text-white">Register Now <i class="bi bi-arrow-right-circle"></i></a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-white bg-success">
<div class="card-body">
<h5 class="card-title"><i class="bi bi-box-seam"></i> Total Products</h5>
<p class="card-text display-4"><?php echo $products_count; ?></p>
<a href="products.php" class="text-white">Browse Catalog <i class="bi bi-arrow-right-circle"></i></a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-white bg-danger">
<div class="card-body">
<h5 class="card-title"><i class="bi bi-file-earmark-text"></i> Open Invoices</h5>
<p class="card-text display-4"><?php echo $open_invoices_count; ?></p>
<p class="card-text">Total Due: $<?php echo number_format($total_due, 2); ?></p>
<a href="invoices.php" class="text-white">View Invoices <i class="bi bi-arrow-right-circle"></i></a>
</div>
</div>
</div>
</div>
<div class="p-5 mb-4 bg-light rounded-3">
<div class="container-fluid py-5">
<h1 class="display-5 fw-bold">Sensa Core Dealer Portal</h1>
<p class="col-md-8 fs-4">Welcome to the central hub for sales, service, and finance operations. Manage your orders, register warranties, and track service requests all in one place.</p>
</div>
</div>
<?php
// Read project preview data from environment
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
require_once 'includes/footer.php';
?>
<?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>
</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>
</div>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
</body>
</html>

105
invoice_details.php Normal file
View File

@ -0,0 +1,105 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
if (!isset($_GET['id'])) {
header('Location: invoices.php');
exit;
}
$invoice_id = $_GET['id'];
try {
$pdo = db();
$sql = "SELECT i.*, o.id as order_id FROM invoices i JOIN orders o ON i.order_id = o.id WHERE i.id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$invoice_id]);
$invoice = $stmt->fetch();
if (!$invoice) {
die('Invoice not found.');
}
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
?>
<h1 class="mb-4">Invoice Details #<?php echo htmlspecialchars($invoice['id']); ?></h1>
<div class="card">
<div class="card-header">Invoice Information</div>
<div class="card-body">
<p><strong>Invoice ID:</strong> <?php echo htmlspecialchars($invoice['id']); ?></p>
<p><strong>Order ID:</strong> <a href="order_details.php?order_id=<?php echo htmlspecialchars($invoice['order_id']); ?>"><?php echo htmlspecialchars($invoice['order_id']); ?></a></p>
<p><strong>Invoice Date:</strong> <?php echo htmlspecialchars($invoice['invoice_date']); ?></p>
<p><strong>Due Date:</strong> <?php echo htmlspecialchars($invoice['due_date']); ?></p>
<p><strong>Total Amount:</strong> $<?php echo htmlspecialchars(number_format($invoice['total_amount'], 2)); ?></p>
<p><strong>Status:</strong> <?php echo htmlspecialchars(ucfirst($invoice['status'])); ?></p>
</div>
</div>
<div class="card mt-4">
<div class="card-header">Payments</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>Payment Date</th>
<th>Amount</th>
<th>Payment Method</th>
</tr>
</thead>
<tbody>
<?php
$sql = "SELECT * FROM payments WHERE invoice_id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$invoice_id]);
$payments = $stmt->fetchAll();
$total_paid = 0;
foreach ($payments as $payment) {
$total_paid += $payment['amount'];
echo '<tr>';
echo '<td>' . htmlspecialchars($payment['payment_date']) . '</td>';
echo '<td>$' . htmlspecialchars(number_format($payment['amount'], 2)) . '</td>';
echo '<td>' . htmlspecialchars($payment['payment_method']) . '</td>';
echo '</tr>';
}
?>
</tbody>
</table>
<p><strong>Total Paid:</strong> $<?php echo htmlspecialchars(number_format($total_paid, 2)); ?></p>
<p><strong>Amount Due:</strong> $<?php echo htmlspecialchars(number_format($invoice['total_amount'] - $total_paid, 2)); ?></p>
</div>
</div>
<?php if ($invoice['status'] !== 'paid'): ?>
<div class="card mt-4">
<div class="card-header">Post a Payment</div>
<div class="card-body">
<form action="post_payment.php" method="POST">
<input type="hidden" name="invoice_id" value="<?php echo $invoice_id; ?>">
<div class="mb-3">
<label for="amount" class="form-label">Amount</label>
<input type="number" class="form-control" id="amount" name="amount" step="0.01" min="0.01" max="<?php echo $invoice['total_amount'] - $total_paid; ?>" required>
</div>
<div class="mb-3">
<label for="payment_method" class="form-label">Payment Method</label>
<select class="form-select" id="payment_method" name="payment_method" required>
<option value="Credit Card">Credit Card</option>
<option value="Bank Transfer">Bank Transfer</option>
<option value="Cheque">Cheque</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Submit Payment</button>
</form>
</div>
</div>
<?php endif; ?>
<?php require_once 'includes/footer.php'; ?>

80
invoices.php Normal file
View File

@ -0,0 +1,80 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$user_id = $_SESSION['user_id'];
$is_admin = $_SESSION['is_admin'] ?? false;
try {
$pdo = db();
// Base query
$sql = "SELECT i.*, o.id as order_id FROM invoices i JOIN orders o ON i.order_id = o.id";
$params = [];
// If the user is not an admin, they can only see their own invoices
if (!$is_admin) {
$sql .= " WHERE o.user_id = ?";
$params[] = $user_id;
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$invoices = $stmt->fetchAll();
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
?>
<h1 class="mb-4">Invoices</h1>
<table class="table table-striped">
<thead>
<tr>
<th>Invoice ID</th>
<th>Order ID</th>
<th>Invoice Date</th>
<th>Due Date</th>
<th>Total Amount</th>
<th>Paid Amount</th>
<th>Balance</th>
<th>Age of Invoice</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($invoices as $invoice): ?>
<tr>
<td><?php echo htmlspecialchars($invoice['id']); ?></td>
<td><a href="order_details.php?order_id=<?php echo htmlspecialchars($invoice['order_id']); ?>"><?php echo htmlspecialchars($invoice['order_id']); ?></a></td>
<td><?php echo htmlspecialchars($invoice['invoice_date']); ?></td>
<td><?php echo htmlspecialchars($invoice['due_date']); ?></td>
<td>$<?php echo htmlspecialchars(number_format($invoice['total_amount'], 2)); ?></td>
<td>$<?php echo htmlspecialchars(number_format($invoice['paid_amount'], 2)); ?></td>
<td>$<?php
$balance = $invoice['total_amount'] - $invoice['paid_amount'];
echo htmlspecialchars(number_format($balance, 2));
?></td>
<td><?php
$invoice_date = new DateTime($invoice['invoice_date']);
$now = new DateTime();
$age = $now->diff($invoice_date)->days;
echo $age . ' days';
?></td>
<td><?php echo htmlspecialchars(ucfirst($invoice['status'])); ?></td>
<td>
<a href="invoice_details.php?id=<?php echo $invoice['id']; ?>" class="btn btn-primary btn-sm">View Details</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php require_once 'includes/footer.php'; ?>

58
login.php Normal file
View File

@ -0,0 +1,58 @@
<?php
require_once __DIR__ . '/includes/header.php';
require_once __DIR__ . '/db/config.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if (empty($username) || empty($password)) {
$error = 'Username and password are required.';
} else {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password_hash'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['dealer_id'] = $user['dealer_id'];
$_SESSION['is_admin'] = $user['is_admin'];
header('Location: index.php');
exit;
} else {
$error = 'Invalid username or password.';
}
}
}
?>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card mt-5">
<div class="card-body">
<h3 class="card-title text-center">Dealer Login</h3>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form method="POST" action="login.php">
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary btn-block">Login</button>
</form>
</div>
</div>
</div>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

6
logout.php Normal file
View File

@ -0,0 +1,6 @@
<?php
session_start();
session_unset();
session_destroy();
header('Location: login.php');
exit;

46
notifications.php Normal file
View File

@ -0,0 +1,46 @@
<?php
require_once __DIR__ . '/includes/header.php';
require_once __DIR__ . '/db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$user_id = $_SESSION['user_id'];
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['mark_all_read'])) {
$stmt = $pdo->prepare("UPDATE notifications SET is_read = 1 WHERE user_id = ?");
$stmt->execute([$user_id]);
header('Location: notifications.php');
exit;
}
$stmt = $pdo->prepare("SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC");
$stmt->execute([$user_id]);
$notifications = $stmt->fetchAll();
?>
<div class="container">
<h1 class="mt-5">Notifications</h1>
<form method="POST" class="mb-3">
<button type="submit" name="mark_all_read" class="btn btn-primary">Mark all as read</button>
</form>
<ul class="list-group">
<?php foreach ($notifications as $notification): ?>
<li class="list-group-item <?php echo $notification['is_read'] ? '' : 'list-group-item-secondary'; ?>">
<a href="service_request_details.php?id=<?php echo $notification['service_request_id']; ?>" class="text-decoration-none text-dark">
<p class="mb-1"><?php echo htmlspecialchars($notification['message']); ?></p>
<small class="text-muted"><?php echo date('F j, Y, g:i a', strtotime($notification['created_at'])); ?></small>
</a>
</li>
<?php endforeach; ?>
<?php if (empty($notifications)): ?>
<li class="list-group-item">You have no notifications.</li>
<?php endif; ?>
</ul>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

78
order_details.php Normal file
View File

@ -0,0 +1,78 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
if (!isset($_GET['id'])) {
header('Location: orders.php');
exit;
}
$order_id = $_GET['id'];
$pdo = db();
// Fetch order details
$sql = "SELECT * FROM orders WHERE id = ? AND user_id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$order_id, $_SESSION['user_id']]);
$order = $stmt->fetch();
if (!$order) {
header('Location: orders.php');
exit;
}
// Fetch order items
$sql = "
SELECT oi.*, p.name as product_name
FROM order_items oi
JOIN products p ON oi.product_id = p.id
WHERE oi.order_id = ?
";
$stmt = $pdo->prepare($sql);
$stmt->execute([$order_id]);
$order_items = $stmt->fetchAll();
?>
<h1 class="mb-4">Order Details #<?php echo $order['id']; ?></h1>
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">Order Summary</h5>
<p><strong>Total Amount:</strong> $<?php echo number_format($order['total_amount'], 2); ?></p>
<p><strong>Status:</strong> <?php echo htmlspecialchars($order['status']); ?></p>
<p><strong>Date:</strong> <?php echo $order['created_at']; ?></p>
</div>
</div>
<h2 class="mb-4">Items in this Order</h2>
<table class="table">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($order_items as $item): ?>
<tr>
<td><?php echo htmlspecialchars($item['product_name']); ?></td>
<td><?php echo $item['quantity']; ?></td>
<td>$<?php echo number_format($item['price'], 2); ?></td>
<td>$<?php echo number_format($item['price'] * $item['quantity'], 2); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<a href="orders.php" class="btn btn-secondary">Back to Orders</a>
<?php require_once 'includes/footer.php'; ?>

72
orders.php Normal file
View File

@ -0,0 +1,72 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$pdo = db();
$status = isset($_GET['status']) ? $_GET['status'] : 'All';
$statuses = ['All', 'Pending', 'Completed', 'Shipped', 'Delivered'];
if (!in_array($status, $statuses)) {
$status = 'All';
}
$sql = "SELECT * FROM orders WHERE user_id = ?";
$params = [$_SESSION['user_id']];
if ($status !== 'All') {
$sql .= " AND status = ?";
$params[] = $status;
}
$sql .= " ORDER BY created_at DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$orders = $stmt->fetchAll();
?>
<h1 class="mb-4">My Orders</h1>
<ul class="nav nav-tabs mb-3">
<?php foreach ($statuses as $s): ?>
<li class="nav-item">
<a class="nav-link <?php echo ($status === $s) ? 'active' : ''; ?>" href="?status=<?php echo $s; ?>"><?php echo $s; ?></a>
</li>
<?php endforeach; ?>
</ul>
<?php if (empty($orders)): ?>
<div class="alert alert-info">
You have no orders with the status '<?php echo htmlspecialchars($status); ?>'.
</div>
<?php else: ?>
<table class="table">
<thead>
<tr>
<th>Order ID</th>
<th>Total Amount</th>
<th>Status</th>
<th>Date</th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $order): ?>
<tr>
<td>#<?php echo $order['id']; ?></td>
<td>$<?php echo number_format($order['total_amount'], 2); ?></td>
<td><span class="badge bg-primary"><?php echo htmlspecialchars($order['status']); ?></span></td>
<td><?php echo date("F j, Y, g:i a", strtotime($order['created_at'])); ?></td>
<td><a href="order_details.php?id=<?php echo $order['id']; ?>" class="btn btn-sm btn-info">View Details</a></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<?php require_once 'includes/footer.php'; ?>

46
post_payment.php Normal file
View File

@ -0,0 +1,46 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$invoice_id = $_POST['invoice_id'];
$amount = $_POST['amount'];
$payment_method = $_POST['payment_method'];
$payment_date = date('Y-m-d');
try {
$pdo = db();
// Insert payment
$sql = "INSERT INTO payments (invoice_id, payment_date, amount, payment_method) VALUES (?, ?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$invoice_id, $payment_date, $amount, $payment_method]);
// Update invoice status if fully paid
$sql = "SELECT i.total_amount, SUM(p.amount) as total_paid FROM invoices i LEFT JOIN payments p ON i.id = p.invoice_id WHERE i.id = ? GROUP BY i.id";
$stmt = $pdo->prepare($sql);
$stmt->execute([$invoice_id]);
$invoice_data = $stmt->fetch();
if ($invoice_data['total_paid'] >= $invoice_data['total_amount']) {
$sql = "UPDATE invoices SET status = 'paid' WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$invoice_id]);
}
header('Location: invoice_details.php?id=' . $invoice_id);
exit;
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
} else {
header('Location: invoices.php');
exit;
}
?>

122
products.php Normal file
View File

@ -0,0 +1,122 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
try {
$pdo = db();
// Fetch categories for filter dropdown
$category_stmt = $pdo->query("SELECT * FROM product_categories ORDER BY name ASC");
$categories = $category_stmt->fetchAll();
// Get filter parameters
$search = $_GET['search'] ?? '';
$selected_category = $_GET['category'] ?? '';
// Build product query
$sql = "SELECT p.*, c.name AS category_name FROM products p LEFT JOIN product_categories c ON p.category_id = c.id";
$params = [];
$where_clauses = [];
if ($search) {
$where_clauses[] = "(p.name LIKE ? OR p.model_number LIKE ?)";
$params[] = '%' . $search . '%';
$params[] = '%' . $search . '%';
}
if ($selected_category) {
$where_clauses[] = "p.category_id = ?";
$params[] = $selected_category;
}
if (!empty($where_clauses)) {
$sql .= " WHERE " . implode(" AND ", $where_clauses);
}
$sql .= " ORDER BY p.name ASC";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$products = $stmt->fetchAll();
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
?>
<h1 class="mb-4">Product Catalog</h1>
<form method="GET" action="products.php" class="mb-4">
<div class="row g-3">
<div class="col-md-6">
<input type="text" class="form-control" placeholder="Search by product name or model..." name="search" value="<?php echo htmlspecialchars($search); ?>">
</div>
<div class="col-md-4">
<select name="category" class="form-select">
<option value="">All Categories</option>
<?php foreach ($categories as $category): ?>
<option value="<?php echo $category['id']; ?>" <?php if ($selected_category == $category['id']) echo 'selected'; ?>>
<?php echo htmlspecialchars($category['name']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-2">
<button class="btn btn-primary w-100" type="submit">Filter</button>
</div>
</div>
</form>
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
<?php if (empty($products)): ?>
<div class="col">
<p>No products found.</p>
</div>
<?php else: ?>
<?php foreach ($products as $product): ?>
<div class="col">
<div class="card h-100">
<img src="<?php echo htmlspecialchars($product['image_url']); ?>" class="card-img-top" alt="<?php echo htmlspecialchars($product['name']); ?>">
<div class="card-body d-flex flex-column">
<h5 class="card-title"><?php echo htmlspecialchars($product['name']); ?></h5>
<p class="card-text"><strong>Price:</strong> $<?php echo htmlspecialchars(number_format($product['price'], 2)); ?></p>
<h6 class="card-subtitle mb-2 text-muted">Model: <?php echo htmlspecialchars($product['model_number']); ?></h6>
<?php if ($product['category_name']): ?>
<h6 class="card-subtitle mb-2 text-muted">Category: <?php echo htmlspecialchars($product['category_name']); ?></h6>
<?php endif; ?>
<p class="card-text"><?php echo htmlspecialchars($product['description']); ?></p>
<?php if ($product['features']): ?>
<p class="card-text"><small><strong>Features:</strong> <?php echo htmlspecialchars($product['features']); ?></small></p>
<?php endif; ?>
<?php if ($product['sample_type']): ?>
<p class="card-text"><small><strong>Sample Type:</strong> <?php echo htmlspecialchars($product['sample_type']); ?></small></p>
<?php endif; ?>
<?php if ($product['measurement_parameters']): ?>
<p class="card-text"><small><strong>Parameters:</strong> <?php echo htmlspecialchars($product['measurement_parameters']); ?></small></p>
<?php endif; ?>
<?php if ($product['result_speed']): ?>
<p class="card-text"><small><strong>Result Speed:</strong> <?php echo htmlspecialchars($product['result_speed']); ?></small></p>
<?php endif; ?>
<div class="mt-auto">
<form action="cart.php?action=add" method="post">
<input type="hidden" name="product_id" value="<?php echo $product['id']; ?>">
<div class="input-group mb-3">
<input type="number" name="quantity" id="quantity-<?php echo $product['id']; ?>" class="form-control" value="1" min="1">
<button type="submit" class="btn btn-primary">Add to Cart</button>
</div>
</form>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<?php require_once 'includes/footer.php'; ?>

95
profile.php Normal file
View File

@ -0,0 +1,95 @@
<?php
require_once __DIR__ . '/includes/header.php';
require_once __DIR__ . '/db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$user_id = $_SESSION['user_id'];
$pdo = db();
$error = '';
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$current_password = $_POST['current_password'] ?? '';
$new_password = $_POST['new_password'] ?? '';
$confirm_password = $_POST['confirm_password'] ?? '';
if (empty($current_password) || empty($new_password) || empty($confirm_password)) {
$error = 'All password fields are required.';
} elseif ($new_password !== $confirm_password) {
$error = 'New password and confirm password do not match.';
} else {
$stmt = $pdo->prepare("SELECT password_hash FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
if ($user && password_verify($current_password, $user['password_hash'])) {
$password_hash = password_hash($new_password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("UPDATE users SET password_hash = ? WHERE id = ?");
if ($stmt->execute([$password_hash, $user_id])) {
$success = 'Password updated successfully.';
} else {
$error = 'Failed to update password.';
}
} else {
$error = 'Incorrect current password.';
}
}
}
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
?>
<div class="container">
<h1 class="mt-5">Profile</h1>
<div class="card">
<div class="card-body">
<h5 class="card-title">Your Information</h5>
<p><strong>Username:</strong> <?php echo htmlspecialchars($user['username']); ?></p>
<?php if (!$user['is_admin']): ?>
<?php
$stmt_dealer = $pdo->prepare("SELECT * FROM dealers WHERE id = ?");
$stmt_dealer->execute([$user['dealer_id']]);
$dealer = $stmt_dealer->fetch();
?>
<p><strong>Dealer:</strong> <?php echo htmlspecialchars($dealer['name']); ?></p>
<p><strong>Email:</strong> <?php echo htmlspecialchars($dealer['email']); ?></p>
<?php endif; ?>
</div>
</div>
<div class="card mt-4">
<div class="card-body">
<h5 class="card-title">Change Password</h5>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?php echo $success; ?></div>
<?php endif; ?>
<form method="POST" action="profile.php">
<div class="form-group">
<label for="current_password">Current Password</label>
<input type="password" class="form-control" id="current_password" name="current_password" required>
</div>
<div class="form-group">
<label for="new_password">New Password</label>
<input type="password" class="form-control" id="new_password" name="new_password" required>
</div>
<div class="form-group">
<label for="confirm_password">Confirm New Password</label>
<input type="password" class="form-control" id="confirm_password" name="confirm_password" required>
</div>
<button type="submit" class="btn btn-primary">Change Password</button>
</form>
</div>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

249
service_request_details.php Normal file
View File

@ -0,0 +1,249 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
header('Location: service_requests.php');
exit;
}
$request_id = $_GET['id'];
$dealer_id = $_SESSION['dealer_id'];
try {
$pdo = db();
$stmt = $pdo->prepare(
"SELECT sr.*
FROM service_requests sr
WHERE sr.id = ? AND (sr.dealer_id = ? OR ?)"
);
$stmt->execute([$request_id, $dealer_id, $_SESSION['is_admin']]);
$request = $stmt->fetch();
if (!$request) {
// Request not found or doesn't belong to the dealer
header('Location: service_requests.php');
exit;
}
// Fetch service request items
$stmt_items = $pdo->prepare(
"SELECT sri.serial_number, sri.issue_description, p.name as product_name
FROM service_request_items sri
JOIN products p ON sri.product_id = p.id
WHERE sri.service_request_id = ?"
);
$stmt_items->execute([$request_id]);
$request_items = $stmt_items->fetchAll();
// Handle comment submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['comment'])) {
$comment = trim($_POST['comment']);
if (!empty($comment)) {
$stmt_insert_comment = $pdo->prepare(
"INSERT INTO service_request_comments (service_request_id, user_id, comment) VALUES (?, ?, ?)"
);
$stmt_insert_comment->execute([$request_id, $_SESSION['user_id'], $comment]);
// Create a notification
$current_user_id = $_SESSION['user_id'];
$request_owner_id = $request['user_id'];
$message = "A new comment has been added to your service request #{$request_id}.";
if ($current_user_id != $request_owner_id) {
// Notify the request owner
$stmt_notify = $pdo->prepare("INSERT INTO notifications (user_id, service_request_id, message) VALUES (?, ?, ?)");
$stmt_notify->execute([$request_owner_id, $request_id, $message]);
} else {
// Notify all admins
$stmt_admins = $pdo->query("SELECT id FROM users WHERE is_admin = 1");
$admins = $stmt_admins->fetchAll(PDO::FETCH_COLUMN);
$stmt_notify = $pdo->prepare("INSERT INTO notifications (user_id, service_request_id, message) VALUES (?, ?, ?)");
foreach ($admins as $admin_id) {
if($admin_id != $current_user_id) {
$stmt_notify->execute([$admin_id, $request_id, $message]);
}
}
}
// Redirect to the same page to prevent form resubmission
header("Location: service_request_details.php?id=$request_id");
exit;
}
}
// Fetch comments for the service request
$stmt_comments = $pdo->prepare(
"SELECT c.*, u.username
FROM service_request_comments c
JOIN users u ON c.user_id = u.id
WHERE c.service_request_id = ?
ORDER BY c.created_at ASC"
);
$stmt_comments->execute([$request_id]);
$comments = $stmt_comments->fetchAll();
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
?>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="service_requests.php">Service Requests</a></li>
<li class="breadcrumb-item active" aria-current="page">Request #<?php echo htmlspecialchars($request['id']); ?></li>
</ol>
</nav>
<h1 class="mb-4">Service Request Details</h1>
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Request #<?php echo htmlspecialchars($request['id']); ?></h5>
<span class="badge bg-warning text-dark"><?php echo htmlspecialchars(ucfirst($request['status'])); ?></span>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<p><strong>Submitted At:</strong> <?php echo date('F j, Y, g:i a', strtotime($request['created_at'])); ?></p>
<p><strong>Last Updated:</strong> <?php echo date('F j, Y, g:i a', strtotime($request['updated_at'])); ?></p>
</div>
</div>
<hr>
<h5>Products</h5>
<table class="table table-bordered">
<thead>
<tr>
<th>Product Name</th>
<th>Serial Number</th>
<th>Issue Description</th>
</tr>
</thead>
<tbody>
<?php foreach ($request_items as $item): ?>
<tr>
<td><?php echo htmlspecialchars($item['product_name']); ?></td>
<td><?php echo htmlspecialchars($item['serial_number']); ?></td>
<td><?php echo nl2br(htmlspecialchars($item['issue_description'])); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php if (!empty($request['file_path'])) : ?>
<hr>
<h5>Attached File</h5>
<p><a href="<?php echo htmlspecialchars($request['file_path']); ?>" target="_blank">View Attached File</a></p>
<?php endif; ?>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] || !empty($_SESSION['dealer_id'])) : ?>
<hr>
<h5>Update Status</h5>
<form action="update_service_request_status.php" method="POST">
<input type="hidden" name="request_id" value="<?php echo $request_id; ?>">
<div class="input-group">
<select name="status" class="form-select">
<option value="pending" <?php if ($request['status'] == 'pending') echo 'selected'; ?>>Pending</option>
<option value="in_progress" <?php if ($request['status'] == 'in_progress') echo 'selected'; ?>>In Progress</option>
<option value="resolved" <?php if ($request['status'] == 'resolved') echo 'selected'; ?>>Resolved</option>
<option value="closed" <?php if ($request['status'] == 'closed') echo 'selected'; ?>>Closed</option>
</select>
<button type="submit" class="btn btn-primary">Update</button>
</div>
</form>
<?php endif; ?>
</div>
</div>
<div class="card mt-4">
<div class="card-header">
<h5 class="mb-0">Shipment Details</h5>
</div>
<div class="card-body">
<?php
$stmt_shipment = $pdo->prepare("SELECT * FROM shipment_details WHERE service_request_id = ?");
$stmt_shipment->execute([$request_id]);
$shipments = $stmt_shipment->fetchAll();
?>
<?php if (empty($shipments)): ?>
<p>No shipment details available.</p>
<?php if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin'] && empty($_SESSION['dealer_id'])) : ?>
<p class="text-muted">Only administrators and dealers can add shipment details.</p>
<?php endif; ?>
<?php else: ?>
<table class="table">
<thead>
<tr>
<th>Carrier</th>
<th>Tracking Number</th>
<th>Shipment Date</th>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] || !empty($_SESSION['dealer_id'])) : ?>
<th>Actions</th>
<?php endif; ?>
</tr>
</thead>
<tbody>
<?php foreach ($shipments as $shipment): ?>
<tr>
<td><?php echo htmlspecialchars($shipment['carrier']); ?></td>
<td><?php echo htmlspecialchars($shipment['tracking_number']); ?></td>
<td><?php echo htmlspecialchars($shipment['shipment_date']); ?></td>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] || !empty($_SESSION['dealer_id'])) : ?>
<td>
<a href="edit_shipment_details.php?id=<?php echo $shipment['id']; ?>" class="btn btn-sm btn-primary">Edit</a>
<a href="delete_shipment_details.php?id=<?php echo $shipment['id']; ?>" class="btn btn-sm btn-danger" onclick="return confirm('Are you sure you want to delete this shipment?')">Delete</a>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<div class="d-flex justify-content-end">
<?php if ((isset($_SESSION['is_admin']) && $_SESSION['is_admin']) || !empty($_SESSION['dealer_id'])) : ?>
<a href="add_shipment_details.php?request_id=<?php echo $request_id; ?>" class="btn btn-primary">Add Shipment</a>
<?php endif; ?>
</div>
</div>
</div>
<div class="card mt-4">
<div class="card-header">
<h5 class="mb-0">Comments</h5>
</div>
<div class="card-body">
<?php foreach ($comments as $comment): ?>
<div class="d-flex mb-3">
<div class="flex-shrink-0">
<i class="bi bi-person-circle fs-3"></i>
</div>
<div class="ms-3">
<div class="fw-bold"><?php echo htmlspecialchars($comment['username']); ?></div>
<?php echo nl2br(htmlspecialchars($comment['comment'])); ?>
<div class="text-muted fs-sm"><?php echo date('F j, Y, g:i a', strtotime($comment['created_at'])); ?></div>
</div>
</div>
<?php endforeach; ?>
<?php if (empty($comments)): ?>
<p>No comments yet.</p>
<?php endif; ?>
</div>
<div class="card-footer">
<form method="POST" action="service_request_details.php?id=<?php echo $request_id; ?>">
<div class="input-group">
<textarea class="form-control" name="comment" placeholder="Add a comment..." rows="3" required></textarea>
<button class="btn btn-primary" type="submit">Post Comment</button>
</div>
</form>
</div>
</div>
<?php require_once 'includes/footer.php'; ?>

227
service_requests.php Normal file
View File

@ -0,0 +1,227 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$dealer_id = $_SESSION['dealer_id'];
$success_message = '';
$error_message = '';
try {
$pdo = db();
// Fetch products for the dropdown
$stmt_products = $pdo->query("SELECT id, name, model_number FROM products ORDER BY name ASC");
$products = $stmt_products->fetchAll();
// Handle form submission
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$submitted_products = $_POST['products'] ?? [];
$file_path = null;
if (isset($_FILES['file_upload']) && $_FILES['file_upload']['error'] == UPLOAD_ERR_OK) {
$upload_dir = __DIR__ . '/uploads/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$file_name = uniqid('file_') . '_' . basename($_FILES['file_upload']['name']);
$target_file = $upload_dir . $file_name;
if (move_uploaded_file($_FILES['file_upload']['tmp_name'], $target_file)) {
$file_path = 'uploads/' . $file_name;
} else {
$error_message = "Sorry, there was an error uploading your file.";
}
}
if (empty($submitted_products)) {
$error_message = "Please add at least one product and provide an issue description.";
} else {
try {
$pdo->beginTransaction();
// Create the main service request
$sql_request = "INSERT INTO service_requests (dealer_id, user_id, file_path) VALUES (?, ?, ?)";
$stmt_request = $pdo->prepare($sql_request);
$stmt_request->execute([$dealer_id, $_SESSION['user_id'], $file_path]);
$service_request_id = $pdo->lastInsertId();
// Add each product to the service_request_items table
$sql_item = "INSERT INTO service_request_items (service_request_id, product_id, serial_number, issue_description) VALUES (?, ?, ?, ?)";
$stmt_item = $pdo->prepare($sql_item);
foreach ($submitted_products as $product_data) {
$product_id = trim($product_data['product_id']);
$serial_number = trim($product_data['serial_number']);
$issue_description = trim($product_data['issue_description']);
if (!empty($product_id) && !empty($serial_number) && !empty($issue_description)) {
$stmt_item->execute([$service_request_id, $product_id, $serial_number, $issue_description]);
}
}
$pdo->commit();
$success_message = "Service request submitted successfully!";
} catch (PDOException $e) {
$pdo->rollBack();
$error_message = "Failed to submit service request: " . $e->getMessage();
}
}
}
// Fetch existing service requests for the dealer
$stmt_requests = $pdo->prepare(
"SELECT sr.id, sr.status, sr.created_at,
GROUP_CONCAT(p.name SEPARATOR ', ') as product_names,
GROUP_CONCAT(sri.serial_number SEPARATOR ', ') as serial_numbers
FROM service_requests sr
LEFT JOIN service_request_items sri ON sr.id = sri.service_request_id
LEFT JOIN products p ON sri.product_id = p.id
WHERE sr.dealer_id = ?
GROUP BY sr.id
ORDER BY sr.created_at DESC"
);
$stmt_requests->execute([$dealer_id]);
$service_requests = $stmt_requests->fetchAll();
} catch (PDOException $e) {
$error_message = "Database error: " . $e->getMessage();
}
?>
<div class="row">
<div class="col-md-5">
<div class="card">
<div class="card-header">
<h1 class="h3 mb-0">Submit a Service Request</h1>
</div>
<div class="card-body">
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo $success_message; ?></div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="alert alert-danger"><?php echo $error_message; ?></div>
<?php endif; ?>
<form action="service_requests.php" method="POST" enctype="multipart/form-data">
<div id="product-entries">
<div class="product-entry mb-3 border p-3">
<div class="row">
<div class="col-md-6">
<label for="product_id_1" class="form-label">Product</label>
<select class="form-select" id="product_id_1" name="products[1][product_id]" required>
<option value="">-- Select a Product --</option>
<?php foreach ($products as $product): ?>
<option value="<?php echo htmlspecialchars($product['id']); ?>">
<?php echo htmlspecialchars($product['name'] . ' (' . $product['model_number'] . ')'); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label for="serial_number_1" class="form-label">Serial Number</label>
<input type="text" class="form-control" id="serial_number_1" name="products[1][serial_number]" required>
</div>
</div>
<div class="mt-2">
<label for="issue_description_1" class="form-label">Issue Description</label>
<textarea class="form-control" id="issue_description_1" name="products[1][issue_description]" rows="2" required></textarea>
</div>
</div>
</div>
<button type="button" class="btn btn-secondary mb-3" id="add-product-btn">Add Another Product</button>
<div class="mb-3">
<label for="file_upload" class="form-label">Attach a File (optional)</label>
<input type="file" class="form-control" id="file_upload" name="file_upload">
</div>
<button type="submit" class="btn btn-primary"><i class="bi bi-send"></i> Submit Request</button>
</form>
</div>
</div>
</div>
<div class="col-md-7">
<div class="card">
<div class="card-header">
<h1 class="h3 mb-0">Your Service Requests</h1>
</div>
<div class="card-body">
<?php if (empty($service_requests)): ?>
<p>You have not submitted any service requests yet.</p>
<?php else: ?>
<table class="table table-striped">
<thead>
<tr>
<th>Request ID</th>
<th>Products</th>
<th>Serials</th>
<th>Status</th>
<th>Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($service_requests as $request): ?>
<tr>
<td><?php echo htmlspecialchars($request['id']); ?></td>
<td><?php echo htmlspecialchars($request['product_names']); ?></td>
<td><?php echo htmlspecialchars($request['serial_numbers']); ?></td>
<td><span class="badge bg-warning text-dark"><?php echo htmlspecialchars(ucfirst($request['status'])); ?></span></td>
<td><?php echo date('M j, Y', strtotime($request['created_at'])); ?></td>
<td>
<a href="service_request_details.php?id=<?php echo $request['id']; ?>" class="btn btn-primary btn-sm">View Details</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
let productEntryCount = 1;
const addProductBtn = document.getElementById('add-product-btn');
const productEntries = document.getElementById('product-entries');
const productOptions = `<?php foreach ($products as $product) { echo '<option value="' . htmlspecialchars($product['id']) . '">' . htmlspecialchars($product['name'] . ' (' . $product['model_number'] . ')') . '</option>'; } ?>`;
addProductBtn.addEventListener('click', function() {
productEntryCount++;
const newEntry = document.createElement('div');
newEntry.classList.add('product-entry', 'mb-3', 'border', 'p-3');
newEntry.innerHTML = `
<div class="row">
<div class="col-md-6">
<label for="product_id_${productEntryCount}" class="form-label">Product</label>
<select class="form-select" id="product_id_${productEntryCount}" name="products[${productEntryCount}][product_id]" required>
<option value="">-- Select a Product --</option>
${productOptions}
</select>
</div>
<div class="col-md-6">
<label for="serial_number_${productEntryCount}" class="form-label">Serial Number</label>
<input type="text" class="form-control" id="serial_number_${productEntryCount}" name="products[${productEntryCount}][serial_number]" required>
</div>
</div>
<div class="mt-2">
<label for="issue_description_${productEntryCount}" class="form-label">Issue Description</label>
<textarea class="form-control" id="issue_description_${productEntryCount}" name="products[${productEntryCount}][issue_description]" rows="2" required></textarea>
</div>
`;
productEntries.appendChild(newEntry);
});
});
</script>
<?php
require_once 'includes/footer.php';
?>

74
targets.php Normal file
View File

@ -0,0 +1,74 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
require_once 'db/config.php';
include_once 'includes/header.php';
$dealer_id = $_SESSION['dealer_id'] ?? 0;
if (!$dealer_id) {
echo "<div class='alert alert-danger'>No dealer ID found in session.</div>";
include_once 'includes/footer.php';
exit();
}
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM dealers WHERE id = ?");
$stmt->execute([$dealer_id]);
$dealer = $stmt->fetch();
if (!$dealer) {
echo "<div class='alert alert-danger'>Dealer not found.</div>";
include_once 'includes/footer.php';
exit();
}
$target = $dealer['target'] ?? 0;
$achievement = $dealer['achievement'] ?? 0;
$credit_limit = $dealer['credit_limit'] ?? 0;
$credit_limit_utilisation = $dealer['credit_limit_utilisation'] ?? 0;
$achievement_percentage = $target > 0 ? ($achievement / $target) * 100 : 0;
$credit_utilisation_percentage = $credit_limit > 0 ? ($credit_limit_utilisation / $credit_limit) * 100 : 0;
?>
<div class="container">
<h1 class="mt-5">Targets and Achievements</h1>
<div class="card mt-4">
<div class="card-body">
<h5 class="card-title">Targets</h5>
<p class="card-text">Your sales target for the current quarter is: <strong>$<?php echo number_format($target, 2); ?></strong></p>
</div>
</div>
<div class="card mt-4">
<div class="card-body">
<h5 class="card-title">Achievements</h5>
<p class="card-text">Your sales so far this quarter: <strong>$<?php echo number_format($achievement, 2); ?></strong></p>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: <?php echo $achievement_percentage; ?>%;" aria-valuenow="<?php echo $achievement_percentage; ?>" aria-valuemin="0" aria-valuemax="100"><?php echo round($achievement_percentage); ?>%</div>
</div>
</div>
</div>
<div class="card mt-4">
<div class="card-body">
<h5 class="card-title">Credit Limit</h5>
<p class="card-text">Your credit limit is: <strong>$<?php echo number_format($credit_limit, 2); ?></strong></p>
</div>
</div>
<div class="card mt-4">
<div class="card-body">
<h5 class="card-title">Credit Limit Utilisation</h5>
<p class="card-text">You have used: <strong>$<?php echo number_format($credit_limit_utilisation, 2); ?></strong></p>
<div class="progress">
<div class="progress-bar bg-warning" role="progressbar" style="width: <?php echo $credit_utilisation_percentage; ?>%;" aria-valuenow="<?php echo $credit_utilisation_percentage; ?>" aria-valuemin="0" aria-valuemax="100"><?php echo round($credit_utilisation_percentage); ?>%</div>
</div>
</div>
</div>
</div>
<?php include_once 'includes/footer.php'; ?>

View File

@ -0,0 +1,30 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id']) || !$_SESSION['is_admin']) {
header('Location: login.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$request_id = $_POST['request_id'];
$status = $_POST['status'];
try {
$pdo = db();
$sql = "UPDATE service_requests SET status = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$status, $request_id]);
header('Location: service_request_details.php?id=' . $request_id);
exit;
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
} else {
header('Location: service_requests.php');
exit;
}
?>

226
warranty_registration.php Normal file
View File

@ -0,0 +1,226 @@
<?php
require_once 'includes/header.php';
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$dealer_id = $_SESSION['dealer_id'];
try {
$pdo = db();
// Fetch unactivated serial numbers for the dealer
$stmt = $pdo->prepare(
"SELECT ss.id, ss.serial_number, p.name as product_name
FROM sold_serials ss
JOIN products p ON ss.product_id = p.id
WHERE ss.dealer_id = ? AND ss.is_activated = FALSE"
);
$stmt->execute([$dealer_id]);
$unactivated_serials = $stmt->fetchAll();
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}
$success_message = '';
$error_message = '';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$sold_serial_id = trim($_POST['sold_serial_id']);
$end_customer_name = trim($_POST['end_customer_name']);
$end_customer_address = trim($_POST['end_customer_address']);
$dealer_invoice_date = trim($_POST['dealer_invoice_date']);
$dealer_invoice_no = trim($_POST['dealer_invoice_no']);
$installation_date = trim($_POST['installation_date']);
if (empty($sold_serial_id) || empty($end_customer_name) || empty($end_customer_address) || empty($dealer_invoice_date) || empty($dealer_invoice_no) || empty($installation_date)) {
$error_message = "All fields are required.";
} else {
$target_dir = "uploads/invoices/";
if (!is_dir($target_dir)) {
mkdir($target_dir, 0777, true);
}
$target_file = $target_dir . basename($_FILES["dealer_invoice"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if file already exists
if (file_exists($target_file)) {
$error_message = "Sorry, file already exists.";
$uploadOk = 0;
}
// Check file size
if ($_FILES["dealer_invoice"]["size"] > 500000) {
$error_message = "Sorry, your file is too large.";
$uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" && $imageFileType != "pdf" ) {
$error_message = "Sorry, only JPG, JPEG, PNG, GIF & PDF files are allowed.";
$uploadOk = 0;
}
if ($uploadOk == 0) {
$error_message = "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
} else {
if (move_uploaded_file($_FILES["dealer_invoice"]["tmp_name"], $target_file)) {
try {
$pdo = db();
$pdo->beginTransaction();
// 1. Insert warranty registration
$sql = "INSERT INTO warranty_registrations (sold_serial_id, end_customer_name, end_customer_address, dealer_invoice_date, dealer_invoice_no, dealer_invoice_path, installation_date, serial_number)
SELECT ?, ?, ?, ?, ?, ?, ?, serial_number FROM sold_serials WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$sold_serial_id, $end_customer_name, $end_customer_address, $dealer_invoice_date, $dealer_invoice_no, $target_file, $installation_date, $sold_serial_id]);
// 2. Mark serial as activated
$sql_update = "UPDATE sold_serials SET is_activated = TRUE WHERE id = ?";
$stmt_update = $pdo->prepare($sql_update);
$stmt_update->execute([$sold_serial_id]);
$pdo->commit();
// Fetch serial number for display message
$stmt_sn = $pdo->prepare("SELECT serial_number FROM sold_serials WHERE id = ?");
$stmt_sn->execute([$sold_serial_id]);
$serial_number = $stmt_sn->fetchColumn();
$success_message = "Warranty for serial number <strong>" . htmlspecialchars($serial_number) . "</strong> registered successfully!";
} catch (PDOException $e) {
$pdo->rollBack();
$error_message = "Database error: " . $e->getMessage();
}
} else {
$error_message = "Sorry, there was an error uploading your file.";
}
}
}
}
require_once 'includes/header.php';
?>
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h1 class="h3 mb-0">Device Warranty Registration</h1>
</div>
<div class="card-body">
<p class="card-text">Register a device installation to activate the warranty. Please select a device serial number, enter the end customer's name, and the installation date.</p>
<?php if ($success_message): ?>
<div class="alert alert-success" role="alert">
<?php echo $success_message; ?>
<script>
// Refresh the page after 3 seconds to update the dropdown
setTimeout(() => window.location.href = 'warranty_registration.php', 3000);
</script>
</div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="alert alert-danger" role="alert">
<?php echo $error_message; ?>
</div>
<?php endif; ?>
<form action="warranty_registration.php" method="POST" enctype="multipart/form-data">
<div class="mb-3">
<label for="sold_serial_id" class="form-label">Device Serial Number</label>
<select class="form-select" id="sold_serial_id" name="sold_serial_id" required>
<option value="">-- Select a Serial Number --</option>
<?php foreach ($unactivated_serials as $serial): ?>
<option value="<?php echo htmlspecialchars($serial['id']); ?>">
<?php echo htmlspecialchars($serial['serial_number'] . ' (' . $serial['product_name'] . ')'); ?>
</option>
<?php endforeach; ?>
</select>
<?php if (empty($unactivated_serials)): ?>
<div class="form-text">No devices are pending warranty activation.</div>
<?php endif; ?>
</div>
<div id="product-details" class="mb-3" style="display: none;">
<div class="card">
<div class="card-header">
<h5>Product Details</h5>
</div>
<div class="card-body">
<p><strong>Name:</strong> <span id="product-name"></span></p>
<p><strong>Model Number:</strong> <span id="product-model"></span></p>
<p><strong>Part Number:</strong> <span id="product-part"></span></p>
<p><strong>Description:</strong> <span id="product-description"></span></p>
<img id="product-image" src="" alt="Product Image" class="img-fluid" style="max-height: 200px;"/>
</div>
</div>
</div>
<div class="mb-3">
<label for="end_customer_name" class="form-label">End Customer's Name (Hospital/Lab)</label>
<input type="text" class="form-control" id="end_customer_name" name="end_customer_name" required>
</div>
<div class="mb-3">
<label for="end_customer_address" class="form-label">End Customer's Address</label>
<textarea class="form-control" id="end_customer_address" name="end_customer_address" rows="3" required></textarea>
</div>
<div class="mb-3">
<label for="dealer_invoice_date" class="form-label">Dealer Invoice Date</label>
<input type="date" class="form-control" id="dealer_invoice_date" name="dealer_invoice_date" required>
</div>
<div class="mb-3">
<label for="dealer_invoice_no" class="form-label">Dealer Invoice No</label>
<input type="text" class="form-control" id="dealer_invoice_no" name="dealer_invoice_no" required>
</div>
<div class="mb-3">
<label for="dealer_invoice" class="form-label">Dealer Invoice</label>
<input class="form-control" type="file" id="dealer_invoice" name="dealer_invoice" required>
</div>
<div class="mb-3">
<label for="installation_date" class="form-label">Installation Date</label>
<input type="date" class="form-control" id="installation_date" name="installation_date" required>
</div>
<button type="submit" class="btn btn-primary" <?php echo empty($unactivated_serials) ? 'disabled' : ''; ?>><i class="bi bi-check-circle"></i> Register Warranty</button>
</form>
</div>
</div>
</div>
</div>
<script>
document.getElementById('sold_serial_id').addEventListener('change', function() {
var soldSerialId = this.value;
if (soldSerialId) {
fetch('api/get_product_details.php?sold_serial_id=' + soldSerialId)
.then(response => response.json())
.then(data => {
if (data.error) {
alert(data.error);
} else {
document.getElementById('product-details').style.display = 'block';
document.getElementById('product-name').textContent = data.name;
document.getElementById('product-model').textContent = data.model_number;
document.getElementById('product-part').textContent = data.part_number;
document.getElementById('product-description').textContent = data.description;
document.getElementById('product-image').src = data.image_url;
}
})
.catch(error => console.error('Error:', error));
} else {
document.getElementById('product-details').style.display = 'none';
}
});
</script>
<?php
require_once 'includes/footer.php';
?>