updaing meeting

This commit is contained in:
Flatlogic Bot 2026-03-27 07:10:38 +00:00
parent 10d64f8648
commit 07691b3ce6
5 changed files with 130 additions and 150 deletions

View File

@ -4,67 +4,7 @@ session_start();
require_once __DIR__ . '/../db/config.php'; require_once __DIR__ . '/../db/config.php';
// --- Helper Functions (MUST BE DEFINED BEFORE settings.php) --- // --- Helper Functions (MUST BE DEFINED BEFORE settings.php) ---
require_once __DIR__ . '/permissions.php';
function isLoggedIn() {
return isset($_SESSION['user_id']);
}
function isSuperAdmin() {
return isset($_SESSION['is_super_admin']) && $_SESSION['is_super_admin'] == 1;
}
function isAdmin() {
if (isSuperAdmin()) return true;
if (isset($_SESSION['user_role']) && strtolower($_SESSION['user_role']) === 'admin') return true;
if (isset($_SESSION['role']) && strtolower($_SESSION['role']) === 'admin') return true;
return false;
}
function redirect($path) {
if (!headers_sent()) {
header("Location: $path");
} else {
echo "<script>window.location.href='$path';</script>";
}
exit;
}
// Permission helpers
function canView($page = null) {
if (isAdmin()) return true;
if ($page) {
return $_SESSION['permissions'][$page]['view'] ?? false;
}
return $_SESSION['can_view'] ?? false;
}
function canAdd($page = null) {
if (isAdmin()) return true;
if ($page) {
return $_SESSION['permissions'][$page]['add'] ?? false;
}
return $_SESSION['can_add'] ?? false;
}
function canEdit($page = null) {
if (isAdmin()) return true;
if ($page) {
return $_SESSION['permissions'][$page]['edit'] ?? false;
}
return $_SESSION['can_edit'] ?? false;
}
function canDelete($page = null) {
if (isAdmin()) return true;
if ($page) {
return $_SESSION['permissions'][$page]['delete'] ?? false;
}
return $_SESSION['can_delete'] ?? false;
}
function canViewInternal() {
return canView('internal');
}
// Now load centralized settings (which may use the helpers above) // Now load centralized settings (which may use the helpers above)
require_once __DIR__ . '/settings.php'; require_once __DIR__ . '/settings.php';

64
includes/permissions.php Normal file
View File

@ -0,0 +1,64 @@
<?php
// --- Helper Functions (Extracted from header.php) ---
function isLoggedIn() {
return isset($_SESSION['user_id']);
}
function isSuperAdmin() {
return isset($_SESSION['is_super_admin']) && $_SESSION['is_super_admin'] == 1;
}
function isAdmin() {
if (isSuperAdmin()) return true;
if (isset($_SESSION['user_role']) && strtolower($_SESSION['user_role']) === 'admin') return true;
if (isset($_SESSION['role']) && strtolower($_SESSION['role']) === 'admin') return true;
return false;
}
function redirect($path) {
if (!headers_sent()) {
header("Location: $path");
} else {
echo "<script>window.location.href='$path';</script>";
}
exit;
}
// Permission helpers
function canView($page = null) {
if (isAdmin()) return true;
if ($page) {
return $_SESSION['permissions'][$page]['view'] ?? false;
}
return $_SESSION['can_view'] ?? false;
}
function canAdd($page = null) {
if (isAdmin()) return true;
if ($page) {
return $_SESSION['permissions'][$page]['add'] ?? false;
}
return $_SESSION['can_add'] ?? false;
}
function canEdit($page = null) {
if (isAdmin()) return true;
if ($page) {
return $_SESSION['permissions'][$page]['edit'] ?? false;
}
return $_SESSION['can_edit'] ?? false;
}
function canDelete($page = null) {
if (isAdmin()) return true;
if ($page) {
return $_SESSION['permissions'][$page]['delete'] ?? false;
}
return $_SESSION['can_delete'] ?? false;
}
function canViewInternal() {
return canView('internal');
}

View File

