From e37d1f25a4061d26489a9822173df5474c8e5abc Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 15 Feb 2026 05:48:33 +0000 Subject: [PATCH] adding whatsapp templetes --- admin/cases.php | 32 +++-- admin/i18n.php | 22 +++ admin/sidebar.php | 3 + admin/whatsapp_template_edit.php | 96 +++++++++++++ admin/whatsapp_templates.php | 87 ++++++++++++ case.php | 13 +- ...60215_add_contact_phone_to_cases_table.sql | 1 + ...260215_create_whatsapp_templates_table.sql | 53 +++++++ includes/footer.php | 55 +++++++- index.php | 11 +- mail/WablasService.php | 133 +++++++++++------- success.php | 10 +- 12 files changed, 437 insertions(+), 79 deletions(-) create mode 100644 admin/whatsapp_template_edit.php create mode 100644 admin/whatsapp_templates.php create mode 100644 db/migrations/20260215_add_contact_phone_to_cases_table.sql create mode 100644 db/migrations/20260215_create_whatsapp_templates_table.sql diff --git a/admin/cases.php b/admin/cases.php index 1e5145e..bd03c3f 100644 --- a/admin/cases.php +++ b/admin/cases.php @@ -60,6 +60,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST[' $goal = $_POST['goal']; $importance = $_POST['importance'] ?? 'normal'; $status = $_POST['status'] ?? 'active'; + $contact_phone = $_POST['contact_phone'] ?? null; $image_url = $_POST['image_url_existing'] ?? ''; // Handle File Upload @@ -85,12 +86,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST[' } if ($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]); + $stmt = $pdo->prepare("UPDATE cases SET category_id=?, title_en=?, title_ar=?, desc_en=?, desc_ar=?, goal=?, image_url=?, importance=?, status=?, contact_phone=? WHERE id=?"); + $stmt->execute([$category_id, $title_en, $title_ar, $desc_en, $desc_ar, $goal, $image_url, $importance, $status, $contact_phone, $id]); log_action('edit_case', "Updated case: $title_en (ID: $id)", $id); } else { - $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]); + $stmt = $pdo->prepare("INSERT INTO cases (category_id, title_en, title_ar, desc_en, desc_ar, goal, raised, image_url, importance, status, contact_phone) VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?)"); + $stmt->execute([$category_id, $title_en, $title_ar, $desc_en, $desc_ar, $goal, $image_url, $importance, $status, $contact_phone]); $new_id = $pdo->lastInsertId(); log_action('create_case', "Created new case: $title_en (ID: $new_id)", $new_id); } @@ -289,12 +290,19 @@ $is_rtl = (get_current_lang() === 'ar'); -
- - - @@ -369,6 +377,7 @@ $is_rtl = (get_current_lang() === 'ar'); document.getElementById('caseGoal').value = ''; document.getElementById('caseImportance').value = 'normal'; document.getElementById('caseStatus').value = 'active'; + document.getElementById('caseContactPhone').value = ''; document.getElementById('caseImageUrlExisting').value = ''; document.getElementById('imagePreviewContainer').style.display = 'none'; document.getElementById('modalTitle').innerText = ''; @@ -432,6 +441,7 @@ $is_rtl = (get_current_lang() === 'ar'); document.getElementById('caseGoal').value = ''; document.getElementById('caseImportance').value = ''; document.getElementById('caseStatus').value = ''; + document.getElementById('caseContactPhone').value = ''; document.getElementById('caseImageUrlExisting').value = ''; if ('') { @@ -445,4 +455,4 @@ $is_rtl = (get_current_lang() === 'ar'); - \ No newline at end of file + diff --git a/admin/i18n.php b/admin/i18n.php index efb1bd8..6d5e1c9 100644 --- a/admin/i18n.php +++ b/admin/i18n.php @@ -221,6 +221,17 @@ $translations = [ 'Donor' => 'Donor', 'Amount' => 'Amount', 'Date' => 'Date', + 'WhatsApp Templates' => 'WhatsApp Templates', + 'Edit WhatsApp Template' => 'Edit WhatsApp Template', + 'Back to Templates' => 'Back to Templates', + 'Template Name' => 'Template Name', + 'Variables' => 'Variables', + 'You can use these variables in your template.' => 'You can use these variables in your template.', + 'Template Body (English)' => 'Template Body (English)', + 'Template Body (Arabic)' => 'Template Body (Arabic)', + 'Enabled' => 'Enabled', + 'Contact Phone' => 'Contact Phone', + 'Optional: For WhatsApp notifications to the case manager.' => 'Optional: For WhatsApp notifications to the case manager.', ], 'ar' => [ 'about_us_page' => 'صفحة من نحن', @@ -430,6 +441,17 @@ $translations = [ 'Donor' => 'المتبرع', 'Amount' => 'المبلغ', 'Date' => 'التاريخ', + 'WhatsApp Templates' => 'قوالب الواتساب', + 'Edit WhatsApp Template' => 'تعديل قالب الواتساب', + 'Back to Templates' => 'الرجوع إلى القوالب', + 'Template Name' => 'اسم القالب', + 'Variables' => 'المتغيرات', + 'You can use these variables in your template.' => 'يمكنك استخدام هذه المتغيرات في القالب الخاص بك.', + 'Template Body (English)' => 'نص القالب (انجليزي)', + 'Template Body (Arabic)' => 'نص القالب (عربي)', + 'Enabled' => 'مفعل', + 'Contact Phone' => 'رقم هاتف الاتصال', + 'Optional: For WhatsApp notifications to the case manager.' => 'اختياري: لإشعارات الواتساب لمدير الحالة.', ] ]; diff --git a/admin/sidebar.php b/admin/sidebar.php index c10cf53..1e8f2bc 100644 --- a/admin/sidebar.php +++ b/admin/sidebar.php @@ -28,6 +28,9 @@ $current_lang = get_current_lang(); + + + diff --git a/admin/whatsapp_template_edit.php b/admin/whatsapp_template_edit.php new file mode 100644 index 0000000..94f2943 --- /dev/null +++ b/admin/whatsapp_template_edit.php @@ -0,0 +1,96 @@ + +prepare("UPDATE whatsapp_templates SET template_body_en=?, template_body_ar=?, status=? WHERE id=?"); + $stmt->execute([$template_body_en, $template_body_ar, $status, $id]); + + header('Location: whatsapp_templates.php?success=saved'); + exit; +} + +$stmt = $pdo->prepare("SELECT * FROM whatsapp_templates WHERE id = ?"); +$stmt->execute([$id]); +$template = $stmt->fetch(); + +if (!$template) { + header('Location: whatsapp_templates.php'); + exit; +} + +$is_rtl = (get_current_lang() === 'ar'); +?> + + + + + + <?= __('Edit WhatsApp Template') ?> - <?= htmlspecialchars(get_org_name()) ?> + + + + + + + + + + + + + + +
+
+

