add calander

This commit is contained in:
Flatlogic Bot 2026-04-13 14:24:18 +00:00
parent 2c097e9eb5
commit 9f7d3b9c16
69 changed files with 1392 additions and 796 deletions

View File

@ -97,13 +97,13 @@ $ledger = get_ledger_paginated($search, $date_from, $date_to, $limit, $offset);
<div class="card-body py-2">
<form method="GET" class="row g-2 align-items-center">
<div class="col-md-5">
<input type="text" name="search" class="form-control form-control-sm" placeholder="بحث..." value="<?= htmlspecialchars($search) ?>">
<input type="text" name="search" class="form-control form-control-sm" placeholder="بحث..." value="<?= htmlspecialchars($search ?? '') ?>">
</div>
<div class="col-md-2">
<input type="date" name="date_from" class="form-control form-control-sm" value="<?= htmlspecialchars($date_from) ?>">
<input type="date" name="date_from" class="form-control form-control-sm" value="<?= htmlspecialchars($date_from ?? '') ?>">
</div>
<div class="col-md-2">
<input type="date" name="date_to" class="form-control form-control-sm" value="<?= htmlspecialchars($date_to) ?>">
<input type="date" name="date_to" class="form-control form-control-sm" value="<?= htmlspecialchars($date_to ?? '') ?>">
</div>
<div class="col-md-3 text-end">
<button type="submit" class="btn btn-sm btn-secondary"><i class="fas fa-filter"></i> تصفية</button>
@ -144,7 +144,7 @@ $ledger = get_ledger_paginated($search, $date_from, $date_to, $limit, $offset);
<select name="debit_account" class="form-select accountSelect" required style="width: 100%;">
<option value="" disabled selected>اختر الحساب...</option>
<?php foreach (get_all_accounts() as $acc): ?>
<option value="<?= htmlspecialchars($acc['name']) ?>"><?= htmlspecialchars($acc['name']) ?></option>
<option value="<?= htmlspecialchars($acc['name'] ?? '') ?>"><?= htmlspecialchars($acc['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -153,7 +153,7 @@ $ledger = get_ledger_paginated($search, $date_from, $date_to, $limit, $offset);
<select name="credit_account" class="form-select accountSelect" required style="width: 100%;">
<option value="" disabled selected>اختر الحساب...</option>
<?php foreach (get_all_accounts() as $acc): ?>
<option value="<?= htmlspecialchars($acc['name']) ?>"><?= htmlspecialchars($acc['name']) ?></option>
<option value="<?= htmlspecialchars($acc['name'] ?? '') ?>"><?= htmlspecialchars($acc['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -204,7 +204,7 @@ $ledger = get_ledger_paginated($search, $date_from, $date_to, $limit, $offset);
<select name="debit_account" id="edit_debit_account" class="form-select accountSelectEdit" required style="width: 100%;">
<option value="" disabled>اختر الحساب...</option>
<?php foreach (get_all_accounts() as $acc): ?>
<option value="<?= htmlspecialchars($acc['name']) ?>"><?= htmlspecialchars($acc['name']) ?></option>
<option value="<?= htmlspecialchars($acc['name'] ?? '') ?>"><?= htmlspecialchars($acc['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -213,7 +213,7 @@ $ledger = get_ledger_paginated($search, $date_from, $date_to, $limit, $offset);
<select name="credit_account" id="edit_credit_account" class="form-select accountSelectEdit" required style="width: 100%;">
<option value="" disabled>اختر الحساب...</option>
<?php foreach (get_all_accounts() as $acc): ?>
<option value="<?= htmlspecialchars($acc['name']) ?>"><?= htmlspecialchars($acc['name']) ?></option>
<option value="<?= htmlspecialchars($acc['name'] ?? '') ?>"><?= htmlspecialchars($acc['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -246,20 +246,20 @@ $ledger = get_ledger_paginated($search, $date_from, $date_to, $limit, $offset);
<?php endif; ?>
<?php foreach ($ledger as $row): ?>
<tr>
<td><?= htmlspecialchars($row['date']) ?></td>
<td><?= htmlspecialchars($row['description']) ?></td>
<td><?= htmlspecialchars($row['reference']) ?></td>
<td><?= htmlspecialchars($row['account_name']) ?></td>
<td><?= htmlspecialchars($row['date'] ?? '') ?></td>
<td><?= htmlspecialchars($row['description'] ?? '') ?></td>
<td><?= htmlspecialchars($row['reference'] ?? '') ?></td>
<td><?= htmlspecialchars($row['account_name'] ?? '') ?></td>
<td><?= number_format($row['debit'], 2) ?></td>
<td><?= number_format($row['credit'], 2) ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['created_by'] ?? $row['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['updated_by'] ?? null)) ?></small></td>
<td>
<button type="button" class="btn btn-sm btn-link text-warning p-0 me-2" title="تعديل" onclick="openEditModal(<?= $row['id'] ?>)"><i class="fas fa-edit"></i></button>
<form method="POST" class="d-inline delete-form">
<input type="hidden" name="delete_entry" value="1">
<input type="hidden" name="delete_id" value="<?= htmlspecialchars($row['id']) ?>">
<input type="hidden" name="delete_id" value="<?= htmlspecialchars($row['id'] ?? '') ?>">
<button type="button" class="btn btn-sm btn-link text-danger p-0 delete-btn" title="حذف">
<i class="fas fa-trash"></i>
</button>

View File

@ -1,196 +0,0 @@
<?php
require_once 'db/config.php';
require_once 'includes/header.php';
require_once 'includes/accounting_functions.php';
// Check permission
$user_id = $_SESSION['user_id'];
$stmt = db()->prepare("SELECT * FROM user_permissions WHERE user_id = ? AND page = 'accounting' AND can_view = 1");
$stmt->execute([$user_id]);
if (!$stmt->fetch()) {
echo "<div class='container mt-4' dir='rtl'>لا تملك صلاحية الوصول لهذه الصفحة.</div>";
require_once 'includes/footer.php';
exit;
}
// Handle form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_entry'])) {
$date = $_POST["date"] ?? "";
$description = $_POST["description"] ?? "";
$reference = $_POST["reference"] ?? "";
$entries = [
["account" => $_POST["debit_account"] ?? "", "debit" => (float)($_POST["amount"] ?? 0), "credit" => 0],
["account" => $_POST["credit_account"] ?? "", "debit" => 0, "credit" => (float)($_POST["amount"] ?? 0)]
];
if (add_journal_entry($date, $description, $reference, $entries)) {
$message = "تم إضافة القيد بنجاح.";
} else {
$error = "حدث خطأ أثناء إضافة القيد.";
}
}
// Pagination and Filtering setup
$page = isset($_GET['p']) ? (int)$_GET['p'] : 1;
$limit = 10;
$offset = ($page - 1) * $limit;
$search = $_GET['search'] ?? '';
$date_from = $_GET['date_from'] ?? '';
$date_to = $_GET['date_to'] ?? '';
// Fetch ledger data with filters
$ledger_all = get_full_ledger_filtered($search, $date_from, $date_to);
$total_items = count($ledger_all);
$total_pages = ceil($total_items / $limit);
$ledger = array_slice($ledger_all, $offset, $limit);
?>
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.table td, .table th { padding: 0.3rem 0.5rem; }
.action-icon { cursor: pointer; text-decoration: none; }
.action-icon:hover { opacity: 0.7; }
</style>
<div class="container mt-4" dir="rtl">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="text-right">المحاسبة (Accounting)</h2>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#journalModal">
<i class="fas fa-plus"></i> إضافة قيد جديد
</button>
</div>
<?php if (isset($message)) echo "<div class='alert alert-success'>$message</div>"; ?>
<?php if (isset($error)) echo "<div class='alert alert-danger'>$error</div>"; ?>
<!-- Filter Form -->
<div class="card mb-4 shadow-sm">
<div class="card-body py-2">
<form method="GET" class="row g-2 align-items-center">
<div class="col-md-5">
<input type="text" name="search" class="form-control form-control-sm" placeholder="بحث..." value="<?= htmlspecialchars($search) ?>">
</div>
<div class="col-md-2">
<input type="date" name="date_from" class="form-control form-control-sm" value="<?= htmlspecialchars($date_from) ?>">
</div>
<div class="col-md-2">
<input type="date" name="date_to" class="form-control form-control-sm" value="<?= htmlspecialchars($date_to) ?>">
</div>
<div class="col-md-3 text-end">
<button type="submit" class="btn btn-sm btn-secondary"><i class="fas fa-filter"></i> تصفية</button>
<a href="accounting.php" class="btn btn-sm btn-outline-secondary"><i class="fas fa-sync"></i></a>
</div>
</form>
</div>
</div>
<!-- Journal Modal -->
<div class="modal fade" id="journalModal" tabindex="-1" aria-labelledby="journalModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form method="POST">
<div class="modal-header">
<h5 class="modal-title" id="journalModalLabel">إضافة قيد محاسبي</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input type="hidden" name="add_entry" value="1">
<div class="row">
<div class="col-md-6 mb-3">
<label>التاريخ</label>
<input type="date" name="date" class="form-control" required value="<?= date('Y-m-d') ?>">
</div>
<div class="col-md-6 mb-3">
<label>المرجع</label>
<input type="text" name="reference" class="form-control">
</div>
</div>
<div class="mb-3">
<label>الوصف</label>
<input type="text" name="description" class="form-control" required>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label>حساب المدين</label>
<select name="debit_account" class="form-select accountSelect" required style="width: 100%;">
<?php foreach (get_all_accounts() as $acc): ?>
<option value="<?= htmlspecialchars($acc['name']) ?>"><?= htmlspecialchars($acc['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label>حساب الدائن</label>
<select name="credit_account" class="form-select accountSelect" required style="width: 100%;">
<?php foreach (get_all_accounts() as $acc): ?>
<option value="<?= htmlspecialchars($acc['name']) ?>"><?= htmlspecialchars($acc['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label>المبلغ</label>
<input type="number" step="0.01" name="amount" class="form-control" required min="0.01">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إغلاق</button>
<button type="submit" class="btn btn-primary">حفظ القيد</button>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3 class="text-right">دفتر الأستاذ (General Ledger)</h3>
<div class="table-responsive">
<table class="table table-hover table-bordered text-right align-middle table-sm">
<thead class="table-light"><tr><th>التاريخ</th><th>الوصف</th><th>المرجع</th><th>الحساب</th><th>مدين</th><th>دائن</th><th>الإجراءات</th></tr></thead>
<tbody>
<?php foreach ($ledger as $row): ?>
<tr>
<td><?= htmlspecialchars($row['date']) ?></td>
<td><?= htmlspecialchars($row['description']) ?></td>
<td><?= htmlspecialchars($row['reference']) ?></td>
<td><?= htmlspecialchars($row['account_name']) ?></td>
<td><?= number_format($row['debit'], 2) ?></td>
<td><?= number_format($row['credit'], 2) ?></td>
<td>
<a href="#" class="action-icon text-warning me-2" title="تعديل" onclick="alert('تعديل القيد <?= $row['id'] ?>')"><i class="fas fa-edit"></i></a>
<a href="#" class="action-icon text-danger" title="حذف" onclick="if(confirm('هل أنت متأكد؟')) alert('حذف القيد <?= $row['id'] ?>')"><i class="fas fa-trash"></i></a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<nav>
<ul class="pagination pagination-sm justify-content-center">
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
<li class="page-item <?= $i == $page ? 'active' : '' ?>">
<a class="page-link" href="?p=<?= $i ?>&search=<?= urlencode($search) ?>&date_from=<?= urlencode($date_from) ?>&date_to=<?= urlencode($date_to) ?>"><?= $i ?></a>
</li>
<?php endfor; ?>
</ul>
</nav>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script>
$(document).ready(function() {
$('.accountSelect').select2({
theme: 'bootstrap-5',
dir: 'rtl',
dropdownParent: $('#journalModal')
});
});
</script>
<?php require_once 'includes/footer.php'; ?>

View File

@ -1,2 +0,0 @@
<span class="my-custom-action text-warning me-2" title="تعديل" onclick='alert("تعديل القيد " + <?= json_encode($row["id"]) ?>)'><i class="fas fa-edit"></i></span>
<span class="my-custom-action text-danger" title="حذف" onclick='if(confirm("هل أنت متأكد؟")) alert("حذف القيد " + <?= json_encode($row["id"]) ?>)'><i class="fas fa-trash"></i></span>

View File

@ -137,13 +137,13 @@ $typeMap = [
<tbody>
<?php foreach ($accounts as $account): ?>
<tr>
<td><?= htmlspecialchars($account['name']) ?></td>
<td><?= htmlspecialchars($account['name'] ?? '') ?></td>
<td>
<span class="badge badge-info px-2 py-1" style="color: black;">
<?= htmlspecialchars($typeMap[$account['type']] ?? $account['type']) ?>
</span>
</td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($account['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($account['created_by'] ?? $account['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($account['updated_by'] ?? null)) ?></small></td>
<td class="text-center">
<button class="btn btn-warning text-white btn-sm shadow-sm mx-1" onclick="editAccount(<?= $account['id'] ?>, '<?= htmlspecialchars($account['name'], ENT_QUOTES) ?>', '<?= htmlspecialchars($account['type'], ENT_QUOTES) ?>')" title="تعديل">
@ -190,7 +190,7 @@ document.addEventListener('DOMContentLoaded', function() {
Swal.fire({
icon: 'success',
title: 'نجاح!',
text: '<?= htmlspecialchars($message) ?>',
text: '<?= htmlspecialchars($message ?? '') ?>',
confirmButtonText: 'حسناً',
confirmButtonColor: '#28a745',
timer: 3000,

333
admin_dashboard.php Normal file
View File

@ -0,0 +1,333 @@
<?php
require_once __DIR__ . '/includes/header.php';
// Role-based routing: Admins stay here, others go to their dashboard
if (!isAdmin()) {
redirect('user_dashboard.php');
}
$user_id = $_SESSION['user_id'];
$is_admin = isAdmin();
// Stats - Total counts from separate tables
$total_inbound = canView('inbound') ? db()->query("SELECT COUNT(*) FROM inbound_mail")->fetchColumn() : 0;
$total_outbound = canView('outbound') ? db()->query("SELECT COUNT(*) FROM outbound_mail")->fetchColumn() : 0;
// Fetch statuses for badge and count
$statuses_data = db()->query("SELECT * FROM mailbox_statuses")->fetchAll(PDO::FETCH_UNIQUE);
$in_progress_id = null;
foreach ($statuses_data as $id => $s) {
if ($s['name'] == 'in_progress') {
$in_progress_id = $id;
break;
}
}
$in_progress_count = 0;
if ($in_progress_id) {
if (canView('inbound')) {
$stmt = db()->prepare("SELECT COUNT(*) FROM inbound_mail WHERE status_id = ?");
$stmt->execute([$in_progress_id]);
$in_progress_count += $stmt->fetchColumn();
}
if (canView('outbound')) {
$stmt = db()->prepare("SELECT COUNT(*) FROM outbound_mail WHERE status_id = ?");
$stmt->execute([$in_progress_id]);
$in_progress_count += $stmt->fetchColumn();
}
}
// My Assignments - Combine from all tables
$my_assignments = [];
$queries = [];
if (canView('inbound')) {
$queries[] = "SELECT id, 'inbound' as type, ref_no, subject, due_date, status_id, created_at FROM inbound_mail WHERE assigned_to = $user_id";
}
if (canView('outbound')) {
$queries[] = "SELECT id, 'outbound' as type, ref_no, subject, due_date, status_id, created_at FROM outbound_mail WHERE assigned_to = $user_id";
}
if (canView('internal')) {
$queries[] = "SELECT id, 'internal' as type, ref_no, subject, due_date, status_id, created_at FROM internal_mail WHERE assigned_to = $user_id";
}
if (!empty($queries)) {
$full_query = "(" . implode(") UNION ALL (", $queries) . ") ORDER BY created_at DESC LIMIT 5";
$stmt = db()->query($full_query);
$my_assignments = $stmt->fetchAll();
// Add status info to assignments
foreach ($my_assignments as &$m) {
$m['status_name'] = $statuses_data[$m['status_id']]['name'] ?? 'unknown';
$m['status_color'] = $statuses_data[$m['status_id']]['color'] ?? '#6c757d';
}
}
// Recent Mail (Global for Admin/Clerk, otherwise limited)
$recent_mail = [];
$recent_queries = [];
if (canView('inbound')) {
$recent_queries[] = "SELECT m.id, 'inbound' as type, m.ref_no, m.subject, m.due_date, m.sender, m.recipient, m.status_id, m.assigned_to, m.created_by, m.date_registered, m.created_at, u.full_name as assigned_to_name
FROM inbound_mail m LEFT JOIN users u ON m.assigned_to = u.id";
}
if (canView('outbound')) {
$recent_queries[] = "SELECT m.id, 'outbound' as type, m.ref_no, m.subject, m.due_date, m.sender, m.recipient, m.status_id, m.assigned_to, m.created_by, m.date_registered, m.created_at, u.full_name as assigned_to_name
FROM outbound_mail m LEFT JOIN users u ON m.assigned_to = u.id";
}
if (!empty($recent_queries)) {
$full_recent_query = "(" . implode(") UNION ALL (", $recent_queries) . ")";
if (!$is_admin && ($_SESSION['user_role'] ?? '') !== 'clerk') {
$full_recent_query = "SELECT * FROM ($full_recent_query) AS combined WHERE assigned_to = $user_id OR created_by = $user_id ORDER BY created_at DESC LIMIT 10";
} else {
$full_recent_query = "SELECT * FROM ($full_recent_query) AS combined ORDER BY created_at DESC LIMIT 10";
}
$stmt = db()->query($full_recent_query);
$recent_mail = $stmt->fetchAll();
// Add status info
foreach ($recent_mail as &$m) {
$m['status_name'] = $statuses_data[$m['status_id']]['name'] ?? 'unknown';
$m['status_color'] = $statuses_data[$m['status_id']]['color'] ?? '#6c757d';
}
}
function getStatusBadge($mail) {
$status_name = $mail['status_name'] ?? 'غير معروف';
$status_color = $mail['status_color'] ?? '#6c757d';
$display_name = $status_name;
if ($status_name == 'received') $display_name = 'تم الاستلام';
if ($status_name == 'in_progress') $display_name = 'قيد المعالجة';
if ($status_name == 'closed') $display_name = 'مكتمل';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name ?? '') . '</span>';
}
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">لوحة التحكم الإدارية</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group me-2">
<?php if (canView('settings')): ?>
<a href="charity-settings.php" class="btn btn-sm btn-outline-dark"><i class="fas fa-cog me-1"></i> الإعدادات</a>
<?php endif; ?>
<?php if (canAdd('inbound')): ?>
<a href="inbound.php?action=add" class="btn btn-sm btn-outline-primary">إضافة بريد وارد</a>
<?php endif; ?>
<?php if (canAdd('outbound')): ?>
<a href="outbound.php?action=add" class="btn btn-sm btn-outline-secondary">إضافة بريد صادر</a>
<?php endif; ?>
</div>
</div>
</div>
<!-- Overdue Alert -->
<?php
if (canView('reports')):
// Combine overdue counts from inbound and outbound
$overdue_count = 0;
$overdue_count += db()->query("SELECT COUNT(*) FROM inbound_mail WHERE due_date < CURDATE() AND status_id IN (SELECT id FROM mailbox_statuses WHERE name != 'closed')")->fetchColumn();
$overdue_count += db()->query("SELECT COUNT(*) FROM outbound_mail WHERE due_date < CURDATE() AND status_id IN (SELECT id FROM mailbox_statuses WHERE name != 'closed')")->fetchColumn();
if ($overdue_count > 0):
?>
<div class="row mb-4">
<div class="col-12">
<div class="alert alert-danger shadow-sm border-0 d-flex align-items-center justify-content-between mb-0">
<div>
<i class="fas fa-exclamation-triangle fs-4 me-3"></i>
<span class="fw-bold">هناك <?= $overdue_count ?> مهام متأخرة تتطلب انتباهك!</span>
</div>
<a href="overdue_report.php" class="btn btn-danger btn-sm">عرض التقرير</a>
</div>
</div>
</div>
<?php
endif;
endif;
?>
<!-- Stats Cards -->
<div class="row g-4 mb-4">
<?php if (canView('inbound')): ?>
<div class="col-md-3">
<div class="card h-100 p-3 shadow-sm border-0 border-start border-primary border-4">
<div class="d-flex align-items-center justify-content-between">
<div>
<h6 class="text-muted mb-1">البريد الوارد</h6>
<h3 class="fw-bold mb-0"><?= $total_inbound ?></h3>
</div>
<div class="bg-primary bg-opacity-10 p-3 rounded-circle">
<i class="fas fa-download text-primary fs-4"></i>
</div>
</div>
</div>
</div>
<?php endif; ?>
<?php if (canView('outbound')): ?>
<div class="col-md-3">
<div class="card h-100 p-3 shadow-sm border-0 border-start border-success border-4">
<div class="d-flex align-items-center justify-content-between">
<div>
<h6 class="text-muted mb-1">البريد الصادر</h6>
<h3 class="fw-bold mb-0"><?= $total_outbound ?></h3>
</div>
<div class="bg-success bg-opacity-10 p-3 rounded-circle">
<i class="fas fa-upload text-success fs-4"></i>
</div>
</div>
</div>
</div>
<?php endif; ?>
<?php if (canView('inbound') || canView('outbound')): ?>
<div class="col-md-3">
<div class="card h-100 p-3 shadow-sm border-0 border-start border-info border-4">
<div class="d-flex align-items-center justify-content-between">
<div>
<h6 class="text-muted mb-1">قيد المعالجة</h6>
<h3 class="fw-bold mb-0"><?= $in_progress_count ?></h3>
</div>
<div class="bg-info bg-opacity-10 p-3 rounded-circle">
<i class="fas fa-clock text-info fs-4"></i>
</div>
</div>
</div>
</div>
<?php endif; ?>
<?php if (canView('users')): ?>
<div class="col-md-3">
<div class="card h-100 p-3 shadow-sm border-0 border-start border-warning border-4">
<div class="d-flex align-items-center justify-content-between">
<div>
<h6 class="text-muted mb-1">المستخدمين</h6>
<h3 class="fw-bold mb-0"><?= db()->query("SELECT COUNT(*) FROM users")->fetchColumn() ?></h3>
</div>
<div class="bg-warning bg-opacity-10 p-3 rounded-circle">
<i class="fas fa-users text-warning fs-4"></i>
</div>
</div>
</div>
</div>
<?php endif; ?>
</div>
<?php if (!empty($my_assignments)): ?>
<!-- My Assignments Section -->
<div class="card shadow-sm border-0 mb-4 bg-primary bg-opacity-10 border-top border-primary border-3">
<div class="card-header bg-transparent py-3 border-0">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0 fw-bold text-primary"><i class="fas fa-tasks me-2"></i> مهامي الحالية</h5>
<span class="badge bg-primary rounded-pill"><?= count($my_assignments) ?></span>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<tbody>
<?php foreach ($my_assignments as $mail): ?>
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>&type=<?= $mail['type'] ?>'">
<td class="ps-4" width="120">
<small class="text-muted d-block">رقم القيد</small>
<span class="fw-bold text-primary"><?= $mail['ref_no'] ?></span>
</td>
<td>
<small class="text-muted d-block">الموضوع</small>
<span class="fw-bold"><?= htmlspecialchars($mail['subject'] ?? '') ?></span>
</td>
<td>
<small class="text-muted d-block">الموعد النهائي</small>
<?php if ($mail['due_date']): ?>
<span class="<?= (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed') ? 'text-danger fw-bold' : '' ?>">
<?= $mail['due_date'] ?>
</span>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td class="text-center">
<small class="text-muted d-block mb-1">الحالة</small>
<?= getStatusBadge($mail) ?>
</td>
<td class="pe-4 text-end">
<i class="fas fa-chevron-left text-primary"></i>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
<?php if (!empty($recent_mail)): ?>
<!-- Recent Mail -->
<div class="card shadow-sm border-0 mb-4">
<div class="card-header bg-white py-3">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0 fw-bold"><?= $is_admin ? 'آخر المراسلات المسجلة' : 'آخر المراسلات' ?></h5>
<a href="inbound.php" class="btn btn-sm btn-link text-decoration-none">عرض الكل</a>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="ps-4">رقم القيد</th>
<th>النوع</th>
<th>الموضوع</th>
<th>الموعد النهائي</th>
<th>المرسل/المستلم</th>
<th>المسؤول</th>
<th>الحالة</th>
<th class="pe-4 text-center">التاريخ</th>
</tr>
</thead>
<tbody>
<?php foreach ($recent_mail as $mail): ?>
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>&type=<?= $mail['type'] ?>'">
<td class="ps-4 fw-bold text-primary"><?= $mail['ref_no'] ?></td>
<td>
<?php if ($mail['type'] == 'inbound'): ?>
<span class="text-primary"><i class="fas fa-arrow-down me-1"></i> وارد</span>
<?php else: ?>
<span class="text-success"><i class="fas fa-arrow-up me-1"></i> صادر</span>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($mail['subject'] ?? '') ?></td>
<td>
<?php if ($mail['due_date']): ?>
<small class="<?= (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed') ? 'text-danger fw-bold' : 'text-muted' ?>">
<?= $mail['due_date'] ?>
</small>
<?php else: ?>
<small class="text-muted">-</small>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($mail['sender'] ?: $mail['recipient']) ?></td>
<td>
<?php if ($mail['assigned_to_name']): ?>
<small><i class="fas fa-user-tag me-1 text-muted"></i> <?= htmlspecialchars($mail['assigned_to_name'] ?? '') ?></small>
<?php else: ?>
<small class="text-muted">غير معين</small>
<?php endif; ?>
</td>
<td><?= getStatusBadge($mail) ?></td>
<td class="pe-4 text-center"><?= date('Y-m-d', strtotime($mail['date_registered'])) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -4,7 +4,7 @@ require_once __DIR__ . '/m_services/MailService.php';
// Only users with settings view permission can access this page
if (!canView('settings')) {
redirect("index.php");
redirect("user_dashboard.php");
}
$success_msg = '';
@ -76,9 +76,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_advanced'])) {
$site_maintenance = isset($_POST['site_maintenance']) ? 1 : 0;
$allow_registration = isset($_POST['allow_registration']) ? 1 : 0;
$site_footer = $_POST['site_footer'];
$site_version = $_POST['site_version'] ?? '1.3.0';
$stmt = db()->prepare("UPDATE charity_settings SET site_maintenance = ?, allow_registration = ?, site_footer = ? WHERE id = 1");
$stmt->execute([$site_maintenance, $allow_registration, $site_footer]);
$stmt = db()->prepare("UPDATE charity_settings SET site_maintenance = ?, allow_registration = ?, site_footer = ?, site_version = ? WHERE id = 1");
$stmt->execute([$site_maintenance, $allow_registration, $site_footer, $site_version]);
$_SESSION['success'] = 'تم تحديث الإعدادات المتقدمة بنجاح';
}
redirect('charity-settings.php');
@ -403,6 +404,12 @@ $post_max = ini_get('post_max_size');
<p class="small text-muted mb-0">تفعيل خيار "إنشاء حساب جديد" في صفحة تسجيل الدخول.</p>
</div>
</div>
<div class="col-md-12">
<div class="mb-3">
<label class="form-label fw-bold">نسخة النظام (System Version)</label>
<input type="text" name="site_version" class="form-control" value="<?= htmlspecialchars($charity['site_version'] ?? '1.3.0') ?>">
</div>
</div>
<div class="col-12">
<div class="mb-3">
<label class="form-label fw-bold">نص تذييل الموقع (Footer Text)</label>
@ -436,7 +443,7 @@ $post_max = ini_get('post_max_size');
<tr>
<td>
<span class="badge px-3 py-2" style="background-color: <?= $status['color'] ?>;">
<?= htmlspecialchars($status['name']) ?>
<?= htmlspecialchars($status['name'] ?? '') ?>
</span>
</td>
<td><code><?= $status['color'] ?></code></td>
@ -485,8 +492,8 @@ $post_max = ini_get('post_max_size');
<?php foreach ($email_logs as $log): ?>
<tr>
<td class="ps-3 small"><?= date('Y-m-d H:i:s', strtotime($log['created_at'])) ?></td>
<td><span class="fw-bold"><?= htmlspecialchars($log['recipient']) ?></span></td>
<td class="small"><?= htmlspecialchars($log['subject']) ?></td>
<td><span class="fw-bold"><?= htmlspecialchars($log['recipient'] ?? '') ?></span></td>
<td class="small"><?= htmlspecialchars($log['subject'] ?? '') ?></td>
<td>
<span class="badge bg-<?= $log['status'] === 'success' ? 'success' : 'danger' ?>">
<?= $log['status'] === 'success' ? 'تم الإرسال' : 'فشل' ?>

View File

@ -48,7 +48,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
// Fetch members
$stmt = db()->query("SELECT * FROM charity_members ORDER BY name ASC");
$search = $_GET['search'] ?? '';
$query = "SELECT * FROM charity_members";
$params = [];
if (!empty($search)) {
$query .= " WHERE name LIKE ? OR role LIKE ? OR phone LIKE ? OR email LIKE ?";
$searchTerm = "%$search%";
$params = [$searchTerm, $searchTerm, $searchTerm, $searchTerm];
}
$query .= " ORDER BY name ASC";
$stmt = db()->prepare($query);
$stmt->execute($params);
$members = $stmt->fetchAll();
?>
@ -68,16 +78,31 @@ $members = $stmt->fetchAll();
<?php if (isset($_SESSION['success'])): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?= htmlspecialchars($_SESSION['success']) ?>
<?= htmlspecialchars($_SESSION['success'] ?? '') ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php unset($_SESSION['success']); ?>
<?php endif; ?>
<div class="card border-0 shadow-sm">
<div class="card-body">
<div class="card-header bg-white border-0 pt-3 pb-0">
<div class="row">
<div class="col-md-4">
<form method="GET" action="">
<div class="input-group input-group-sm">
<input type="text" name="search" class="form-control" placeholder="بحث بالاسم، الجوال، الإيميل..." value="<?= htmlspecialchars($search ?? '') ?>">
<button class="btn btn-outline-secondary" type="submit"><i class="fas fa-search"></i></button>
<?php if (!empty($search)): ?>
<a href="charity_members.php" class="btn btn-outline-danger"><i class="fas fa-times"></i></a>
<?php endif; ?>
</div>
</form>
</div>
</div>
</div>
<div class="card-body pt-3">
<div class="table-responsive">
<table class="table table-hover align-middle">
<table class="table table-sm table-hover align-middle" style="font-size: 0.9rem;">
<thead class="table-light">
<tr>
<th>الاسم</th>
@ -96,26 +121,26 @@ $members = $stmt->fetchAll();
<tr>
<td>
<div class="d-flex align-items-center">
<div class="bg-primary bg-opacity-10 text-primary rounded-circle d-flex align-items-center justify-content-center me-3" style="width: 40px; height: 40px;">
<div class="bg-primary bg-opacity-10 text-primary rounded-circle d-flex align-items-center justify-content-center me-3" style="width: 32px; height: 32px; font-size: 0.85rem;">
<i class="fas fa-user"></i>
</div>
<div>
<div class="fw-bold"><?= htmlspecialchars($member['name']) ?></div>
<div class="fw-bold"><?= htmlspecialchars($member['name'] ?? '') ?></div>
</div>
</div>
</td>
<td><?= htmlspecialchars($member['role']) ?></td>
<td><?= htmlspecialchars($member['phone']) ?></td>
<td><?= htmlspecialchars($member['email']) ?></td>
<td><?= htmlspecialchars($member['join_date']) ?></td>
<td><?= htmlspecialchars($member['role'] ?? '') ?></td>
<td><?= htmlspecialchars($member['phone'] ?? '') ?></td>
<td><?= htmlspecialchars($member['email'] ?? '') ?></td>
<td><?= htmlspecialchars($member['join_date'] ?? '') ?></td>
<td>
<?php if ($member['status'] === 'active'): ?>
<span class="badge bg-success bg-opacity-10 text-success px-3 py-2 rounded-pill">نشط</span>
<span class="badge bg-success bg-opacity-10 text-success px-2 py-1 rounded-pill">نشط</span>
<?php else: ?>
<span class="badge bg-secondary bg-opacity-10 text-secondary px-3 py-2 rounded-pill">غير نشط</span>
<span class="badge bg-secondary bg-opacity-10 text-secondary px-2 py-1 rounded-pill">غير نشط</span>
<?php endif; ?>
</td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($member['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($member['created_by'] ?? $member['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($member['updated_by'] ?? null)) ?></small></td>
<td class="text-end">
<?php if (isAdmin() || canEdit('charity_members')): ?>
@ -146,23 +171,23 @@ $members = $stmt->fetchAll();
<div class="mb-3">
<label class="form-label">الاسم</label>
<input type="text" class="form-control" name="name" value="<?= htmlspecialchars($member['name']) ?>" required>
<input type="text" class="form-control" name="name" value="<?= htmlspecialchars($member['name'] ?? '') ?>" required>
</div>
<div class="mb-3">
<label class="form-label">الدور/الصفة في الجمعية</label>
<input type="text" class="form-control" name="role" value="<?= htmlspecialchars($member['role']) ?>" placeholder="مثال: عضو مجلس الإدارة، مدير عام...">
<input type="text" class="form-control" name="role" value="<?= htmlspecialchars($member['role'] ?? '') ?>" placeholder="مثال: عضو مجلس الإدارة، مدير عام...">
</div>
<div class="mb-3">
<label class="form-label">رقم الجوال</label>
<input type="text" class="form-control" name="phone" value="<?= htmlspecialchars($member['phone']) ?>">
<input type="text" class="form-control" name="phone" value="<?= htmlspecialchars($member['phone'] ?? '') ?>">
</div>
<div class="mb-3">
<label class="form-label">البريد الإلكتروني</label>
<input type="email" class="form-control" name="email" value="<?= htmlspecialchars($member['email']) ?>">
<input type="email" class="form-control" name="email" value="<?= htmlspecialchars($member['email'] ?? '') ?>">
</div>
<div class="mb-3">
<label class="form-label">تاريخ الانضمام</label>
<input type="date" class="form-control" name="join_date" value="<?= htmlspecialchars($member['join_date']) ?>">
<input type="date" class="form-control" name="join_date" value="<?= htmlspecialchars($member['join_date'] ?? '') ?>">
</div>
<div class="mb-3">
<label class="form-label">الحالة</label>
@ -192,7 +217,7 @@ $members = $stmt->fetchAll();
<div class="modal-body text-center p-4">
<i class="fas fa-exclamation-triangle text-danger fa-3x mb-3"></i>
<h4 class="mb-3">هل أنت متأكد؟</h4>
<p class="text-muted">هل تريد حقاً حذف العضو "<?= htmlspecialchars($member['name']) ?>"؟ لا يمكن التراجع عن هذا الإجراء وسيتم حذفه من أي لجان مرتبط بها.</p>
<p class="text-muted">هل تريد حقاً حذف العضو "<?= htmlspecialchars($member['name'] ?? '') ?>"؟ لا يمكن التراجع عن هذا الإجراء وسيتم حذفه من أي لجان مرتبط بها.</p>
</div>
<div class="modal-footer justify-content-center border-0">
<form method="POST">

View File

@ -94,7 +94,7 @@ $status_labels = [
<?php if (isset($_SESSION['success'])): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?= htmlspecialchars($_SESSION['success']) ?>
<?= htmlspecialchars($_SESSION['success'] ?? '') ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php unset($_SESSION['success']); ?>
@ -172,8 +172,8 @@ $status_labels = [
?>
<tr>
<td>
<div class="fw-bold"><?= htmlspecialchars($plan['title']) ?></div>
<div class="small text-muted text-truncate" style="max-width: 250px;"><?= htmlspecialchars($plan['description']) ?></div>
<div class="fw-bold"><?= htmlspecialchars($plan['title'] ?? '') ?></div>
<div class="small text-muted text-truncate" style="max-width: 250px;"><?= htmlspecialchars($plan['description'] ?? '') ?></div>
</td>
<td>
<div class="small"><i class="fas fa-calendar-alt text-muted me-1"></i> من: <?= $plan['start_date'] ?></div>
@ -192,7 +192,7 @@ $status_labels = [
<?= $status_labels[$plan['status']] ?>
</span>
</td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($plan['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($plan['created_by'] ?? $plan['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($plan['updated_by'] ?? null)) ?></small></td>
<td class="text-end">
<?php if (isAdmin() || canEdit('charity_plans')): ?>
@ -223,11 +223,11 @@ $status_labels = [
<div class="mb-3">
<label class="form-label">العنوان</label>
<input type="text" class="form-control" name="title" value="<?= htmlspecialchars($plan['title']) ?>" required>
<input type="text" class="form-control" name="title" value="<?= htmlspecialchars($plan['title'] ?? '') ?>" required>
</div>
<div class="mb-3">
<label class="form-label">الوصف</label>
<textarea class="form-control" name="description" rows="2"><?= htmlspecialchars($plan['description']) ?></textarea>
<textarea class="form-control" name="description" rows="2"><?= htmlspecialchars($plan['description'] ?? '') ?></textarea>
</div>
<div class="row">
<div class="col-md-6 mb-3">

0
check_data.php Normal file
View File

0
check_db.php Normal file
View File

0
check_users.php Normal file
View File

View File

@ -185,7 +185,7 @@ usort($committees, function($a, $b) {
<span class="text-muted fw-bold ms-2">#<?= $index + 1 ?></span>
<?php endif; ?>
</td>
<td class="fw-bold fs-6"><?= htmlspecialchars($c['name']) ?></td>
<td class="fw-bold fs-6"><?= htmlspecialchars($c['name'] ?? '') ?></td>
<td class="text-center">
<span class="badge bg-light text-dark border p-2 rounded-circle fs-6"><?= $c['members_count'] ?></span>
</td>

View File

@ -2,7 +2,7 @@
require_once __DIR__ . '/includes/header.php';
if (!canView('committees')) {
redirect('index.php');
redirect('user_dashboard.php');
}
$error = '';
@ -108,10 +108,10 @@ if (isset($_SESSION['error'])) {
<?php if (count($committees) > 0): ?>
<?php foreach ($committees as $committee): ?>
<tr>
<td class="ps-4"><?= htmlspecialchars($committee['id']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($committee['name']) ?></td>
<td class="ps-4"><?= htmlspecialchars($committee['id'] ?? '') ?></td>
<td class="fw-bold"><?= htmlspecialchars($committee['name'] ?? '') ?></td>
<td><?= htmlspecialchars($committee['description'] ?? '') ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($committee['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($committee['created_by'] ?? $committee['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($committee['updated_by'] ?? null)) ?></small></td>
<td class="text-center">
<a href="view_committee.php?id=<?= $committee['id'] ?>" class="btn btn-sm btn-outline-info me-1" title="إدارة اللجنة"><i class="fas fa-cog"></i> إدارة</a>

View File

@ -20,6 +20,14 @@ function db() {
$pdo->exec("SET @app_user_id = " . (int)$_SESSION['user_id']);
}
}
// FORCE SET IT EVERY TIME db() IS CALLED just in case the connection was dropped or it wasn't set!
if (isset($_SESSION['user_id']) && $pdo) {
try {
$pdo->exec("SET @app_user_id = " . (int)$_SESSION['user_id']);
} catch (Exception $e) {}
}
return $pdo;
}

View File

@ -0,0 +1 @@
ALTER TABLE charity_settings ADD COLUMN IF NOT EXISTS site_version varchar(50) DEFAULT '1.3.0';

View File

@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS events (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
event_date DATE NOT NULL,
start_time TIME DEFAULT NULL,
end_time TIME DEFAULT NULL,
location VARCHAR(255) DEFAULT NULL,
created_by INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL
);

0
desc_db.php Normal file
View File

314
events.php Normal file
View File

@ -0,0 +1,314 @@
<?php
require_once 'includes/header.php';
if (!canView('events')) {
echo "<div class='alert alert-danger m-4'>ليس لديك صلاحية لعرض هذه الصفحة.</div>";
require_once 'includes/footer.php';
exit;
}
$can_add = canAdd('events');
$can_edit = canEdit('events');
$can_delete = canDelete('events');
// Handle AJAX requests
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['ajax'])) {
ob_clean(); header('Content-Type: application/json');
$action = $_POST['action'] ?? '';
if ($action === 'fetch') {
$stmt = db()->query("SELECT id, title, description, event_date, start_time, end_time, location FROM events");
$events = $stmt->fetchAll();
$fc_events = [];
foreach($events as $e) {
$start = $e['event_date'];
if ($e['start_time']) $start .= 'T' . $e['start_time'];
$end = $e['event_date'];
if ($e['end_time']) $end .= 'T' . $e['end_time'];
$fc_events[] = [
'id' => $e['id'],
'title' => $e['title'],
'start' => $start,
'end' => $end,
'extendedProps' => [
'description' => $e['description'] ?? '',
'location' => $e['location'] ?? '',
'start_time' => $e['start_time'] ? substr($e['start_time'], 0, 5) : '',
'end_time' => $e['end_time'] ? substr($e['end_time'], 0, 5) : ''
]
];
}
echo json_encode($fc_events);
exit;
}
if ($action === 'save' && ($can_add || $can_edit)) {
$id = $_POST['id'] ?? 0;
$title = $_POST['title'] ?? '';
$date = $_POST['event_date'] ?? '';
$start_time = !empty($_POST['start_time']) ? $_POST['start_time'] : null;
$end_time = !empty($_POST['end_time']) ? $_POST['end_time'] : null;
$location = $_POST['location'] ?? '';
$description = $_POST['description'] ?? '';
if (!$title || !$date) {
echo json_encode(['success' => false, 'error' => 'البيانات الأساسية مطلوبة']);
exit;
}
if ($id && $can_edit) {
$stmt = db()->prepare("UPDATE events SET title=?, description=?, event_date=?, start_time=?, end_time=?, location=? WHERE id=?");
$stmt->execute([$title, $description, $date, $start_time, $end_time, $location, $id]);
} elseif (!$id && $can_add) {
$stmt = db()->prepare("INSERT INTO events (title, description, event_date, start_time, end_time, location, created_by) VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$title, $description, $date, $start_time, $end_time, $location, $_SESSION['user_id']]);
}
echo json_encode(['success' => true]);
exit;
}
if ($action === 'delete' && $can_delete) {
$id = $_POST['id'] ?? 0;
db()->prepare("DELETE FROM events WHERE id=?")->execute([$id]);
echo json_encode(['success' => true]);
exit;
}
}
?>
<link href='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.css' rel='stylesheet' />
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/locales/ar.js'></script>
<div class="container-fluid py-4">
<div class="row mb-4 align-items-center">
<div class="col">
<h2 class="h4 mb-0"><i class="fas fa-calendar-alt text-primary me-2"></i> التقويم والأحداث</h2>
</div>
<div class="col-auto">
<a href="print_events.php" target="_blank" class="btn btn-secondary me-2">
<i class="fas fa-print me-1"></i> طباعة الأحداث
</a>
<?php if ($can_add): ?>
<button class="btn btn-primary" onclick="openEventModal()">
<i class="fas fa-plus me-1"></i> إضافة حدث جديد
</button>
<?php endif; ?>
</div>
</div>
<div class="card shadow-sm border-0">
<div class="card-body p-4">
<div id='calendar'></div>
</div>
</div>
</div>
<!-- Event Modal -->
<div class="modal fade" id="eventModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="eventModalTitle">إضافة حدث</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="eventForm">
<input type="hidden" id="event_id" name="id">
<input type="hidden" name="action" value="save">
<div class="mb-3">
<label class="form-label">عنوان الحدث <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="event_title" name="title" required>
</div>
<div class="mb-3">
<label class="form-label">التاريخ <span class="text-danger">*</span></label>
<input type="date" class="form-control" id="event_date" name="event_date" required>
</div>
<div class="row mb-3">
<div class="col-6">
<label class="form-label">وقت البدء</label>
<input type="time" class="form-control" id="event_start_time" name="start_time">
</div>
<div class="col-6">
<label class="form-label">وقت الانتهاء</label>
<input type="time" class="form-control" id="event_end_time" name="end_time">
</div>
</div>
<div class="mb-3">
<label class="form-label">المكان</label>
<input type="text" class="form-control" id="event_location" name="location">
</div>
<div class="mb-3">
<label class="form-label">التفاصيل</label>
<textarea class="form-control" id="event_description" name="description" rows="3"></textarea>
</div>
</form>
</div>
<div class="modal-footer justify-content-between">
<div>
<?php if ($can_delete): ?>
<button type="button" class="btn btn-danger d-none" id="btnDeleteEvent" onclick="deleteEvent()">حذف</button>
<?php endif; ?>
</div>
<div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button>
<button type="button" class="btn btn-primary" onclick="saveEvent()">حفظ</button>
</div>
</div>
</div>
</div>
</div>
<script>
let calendar;
let eventModal;
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
calendar = new FullCalendar.Calendar(calendarEl, {
locale: 'ar',
direction: 'rtl',
initialView: 'dayGridMonth',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: function(info, successCallback, failureCallback) {
let fd = new FormData();
fd.append('action', 'fetch');
fetch('events.php?ajax=1', {
method: 'POST',
body: fd
})
.then(r => r.json())
.then(data => successCallback(data))
.catch(err => failureCallback(err));
},
dateClick: function(info) {
openEventModal({ date: info.dateStr });
},
eventClick: function(info) {
let ev = info.event;
let props = ev.extendedProps;
// Format date for <input type="date"> which expects YYYY-MM-DD
let dateStr = ev.start.getFullYear() + '-' +
String(ev.start.getMonth() + 1).padStart(2, '0') + '-' +
String(ev.start.getDate()).padStart(2, '0');
openEventModal({
id: ev.id,
title: ev.title,
date: dateStr,
start_time: props.start_time,
end_time: props.end_time,
location: props.location,
description: props.description
});
}
});
calendar.render();
eventModal = new bootstrap.Modal(document.getElementById('eventModal'));
});
function openEventModal(data = null) {
document.getElementById('eventForm').reset();
document.getElementById('event_id').value = '';
document.getElementById('eventModalTitle').innerText = 'إضافة حدث جديد';
let btnDel = document.getElementById('btnDeleteEvent');
if (btnDel) btnDel.classList.add('d-none');
if (data) {
document.getElementById('event_id').value = data.id || '';
document.getElementById('event_title').value = data.title || '';
document.getElementById('event_date').value = data.date || '';
document.getElementById('event_start_time').value = data.start_time || '';
document.getElementById('event_end_time').value = data.end_time || '';
document.getElementById('event_location').value = data.location || '';
document.getElementById('event_description').value = data.description || '';
if (data.id) {
document.getElementById('eventModalTitle').innerText = 'تعديل حدث';
if (btnDel) btnDel.classList.remove('d-none');
}
}
eventModal.show();
}
function saveEvent() {
const form = document.getElementById('eventForm');
if (!form.reportValidity()) return;
fetch('events.php?ajax=1', {
method: 'POST',
body: new FormData(form)
})
.then(r => r.json())
.then(res => {
if (res.success) {
eventModal.hide();
calendar.refetchEvents();
Swal.fire({icon: 'success', title: 'تم الحفظ', showConfirmButton: false, timer: 1500});
} else {
Swal.fire({icon: 'error', title: 'خطأ', text: res.error || 'حدث خطأ أثناء الحفظ'});
}
});
}
function deleteEvent() {
const id = document.getElementById('event_id').value;
if (!id) return;
Swal.fire({
title: 'هل أنت متأكد؟',
text: "لن تتمكن من التراجع عن هذا!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
cancelButtonColor: '#3085d6',
confirmButtonText: 'نعم، احذف!',
cancelButtonText: 'إلغاء'
}).then((result) => {
if (result.isConfirmed) {
let fd = new FormData();
fd.append('action', 'delete');
fd.append('id', id);
fetch('events.php?ajax=1', {
method: 'POST',
body: fd
})
.then(r => r.json())
.then(res => {
if (res.success) {
eventModal.hide();
calendar.refetchEvents();
Swal.fire({icon: 'success', title: 'تم الحذف', showConfirmButton: false, timer: 1500});
}
});
}
});
}
</script>
<style>
/* FullCalendar customization */
.fc-theme-standard .fc-scrollgrid { border-color: var(--bs-border-color); }
.fc-theme-standard td, .fc-theme-standard th { border-color: var(--bs-border-color); }
.fc .fc-button-primary { background-color: #0d6efd; border-color: #0d6efd; }
.fc .fc-button-primary:not(:disabled):active, .fc .fc-button-primary:not(:disabled).fc-button-active {
background-color: #0a58ca; border-color: #0a53be;
}
.fc-event { cursor: pointer; }
.fc .fc-toolbar-title { font-size: 1.25em; font-weight: bold; }
[data-bs-theme="dark"] .fc-theme-standard .fc-scrollgrid { border-color: rgba(255,255,255,0.1); }
[data-bs-theme="dark"] .fc-theme-standard td, [data-bs-theme="dark"] .fc-theme-standard th { border-color: rgba(255,255,255,0.1); }
[data-bs-theme="dark"] .fc-day-today { background-color: rgba(255,255,255,0.05) !important; }
</style>
<?php require_once 'includes/footer.php'; ?>

View File

@ -2,7 +2,7 @@
require_once __DIR__ . '/includes/header.php';
if (!canView('expense_settings')) {
redirect('index.php');
redirect('user_dashboard.php');
}
$error = '';
@ -109,16 +109,16 @@ if (isset($_SESSION['error'])) {
<tbody>
<?php foreach ($categories as $cat): ?>
<tr>
<td class="ps-4 fw-bold"><?= htmlspecialchars($cat['name']) ?></td>
<td class="ps-4 fw-bold"><?= htmlspecialchars($cat['name'] ?? '') ?></td>
<td>
<?php if($cat['account_name']): ?>
<span class="badge bg-info text-dark"><?= htmlspecialchars($cat['account_name']) ?></span>
<span class="badge bg-info text-dark"><?= htmlspecialchars($cat['account_name'] ?? '') ?></span>
<?php else: ?>
<span class="text-muted text-small">غير مرتبط</span>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($cat['description']) ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($cat['created_by'] ?? null)) ?></small></td>
<td><?= htmlspecialchars($cat['description'] ?? '') ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($cat['created_by'] ?? $cat['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($cat['updated_by'] ?? null)) ?></small></td>
<td class="text-center">
<?php if (canEdit('expense_settings')): ?>
@ -164,7 +164,7 @@ if (isset($_SESSION['error'])) {
<option value="">-- اختر الحساب --</option>
<?php foreach($accounts as $acc): ?>
<option value="<?= $acc['id'] ?>">
<?= htmlspecialchars($acc['name']) ?> (<?= $acc['type'] ?>)
<?= htmlspecialchars($acc['name'] ?? '') ?> (<?= $acc['type'] ?>)
</option>
<?php endforeach; ?>
</select>

View File

@ -2,7 +2,7 @@
require_once __DIR__ . '/includes/header.php';
if (!canView('expenses')) {
redirect('index.php');
redirect('user_dashboard.php');
}
// Params
@ -89,7 +89,7 @@ $categories = db()->query("SELECT * FROM expense_categories ORDER BY name")->fet
<select name="category_id" class="form-select">
<option value="">الكل</option>
<?php foreach ($categories as $cat): ?>
<option value="<?= $cat['id'] ?>" <?= $category_id == $cat['id'] ? 'selected' : '' ?>><?= htmlspecialchars($cat['name']) ?></option>
<option value="<?= $cat['id'] ?>" <?= $category_id == $cat['id'] ? 'selected' : '' ?>><?= htmlspecialchars($cat['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -134,7 +134,7 @@ $categories = db()->query("SELECT * FROM expense_categories ORDER BY name")->fet
<?php foreach ($category_breakdown as $name => $amount): ?>
<div class="col-6 col-md-4">
<div class="p-2 border rounded bg-light">
<small class="d-block text-muted"><?= htmlspecialchars($name) ?></small>
<small class="d-block text-muted"><?= htmlspecialchars($name ?? '') ?></small>
<span class="fw-bold"><?= number_format($amount, 3) ?></span>
</div>
</div>
@ -173,11 +173,11 @@ $categories = db()->query("SELECT * FROM expense_categories ORDER BY name")->fet
<?php foreach ($expenses as $exp): ?>
<tr>
<td class="ps-3"><?= $exp['date'] ?></td>
<td><?= htmlspecialchars($exp['category_name']) ?></td>
<td><?= htmlspecialchars($exp['description']) ?></td>
<td><?= htmlspecialchars($exp['category_name'] ?? '') ?></td>
<td><?= htmlspecialchars($exp['description'] ?? '') ?></td>
<td><?= htmlspecialchars($exp['vendor'] ?: '-') ?></td>
<td><?= htmlspecialchars($exp['reference'] ?: '-') ?></td>
<td><?= htmlspecialchars($exp['payment_method']) ?></td>
<td><?= htmlspecialchars($exp['payment_method'] ?? '') ?></td>
<td><small><?= htmlspecialchars($exp['created_by'] ?: '-') ?></small></td>
<td class="text-end pe-3 fw-bold"><?= number_format($exp['amount'], 2) ?></td>
</tr>

View File

@ -4,7 +4,7 @@ require_once __DIR__ . '/includes/accounting_functions.php'; // Include accounti
require_once __DIR__ . '/includes/pagination.php';
if (!canView('expenses')) {
redirect('index.php');
redirect('user_dashboard.php');
}
$error = '';
@ -254,14 +254,14 @@ if (isset($_SESSION['success'])) {
<select name="category_id" class="form-select">
<option value="">الكل</option>
<?php foreach ($categories as $cat): ?>
<option value="<?= $cat['id'] ?>" <?= $category_filter == $cat['id'] ? 'selected' : '' ?>><?= htmlspecialchars($cat['name']) ?></option>
<option value="<?= $cat['id'] ?>" <?= $category_filter == $cat['id'] ? 'selected' : '' ?>><?= htmlspecialchars($cat['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3">
<label class="form-label">بحث</label>
<div class="input-group">
<input type="text" name="search" class="form-control" placeholder="وصف، مورد، مرجع..." value="<?= htmlspecialchars($search) ?>">
<input type="text" name="search" class="form-control" placeholder="وصف، مورد، مرجع..." value="<?= htmlspecialchars($search ?? '') ?>">
<button class="btn btn-primary" type="submit"><i class="fas fa-search"></i></button>
</div>
</div>
@ -297,21 +297,21 @@ if (isset($_SESSION['success'])) {
<?php foreach ($expenses as $exp): ?>
<tr>
<td class="ps-4"><?= $exp['date'] ?></td>
<td><span class="badge bg-secondary bg-opacity-10 text-secondary"><?= htmlspecialchars($exp['category_name']) ?></span></td>
<td><span class="badge bg-secondary bg-opacity-10 text-secondary"><?= htmlspecialchars($exp['category_name'] ?? '') ?></span></td>
<td>
<?= htmlspecialchars($exp['description']) ?>
<?= htmlspecialchars($exp['description'] ?? '') ?>
<?php if ($exp['reference']): ?>
<br><small class="text-muted">Ref: <?= htmlspecialchars($exp['reference']) ?></small>
<br><small class="text-muted">Ref: <?= htmlspecialchars($exp['reference'] ?? '') ?></small>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($exp['vendor'] ?: '-') ?></td>
<td class="fw-bold text-danger"><?= number_format($exp['amount'], 2) ?></td>
<td><?= htmlspecialchars($exp['payment_method']) ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($exp['created_by'] ?? null)) ?></small></td>
<td><?= htmlspecialchars($exp['payment_method'] ?? '') ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($exp['created_by'] ?? $exp['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($exp['updated_by'] ?? null)) ?></small></td>
<td>
<?php if ($exp['receipt_file']): ?>
<a href="<?= htmlspecialchars($exp['receipt_file']) ?>" target="_blank" class="btn btn-sm btn-outline-secondary">
<a href="<?= htmlspecialchars($exp['receipt_file'] ?? '') ?>" target="_blank" class="btn btn-sm btn-outline-secondary">
<i class="fas fa-paperclip"></i>
</a>
<?php else: ?>
@ -377,7 +377,7 @@ if (isset($_SESSION['success'])) {
<select name="category_id" id="modalCategory" class="form-select" required>
<option value="">اختر التصنيف...</option>
<?php foreach ($categories as $cat): ?>
<option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['name']) ?></option>
<option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>

View File

@ -2,7 +2,7 @@
require_once __DIR__ . '/includes/header.php';
if (!canView('expenses')) {
redirect('index.php');
redirect('user_dashboard.php');
}
// Helper to get totals
@ -153,13 +153,13 @@ $recent_expenses = $stmt->fetchAll(PDO::FETCH_ASSOC);
<?php foreach ($recent_expenses as $exp): ?>
<tr>
<td class="ps-4"><?= $exp['date'] ?></td>
<td><span class="badge bg-secondary bg-opacity-10 text-secondary"><?= htmlspecialchars($exp['category_name']) ?></span></td>
<td><span class="badge bg-secondary bg-opacity-10 text-secondary"><?= htmlspecialchars($exp['category_name'] ?? '') ?></span></td>
<td>
<div class="fw-bold"><?= htmlspecialchars($exp['description'] ?: '-') ?></div>
<div class="small text-muted"><?= htmlspecialchars($exp['vendor'] ?: '') ?></div>
</td>
<td class="fw-bold text-danger"><?= number_format($exp['amount'], 2) ?></td>
<td><?= htmlspecialchars($exp['payment_method']) ?></td>
<td><?= htmlspecialchars($exp['payment_method'] ?? '') ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>

1
fix_audit.php Normal file
View File

@ -0,0 +1 @@

18
fix_nulls.php Normal file
View File

@ -0,0 +1,18 @@
<?php
$files = ['charity_members.php', 'charity_plans.php', 'committees.php', 'expenses.php', 'accounts.php', 'accounting.php'];
foreach ($files as $file) {
if (file_exists($file)) {
$content = file_get_contents($file);
// Use ~ as delimiter to avoid issues with /
$pattern1 = "~htmlspecialchars\(\s*\\\$([a-zA-Z0-9_]+)\\[\'([a-zA-Z0-9_]+)\\'\]\s*\)~s";
$pattern2 = '~htmlspecialchars\(\s*\$([a-zA-Z0-9_]+)\["([a-zA-Z0-9_]+)"\]\s*\)~s';
$content = preg_replace($pattern1, "htmlspecialchars(\\\\$1[\\\'\\2\\] ?? '')", $content);
$content = preg_replace($pattern2, 'htmlspecialchars($\1["\2"] ?? "")', $content);
file_put_contents($file, $content);
echo "Processed $file\n";
}
}
?>

View File

@ -3,7 +3,7 @@ require_once __DIR__ . '/includes/header.php';
require_once __DIR__ . '/m_services/MailService.php';
if (isLoggedIn()) {
redirect('index.php');
redirect('user_dashboard.php');
}
$error = '';
@ -92,7 +92,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<div class="card p-4 shadow-sm border-0 text-center">
<div class="mb-4">
<?php if (!empty($charity_info['charity_logo'])): ?>
<img src="<?= htmlspecialchars($charity_info['charity_logo']) ?>" alt="Logo" class="mb-3" style="max-height: 80px;">
<img src="<?= htmlspecialchars($charity_info['charity_logo'] ?? '') ?>" alt="Logo" class="mb-3" style="max-height: 80px;">
<?php endif; ?>
<h4 class="fw-bold">استعادة كلمة المرور</h4>
<p class="text-muted small">بريد <?= htmlspecialchars($charity_info['charity_name'] ?? 'النظام') ?></p>

View File

@ -81,10 +81,10 @@ $records = $stmt->fetchAll();
</div>
<?php if ($error): ?>
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
<div class="alert alert-danger"><?= htmlspecialchars($error ?? '') ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?= htmlspecialchars($success) ?></div>
<div class="alert alert-success"><?= htmlspecialchars($success ?? '') ?></div>
<?php endif; ?>
<div class="card shadow-sm border-0">
@ -113,7 +113,7 @@ $records = $stmt->fetchAll();
<?php foreach ($records as $row): ?>
<tr class="<?= !$row['att_id'] ? 'table-light text-muted' : '' ?>">
<td class="fw-bold"><?= htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) ?></td>
<td class="small"><?= htmlspecialchars($row['job_title']) ?></td>
<td class="small"><?= htmlspecialchars($row['job_title'] ?? '') ?></td>
<td>
<?php if ($row['att_id']): ?>
<?php
@ -142,7 +142,7 @@ $records = $stmt->fetchAll();
<td><?= $row['check_in'] ? date('h:i A', strtotime($row['check_in'])) : '-' ?></td>
<td><?= $row['check_out'] ? date('h:i A', strtotime($row['check_out'])) : '-' ?></td>
<td class="text-truncate" style="max-width: 150px;"><?= htmlspecialchars($row['notes'] ?? '') ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['created_by'] ?? $row['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['updated_by'] ?? null)) ?></small></td>
<td>
<?php if (canEdit('hr_attendance')): ?>

View File

@ -101,7 +101,7 @@ $recent_employees = db()->query("SELECT * FROM hr_employees ORDER BY join_date D
<?php foreach ($recent_employees as $emp): ?>
<tr>
<td><?= htmlspecialchars($emp['first_name'] . ' ' . $emp['last_name']) ?></td>
<td><?= htmlspecialchars($emp['job_title']) ?></td>
<td><?= htmlspecialchars($emp['job_title'] ?? '') ?></td>
<td><?= date('Y-m-d', strtotime($emp['join_date'])) ?></td>
</tr>
<?php endforeach; ?>

View File

@ -112,10 +112,10 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
</div>
<?php if ($error): ?>
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
<div class="alert alert-danger"><?= htmlspecialchars($error ?? '') ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?= htmlspecialchars($success) ?></div>
<div class="alert alert-success"><?= htmlspecialchars($success ?? '') ?></div>
<?php endif; ?>
<!-- Departments Modal -->
@ -134,7 +134,7 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
<ul class="list-group">
<?php foreach ($departments as $dept): ?>
<li class="list-group-item d-flex justify-content-between align-items-center">
<?= htmlspecialchars($dept['name']) ?>
<?= htmlspecialchars($dept['name'] ?? '') ?>
<form method="post" onsubmit="return confirm('هل أنت متأكد؟');">
<input type="hidden" name="id" value="<?= $dept['id'] ?>">
<button type="submit" name="delete_department" class="btn btn-sm btn-danger"><i class="fas fa-trash"></i></button>
@ -204,7 +204,7 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
<select name="department_id" id="empDept" class="form-select">
<option value="">-- اختر القسم --</option>
<?php foreach ($departments as $dept): ?>
<option value="<?= $dept['id'] ?>"><?= htmlspecialchars($dept['name']) ?></option>
<option value="<?= $dept['id'] ?>"><?= htmlspecialchars($dept['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -285,12 +285,12 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
</div>
<div>
<div class="fw-bold"><?= htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) ?></div>
<div class="small text-muted"><?= htmlspecialchars($row['email']) ?></div>
<div class="small text-muted"><?= htmlspecialchars($row['email'] ?? '') ?></div>
</div>
</div>
</td>
<td><span class="badge bg-secondary"><?= htmlspecialchars($row['dept_name'] ?? '-') ?></span></td>
<td><?= htmlspecialchars($row['job_title']) ?></td>
<td><?= htmlspecialchars($row['job_title'] ?? '') ?></td>
<td><?= $row['join_date'] ?></td>
<td>
<?php
@ -302,10 +302,10 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
default => 'secondary'
};
?>
<span class="badge bg-<?= $status_cls ?>"><?= htmlspecialchars($row['status']) ?></span>
<span class="badge bg-<?= $status_cls ?>"><?= htmlspecialchars($row['status'] ?? '') ?></span>
</td>
<td><span class="badge bg-light text-dark border"><?= htmlspecialchars($row['zkteco_uid'] ?: '-') ?></span></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($emp['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($emp['created_by'] ?? $emp['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($emp['updated_by'] ?? null)) ?></small></td>
<td>
<div class="btn-group">
@ -314,14 +314,14 @@ $pagination = getPagination($page, $totalEmployees, $perPage);
data-bs-toggle="modal"
data-bs-target="#employeeModal"
data-id="<?= $row['id'] ?>"
data-fname="<?= htmlspecialchars($row['first_name']) ?>"
data-lname="<?= htmlspecialchars($row['last_name']) ?>"
data-email="<?= htmlspecialchars($row['email']) ?>"
data-phone="<?= htmlspecialchars($row['phone']) ?>"
data-fname="<?= htmlspecialchars($row['first_name'] ?? '') ?>"
data-lname="<?= htmlspecialchars($row['last_name'] ?? '') ?>"
data-email="<?= htmlspecialchars($row['email'] ?? '') ?>"
data-phone="<?= htmlspecialchars($row['phone'] ?? '') ?>"
data-gender="<?= $row['gender'] ?>"
data-bdate="<?= $row['birth_date'] ?>"
data-dept="<?= $row['department_id'] ?>"
data-job="<?= htmlspecialchars($row['job_title']) ?>"
data-job="<?= htmlspecialchars($row['job_title'] ?? '') ?>"
data-join="<?= $row['join_date'] ?>"
data-salary="<?= $row['basic_salary'] ?>"
data-status="<?= $row['status'] ?>" data-user="<?= $row['user_id'] ?>"

View File

@ -59,10 +59,10 @@ $holidays = db()->query("SELECT * FROM hr_holidays ORDER BY date_from DESC")->fe
</div>
<?php if ($error): ?>
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
<div class="alert alert-danger"><?= htmlspecialchars($error ?? '') ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?= htmlspecialchars($success) ?></div>
<div class="alert alert-success"><?= htmlspecialchars($success ?? '') ?></div>
<?php endif; ?>
<div class="card shadow-sm">
@ -98,11 +98,11 @@ $holidays = db()->query("SELECT * FROM hr_holidays ORDER BY date_from DESC")->fe
}
?>
<tr>
<td class="fw-bold"><?= htmlspecialchars($row['name']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($row['name'] ?? '') ?></td>
<td><?= $row['date_from'] ?></td>
<td><?= $row['date_to'] ?></td>
<td><span class="badge bg-<?= $status_cls ?>"><?= $status_txt ?></span></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['created_by'] ?? $row['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['updated_by'] ?? null)) ?></small></td>
<td>
<?php if (canEdit('hr_attendance')): ?>
@ -110,7 +110,7 @@ $holidays = db()->query("SELECT * FROM hr_holidays ORDER BY date_from DESC")->fe
data-bs-toggle="modal"
data-bs-target="#holidayModal"
data-id="<?= $row['id'] ?>"
data-name="<?= htmlspecialchars($row['name']) ?>"
data-name="<?= htmlspecialchars($row['name'] ?? '') ?>"
data-from="<?= $row['date_from'] ?>"
data-to="<?= $row['date_to'] ?>"
onclick="editHoliday(this)">

View File

@ -134,10 +134,10 @@ $requests = $stmt->fetchAll();
</div>
<?php if ($error): ?>
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
<div class="alert alert-danger"><?= htmlspecialchars($error ?? '') ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?= htmlspecialchars($success) ?></div>
<div class="alert alert-success"><?= htmlspecialchars($success ?? '') ?></div>
<?php endif; ?>
<ul class="nav nav-tabs mb-4">
@ -153,10 +153,10 @@ $requests = $stmt->fetchAll();
<div class="card shadow-sm mb-4">
<div class="card-body">
<form method="GET" class="row g-3 align-items-center">
<input type="hidden" name="tab" value="<?= htmlspecialchars($tab) ?>">
<input type="hidden" name="tab" value="<?= htmlspecialchars($tab ?? '') ?>">
<div class="col-md-4">
<input type="text" name="search" class="form-control" placeholder="بحث باسم الموظف أو السبب..." value="<?= htmlspecialchars($search) ?>">
<input type="text" name="search" class="form-control" placeholder="بحث باسم الموظف أو السبب..." value="<?= htmlspecialchars($search ?? '') ?>">
</div>
<div class="col-md-3">
@ -185,7 +185,7 @@ $requests = $stmt->fetchAll();
<div class="col-md-2 d-flex gap-2">
<button type="submit" class="btn btn-primary flex-grow-1"><i class="fas fa-search"></i> بحث</button>
<?php if ($search || $filter_type || $filter_status): ?>
<a href="?tab=<?= htmlspecialchars($tab) ?>" class="btn btn-outline-secondary">إلغاء</a>
<a href="?tab=<?= htmlspecialchars($tab ?? '') ?>" class="btn btn-outline-secondary">إلغاء</a>
<?php endif; ?>
</div>
</form>
@ -234,7 +234,7 @@ $requests = $stmt->fetchAll();
من <?= $req['start_date'] ?><br>إلى <?= $req['end_date'] ?>
</td>
<td><?= $req['days_count'] ?> يوم</td>
<td class="text-truncate" style="max-width: 150px;"><?= htmlspecialchars($req['reason']) ?></td>
<td class="text-truncate" style="max-width: 150px;"><?= htmlspecialchars($req['reason'] ?? '') ?></td>
<td>
<?php
$status_cls = match($req['status']) {
@ -253,7 +253,7 @@ $requests = $stmt->fetchAll();
<?php if ($tab === 'all'): ?>
<td class="small"><?= htmlspecialchars($req['approver_name'] ?? '-') ?></td>
<?php endif; ?>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($req['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($req['created_by'] ?? $req['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($req['updated_by'] ?? null)) ?></small></td>
<td>
<?php if ($req['status'] === 'pending' && canEdit('hr_leaves')): ?>
@ -266,7 +266,7 @@ $requests = $stmt->fetchAll();
data-type="<?= $req['leave_type'] ?>"
data-start="<?= $req['start_date'] ?>"
data-end="<?= $req['end_date'] ?>"
data-reason="<?= htmlspecialchars($req['reason']) ?>"
data-reason="<?= htmlspecialchars($req['reason'] ?? '') ?>"
onclick="editLeave(this)">
<i class="fas fa-edit"></i>
</button>

View File

@ -175,10 +175,10 @@ $total_salaries = $sumStmt->fetchColumn() ?: 0;
</div>
<?php if ($error): ?>
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
<div class="alert alert-danger"><?= htmlspecialchars($error ?? '') ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?= htmlspecialchars($success) ?></div>
<div class="alert alert-success"><?= htmlspecialchars($success ?? '') ?></div>
<?php endif; ?>
<div class="row mb-3">
@ -217,7 +217,7 @@ $total_salaries = $sumStmt->fetchColumn() ?: 0;
<tr>
<td>
<div class="fw-bold"><?= htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) ?></div>
<div class="small text-muted"><?= htmlspecialchars($row['job_title']) ?></div>
<div class="small text-muted"><?= htmlspecialchars($row['job_title'] ?? '') ?></div>
</td>
<td><?= number_format($row['basic_salary'], 2) ?></td>
<td class="text-success"><?= number_format($row['bonuses'], 2) ?></td>
@ -231,7 +231,7 @@ $total_salaries = $sumStmt->fetchColumn() ?: 0;
<span class="badge bg-info text-dark" title="مرحل للمحاسبة"><i class="fas fa-check-circle"></i></span>
<?php endif; ?>
</td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['created_by'] ?? $row['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($row['updated_by'] ?? null)) ?></small></td>
<td>
<?php if (canEdit('hr_payroll')): ?>
@ -239,7 +239,7 @@ $total_salaries = $sumStmt->fetchColumn() ?: 0;
data-bs-toggle="modal"
data-bs-target="#editPayModal"
data-id="<?= $row['id'] ?>"
data-name="<?= htmlspecialchars($row['first_name']) ?>"
data-name="<?= htmlspecialchars($row['first_name'] ?? '') ?>"
data-bonus="<?= $row['bonuses'] ?>"
data-deduct="<?= $row['deductions'] ?>"
data-status="<?= $row['status'] ?>">

View File

@ -146,10 +146,10 @@ $year = $_GET['year'] ?? date('Y');
<td>#<?= $emp['id'] ?></td>
<td><?= htmlspecialchars($emp['first_name'] . ' ' . $emp['last_name']) ?></td>
<td><?= htmlspecialchars($emp['dept_name'] ?? '-') ?></td>
<td><?= htmlspecialchars($emp['job_title']) ?></td>
<td><?= htmlspecialchars($emp['job_title'] ?? '') ?></td>
<td><?= $emp['join_date'] ?></td>
<td><?= number_format($emp['basic_salary'], 2) ?></td>
<td><?= htmlspecialchars($emp['phone']) ?></td>
<td><?= htmlspecialchars($emp['phone'] ?? '') ?></td>
</tr>
<?php endforeach; ?>
</tbody>

View File

@ -149,14 +149,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<?php if ($error): ?>
<div class="alert alert-danger shadow-sm border-0 border-start border-danger border-4 alert-dismissible fade show" role="alert">
<i class="fas fa-exclamation-circle me-2"></i> <?= htmlspecialchars($error) ?>
<i class="fas fa-exclamation-circle me-2"></i> <?= htmlspecialchars($error ?? '') ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success shadow-sm border-0 border-start border-success border-4 alert-dismissible fade show" role="alert">
<i class="fas fa-check-circle me-2"></i> <?= htmlspecialchars($success) ?>
<i class="fas fa-check-circle me-2"></i> <?= htmlspecialchars($success ?? '') ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
@ -193,11 +193,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<form method="POST" action="">
<div class="mb-3">
<label class="form-label">IP Address (عنوان الجهاز)</label>
<input type="text" class="form-control" name="ip_address" value="<?= htmlspecialchars($ip) ?>" required placeholder="مثال: 192.168.1.201">
<input type="text" class="form-control" name="ip_address" value="<?= htmlspecialchars($ip ?? '') ?>" required placeholder="مثال: 192.168.1.201">
</div>
<div class="mb-3">
<label class="form-label">Port (المنفذ)</label>
<input type="number" class="form-control" name="port" value="<?= htmlspecialchars($port) ?>" required placeholder="الافتراضي: 4370">
<input type="number" class="form-control" name="port" value="<?= htmlspecialchars($port ?? '') ?>" required placeholder="الافتراضي: 4370">
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
<button type="submit" name="save_settings" class="btn btn-primary"><i class="fas fa-save me-1"></i> حفظ الإعدادات</button>

View File

@ -253,20 +253,20 @@ if (isset($_GET['id'])) {
<?php endif; ?>
<?php foreach ($mails as $mail): ?>
<tr>
<td class="ps-4"><span class="fw-bold text-primary"><?= htmlspecialchars($mail['ref_no']) ?></span></td>
<td class="ps-4"><span class="fw-bold text-primary"><?= htmlspecialchars($mail['ref_no'] ?? '') ?></span></td>
<td><?= date('Y-m-d', strtotime($mail['date_registered'])) ?></td>
<td>
<div class="fw-semibold text-truncate" style="max-width: 250px;"><?= htmlspecialchars($mail['subject']) ?></div>
<div class="fw-semibold text-truncate" style="max-width: 250px;"><?= htmlspecialchars($mail['subject'] ?? '') ?></div>
<?php if ($mail['attachment_names']): ?>
<span class="badge bg-light text-muted fw-normal" style="font-size: 0.65rem;">
<i class="fas fa-paperclip me-1"></i> <?= count(explode('|||', $mail['attachment_names'])) ?> مرفقات
</span>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($mail['sender']) ?></td>
<td><?= htmlspecialchars($mail['sender'] ?? '') ?></td>
<td>
<span class="badge rounded-pill" style="background-color: <?= $mail['status_color'] ?>20; color: <?= $mail['status_color'] ?>;">
<i class="fas fa-circle me-1 small"></i> <?= htmlspecialchars($mail['status_name']) ?>
<i class="fas fa-circle me-1 small"></i> <?= htmlspecialchars($mail['status_name'] ?? '') ?>
</span>
</td>
<td>
@ -277,7 +277,7 @@ if (isset($_GET['id'])) {
<span class="small"><?= htmlspecialchars($mail['assigned_to_name'] ?: 'غير محدد') ?></span>
</div>
</td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($mail['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($mail['created_by'] ?? $mail['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($mail['updated_by'] ?? null)) ?></small></td>
<td class="text-center pe-4">
<div class="btn-group shadow-sm rounded">

View File

@ -1,21 +1,22 @@
<?php if (isLoggedIn()): ?>
<?php if (isLoggedIn() && empty($hide_layout)): ?>
</main><!-- Close main-content -->
<?php endif; ?>
<?php if (empty($hide_layout)): ?>
<footer class="footer mt-auto py-4 bg-white border-top">
<div class="container-fluid px-md-4 text-center">
<div class="d-flex flex-column align-items-center">
<?php if (!empty($sys_settings['site_footer'])): ?>
<div class="mb-3 text-secondary" style="max-width: 800px; line-height: 1.6;">
<?= nl2br(htmlspecialchars($sys_settings['site_footer'])) ?>
<?= nl2br(htmlspecialchars($sys_settings['site_footer'] ?? '')) ?>
</div>
<?php endif; ?>
<span class="text-muted small mb-1">
&copy; <?= date('Y') ?> <?= htmlspecialchars($sys_settings['site_name']) ?>. جميع الحقوق محفوظة.
&copy; <?= date('Y') ?> <?= htmlspecialchars($sys_settings['site_name'] ?? '') ?>. جميع الحقوق محفوظة.
</span>
<div class="d-flex align-items-center gap-3">
<span class="badge bg-secondary opacity-50 fw-normal" style="font-size: 0.65rem;">نسخة النظام 1.3.0</span>
<span class="badge bg-secondary opacity-50 fw-normal" style="font-size: 0.65rem;">نسخة النظام <?= htmlspecialchars($sys_settings['site_version'] ?? '1.3.0') ?></span>
<?php if (isAdmin()): ?>
<a href="charity-settings.php" onclick="localStorage.setItem('activeSettingsTab', '#general');" class="text-muted text-decoration-none small hover-primary border-start ps-3">
<i class="fas fa-cog me-1"></i> الإعدادات
@ -28,6 +29,7 @@
</div>
</div>
</footer>
<?php endif; ?>
<style>
.hover-primary:hover {

View File

@ -51,7 +51,7 @@ if (isLoggedIn()) {
}
// Auth Check (after fetch to ensure session is updated)
if (!isLoggedIn() && basename($_SERVER['PHP_SELF']) !== 'login.php' && basename($_SERVER['PHP_SELF']) !== 'forgot_password.php' && basename($_SERVER['PHP_SELF']) !== 'install.php') {
if (!isLoggedIn() && basename($_SERVER['PHP_SELF']) !== 'login.php' && basename($_SERVER['PHP_SELF']) !== 'forgot_password.php' && basename($_SERVER['PHP_SELF']) !== 'install.php' && basename($_SERVER['PHP_SELF']) !== 'index.php') {
redirect('login.php');
}
@ -77,10 +77,13 @@ $committees_pages = ["committees.php", "view_committee.php", "committee_reports.
$is_committees_open = in_array($cp, $committees_pages);
$events_pages = ['events.php'];
$is_events_open = in_array($cp, $events_pages);
$meetings_pages = ['meetings.php'];
$is_meetings_open = in_array($cp, $meetings_pages);
$admin_pages = ['index.php', 'users.php', 'charity-settings.php', 'charity_members.php', 'charity_plans.php'];
$admin_pages = ['admin_dashboard.php', 'users.php', 'charity-settings.php', 'charity_members.php', 'charity_plans.php'];
$is_admin_open = in_array($cp, $admin_pages);
?>
<!DOCTYPE html>
@ -88,7 +91,7 @@ $is_admin_open = in_array($cp, $admin_pages);
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($sys_settings['site_name']) ?></title>
<title><?= htmlspecialchars($sys_settings['site_name'] ?? '') ?></title>
<!-- Bootstrap 5 RTL -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css">
@ -199,7 +202,7 @@ $is_admin_open = in_array($cp, $admin_pages);
</head>
<body>
<?php if (isLoggedIn()): ?>
<?php if (isLoggedIn() && empty($hide_layout)): ?>
<!-- Sidebar -->
<div class="sidebar d-flex flex-column" id="sidebar">
<div class="p-3 text-center border-bottom border-secondary">
@ -207,7 +210,7 @@ $is_admin_open = in_array($cp, $admin_pages);
<?php if (!empty($sys_settings['site_logo'])): ?>
<img src="<?= $sys_settings['site_logo'] ?>" alt="Logo" class="img-fluid mb-2" style="max-height: 50px;">
<?php endif; ?>
<h5 class="mb-0 fw-bold"><?= htmlspecialchars($sys_settings['site_name']) ?></h5>
<h5 class="mb-0 fw-bold"><?= htmlspecialchars($sys_settings['site_name'] ?? '') ?></h5>
</a>
</div>
@ -521,6 +524,26 @@ $is_admin_open = in_array($cp, $admin_pages);
</li>
<?php endif; ?>
<!-- Events Group -->
<?php if (canView('events')): ?>
<li class="nav-item">
<button class="sidebar-group-btn <?= $is_events_open ? '' : 'collapsed' ?>" type="button" data-bs-toggle="collapse" data-bs-target="#menu-events" aria-expanded="<?= $is_events_open ? 'true' : 'false' ?>">
<span class="group-content group-events" style="color: #6f42c1;">
<i class="fas fa-calendar-alt"></i> التقويم والأحداث
</span>
<i class="fas fa-chevron-down arrow-icon"></i>
</button>
<div class="collapse <?= $is_events_open ? 'show' : '' ?>" id="menu-events">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= $cp == 'events.php' ? 'active' : '' ?>" href="events.php">
التقويم
</a>
</li>
</ul>
</div>
</li>
<?php endif; ?>
<!-- Admin Group -->
<?php if (canView('users') || canView('settings') || isAdmin() || canView('committees')): ?>
<li class="nav-item">
@ -547,7 +570,7 @@ $is_admin_open = in_array($cp, $admin_pages);
<?php if (isAdmin()): ?>
<li class="nav-item">
<a class="nav-link <?= $cp == 'index.php' ? 'active' : '' ?>" href="index.php">
<a class="nav-link <?= $cp == 'admin_dashboard.php' ? 'active' : '' ?>" href="admin_dashboard.php">
إحصائيات النظام
</a>
</li>
@ -575,7 +598,7 @@ $is_admin_open = in_array($cp, $admin_pages);
</ul>
<div class="mt-auto p-3 text-center opacity-50 small">
&copy; <?= date('Y') ?> <?= htmlspecialchars($sys_settings['site_name']) ?>
&copy; <?= date('Y') ?> <?= htmlspecialchars($sys_settings['site_name'] ?? '') ?>
</div>
</div>

View File

@ -65,7 +65,9 @@ function canViewInternal() {
// Added for auditing display
function getAuditUserName($user_id) {
if (!$user_id) return 'غير متوفر';
// Debugging modification to see what was actually passed
if ($user_id === null || $user_id === '') return 'غير متوفر (Empty)';
static $userCache = null;
if ($userCache === null) {
$userCache = [];
@ -76,5 +78,6 @@ function getAuditUserName($user_id) {
}
} catch(Exception $e) {}
}
return $userCache[$user_id] ?? '-';
}
return $userCache[$user_id] ?? 'غير معروف (ID: ' . htmlspecialchars($user_id ?? '') . ')';
}

View File

@ -24,6 +24,7 @@ if (!function_exists('get_settings')) {
'site_phone' => $charity['charity_phone'] ?? '',
'site_address' => $charity['charity_address'] ?? '',
'site_logo' => $charity['charity_logo'] ?? '',
'site_version' => $charity['site_version'] ?? '1.3.0',
'site_favicon' => $charity['charity_favicon'] ?? '',
'site_maintenance' => (bool)($charity['site_maintenance'] ?? 0),
'site_footer' => $charity['site_footer'] ?? '',

471
index.php
View File

@ -1,333 +1,174 @@
<?php
$hide_layout = true;
require_once __DIR__ . '/includes/header.php';
// Role-based routing: Admins stay here, others go to their dashboard
if (!isAdmin()) {
redirect('user_dashboard.php');
}
$user_id = $_SESSION['user_id'];
$is_admin = isAdmin();
// Stats - Total counts from separate tables
$total_inbound = canView('inbound') ? db()->query("SELECT COUNT(*) FROM inbound_mail")->fetchColumn() : 0;
$total_outbound = canView('outbound') ? db()->query("SELECT COUNT(*) FROM outbound_mail")->fetchColumn() : 0;
// Fetch statuses for badge and count
$statuses_data = db()->query("SELECT * FROM mailbox_statuses")->fetchAll(PDO::FETCH_UNIQUE);
$in_progress_id = null;
foreach ($statuses_data as $id => $s) {
if ($s['name'] == 'in_progress') {
$in_progress_id = $id;
break;
}
}
$in_progress_count = 0;
if ($in_progress_id) {
if (canView('inbound')) {
$stmt = db()->prepare("SELECT COUNT(*) FROM inbound_mail WHERE status_id = ?");
$stmt->execute([$in_progress_id]);
$in_progress_count += $stmt->fetchColumn();
}
if (canView('outbound')) {
$stmt = db()->prepare("SELECT COUNT(*) FROM outbound_mail WHERE status_id = ?");
$stmt->execute([$in_progress_id]);
$in_progress_count += $stmt->fetchColumn();
}
}
// My Assignments - Combine from all tables
$my_assignments = [];
$queries = [];
if (canView('inbound')) {
$queries[] = "SELECT id, 'inbound' as type, ref_no, subject, due_date, status_id, created_at FROM inbound_mail WHERE assigned_to = $user_id";
}
if (canView('outbound')) {
$queries[] = "SELECT id, 'outbound' as type, ref_no, subject, due_date, status_id, created_at FROM outbound_mail WHERE assigned_to = $user_id";
}
if (canView('internal')) {
$queries[] = "SELECT id, 'internal' as type, ref_no, subject, due_date, status_id, created_at FROM internal_mail WHERE assigned_to = $user_id";
}
if (!empty($queries)) {
$full_query = "(" . implode(") UNION ALL (", $queries) . ") ORDER BY created_at DESC LIMIT 5";
$stmt = db()->query($full_query);
$my_assignments = $stmt->fetchAll();
// Add status info to assignments
foreach ($my_assignments as &$m) {
$m['status_name'] = $statuses_data[$m['status_id']]['name'] ?? 'unknown';
$m['status_color'] = $statuses_data[$m['status_id']]['color'] ?? '#6c757d';
}
}
// Recent Mail (Global for Admin/Clerk, otherwise limited)
$recent_mail = [];
$recent_queries = [];
if (canView('inbound')) {
$recent_queries[] = "SELECT m.id, 'inbound' as type, m.ref_no, m.subject, m.due_date, m.sender, m.recipient, m.status_id, m.assigned_to, m.created_by, m.date_registered, m.created_at, u.full_name as assigned_to_name
FROM inbound_mail m LEFT JOIN users u ON m.assigned_to = u.id";
}
if (canView('outbound')) {
$recent_queries[] = "SELECT m.id, 'outbound' as type, m.ref_no, m.subject, m.due_date, m.sender, m.recipient, m.status_id, m.assigned_to, m.created_by, m.date_registered, m.created_at, u.full_name as assigned_to_name
FROM outbound_mail m LEFT JOIN users u ON m.assigned_to = u.id";
}
if (!empty($recent_queries)) {
$full_recent_query = "(" . implode(") UNION ALL (", $recent_queries) . ")";
if (!$is_admin && ($_SESSION['user_role'] ?? '') !== 'clerk') {
$full_recent_query = "SELECT * FROM ($full_recent_query) AS combined WHERE assigned_to = $user_id OR created_by = $user_id ORDER BY created_at DESC LIMIT 10";
} else {
$full_recent_query = "SELECT * FROM ($full_recent_query) AS combined ORDER BY created_at DESC LIMIT 10";
}
$stmt = db()->query($full_recent_query);
$recent_mail = $stmt->fetchAll();
// Add status info
foreach ($recent_mail as &$m) {
$m['status_name'] = $statuses_data[$m['status_id']]['name'] ?? 'unknown';
$m['status_color'] = $statuses_data[$m['status_id']]['color'] ?? '#6c757d';
}
}
function getStatusBadge($mail) {
$status_name = $mail['status_name'] ?? 'غير معروف';
$status_color = $mail['status_color'] ?? '#6c757d';
$display_name = $status_name;
if ($status_name == 'received') $display_name = 'تم الاستلام';
if ($status_name == 'in_progress') $display_name = 'قيد المعالجة';
if ($status_name == 'closed') $display_name = 'مكتمل';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name) . '</span>';
}
$is_logged_in = isLoggedIn();
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">لوحة التحكم الإدارية</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group me-2">
<?php if (canView('settings')): ?>
<a href="charity-settings.php" class="btn btn-sm btn-outline-dark"><i class="fas fa-cog me-1"></i> الإعدادات</a>
<div class="landing-page-wrapper">
<!-- Abstract Background Shapes -->
<div class="bg-shape shape-blue"></div>
<div class="bg-shape shape-green"></div>
<div class="bg-shape shape-yellow"></div>
<div class="landing-content p-4 text-center">
<!-- Logo -->
<div class="logo-container mb-4">
<?php if (!empty($sys_settings['site_logo'])): ?>
<img src="<?= htmlspecialchars($sys_settings['site_logo']) ?>" alt="Logo" class="site-logo img-fluid">
<?php else: ?>
<div class="text-primary fallback-logo">
<i class="fas fa-hands-helping fa-5x"></i>
</div>
<?php endif; ?>
<?php if (canAdd('inbound')): ?>
<a href="inbound.php?action=add" class="btn btn-sm btn-outline-primary">إضافة بريد وارد</a>
<?php endif; ?>
<?php if (canAdd('outbound')): ?>
<a href="outbound.php?action=add" class="btn btn-sm btn-outline-secondary">إضافة بريد صادر</a>
</div>
<!-- Site Name -->
<h1 class="site-title fw-bold mb-3"><?= htmlspecialchars($sys_settings['site_name'] ?? 'النظام الإداري') ?></h1>
<!-- Slogan -->
<?php if (!empty($sys_settings['site_slogan'])): ?>
<p class="site-slogan text-secondary mb-5 fs-5">
<?= htmlspecialchars($sys_settings['site_slogan']) ?>
</p>
<?php endif; ?>
<!-- Action Button -->
<div class="action-buttons mt-2">
<?php if ($is_logged_in): ?>
<a href="user_dashboard.php" class="btn btn-primary btn-lg rounded-pill px-5 py-3 shadow-sm hover-lift">
<i class="fas fa-tachometer-alt me-2"></i> الدخول إلى لوحة التحكم
</a>
<?php else: ?>
<a href="login.php" class="btn btn-primary btn-lg rounded-pill px-5 py-3 shadow-sm hover-lift">
<i class="fas fa-sign-in-alt me-2"></i> تسجيل الدخول
</a>
<?php endif; ?>
</div>
</div>
</div>
<!-- Overdue Alert -->
<?php
if (canView('reports')):
// Combine overdue counts from inbound and outbound
$overdue_count = 0;
$overdue_count += db()->query("SELECT COUNT(*) FROM inbound_mail WHERE due_date < CURDATE() AND status_id IN (SELECT id FROM mailbox_statuses WHERE name != 'closed')")->fetchColumn();
$overdue_count += db()->query("SELECT COUNT(*) FROM outbound_mail WHERE due_date < CURDATE() AND status_id IN (SELECT id FROM mailbox_statuses WHERE name != 'closed')")->fetchColumn();
<style>
/* Full Page Reset for Landing */
html, body {
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f8f9fa;
}
.landing-page-wrapper {
position: relative;
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #fdfdfd 0%, #f1f3f5 100%);
z-index: 1;
}
.landing-content {
position: relative;
z-index: 10;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 2rem;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.08);
max-width: 650px;
width: 90%;
padding: 3rem !important;
animation: fadeIn 0.8s ease-out forwards;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.site-logo {
max-height: 140px;
transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.site-logo:hover, .fallback-logo:hover {
transform: scale(1.08);
}
.site-title {
color: #2c3e50;
font-size: 2.5rem;
letter-spacing: -0.5px;
}
.site-slogan {
font-weight: 300;
line-height: 1.6;
}
.hover-lift {
transition: all 0.3s ease;
font-weight: 600;
letter-spacing: 0.5px;
}
if ($overdue_count > 0):
?>
<div class="row mb-4">
<div class="col-12">
<div class="alert alert-danger shadow-sm border-0 d-flex align-items-center justify-content-between mb-0">
<div>
<i class="fas fa-exclamation-triangle fs-4 me-3"></i>
<span class="fw-bold">هناك <?= $overdue_count ?> مهام متأخرة تتطلب انتباهك!</span>
</div>
<a href="overdue_report.php" class="btn btn-danger btn-sm">عرض التقرير</a>
</div>
</div>
</div>
<?php
endif;
endif;
?>
.hover-lift:hover {
transform: translateY(-4px);
box-shadow: 0 10px 20px rgba(13, 110, 253, 0.3) !important;
}
<!-- Stats Cards -->
<div class="row g-4 mb-4">
<?php if (canView('inbound')): ?>
<div class="col-md-3">
<div class="card h-100 p-3 shadow-sm border-0 border-start border-primary border-4">
<div class="d-flex align-items-center justify-content-between">
<div>
<h6 class="text-muted mb-1">البريد الوارد</h6>
<h3 class="fw-bold mb-0"><?= $total_inbound ?></h3>
</div>
<div class="bg-primary bg-opacity-10 p-3 rounded-circle">
<i class="fas fa-download text-primary fs-4"></i>
</div>
</div>
</div>
</div>
<?php endif; ?>
/* Abstract Background Shapes with smooth animation */
.bg-shape {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.5;
z-index: 0;
animation: float 25s infinite ease-in-out alternate;
}
<?php if (canView('outbound')): ?>
<div class="col-md-3">
<div class="card h-100 p-3 shadow-sm border-0 border-start border-success border-4">
<div class="d-flex align-items-center justify-content-between">
<div>
<h6 class="text-muted mb-1">البريد الصادر</h6>
<h3 class="fw-bold mb-0"><?= $total_outbound ?></h3>
</div>
<div class="bg-success bg-opacity-10 p-3 rounded-circle">
<i class="fas fa-upload text-success fs-4"></i>
</div>
</div>
</div>
</div>
<?php endif; ?>
.shape-blue {
width: 50vw;
height: 50vw;
background: #0d6efd; /* Bootstrap Primary */
top: -15%;
right: -10%;
animation-delay: 0s;
}
<?php if (canView('inbound') || canView('outbound')): ?>
<div class="col-md-3">
<div class="card h-100 p-3 shadow-sm border-0 border-start border-info border-4">
<div class="d-flex align-items-center justify-content-between">
<div>
<h6 class="text-muted mb-1">قيد المعالجة</h6>
<h3 class="fw-bold mb-0"><?= $in_progress_count ?></h3>
</div>
<div class="bg-info bg-opacity-10 p-3 rounded-circle">
<i class="fas fa-clock text-info fs-4"></i>
</div>
</div>
</div>
</div>
<?php endif; ?>
.shape-green {
width: 45vw;
height: 45vw;
background: #198754; /* Bootstrap Success */
bottom: -20%;
left: -15%;
animation-delay: -7s;
}
<?php if (canView('users')): ?>
<div class="col-md-3">
<div class="card h-100 p-3 shadow-sm border-0 border-start border-warning border-4">
<div class="d-flex align-items-center justify-content-between">
<div>
<h6 class="text-muted mb-1">المستخدمين</h6>
<h3 class="fw-bold mb-0"><?= db()->query("SELECT COUNT(*) FROM users")->fetchColumn() ?></h3>
</div>
<div class="bg-warning bg-opacity-10 p-3 rounded-circle">
<i class="fas fa-users text-warning fs-4"></i>
</div>
</div>
</div>
</div>
<?php endif; ?>
</div>
.shape-yellow {
width: 30vw;
height: 30vw;
background: #ffc107; /* Bootstrap Warning */
top: 30%;
left: 20%;
animation-delay: -14s;
}
<?php if (!empty($my_assignments)): ?>
<!-- My Assignments Section -->
<div class="card shadow-sm border-0 mb-4 bg-primary bg-opacity-10 border-top border-primary border-3">
<div class="card-header bg-transparent py-3 border-0">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0 fw-bold text-primary"><i class="fas fa-tasks me-2"></i> مهامي الحالية</h5>
<span class="badge bg-primary rounded-pill"><?= count($my_assignments) ?></span>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<tbody>
<?php foreach ($my_assignments as $mail): ?>
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>&type=<?= $mail['type'] ?>'">
<td class="ps-4" width="120">
<small class="text-muted d-block">رقم القيد</small>
<span class="fw-bold text-primary"><?= $mail['ref_no'] ?></span>
</td>
<td>
<small class="text-muted d-block">الموضوع</small>
<span class="fw-bold"><?= htmlspecialchars($mail['subject']) ?></span>
</td>
<td>
<small class="text-muted d-block">الموعد النهائي</small>
<?php if ($mail['due_date']): ?>
<span class="<?= (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed') ? 'text-danger fw-bold' : '' ?>">
<?= $mail['due_date'] ?>
</span>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td class="text-center">
<small class="text-muted d-block mb-1">الحالة</small>
<?= getStatusBadge($mail) ?>
</td>
<td class="pe-4 text-end">
<i class="fas fa-chevron-left text-primary"></i>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
@keyframes float {
0% { transform: translate(0, 0) scale(1); }
33% { transform: translate(3%, 5%) scale(1.05); }
66% { transform: translate(-2%, 8%) scale(0.95); }
100% { transform: translate(-5%, -2%) scale(1.02); }
}
<?php if (!empty($recent_mail)): ?>
<!-- Recent Mail -->
<div class="card shadow-sm border-0 mb-4">
<div class="card-header bg-white py-3">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0 fw-bold"><?= $is_admin ? 'آخر المراسلات المسجلة' : 'آخر المراسلات' ?></h5>
<a href="inbound.php" class="btn btn-sm btn-link text-decoration-none">عرض الكل</a>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="ps-4">رقم القيد</th>
<th>النوع</th>
<th>الموضوع</th>
<th>الموعد النهائي</th>
<th>المرسل/المستلم</th>
<th>المسؤول</th>
<th>الحالة</th>
<th class="pe-4 text-center">التاريخ</th>
</tr>
</thead>
<tbody>
<?php foreach ($recent_mail as $mail): ?>
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>&type=<?= $mail['type'] ?>'">
<td class="ps-4 fw-bold text-primary"><?= $mail['ref_no'] ?></td>
<td>
<?php if ($mail['type'] == 'inbound'): ?>
<span class="text-primary"><i class="fas fa-arrow-down me-1"></i> وارد</span>
<?php else: ?>
<span class="text-success"><i class="fas fa-arrow-up me-1"></i> صادر</span>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($mail['subject']) ?></td>
<td>
<?php if ($mail['due_date']): ?>
<small class="<?= (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed') ? 'text-danger fw-bold' : 'text-muted' ?>">
<?= $mail['due_date'] ?>
</small>
<?php else: ?>
<small class="text-muted">-</small>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($mail['sender'] ?: $mail['recipient']) ?></td>
<td>
<?php if ($mail['assigned_to_name']): ?>
<small><i class="fas fa-user-tag me-1 text-muted"></i> <?= htmlspecialchars($mail['assigned_to_name']) ?></small>
<?php else: ?>
<small class="text-muted">غير معين</small>
<?php endif; ?>
</td>
<td><?= getStatusBadge($mail) ?></td>
<td class="pe-4 text-center"><?= date('Y-m-d', strtotime($mail['date_registered'])) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
/* Mobile Adjustments */
@media (max-width: 576px) {
.site-title { font-size: 2rem; }
.landing-content { padding: 2rem !important; }
.site-logo { max-height: 100px; }
}
</style>
<?php require_once __DIR__ . '/includes/footer.php'; ?>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -68,7 +68,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$content .= "}\n";
if (file_put_contents($config_file, $content)) {
header('Location: ' . htmlspecialchars($_SERVER['SCRIPT_NAME']) . '?step=3');
header('Location: ' . htmlspecialchars($_SERVER['SCRIPT_NAME'] ?? '') . '?step=3');
exit;
} else {
$error = "Failed to write configuration file to $config_file. Please check permissions.";
@ -118,7 +118,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (empty($sql)) continue;
// Split SQL into individual statements by ; followed by newline
$statements = preg_split('/;(?:\\s*[
$statements = preg_split('/;(?:\\s*[
]+)/', $sql);
$file_success = true;
@ -168,7 +168,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (empty($errors)) {
$success = "Successfully applied migrations.";
header('Location: ' . htmlspecialchars($_SERVER['SCRIPT_NAME']) . '?step=4');
header('Location: ' . htmlspecialchars($_SERVER['SCRIPT_NAME'] ?? '') . '?step=4');
exit;
} else {
$error = "Applied migrations, but some errors occurred:<br><ul><li>" . implode('</li><li>', $errors) . "</li></ul>";
@ -199,7 +199,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pdo->exec("INSERT IGNORE INTO charity_settings (id, charity_name) VALUES (1, 'Admin Panel')");
$pdo->exec("INSERT IGNORE INTO smtp_settings (id, is_enabled) VALUES (1, 0)");
header('Location: ' . htmlspecialchars($_SERVER['SCRIPT_NAME']) . '?step=5');
header('Location: ' . htmlspecialchars($_SERVER['SCRIPT_NAME'] ?? '') . '?step=5');
exit;
} catch (Throwable $e) {
$error = "Failed to create admin account: " . $e->getMessage();
@ -263,7 +263,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
</ul>
<div class="d-grid">
<?php if ($all_requirements_met): ?>
<a href="<?= htmlspecialchars($_SERVER['SCRIPT_NAME']) ?>?step=2" class="btn btn-primary">Next: Database Config</a>
<a href="<?= htmlspecialchars($_SERVER['SCRIPT_NAME'] ?? '') ?>?step=2" class="btn btn-primary">Next: Database Config</a>
<?php else:
echo "<button class=\"btn btn-secondary\" disabled>Fix requirements to continue</button>";
endif; ?>
@ -271,7 +271,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<?php elseif ($step === 2): ?>
<h4>Step 2: Database Connection</h4>
<form method="POST" action="<?= htmlspecialchars($_SERVER['SCRIPT_NAME']) ?>?step=2">
<form method="POST" action="<?= htmlspecialchars($_SERVER['SCRIPT_NAME'] ?? '') ?>?step=2">
<div class="mb-3">
<label class="form-label">Database Host</label>
<input type="text" name="db_host" class="form-control" value="127.0.0.1" required>
@ -296,7 +296,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<?php elseif ($step === 3): ?>
<h4>Step 3: Database Migrations</h4>
<p>We will now run the SQL scripts to set up your database tables.</p>
<form method="POST" action="<?= htmlspecialchars($_SERVER['SCRIPT_NAME']) ?>?step=3">
<form method="POST" action="<?= htmlspecialchars($_SERVER['SCRIPT_NAME'] ?? '') ?>?step=3">
<div class="d-grid">
<button type="submit" class="btn btn-primary">Run Migrations</button>
</div>
@ -304,7 +304,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<?php elseif ($step === 4): ?>
<h4>Step 4: Admin Account</h4>
<form method="POST" action="<?= htmlspecialchars($_SERVER['SCRIPT_NAME']) ?>?step=4">
<form method="POST" action="<?= htmlspecialchars($_SERVER['SCRIPT_NAME'] ?? '') ?>?step=4">
<div class="mb-3">
<label class="form-label">Admin Username</label>
<input type="text" name="admin_user" class="form-control" value="admin" required>

View File

@ -3,7 +3,7 @@ require_once __DIR__ . '/includes/header.php';
// Every logged-in user can access their own internal mail if they have permission
if (!canView('internal')) {
redirect('index.php');
redirect('user_dashboard.php');
}
$user_id = $_SESSION['user_id'];
@ -55,7 +55,7 @@ function getStatusBadgeInternal($mail) {
if ($status_name == 'in_progress') $display_name = 'قيد المعالجة';
if ($status_name == 'closed') $display_name = 'مؤرشف';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name) . '</span>';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name ?? '') . '</span>';
}
?>
@ -72,7 +72,7 @@ function getStatusBadgeInternal($mail) {
<?php if ($success): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?= htmlspecialchars($success) ?>
<?= htmlspecialchars($success ?? '') ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
@ -83,7 +83,7 @@ function getStatusBadgeInternal($mail) {
<div class="col-md-6">
<div class="input-group">
<span class="input-group-text bg-light border-end-0"><i class="fas fa-search text-muted"></i></span>
<input type="text" name="search" class="form-control border-start-0" placeholder="بحث في الموضوع، الرسالة، أو المرسل..." value="<?= htmlspecialchars($search) ?>">
<input type="text" name="search" class="form-control border-start-0" placeholder="بحث في الموضوع، الرسالة، أو المرسل..." value="<?= htmlspecialchars($search ?? '') ?>">
<button type="submit" class="btn btn-primary">بحث</button>
</div>
</div>
@ -126,14 +126,14 @@ function getStatusBadgeInternal($mail) {
</div>
</td>
<td>
<div class="fw-bold"><?= htmlspecialchars($msg['subject']) ?></div>
<div class="fw-bold"><?= htmlspecialchars($msg['subject'] ?? '') ?></div>
<small class="text-muted text-truncate d-inline-block" style="max-width: 300px;">
<?= strip_tags($msg['description']) ?>
</small>
</td>
<td>
<?php if (!empty($msg['attachment_names'])): ?>
<small class="text-muted"><i class="fas fa-paperclip me-1"></i> <?= htmlspecialchars($msg['attachment_names']) ?></small>
<small class="text-muted"><i class="fas fa-paperclip me-1"></i> <?= htmlspecialchars($msg['attachment_names'] ?? '') ?></small>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
@ -142,7 +142,7 @@ function getStatusBadgeInternal($mail) {
<small class="text-muted"><?= date('Y-m-d H:i', strtotime($msg['created_at'])) ?></small>
</td>
<td><?= getStatusBadgeInternal($msg) ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($msg['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($msg['created_by'] ?? $msg['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($msg['updated_by'] ?? null)) ?></small></td>
<td class="pe-4 text-center">
<a href="view_mail.php?id=<?= $msg['id'] ?>&type=internal" class="btn btn-sm btn-light rounded-pill px-3">عرض</a>

View File

@ -3,7 +3,7 @@ require_once __DIR__ . '/includes/header.php';
require_once __DIR__ . '/m_services/MailService.php';
if (!canView('internal')) {
redirect('index.php');
redirect('user_dashboard.php');
}
$user_id = $_SESSION['user_id'];
@ -67,8 +67,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
$htmlBody = "
<div dir='rtl' style='font-family: Arial, sans-serif;'>
<h3>لديك رسالة داخلية جديدة</h3>
<p><strong>الموضوع:</strong> " . htmlspecialchars($subject) . "</p>
<p><strong>المرسل:</strong> " . htmlspecialchars($_SESSION['name']) . "</p>
<p><strong>الموضوع:</strong> " . htmlspecialchars($subject ?? '') . "</p>
<p><strong>المرسل:</strong> " . htmlspecialchars($_SESSION['name'] ?? '') . "</p>
<hr>
<div>" . $description . "</div>
<br>
@ -150,7 +150,7 @@ function getStatusBadgeInternal($mail) {
if ($status_name == 'in_progress') $display_name = 'قيد المتابعة';
if ($status_name == 'closed') $display_name = 'مؤرشفة';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name) . '</span>';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name ?? '') . '</span>';
}
?>
@ -167,14 +167,14 @@ function getStatusBadgeInternal($mail) {
<?php if ($success): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?= htmlspecialchars($success) ?>
<?= htmlspecialchars($success ?? '') ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?= htmlspecialchars($error) ?>
<?= htmlspecialchars($error ?? '') ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
@ -185,7 +185,7 @@ function getStatusBadgeInternal($mail) {
<div class="col-md-6">
<div class="input-group">
<span class="input-group-text bg-light border-end-0"><i class="fas fa-search text-muted"></i></span>
<input type="text" name="search" class="form-control border-start-0" placeholder="بحث في الموضوع، الرسالة، أو المستلم..." value="<?= htmlspecialchars($search) ?>">
<input type="text" name="search" class="form-control border-start-0" placeholder="بحث في الموضوع، الرسالة، أو المستلم..." value="<?= htmlspecialchars($search ?? '') ?>">
<button type="submit" class="btn btn-primary">بحث</button>
</div>
</div>
@ -228,14 +228,14 @@ function getStatusBadgeInternal($mail) {
</div>
</td>
<td>
<div class="fw-bold"><?= htmlspecialchars($msg['subject']) ?></div>
<div class="fw-bold"><?= htmlspecialchars($msg['subject'] ?? '') ?></div>
<small class="text-muted text-truncate d-inline-block" style="max-width: 300px;">
<?= strip_tags($msg['description']) ?>
</small>
</td>
<td>
<?php if (!empty($msg['attachment_names'])): ?>
<small class="text-muted"><i class="fas fa-paperclip me-1"></i> <?= htmlspecialchars($msg['attachment_names']) ?></small>
<small class="text-muted"><i class="fas fa-paperclip me-1"></i> <?= htmlspecialchars($msg['attachment_names'] ?? '') ?></small>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
@ -244,7 +244,7 @@ function getStatusBadgeInternal($mail) {
<small class="text-muted"><?= date('Y-m-d H:i', strtotime($msg['created_at'])) ?></small>
</td>
<td><?= getStatusBadgeInternal($msg) ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($msg['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($msg['created_by'] ?? $msg['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($msg['updated_by'] ?? null)) ?></small></td>
<td class="pe-4 text-center">
<a href="view_mail.php?id=<?= $msg['id'] ?>&type=internal" class="btn btn-sm btn-light rounded-pill px-3">عرض</a>

View File

@ -40,9 +40,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<div class="text-center mb-4">
<a href="index.php" class="text-decoration-none text-dark d-block">
<?php if (!empty($sys_settings['site_logo'])): ?>
<img src="<?php echo htmlspecialchars($sys_settings['site_logo']); ?>" alt="Logo" class="img-fluid mb-3" style="max-height: 80px;">
<img src="<?php echo htmlspecialchars($sys_settings['site_logo'] ?? ''); ?>" alt="Logo" class="img-fluid mb-3" style="max-height: 80px;">
<?php endif; ?>
<h4 class="fw-bold mb-0"><?php echo htmlspecialchars($sys_settings['site_name']); ?></h4>
<h4 class="fw-bold mb-0"><?php echo htmlspecialchars($sys_settings['site_name'] ?? ''); ?></h4>
<p class="text-danger mb-0 fw-bold">نظام إدارة الفرق التطوعية ولجان الزكاة</p>
</a>
<p class="text-muted small">يرجى إدخال بيانات الاعتماد الخاصة بك</p>

View File

@ -4,7 +4,7 @@ require_once __DIR__ . '/includes/header.php';
require_once __DIR__ . '/includes/pagination.php';
if (!canView('meetings')) {
redirect('index.php');
redirect('user_dashboard.php');
}
$error = '';
@ -190,7 +190,7 @@ if (isset($_SESSION['success'])) {
<div class="col-md-3">
<label class="form-label">بحث</label>
<div class="input-group">
<input type="text" name="search" class="form-control" placeholder="عنوان، وصف، مكان..." value="<?= htmlspecialchars($search) ?>">
<input type="text" name="search" class="form-control" placeholder="عنوان، وصف، مكان..." value="<?= htmlspecialchars($search ?? '') ?>">
<button class="btn btn-primary" type="submit"><i class="fas fa-search"></i></button>
</div>
</div>
@ -240,9 +240,9 @@ if (isset($_SESSION['success'])) {
?>
<tr>
<td class="ps-4 fw-bold">
<?= htmlspecialchars($meeting['title']) ?>
<?= htmlspecialchars($meeting['title'] ?? '') ?>
<?php if ($agenda_preview): ?>
<div class="small text-muted fw-normal text-truncate" style="max-width: 250px;"><?= htmlspecialchars($agenda_preview) ?></div>
<div class="small text-muted fw-normal text-truncate" style="max-width: 250px;"><?= htmlspecialchars($agenda_preview ?? '') ?></div>
<?php endif; ?>
</td>
<td>
@ -251,14 +251,14 @@ if (isset($_SESSION['success'])) {
</td>
<td>
<?php if ($meeting['location']): ?>
<i class="fas fa-map-marker-alt text-danger me-1"></i> <?= htmlspecialchars($meeting['location']) ?>
<i class="fas fa-map-marker-alt text-danger me-1"></i> <?= htmlspecialchars($meeting['location'] ?? '') ?>
<?php else: ?>
-
<?php endif; ?>
</td>
<td><?= htmlspecialchars($meeting['created_by_name']) ?></td>
<td><?= htmlspecialchars($meeting['created_by_name'] ?? '') ?></td>
<td><span class="badge <?= $status_class ?>"><?= $status_text ?></span></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($meeting['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($meeting['created_by'] ?? $meeting['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($meeting['updated_by'] ?? null)) ?></small></td>
<td class="text-center">
<?php if (canEdit('meetings')): ?>

View File

@ -93,10 +93,10 @@ $requests = $stmt->fetchAll();
</div>
<?php if ($error): ?>
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
<div class="alert alert-danger"><?= htmlspecialchars($error ?? '') ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?= htmlspecialchars($success) ?></div>
<div class="alert alert-success"><?= htmlspecialchars($success ?? '') ?></div>
<?php endif; ?>
<div class="card shadow-sm">
@ -137,7 +137,7 @@ $requests = $stmt->fetchAll();
من <?= $req['start_date'] ?><br>إلى <?= $req['end_date'] ?>
</td>
<td><?= $req['days_count'] ?> يوم</td>
<td class="text-truncate" style="max-width: 150px;"><?= htmlspecialchars($req['reason']) ?></td>
<td class="text-truncate" style="max-width: 150px;"><?= htmlspecialchars($req['reason'] ?? '') ?></td>
<td class="small"><?= date('Y-m-d', strtotime($req['created_at'])) ?></td>
<td>
<?php

View File

@ -242,23 +242,23 @@ if (isset($_GET['id'])) {
<?php endif; ?>
<?php foreach ($mails as $mail): ?>
<tr>
<td class="ps-4"><span class="fw-bold text-primary"><?= htmlspecialchars($mail['ref_no']) ?></span></td>
<td class="ps-4"><span class="fw-bold text-primary"><?= htmlspecialchars($mail['ref_no'] ?? '') ?></span></td>
<td><?= date('Y-m-d', strtotime($mail['date_registered'])) ?></td>
<td>
<div class="fw-semibold text-truncate" style="max-width: 300px;"><?= htmlspecialchars($mail['subject']) ?></div>
<div class="fw-semibold text-truncate" style="max-width: 300px;"><?= htmlspecialchars($mail['subject'] ?? '') ?></div>
<?php if ($mail['attachment_names']): ?>
<span class="badge bg-light text-muted fw-normal" style="font-size: 0.65rem;">
<i class="fas fa-paperclip me-1"></i> <?= count(explode('|||', $mail['attachment_names'])) ?> مرفقات
</span>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($mail['recipient']) ?></td>
<td><?= htmlspecialchars($mail['recipient'] ?? '') ?></td>
<td>
<span class="badge rounded-pill" style="background-color: <?= $mail['status_color'] ?>20; color: <?= $mail['status_color'] ?>;">
<i class="fas fa-circle me-1 small"></i> <?= htmlspecialchars($mail['status_name']) ?>
<i class="fas fa-circle me-1 small"></i> <?= htmlspecialchars($mail['status_name'] ?? '') ?>
</span>
</td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($mail['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($mail['created_by'] ?? $mail['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($mail['updated_by'] ?? null)) ?></small></td>
<td class="text-center pe-4">
<div class="btn-group shadow-sm rounded">

View File

@ -2,7 +2,7 @@
require_once 'includes/header.php';
if (!canView('reports')) {
redirect('index.php');
redirect('user_dashboard.php');
}
$type_filter = $_GET['type'] ?? '';
@ -64,7 +64,7 @@ function getStatusBadgeForReport($item) {
if ($status_name == 'in_progress') $display_name = 'قيد المعالجة';
if ($status_name == 'closed') $display_name = 'مكتمل';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name) . '</span>';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name ?? '') . '</span>';
}
?>
@ -89,7 +89,7 @@ function getStatusBadgeForReport($item) {
<option value="">الكل</option>
<?php foreach ($users as $user): ?>
<option value="<?= $user['id'] ?>" <?= $user_filter == $user['id'] ? 'selected' : '' ?>>
<?= htmlspecialchars($user['full_name']) ?>
<?= htmlspecialchars($user['full_name'] ?? '') ?>
</option>
<?php endforeach; ?>
</select>
@ -132,13 +132,13 @@ function getStatusBadgeForReport($item) {
$diff = $today->diff($due_date)->format("%a");
?>
<tr>
<td class="fw-bold"><?= htmlspecialchars($item['ref_no']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($item['ref_no'] ?? '') ?></td>
<td>
<span class="badge bg-<?= $item['type'] == 'inbound' ? 'info' : 'warning' ?>">
<?= $item['type'] == 'inbound' ? 'وارد' : 'صادر' ?>
</span>
</td>
<td><?= htmlspecialchars($item['subject']) ?></td>
<td><?= htmlspecialchars($item['subject'] ?? '') ?></td>
<td><?= htmlspecialchars($item['assigned_name'] ?? 'غير معين') ?></td>
<td><?= getStatusBadgeForReport($item) ?></td>
<td class="text-danger fw-bold"><?= $item['due_date'] ?></td>

View File

@ -94,13 +94,13 @@ $status_labels = [
<!-- Header -->
<div class="print-header">
<div>
<h2 class="mb-1 fw-bold"><?= htmlspecialchars($settings['site_name']) ?></h2>
<h2 class="mb-1 fw-bold"><?= htmlspecialchars($settings['site_name'] ?? '') ?></h2>
<p class="mb-0 text-muted fs-5">تقرير الجمعية الشامل (الخطط، الأهداف والأعضاء)</p>
<small>تاريخ التقرير: <?= date('Y-m-d') ?></small>
</div>
<div>
<?php if (!empty($settings['site_logo'])): ?>
<img src="<?= htmlspecialchars($settings['site_logo']) ?>" class="print-logo" alt="Logo">
<img src="<?= htmlspecialchars($settings['site_logo'] ?? '') ?>" class="print-logo" alt="Logo">
<?php endif; ?>
</div>
</div>
@ -154,9 +154,9 @@ $status_labels = [
<tr>
<td style="text-align: center;"><?= $index + 1 ?></td>
<td>
<strong><?= htmlspecialchars($plan['title']) ?></strong>
<strong><?= htmlspecialchars($plan['title'] ?? '') ?></strong>
<?php if($plan['description']): ?>
<br><small class="text-muted"><?= htmlspecialchars($plan['description']) ?></small>
<br><small class="text-muted"><?= htmlspecialchars($plan['description'] ?? '') ?></small>
<?php endif; ?>
</td>
<td class="small">
@ -193,7 +193,7 @@ $status_labels = [
<?php foreach ($members as $index => $m): ?>
<tr>
<td style="text-align: center;"><?= $index + 1 ?></td>
<td><strong><?= htmlspecialchars($m['name']) ?></strong></td>
<td><strong><?= htmlspecialchars($m['name'] ?? '') ?></strong></td>
<td><?= htmlspecialchars($m['role'] ?: '-') ?></td>
<td dir="ltr" style="text-align: right;"><?= htmlspecialchars($m['phone'] ?: '-') ?></td>
<td dir="ltr" style="text-align: right;"><?= htmlspecialchars($m['email'] ?: '-') ?></td>
@ -207,7 +207,7 @@ $status_labels = [
<!-- Footer -->
<div class="mt-5 pt-3 border-top text-center text-muted small">
هذا التقرير معتمد ومستخرج آلياً من نظام إدارة الجمعية - <?= htmlspecialchars($settings['site_name']) ?>
هذا التقرير معتمد ومستخرج آلياً من نظام إدارة الجمعية - <?= htmlspecialchars($settings['site_name'] ?? '') ?>
</div>
</div>

View File

@ -103,13 +103,13 @@ usort($committees, function($a, $b) {
<!-- Header -->
<div class="print-header">
<div>
<h2 class="mb-1 fw-bold"><?= htmlspecialchars($settings['site_name']) ?></h2>
<h2 class="mb-1 fw-bold"><?= htmlspecialchars($settings['site_name'] ?? '') ?></h2>
<p class="mb-0 text-muted fs-5">تقرير اللجان وتقييم الأداء العام</p>
<small>تاريخ التقرير: <?= date('Y-m-d') ?></small>
</div>
<div>
<?php if (!empty($settings['site_logo'])): ?>
<img src="<?= htmlspecialchars($settings['site_logo']) ?>" class="print-logo" alt="Logo">
<img src="<?= htmlspecialchars($settings['site_logo'] ?? '') ?>" class="print-logo" alt="Logo">
<?php endif; ?>
</div>
</div>
@ -123,7 +123,7 @@ usort($committees, function($a, $b) {
<div class="committee-section">
<div class="committee-title d-flex justify-content-between align-items-center">
<span class="fs-5">
<?= $index + 1 ?>. <?= htmlspecialchars($c['name']) ?>
<?= $index + 1 ?>. <?= htmlspecialchars($c['name'] ?? '') ?>
</span>
<div class="score-badge">
مؤشر الأداء (KPI): <strong><?= round($c['score']) ?>%</strong>
@ -131,7 +131,7 @@ usort($committees, function($a, $b) {
</div>
<p class="text-muted small mt-2 mb-2 px-2">
<?= htmlspecialchars($c['description']) ?: 'لا يوجد وصف' ?>
<?= htmlspecialchars($c['description'] ?? '') ?: 'لا يوجد وصف' ?>
</p>
<div class="px-2 mb-3 small text-secondary">
@ -154,8 +154,8 @@ usort($committees, function($a, $b) {
<?php foreach ($c['members'] as $m_index => $m): ?>
<tr>
<td style="text-align: center;"><?= $m_index + 1 ?></td>
<td><strong><?= htmlspecialchars($m['full_name']) ?></strong></td>
<td><?= htmlspecialchars($m['role']) ?></td>
<td><strong><?= htmlspecialchars($m['full_name'] ?? '') ?></strong></td>
<td><?= htmlspecialchars($m['role'] ?? '') ?></td>
<td dir="ltr" style="text-align: right;"><?= htmlspecialchars($m['phone'] ?? '-') ?></td>
</tr>
<?php endforeach; ?>
@ -170,7 +170,7 @@ usort($committees, function($a, $b) {
<!-- Footer -->
<div class="mt-5 pt-3 border-top text-center text-muted small">
هذا التقرير معتمد ومستخرج آلياً من نظام إدارة اللجان - <?= htmlspecialchars($settings['site_name']) ?>
هذا التقرير معتمد ومستخرج آلياً من نظام إدارة اللجان - <?= htmlspecialchars($settings['site_name'] ?? '') ?>
</div>
</div>

202
print_events.php Normal file
View File

@ -0,0 +1,202 @@
<?php
require_once __DIR__ . '/db/config.php';
require_once __DIR__ . '/includes/settings.php';
require_once __DIR__ . '/includes/permissions.php';
session_start();
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
if (!canView('events')) {
die("ليس لديك صلاحية لعرض هذه الصفحة");
}
try {
$db = db();
$stmt = $db->query("SELECT * FROM events ORDER BY event_date ASC, start_time ASC");
$events = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
die("خطأ في قاعدة البيانات");
}
$settings = get_settings();
$logo_path = $settings['site_logo'] ?? '';
if (empty($logo_path) || !file_exists($logo_path)) {
if (!empty($logo_path) && file_exists('uploads/charity/' . $logo_path)) {
$logo_path = 'uploads/charity/' . $logo_path;
} else {
$possible_logos = glob('uploads/charity/*logo*.*');
if (!empty($possible_logos)) {
$logo_path = $possible_logos[0];
} else {
$logo_path = '';
}
}
}
$logo_html = '';
if ($logo_path) {
$logo_html = '<img src="' . $logo_path . '" alt="Logo" style="max-height: 80px;">';
}
?>
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>طباعة الأحداث والتقويم</title>
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@page {
size: A4;
margin: 1.5cm;
}
body {
font-family: 'Cairo', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #fff;
color: #333;
margin: 0;
padding: 20px;
direction: rtl;
}
.container {
max-width: 1000px;
margin: 0 auto;
}
.header {
text-align: center;
border-bottom: 2px solid #00827F;
padding-bottom: 20px;
margin-bottom: 30px;
}
.header h1 {
margin: 10px 0 5px;
font-size: 24px;
color: #00827F;
}
.header h2 {
margin: 5px 0;
font-size: 16px;
color: #555;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 30px;
}
th, td {
border: 1px solid #ddd;
padding: 12px 8px;
text-align: right;
}
th {
background-color: #f4f7f6;
color: #00827F;
font-weight: bold;
}
tr:nth-child(even) {
background-color: #fafafa;
}
.no-print {
position: fixed;
top: 20px;
left: 20px;
background: #00827F;
color: #fff;
padding: 10px 25px;
border: none;
border-radius: 30px;
cursor: pointer;
z-index: 1000;
font-family: 'Cairo', sans-serif;
font-weight: bold;
box-shadow: 0 4px 10px rgba(0,0,0,0.2);
text-decoration: none;
display: inline-block;
}
.date-badge {
display: inline-block;
background: #e9ecef;
padding: 4px 8px;
border-radius: 4px;
font-size: 14px;
font-weight: bold;
}
@media print {
body { padding: 0; }
.no-print { display: none; }
}
</style>
</head>
<body>
<button class="no-print" onclick="window.print()">
<i class="fas fa-print"></i> طباعة
</button>
<div class="container">
<div class="header">
<?php if ($logo_html): ?>
<div style="margin-bottom: 10px;"><?= $logo_html ?></div>
<?php endif; ?>
<h1><?= htmlspecialchars($settings['site_name'] ?? 'النظام') ?></h1>
<?php if (!empty($settings['site_slogan'])): ?>
<h2><?= htmlspecialchars($settings['site_slogan']) ?></h2>
<?php endif; ?>
<div style="margin-top: 20px; font-size: 20px; font-weight: bold;">قائمة الأحداث والفعاليات</div>
</div>
<?php if (empty($events)): ?>
<div style="text-align: center; padding: 50px; color: #777;">
لا توجد أحداث مسجلة حالياً
</div>
<?php else: ?>
<table>
<thead>
<tr>
<th width="5%">#</th>
<th width="25%">عنوان الحدث</th>
<th width="15%">التاريخ</th>
<th width="15%">الوقت</th>
<th width="15%">المكان</th>
<th width="25%">التفاصيل</th>
</tr>
</thead>
<tbody>
<?php
$count = 1;
foreach ($events as $e):
// Format date and time safely
$date_obj = date_create($e['event_date']);
$formatted_date = $date_obj ? date_format($date_obj, 'Y-m-d') : $e['event_date'];
$time_str = '';
if (!empty($e['start_time'])) {
$time_str = date('H:i', strtotime($e['start_time']));
if (!empty($e['end_time'])) {
$time_str .= ' - ' . date('H:i', strtotime($e['end_time']));
}
}
?>
<tr>
<td><?= $count++ ?></td>
<td><strong><?= htmlspecialchars($e['title'] ?? '') ?></strong></td>
<td><span class="date-badge"><?= $formatted_date ?></span></td>
<td><span dir="ltr"><?= htmlspecialchars($time_str) ?></span></td>
<td><?= htmlspecialchars($e['location'] ?? 'غير محدد') ?></td>
<td><?= nl2br(htmlspecialchars($e['description'] ?? '')) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<div style="margin-top: 30px; text-align: center; font-size: 12px; color: #999;">
تم استخراج هذا المستند إلكترونياً من النظام بتاريخ <?= date('Y-m-d H:i') ?>
</div>
</div>
</body>
</html>

View File

@ -89,7 +89,7 @@ $hijriDate = gregorianToHijri($mail['date_registered']);
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>طباعة بريد وارد - <?= htmlspecialchars($mail['ref_no']) ?></title>
<title>طباعة بريد وارد - <?= htmlspecialchars($mail['ref_no'] ?? '') ?></title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;700&display=swap" rel="stylesheet">
<style>
@ -257,17 +257,17 @@ $hijriDate = gregorianToHijri($mail['date_registered']);
<div class="header-container">
<div class="header-logo">
<?php if ($logo): ?>
<img src="<?= htmlspecialchars($logo) ?>" alt="Logo">
<img src="<?= htmlspecialchars($logo ?? '') ?>" alt="Logo">
<?php else: ?>
<div style="font-weight: bold; font-size: 26px; color: #00827F;"><?= htmlspecialchars($site_name) ?></div>
<div style="font-weight: bold; font-size: 26px; color: #00827F;"><?= htmlspecialchars($site_name ?? '') ?></div>
<?php endif; ?>
</div>
<div class="header-info">
<div class="site-name"><?= htmlspecialchars($site_name) ?></div>
<div class="site-name"><?= htmlspecialchars($site_name ?? '') ?></div>
<?php if (!empty($site_slogan)): ?>
<div class="site-slogan"><?= htmlspecialchars($site_slogan) ?></div>
<div class="site-slogan"><?= htmlspecialchars($site_slogan ?? '') ?></div>
<?php endif; ?>
<div style="font-size: 12px; color: #666;"><?= htmlspecialchars($site_address) ?></div>
<div style="font-size: 12px; color: #666;"><?= htmlspecialchars($site_address ?? '') ?></div>
</div>
</div>
</td>
@ -278,8 +278,8 @@ $hijriDate = gregorianToHijri($mail['date_registered']);
<tr>
<td>
<div class="mail-meta">
<div><strong>رقم القيد:</strong> <?= htmlspecialchars($mail['ref_no']) ?></div>
<div><strong>التاريخ:</strong> <?= htmlspecialchars($hijriDate) ?> | <?= htmlspecialchars($mail['date_registered']) ?>م</div>
<div><strong>رقم القيد:</strong> <?= htmlspecialchars($mail['ref_no'] ?? '') ?></div>
<div><strong>التاريخ:</strong> <?= htmlspecialchars($hijriDate ?? '') ?> | <?= htmlspecialchars($mail['date_registered'] ?? '') ?>م</div>
</div>
<div class="mail-content">

View File

@ -64,7 +64,7 @@ if ($logo_path) {
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>محضر اجتماع - <?= htmlspecialchars($meeting['title']) ?></title>
<title>محضر اجتماع - <?= htmlspecialchars($meeting['title'] ?? '') ?></title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
@ -187,9 +187,9 @@ if ($logo_path) {
<?php if ($logo_html): ?>
<div style="margin-bottom: 10px;"><?= $logo_html ?></div>
<?php endif; ?>
<h1><?= htmlspecialchars($settings['site_name']) ?></h1>
<h1><?= htmlspecialchars($settings['site_name'] ?? '') ?></h1>
<?php if ($settings['site_slogan']): ?>
<h2><?= htmlspecialchars($settings['site_slogan']) ?></h2>
<h2><?= htmlspecialchars($settings['site_slogan'] ?? '') ?></h2>
<?php endif; ?>
<div style="margin-top: 20px; font-size: 20px; font-weight: bold; text-decoration: underline;">محضر اجتماع رسمي</div>
</div>
@ -198,11 +198,11 @@ if ($logo_path) {
<div class="info-grid">
<div class="info-item">
<span class="info-label">عنوان الاجتماع:</span>
<?= htmlspecialchars($meeting['title']) ?>
<?= htmlspecialchars($meeting['title'] ?? '') ?>
</div>
<div class="info-item">
<span class="info-label">المنظم:</span>
<?= htmlspecialchars($meeting['created_by_name']) ?>
<?= htmlspecialchars($meeting['created_by_name'] ?? '') ?>
</div>
<div class="info-item">
<span class="info-label">التاريخ:</span>

View File

@ -89,7 +89,7 @@ $hijriDate = gregorianToHijri($mail['date_registered']);
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>طباعة بريد صادر - <?= htmlspecialchars($mail['ref_no']) ?></title>
<title>طباعة بريد صادر - <?= htmlspecialchars($mail['ref_no'] ?? '') ?></title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;700&display=swap" rel="stylesheet">
<style>
@ -257,17 +257,17 @@ $hijriDate = gregorianToHijri($mail['date_registered']);
<div class="header-container">
<div class="header-logo">
<?php if ($logo): ?>
<img src="<?= htmlspecialchars($logo) ?>" alt="Logo">
<img src="<?= htmlspecialchars($logo ?? '') ?>" alt="Logo">
<?php else: ?>
<div style="font-weight: bold; font-size: 26px; color: #00827F;"><?= htmlspecialchars($site_name) ?></div>
<div style="font-weight: bold; font-size: 26px; color: #00827F;"><?= htmlspecialchars($site_name ?? '') ?></div>
<?php endif; ?>
</div>
<div class="header-info">
<div class="site-name"><?= htmlspecialchars($site_name) ?></div>
<div class="site-name"><?= htmlspecialchars($site_name ?? '') ?></div>
<?php if (!empty($site_slogan)): ?>
<div class="site-slogan"><?= htmlspecialchars($site_slogan) ?></div>
<div class="site-slogan"><?= htmlspecialchars($site_slogan ?? '') ?></div>
<?php endif; ?>
<div style="font-size: 12px; color: #666;"><?= htmlspecialchars($site_address) ?></div>
<div style="font-size: 12px; color: #666;"><?= htmlspecialchars($site_address ?? '') ?></div>
</div>
</div>
</td>
@ -278,8 +278,8 @@ $hijriDate = gregorianToHijri($mail['date_registered']);
<tr>
<td>
<div class="mail-meta">
<div><strong>رقم القيد:</strong> <?= htmlspecialchars($mail['ref_no']) ?></div>
<div><strong>التاريخ:</strong> <?= htmlspecialchars($hijriDate) ?> | <?= htmlspecialchars($mail['date_registered']) ?>م</div>
<div><strong>رقم القيد:</strong> <?= htmlspecialchars($mail['ref_no'] ?? '') ?></div>
<div><strong>التاريخ:</strong> <?= htmlspecialchars($hijriDate ?? '') ?> | <?= htmlspecialchars($mail['date_registered'] ?? '') ?>م</div>
</div>
<div class="mail-content">

View File

@ -133,8 +133,8 @@ $recent_transactions = $stmt->fetchAll();
?>
<span class="badge <?= $b[0] ?>"><?= $b[1] ?></span>
</td>
<td class="fw-bold"><?= htmlspecialchars($t['item_name']) ?></td>
<td><?= htmlspecialchars($t['store_name']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($t['item_name'] ?? '') ?></td>
<td><?= htmlspecialchars($t['store_name'] ?? '') ?></td>
<td dir="ltr" class="text-end fw-bold"><?= number_format($t['quantity'], 2) ?></td>
<td><?= htmlspecialchars($t['user_name'] ?? '-') ?></td>
<td><?= date('Y-m-d H:i', strtotime($t['created_at'])) ?></td>

View File

@ -125,7 +125,7 @@ $history = $stmt->fetchAll();
<select name="store_id" class="form-select" required>
<option value="">-- اختر المستودع --</option>
<?php foreach ($stores as $store): ?>
<option value="<?= $store['id'] ?>"><?= htmlspecialchars($store['name']) ?></option>
<option value="<?= $store['id'] ?>"><?= htmlspecialchars($store['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -134,7 +134,7 @@ $history = $stmt->fetchAll();
<select name="item_id" class="form-select" required>
<option value="">-- اختر الصنف --</option>
<?php foreach ($items as $item): ?>
<option value="<?= $item['id'] ?>"><?= htmlspecialchars($item['name']) ?> (<?= htmlspecialchars($item['sku'] ?: '-') ?>)</option>
<option value="<?= $item['id'] ?>"><?= htmlspecialchars($item['name'] ?? '') ?> (<?= htmlspecialchars($item['sku'] ?: '-') ?>)</option>
<?php endforeach; ?>
</select>
</div>
@ -194,8 +194,8 @@ $history = $stmt->fetchAll();
<?php foreach ($history as $h): ?>
<tr>
<td class="ps-4"><?= $h['id'] ?></td>
<td class="fw-bold"><?= htmlspecialchars($h['item_name']) ?></td>
<td><?= htmlspecialchars($h['store_name']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($h['item_name'] ?? '') ?></td>
<td><?= htmlspecialchars($h['store_name'] ?? '') ?></td>
<td class="text-success fw-bold" dir="ltr">+<?= number_format($h['quantity'], 2) ?></td>
<td><?= htmlspecialchars($h['user_name'] ?? '-') ?></td>
<td><?= date('Y-m-d H:i', strtotime($h['created_at'])) ?></td>

View File

@ -173,7 +173,7 @@ $categories = db()->query("SELECT * FROM stock_categories ORDER BY name ASC")->f
<?php endif; ?>
<?php foreach ($items as $item): ?>
<tr>
<td class="ps-4 fw-bold"><?= htmlspecialchars($item['name']) ?></td>
<td class="ps-4 fw-bold"><?= htmlspecialchars($item['name'] ?? '') ?></td>
<td><?= htmlspecialchars($item['sku'] ?? '-') ?></td>
<td><span class="badge bg-secondary"><?= htmlspecialchars($item['category_name'] ?? 'عام') ?></span></td>
<td>
@ -184,8 +184,8 @@ $categories = db()->query("SELECT * FROM stock_categories ORDER BY name ASC")->f
<span class="<?= $cls ?>"><?= number_format($qty, 2) ?></span>
</td>
<td><?= number_format($item['min_quantity']) ?></td>
<td><?= htmlspecialchars($item['unit']) ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($item['created_by'] ?? null)) ?></small></td>
<td><?= htmlspecialchars($item['unit'] ?? '') ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($item['created_by'] ?? $item['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($item['updated_by'] ?? null)) ?></small></td>
<td class="text-center">
<?php if (canEdit('stock_items')): ?>
@ -238,7 +238,7 @@ $categories = db()->query("SELECT * FROM stock_categories ORDER BY name ASC")->f
<select name="category_id" id="modalCategory" class="form-select">
<option value="">-- اختر --</option>
<?php foreach ($categories as $cat): ?>
<option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['name']) ?></option>
<option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>

View File

@ -158,10 +158,10 @@ $items = db()->query("SELECT * FROM stock_items ORDER BY name ASC")->fetchAll();
<?php foreach ($loans as $loan): ?>
<tr>
<td class="fw-bold">
<?= htmlspecialchars($loan['borrower_name']) ?>
<br><small class="text-muted"><?= htmlspecialchars($loan['borrower_phone']) ?></small>
<?= htmlspecialchars($loan['borrower_name'] ?? '') ?>
<br><small class="text-muted"><?= htmlspecialchars($loan['borrower_phone'] ?? '') ?></small>
</td>
<td><?= htmlspecialchars($loan['item_name']) ?></td>
<td><?= htmlspecialchars($loan['item_name'] ?? '') ?></td>
<td class="fw-bold"><?= number_format($loan['quantity'], 2) ?></td>
<td><?= date('Y-m-d', strtotime($loan['lend_date'])) ?></td>
<td>
@ -172,7 +172,7 @@ $items = db()->query("SELECT * FROM stock_items ORDER BY name ASC")->fetchAll();
<span class="<?= $cls ?>"><?= date('Y-m-d', $due) ?></span>
</td>
<td><span class="badge bg-warning text-dark">نشط</span></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($loan['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($loan['created_by'] ?? $loan['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($loan['updated_by'] ?? null)) ?></small></td>
<td>
<form method="POST" onsubmit="return confirm('هل استلمت المواد المرجعة؟ سيتم إضافتها للمخزون.')">
@ -208,7 +208,7 @@ $items = db()->query("SELECT * FROM stock_items ORDER BY name ASC")->fetchAll();
<label class="form-label">المستودع</label>
<select name="store_id" class="form-select" required>
<?php foreach ($stores as $store): ?>
<option value="<?= $store['id'] ?>"><?= htmlspecialchars($store['name']) ?></option>
<option value="<?= $store['id'] ?>"><?= htmlspecialchars($store['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -216,7 +216,7 @@ $items = db()->query("SELECT * FROM stock_items ORDER BY name ASC")->fetchAll();
<label class="form-label">المادة</label>
<select name="item_id" class="form-select" required>
<?php foreach ($items as $item): ?>
<option value="<?= $item['id'] ?>"><?= htmlspecialchars($item['name']) ?></option>
<option value="<?= $item['id'] ?>"><?= htmlspecialchars($item['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>

View File

@ -125,7 +125,7 @@ $history = $stmt->fetchAll();
<select name="store_id" class="form-select" required>
<option value="">-- اختر المستودع --</option>
<?php foreach ($stores as $store): ?>
<option value="<?= $store['id'] ?>"><?= htmlspecialchars($store['name']) ?></option>
<option value="<?= $store['id'] ?>"><?= htmlspecialchars($store['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -134,7 +134,7 @@ $history = $stmt->fetchAll();
<select name="item_id" class="form-select" required>
<option value="">-- اختر الصنف --</option>
<?php foreach ($items as $item): ?>
<option value="<?= $item['id'] ?>"><?= htmlspecialchars($item['name']) ?> (<?= htmlspecialchars($item['sku'] ?: '-') ?>)</option>
<option value="<?= $item['id'] ?>"><?= htmlspecialchars($item['name'] ?? '') ?> (<?= htmlspecialchars($item['sku'] ?: '-') ?>)</option>
<?php endforeach; ?>
</select>
</div>
@ -210,8 +210,8 @@ $history = $stmt->fetchAll();
<span class="badge bg-danger">صرف</span>
<?php endif; ?>
</td>
<td class="fw-bold"><?= htmlspecialchars($h['item_name']) ?></td>
<td><?= htmlspecialchars($h['store_name']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($h['item_name'] ?? '') ?></td>
<td><?= htmlspecialchars($h['store_name'] ?? '') ?></td>
<td class="text-danger fw-bold" dir="ltr">-<?= number_format($h['quantity'], 2) ?></td>
<td><?= htmlspecialchars($h['user_name'] ?? '-') ?></td>
<td><?= date('Y-m-d H:i', strtotime($h['created_at'])) ?></td>

View File

@ -71,7 +71,7 @@ $items = db()->query("SELECT * FROM stock_items ORDER BY name ASC")->fetchAll();
<select name="store_id" class="form-select">
<option value="">الكل</option>
<?php foreach ($stores as $s): ?>
<option value="<?= $s['id'] ?>" <?= $store_id == $s['id'] ? 'selected' : '' ?>><?= htmlspecialchars($s['name']) ?></option>
<option value="<?= $s['id'] ?>" <?= $store_id == $s['id'] ? 'selected' : '' ?>><?= htmlspecialchars($s['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -80,7 +80,7 @@ $items = db()->query("SELECT * FROM stock_items ORDER BY name ASC")->fetchAll();
<select name="item_id" class="form-select">
<option value="">الكل</option>
<?php foreach ($items as $i): ?>
<option value="<?= $i['id'] ?>" <?= $item_id == $i['id'] ? 'selected' : '' ?>><?= htmlspecialchars($i['name']) ?></option>
<option value="<?= $i['id'] ?>" <?= $item_id == $i['id'] ? 'selected' : '' ?>><?= htmlspecialchars($i['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
@ -137,8 +137,8 @@ $items = db()->query("SELECT * FROM stock_items ORDER BY name ASC")->fetchAll();
echo $types[$t['transaction_type']] ?? $t['transaction_type'];
?>
</td>
<td><?= htmlspecialchars($t['store_name']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($t['item_name']) ?></td>
<td><?= htmlspecialchars($t['store_name'] ?? '') ?></td>
<td class="fw-bold"><?= htmlspecialchars($t['item_name'] ?? '') ?></td>
<td dir="ltr" class="text-end fw-bold">
<?php if ($t['transaction_type'] == 'in' || $t['transaction_type'] == 'return'): ?>
<span class="text-success">+<?= number_format($t['quantity'], 2) ?></span>
@ -149,7 +149,7 @@ $items = db()->query("SELECT * FROM stock_items ORDER BY name ASC")->fetchAll();
<td><?= htmlspecialchars($t['user_name'] ?? '-') ?></td>
<td class="small text-muted">
<?php if ($t['reference']): ?>
<strong>المرجع:</strong> <?= htmlspecialchars($t['reference']) ?><br>
<strong>المرجع:</strong> <?= htmlspecialchars($t['reference'] ?? '') ?><br>
<?php endif; ?>
<?= htmlspecialchars($t['notes'] ?? '') ?>
</td>

View File

@ -117,7 +117,7 @@ $categories = db()->query("SELECT * FROM stock_categories ORDER BY name ASC")->f
<?php foreach ($stores as $s): ?>
<tr>
<td><?= $s['id'] ?></td>
<td class="fw-bold"><?= htmlspecialchars($s['name']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($s['name'] ?? '') ?></td>
<td><?= htmlspecialchars($s['location'] ?? '-') ?></td>
<td><?= date('Y-m-d', strtotime($s['created_at'])) ?></td>
<td>
@ -166,7 +166,7 @@ $categories = db()->query("SELECT * FROM stock_categories ORDER BY name ASC")->f
<?php foreach ($categories as $c): ?>
<tr>
<td><?= $c['id'] ?></td>
<td class="fw-bold"><?= htmlspecialchars($c['name']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($c['name'] ?? '') ?></td>
<td><?= htmlspecialchars($c['description'] ?? '-') ?></td>
<td><?= date('Y-m-d', strtotime($c['created_at'])) ?></td>
<td>

0
test_db.php Normal file
View File

1
test_insert.php Normal file
View File

@ -0,0 +1 @@

0
test_trigger2.php Normal file
View File

0
test_trigger3.php Normal file
View File

View File

@ -29,7 +29,7 @@ $trial_balance = get_trial_balance();
$total_credit += $row['total_credit'];
?>
<tr>
<td><?= htmlspecialchars($row['account_name']) ?></td>
<td><?= htmlspecialchars($row['account_name'] ?? '') ?></td>
<td><?= number_format($row['total_debit'], 2) ?></td>
<td><?= number_format($row['total_credit'], 2) ?></td>
</tr>

View File

@ -85,7 +85,7 @@ function getStatusBadge($mail) {
if ($status_name == 'in_progress') $display_name = 'قيد المعالجة';
if ($status_name == 'closed') $display_name = 'مكتمل';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name) . '</span>';
return '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name ?? '') . '</span>';
}
?>
@ -257,7 +257,7 @@ function getStatusBadge($mail) {
<?php foreach ($my_assignments as $mail): ?>
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>&type=<?= $mail['type'] ?>'">
<td class="ps-4 fw-bold text-primary"><?= $mail['ref_no'] ?></td>
<td><?= htmlspecialchars($mail['subject']) ?></td>
<td><?= htmlspecialchars($mail['subject'] ?? '') ?></td>
<td>
<?php if ($mail['due_date']): ?>
<small class="<?= (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed') ? 'text-danger fw-bold' : 'text-muted' ?>">
@ -298,7 +298,7 @@ function getStatusBadge($mail) {
<?php foreach ($recent_activity as $act): ?>
<a href="view_mail.php?id=<?= $act['id'] ?>&type=<?= $act['type'] ?>" class="list-group-item list-group-item-action p-3 border-0 border-bottom">
<div class="d-flex w-100 justify-content-between mb-1">
<h6 class="mb-1 fw-bold text-truncate" title="<?= htmlspecialchars($act['subject']) ?>"><?= htmlspecialchars($act['subject']) ?></h6>
<h6 class="mb-1 fw-bold text-truncate" title="<?= htmlspecialchars($act['subject'] ?? '') ?>"><?= htmlspecialchars($act['subject'] ?? '') ?></h6>
<small class="text-muted"><?= date('m-d', strtotime($act['updated_at'])) ?></small>
</div>
<div class="d-flex justify-content-between align-items-center">

View File

@ -3,7 +3,7 @@ require_once __DIR__ . '/includes/header.php';
require_once __DIR__ . '/includes/pagination.php';
if (!canView('users')) {
redirect('index.php');
redirect('user_dashboard.php');
}
$error = '';
@ -35,7 +35,8 @@ $modules = [
'meetings' => 'الاجتماعات',
'committees' => 'اللجان',
'charity_members' => 'أعضاء الجمعية',
'charity_plans' => 'الخطط والأهداف'
'charity_plans' => 'الخطط والأهداف',
'events' => 'التقويم والأحداث'
];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
@ -261,8 +262,8 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
</div>
<?php endif; ?>
</td>
<td class="fw-bold"><?= htmlspecialchars($user['full_name']) ?></td>
<td><?= htmlspecialchars($user['username']) ?></td>
<td class="fw-bold"><?= htmlspecialchars($user['full_name'] ?? '') ?></td>
<td><?= htmlspecialchars($user['username'] ?? '') ?></td>
<td><?= htmlspecialchars($user['email'] ?? '-') ?></td>
<td>
<?php if ($user['role'] === 'admin'): ?>
@ -274,7 +275,7 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
<?php endif; ?>
</td>
<td><?= $user['created_at'] ?></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($user['created_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user text-primary opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($user['created_by'] ?? $user['updated_by'] ?? null)) ?></small></td>
<td><small class="text-muted"><i class="fas fa-user-edit text-warning opacity-50 me-1"></i><?= htmlspecialchars(getAuditUserName($user['updated_by'] ?? null)) ?></small></td>
<td class="pe-4 text-center">
<?php if (canEdit('users')): ?>

View File

@ -2,7 +2,7 @@
require_once __DIR__ . '/includes/header.php';
if (!canView('committees')) {
redirect('index.php');
redirect('user_dashboard.php');
}
$id = $_GET['id'] ?? 0;
@ -170,7 +170,7 @@ if ($tab === 'members') {
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">إدارة اللجنة: <?= htmlspecialchars($committee['name']) ?></h1>
<h1 class="h2">إدارة اللجنة: <?= htmlspecialchars($committee['name'] ?? '') ?></h1>
<a href="committees.php" class="btn btn-secondary shadow-sm">
<i class="fas fa-arrow-right"></i> عودة للجان
</a>
@ -190,7 +190,7 @@ if ($tab === 'members') {
</div>
<?php endif; ?>
<p class="lead text-muted"><?= nl2br(htmlspecialchars($committee['description'])) ?></p>
<p class="lead text-muted"><?= nl2br(htmlspecialchars($committee['description'] ?? '')) ?></p>
<ul class="nav nav-tabs mb-4">
<li class="nav-item">
@ -237,10 +237,10 @@ if ($tab === 'members') {
<?php if (count($members) > 0): ?>
<?php foreach ($members as $m): ?>
<tr>
<td class="ps-4 fw-bold"><?= htmlspecialchars($m['full_name']) ?></td>
<td><?= htmlspecialchars($m['email']) ?></td>
<td class="ps-4 fw-bold"><?= htmlspecialchars($m['full_name'] ?? '') ?></td>
<td><?= htmlspecialchars($m['email'] ?? '') ?></td>
<td><a href="tel:<?= htmlspecialchars($m['phone'] ?? '') ?>"><?= htmlspecialchars($m['phone'] ?? '-' ) ?></a></td>
<td><span class="badge bg-info text-dark"><?= htmlspecialchars($m['role']) ?></span></td>
<td><span class="badge bg-info text-dark"><?= htmlspecialchars($m['role'] ?? '') ?></span></td>
<td><?= $m['joined_at'] ?></td>
<td class="text-center">
<?php if (canEdit('committees')): ?>
@ -285,7 +285,7 @@ if ($tab === 'members') {
<select name="charity_member_id" class="form-select" required>
<option value="">-- اختر مستخدم --</option>
<?php foreach ($available_users as $u): ?>
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name']) ?> (<?= htmlspecialchars($u['email']) ?>)</option>
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name'] ?? '') ?> (<?= htmlspecialchars($u['email'] ?? '') ?>)</option>
<?php endforeach; ?>
</select>
</div>
@ -379,7 +379,7 @@ if ($tab === 'members') {
<?php foreach ($plans as $p): ?>
<tr>
<td class="ps-4 fw-bold">
<?= htmlspecialchars($p['title']) ?>
<?= htmlspecialchars($p['title'] ?? '') ?>
<div class="small text-muted text-truncate" style="max-width: 200px;"><?= htmlspecialchars($p['description'] ?? '') ?></div>
</td>
<td><?= $p['start_date'] ?: '-' ?></td>
@ -516,7 +516,7 @@ if ($tab === 'members') {
<?php foreach ($activities as $a): ?>
<tr>
<td class="ps-4 fw-bold">
<?= htmlspecialchars($a['title']) ?>
<?= htmlspecialchars($a['title'] ?? '') ?>
<div class="small text-muted text-truncate" style="max-width: 200px;"><?= htmlspecialchars($a['description'] ?? '') ?></div>
</td>
<td><?= $a['activity_date'] ?: '-' ?></td>

View File

@ -5,7 +5,7 @@ require_once __DIR__ . '/m_services/MailService.php';
$id = $_GET['id'] ?? 0;
$type = $_GET['type'] ?? '';
if (!$id) redirect('index.php');
if (!$id) redirect('user_dashboard.php');
// If type is not provided, try to find it in any of the tables (for backward compatibility if any links were missed)
if (!$type) {
@ -20,7 +20,7 @@ if (!$type) {
}
}
if (!$type) redirect('index.php');
if (!$type) redirect('user_dashboard.php');
$table_mail = $type . '_mail';
$table_attachments = $type . '_attachments';
@ -36,14 +36,14 @@ $stmt = db()->prepare("SELECT m.*, u1.full_name as assigned_name, u2.full_name a
$stmt->execute([$id]);
$mail = $stmt->fetch();
if (!$mail) redirect('index.php');
if (!$mail) redirect('user_dashboard.php');
// Add back the type for logic below
$mail['type'] = $type;
// Check if user has view permission for this mail type
if (!canView($type)) {
redirect('index.php');
redirect('user_dashboard.php');
}
// Security check for internal mail: only sender or recipient can view
@ -81,15 +81,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_comment'])) {
$html = "
<div dir='rtl'>
<h3>مرحباً " . htmlspecialchars($referred_user['full_name']) . "</h3>
<p>قام <strong>" . htmlspecialchars($sender_name) . "</strong> بإحالة بريد إليك مع التعليق التالي:</p>
<h3>مرحباً " . htmlspecialchars($referred_user['full_name'] ?? '') . "</h3>
<p>قام <strong>" . htmlspecialchars($sender_name ?? '') . "</strong> بإحالة بريد إليك مع التعليق التالي:</p>
<blockquote style='background: #f9f9f9; padding: 10px; border-left: 5px solid #ccc;'>
" . nl2br(htmlspecialchars($comment)) . "
" . nl2br(htmlspecialchars($comment ?? '')) . "
</blockquote>
<p><strong>تفاصيل البريد:</strong></p>
<ul>
<li><strong>رقم القيد:</strong> " . htmlspecialchars($mail['ref_no']) . "</li>
<li><strong>الموضوع:</strong> " . htmlspecialchars($mail['subject']) . "</li>
<li><strong>رقم القيد:</strong> " . htmlspecialchars($mail['ref_no'] ?? '') . "</li>
<li><strong>الموضوع:</strong> " . htmlspecialchars($mail['subject'] ?? '') . "</li>
</ul>
<p><a href='{$mail_link}' style='display: inline-block; padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px;'>عرض البريد</a></p>
</div>
@ -271,7 +271,7 @@ if ($type == 'internal') {
if ($s_name == 'in_progress') $d_name = 'قيد المعالجة';
if ($s_name == 'closed') $d_name = ($type == 'internal' ? 'مؤرشف' : 'مكتمل');
?>
<span class="badge" style="background-color: <?= $s_color ?>;"><?= htmlspecialchars($d_name) ?></span>
<span class="badge" style="background-color: <?= $s_color ?>;"><?= htmlspecialchars($d_name ?? '') ?></span>
</p>
</div>
<div class="col-12">
@ -281,7 +281,7 @@ if ($type == 'internal') {
if ($type == 'outbound' || $type == 'internal') {
echo $mail['subject'];
} else {
echo htmlspecialchars($mail['subject']);
echo htmlspecialchars($mail['subject'] ?? '');
}
?>
</div>
@ -290,11 +290,11 @@ if ($type == 'internal') {
<?php if ($type == 'internal'): ?>
<div class="col-md-6">
<label class="text-muted small">المرسل</label>
<p class="fw-bold text-primary"><?= htmlspecialchars($mail['creator_name']) ?></p>
<p class="fw-bold text-primary"><?= htmlspecialchars($mail['creator_name'] ?? '') ?></p>
</div>
<div class="col-md-6">
<label class="text-muted small">المستلم</label>
<p class="fw-bold text-success"><?= htmlspecialchars($mail['assigned_name']) ?></p>
<p class="fw-bold text-success"><?= htmlspecialchars($mail['assigned_name'] ?? '') ?></p>
</div>
<?php else: ?>
<div class="col-md-6">
@ -349,7 +349,7 @@ if ($type == 'internal') {
<select name="referred_user_id" class="form-select form-select-sm">
<option value="">-- اختر موظفاً للإحالة --</option>
<?php foreach ($all_users as $u): ?>
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name']) ?> (<?= ucfirst($u['role']) ?>)</option>
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name'] ?? '') ?> (<?= ucfirst($u['role']) ?>)</option>
<?php endforeach; ?>
</select>
</div>
@ -363,16 +363,16 @@ if ($type == 'internal') {
<div class="border-bottom pb-2 mb-2">
<div class="d-flex justify-content-between">
<div>
<span class="fw-bold text-primary"><?= htmlspecialchars($c['full_name']) ?></span>
<span class="fw-bold text-primary"><?= htmlspecialchars($c['full_name'] ?? '') ?></span>
<?php if ($c['referred_name']): ?>
<span class="badge bg-info text-dark ms-2 small">
<i class="fas fa-share ms-1"></i> إحالة إلى: <?= htmlspecialchars($c['referred_name']) ?>
<i class="fas fa-share ms-1"></i> إحالة إلى: <?= htmlspecialchars($c['referred_name'] ?? '') ?>
</span>
<?php endif; ?>
</div>
<span class="text-muted small"><?= $c['created_at'] ?></span>
</div>
<p class="mb-0 small"><?= nl2br(htmlspecialchars($c['comment'])) ?></p>
<p class="mb-0 small"><?= nl2br(htmlspecialchars($c['comment'] ?? '')) ?></p>
</div>
<?php endforeach; else: ?>
<p class="text-center text-muted small">لا توجد ردود بعد</p>