@ -96,16 +96,16 @@ if (isset($_SESSION['success'])) {
} }
?> ?>
<!-- Quill CSS --> <!-- Summernote Lite CSS -->
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-lite.min.css" rel="stylesheet">
<style> <style>
/* Custom Quill Styles for Bootstrap Integration */ /* Custom Styles for Summernote Integration */
.ql-container { .note-editor .note-toolbar {
font-family: 'Cairo', sans-serif; background: #f8f9fa;
font-size: 1rem;
} }
.ql-editor { .note-editable {
min-height: 150px; background: #fff;
min-height: 200px;
} }
</style> </style>
@ -260,63 +260,58 @@ if (isset($_SESSION['success'])) {
<input type="hidden" name="id" id="modalId" value="0"> <input type="hidden" name="id" id="modalId" value="0">
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-bold">عنوان الاجتماع (Title)</label> <label class="form-label fw-bold">عنوان الاجتماع</label>
<input type="text" name="title" id="modalTitleInput" class="form-control" required placeholder="مثال: اجتماع الفريق الأسبوعي"> <input type="text" name="title" id="modalTitleInput" class="form-control" required placeholder="مثال: اجتماع الفريق الأسبوعي">
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label class="form-label fw-bold">وقت البدء (Start)</label> <label class="form-label fw-bold">وقت البدء</label>
<input type="datetime-local" name="start_time" id="modalStartTime" class="form-control" required> <input type="datetime-local" name="start_time" id="modalStartTime" class="form-control" required>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label class="form-label fw-bold">وقت الانتهاء (End)</label> <label class="form-label fw-bold">وقت الانتهاء</label>
<input type="datetime-local" name="end_time" id="modalEndTime" class="form-control" required> <input type="datetime-local" name="end_time" id="modalEndTime" class="form-control" required>
</div> </div>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-bold">الموقع / الرابط (Place Held)</label> <label class="form-label fw-bold">الموقع / الرابط</label>
<input type="text" name="location" id="modalLocation" class="form-control" placeholder="غرفة الاجتماعات، Zoom، Google Meet..."> <input type="text" name="location" id="modalLocation" class="form-control" placeholder="غرفة الاجتماعات، Zoom، Google Meet...">
</div> </div>
<!-- Hidden inputs for Quill content -->
<input type="hidden" name="agenda" id="hiddenAgenda">
<input type="hidden" name="meeting_details" id="hiddenMeetingDetails">
<input type="hidden" name="description" id="hiddenDescription">
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-bold">جدول الأعمال (Agenda) <span class="badge bg-secondary">Rich Text</span></label> <label class="form-label fw-bold">جدول الأعمال</label>
<div id="editorAgenda"></div> <textarea name="agenda" id="agenda" class="summernote" placeholder="أدخل بنود جدول الأعمال والمواضيع المطروحة للنقاش هنا..."></textarea>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label class="form-label fw-bold">الحضور (Attendees)</label> <label class="form-label fw-bold">الحضور</label>
<textarea name="attendees" id="modalAttendees" class="form-control" rows="2" placeholder="أسماء الحضور..."></textarea> <textarea name="attendees" id="modalAttendees" class="form-control" rows="2" placeholder="أسماء الحضور..."></textarea>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label class="form-label fw-bold">الغياب (Absentees)</label> <label class="form-label fw-bold">الغياب</label>
<textarea name="absentees" id="modalAbsentees" class="form-control" rows="2" placeholder="أسماء الغائبين..."></textarea> <textarea name="absentees" id="modalAbsentees" class="form-control" rows="2" placeholder="أسماء الغائبين..."></textarea>
</div> </div>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-bold">تفاصيل الاجتماع / المحضر (Meeting Details) <span class="badge bg-secondary">Rich Text</span></label> <label class="form-label fw-bold">تفاصيل الاجتماع / المحضر</label>
<div id="editorMeetingDetails"></div> <textarea name="meeting_details" id="meeting_details" class="summernote" placeholder="أدخل تفاصيل محضر الاجتماع، القرارات المتخذة، والنقاط التي تمت مناقشتها..."></textarea>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-bold">ملاحظات إضافية (Description) <span class="badge bg-secondary">Rich Text</span></label> <label class="form-label fw-bold">ملاحظات إضافية</label>
<div id="editorDescription"></div> <textarea name="description" id="description" class="summernote" placeholder="أي ملاحظات إضافية..."></textarea>
</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="status" id="modalStatus" class="form-select"> <select name="status" id="modalStatus" class="form-select">
<option value="scheduled">مجدول (Scheduled)</option> <option value="scheduled">مجدول</option>
<option value="completed">منتهي (Completed)</option> <option value="completed">منتهي</option>
<option value="cancelled">ملغي (Cancelled)</option> <option value="cancelled">ملغي</option>
</select> </select>
</div> </div>
</div> </div>
@ -331,53 +326,31 @@ if (isset($_SESSION['success'])) {
<?php require_once __DIR__ . '/includes/footer.php'; ?> <?php require_once __DIR__ . '/includes/footer.php'; ?>
<!-- Quill JS --> <!-- jQuery (required for Summernote) -->
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<!-- Summernote Lite JS -->
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-lite.min.js"></script>
<script> <script>
// Initialize Quill editors $(document).ready(function() {
var quillAgenda, quillMeetingDetails, quillDescription; // Initialize Summernote
$('.summernote').each(function() {
document.addEventListener('DOMContentLoaded', function() { $(this).summernote({
var toolbarOptions = [ placeholder: $(this).attr('placeholder') || 'أدخل التفاصيل هنا...',
['bold', 'italic', 'underline', 'strike'], // toggled buttons tabsize: 2,
['blockquote', 'code-block'], height: 200,
toolbar: [
[{ 'header': 1 }, { 'header': 2 }], // custom button values ['style', ['style']],
[{ 'list': 'ordered'}, { 'list': 'bullet' }], ['font', ['bold', 'underline', 'clear', 'strikethrough', 'superscript', 'subscript']],
[{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript ['fontname', ['fontname']],
[{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent ['color', ['color']],
[{ 'direction': 'rtl' }], // text direction ['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown ['insert', ['link', 'picture', 'video', 'hr']],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }], ['view', ['fullscreen', 'codeview', 'help']]
],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme // Ensure RTL support if needed (Summernote usually auto-detects or needs plugin, but 'dir=rtl' on body often helps)
[{ 'font': [] }],
[{ 'align': [] }],
['clean'] // remove formatting button
];
quillAgenda = new Quill('#editorAgenda', {
modules: { toolbar: toolbarOptions },
theme: 'snow'
}); });
quillMeetingDetails = new Quill('#editorMeetingDetails', {
modules: { toolbar: toolbarOptions },
theme: 'snow'
});
quillDescription = new Quill('#editorDescription', {
modules: { toolbar: toolbarOptions },
theme: 'snow'
});
// Form Submission Handling
document.getElementById('meetingForm').addEventListener('submit', function() {
document.getElementById('hiddenAgenda').value = quillAgenda.root.innerHTML;
document.getElementById('hiddenMeetingDetails').value = quillMeetingDetails.root.innerHTML;
document.getElementById('hiddenDescription').value = quillDescription.root.innerHTML;
}); });
}); });
@ -391,6 +364,9 @@ function openModal(action, data = null) {
document.getElementById('modalAction').value = action; document.getElementById('modalAction').value = action;
const title = document.getElementById('modalTitle'); const title = document.getElementById('modalTitle');
// Reset Summernote content first
$('.summernote').summernote('code', '');
if (action === 'add') { if (action === 'add') {
title.textContent = 'جدولة اجتماع جديد'; title.textContent = 'جدولة اجتماع جديد';
document.getElementById('modalId').value = 0; document.getElementById('modalId').value = 0;
@ -399,11 +375,6 @@ function openModal(action, data = null) {
document.getElementById('modalAbsentees').value = ''; document.getElementById('modalAbsentees').value = '';
document.getElementById('modalLocation').value = ''; document.getElementById('modalLocation').value = '';
// Clear Quill content
quillAgenda.setText('');
quillMeetingDetails.setText('');
quillDescription.setText('');
// Default start time: Next hour, :00 // Default start time: Next hour, :00
const now = new Date(); const now = new Date();
now.setMinutes(0, 0, 0); now.setMinutes(0, 0, 0);
@ -436,11 +407,10 @@ function openModal(action, data = null) {
document.getElementById('modalEndTime').value = data.end_time.replace(' ', 'T').slice(0, 16); document.getElementById('modalEndTime').value = data.end_time.replace(' ', 'T').slice(0, 16);
document.getElementById('modalStatus').value = data.status; document.getElementById('modalStatus').value = data.status;
// Set Quill content (safely handle nulls) // Set Summernote content
// Note: We use clipboard.dangerouslyPasteHTML to properly render existing HTML $('#agenda').summernote('code', data.agenda || '');
quillAgenda.clipboard.dangerouslyPasteHTML(data.agenda || ''); $('#meeting_details').summernote('code', data.meeting_details || '');
quillMeetingDetails.clipboard.dangerouslyPasteHTML(data.meeting_details || ''); $('#description').summernote('code', data.description || '');
quillDescription.clipboard.dangerouslyPasteHTML(data.description || '');
} }
meetingModal.show(); meetingModal.show();

View File

@ -1,6 +1,7 @@
<?php <?php
require_once __DIR__ . '/db/config.php'; require_once __DIR__ . '/db/config.php';
require_once __DIR__ . '/includes/settings.php'; require_once __DIR__ . '/includes/settings.php';
require_once __DIR__ . '/includes/permissions.php';
session_start(); session_start();
@ -9,6 +10,10 @@ if (!isset($_SESSION['user_id'])) {
exit; exit;
} }
if (!canView('meetings')) {
die("ليس لديك صلاحية لعرض هذه الصفحة");
}
$id = $_GET['id'] ?? 0; $id = $_GET['id'] ?? 0;
if (!$id) { if (!$id) {
@ -209,7 +214,7 @@ if ($logo_path) {
<?php if ($meeting['agenda']): ?> <?php if ($meeting['agenda']): ?>
<div class="section"> <div class="section">
<div class="section-title">جدول الأعمال (Agenda)</div> <div class="section-title">جدول الأعمال</div>
<div class="content-box rich-text"><?= $meeting['agenda'] ?></div> <div class="content-box rich-text"><?= $meeting['agenda'] ?></div>
</div> </div>
<?php endif; ?> <?php endif; ?>
@ -217,11 +222,11 @@ if ($logo_path) {
<div class="section"> <div class="section">
<div class="info-grid"> <div class="info-grid">
<div> <div>
<div class="section-title">الحضور (Present)</div> <div class="section-title">الحضور</div>
<div class="content-box"><?= nl2br(htmlspecialchars($meeting['attendees'] ?: 'لا يوجد')) ?></div> <div class="content-box"><?= nl2br(htmlspecialchars($meeting['attendees'] ?: 'لا يوجد')) ?></div>
</div> </div>
<div> <div>
<div class="section-title">الغياب / الاعتذار (Absent)</div> <div class="section-title">الغياب / الاعتذار</div>
<div class="content-box"><?= nl2br(htmlspecialchars($meeting['absentees'] ?: 'لا يوجد')) ?></div> <div class="content-box"><?= nl2br(htmlspecialchars($meeting['absentees'] ?: 'لا يوجد')) ?></div>
</div> </div>
</div> </div>
@ -229,7 +234,7 @@ if ($logo_path) {
<?php if ($meeting['meeting_details']): ?> <?php if ($meeting['meeting_details']): ?>
<div class="section"> <div class="section">
<div class="section-title">تفاصيل الاجتماع / المحضر (Minutes)</div> <div class="section-title">تفاصيل الاجتماع / المحضر</div>
<div class="content-box rich-text" style="min-height: 150px;"><?= $meeting['meeting_details'] ?></div> <div class="content-box rich-text" style="min-height: 150px;"><?= $meeting['meeting_details'] ?></div>
</div> </div>
<?php endif; ?> <?php endif; ?>

View File

@ -30,7 +30,8 @@ $modules = [
'stock_reports' => 'المخزون - التقارير', 'stock_reports' => 'المخزون - التقارير',
'stock_settings' => 'المخزون - الإعدادات', 'stock_settings' => 'المخزون - الإعدادات',
'expenses' => 'المصروفات', 'expenses' => 'المصروفات',
'expense_settings' => 'المصروفات - الإعدادات' 'expense_settings' => 'المصروفات - الإعدادات',
'meetings' => 'الاجتماعات'
]; ];
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST') {