diff --git a/assets/css/custom.css b/assets/css/custom.css
index b9b0cca..e4322e1 100644
--- a/assets/css/custom.css
+++ b/assets/css/custom.css
@@ -520,4 +520,5 @@ body {
.sidebar .collapse .nav-link:hover,
.sidebar .collapse .nav-link.active {
color: #fff;
-}
\ No newline at end of file
+}
+.group-meetings { color: #20c997 !important; } /* Teal */
diff --git a/db/migrations/016_split_mailbox_tables.sql b/db/migrations/015_split_mailbox_tables.sql
similarity index 100%
rename from db/migrations/016_split_mailbox_tables.sql
rename to db/migrations/015_split_mailbox_tables.sql
diff --git a/db/migrations/027_add_meeting_module.sql b/db/migrations/027_add_meeting_module.sql
new file mode 100644
index 0000000..12c2535
--- /dev/null
+++ b/db/migrations/027_add_meeting_module.sql
@@ -0,0 +1,16 @@
+CREATE TABLE IF NOT EXISTS `meetings` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `title` VARCHAR(255) NOT NULL,
+ `description` TEXT,
+ `start_time` DATETIME NOT NULL,
+ `end_time` DATETIME NOT NULL,
+ `location` VARCHAR(255),
+ `status` ENUM('scheduled', 'completed', 'cancelled') DEFAULT 'scheduled',
+ `created_by` INT,
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE SET NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- Add permissions for existing admins
+INSERT IGNORE INTO `user_permissions` (`user_id`, `page`, `can_view`, `can_add`, `can_edit`, `can_delete`)
+SELECT `id`, 'meetings', 1, 1, 1, 1 FROM `users` WHERE `role` = 'admin' OR `is_super_admin` = 1;
diff --git a/db/migrations/028_expand_meetings_table.sql b/db/migrations/028_expand_meetings_table.sql
new file mode 100644
index 0000000..4c8da91
--- /dev/null
+++ b/db/migrations/028_expand_meetings_table.sql
@@ -0,0 +1,5 @@
+ALTER TABLE `meetings`
+ADD COLUMN `agenda` TEXT AFTER `description`,
+ADD COLUMN `attendees` TEXT AFTER `location`,
+ADD COLUMN `absentees` TEXT AFTER `attendees`,
+ADD COLUMN `meeting_details` TEXT AFTER `absentees`;
diff --git a/includes/header.php b/includes/header.php
index 7adaa3e..7eb39e6 100644
--- a/includes/header.php
+++ b/includes/header.php
@@ -133,6 +133,9 @@ $is_stock_open = in_array($cp, $stock_pages);
$expenses_pages = ['expenses.php', 'expense_categories.php', 'expense_reports.php'];
$is_expenses_open = in_array($cp, $expenses_pages);
+$meetings_pages = ['meetings.php'];
+$is_meetings_open = in_array($cp, $meetings_pages);
+
$admin_pages = ['index.php', 'users.php', 'charity-settings.php'];
$is_admin_open = in_array($cp, $admin_pages);
?>
@@ -527,6 +530,27 @@ $is_admin_open = in_array($cp, $admin_pages);
+
+
+
+
+
+
+
+
diff --git a/meetings.php b/meetings.php
new file mode 100644
index 0000000..2f2bc23
--- /dev/null
+++ b/meetings.php
@@ -0,0 +1,454 @@
+prepare("INSERT INTO meetings (title, description, agenda, attendees, absentees, meeting_details, start_time, end_time, location, status, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ $stmt->execute([$title, $description, $agenda, $attendees, $absentees, $meeting_details, $start_time, $end_time, $location, $status, $_SESSION['user_id']]);
+ $_SESSION['success'] = 'تم جدولة الاجتماع بنجاح';
+ } else {
+ $stmt = $db->prepare("UPDATE meetings SET title=?, description=?, agenda=?, attendees=?, absentees=?, meeting_details=?, start_time=?, end_time=?, location=?, status=? WHERE id=?");
+ $stmt->execute([$title, $description, $agenda, $attendees, $absentees, $meeting_details, $start_time, $end_time, $location, $status, $id]);
+ $_SESSION['success'] = 'تم تحديث الاجتماع بنجاح';
+ }
+ redirect('meetings.php');
+ } catch (PDOException $e) {
+ $error = 'حدث خطأ: ' . $e->getMessage();
+ }
+ }
+ }
+}
+
+if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
+ if (!canDelete('meetings')) redirect('meetings.php');
+ $id = $_GET['id'];
+ $db = db();
+
+ $stmt = $db->prepare("DELETE FROM meetings WHERE id = ?");
+ $stmt->execute([$id]);
+
+ $_SESSION['success'] = 'تم حذف الاجتماع بنجاح';
+ redirect('meetings.php');
+}
+
+// Fetch Data for List
+$date_from = $_GET['date_from'] ?? date('Y-m-01');
+$date_to = $_GET['date_to'] ?? date('Y-m-t');
+$status_filter = $_GET['status'] ?? '';
+$search = $_GET['search'] ?? '';
+
+$sql = "SELECT m.*, u.username as created_by_name
+ FROM meetings m
+ LEFT JOIN users u ON m.created_by = u.id
+ WHERE DATE(m.start_time) BETWEEN ? AND ?";
+$params = [$date_from, $date_to];
+
+if ($status_filter) {
+ $sql .= " AND m.status = ?";
+ $params[] = $status_filter;
+}
+if ($search) {
+ $sql .= " AND (m.title LIKE ? OR m.description LIKE ? OR m.location LIKE ?)";
+ $params[] = "%$search%";
+ $params[] = "%$search%";
+ $params[] = "%$search%";
+}
+
+$sql .= " ORDER BY m.start_time ASC";
+
+$stmt = db()->prepare($sql);
+$stmt->execute($params);
+$meetings = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+if (isset($_SESSION['success'])) {
+ $success = $_SESSION['success'];
+ unset($_SESSION['success']);
+}
+?>
+
+
+
+
+
+
+
إدارة الاجتماعات
+
+
+
+
+
+
+
+ = $success ?>
+
+
+
+
+
+
+ = $error ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | العنوان |
+ التاريخ والوقت |
+ المكان |
+ المنظم |
+ الحالة |
+ الإجراءات |
+
+
+
+
+
+ | لا توجد اجتماعات مطابقة |
+
+
+
+ 'bg-primary',
+ 'completed' => 'bg-success',
+ 'cancelled' => 'bg-danger',
+ default => 'bg-secondary'
+ };
+ $status_text = match($meeting['status']) {
+ 'scheduled' => 'مجدول',
+ 'completed' => 'منتهي',
+ 'cancelled' => 'ملغي',
+ default => $meeting['status']
+ };
+ // Strip tags for preview, but keep it clean
+ $agenda_preview = strip_tags($meeting['agenda'] ?? '');
+ ?>
+
+ |
+ = htmlspecialchars($meeting['title']) ?>
+
+ = htmlspecialchars($agenda_preview) ?>
+
+ |
+
+ = date('Y-m-d', strtotime($meeting['start_time'])) ?>
+ = date('H:i', strtotime($meeting['start_time'])) ?> - = date('H:i', strtotime($meeting['end_time'])) ?>
+ |
+
+
+ = htmlspecialchars($meeting['location']) ?>
+
+ -
+
+ |
+ = htmlspecialchars($meeting['created_by_name']) ?> |
+ = $status_text ?> |
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/print_meeting.php b/print_meeting.php
new file mode 100644
index 0000000..bae3918
--- /dev/null
+++ b/print_meeting.php
@@ -0,0 +1,260 @@
+prepare("SELECT m.*, u.username as created_by_name FROM meetings m LEFT JOIN users u ON m.created_by = u.id WHERE m.id = ?");
+ $stmt->execute([$id]);
+ $meeting = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$meeting) {
+ die("الاجتماع غير موجود");
+ }
+} catch (PDOException $e) {
+ die("خطأ في قاعدة البيانات");
+}
+
+$settings = get_settings();
+$logo_path = 'uploads/charity/' . ($settings['site_logo'] ?? 'default_logo.png');
+// Check if logo exists
+if (!file_exists($logo_path)) {
+ // Try to find any logo in the directory if the specific one is missing
+ $possible_logos = glob('uploads/charity/*logo*.*');
+ if (!empty($possible_logos)) {
+ $logo_path = $possible_logos[0];
+ } else {
+ $logo_path = '';
+ }
+}
+
+if ($logo_path) {
+ $logo_html = '
';
+} else {
+ $logo_html = '';
+}
+
+?>
+
+
+
+
+ محضر اجتماع - = htmlspecialchars($meeting['title']) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ عنوان الاجتماع:
+ = htmlspecialchars($meeting['title']) ?>
+
+
+ المنظم:
+ = htmlspecialchars($meeting['created_by_name']) ?>
+
+
+ التاريخ:
+ = date('Y-m-d', strtotime($meeting['start_time'])) ?>
+
+
+ الوقت:
+ = date('H:i', strtotime($meeting['start_time'])) ?> - = date('H:i', strtotime($meeting['end_time'])) ?>
+
+
+ المكان:
+ = htmlspecialchars($meeting['location'] ?: 'غير محدد') ?>
+
+
+
+
+
+
+
جدول الأعمال (Agenda)
+
= $meeting['agenda'] ?>
+
+
+
+
+
+
+
الحضور (Present)
+
= nl2br(htmlspecialchars($meeting['attendees'] ?: 'لا يوجد')) ?>
+
+
+
الغياب / الاعتذار (Absent)
+
= nl2br(htmlspecialchars($meeting['absentees'] ?: 'لا يوجد')) ?>
+
+
+
+
+
+
+
تفاصيل الاجتماع / المحضر (Minutes)
+
= $meeting['meeting_details'] ?>
+
+
+
+
+
+
ملاحظات إضافية
+
= $meeting['description'] ?>
+
+
+
+
+
+
توقيع مقرر الاجتماع
+
+
+
+
اعتماد المدير / الرئيس
+
+
+
+
+
+ تم استخراج هذا المستند إلكترونياً من النظام بتاريخ = date('Y-m-d H:i') ?>
+
+
+
+
\ No newline at end of file