From cfd8ea573319110725470430297e25e28a1761c7 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Fri, 13 Feb 2026 07:40:13 +0000 Subject: [PATCH] Autosave: 20260213-074012 --- admin/cases.php | 189 +++++++++------ admin/{organizations.php => categories.php} | 99 ++++---- admin/donations.php | 52 ++-- admin/index.php | 75 ++---- admin/profile.php | 147 ++++++++++++ admin/settings.php | 127 ++++++++++ admin/sidebar.php | 16 ++ assets/images/logo_1770967720.jpg | Bin 0 -> 6101 bytes checkout.php | 9 +- db/thawani_config.php | 23 +- index.php | 249 +++++++++++++------- mail/WablasService.php | 79 +++++++ success.php | 20 +- 13 files changed, 778 insertions(+), 307 deletions(-) rename admin/{organizations.php => categories.php} (58%) create mode 100644 admin/profile.php create mode 100644 admin/settings.php create mode 100644 admin/sidebar.php create mode 100644 assets/images/logo_1770967720.jpg create mode 100644 mail/WablasService.php diff --git a/admin/cases.php b/admin/cases.php index ef887e0..0124646 100644 --- a/admin/cases.php +++ b/admin/cases.php @@ -3,50 +3,55 @@ require_once 'auth.php'; require_once '../db/config.php'; require_login(); -$user = get_user(); $pdo = db(); $msg = ''; // Handle Delete if (isset($_GET['delete'])) { $id = (int)$_GET['delete']; - if (is_super_admin()) { - $pdo->prepare("DELETE FROM cases WHERE id = ?")->execute([$id]); - } else { - $pdo->prepare("DELETE FROM cases WHERE id = ? AND org_id = ?")->execute([$id, $user['org_id']]); - } + $pdo->prepare("DELETE FROM cases WHERE id = ?")->execute([$id]); header('Location: cases.php?success=deleted'); exit; } // Fetch cases -if (is_super_admin()) { - $cases = $pdo->query("SELECT c.*, o.name_en as org_name FROM cases c JOIN organizations o ON c.org_id = o.id")->fetchAll(); - $orgs = $pdo->query("SELECT * FROM organizations")->fetchAll(); -} else { - $cases = $pdo->prepare("SELECT c.*, o.name_en as org_name FROM cases c JOIN organizations o ON c.org_id = o.id WHERE c.org_id = ?"); - $cases->execute([$user['org_id']]); - $cases = $cases->fetchAll(); - $orgs = []; // Org admin doesn't need to select org -} +$cases = $pdo->query("SELECT c.*, cat.name_en as cat_name FROM cases c LEFT JOIN categories cat ON c.category_id = cat.id ORDER BY c.id DESC")->fetchAll(); +$categories = $pdo->query("SELECT * FROM categories")->fetchAll(); // Handle Add/Edit if ($_SERVER['REQUEST_METHOD'] === 'POST') { $id = $_POST['id'] ?? null; - $org_id = is_super_admin() ? $_POST['org_id'] : $user['org_id']; + $category_id = $_POST['category_id']; $title_en = $_POST['title_en']; $title_ar = $_POST['title_ar']; $desc_en = $_POST['desc_en']; $desc_ar = $_POST['desc_ar']; $goal = $_POST['goal']; - $image_url = $_POST['image_url']; + $importance = $_POST['importance'] ?? 'normal'; + $status = $_POST['status'] ?? 'active'; + $image_url = $_POST['image_url_existing'] ?? ''; + + // Handle File Upload + if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) { + $ext = strtolower(pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION)); + $allowed = ['jpg', 'jpeg', 'png', 'webp', 'gif']; + if (in_array($ext, $allowed)) { + $filename = uniqid('case_') . '.' . $ext; + $upload_dir = '../assets/images/cases/'; + if (!is_dir($upload_dir)) mkdir($upload_dir, 0775, true); + + if (move_uploaded_file($_FILES['image']['tmp_name'], $upload_dir . $filename)) { + $image_url = 'assets/images/cases/' . $filename; + } + } + } if ($id) { - $stmt = $pdo->prepare("UPDATE cases SET org_id=?, title_en=?, title_ar=?, desc_en=?, desc_ar=?, goal=?, image_url=? WHERE id=?"); - $stmt->execute([$org_id, $title_en, $title_ar, $desc_en, $desc_ar, $goal, $image_url, $id]); + $stmt = $pdo->prepare("UPDATE cases SET category_id=?, title_en=?, title_ar=?, desc_en=?, desc_ar=?, goal=?, image_url=?, importance=?, status=? WHERE id=?"); + $stmt->execute([$category_id, $title_en, $title_ar, $desc_en, $desc_ar, $goal, $image_url, $importance, $status, $id]); } else { - $stmt = $pdo->prepare("INSERT INTO cases (org_id, title_en, title_ar, desc_en, desc_ar, goal, raised, image_url) VALUES (?, ?, ?, ?, ?, ?, 0, ?)"); - $stmt->execute([$org_id, $title_en, $title_ar, $desc_en, $desc_ar, $goal, $image_url]); + $stmt = $pdo->prepare("INSERT INTO cases (category_id, title_en, title_ar, desc_en, desc_ar, goal, raised, image_url, importance, status) VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, ?)"); + $stmt->execute([$category_id, $title_en, $title_ar, $desc_en, $desc_ar, $goal, $image_url, $importance, $status]); } header('Location: cases.php?success=saved'); exit; @@ -55,13 +60,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $edit_case = null; if (isset($_GET['edit'])) { $id = (int)$_GET['edit']; - if (is_super_admin()) { - $stmt = $pdo->prepare("SELECT * FROM cases WHERE id = ?"); - $stmt->execute([$id]); - } else { - $stmt = $pdo->prepare("SELECT * FROM cases WHERE id = ? AND org_id = ?"); - $stmt->execute([$id, $user['org_id']]); - } + $stmt = $pdo->prepare("SELECT * FROM cases WHERE id = ?"); + $stmt->execute([$id]); $edit_case = $stmt->fetch(); } ?> @@ -82,22 +82,14 @@ if (isset($_GET['edit'])) { .nav-link:hover, .nav-link.active { color: #fff; background: #1f2937; } .nav-link.active { background: var(--primary-color); } .card { border: none; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } + .badge-urgent { background-color: #ef4444; } + .badge-top_priority { background-color: #8b5cf6; } + .badge-normal { background-color: #6b7280; } + .case-img-preview { width: 50px; height: 50px; object-fit: cover; border-radius: 6px; } - +
@@ -119,10 +111,11 @@ if (isset($_GET['edit'])) { - - + + - + + @@ -130,12 +123,39 @@ if (isset($_GET['edit'])) { + + + + - - - - - + - @@ -123,33 +110,29 @@ if (isset($_GET['edit'])) { - - + - @@ -83,11 +60,16 @@ if (is_super_admin()) { + + - - - + diff --git a/admin/index.php b/admin/index.php index cad74c9..f8fe67f 100644 --- a/admin/index.php +++ b/admin/index.php @@ -7,39 +7,18 @@ $user = get_user(); $pdo = db(); // Fetch stats -if (is_super_admin()) { - $total_orgs = $pdo->query("SELECT COUNT(*) FROM organizations")->fetchColumn(); - $total_cases = $pdo->query("SELECT COUNT(*) FROM cases")->fetchColumn(); - $total_donations = $pdo->query("SELECT SUM(amount) FROM donations WHERE status = 'completed'")->fetchColumn() ?: 0; - - // Fetch recent donations - $recent_donations = $pdo->query(" - SELECT d.*, c.title_en as case_title - FROM donations d - JOIN cases c ON d.case_id = c.id - ORDER BY d.created_at DESC - LIMIT 5 - ")->fetchAll(); -} else { - $org_id = $user['org_id']; - $total_cases = $pdo->query("SELECT COUNT(*) FROM cases WHERE org_id = $org_id")->fetchColumn(); - $total_donations = $pdo->query(" - SELECT SUM(d.amount) - FROM donations d - JOIN cases c ON d.case_id = c.id - WHERE c.org_id = $org_id AND d.status = 'completed' - ")->fetchColumn() ?: 0; - - // Fetch recent donations for this org - $recent_donations = $pdo->query(" - SELECT d.*, c.title_en as case_title - FROM donations d - JOIN cases c ON d.case_id = c.id - WHERE c.org_id = $org_id - ORDER BY d.created_at DESC - LIMIT 5 - ")->fetchAll(); -} +$total_categories = $pdo->query("SELECT COUNT(*) FROM categories")->fetchColumn(); +$total_cases = $pdo->query("SELECT COUNT(*) FROM cases")->fetchColumn(); +$total_donations = $pdo->query("SELECT SUM(amount) FROM donations WHERE status = 'completed'")->fetchColumn() ?: 0; + +// Fetch recent donations +$recent_donations = $pdo->query(" + SELECT d.*, c.title_en as case_title + FROM donations d + JOIN cases c ON d.case_id = c.id + ORDER BY d.created_at DESC + LIMIT 5 +")->fetchAll(); ?> @@ -66,44 +45,30 @@ if (is_super_admin()) { - +
-

Welcome,

+

Welcome,

Manage your charity activities and donations.

-
-
Organizations
-
+
Categories
+
- +
- -
+
@@ -114,7 +79,7 @@ if (is_super_admin()) {
-
+
@@ -172,4 +137,4 @@ if (is_super_admin()) {
- \ No newline at end of file + diff --git a/admin/profile.php b/admin/profile.php new file mode 100644 index 0000000..40c07d1 --- /dev/null +++ b/admin/profile.php @@ -0,0 +1,147 @@ +query("SELECT * FROM org_profile LIMIT 1")->fetch(); + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $name_en = $_POST['name_en']; + $name_ar = $_POST['name_ar']; + $description_en = $_POST['description_en']; + $description_ar = $_POST['description_ar']; + $email = $_POST['email']; + $phone = $_POST['phone']; + $address = $_POST['address']; + $logo_url = $profile['logo_url'] ?? ''; + + // Handle Logo Upload + if (isset($_FILES['logo']) && $_FILES['logo']['error'] === UPLOAD_ERR_OK) { + $upload_dir = '../assets/images/'; + if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true); + + $file_ext = pathinfo($_FILES['logo']['name'], PATHINFO_EXTENSION); + $file_name = 'logo_' . time() . '.' . $file_ext; + $target_file = $upload_dir . $file_name; + + if (move_uploaded_file($_FILES['logo']['tmp_name'], $target_file)) { + $logo_url = 'assets/images/' . $file_name; + } + } + + if ($profile) { + $stmt = $pdo->prepare("UPDATE org_profile SET name_en=?, name_ar=?, description_en=?, description_ar=?, email=?, phone=?, address=?, logo_url=? WHERE id=?"); + $stmt->execute([$name_en, $name_ar, $description_en, $description_ar, $email, $phone, $address, $logo_url, $profile['id']]); + } else { + $stmt = $pdo->prepare("INSERT INTO org_profile (name_en, name_ar, description_en, description_ar, email, phone, address, logo_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); + $stmt->execute([$name_en, $name_ar, $description_en, $description_ar, $email, $phone, $address, $logo_url]); + } + + header('Location: profile.php?success=1'); + exit; +} +?> + + + + + + Organization Profile - CharityHub Admin + + + + + + + +
+
+

Organization Profile

+
+ + +
+ Profile updated successfully! + +
+ + +
+
+
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+
+ +
+ + + +
+ +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + + diff --git a/admin/settings.php b/admin/settings.php new file mode 100644 index 0000000..3778907 --- /dev/null +++ b/admin/settings.php @@ -0,0 +1,127 @@ + $value) { + $stmt = $pdo->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = ?"); + $stmt->execute([$value, $key]); + } + header('Location: settings.php?success=1'); + exit; +} + +$settings_raw = $pdo->query("SELECT * FROM settings")->fetchAll(); +$settings = []; +foreach ($settings_raw as $s) { + $settings[$s['setting_key']] = $s['setting_value']; +} +?> + + + + + + Gateway Settings - CharityHub Admin + + + + + + + +
+
+

Gateway Settings

+
+ + +
+ Settings updated successfully! + +
+ + +
+
+ +
+
+
+
Thawani Payment Gateway
+
+
+
+ + +
Your Thawani Secret Key from merchant dashboard.
+
+
+ + +
Your Thawani Publishable Key.
+
+
+ + +
+
+
+
+ + +
+
+
+
Wablas WhatsApp Gateway
+
+
+
+ + +
Your Wablas API Token.
+
+
+ + +
Optional security key if required by your Wablas account.
+
+
+ + +
The server URL for Wablas API (e.g., https://console.wablas.com).
+
+
+
+
+
+ +
+ +
+ +
+ + + + \ No newline at end of file diff --git a/admin/sidebar.php b/admin/sidebar.php new file mode 100644 index 0000000..b81d7df --- /dev/null +++ b/admin/sidebar.php @@ -0,0 +1,16 @@ + + diff --git a/assets/images/logo_1770967720.jpg b/assets/images/logo_1770967720.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7d677aca1d7887859595c3dd9038bf75aa1c2d55 GIT binary patch literal 6101 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 literal 0 HcmV?d00001 diff --git a/checkout.php b/checkout.php index dc51841..1c48f7f 100644 --- a/checkout.php +++ b/checkout.php @@ -11,6 +11,7 @@ $case_id = (int)$_POST['case_id']; $amount = (float)$_POST['amount']; $donor_name = $_POST['donor_name'] ?? 'Anonymous'; $donor_email = $_POST['donor_email'] ?? ''; +$donor_phone = $_POST['donor_phone'] ?? ''; if ($amount <= 0) { die("Invalid amount"); @@ -28,8 +29,8 @@ if (!$case) { } // Create pending donation -$stmt = $pdo->prepare("INSERT INTO donations (case_id, amount, status, donor_name, donor_email) VALUES (?, ?, 'pending', ?, ?)"); -$stmt->execute([$case_id, $amount, $donor_name, $donor_email]); +$stmt = $pdo->prepare("INSERT INTO donations (case_id, amount, status, donor_name, donor_email, donor_phone) VALUES (?, ?, 'pending', ?, ?, ?)"); +$stmt->execute([$case_id, $amount, $donor_name, $donor_email, $donor_phone]); $donation_id = $pdo->lastInsertId(); // Thawani Checkout Session Request @@ -53,7 +54,7 @@ $payload = [ // In a real scenario, we'd use CURL to call Thawani API. // Since we don't have real keys, we'll mock the redirect or show a simulation. -if (THAWANI_SECRET_KEY === 'rRQ26GcsZ60u9Y9v9876543210') { +if (THAWANI_SECRET_KEY === 'rRQ26GcsZ60u9Y9v9876543210' || empty(THAWANI_SECRET_KEY)) { // Simulation Mode ?> @@ -99,4 +100,4 @@ if (isset($data['data']['session_id'])) { } else { echo "Thawani Error: " . ($data['description'] ?? 'Unknown error'); } -*/ +*/ \ No newline at end of file diff --git a/db/thawani_config.php b/db/thawani_config.php index e0c5486..aee6eed 100644 --- a/db/thawani_config.php +++ b/db/thawani_config.php @@ -1,12 +1,25 @@ query("SELECT setting_key, setting_value FROM settings WHERE setting_key LIKE 'thawani_%'"); + $settings = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); + } + return $settings; +} + +$th_settings = get_thawani_settings(); + +define('THAWANI_SECRET_KEY', $th_settings['thawani_secret_key'] ?: getenv('THAWANI_SECRET_KEY') ?: 'rRQ26GcsZ60u9Y9v9876543210'); +define('THAWANI_PUBLISHABLE_KEY', $th_settings['thawani_publishable_key'] ?: getenv('THAWANI_PUBLISHABLE_KEY') ?: 'HGvT9876543210'); +define('THAWANI_ENV', $th_settings['thawani_env'] ?: 'sandbox'); // sandbox or production $thawani_url = (THAWANI_ENV === 'sandbox') ? 'https://uatapi.thawani.om/api/v1' : 'https://api.thawani.om/api/v1'; -define('THAWANI_API_URL', $thawani_url); +define('THAWANI_API_URL', $thawani_url); \ No newline at end of file diff --git a/index.php b/index.php index b1fabdf..82482e7 100644 --- a/index.php +++ b/index.php @@ -11,7 +11,7 @@ $texts = [ 'en' => [ 'title' => 'Support a Cause', 'subtitle' => 'Empower communities worldwide through your generosity.', - 'all_orgs' => 'All Organizations', + 'all_cats' => 'All Categories', 'raised' => 'Raised', 'of' => 'of', 'goal' => 'Goal', @@ -19,19 +19,20 @@ $texts = [ 'lang_name' => 'العربية', 'lang_code' => 'ar', 'hero_title' => 'Make a Real Impact Today', - 'hero_sub' => 'Choose a campaign from our trusted partner organizations and help change lives in minutes.', - 'no_cases' => 'No active cases found for this organization.', + 'hero_sub' => 'Choose a campaign from our trusted categories and help change lives in minutes.', + 'no_cases' => 'No active cases found for this category.', 'admin_panel' => 'Admin Panel', 'modal_title' => 'Make a Donation', 'modal_amount' => 'Amount (OMR)', 'modal_name' => 'Your Name', 'modal_email' => 'Your Email', + 'modal_phone' => 'Phone Number', 'modal_submit' => 'Proceed to Payment', ], 'ar' => [ 'title' => 'ادعم قضية', 'subtitle' => 'مكن المجتمعات في جميع أنحاء العالم من خلال كرمك.', - 'all_orgs' => 'جميع المؤسسات', + 'all_cats' => 'جميع الفئات', 'raised' => 'تم جمع', 'of' => 'من', 'goal' => 'الهدف', @@ -39,13 +40,14 @@ $texts = [ 'lang_name' => 'English', 'lang_code' => 'en', 'hero_title' => 'أحدث تأثيراً حقيقياً اليوم', - 'hero_sub' => 'اختر حملة من مؤسساتنا الشريكة الموثوقة وساعد في تغيير الأرواح في دقائق.', - 'no_cases' => 'لا توجد حالات نشطة لهذه المؤسسة.', + 'hero_sub' => 'اختر حملة من فئاتنا الموثوقة وساعد في تغيير الأرواح في دقائق.', + 'no_cases' => 'لا توجد حالات نشطة لهذه الفئة.', 'admin_panel' => 'لوحة التحكم', 'modal_title' => 'تبرع الآن', 'modal_amount' => 'المبلغ (ريال عماني)', 'modal_name' => 'الاسم', 'modal_email' => 'البريد الإلكتروني', + 'modal_phone' => 'رقم الهاتف', 'modal_submit' => 'الانتقال للدفع', ] ]; @@ -54,27 +56,39 @@ $t = $texts[$lang]; // Database fetch $pdo = db(); -$orgs = $pdo->query("SELECT * FROM organizations")->fetchAll(); -$selected_org = $_GET['org'] ?? 'all'; +$profile = $pdo->query("SELECT * FROM org_profile LIMIT 1")->fetch(); +$categories = $pdo->query("SELECT * FROM categories")->fetchAll(); +$selected_cat = $_GET['cat'] ?? 'all'; -$sql = "SELECT c.*, o.name_en as org_name_en, o.name_ar as org_name_ar +$sql = "SELECT c.*, cat.name_en as cat_name_en, cat.name_ar as cat_name_ar FROM cases c - JOIN organizations o ON c.org_id = o.id"; -if ($selected_org !== 'all') { - $sql .= " WHERE c.org_id = " . (int)$selected_org; + LEFT JOIN categories cat ON c.category_id = cat.id + WHERE c.status = 'active'"; +if ($selected_cat !== 'all') { + $sql .= " AND c.category_id = " . (int)$selected_cat; } +$sql .= " ORDER BY CASE WHEN c.importance = 'top_priority' THEN 1 WHEN c.importance = 'urgent' THEN 2 ELSE 3 END, c.id DESC"; $cases = $pdo->query($sql)->fetchAll(); // Project meta $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? $t['subtitle']; $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; + +// Helper for safe truncation +function safe_truncate($text, $limit = 120) { + if (empty($text)) return ''; + if (function_exists('mb_strimwidth')) { + return mb_strimwidth($text, 0, $limit, "..."); + } + return (strlen($text) > $limit) ? substr($text, 0, $limit) . "..." : $text; +} ?> - <?= $t['title'] ?> + <?= ($lang === 'en' ? ($profile['name_en'] ?? 'Organization') : ($profile['name_ar'] ?? 'المؤسسة')) . ' - ' . $t['title'] ?> @@ -101,7 +115,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; :root { --primary-color: #059669; --primary-hover: #047857; - --bg-light: #f9fafb; + --bg-light: #f3f4f6; --text-main: #111827; --text-muted: #6b7280; --font-family: ; @@ -123,44 +137,51 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; .brand-text { font-weight: 700; - font-size: 1.5rem; - color: var(--primary-color); + font-size: 1.25rem; + color: var(--text-main); text-decoration: none; + display: flex; + align-items: center; + } + + .brand-logo { + height: 40px; + margin-inline-end: 12px; } .hero { - padding: 5rem 0; - background: linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.9)), url('https://images.pexels.com/photos/6646917/pexels-photo-6646917.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1'); - background-size: cover; - background-position: center; + padding: 4rem 0; + background: #fff; + border-bottom: 1px solid #e5e7eb; text-align: center; margin-bottom: 3rem; } .hero h1 { - font-size: 3rem; + font-size: 2.5rem; font-weight: 800; - margin-bottom: 1.5rem; + margin-bottom: 1rem; letter-spacing: -0.025em; } .hero p { - font-size: 1.25rem; + font-size: 1.125rem; color: var(--text-muted); - max-width: 700px; + max-width: 600px; margin: 0 auto; } - .org-tabs { + .cat-tabs { margin-bottom: 2rem; display: flex; - gap: 1rem; + gap: 0.75rem; overflow-x: auto; - padding-bottom: 1rem; + padding-bottom: 0.5rem; + justify-content: center; } - .org-tab { - padding: 0.5rem 1.5rem; + .cat-tab { + padding: 0.5rem 1.25rem; border-radius: 9999px; background: #fff; border: 1px solid #e5e7eb; @@ -168,9 +189,11 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; text-decoration: none; white-space: nowrap; transition: all 0.2s; + font-weight: 500; + font-size: 0.9375rem; } - .org-tab:hover, .org-tab.active { + .cat-tab:hover, .cat-tab.active { background: var(--primary-color); color: #fff; border-color: var(--primary-color); @@ -178,26 +201,46 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; .case-card { background: #fff; - border-radius: 12px; + border-radius: 16px; overflow: hidden; border: 1px solid #e5e7eb; transition: transform 0.2s, box-shadow 0.2s; height: 100%; display: flex; flex-direction: column; + position: relative; } .case-card:hover { transform: translateY(-4px); - box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); + box-shadow: 0 12px 20px -5px rgba(0, 0, 0, 0.08); } .case-image { - height: 200px; + height: 220px; width: 100%; object-fit: cover; } + .importance-badge { + position: absolute; + top: 1rem; + right: 1rem; + padding: 0.35rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.025em; + color: #fff; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + } + [dir="rtl"] .importance-badge { right: auto; left: 1rem; } + + .badge-urgent { background-color: #ef4444; } + .badge-top_priority { background-color: #8b5cf6; } + .badge-normal { display: none; } + .case-content { padding: 1.5rem; flex-grow: 1; @@ -205,29 +248,35 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; flex-direction: column; } - .case-org { - font-size: 0.875rem; + .case-cat { + font-size: 0.8125rem; color: var(--primary-color); - font-weight: 600; + font-weight: 700; margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.05em; } .case-title { font-size: 1.25rem; font-weight: 700; - margin-bottom: 1rem; + margin-bottom: 0.75rem; color: var(--text-main); + line-height: 1.4; } .progress-container { - margin: 1.5rem 0; + margin: 1.25rem 0; + padding: 1.25rem; + background: #f9fafb; + border-radius: 12px; } .progress { - height: 10px; + height: 8px; border-radius: 9999px; background-color: #e5e7eb; - margin-bottom: 0.5rem; + margin-bottom: 0.75rem; } .progress-bar { @@ -237,7 +286,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; .progress-stats { display: flex; justify-content: space-between; - font-size: 0.875rem; + font-size: 0.8125rem; color: var(--text-muted); } @@ -245,24 +294,30 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; background-color: var(--primary-color); color: #fff; border: none; - padding: 0.75rem 1.5rem; - border-radius: 8px; - font-weight: 600; + padding: 0.875rem 1.5rem; + border-radius: 12px; + font-weight: 700; width: 100%; - transition: background 0.2s; + transition: all 0.2s; + margin-top: auto; } .btn-donate:hover { background-color: var(--primary-hover); color: #fff; + transform: scale(1.02); } footer { background: #fff; border-top: 1px solid #e5e7eb; - padding: 3rem 0; + padding: 4rem 0; margin-top: 5rem; - text-align: center; + } + + .footer-logo { + height: 30px; + margin-bottom: 1rem; } /* RTL Adjustments */ @@ -276,11 +331,14 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
Title (EN/AR)OrganizationCaseCategory GoalRaisedStatusImportance Actions
-
- +
+ + + +
+ +
+ +
+
+ +
+
+
+
$
+ Raised: $ +
+ + Active + + Paused + + Disabled + + + + + $$ @@ -152,23 +172,25 @@ if (isset($_GET['edit'])) {
Name (EN/AR)Logo Actions
-
- +
+
logo - - + +
DonorContact CaseOrganization Amount Status Date
-
- + +
+
+
+
+
+
$ @@ -99,7 +81,7 @@ if (is_super_admin()) {
No donations found.No donations found.