311 lines
16 KiB
PHP
311 lines
16 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../db/config.php';
|
|
require_once __DIR__ . '/../includes/functions.php';
|
|
|
|
$pdo = db();
|
|
require_permission('all');
|
|
|
|
$id = $_GET['id'] ?? null;
|
|
$user = null;
|
|
|
|
if ($id) {
|
|
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
|
$stmt->execute([$id]);
|
|
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
if (!$user) {
|
|
header('Location: users.php');
|
|
exit;
|
|
}
|
|
} else {
|
|
// Default values for new user
|
|
$user = [
|
|
'id' => null,
|
|
'username' => '',
|
|
'full_name' => '',
|
|
'email' => '',
|
|
'group_id' => '',
|
|
'employee_id' => '',
|
|
'is_active' => 1,
|
|
'is_ratable' => 0,
|
|
'profile_pic' => '',
|
|
'created_at' => date('Y-m-d H:i:s')
|
|
];
|
|
}
|
|
|
|
$message = '';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$full_name = $_POST['full_name'];
|
|
$username = $_POST['username'];
|
|
$email = $_POST['email'];
|
|
$group_id = $_POST['group_id'];
|
|
$employee_id = $_POST['employee_id'] ?? null;
|
|
$is_active = isset($_POST['is_active']) ? 1 : 0;
|
|
$is_ratable = isset($_POST['is_ratable']) ? 1 : 0;
|
|
$assigned_outlets = $_POST['outlets'] ?? [];
|
|
$password = $_POST['password'] ?? '';
|
|
|
|
// Validation
|
|
if (!$id && empty($password)) {
|
|
$message = '<div class="alert alert-danger">Password is required for new users.</div>';
|
|
} else {
|
|
// Check if username already exists
|
|
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ? AND id != ?");
|
|
$stmt->execute([$username, (int)$id]);
|
|
if ($stmt->fetch()) {
|
|
$message = '<div class="alert alert-danger">Username already taken.</div>';
|
|
}
|
|
}
|
|
|
|
if (!$message) {
|
|
$pdo->beginTransaction();
|
|
try {
|
|
if ($id) {
|
|
// Update
|
|
$sql = "UPDATE users SET full_name = ?, username = ?, email = ?, group_id = ?, is_active = ?, is_ratable = ?, employee_id = ? WHERE id = ?";
|
|
$params = [$full_name, $username, $email, $group_id, $is_active, $is_ratable, $employee_id, $id];
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
|
|
if (!empty($password)) {
|
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
|
$pdo->prepare("UPDATE users SET password = ? WHERE id = ?")->execute([$hashed_password, $id]);
|
|
}
|
|
$user_id = $id;
|
|
} else {
|
|
// Insert
|
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
|
$sql = "INSERT INTO users (full_name, username, email, group_id, is_active, is_ratable, employee_id, password) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
|
$params = [$full_name, $username, $email, $group_id, $is_active, $is_ratable, $employee_id, $hashed_password];
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
$user_id = $pdo->lastInsertId();
|
|
}
|
|
|
|
// Update assigned outlets
|
|
$pdo->prepare("DELETE FROM user_outlets WHERE user_id = ?")->execute([$user_id]);
|
|
if (!empty($assigned_outlets)) {
|
|
$stmt_outlet = $pdo->prepare("INSERT INTO user_outlets (user_id, outlet_id) VALUES (?, ?)");
|
|
foreach ($assigned_outlets as $outlet_id) {
|
|
$stmt_outlet->execute([$user_id, $outlet_id]);
|
|
}
|
|
}
|
|
|
|
// Handle Profile Picture Upload
|
|
if (isset($_FILES['profile_pic']) && $_FILES['profile_pic']['error'] === UPLOAD_ERR_OK) {
|
|
$upload_dir = __DIR__ . '/../assets/images/users/';
|
|
if (!is_dir($upload_dir)) {
|
|
mkdir($upload_dir, 0775, true);
|
|
}
|
|
|
|
$file_tmp = $_FILES['profile_pic']['tmp_name'];
|
|
$file_name = $_FILES['profile_pic']['name'];
|
|
$file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
|
|
$allowed_exts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
|
|
|
if (in_array($file_ext, $allowed_exts)) {
|
|
$new_file_name = 'user_' . $user_id . '_' . uniqid() . '.' . $file_ext;
|
|
$upload_path = $upload_dir . $new_file_name;
|
|
|
|
if (move_uploaded_file($file_tmp, $upload_path)) {
|
|
// Delete old profile pic if exists
|
|
if ($user['profile_pic'] && file_exists(__DIR__ . '/../' . $user['profile_pic'])) {
|
|
unlink(__DIR__ . '/../' . $user['profile_pic']);
|
|
}
|
|
|
|
$profile_pic_path = 'assets/images/users/' . $new_file_name;
|
|
$pdo->prepare("UPDATE users SET profile_pic = ? WHERE id = ?")->execute([$profile_pic_path, $user_id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
$pdo->commit();
|
|
|
|
if ($id) {
|
|
$message = '<div class="alert alert-success">User updated successfully!</div>';
|
|
} else {
|
|
header("Location: user_edit.php?id=$user_id&success=1");
|
|
exit;
|
|
}
|
|
|
|
// Refresh user data
|
|
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
|
$stmt->execute([$user_id]);
|
|
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
} catch (Exception $e) {
|
|
$pdo->rollBack();
|
|
$message = '<div class="alert alert-danger">Error saving user: ' . $e->getMessage() . '</div>';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['success'])) {
|
|
$message = '<div class="alert alert-success">User created successfully!</div>';
|
|
}
|
|
|
|
$groups = $pdo->query("SELECT * FROM user_groups ORDER BY name")->fetchAll();
|
|
$all_outlets = $pdo->query("SELECT * FROM outlets ORDER BY name")->fetchAll();
|
|
$assigned_outlet_ids = [];
|
|
if ($id) {
|
|
$user_outlets = $pdo->prepare("SELECT outlet_id FROM user_outlets WHERE user_id = ?");
|
|
$user_outlets->execute([$id]);
|
|
$assigned_outlet_ids = $user_outlets->fetchAll(PDO::FETCH_COLUMN);
|
|
}
|
|
|
|
include 'includes/header.php';
|
|
?>
|
|
|
|
<div class="mb-4">
|
|
<a href="users.php" class="text-decoration-none text-muted small"><i class="bi bi-arrow-left"></i> Back to Users</a>
|
|
<div class="d-flex align-items-center mt-2">
|
|
<h2 class="fw-bold mb-0"><?= $id ? 'Edit' : 'Add' ?> User<?= $user['username'] ? ': ' . htmlspecialchars($user['username']) : '' ?></h2>
|
|
</div>
|
|
</div>
|
|
|
|
<?= $message ?>
|
|
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<div class="card border-0 shadow-sm rounded-4 mb-4">
|
|
<div class="card-body p-4">
|
|
<form method="POST" enctype="multipart/form-data">
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<label class="form-label small fw-bold text-muted">FULL NAME</label>
|
|
<input type="text" name="full_name" class="form-control" value="<?= htmlspecialchars($user['full_name']) ?>" required>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label small fw-bold text-muted">USERNAME</label>
|
|
<input type="text" name="username" class="form-control" value="<?= htmlspecialchars($user['username']) ?>" required>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<label class="form-label small fw-bold text-muted">EMAIL</label>
|
|
<input type="email" name="email" class="form-control" value="<?= htmlspecialchars($user['email']) ?>" required>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label small fw-bold text-muted">EMPLOYEE / BIOMETRIC ID</label>
|
|
<input type="text" name="employee_id" class="form-control mb-3" value="<?= htmlspecialchars($user['employee_id'] ?? '') ?>" placeholder="e.g. 101">
|
|
<label class="form-label small fw-bold text-muted">USER GROUP / ROLE</label>
|
|
<select name="group_id" class="form-select" required>
|
|
<option value="">Select Group</option>
|
|
<?php foreach ($groups as $group): ?>
|
|
<option value="<?= $group['id'] ?>" <?= $user['group_id'] == $group['id'] ? 'selected' : '' ?>><?= htmlspecialchars($group['name']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-4">
|
|
<div class="col-md-12">
|
|
<label class="form-label small fw-bold text-muted">PROFILE PICTURE</label>
|
|
<div class="d-flex align-items-center gap-3">
|
|
<?php if ($user['profile_pic']): ?>
|
|
<img src="../<?= htmlspecialchars($user['profile_pic']) ?>?v=<?= time() ?>" alt="Profile Picture" class="rounded-circle shadow-sm" style="width: 80px; height: 80px; object-fit: cover;">
|
|
<?php else: ?>
|
|
<div class="bg-primary bg-gradient text-white rounded-circle d-flex align-items-center justify-content-center shadow-sm" style="width: 80px; height: 80px; font-weight: 700; font-size: 1.5rem;">
|
|
<?= strtoupper(substr($user['full_name'] ?: $user['username'] ?: 'U', 0, 1)) ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div class="flex-grow-1">
|
|
<input type="file" name="profile_pic" class="form-control" accept="image/*">
|
|
<div class="form-text mt-1">Allowed: JPG, PNG, GIF, WebP. Recommended: Square image.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label class="form-label small fw-bold text-muted"><?= $id ? 'NEW PASSWORD (LEAVE BLANK TO KEEP CURRENT)' : 'PASSWORD' ?></label>
|
|
<input type="password" name="password" class="form-control" placeholder="<?= $id ? '******' : 'Enter password' ?>" <?= $id ? '' : 'required' ?>>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label class="form-label small fw-bold text-muted d-block mb-2">ASSIGNED OUTLETS</label>
|
|
<div class="row">
|
|
<?php foreach ($all_outlets as $outlet): ?>
|
|
<div class="col-md-4 mb-2">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="outlets[]" value="<?= $outlet['id'] ?>" id="outlet_<?= $outlet['id'] ?>" <?= in_array($outlet['id'], $assigned_outlet_ids) ? 'checked' : '' ?>>
|
|
<label class="form-check-label small" for="outlet_<?= $outlet['id'] ?>">
|
|
<?= htmlspecialchars($outlet['name']) ?>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<div class="form-text mt-1">Assign one or more outlets to this user.</div>
|
|
</div>
|
|
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" name="is_active" id="isActiveSwitch" <?= $user['is_active'] ? 'checked' : '' ?>>
|
|
<label class="form-check-label fw-bold text-muted small" for="isActiveSwitch">ACTIVE ACCOUNT</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" name="is_ratable" id="isRatableSwitch" <?= $user['is_ratable'] ? 'checked' : '' ?>>
|
|
<label class="form-check-label fw-bold text-muted small" for="isRatableSwitch">DISPLAY IN STAFF RATINGS</label>
|
|
</div>
|
|
<div class="form-text small mt-1">Enable this to allow customers to rate this staff member in the public rating page.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="my-4">
|
|
|
|
<div class="d-flex justify-content-end gap-2">
|
|
<a href="users.php" class="btn btn-light rounded-pill px-4">Cancel</a>
|
|
<button type="submit" class="btn btn-primary rounded-pill px-4 fw-bold"><?= $id ? 'Update' : 'Create' ?> User</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<div class="card border-0 shadow-sm rounded-4 bg-primary bg-gradient text-white shadow">
|
|
<div class="card-body p-4">
|
|
<h5 class="fw-bold mb-3">User Info</h5>
|
|
<div class="d-flex align-items-center mb-3">
|
|
<?php if ($user['profile_pic']): ?>
|
|
<img src="../<?= htmlspecialchars($user['profile_pic']) ?>?v=<?= time() ?>" alt="Profile Picture" class="rounded-circle shadow-sm border border-2 border-white me-3" style="width: 60px; height: 60px; object-fit: cover;">
|
|
<?php else: ?>
|
|
<div class="bg-white text-primary rounded-circle d-flex align-items-center justify-content-center me-3" style="width:60px;height:60px; font-weight:700; font-size:1.5rem;">
|
|
<?= strtoupper(substr($user['full_name'] ?: $user['username'] ?: 'U', 0, 1)) ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div>
|
|
<div class="fw-bold"><?= htmlspecialchars($user['full_name'] ?: 'New User') ?></div>
|
|
<div class="small opacity-75">Member since <?= date('M Y', strtotime($user['created_at'])) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="small">
|
|
<div class="mb-1"><i class="bi bi-envelope me-2"></i> <?= htmlspecialchars($user['email'] ?: 'Email not set') ?></div>
|
|
<div><i class="bi bi-person-badge me-2"></i> User ID: <?= $id ? '#' . $id : '<i>New</i>' ?></div>
|
|
</div>
|
|
|
|
<hr class="opacity-25 my-3">
|
|
<div class="small">
|
|
<div class="fw-bold mb-2">Assigned Outlets:</div>
|
|
<?php if (empty($assigned_outlet_ids)): ?>
|
|
<div class="opacity-75">No outlets assigned.</div>
|
|
<?php else: ?>
|
|
<ul class="list-unstyled mb-0 opacity-75">
|
|
<?php foreach ($all_outlets as $outlet): ?>
|
|
<?php if (in_array($outlet['id'], $assigned_outlet_ids)): ?>
|
|
<li><i class="bi bi-geo-alt me-1"></i> <?= htmlspecialchars($outlet['name']) ?></li>
|
|
<?php endif; ?>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php include 'includes/footer.php'; ?>
|