+ +
+ +
+
+ +
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ > + +
+ +
+
+
+ + + + diff --git a/admin/whatsapp_templates.php b/admin/whatsapp_templates.php new file mode 100644 index 0000000..508c1a2 --- /dev/null +++ b/admin/whatsapp_templates.php @@ -0,0 +1,87 @@ + +query("SELECT * FROM whatsapp_templates ORDER BY template_name")->fetchAll(); + +$is_rtl = (get_current_lang() === 'ar'); +?> + + + + + + <?= __('WhatsApp Templates') ?> - <?= htmlspecialchars(get_org_name()) ?> + + + + + + + + + + + + + + +
+
+

+
+ + +
+ + +
+ + +
+
+ + + + + + + + + + + + + + + + + +
+
+ Variables: +
+ + + + + + + +
+
+
+
+ + + + diff --git a/case.php b/case.php index 58457d0..e12502e 100644 --- a/case.php +++ b/case.php @@ -1,4 +1,4 @@ -''' 'العربية', 'lang_code' => 'ar', 'goal_reached' => 'Goal Reached! Campaign Completed.', + 'modal_name_placeholder' => 'Anonymous Donor', + 'modal_email_placeholder' => 'you@example.com', ], 'ar' => [ 'title' => 'تفاصيل الحالة', @@ -65,6 +67,8 @@ $texts = [ 'lang_name' => 'English', 'lang_code' => 'en', 'goal_reached' => 'تم تحقيق الهدف! الحملة مكتملة.', + 'modal_name_placeholder' => 'فاعل خير', + 'modal_email_placeholder' => 'you@example.com', ] ]; @@ -214,12 +218,12 @@ require_once 'includes/header.php';
- +
- +
@@ -296,5 +300,4 @@ require_once 'includes/header.php'; } - -''' + \ No newline at end of file diff --git a/db/migrations/20260215_add_contact_phone_to_cases_table.sql b/db/migrations/20260215_add_contact_phone_to_cases_table.sql new file mode 100644 index 0000000..36e5dbe --- /dev/null +++ b/db/migrations/20260215_add_contact_phone_to_cases_table.sql @@ -0,0 +1 @@ +ALTER TABLE `cases` ADD `contact_phone` VARCHAR(255) NULL DEFAULT NULL AFTER `status`; \ No newline at end of file diff --git a/db/migrations/20260215_create_whatsapp_templates_table.sql b/db/migrations/20260215_create_whatsapp_templates_table.sql new file mode 100644 index 0000000..ae4fe68 --- /dev/null +++ b/db/migrations/20260215_create_whatsapp_templates_table.sql @@ -0,0 +1,53 @@ +CREATE TABLE `whatsapp_templates` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `template_name` varchar(255) NOT NULL, + `template_body_en` text DEFAULT NULL, + `template_body_ar` text DEFAULT NULL, + `variables` varchar(255) DEFAULT NULL, + `status` tinyint(1) NOT NULL DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `template_name` (`template_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +INSERT INTO `whatsapp_templates` (`template_name`, `template_body_en`, `template_body_ar`, `variables`) VALUES +('donation_thank_you', 'Dear {donor_name}, + +Thank you for your generous donation of OMR {amount} to "{case_title}". + +Your support makes a real difference! ❤️ + +{org_name} Team', 'عزيزي {donor_name}، + +نشكرك على تبرعك السخي بمبلغ {amount} ريال عماني لـ "{case_title}". + +دعمك يصنع فرقًا حقيقيًا! ❤️ + +فريق {org_name}', '{donor_name}, {amount}, {case_title}, {org_name}'), +('donation_gift_notification', 'Hello {recipient_name}! ✨ + +{donor_name} has made a donation to "{case_title}" in your name as a special gift.{gift_message} + +May this kindness bring joy to your day! ❤️ + +{org_name} Team', 'أهلاً {recipient_name}! ✨ + +لقد قدم {donor_name} تبرعًا لـ "{case_title}" باسمك كهدية خاصة.{gift_message} + +نرجو أن يجلب هذا اللطف الفرح ليومك! ❤️ + +فريق {org_name}', '{recipient_name}, {donor_name}, {case_title}, {gift_message}, {org_name}'), +('case_donation_notification', 'Hello! + +A donation of OMR {amount} was just made for "{case_title}" by {donor_name}. + +Thank you for your efforts in managing this case. + +{org_name} Team', 'أهلاً! + +تم تقديم تبرع بمبلغ {amount} ريال عماني لـ "{case_title}" من قبل {donor_name}. + +نشكرك على جهودك في إدارة هذه الحالة. + +فريق {org_name}', '{amount}, {case_title}, {donor_name}, {org_name}'); diff --git a/includes/footer.php b/includes/footer.php index 60e702f..46e742b 100644 --- a/includes/footer.php +++ b/includes/footer.php @@ -1,11 +1,58 @@ -
+'''

© . All rights reserved.

-

Address, City, Country

-

Phone: +123456789 | Email: info@example.com

+ + +

+ + + +

+ + + + + | + + + + +

+
-
\ No newline at end of file +
+ +''' \ No newline at end of file diff --git a/index.php b/index.php index e0bd86f..9e1adf8 100644 --- a/index.php +++ b/index.php @@ -1,4 +1,4 @@ -''' 'Home', 'about_us' => 'About Us', 'contact_us' => 'Contact Us', + 'modal_name_placeholder' => 'Anonymous Donor', + 'modal_email_placeholder' => 'you@example.com', ], 'ar' => [ 'title' => 'ادعم قضية', @@ -89,6 +91,8 @@ $texts = [ 'home' => 'الرئيسية', 'about_us' => 'من نحن', 'contact_us' => 'اتصل بنا', + 'modal_name_placeholder' => 'فاعل خير', + 'modal_email_placeholder' => 'you@example.com', ] ]; @@ -537,12 +541,12 @@ require_once 'includes/header.php';
- +
- +
@@ -639,4 +643,3 @@ require_once 'includes/header.php'; -'' \ No newline at end of file diff --git a/mail/WablasService.php b/mail/WablasService.php index 5410268..d069abf 100644 --- a/mail/WablasService.php +++ b/mail/WablasService.php @@ -15,28 +15,19 @@ class WablasService { return ['success' => false, 'error' => 'Settings missing']; } - // Clean phone number (remove +, spaces, etc) $to = preg_replace('/[^0-9]/', '', $to); - - // Add 968 prefix if missing and it's an 8-digit Omani number if (strlen($to) === 8) { $to = '968' . $to; } - // Prepare data - $data = [ - 'phone' => $to, - 'message' => $message, - ]; - - // Add security key if provided (using both common keys to ensure compatibility) + $data = ['phone' => $to, 'message' => $message]; if (!empty($securityKey)) { $data['security_key'] = $securityKey; $data['secret_key'] = $securityKey; } $curl = curl_init(); - curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: $token")); + curl_setopt($curl, CURLOPT_HTTPHEADER, ["Authorization: $token"]); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data)); @@ -62,52 +53,94 @@ class WablasService { return ['success' => false, 'error' => $result]; } - public static function getOrgName() { + public static function getOrgName($lang = 'en') { $pdo = db(); - $org = $pdo->query("SELECT name_en FROM org_profile LIMIT 1")->fetch(); - return $org['name_en'] ?? 'Organization'; + $org = $pdo->query("SELECT name_en, name_ar FROM org_profile LIMIT 1")->fetch(); + return ($lang === 'ar') ? ($org['name_ar'] ?? 'المنظمة') : ($org['name_en'] ?? 'Organization'); } - public static function sendThankYou($donation) { - $name = !empty($donation['donor_name']) ? $donation['donor_name'] : 'Donor'; - $amount = number_format($donation['amount'], 3); - $orgName = self::getOrgName(); - - // Fetch case title - $pdo = db(); - $stmt = $pdo->prepare("SELECT title_en FROM cases WHERE id = ?"); - $stmt->execute([$donation['case_id']]); - $case = $stmt->fetch(); - $caseTitle = $case ? $case['title_en'] : 'a cause'; - - $message = "Dear $name,\n\nThank you for your generous donation of OMR $amount to \"$caseTitle\".\n\nYour support makes a real difference! ❤️\n\n$orgName Team"; - - if (!empty($donation['donor_phone'])) { - return self::sendMessage($donation['donor_phone'], $message); - } - - return ['success' => false, 'error' => 'No phone number provided']; - } - - public static function sendGiftNotification($donation) { - if (empty($donation['is_gift']) || empty($donation['gift_recipient_phone'])) { - return ['success' => false, 'error' => 'Not a gift or no recipient phone']; + private static function sendTemplatedMessage($to, $templateName, $vars, $lang = 'en') { + if (empty($to)) { + return ['success' => false, 'error' => 'Recipient phone number is missing.']; } - $donorName = !empty($donation['donor_name']) ? $donation['donor_name'] : 'A generous donor'; - $recipientName = !empty($donation['gift_recipient_name']) ? $donation['gift_recipient_name'] : 'Friend'; - $giftMessage = !empty($donation['gift_message']) ? "\n\nMessage: \"" . $donation['gift_message'] . "\"" : ""; - $orgName = self::getOrgName(); - - // Fetch case title $pdo = db(); - $stmt = $pdo->prepare("SELECT title_en FROM cases WHERE id = ?"); + $stmt = $pdo->prepare("SELECT * FROM whatsapp_templates WHERE template_name = ? AND status = 1"); + $stmt->execute([$templateName]); + $template = $stmt->fetch(); + + if (!$template) { + error_log("WhatsApp template '$templateName' not found or is disabled."); + return ['success' => false, 'error' => "Template '$templateName' not found or disabled."]; + } + + $messageBody = ($lang === 'ar' && !empty($template['template_body_ar'])) ? $template['template_body_ar'] : $template['template_body_en']; + + foreach ($vars as $key => $value) { + $messageBody = str_replace('{'.$key.'}', $value, $messageBody); + } + + return self::sendMessage($to, $messageBody); + } + + public static function sendThankYou($donation, $lang = 'en') { + $pdo = db(); + $stmt = $pdo->prepare("SELECT title_en, title_ar FROM cases WHERE id = ?"); $stmt->execute([$donation['case_id']]); $case = $stmt->fetch(); - $caseTitle = $case ? $case['title_en'] : 'a charitable cause'; + $caseTitle = ($lang === 'ar' && !empty($case['title_ar'])) ? $case['title_ar'] : $case['title_en']; - $message = "Hello $recipientName! ✨\n\n$donorName has made a donation to \"$caseTitle\" in your name as a special gift.$giftMessage\n\nMay this kindness bring joy to your day! ❤️\n\n$orgName Team"; - - return self::sendMessage($donation['gift_recipient_phone'], $message); + $vars = [ + 'donor_name' => !empty($donation['donor_name']) ? $donation['donor_name'] : (($lang === 'ar') ? 'فاعل خير' : 'Anonymous'), + 'amount' => number_format($donation['amount'], 3), + 'case_title' => $caseTitle, + 'org_name' => self::getOrgName($lang) + ]; + + return self::sendTemplatedMessage($donation['donor_phone'], 'donation_thank_you', $vars, $lang); } -} + + public static function sendGiftNotification($donation, $lang = 'en') { + if (empty($donation['is_gift'])) { + return ['success' => false, 'error' => 'Not a gift']; + } + + $pdo = db(); + $stmt = $pdo->prepare("SELECT title_en, title_ar FROM cases WHERE id = ?"); + $stmt->execute([$donation['case_id']]); + $case = $stmt->fetch(); + $caseTitle = ($lang === 'ar' && !empty($case['title_ar'])) ? $case['title_ar'] : $case['title_en']; + + $vars = [ + 'recipient_name' => !empty($donation['gift_recipient_name']) ? $donation['gift_recipient_name'] : (($lang === 'ar') ? 'صديق' : 'Friend'), + 'donor_name' => !empty($donation['donor_name']) ? $donation['donor_name'] : (($lang === 'ar') ? 'فاعل خير' : 'A generous donor'), + 'case_title' => $caseTitle, + 'gift_message' => !empty($donation['gift_message']) ? "\n\n" . (($lang === 'ar') ? 'رسالة:' : 'Message:') . " \"" . $donation['gift_message'] . "\"" : "", + 'org_name' => self::getOrgName($lang) + ]; + + return self::sendTemplatedMessage($donation['gift_recipient_phone'], 'donation_gift_notification', $vars, $lang); + } + + public static function sendCaseDonationNotification($donation, $lang = 'en') { + $pdo = db(); + $stmt = $pdo->prepare("SELECT c.title_en, c.title_ar, c.contact_phone FROM cases c WHERE c.id = ?"); + $stmt->execute([$donation['case_id']]); + $case = $stmt->fetch(); + + if (!$case || empty($case['contact_phone'])) { + return ['success' => false, 'error' => 'Case contact phone not found']; + } + + $caseTitle = ($lang === 'ar' && !empty($case['title_ar'])) ? $case['title_ar'] : $case['title_en']; + + $vars = [ + 'amount' => number_format($donation['amount'], 3), + 'case_title' => $caseTitle, + 'donor_name' => !empty($donation['donor_name']) ? $donation['donor_name'] : (($lang === 'ar') ? 'فاعل خير' : 'Anonymous'), + 'org_name' => self::getOrgName($lang) + ]; + + return self::sendTemplatedMessage($case['contact_phone'], 'case_donation_notification', $vars, $lang); + } +} \ No newline at end of file diff --git a/success.php b/success.php index a3c1448..e8d6ee5 100644 --- a/success.php +++ b/success.php @@ -103,12 +103,12 @@ if ($donation) { $stmt->execute([$donation['id']]); $fullDonation = $stmt->fetch(); - // Send WhatsApp notification to donor - WablasService::sendThankYou($fullDonation); + // Send WhatsApp notifications + WablasService::sendThankYou($fullDonation, $lang); + WablasService::sendCaseDonationNotification($fullDonation, $lang); - // Send WhatsApp notification to recipient if it\'s a gift if ($fullDonation['is_gift']) { - WablasService::sendGiftNotification($fullDonation); + WablasService::sendGiftNotification($fullDonation, $lang); } $success = true; @@ -201,4 +201,4 @@ $orgName = ($lang === 'en') ? ($org['name_en'] ?? 'Organization') : ($org['name_
- \ No newline at end of file +