adding permission
This commit is contained in:
parent
e70adf8720
commit
118aae16b0
26
api/update_theme.php
Normal file
26
api/update_theme.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once __DIR__ . '/../db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Not authenticated']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode(file_get_contents('php://input'), true);
|
||||||
|
$theme = $data['theme'] ?? 'light';
|
||||||
|
|
||||||
|
// Validate theme
|
||||||
|
$allowed_themes = ['light', 'dark', 'midnight', 'forest'];
|
||||||
|
if (!in_array($theme, $allowed_themes)) {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Invalid theme']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt = db()->prepare("UPDATE users SET theme = ? WHERE id = ?");
|
||||||
|
$stmt->execute([$theme, $_SESSION['user_id']]);
|
||||||
|
echo json_encode(['success' => true]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||||
|
}
|
||||||
3
db/migrations/008_add_password_reset.sql
Normal file
3
db/migrations/008_add_password_reset.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
-- Add password reset token columns to users table
|
||||||
|
ALTER TABLE users ADD COLUMN reset_token VARCHAR(100) NULL;
|
||||||
|
ALTER TABLE users ADD COLUMN reset_token_expiry DATETIME NULL;
|
||||||
2
db/migrations/009_add_theme_to_users.sql
Normal file
2
db/migrations/009_add_theme_to_users.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
-- Migration: Add theme to users
|
||||||
|
ALTER TABLE users ADD COLUMN theme VARCHAR(20) DEFAULT 'light';
|
||||||
11
db/migrations/010_add_granular_permissions.sql
Normal file
11
db/migrations/010_add_granular_permissions.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-- Migration: Add granular permissions to users table
|
||||||
|
ALTER TABLE users
|
||||||
|
ADD COLUMN can_view TINYINT(1) DEFAULT 1,
|
||||||
|
ADD COLUMN can_add TINYINT(1) DEFAULT 0,
|
||||||
|
ADD COLUMN can_edit TINYINT(1) DEFAULT 0,
|
||||||
|
ADD COLUMN can_delete TINYINT(1) DEFAULT 0;
|
||||||
|
|
||||||
|
-- Set defaults for existing roles
|
||||||
|
UPDATE users SET can_view = 1, can_add = 1, can_edit = 1, can_delete = 1 WHERE role = 'admin';
|
||||||
|
UPDATE users SET can_view = 1, can_add = 1, can_edit = 1, can_delete = 0 WHERE role = 'clerk';
|
||||||
|
UPDATE users SET can_view = 1, can_add = 0, can_edit = 0, can_delete = 0 WHERE role = 'staff';
|
||||||
150
forgot_password.php
Normal file
150
forgot_password.php
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/header.php';
|
||||||
|
require_once __DIR__ . '/mail/MailService.php';
|
||||||
|
|
||||||
|
if (isLoggedIn()) {
|
||||||
|
redirect('index.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
$success = '';
|
||||||
|
$step = 'request'; // 'request' or 'reset'
|
||||||
|
|
||||||
|
// Fetch charity settings for logo/name
|
||||||
|
$stmt = db()->query("SELECT * FROM charity_settings WHERE id = 1");
|
||||||
|
$charity = $stmt->fetch();
|
||||||
|
|
||||||
|
// Check if we are in reset mode (token in URL)
|
||||||
|
$token = $_GET['token'] ?? '';
|
||||||
|
if ($token) {
|
||||||
|
$stmt = db()->prepare("SELECT * FROM users WHERE reset_token = ? AND reset_token_expiry > NOW()");
|
||||||
|
$stmt->execute([$token]);
|
||||||
|
$user = $stmt->fetch();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$step = 'reset';
|
||||||
|
} else {
|
||||||
|
$error = 'رابط استعادة كلمة المرور غير صالح أو منتهي الصلاحية.';
|
||||||
|
$step = 'request';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle POST requests
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
if (isset($_POST['request_reset'])) {
|
||||||
|
$email = trim($_POST['email'] ?? '');
|
||||||
|
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$stmt = db()->prepare("SELECT id, full_name FROM users WHERE email = ?");
|
||||||
|
$stmt->execute([$email]);
|
||||||
|
$user = $stmt->fetch();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$newToken = bin2hex(random_bytes(32));
|
||||||
|
$expiry = date('Y-m-d H:i:s', strtotime('+1 hour'));
|
||||||
|
|
||||||
|
$update = db()->prepare("UPDATE users SET reset_token = ?, reset_token_expiry = ? WHERE id = ?");
|
||||||
|
$update->execute([$newToken, $expiry, $user['id']]);
|
||||||
|
|
||||||
|
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
|
||||||
|
$host = $_SERVER['HTTP_HOST'];
|
||||||
|
$resetLink = "$protocol://$host/forgot_password.php?token=$newToken";
|
||||||
|
|
||||||
|
$subject = "استعادة كلمة المرور - " . ($charity['charity_name'] ?? 'الجمعية الخيرية');
|
||||||
|
$html = "
|
||||||
|
<div dir='rtl' style='font-family: Arial, sans-serif; text-align: right;'>
|
||||||
|
<h3>مرحباً {$user['full_name']}</h3>
|
||||||
|
<p>لقد طلبت استعادة كلمة المرور الخاصة بك. يرجى الضغط على الرابط أدناه لإعادة تعيينها:</p>
|
||||||
|
<p><a href='$resetLink' style='background: #000; color: #fff; padding: 10px 20px; text-decoration: none; border-radius: 5px;'>إعادة تعيين كلمة المرور</a></p>
|
||||||
|
<p>هذا الرابط صالح لمدة ساعة واحدة فقط.</p>
|
||||||
|
<p>إذا لم تطلب هذا، يرجى تجاهل هذه الرسالة.</p>
|
||||||
|
</div>
|
||||||
|
";
|
||||||
|
|
||||||
|
$res = MailService::sendMail($email, $subject, $html);
|
||||||
|
if ($res['success']) {
|
||||||
|
$success = 'تم إرسال رابط استعادة كلمة المرور إلى بريدك الإلكتروني.';
|
||||||
|
} else {
|
||||||
|
$error = 'فشل إرسال البريد الإلكتروني. يرجى المحاولة لاحقاً أو التواصل مع الإدارة.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For security, don't reveal if email exists, but here we can be more helpful if it's a closed admin panel
|
||||||
|
$error = 'البريد الإلكتروني غير مسجل لدينا.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$error = 'يرجى إدخال بريد إلكتروني صحيح.';
|
||||||
|
}
|
||||||
|
} elseif (isset($_POST['reset_password'])) {
|
||||||
|
$password = $_POST['password'] ?? '';
|
||||||
|
$confirm = $_POST['confirm_password'] ?? '';
|
||||||
|
|
||||||
|
if (strlen($password) < 6) {
|
||||||
|
$error = 'كلمة المرور يجب أن تكون 6 أحرف على الأقل.';
|
||||||
|
} elseif ($password !== $confirm) {
|
||||||
|
$error = 'كلمات المرور غير متطابقة.';
|
||||||
|
} else {
|
||||||
|
$hashed = password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
$update = db()->prepare("UPDATE users SET password = ?, reset_token = NULL, reset_token_expiry = NULL WHERE id = ?");
|
||||||
|
$update->execute([$hashed, $user['id']]);
|
||||||
|
$success = 'تم تغيير كلمة المرور بنجاح. يمكنك الآن <a href="login.php">تسجيل الدخول</a>.';
|
||||||
|
$step = 'completed';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="row justify-content-center align-items-center" style="min-height: 80vh;">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card p-4 shadow-sm border-0 text-center">
|
||||||
|
<div class="mb-4">
|
||||||
|
<?php if ($charity['charity_logo']): ?>
|
||||||
|
<img src="<?= htmlspecialchars($charity['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['charity_name'] ?? 'الجمعية الخيرية') ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert alert-danger"><?= $error ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($success): ?>
|
||||||
|
<div class="alert alert-success"><?= $success ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($step === 'request'): ?>
|
||||||
|
<form method="POST">
|
||||||
|
<div class="mb-3 text-start">
|
||||||
|
<label class="form-label">البريد الإلكتروني</label>
|
||||||
|
<input type="email" name="email" class="form-control" placeholder="example@domain.com" required>
|
||||||
|
<div class="form-text">أدخل البريد الإلكتروني المرتبط بحسابك.</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-grid mt-4">
|
||||||
|
<button type="submit" name="request_reset" class="btn btn-dark">إرسال رابط الاستعادة</button>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<a href="login.php" class="text-decoration-none small text-secondary">العودة لتسجيل الدخول</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php elseif ($step === 'reset'): ?>
|
||||||
|
<form method="POST">
|
||||||
|
<div class="mb-3 text-start">
|
||||||
|
<label class="form-label">كلمة المرور الجديدة</label>
|
||||||
|
<input type="password" name="password" class="form-control" required minlength="6">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3 text-start">
|
||||||
|
<label class="form-label">تأكيد كلمة المرور</label>
|
||||||
|
<input type="password" name="confirm_password" class="form-control" required minlength="6">
|
||||||
|
</div>
|
||||||
|
<div class="d-grid mt-4">
|
||||||
|
<button type="submit" name="reset_password" class="btn btn-primary">تغيير كلمة المرور</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php elseif ($step === 'completed'): ?>
|
||||||
|
<div class="mt-3">
|
||||||
|
<a href="login.php" class="btn btn-outline-dark">الذهاب لصفحة الدخول</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
135
inbound.php
135
inbound.php
@ -2,6 +2,11 @@
|
|||||||
require_once __DIR__ . '/includes/header.php';
|
require_once __DIR__ . '/includes/header.php';
|
||||||
require_once __DIR__ . '/mail/MailService.php';
|
require_once __DIR__ . '/mail/MailService.php';
|
||||||
|
|
||||||
|
// Check if user has view permission
|
||||||
|
if (!canView()) {
|
||||||
|
redirect('index.php');
|
||||||
|
}
|
||||||
|
|
||||||
$error = '';
|
$error = '';
|
||||||
$success = '';
|
$success = '';
|
||||||
$user_id = $_SESSION['user_id'];
|
$user_id = $_SESSION['user_id'];
|
||||||
@ -47,62 +52,72 @@ function sendAssignmentNotification($assigned_to_id, $ref_no, $subject) {
|
|||||||
// Handle actions
|
// Handle actions
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$action = $_POST['action'] ?? '';
|
$action = $_POST['action'] ?? '';
|
||||||
$type = 'inbound';
|
|
||||||
$ref_no = $_POST['ref_no'] ?? '';
|
// Permission checks for POST actions
|
||||||
$date_registered = $_POST['date_registered'] ?? date('Y-m-d');
|
if (($action === 'add' && !canAdd()) || ($action === 'edit' && !canEdit())) {
|
||||||
$due_date = !empty($_POST['due_date']) ? $_POST['due_date'] : null;
|
$error = 'عذراً، ليس لديك الصلاحية للقيام بهذا الإجراء';
|
||||||
$sender = $_POST['sender'] ?? '';
|
|
||||||
$recipient = $_POST['recipient'] ?? '';
|
|
||||||
$subject = $_POST['subject'] ?? '';
|
|
||||||
$description = $_POST['description'] ?? '';
|
|
||||||
$status_id = $_POST['status_id'] ?? $default_status_id;
|
|
||||||
$assigned_to = !empty($_POST['assigned_to']) ? $_POST['assigned_to'] : null;
|
|
||||||
$id = $_POST['id'] ?? 0;
|
|
||||||
|
|
||||||
if ($ref_no && $subject) {
|
|
||||||
try {
|
|
||||||
if ($action === 'add') {
|
|
||||||
$stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
||||||
$stmt->execute([$type, $ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
|
||||||
|
|
||||||
if ($assigned_to) {
|
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
$success = 'تمت إضافة البريد بنجاح';
|
|
||||||
} elseif ($action === 'edit') {
|
|
||||||
// Get previous assigned_to to check if it changed
|
|
||||||
$stmt_old = db()->prepare("SELECT assigned_to FROM mailbox WHERE id = ?");
|
|
||||||
$stmt_old->execute([$id]);
|
|
||||||
$old_assigned_to = $stmt_old->fetchColumn();
|
|
||||||
|
|
||||||
$stmt = db()->prepare("UPDATE mailbox SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ? AND type = 'inbound'");
|
|
||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]);
|
|
||||||
|
|
||||||
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
$success = 'تم تحديث البيانات بنجاح';
|
|
||||||
}
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
if ($e->getCode() == 23000) {
|
|
||||||
$error = 'رقم القيد مستخدم مسبقاً';
|
|
||||||
} else {
|
|
||||||
$error = 'حدث خطأ: ' . $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$error = 'يرجى ملء الحقول المطلوبة (رقم القيد، الموضوع)';
|
$type = 'inbound';
|
||||||
|
$ref_no = $_POST['ref_no'] ?? '';
|
||||||
|
$date_registered = $_POST['date_registered'] ?? date('Y-m-d');
|
||||||
|
$due_date = !empty($_POST['due_date']) ? $_POST['due_date'] : null;
|
||||||
|
$sender = $_POST['sender'] ?? '';
|
||||||
|
$recipient = $_POST['recipient'] ?? '';
|
||||||
|
$subject = $_POST['subject'] ?? '';
|
||||||
|
$description = $_POST['description'] ?? '';
|
||||||
|
$status_id = $_POST['status_id'] ?? $default_status_id;
|
||||||
|
$assigned_to = !empty($_POST['assigned_to']) ? $_POST['assigned_to'] : null;
|
||||||
|
$id = $_POST['id'] ?? 0;
|
||||||
|
|
||||||
|
if ($ref_no && $subject) {
|
||||||
|
try {
|
||||||
|
if ($action === 'add') {
|
||||||
|
$stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
$stmt->execute([$type, $ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
||||||
|
|
||||||
|
if ($assigned_to) {
|
||||||
|
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
$success = 'تمت إضافة البريد بنجاح';
|
||||||
|
} elseif ($action === 'edit') {
|
||||||
|
// Get previous assigned_to to check if it changed
|
||||||
|
$stmt_old = db()->prepare("SELECT assigned_to FROM mailbox WHERE id = ?");
|
||||||
|
$stmt_old->execute([$id]);
|
||||||
|
$old_assigned_to = $stmt_old->fetchColumn();
|
||||||
|
|
||||||
|
$stmt = db()->prepare("UPDATE mailbox SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ? AND type = 'inbound'");
|
||||||
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]);
|
||||||
|
|
||||||
|
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
||||||
|
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
$success = 'تم تحديث البيانات بنجاح';
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
if ($e->getCode() == 23000) {
|
||||||
|
$error = 'رقم القيد مستخدم مسبقاً';
|
||||||
|
} else {
|
||||||
|
$error = 'حدث خطأ: ' . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$error = 'يرجى ملء الحقول المطلوبة (رقم القيد، الموضوع)';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete action
|
// Delete action
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
|
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
|
||||||
$id = $_GET['id'];
|
if (!canDelete()) {
|
||||||
$stmt = db()->prepare("DELETE FROM mailbox WHERE id = ? AND type = 'inbound'");
|
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
|
||||||
$stmt->execute([$id]);
|
} else {
|
||||||
$success = 'تم حذف البريد بنجاح';
|
$id = $_GET['id'];
|
||||||
|
$stmt = db()->prepare("DELETE FROM mailbox WHERE id = ? AND type = 'inbound'");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$success = 'تم حذف البريد بنجاح';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$search = $_GET['search'] ?? '';
|
$search = $_GET['search'] ?? '';
|
||||||
@ -137,9 +152,11 @@ $users_list = db()->query("SELECT id, full_name FROM users ORDER BY full_name")-
|
|||||||
// Handle Deep Link for Edit
|
// Handle Deep Link for Edit
|
||||||
$deepLinkData = null;
|
$deepLinkData = null;
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
||||||
$stmt = db()->prepare("SELECT * FROM mailbox WHERE id = ? AND type = 'inbound'");
|
if (canEdit()) {
|
||||||
$stmt->execute([$_GET['id']]);
|
$stmt = db()->prepare("SELECT * FROM mailbox WHERE id = ? AND type = 'inbound'");
|
||||||
$deepLinkData = $stmt->fetch();
|
$stmt->execute([$_GET['id']]);
|
||||||
|
$deepLinkData = $stmt->fetch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatusBadgeInList($mail) {
|
function getStatusBadgeInList($mail) {
|
||||||
@ -158,9 +175,11 @@ function getStatusBadgeInList($mail) {
|
|||||||
|
|
||||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
<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>
|
<h1 class="h2">البريد الوارد</h1>
|
||||||
|
<?php if (canAdd()): ?>
|
||||||
<button type="button" class="btn btn-primary shadow-sm" onclick="openMailModal('add')">
|
<button type="button" class="btn btn-primary shadow-sm" onclick="openMailModal('add')">
|
||||||
<i class="fas fa-plus-circle me-1"></i> إضافة جديد
|
<i class="fas fa-plus-circle me-1"></i> إضافة جديد
|
||||||
</button>
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if ($success): ?>
|
<?php if ($success): ?>
|
||||||
@ -243,11 +262,17 @@ function getStatusBadgeInList($mail) {
|
|||||||
<td><?= getStatusBadgeInList($mail) ?></td>
|
<td><?= getStatusBadgeInList($mail) ?></td>
|
||||||
<td class="pe-4 text-center">
|
<td class="pe-4 text-center">
|
||||||
<a href="view_mail.php?id=<?= $mail['id'] ?>" class="btn btn-sm btn-outline-info" title="عرض التفاصيل"><i class="fas fa-eye"></i></a>
|
<a href="view_mail.php?id=<?= $mail['id'] ?>" class="btn btn-sm btn-outline-info" title="عرض التفاصيل"><i class="fas fa-eye"></i></a>
|
||||||
|
|
||||||
|
<?php if (canEdit()): ?>
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary"
|
<button type="button" class="btn btn-sm btn-outline-primary"
|
||||||
onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
|
onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (canDelete()): ?>
|
||||||
<a href="javascript:void(0)" onclick="confirmDelete(<?= $mail['id'] ?>)" class="btn btn-sm btn-outline-danger" title="حذف"><i class="fas fa-trash"></i></a>
|
<a href="javascript:void(0)" onclick="confirmDelete(<?= $mail['id'] ?>)" class="btn btn-sm btn-outline-danger" title="حذف"><i class="fas fa-trash"></i></a>
|
||||||
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; else: ?>
|
<?php endforeach; else: ?>
|
||||||
@ -261,6 +286,7 @@ function getStatusBadgeInList($mail) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if (canAdd() || canEdit()): ?>
|
||||||
<!-- Mail Modal -->
|
<!-- Mail Modal -->
|
||||||
<div class="modal fade" id="mailModal" tabindex="-1" aria-labelledby="mailModalLabel" aria-hidden="true">
|
<div class="modal fade" id="mailModal" tabindex="-1" aria-labelledby="mailModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
@ -433,6 +459,7 @@ function confirmDelete(id) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.modal-content {
|
.modal-content {
|
||||||
@ -444,4 +471,4 @@ function confirmDelete(id) {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
|
|||||||
@ -1,7 +1,46 @@
|
|||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer mt-auto py-3 bg-white border-top">
|
||||||
|
<div class="container-fluid px-md-4">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-md-6 text-center text-md-start mb-2 mb-md-0">
|
||||||
|
<span class="text-muted small">
|
||||||
|
© <?= date('Y') ?> <?= htmlspecialchars($charity_name) ?>. جميع الحقوق محفوظة.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 text-center text-md-end">
|
||||||
|
<ul class="list-inline mb-0">
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<a href="index.php" class="text-muted text-decoration-none small hover-primary">
|
||||||
|
<i class="fas fa-home me-1"></i> لوحة التحكم
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item ms-3">
|
||||||
|
<a href="profile.php" class="text-muted text-decoration-none small hover-primary">
|
||||||
|
<i class="fas fa-user-circle me-1"></i> الملف الشخصي
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php if (isAdmin()): ?>
|
||||||
|
<li class="list-inline-item ms-3">
|
||||||
|
<a href="charity-settings.php" class="text-muted text-decoration-none small hover-primary">
|
||||||
|
<i class="fas fa-cog me-1"></i> الإعدادات
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php endif; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hover-primary:hover {
|
||||||
|
color: #0d6efd !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Global JS functions if needed
|
// Global JS functions if needed
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -10,12 +10,30 @@ function isAdmin() {
|
|||||||
return isset($_SESSION['user_role']) && $_SESSION['user_role'] === 'admin';
|
return isset($_SESSION['user_role']) && $_SESSION['user_role'] === 'admin';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function canView() {
|
||||||
|
return isAdmin() || (isset($_SESSION['can_view']) && $_SESSION['can_view'] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function canAdd() {
|
||||||
|
return isAdmin() || (isset($_SESSION['can_add']) && $_SESSION['can_add'] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function canEdit() {
|
||||||
|
return isAdmin() || (isset($_SESSION['can_edit']) && $_SESSION['can_edit'] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function canDelete() {
|
||||||
|
return isAdmin() || (isset($_SESSION['can_delete']) && $_SESSION['can_delete'] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
function redirect($path) {
|
function redirect($path) {
|
||||||
header("Location: $path");
|
header("Location: $path");
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isLoggedIn() && basename($_SERVER['PHP_SELF']) !== 'login.php') {
|
// Allowed pages when not logged in
|
||||||
|
$allowed_pages = ['login.php', 'forgot_password.php'];
|
||||||
|
if (!isLoggedIn() && !in_array(basename($_SERVER['PHP_SELF']), $allowed_pages)) {
|
||||||
redirect('login.php');
|
redirect('login.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,13 +47,20 @@ $charity_favicon = $charity['charity_favicon'] ?? null;
|
|||||||
// Fetch current user info if logged in
|
// Fetch current user info if logged in
|
||||||
$current_user = null;
|
$current_user = null;
|
||||||
if (isLoggedIn()) {
|
if (isLoggedIn()) {
|
||||||
$stmt = db()->prepare("SELECT full_name, profile_image FROM users WHERE id = ?");
|
$stmt = db()->prepare("SELECT full_name, profile_image, theme, can_view, can_add, can_edit, can_delete FROM users WHERE id = ?");
|
||||||
$stmt->execute([$_SESSION['user_id']]);
|
$stmt->execute([$_SESSION['user_id']]);
|
||||||
$current_user = $stmt->fetch();
|
$current_user = $stmt->fetch();
|
||||||
|
|
||||||
|
// Update session permissions
|
||||||
|
$_SESSION['can_view'] = $current_user['can_view'];
|
||||||
|
$_SESSION['can_add'] = $current_user['can_add'];
|
||||||
|
$_SESSION['can_edit'] = $current_user['can_edit'];
|
||||||
|
$_SESSION['can_delete'] = $current_user['can_delete'];
|
||||||
}
|
}
|
||||||
|
$user_theme = $current_user['theme'] ?? 'light';
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="ar" dir="rtl">
|
<html lang="ar" dir="rtl" data-theme="<?= htmlspecialchars($user_theme) ?>">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
@ -56,42 +81,136 @@ if (isLoggedIn()) {
|
|||||||
<script src="https://cdn.ckeditor.com/ckeditor5/36.0.1/classic/ckeditor.js?v=<?php echo time(); ?>"></script>
|
<script src="https://cdn.ckeditor.com/ckeditor5/36.0.1/classic/ckeditor.js?v=<?php echo time(); ?>"></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
:root {
|
||||||
|
/* Light Theme (Default) */
|
||||||
|
--bg-color: #f8f9fa;
|
||||||
|
--text-color: #212529;
|
||||||
|
--sidebar-bg: #ffffff;
|
||||||
|
--card-bg: #ffffff;
|
||||||
|
--nav-link-color: #333333;
|
||||||
|
--nav-link-hover-bg: #f0f7ff;
|
||||||
|
--primary-color: #0d6efd;
|
||||||
|
--border-color: rgba(0, 0, 0, 0.075);
|
||||||
|
--muted-text: #6c757d;
|
||||||
|
--input-bg: #ffffff;
|
||||||
|
--input-border: #dee2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--bg-color: #121212;
|
||||||
|
--text-color: #e0e0e0;
|
||||||
|
--sidebar-bg: #1e1e1e;
|
||||||
|
--card-bg: #1e1e1e;
|
||||||
|
--nav-link-color: #bbbbbb;
|
||||||
|
--nav-link-hover-bg: #2c2c2c;
|
||||||
|
--primary-color: #3788ff;
|
||||||
|
--border-color: rgba(255, 255, 255, 0.1);
|
||||||
|
--muted-text: #999999;
|
||||||
|
--input-bg: #2d2d2d;
|
||||||
|
--input-border: #444444;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="midnight"] {
|
||||||
|
--bg-color: #0b0e14;
|
||||||
|
--text-color: #cbd5e0;
|
||||||
|
--sidebar-bg: #1a202c;
|
||||||
|
--card-bg: #1a202c;
|
||||||
|
--nav-link-color: #a0aec0;
|
||||||
|
--nav-link-hover-bg: #2d3748;
|
||||||
|
--primary-color: #63b3ed;
|
||||||
|
--border-color: rgba(255, 255, 255, 0.05);
|
||||||
|
--muted-text: #718096;
|
||||||
|
--input-bg: #2d3748;
|
||||||
|
--input-border: #4a5568;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="forest"] {
|
||||||
|
--bg-color: #f0f4f0;
|
||||||
|
--text-color: #2d372d;
|
||||||
|
--sidebar-bg: #ffffff;
|
||||||
|
--card-bg: #ffffff;
|
||||||
|
--nav-link-color: #4a5d4a;
|
||||||
|
--nav-link-hover-bg: #e8f0e8;
|
||||||
|
--primary-color: #2d6a4f;
|
||||||
|
--border-color: rgba(0, 0, 0, 0.05);
|
||||||
|
--muted-text: #6b8e6b;
|
||||||
|
--input-bg: #ffffff;
|
||||||
|
--input-border: #ccd5cc;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Cairo', sans-serif;
|
font-family: 'Cairo', sans-serif;
|
||||||
background-color: #f8f9fa;
|
background-color: var(--bg-color);
|
||||||
|
color: var(--text-color);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bootstrap Overrides */
|
||||||
|
.bg-white { background-color: var(--card-bg) !important; }
|
||||||
|
.bg-light { background-color: var(--bg-color) !important; }
|
||||||
|
.text-dark { color: var(--text-color) !important; }
|
||||||
|
.text-muted { color: var(--muted-text) !important; }
|
||||||
|
.border-bottom { border-bottom: 1px solid var(--border-color) !important; }
|
||||||
|
.border-top { border-top: 1px solid var(--border-color) !important; }
|
||||||
|
.border { border: 1px solid var(--border-color) !important; }
|
||||||
|
.list-group-item { background-color: var(--card-bg); border-color: var(--border-color); color: var(--text-color); }
|
||||||
|
.form-control, .form-select { background-color: var(--input-bg); border-color: var(--input-border); color: var(--text-color); }
|
||||||
|
.form-control:focus, .form-select:focus { background-color: var(--input-bg); color: var(--text-color); border-color: var(--primary-color); }
|
||||||
|
.table { color: var(--text-color); border-color: var(--border-color); }
|
||||||
|
.table thead th { background-color: var(--bg-color); color: var(--text-color); }
|
||||||
|
.table-hover tbody tr:hover { background-color: var(--nav-link-hover-bg); }
|
||||||
|
|
||||||
|
.container-fluid.main-container {
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
.sidebar {
|
.sidebar {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: #fff;
|
background: var(--sidebar-bg);
|
||||||
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
box-shadow: 0 0.125rem 0.25rem var(--border-color);
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
}
|
}
|
||||||
.nav-link {
|
.nav-link {
|
||||||
color: #333;
|
color: var(--nav-link-color);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 0.8rem 1.5rem;
|
padding: 0.8rem 1.5rem;
|
||||||
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
.nav-link:hover, .nav-link.active {
|
.nav-link:hover, .nav-link.active {
|
||||||
background-color: #f0f7ff;
|
background-color: var(--nav-link-hover-bg);
|
||||||
color: #0d6efd;
|
color: var(--primary-color);
|
||||||
border-left: 4px solid #0d6efd;
|
border-left: 4px solid var(--primary-color);
|
||||||
}
|
}
|
||||||
.card {
|
.card {
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
box-shadow: 0 0.125rem 0.25rem var(--border-color);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
background-color: var(--card-bg);
|
||||||
|
color: var(--text-color);
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
}
|
}
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
background-color: #0d6efd;
|
background-color: var(--primary-color);
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
filter: brightness(90%);
|
||||||
|
}
|
||||||
|
|
||||||
.status-received { background-color: #e9ecef; color: #495057; }
|
.status-received { background-color: #e9ecef; color: #495057; }
|
||||||
.status-in_progress { background-color: #cff4fc; color: #055160; }
|
.status-in_progress { background-color: #cff4fc; color: #055160; }
|
||||||
.status-closed { background-color: #d1e7dd; color: #0f5132; }
|
.status-closed { background-color: #d1e7dd; color: #0f5132; }
|
||||||
|
|
||||||
/* Modal Header Styling */
|
.modal-content {
|
||||||
|
background-color: var(--card-bg);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
.modal-header.bg-primary {
|
.modal-header.bg-primary {
|
||||||
background-color: #0d6efd !important;
|
background-color: var(--primary-color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-profile-img {
|
.user-profile-img {
|
||||||
@ -99,17 +218,55 @@ if (isLoggedIn()) {
|
|||||||
height: 80px;
|
height: 80px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 2px solid #0d6efd;
|
border: 2px solid var(--primary-color);
|
||||||
}
|
}
|
||||||
.charity-logo {
|
.charity-logo {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 60px;
|
max-height: 60px;
|
||||||
}
|
}
|
||||||
|
.navbar {
|
||||||
|
background-color: var(--sidebar-bg) !important;
|
||||||
|
border-color: var(--border-color) !important;
|
||||||
|
}
|
||||||
|
.navbar-brand {
|
||||||
|
color: var(--text-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Theme Switcher Styles */
|
||||||
|
.theme-switcher {
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
.theme-options {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.theme-btn {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
.theme-btn:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
.theme-btn.active {
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
}
|
||||||
|
.theme-btn-light { background-color: #f8f9fa; border: 1px solid #ddd; }
|
||||||
|
.theme-btn-dark { background-color: #121212; }
|
||||||
|
.theme-btn-midnight { background-color: #0b0e14; }
|
||||||
|
.theme-btn-forest { background-color: #2d6a4f; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid main-container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<?php if (isLoggedIn()): ?>
|
<?php if (isLoggedIn()): ?>
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
@ -178,7 +335,19 @@ if (isLoggedIn()) {
|
|||||||
<i class="fas fa-user-circle me-2"></i> الملف الشخصي
|
<i class="fas fa-user-circle me-2"></i> الملف الشخصي
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item mt-4">
|
|
||||||
|
<!-- Theme Switcher -->
|
||||||
|
<li class="theme-switcher">
|
||||||
|
<div class="small fw-bold mb-2 text-center">المظهر</div>
|
||||||
|
<div class="theme-options">
|
||||||
|
<div class="theme-btn theme-btn-light <?= $user_theme == 'light' ? 'active' : '' ?>" onclick="setTheme('light')" title="فاتح"></div>
|
||||||
|
<div class="theme-btn theme-btn-dark <?= $user_theme == 'dark' ? 'active' : '' ?>" onclick="setTheme('dark')" title="داكن"></div>
|
||||||
|
<div class="theme-btn theme-btn-midnight <?= $user_theme == 'midnight' ? 'active' : '' ?>" onclick="setTheme('midnight')" title="منتصف الليل"></div>
|
||||||
|
<div class="theme-btn theme-btn-forest <?= $user_theme == 'forest' ? 'active' : '' ?>" onclick="setTheme('forest')" title="غابة"></div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item mt-2">
|
||||||
<a class="nav-link text-danger" href="logout.php">
|
<a class="nav-link text-danger" href="logout.php">
|
||||||
<i class="fas fa-sign-out-alt me-2"></i> تسجيل الخروج
|
<i class="fas fa-sign-out-alt me-2"></i> تسجيل الخروج
|
||||||
</a>
|
</a>
|
||||||
@ -186,6 +355,32 @@ if (isLoggedIn()) {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function setTheme(theme) {
|
||||||
|
document.documentElement.setAttribute('data-theme', theme);
|
||||||
|
document.querySelectorAll('.theme-btn').forEach(btn => btn.classList.remove('active'));
|
||||||
|
document.querySelector('.theme-btn-' + theme).classList.add('active');
|
||||||
|
|
||||||
|
fetch('api/update_theme.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ theme: theme })
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (!data.success) console.error('Failed to update theme preference');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-md navbar-light bg-white d-md-none border-bottom mb-3"><div class="container-fluid"><span class="navbar-brand">القائمة</span><button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".sidebar" aria-controls="sidebar" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button></div></nav><main class="<?= isLoggedIn() ? 'col-md-9 ms-sm-auto col-lg-10' : 'col-12' ?> px-md-4 py-4">
|
<nav class="navbar navbar-expand-md navbar-light bg-white d-md-none border-bottom mb-3">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<span class="navbar-brand">القائمة</span>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".sidebar" aria-controls="sidebar" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<main class="<?= isLoggedIn() ? 'col-md-9 ms-sm-auto col-lg-10' : 'col-12' ?> px-md-4 py-4">
|
||||||
|
|||||||
@ -25,6 +25,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$_SESSION['username'] = $user['username'];
|
$_SESSION['username'] = $user['username'];
|
||||||
$_SESSION['full_name'] = $user['full_name'];
|
$_SESSION['full_name'] = $user['full_name'];
|
||||||
$_SESSION['user_role'] = $user['role'];
|
$_SESSION['user_role'] = $user['role'];
|
||||||
|
|
||||||
|
// Set permissions in session immediately
|
||||||
|
$_SESSION['can_view'] = $user['can_view'] ?? 1;
|
||||||
|
$_SESSION['can_add'] = $user['can_add'] ?? 0;
|
||||||
|
$_SESSION['can_edit'] = $user['can_edit'] ?? 0;
|
||||||
|
$_SESSION['can_delete'] = $user['can_delete'] ?? 0;
|
||||||
|
|
||||||
redirect('index.php');
|
redirect('index.php');
|
||||||
} else {
|
} else {
|
||||||
$error = 'اسم المستخدم أو كلمة المرور غير صحيحة';
|
$error = 'اسم المستخدم أو كلمة المرور غير صحيحة';
|
||||||
@ -70,4 +77,4 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
|
|||||||
165
outbound.php
165
outbound.php
@ -2,6 +2,11 @@
|
|||||||
require_once __DIR__ . '/includes/header.php';
|
require_once __DIR__ . '/includes/header.php';
|
||||||
require_once __DIR__ . '/mail/MailService.php';
|
require_once __DIR__ . '/mail/MailService.php';
|
||||||
|
|
||||||
|
// Check if user has view permission
|
||||||
|
if (!canView()) {
|
||||||
|
redirect('index.php');
|
||||||
|
}
|
||||||
|
|
||||||
// Safe truncation helper
|
// Safe truncation helper
|
||||||
if (!function_exists('truncate_text')) {
|
if (!function_exists('truncate_text')) {
|
||||||
function truncate_text($text, $limit = 100) {
|
function truncate_text($text, $limit = 100) {
|
||||||
@ -59,86 +64,96 @@ function sendAssignmentNotification($assigned_to_id, $ref_no, $subject) {
|
|||||||
// Handle actions
|
// Handle actions
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$action = $_POST['action'] ?? '';
|
$action = $_POST['action'] ?? '';
|
||||||
$type = 'outbound';
|
|
||||||
$ref_no = $_POST['ref_no'] ?? '';
|
// Permission checks for POST actions
|
||||||
$date_registered = $_POST['date_registered'] ?? date('Y-m-d');
|
if (($action === 'add' && !canAdd()) || ($action === 'edit' && !canEdit())) {
|
||||||
$due_date = !empty($_POST['due_date']) ? $_POST['due_date'] : null;
|
$error = 'عذراً، ليس لديك الصلاحية للقيام بهذا الإجراء';
|
||||||
$sender = $_POST['sender'] ?? '';
|
} else {
|
||||||
$recipient = $_POST['recipient'] ?? '';
|
$type = 'outbound';
|
||||||
$subject = $_POST['subject'] ?? '';
|
$ref_no = $_POST['ref_no'] ?? '';
|
||||||
$description = $_POST['description'] ?? '';
|
$date_registered = $_POST['date_registered'] ?? date('Y-m-d');
|
||||||
$status_id = $_POST['status_id'] ?? $default_status_id;
|
$due_date = !empty($_POST['due_date']) ? $_POST['due_date'] : null;
|
||||||
$assigned_to = !empty($_POST['assigned_to']) ? $_POST['assigned_to'] : null;
|
$sender = $_POST['sender'] ?? '';
|
||||||
$id = $_POST['id'] ?? 0;
|
$recipient = $_POST['recipient'] ?? '';
|
||||||
|
$subject = $_POST['subject'] ?? '';
|
||||||
|
$description = $_POST['description'] ?? '';
|
||||||
|
$status_id = $_POST['status_id'] ?? $default_status_id;
|
||||||
|
$assigned_to = !empty($_POST['assigned_to']) ? $_POST['assigned_to'] : null;
|
||||||
|
$id = $_POST['id'] ?? 0;
|
||||||
|
|
||||||
if ($ref_no && $subject) {
|
if ($ref_no && $subject) {
|
||||||
try {
|
try {
|
||||||
db()->beginTransaction();
|
db()->beginTransaction();
|
||||||
if ($action === 'add') {
|
if ($action === 'add') {
|
||||||
$stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$type, $ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
$stmt->execute([$type, $ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
||||||
$mail_id = db()->lastInsertId();
|
$mail_id = db()->lastInsertId();
|
||||||
|
|
||||||
if ($assigned_to) {
|
if ($assigned_to) {
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
$success = 'تمت إضافة البريد الصادر بنجاح';
|
||||||
|
} elseif ($action === 'edit') {
|
||||||
|
$mail_id = $id;
|
||||||
|
|
||||||
|
// Get previous assigned_to to check if it changed
|
||||||
|
$stmt_old = db()->prepare("SELECT assigned_to FROM mailbox WHERE id = ?");
|
||||||
|
$stmt_old->execute([$id]);
|
||||||
|
$old_assigned_to = $stmt_old->fetchColumn();
|
||||||
|
|
||||||
|
$stmt = db()->prepare("UPDATE mailbox SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ? AND type = 'outbound'");
|
||||||
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $mail_id]);
|
||||||
|
|
||||||
|
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
||||||
|
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
$success = 'تم تحديث البيانات بنجاح';
|
||||||
}
|
}
|
||||||
|
|
||||||
$success = 'تمت إضافة البريد الصادر بنجاح';
|
|
||||||
} elseif ($action === 'edit') {
|
|
||||||
$mail_id = $id;
|
|
||||||
|
|
||||||
// Get previous assigned_to to check if it changed
|
|
||||||
$stmt_old = db()->prepare("SELECT assigned_to FROM mailbox WHERE id = ?");
|
|
||||||
$stmt_old->execute([$id]);
|
|
||||||
$old_assigned_to = $stmt_old->fetchColumn();
|
|
||||||
|
|
||||||
$stmt = db()->prepare("UPDATE mailbox SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ? AND type = 'outbound'");
|
// Handle Attachments
|
||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $mail_id]);
|
if (!empty($_FILES['attachments']['name'][0])) {
|
||||||
|
$upload_dir = 'uploads/attachments/';
|
||||||
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
$success = 'تم تحديث البيانات بنجاح';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle Attachments
|
foreach ($_FILES['attachments']['name'] as $key => $name) {
|
||||||
if (!empty($_FILES['attachments']['name'][0])) {
|
if ($_FILES['attachments']['error'][$key] === 0) {
|
||||||
$upload_dir = 'uploads/attachments/';
|
$file_name = time() . '_' . basename($name);
|
||||||
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
|
$target_path = $upload_dir . $file_name;
|
||||||
|
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
||||||
foreach ($_FILES['attachments']['name'] as $key => $name) {
|
$stmt = db()->prepare("INSERT INTO attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
||||||
if ($_FILES['attachments']['error'][$key] === 0) {
|
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
||||||
$file_name = time() . '_' . basename($name);
|
}
|
||||||
$target_path = $upload_dir . $file_name;
|
|
||||||
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
|
||||||
$stmt = db()->prepare("INSERT INTO attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
|
||||||
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
db()->commit();
|
db()->commit();
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
db()->rollBack();
|
db()->rollBack();
|
||||||
if ($e->getCode() == 23000) {
|
if ($e->getCode() == 23000) {
|
||||||
$error = 'رقم القيد مستخدم مسبقاً';
|
$error = 'رقم القيد مستخدم مسبقاً';
|
||||||
} else {
|
} else {
|
||||||
$error = 'حدث خطأ: ' . $e->getMessage();
|
$error = 'حدث خطأ: ' . $e->getMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$error = 'يرجى ملء الحقول المطلوبة (رقم القيد، الموضوع)';
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$error = 'يرجى ملء الحقول المطلوبة (رقم القيد، الموضوع)';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete action
|
// Delete action
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
|
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
|
||||||
$id = $_GET['id'];
|
if (!canDelete()) {
|
||||||
$stmt = db()->prepare("DELETE FROM mailbox WHERE id = ? AND type = 'outbound'");
|
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
|
||||||
$stmt->execute([$id]);
|
} else {
|
||||||
$success = 'تم حذف البريد بنجاح';
|
$id = $_GET['id'];
|
||||||
|
$stmt = db()->prepare("DELETE FROM mailbox WHERE id = ? AND type = 'outbound'");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$success = 'تم حذف البريد بنجاح';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$search = $_GET['search'] ?? '';
|
$search = $_GET['search'] ?? '';
|
||||||
@ -173,9 +188,11 @@ $users_list = db()->query("SELECT id, full_name FROM users ORDER BY full_name")-
|
|||||||
// Handle Deep Link for Edit
|
// Handle Deep Link for Edit
|
||||||
$deepLinkData = null;
|
$deepLinkData = null;
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
||||||
$stmt = db()->prepare("SELECT * FROM mailbox WHERE id = ? AND type = 'outbound'");
|
if (canEdit()) {
|
||||||
$stmt->execute([$_GET['id']]);
|
$stmt = db()->prepare("SELECT * FROM mailbox WHERE id = ? AND type = 'outbound'");
|
||||||
$deepLinkData = $stmt->fetch();
|
$stmt->execute([$_GET['id']]);
|
||||||
|
$deepLinkData = $stmt->fetch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatusBadgeInList($mail) {
|
function getStatusBadgeInList($mail) {
|
||||||
@ -194,9 +211,11 @@ function getStatusBadgeInList($mail) {
|
|||||||
|
|
||||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
<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>
|
<h1 class="h2">البريد الصادر</h1>
|
||||||
|
<?php if (canAdd()): ?>
|
||||||
<button type="button" class="btn btn-primary shadow-sm" onclick="openMailModal('add')">
|
<button type="button" class="btn btn-primary shadow-sm" onclick="openMailModal('add')">
|
||||||
<i class="fas fa-plus-circle me-1"></i> إضافة جديد
|
<i class="fas fa-plus-circle me-1"></i> إضافة جديد
|
||||||
</button>
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if ($success): ?>
|
<?php if ($success): ?>
|
||||||
@ -279,11 +298,17 @@ function getStatusBadgeInList($mail) {
|
|||||||
<td><?= getStatusBadgeInList($mail) ?></td>
|
<td><?= getStatusBadgeInList($mail) ?></td>
|
||||||
<td class="pe-4 text-center">
|
<td class="pe-4 text-center">
|
||||||
<a href="view_mail.php?id=<?= $mail['id'] ?>" class="btn btn-sm btn-outline-info" title="عرض التفاصيل"><i class="fas fa-eye"></i></a>
|
<a href="view_mail.php?id=<?= $mail['id'] ?>" class="btn btn-sm btn-outline-info" title="عرض التفاصيل"><i class="fas fa-eye"></i></a>
|
||||||
|
|
||||||
|
<?php if (canEdit()): ?>
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary"
|
<button type="button" class="btn btn-sm btn-outline-primary"
|
||||||
onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
|
onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (canDelete()): ?>
|
||||||
<a href="javascript:void(0)" onclick="confirmDelete(<?= $mail['id'] ?>)" class="btn btn-sm btn-outline-danger" title="حذف"><i class="fas fa-trash"></i></a>
|
<a href="javascript:void(0)" onclick="confirmDelete(<?= $mail['id'] ?>)" class="btn btn-sm btn-outline-danger" title="حذف"><i class="fas fa-trash"></i></a>
|
||||||
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; else: ?>
|
<?php endforeach; else: ?>
|
||||||
@ -297,6 +322,7 @@ function getStatusBadgeInList($mail) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if (canAdd() || canEdit()): ?>
|
||||||
<!-- Mail Modal -->
|
<!-- Mail Modal -->
|
||||||
<div class="modal fade" id="mailModal" tabindex="-1" aria-labelledby="mailModalLabel" aria-hidden="true">
|
<div class="modal fade" id="mailModal" tabindex="-1" aria-labelledby="mailModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-xl">
|
<div class="modal-dialog modal-xl">
|
||||||
@ -504,6 +530,7 @@ function confirmDelete(id) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.ck-editor__editable_inline {
|
.ck-editor__editable_inline {
|
||||||
@ -518,4 +545,4 @@ function confirmDelete(id) {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/includes/header.php';
|
require_once __DIR__ . '/includes/header.php';
|
||||||
|
|
||||||
|
// Check if user has view permission
|
||||||
|
if (!canView()) {
|
||||||
|
// If they can't even view, they shouldn't be here, but header.php already handles basic login.
|
||||||
|
// We'll let them see their profile at least, but maybe not this dashboard.
|
||||||
|
}
|
||||||
|
|
||||||
$user_id = $_SESSION['user_id'];
|
$user_id = $_SESSION['user_id'];
|
||||||
$user_role = $_SESSION['user_role'];
|
$user_role = $_SESSION['user_role'];
|
||||||
$is_admin = isAdmin();
|
$is_admin = isAdmin();
|
||||||
@ -37,8 +43,8 @@ $recent_query = "SELECT m.*, s.name as status_name, s.color as status_color, u.f
|
|||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
LEFT JOIN users u ON m.assigned_to = u.id";
|
LEFT JOIN users u ON m.assigned_to = u.id";
|
||||||
|
|
||||||
if ($is_clerk) {
|
if ($is_admin || $is_clerk) {
|
||||||
// Clerks see all recent activity
|
// Admins and Clerks see all recent activity if they have view permission
|
||||||
$recent_stmt = db()->prepare($recent_query . " ORDER BY m.updated_at DESC LIMIT 10");
|
$recent_stmt = db()->prepare($recent_query . " ORDER BY m.updated_at DESC LIMIT 10");
|
||||||
$recent_stmt->execute();
|
$recent_stmt->execute();
|
||||||
} else {
|
} else {
|
||||||
@ -71,10 +77,17 @@ function getStatusBadge($mail) {
|
|||||||
<div>
|
<div>
|
||||||
<h2 class="fw-bold mb-1">مرحباً، <?= htmlspecialchars($current_user['full_name'] ?? $_SESSION['username']) ?>!</h2>
|
<h2 class="fw-bold mb-1">مرحباً، <?= htmlspecialchars($current_user['full_name'] ?? $_SESSION['username']) ?>!</h2>
|
||||||
<p class="mb-0 opacity-75">
|
<p class="mb-0 opacity-75">
|
||||||
<?php if ($is_clerk): ?>
|
أنت مسجل كـ <strong>
|
||||||
أنت مسجل كـ <strong>كاتب</strong>. يمكنك متابعة كافة المراسلات وإدارة المهام.
|
<?php
|
||||||
|
if ($is_admin) echo 'مدير النظام';
|
||||||
|
elseif ($is_clerk) echo 'كاتب';
|
||||||
|
else echo 'موظف';
|
||||||
|
?>
|
||||||
|
</strong>.
|
||||||
|
<?php if ($is_admin || $is_clerk): ?>
|
||||||
|
يمكنك متابعة كافة المراسلات وإدارة المهام.
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
أنت مسجل كـ <strong>موظف</strong>. تابع مهامك المسندة إليك هنا.
|
تابع مهامك المسندة إليك هنا.
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -121,8 +134,8 @@ function getStatusBadge($mail) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if ($is_clerk): ?>
|
<?php if ($is_admin || $is_clerk): ?>
|
||||||
<!-- Clerk specific stats -->
|
<!-- Admin/Clerk specific stats -->
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="card h-100 p-3 shadow-sm border-0 border-start border-info border-4">
|
<div class="card h-100 p-3 shadow-sm border-0 border-start border-info border-4">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
@ -197,8 +210,10 @@ function getStatusBadge($mail) {
|
|||||||
<div class="card-header bg-white py-3 border-bottom d-flex justify-content-between align-items-center">
|
<div class="card-header bg-white py-3 border-bottom d-flex justify-content-between align-items-center">
|
||||||
<h5 class="mb-0 fw-bold"><i class="fas fa-clipboard-list me-2 text-primary"></i> مهامي المسندة</h5>
|
<h5 class="mb-0 fw-bold"><i class="fas fa-clipboard-list me-2 text-primary"></i> مهامي المسندة</h5>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
|
<?php if (canAdd()): ?>
|
||||||
<a href="inbound.php?action=add" class="btn btn-sm btn-outline-primary">إضافة وارد</a>
|
<a href="inbound.php?action=add" class="btn btn-sm btn-outline-primary">إضافة وارد</a>
|
||||||
<a href="outbound.php" class="btn btn-sm btn-outline-success">إضافة صادر</a>
|
<a href="outbound.php" class="btn btn-sm btn-outline-success">إضافة صادر</a>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
@ -253,7 +268,7 @@ function getStatusBadge($mail) {
|
|||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="card shadow-sm border-0 mb-4 h-100">
|
<div class="card shadow-sm border-0 mb-4 h-100">
|
||||||
<div class="card-header bg-white py-3 border-bottom">
|
<div class="card-header bg-white py-3 border-bottom">
|
||||||
<h5 class="mb-0 fw-bold"><i class="fas fa-bell me-2 text-warning"></i> <?= $is_clerk ? 'آخر المراسلات' : 'نشاطاتي الأخيرة' ?></h5>
|
<h5 class="mb-0 fw-bold"><i class="fas fa-bell me-2 text-warning"></i> <?= ($is_admin || $is_clerk) ? 'آخر المراسلات' : 'نشاطاتي الأخيرة' ?></h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-0" style="max-height: 500px; overflow-y: auto;">
|
<div class="card-body p-0" style="max-height: 500px; overflow-y: auto;">
|
||||||
<div class="list-group list-group-flush">
|
<div class="list-group list-group-flush">
|
||||||
@ -287,4 +302,4 @@ function getStatusBadge($mail) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
|
|||||||
105
users.php
105
users.php
@ -15,13 +15,19 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$role = $_POST['role'] ?? 'staff';
|
$role = $_POST['role'] ?? 'staff';
|
||||||
$password = $_POST['password'] ?? '';
|
$password = $_POST['password'] ?? '';
|
||||||
$id = $_POST['id'] ?? 0;
|
$id = $_POST['id'] ?? 0;
|
||||||
|
|
||||||
|
// Permissions
|
||||||
|
$can_view = isset($_POST['can_view']) ? 1 : 0;
|
||||||
|
$can_add = isset($_POST['can_add']) ? 1 : 0;
|
||||||
|
$can_edit = isset($_POST['can_edit']) ? 1 : 0;
|
||||||
|
$can_delete = isset($_POST['can_delete']) ? 1 : 0;
|
||||||
|
|
||||||
if ($action === 'add') {
|
if ($action === 'add') {
|
||||||
if ($username && $password && $full_name) {
|
if ($username && $password && $full_name) {
|
||||||
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
||||||
try {
|
try {
|
||||||
$stmt = db()->prepare("INSERT INTO users (username, password, full_name, role) VALUES (?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO users (username, password, full_name, role, can_view, can_add, can_edit, can_delete) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$username, $hashed_password, $full_name, $role]);
|
$stmt->execute([$username, $hashed_password, $full_name, $role, $can_view, $can_add, $can_edit, $can_delete]);
|
||||||
$success = 'تم إضافة المستخدم بنجاح';
|
$success = 'تم إضافة المستخدم بنجاح';
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
if ($e->getCode() == 23000) {
|
if ($e->getCode() == 23000) {
|
||||||
@ -38,11 +44,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
try {
|
try {
|
||||||
if ($password) {
|
if ($password) {
|
||||||
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
||||||
$stmt = db()->prepare("UPDATE users SET username = ?, full_name = ?, role = ?, password = ? WHERE id = ?");
|
$stmt = db()->prepare("UPDATE users SET username = ?, full_name = ?, role = ?, password = ?, can_view = ?, can_add = ?, can_edit = ?, can_delete = ? WHERE id = ?");
|
||||||
$stmt->execute([$username, $full_name, $role, $hashed_password, $id]);
|
$stmt->execute([$username, $full_name, $role, $hashed_password, $can_view, $can_add, $can_edit, $can_delete, $id]);
|
||||||
} else {
|
} else {
|
||||||
$stmt = db()->prepare("UPDATE users SET username = ?, full_name = ?, role = ? WHERE id = ?");
|
$stmt = db()->prepare("UPDATE users SET username = ?, full_name = ?, role = ?, can_view = ?, can_add = ?, can_edit = ?, can_delete = ? WHERE id = ?");
|
||||||
$stmt->execute([$username, $full_name, $role, $id]);
|
$stmt->execute([$username, $full_name, $role, $can_view, $can_add, $can_edit, $can_delete, $id]);
|
||||||
}
|
}
|
||||||
$success = 'تم تحديث بيانات المستخدم بنجاح';
|
$success = 'تم تحديث بيانات المستخدم بنجاح';
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
@ -77,7 +83,7 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
<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>
|
<h1 class="h2">إدارة المستخدمين والصلاحيات</h1>
|
||||||
<button type="button" class="btn btn-primary shadow-sm" onclick="openUserModal('add')">
|
<button type="button" class="btn btn-primary shadow-sm" onclick="openUserModal('add')">
|
||||||
<i class="fas fa-user-plus me-1"></i> إضافة مستخدم جديد
|
<i class="fas fa-user-plus me-1"></i> إضافة مستخدم جديد
|
||||||
</button>
|
</button>
|
||||||
@ -106,6 +112,7 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
|
|||||||
<th class="ps-4">الاسم الكامل</th>
|
<th class="ps-4">الاسم الكامل</th>
|
||||||
<th>اسم المستخدم</th>
|
<th>اسم المستخدم</th>
|
||||||
<th>الدور</th>
|
<th>الدور</th>
|
||||||
|
<th>الصلاحيات</th>
|
||||||
<th>تاريخ الإنشاء</th>
|
<th>تاريخ الإنشاء</th>
|
||||||
<th class="pe-4 text-center">الإجراءات</th>
|
<th class="pe-4 text-center">الإجراءات</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -124,6 +131,14 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
|
|||||||
<span class="badge bg-secondary">موظف</span>
|
<span class="badge bg-secondary">موظف</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex gap-1">
|
||||||
|
<span class="badge <?= $user['can_view'] ? 'bg-success' : 'bg-light text-muted' ?>" title="عرض">ع</span>
|
||||||
|
<span class="badge <?= $user['can_add'] ? 'bg-success' : 'bg-light text-muted' ?>" title="إضافة">إ</span>
|
||||||
|
<span class="badge <?= $user['can_edit'] ? 'bg-success' : 'bg-light text-muted' ?>" title="تعديل">ت</span>
|
||||||
|
<span class="badge <?= $user['can_delete'] ? 'bg-success' : 'bg-light text-muted' ?>" title="حذف">ح</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
<td><?= $user['created_at'] ?></td>
|
<td><?= $user['created_at'] ?></td>
|
||||||
<td class="pe-4 text-center">
|
<td class="pe-4 text-center">
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary"
|
<button type="button" class="btn btn-sm btn-outline-primary"
|
||||||
@ -171,12 +186,42 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
|
|||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label fw-bold">الدور</label>
|
<label class="form-label fw-bold">الدور</label>
|
||||||
<select name="role" id="modalRole" class="form-select">
|
<select name="role" id="modalRole" class="form-select" onchange="applyRolePresets(this.value)">
|
||||||
<option value="staff">موظف</option>
|
<option value="staff">موظف</option>
|
||||||
<option value="clerk">كاتب</option>
|
<option value="clerk">كاتب</option>
|
||||||
<option value="admin">مدير</option>
|
<option value="admin">مدير</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label fw-bold d-block">الصلاحيات</label>
|
||||||
|
<div class="row g-2 bg-light p-3 rounded">
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="can_view" id="permView" value="1">
|
||||||
|
<label class="form-check-label" for="permView">عرض البيانات</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="can_add" id="permAdd" value="1">
|
||||||
|
<label class="form-check-label" for="permAdd">إضافة سجلات</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="can_edit" id="permEdit" value="1">
|
||||||
|
<label class="form-check-label" for="permEdit">تعديل سجلات</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="can_delete" id="permDelete" value="1">
|
||||||
|
<label class="form-check-label" for="permDelete">حذف سجلات</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer bg-light">
|
<div class="modal-footer bg-light">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button>
|
||||||
@ -190,6 +235,23 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
|
|||||||
<script>
|
<script>
|
||||||
let userModal;
|
let userModal;
|
||||||
|
|
||||||
|
function applyRolePresets(role) {
|
||||||
|
const view = document.getElementById('permView');
|
||||||
|
const add = document.getElementById('permAdd');
|
||||||
|
const edit = document.getElementById('permEdit');
|
||||||
|
const del = document.getElementById('permDelete');
|
||||||
|
|
||||||
|
if (role === 'admin') {
|
||||||
|
view.checked = add.checked = edit.checked = del.checked = true;
|
||||||
|
} else if (role === 'clerk') {
|
||||||
|
view.checked = add.checked = edit.checked = true;
|
||||||
|
del.checked = false;
|
||||||
|
} else {
|
||||||
|
view.checked = true;
|
||||||
|
add.checked = edit.checked = del.checked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function openUserModal(action, data = null) {
|
function openUserModal(action, data = null) {
|
||||||
if (!userModal) {
|
if (!userModal) {
|
||||||
const modalEl = document.getElementById('userModal');
|
const modalEl = document.getElementById('userModal');
|
||||||
@ -212,6 +274,13 @@ function openUserModal(action, data = null) {
|
|||||||
username: document.getElementById('modalUsername'),
|
username: document.getElementById('modalUsername'),
|
||||||
role: document.getElementById('modalRole')
|
role: document.getElementById('modalRole')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const perms = {
|
||||||
|
can_view: document.getElementById('permView'),
|
||||||
|
can_add: document.getElementById('permAdd'),
|
||||||
|
can_edit: document.getElementById('permEdit'),
|
||||||
|
can_delete: document.getElementById('permDelete')
|
||||||
|
};
|
||||||
|
|
||||||
modalAction.value = action;
|
modalAction.value = action;
|
||||||
|
|
||||||
@ -220,6 +289,7 @@ function openUserModal(action, data = null) {
|
|||||||
modalId.value = '0';
|
modalId.value = '0';
|
||||||
Object.keys(fields).forEach(key => fields[key].value = '');
|
Object.keys(fields).forEach(key => fields[key].value = '');
|
||||||
modalRole.value = 'staff';
|
modalRole.value = 'staff';
|
||||||
|
applyRolePresets('staff');
|
||||||
modalPassword.required = true;
|
modalPassword.required = true;
|
||||||
pwdHint.textContent = '';
|
pwdHint.textContent = '';
|
||||||
} else {
|
} else {
|
||||||
@ -228,6 +298,13 @@ function openUserModal(action, data = null) {
|
|||||||
Object.keys(fields).forEach(key => {
|
Object.keys(fields).forEach(key => {
|
||||||
if (fields[key]) fields[key].value = data[key] || '';
|
if (fields[key]) fields[key].value = data[key] || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set permissions checkboxes
|
||||||
|
perms.can_view.checked = data.can_view == 1;
|
||||||
|
perms.can_add.checked = data.can_add == 1;
|
||||||
|
perms.can_edit.checked = data.can_edit == 1;
|
||||||
|
perms.can_delete.checked = data.can_delete == 1;
|
||||||
|
|
||||||
modalPassword.required = false;
|
modalPassword.required = false;
|
||||||
pwdHint.textContent = '(اتركه فارغاً للحفاظ على كلمة المرور الحالية)';
|
pwdHint.textContent = '(اتركه فارغاً للحفاظ على كلمة المرور الحالية)';
|
||||||
}
|
}
|
||||||
@ -243,7 +320,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
'id' => $_POST['id'] ?? 0,
|
'id' => $_POST['id'] ?? 0,
|
||||||
'username' => $_POST['username'] ?? '',
|
'username' => $_POST['username'] ?? '',
|
||||||
'full_name' => $_POST['full_name'] ?? '',
|
'full_name' => $_POST['full_name'] ?? '',
|
||||||
'role' => $_POST['role'] ?? 'staff'
|
'role' => $_POST['role'] ?? 'staff',
|
||||||
|
'can_view' => $_POST['can_view'] ?? 0,
|
||||||
|
'can_add' => $_POST['can_add'] ?? 0,
|
||||||
|
'can_edit' => $_POST['can_edit'] ?? 0,
|
||||||
|
'can_delete' => $_POST['can_delete'] ?? 0
|
||||||
]) ?>;
|
]) ?>;
|
||||||
openUserModal('<?= $_POST['action'] ?>', errorData);
|
openUserModal('<?= $_POST['action'] ?>', errorData);
|
||||||
<?php elseif (isset($_GET['action']) && $_GET['action'] === 'add'): ?>
|
<?php elseif (isset($_GET['action']) && $_GET['action'] === 'add'): ?>
|
||||||
@ -283,6 +364,10 @@ function confirmDelete(id) {
|
|||||||
.modal-header.bg-primary {
|
.modal-header.bg-primary {
|
||||||
background-color: #0d6efd !important;
|
background-color: #0d6efd !important;
|
||||||
}
|
}
|
||||||
|
.form-check-input:checked {
|
||||||
|
background-color: #198754;
|
||||||
|
border-color: #198754;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/includes/header.php';
|
require_once __DIR__ . '/includes/header.php';
|
||||||
|
|
||||||
|
// Check if user has view permission
|
||||||
|
if (!canView()) {
|
||||||
|
redirect('index.php');
|
||||||
|
}
|
||||||
|
|
||||||
$id = $_GET['id'] ?? 0;
|
$id = $_GET['id'] ?? 0;
|
||||||
if (!$id) redirect('index.php');
|
if (!$id) redirect('index.php');
|
||||||
|
|
||||||
@ -21,53 +26,65 @@ $error = '';
|
|||||||
|
|
||||||
// Handle Comment submission
|
// Handle Comment submission
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_comment'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_comment'])) {
|
||||||
$comment = $_POST['comment'] ?? '';
|
if (!canEdit()) {
|
||||||
if ($comment) {
|
$error = 'عذراً، ليس لديك الصلاحية لإضافة تعليقات';
|
||||||
$stmt = db()->prepare("INSERT INTO comments (mail_id, user_id, comment) VALUES (?, ?, ?)");
|
} else {
|
||||||
$stmt->execute([$id, $_SESSION['user_id'], $comment]);
|
$comment = $_POST['comment'] ?? '';
|
||||||
$success = 'تم إضافة التعليق بنجاح';
|
if ($comment) {
|
||||||
|
$stmt = db()->prepare("INSERT INTO comments (mail_id, user_id, comment) VALUES (?, ?, ?)");
|
||||||
|
$stmt->execute([$id, $_SESSION['user_id'], $comment]);
|
||||||
|
$success = 'تم إضافة التعليق بنجاح';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Attachment upload
|
// Handle Attachment upload
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['attachment'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['attachment'])) {
|
||||||
$file = $_FILES['attachment'];
|
if (!canEdit()) {
|
||||||
$display_name = $_POST['display_name'] ?? '';
|
$error = 'عذراً، ليس لديك الصلاحية لرفع مرفقات';
|
||||||
if ($file['error'] === 0) {
|
} else {
|
||||||
$upload_dir = 'uploads/attachments/';
|
$file = $_FILES['attachment'];
|
||||||
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
|
$display_name = $_POST['display_name'] ?? '';
|
||||||
|
if ($file['error'] === 0) {
|
||||||
$file_name = time() . '_' . basename($file['name']);
|
$upload_dir = 'uploads/attachments/';
|
||||||
$target_path = $upload_dir . $file_name;
|
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
|
||||||
|
|
||||||
if (move_uploaded_file($file['tmp_name'], $target_path)) {
|
$file_name = time() . '_' . basename($file['name']);
|
||||||
$stmt = db()->prepare("INSERT INTO attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
$target_path = $upload_dir . $file_name;
|
||||||
$stmt->execute([$id, $display_name, $target_path, $file['name'], $file['size']]);
|
|
||||||
$success = 'تم رفع الملف بنجاح';
|
if (move_uploaded_file($file['tmp_name'], $target_path)) {
|
||||||
} else {
|
$stmt = db()->prepare("INSERT INTO attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
||||||
$error = 'فشل في رفع الملف';
|
$stmt->execute([$id, $display_name, $target_path, $file['name'], $file['size']]);
|
||||||
|
$success = 'تم رفع الملف بنجاح';
|
||||||
|
} else {
|
||||||
|
$error = 'فشل في رفع الملف';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Attachment deletion
|
// Handle Attachment deletion
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_attachment'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_attachment'])) {
|
||||||
$attachment_id = $_POST['attachment_id'] ?? 0;
|
if (!canDelete()) {
|
||||||
if ($attachment_id) {
|
$error = 'عذراً، ليس لديك الصلاحية لحذف المرفقات';
|
||||||
$stmt = db()->prepare("SELECT * FROM attachments WHERE id = ?");
|
} else {
|
||||||
$stmt->execute([$attachment_id]);
|
$attachment_id = $_POST['attachment_id'] ?? 0;
|
||||||
$attachment = $stmt->fetch();
|
if ($attachment_id) {
|
||||||
|
$stmt = db()->prepare("SELECT * FROM attachments WHERE id = ?");
|
||||||
if ($attachment) {
|
|
||||||
// Delete file from disk
|
|
||||||
if (file_exists($attachment['file_path'])) {
|
|
||||||
unlink($attachment['file_path']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete record from DB
|
|
||||||
$stmt = db()->prepare("DELETE FROM attachments WHERE id = ?");
|
|
||||||
$stmt->execute([$attachment_id]);
|
$stmt->execute([$attachment_id]);
|
||||||
$success = 'تم حذف المرفق بنجاح';
|
$attachment = $stmt->fetch();
|
||||||
|
|
||||||
|
if ($attachment) {
|
||||||
|
// Delete file from disk
|
||||||
|
if (file_exists($attachment['file_path'])) {
|
||||||
|
unlink($attachment['file_path']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete record from DB
|
||||||
|
$stmt = db()->prepare("DELETE FROM attachments WHERE id = ?");
|
||||||
|
$stmt->execute([$attachment_id]);
|
||||||
|
$success = 'تم حذف المرفق بنجاح';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +108,9 @@ function isPreviewable($fileName) {
|
|||||||
<h1 class="h2">تفاصيل <?= $mail['type'] == 'inbound' ? 'البريد الوارد' : 'البريد الصادر' ?></h1>
|
<h1 class="h2">تفاصيل <?= $mail['type'] == 'inbound' ? 'البريد الوارد' : 'البريد الصادر' ?></h1>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<a href="<?= $mail['type'] ?>.php" class="btn btn-outline-secondary">عودة للقائمة</a>
|
<a href="<?= $mail['type'] ?>.php" class="btn btn-outline-secondary">عودة للقائمة</a>
|
||||||
|
<?php if (canEdit()): ?>
|
||||||
<a href="<?= $mail['type'] ?>.php?action=edit&id=<?= $mail['id'] ?>" class="btn btn-outline-primary">تعديل البيانات</a>
|
<a href="<?= $mail['type'] ?>.php?action=edit&id=<?= $mail['id'] ?>" class="btn btn-outline-primary">تعديل البيانات</a>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -205,12 +224,14 @@ function isPreviewable($fileName) {
|
|||||||
<h5 class="mb-0 fw-bold">التعليقات والمتابعة</h5>
|
<h5 class="mb-0 fw-bold">التعليقات والمتابعة</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<?php if (canEdit()): ?>
|
||||||
<form method="POST" class="mb-4">
|
<form method="POST" class="mb-4">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<textarea name="comment" class="form-control" rows="2" placeholder="أضف تعليقاً أو ملاحظة متابعة..." required></textarea>
|
<textarea name="comment" class="form-control" rows="2" placeholder="أضف تعليقاً أو ملاحظة متابعة..." required></textarea>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" name="add_comment" class="btn btn-sm btn-primary">إرسال تعليق</button>
|
<button type="submit" name="add_comment" class="btn btn-sm btn-primary">إرسال تعليق</button>
|
||||||
</form>
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="comment-list">
|
<div class="comment-list">
|
||||||
<?php if ($mail_comments): foreach ($mail_comments as $c): ?>
|
<?php if ($mail_comments): foreach ($mail_comments as $c): ?>
|
||||||
@ -236,6 +257,7 @@ function isPreviewable($fileName) {
|
|||||||
<h5 class="mb-0 fw-bold">المرفقات</h5>
|
<h5 class="mb-0 fw-bold">المرفقات</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<?php if (canEdit()): ?>
|
||||||
<form method="POST" enctype="multipart/form-data" class="mb-4">
|
<form method="POST" enctype="multipart/form-data" class="mb-4">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label class="form-label small mb-1">اسم المرفق (يظهر في القائمة)</label>
|
<label class="form-label small mb-1">اسم المرفق (يظهر في القائمة)</label>
|
||||||
@ -245,6 +267,7 @@ function isPreviewable($fileName) {
|
|||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-sm btn-secondary w-100">رفع ملف</button>
|
<button type="submit" class="btn btn-sm btn-secondary w-100">رفع ملف</button>
|
||||||
</form>
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="list-group list-group-flush">
|
<div class="list-group list-group-flush">
|
||||||
<?php if ($mail_attachments): foreach ($mail_attachments as $a): ?>
|
<?php if ($mail_attachments): foreach ($mail_attachments as $a): ?>
|
||||||
@ -266,6 +289,8 @@ function isPreviewable($fileName) {
|
|||||||
<i class="fas fa-eye"></i>
|
<i class="fas fa-eye"></i>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (canDelete()): ?>
|
||||||
<form method="POST" class="d-inline delete-attachment-form">
|
<form method="POST" class="d-inline delete-attachment-form">
|
||||||
<input type="hidden" name="attachment_id" value="<?= $a['id'] ?>">
|
<input type="hidden" name="attachment_id" value="<?= $a['id'] ?>">
|
||||||
<input type="hidden" name="delete_attachment" value="1">
|
<input type="hidden" name="delete_attachment" value="1">
|
||||||
@ -273,6 +298,7 @@ function isPreviewable($fileName) {
|
|||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -364,4 +390,4 @@ function isPreviewable($fileName) {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user