import { v4 as uuidv4 } from "uuid"; export type NeedType = | "electricity" | "water" | "food" | "health" | "housing" | "refrigerator" | "air_conditioner" | "court_order"; export type RequestSource = "beneficiary" | "charity" | "official"; export type RequestStatus = | "new" | "pending_review" | "verified" | "published" | "donated" | "delivered" | "receipt_confirmed" | "thank_you_submitted" | "whatsapp_sent" | "closed" | "rejected"; export type WhatsappStatus = "pending" | "sent" | "failed"; export interface DonationRequest { id: string; caseId: string; beneficiaryName: string; nationalId: string; phone: string; source: RequestSource; sourceName: string; needType: NeedType; requestedAmount: number; collectedAmount: number; description: string; status: RequestStatus; currentStep: number; donorId: string | null; donorName: string | null; thankYouMessage: string | null; whatsappStatus: WhatsappStatus | null; whatsappSentAt: string | null; rejectionReason: string | null; createdAt: string; updatedAt: string; } export interface Donor { id: string; name: string; phone: string; email: string | null; totalDonated: number; donationCount: number; } export interface EligibilityRecord { nationalId: string; eligible: boolean; } export interface WhatsappLogEntry { id: string; caseId: string; donorName: string; donorPhone: string; beneficiaryMessage: string; whatsappMessage: string; status: WhatsappStatus; sentAt: string | null; createdAt: string; } // Outbound WhatsApp "thank the donor" notifications, fired right after a // successful donation. They are queued here (in-memory) and picked up by an // external poller (OpenClaw) that actually sends the WhatsApp message and then // marks the row as sent. Resets on container restart like all mock data. export interface DonorNotification { id: string; caseId: string; donorName: string; donorPhone: string; // normalized to international form, e.g. 9665XXXXXXXX message: string; status: WhatsappStatus; // pending | sent | failed sentAt: string | null; createdAt: string; } // Fixed Arabic confirmation message sent to the donor after a successful // donation. This is an outbound WhatsApp message (not in-app UI text), so it is // intentionally a single fixed string and does not go through LanguageContext. export const DONOR_THANK_YOU_MESSAGE = "إحسانك يُثمر وعطاؤك يعين ..\n\nتمت عملية تبرعك عبر منصة إحسان بنجاح\n\n(والله يحب المحسنين)"; export const donorNotifications: DonorNotification[] = []; // Normalize a Saudi phone number to WhatsApp international form. // 05XXXXXXXX -> 9665XXXXXXXX // 5XXXXXXXX -> 9665XXXXXXXX // 9665XXXXXXXX -> 9665XXXXXXXX (unchanged) // +966 5XXXXXXXX -> 9665XXXXXXXX // Returns digits only (no '+'). Falls back to the cleaned digits if the shape // is unexpected, so we never throw inside the donation flow. export function normalizeSaudiPhone(raw: string): string { const digits = String(raw || "").replace(/\D/g, ""); if (!digits) return ""; if (digits.startsWith("966")) return digits; if (digits.startsWith("0")) return "966" + digits.slice(1); if (digits.startsWith("5") && digits.length === 9) return "966" + digits; return digits; } // ─── Eligibility Database ─────────────────────────────────────────────────── export const eligibilityDb: EligibilityRecord[] = [ { nationalId: "1090512345", eligible: true }, { nationalId: "1023456789", eligible: true }, { nationalId: "2098765432", eligible: true }, { nationalId: "1056789012", eligible: true }, { nationalId: "2034567890", eligible: true }, { nationalId: "1099999999", eligible: false }, ]; // ─── Donors ───────────────────────────────────────────────────────────────── export const donors: Donor[] = [ { id: "donor-001", name: "عبدالله المنصور", phone: "0501234567", email: "abdullah@example.com", totalDonated: 5000, donationCount: 2, }, { id: "donor-002", name: "سارة الأحمد", phone: "0556789012", email: "sara@example.com", totalDonated: 3000, donationCount: 1, }, { id: "donor-003", name: "محمد الشمري", phone: "0589012345", email: null, totalDonated: 2500, donationCount: 1, }, ]; // ─── Mock Requests ─────────────────────────────────────────────────────────── const now = new Date(); const d = (daysAgo: number) => new Date(now.getTime() - daysAgo * 86400000).toISOString(); export const requests: DonationRequest[] = [ { id: "req-001", caseId: "CASE-001", beneficiaryName: "أحمد إبراهيم الحربي", nationalId: "1090512345", phone: "0501111111", source: "beneficiary", sourceName: "مستفيد مباشر", needType: "electricity", requestedAmount: 2400, collectedAmount: 2400, description: "فاتورة كهرباء متراكمة لمدة 6 أشهر، أب لأربعة أطفال", status: "closed", currentStep: 10, donorId: "donor-001", donorName: "عبدالله المنصور", thankYouMessage: "جزاكم الله خيراً، وصلني الدعم وكان له أثر كبير عليّ وعلى أسرتي.", whatsappStatus: "sent", whatsappSentAt: d(1), rejectionReason: null, createdAt: d(30), updatedAt: d(1), }, { id: "req-002", caseId: "CASE-002", beneficiaryName: "فاطمة علي السلمي", nationalId: "1023456789", phone: "0502222222", source: "charity", sourceName: "جمعية البر الخيرية", needType: "water", requestedAmount: 1800, collectedAmount: 1800, description: "فاتورة مياه متأخرة، أرملة تعيل ثلاثة أطفال", status: "whatsapp_sent", currentStep: 9, donorId: "donor-002", donorName: "سارة الأحمد", thankYouMessage: "بارك الله فيكم، وصل الدعم في الوقت المناسب جداً.", whatsappStatus: "sent", whatsappSentAt: d(2), rejectionReason: null, createdAt: d(25), updatedAt: d(2), }, { id: "req-003", caseId: "CASE-003", beneficiaryName: "خالد محمد الغامدي", nationalId: "2098765432", phone: "0503333333", source: "official", sourceName: "وزارة العدل", needType: "food", requestedAmount: 1200, collectedAmount: 1200, description: "سلة غذائية شهرية لعائلة من 6 أفراد", status: "thank_you_submitted", currentStep: 8, donorId: "donor-003", donorName: "محمد الشمري", thankYouMessage: "شكراً جزيلاً، السلة الغذائية أفادتنا كثيراً.", whatsappStatus: "pending", whatsappSentAt: null, rejectionReason: null, createdAt: d(20), updatedAt: d(3), }, { id: "req-004", caseId: "CASE-004", beneficiaryName: "مريم سالم العتيبي", nationalId: "1056789012", phone: "0504444444", source: "charity", sourceName: "الهلال الأحمر السعودي", needType: "health", requestedAmount: 5000, collectedAmount: 5000, description: "مصاريف علاج ومستلزمات طبية لمريضة مزمنة", status: "receipt_confirmed", currentStep: 7, donorId: "donor-001", donorName: "عبدالله المنصور", thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(18), updatedAt: d(4), }, { id: "req-005", caseId: "CASE-005", beneficiaryName: "عمر عبدالرحمن الدوسري", nationalId: "2034567890", phone: "0505555555", source: "official", sourceName: "شركة المياه الوطنية", needType: "housing", requestedAmount: 8000, collectedAmount: 8000, description: "إصلاحات طارئة في المسكن بعد تسرب المياه", status: "delivered", currentStep: 6, donorId: "donor-002", donorName: "سارة الأحمد", thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(15), updatedAt: d(5), }, { id: "req-006", caseId: "CASE-006", beneficiaryName: "نورة سعد القحطاني", nationalId: "1090512345", phone: "0506666666", source: "beneficiary", sourceName: "مستفيد مباشر", needType: "refrigerator", requestedAmount: 1500, collectedAmount: 1500, description: "ثلاجة منزلية لعائلة تفتقر لوسيلة حفظ الغذاء", status: "donated", currentStep: 5, donorId: "donor-003", donorName: "محمد الشمري", thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(10), updatedAt: d(6), }, { id: "req-007", caseId: "CASE-007", beneficiaryName: "سليمان ناصر الزهراني", nationalId: "1023456789", phone: "0507777777", source: "charity", sourceName: "جمعية التنمية الأسرية", needType: "air_conditioner", requestedAmount: 2000, collectedAmount: 0, description: "مكيف لمنزل في منطقة حارة، وجود أطفال ومسنين", status: "published", currentStep: 4, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(8), updatedAt: d(7), }, { id: "req-008", caseId: "CASE-008", beneficiaryName: "حسن عبدالله الرشيدي", nationalId: "2056789012", phone: "0508888888", source: "official", sourceName: "وزارة العدل", needType: "court_order", requestedAmount: 3500, collectedAmount: 0, description: "سداد غرامة قضائية لتجنب الحجز على الممتلكات", status: "verified", currentStep: 3, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(6), updatedAt: d(5), }, { id: "req-009", caseId: "CASE-009", beneficiaryName: "رنا طارق المالكي", nationalId: "9999999999", phone: "0509999999", source: "beneficiary", sourceName: "مستفيد مباشر", needType: "food", requestedAmount: 900, collectedAmount: 0, description: "سلة غذائية لأسرة محتاجة", status: "pending_review", currentStep: 2, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(2), updatedAt: d(1), }, { id: "req-010", caseId: "CASE-010", beneficiaryName: "بدر محمد الجهني", nationalId: "1099999999", phone: "0511111111", source: "charity", sourceName: "الجمعية الخيرية", needType: "electricity", requestedAmount: 1800, collectedAmount: 0, description: "فاتورة كهرباء متراكمة", status: "rejected", currentStep: 2, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: "المستفيد غير مؤهل وفق قاعدة بيانات الاستحقاق", createdAt: d(5), updatedAt: d(4), }, { id: "req-011", caseId: "CASE-011", beneficiaryName: "أميرة خالد السبيعي", nationalId: "1056789012", phone: "0512222222", source: "official", sourceName: "شركة الكهرباء السعودية", needType: "electricity", requestedAmount: 3200, collectedAmount: 0, description: "فاتورة كهرباء لمنزل أرملة ذات أطفال صغار", status: "new", currentStep: 1, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(1), updatedAt: d(0), }, { id: "req-012", caseId: "CASE-012", beneficiaryName: "هند فيصل العنزي", nationalId: "1067890123", phone: "0513333333", source: "charity", sourceName: "جمعية كافل الخيرية", needType: "food", requestedAmount: 1200, collectedAmount: 780, description: "سلة غذائية شهرية لأسرة مكونة من خمسة أفراد", status: "published", currentStep: 4, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(9), updatedAt: d(2), }, { id: "req-013", caseId: "CASE-013", beneficiaryName: "صالح عوض الحارثي", nationalId: "2078901234", phone: "0514444444", source: "official", sourceName: "شركة الكهرباء السعودية", needType: "electricity", requestedAmount: 2600, collectedAmount: 1850, description: "سداد فاتورة كهرباء متراكمة لمنزل أسرة متعففة", status: "published", currentStep: 4, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(7), updatedAt: d(1), }, { id: "req-014", caseId: "CASE-014", beneficiaryName: "لطيفة عبدالله الشهري", nationalId: "1089012345", phone: "0515555555", source: "charity", sourceName: "الهلال الأحمر السعودي", needType: "health", requestedAmount: 6000, collectedAmount: 1500, description: "مستلزمات طبية وأجهزة منزلية لمريضة مزمنة", status: "published", currentStep: 4, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(6), updatedAt: d(1), }, { id: "req-015", caseId: "CASE-015", beneficiaryName: "ماجد سعيد القرني", nationalId: "2090123456", phone: "0516666666", source: "beneficiary", sourceName: "مستفيد مباشر", needType: "water", requestedAmount: 1400, collectedAmount: 1120, description: "سداد فاتورة مياه متأخرة لأسرة تعيلها أرملة", status: "published", currentStep: 4, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(5), updatedAt: d(1), }, { id: "req-016", caseId: "CASE-016", beneficiaryName: "ريم ناصر المطيري", nationalId: "1078901234", phone: "0517777777", source: "charity", sourceName: "جمعية الإسكان التنموي", needType: "housing", requestedAmount: 9000, collectedAmount: 3200, description: "ترميم وحدة سكنية متضررة لأسرة ذات دخل محدود", status: "published", currentStep: 4, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(4), updatedAt: d(1), }, { id: "req-017", caseId: "CASE-017", beneficiaryName: "عبدالعزيز فهد الرشيد", nationalId: "2012345678", phone: "0518888888", source: "official", sourceName: "جمعية تكافل", needType: "air_conditioner", requestedAmount: 2200, collectedAmount: 2100, description: "تأمين مكيف لمنزل يقطنه مسنون في منطقة شديدة الحرارة", status: "published", currentStep: 4, donorId: null, donorName: null, thankYouMessage: null, whatsappStatus: null, whatsappSentAt: null, rejectionReason: null, createdAt: d(3), updatedAt: d(1), }, ]; // ─── WhatsApp Log ──────────────────────────────────────────────────────────── export const whatsappLog: WhatsappLogEntry[] = [ { id: "wa-001", caseId: "CASE-001", donorName: "عبدالله المنصور", donorPhone: "0501234567", beneficiaryMessage: "جزاكم الله خيراً، وصلني الدعم وكان له أثر كبير عليّ وعلى أسرتي.", whatsappMessage: "السلام عليكم، نشكركم على تبرعكم عبر منصة إحسان.\nتم إيصال الدعم للمستفيد، وهذه رسالة الشكر من المستفيد:\n\"جزاكم الله خيراً، وصلني الدعم وكان له أثر كبير عليّ وعلى أسرتي.\"\nرقم الحالة: CASE-001", status: "sent", sentAt: d(1), createdAt: d(2), }, { id: "wa-002", caseId: "CASE-002", donorName: "سارة الأحمد", donorPhone: "0556789012", beneficiaryMessage: "بارك الله فيكم، وصل الدعم في الوقت المناسب جداً.", whatsappMessage: "السلام عليكم، نشكركم على تبرعكم عبر منصة إحسان.\nتم إيصال الدعم للمستفيد، وهذه رسالة الشكر من المستفيد:\n\"بارك الله فيكم، وصل الدعم في الوقت المناسب جداً.\"\nرقم الحالة: CASE-002", status: "sent", sentAt: d(2), createdAt: d(3), }, { id: "wa-003", caseId: "CASE-003", donorName: "محمد الشمري", donorPhone: "0589012345", beneficiaryMessage: "شكراً جزيلاً، السلة الغذائية أفادتنا كثيراً.", whatsappMessage: "السلام عليكم، نشكركم على تبرعكم عبر منصة إحسان.\nتم إيصال الدعم للمستفيد، وهذه رسالة الشكر من المستفيد:\n\"شكراً جزيلاً، السلة الغذائية أفادتنا كثيراً.\"\nرقم الحالة: CASE-003", status: "pending", sentAt: null, createdAt: d(3), }, ]; // ─── Helper: Determine status after eligibility check ─────────────────────── export function checkEligibility(nationalId: string): { eligible: boolean | null; } { const record = eligibilityDb.find((r) => r.nationalId === nationalId); if (!record) return { eligible: null }; return { eligible: record.eligible }; } // ─── Helper: Status → Step mapping ────────────────────────────────────────── export const STATUS_STEP: Record = { new: 1, pending_review: 2, verified: 3, published: 4, donated: 5, delivered: 6, receipt_confirmed: 7, thank_you_submitted: 8, whatsapp_sent: 9, closed: 10, rejected: 2, };