300 lines
16 KiB
PHP
300 lines
16 KiB
PHP
<?php
|
|
require_once 'auth.php';
|
|
require_once '../db/config.php';
|
|
require_login();
|
|
|
|
$pdo = db();
|
|
$msg = '';
|
|
|
|
// Handle Delete
|
|
if (isset($_GET['delete'])) {
|
|
$id = (int)$_GET['delete'];
|
|
$pdo->prepare("DELETE FROM cases WHERE id = ?")->execute([$id]);
|
|
header('Location: cases.php?success=deleted');
|
|
exit;
|
|
}
|
|
|
|
// Fetch cases
|
|
$cases = $pdo->query("SELECT c.*, cat.name_en as cat_name FROM cases c LEFT JOIN categories cat ON c.category_id = cat.id ORDER BY c.id DESC")->fetchAll();
|
|
$categories = $pdo->query("SELECT * FROM categories")->fetchAll();
|
|
|
|
// Handle Add/Edit
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$id = $_POST['id'] ?? null;
|
|
$category_id = $_POST['category_id'];
|
|
$title_en = $_POST['title_en'];
|
|
$title_ar = $_POST['title_ar'];
|
|
$desc_en = $_POST['desc_en'];
|
|
$desc_ar = $_POST['desc_ar'];
|
|
$goal = $_POST['goal'];
|
|
$importance = $_POST['importance'] ?? 'normal';
|
|
$status = $_POST['status'] ?? 'active';
|
|
$image_url = $_POST['image_url_existing'] ?? '';
|
|
|
|
// Handle File Upload
|
|
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
|
|
$ext = strtolower(pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION));
|
|
$allowed = ['jpg', 'jpeg', 'png', 'webp', 'gif'];
|
|
if (in_array($ext, $allowed)) {
|
|
$filename = uniqid('case_') . '.' . $ext;
|
|
$upload_dir = '../assets/images/cases/';
|
|
if (!is_dir($upload_dir)) mkdir($upload_dir, 0775, true);
|
|
|
|
if (move_uploaded_file($_FILES['image']['tmp_name'], $upload_dir . $filename)) {
|
|
$image_url = 'assets/images/cases/' . $filename;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($id) {
|
|
$stmt = $pdo->prepare("UPDATE cases SET category_id=?, title_en=?, title_ar=?, desc_en=?, desc_ar=?, goal=?, image_url=?, importance=?, status=? WHERE id=?");
|
|
$stmt->execute([$category_id, $title_en, $title_ar, $desc_en, $desc_ar, $goal, $image_url, $importance, $status, $id]);
|
|
} else {
|
|
$stmt = $pdo->prepare("INSERT INTO cases (category_id, title_en, title_ar, desc_en, desc_ar, goal, raised, image_url, importance, status) VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, ?)");
|
|
$stmt->execute([$category_id, $title_en, $title_ar, $desc_en, $desc_ar, $goal, $image_url, $importance, $status]);
|
|
}
|
|
header('Location: cases.php?success=saved');
|
|
exit;
|
|
}
|
|
|
|
$edit_case = null;
|
|
if (isset($_GET['edit'])) {
|
|
$id = (int)$_GET['edit'];
|
|
$stmt = $pdo->prepare("SELECT * FROM cases WHERE id = ?");
|
|
$stmt->execute([$id]);
|
|
$edit_case = $stmt->fetch();
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Manage Cases - CharityHub Admin</title>
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
|
<style>
|
|
:root { --sidebar-width: 260px; --primary-color: #059669; }
|
|
body { background-color: #f3f4f6; }
|
|
.sidebar { width: var(--sidebar-width); height: 100vh; position: fixed; left: 0; top: 0; background: #111827; color: #fff; padding: 1.5rem; }
|
|
.main-content { margin-left: var(--sidebar-width); padding: 2rem; }
|
|
.nav-link { color: #9ca3af; margin-bottom: 0.5rem; border-radius: 8px; }
|
|
.nav-link:hover, .nav-link.active { color: #fff; background: #1f2937; }
|
|
.nav-link.active { background: var(--primary-color); }
|
|
.card { border: none; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
|
|
.badge-urgent { background-color: #ef4444; }
|
|
.badge-top_priority { background-color: #8b5cf6; }
|
|
.badge-normal { background-color: #6b7280; }
|
|
.case-img-preview { width: 50px; height: 50px; object-fit: cover; border-radius: 6px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<?php include "sidebar.php"; ?>
|
|
|
|
<div class="main-content">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h2>Manage Donation Cases</h2>
|
|
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#caseModal" onclick="clearForm()">
|
|
<i class="bi bi-plus-lg me-1"></i> New Case
|
|
</button>
|
|
</div>
|
|
|
|
<?php if (isset($_GET['success'])): ?>
|
|
<div class="alert alert-success alert-dismissible fade show">
|
|
Operation successful!
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th class="ps-4">Case</th>
|
|
<th>Category</th>
|
|
<th>Goal</th>
|
|
<th>Status</th>
|
|
<th>Importance</th>
|
|
<th class="text-end pe-4">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($cases as $case): ?>
|
|
<tr>
|
|
<td class="ps-4">
|
|
<div class="d-flex align-items-center">
|
|
<?php if ($case['image_url']): ?>
|
|
<img src="../<?= htmlspecialchars($case['image_url']) ?>" class="case-img-preview me-3" alt="">
|
|
<?php else: ?>
|
|
<div class="case-img-preview me-3 bg-secondary d-flex align-items-center justify-content-center text-white">
|
|
<i class="bi bi-image"></i>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div>
|
|
<div><strong><?= htmlspecialchars($case['title_en']) ?></strong></div>
|
|
<small class="text-muted"><?= htmlspecialchars($case['title_ar']) ?></small>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td><?= htmlspecialchars($case['cat_name'] ?? 'N/A') ?></td>
|
|
<td>
|
|
<div>OMR <?= number_format($case['goal'], 3) ?></div>
|
|
<small class="text-muted">Raised: OMR <?= number_format($case['raised'], 3) ?></small>
|
|
</td>
|
|
<td>
|
|
<?php if ($case['status'] === 'active'): ?>
|
|
<span class="badge bg-success">Active</span>
|
|
<?php elseif ($case['status'] === 'paused'): ?>
|
|
<span class="badge bg-warning text-dark">Paused</span>
|
|
<?php else: ?>
|
|
<span class="badge bg-danger">Disabled</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<span class="badge badge-<?= $case['importance'] ?>">
|
|
<?= ucfirst(str_replace('_', ' ', $case['importance'])) ?>
|
|
</span>
|
|
</td>
|
|
<td class="text-end pe-4">
|
|
<a href="?edit=<?= $case['id'] ?>" class="btn btn-sm btn-outline-primary me-1"><i class="bi bi-pencil"></i></a>
|
|
<a href="?delete=<?= $case['id'] ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Are you sure?')"><i class="bi bi-trash"></i></a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Case Modal -->
|
|
<div class="modal fade" id="caseModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<form method="POST" enctype="multipart/form-data">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="modalTitle">New Case</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<input type="hidden" name="id" id="caseId">
|
|
<input type="hidden" name="image_url_existing" id="caseImageUrlExisting">
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Category</label>
|
|
<select name="category_id" id="caseCategory" class="form-select" required>
|
|
<option value="">Select Category</option>
|
|
<?php foreach ($categories as $cat): ?>
|
|
<option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['name_en']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Title (English)</label>
|
|
<input type="text" name="title_en" id="caseTitleEn" class="form-control" required>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Title (Arabic)</label>
|
|
<input type="text" name="title_ar" id="caseTitleAr" class="form-control" dir="rtl" required>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Description (English)</label>
|
|
<textarea name="desc_en" id="caseDescEn" class="form-control" rows="3"></textarea>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Description (Arabic)</label>
|
|
<textarea name="desc_ar" id="caseDescAr" class="form-control" dir="rtl" rows="3"></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-4 mb-3">
|
|
<label class="form-label">Goal Amount (OMR)</label>
|
|
<input type="number" name="goal" id="caseGoal" class="form-control" step="0.001" required>
|
|
</div>
|
|
<div class="col-md-4 mb-3">
|
|
<label class="form-label">Importance</label>
|
|
<select name="importance" id="caseImportance" class="form-select">
|
|
<option value="normal">Normal</option>
|
|
<option value="urgent">Urgent</option>
|
|
<option value="top_priority">Top Priority</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-4 mb-3">
|
|
<label class="form-label">Status</label>
|
|
<select name="status" id="caseStatus" class="form-select">
|
|
<option value="active">Active</option>
|
|
<option value="paused">Paused</option>
|
|
<option value="disabled">Disabled</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Case Image</label>
|
|
<input type="file" name="image" class="form-control" accept="image/*">
|
|
<div id="imagePreviewContainer" class="mt-2" style="display:none;">
|
|
<small class="text-muted d-block mb-1">Current Image:</small>
|
|
<img id="imagePreview" src="" class="rounded border" style="max-height: 100px;">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-primary">Save Case</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
const caseModal = new bootstrap.Modal(document.getElementById('caseModal'));
|
|
|
|
function clearForm() {
|
|
document.getElementById('caseId').value = '';
|
|
document.getElementById('caseCategory').value = '';
|
|
document.getElementById('caseTitleEn').value = '';
|
|
document.getElementById('caseTitleAr').value = '';
|
|
document.getElementById('caseDescEn').value = '';
|
|
document.getElementById('caseDescAr').value = '';
|
|
document.getElementById('caseGoal').value = '';
|
|
document.getElementById('caseImportance').value = 'normal';
|
|
document.getElementById('caseStatus').value = 'active';
|
|
document.getElementById('caseImageUrlExisting').value = '';
|
|
document.getElementById('imagePreviewContainer').style.display = 'none';
|
|
document.getElementById('modalTitle').innerText = 'New Case';
|
|
}
|
|
|
|
<?php if ($edit_case): ?>
|
|
window.addEventListener('load', () => {
|
|
document.getElementById('caseId').value = '<?= $edit_case['id'] ?>';
|
|
document.getElementById('caseCategory').value = '<?= $edit_case['category_id'] ?>';
|
|
document.getElementById('caseTitleEn').value = '<?= addslashes($edit_case['title_en']) ?>';
|
|
document.getElementById('caseTitleAr').value = '<?= addslashes($edit_case['title_ar']) ?>';
|
|
document.getElementById('caseDescEn').value = '<?= addslashes($edit_case['desc_en'] ?? '') ?>';
|
|
document.getElementById('caseDescAr').value = '<?= addslashes($edit_case['desc_ar'] ?? '') ?>';
|
|
document.getElementById('caseGoal').value = '<?= $edit_case['goal'] ?>';
|
|
document.getElementById('caseImportance').value = '<?= $edit_case['importance'] ?>';
|
|
document.getElementById('caseStatus').value = '<?= $edit_case['status'] ?>';
|
|
document.getElementById('caseImageUrlExisting').value = '<?= $edit_case['image_url'] ?>';
|
|
|
|
if ('<?= $edit_case['image_url'] ?>') {
|
|
document.getElementById('imagePreview').src = '../<?= $edit_case['image_url'] ?>';
|
|
document.getElementById('imagePreviewContainer').style.display = 'block';
|
|
}
|
|
|
|
document.getElementById('modalTitle').innerText = 'Edit Case';
|
|
caseModal.show();
|
|
});
|
|
<?php endif; ?>
|
|
</script>
|
|
</body>
|
|
</html>
|