// SupportWidget.jsx — لوحةُ الدعم الجانبية: محادثةٌ مع مساعدِ الدعم + تذكرةٌ للفريق // // ⚠️ **مساعدُ الدعم يجيبُ عمّا يعرفُه فقط.** إجاباتُه مكتوبةٌ هنا في `KB` — ليست // مولَّدةً ولا متّصلةً بنموذجٍ لغويّ. فإن لم يجدْ جواباً قال ذلك صراحةً وفتح // التذكرة، ولم يخترعْ جواباً. (لوصلِه بمساعدٍ حقيقيٍّ لاحقاً: بدِّلْ `askSupport` // وحدَها بنداءِ الخادم — بقيةُ اللوحةِ لا تتغيّر.) /* ── قاعدةُ معرفةِ الدعم: كلماتٌ مفتاحيةٌ ← جواب ── ⚠️ **لغةُ الموقع فصحى.** كلُّ ما يقرؤه المستخدمُ هنا مكتوبٌ بالعربية الفصيحة، ولا تُستعمَلُ العاميّةُ في نصوصِ الواجهةِ ألبتّة. */ const SUPPORT_KB = [ { k: ['اشتراك', 'الباقة', 'باقة', 'ترقية', 'خطة', 'الأسعار', 'سعر', 'دفع', 'تجديد'], a: 'تجد الباقات وأسعارها في صفحة **الاشتراكات** من القائمة الجانبية، ويمكنك تغيير باقتك أو إلغاؤها من الصفحة نفسها في أي وقت.', }, { k: ['كريدت', 'رصيد', 'نقاط', 'استهلاك', 'انتهى'], a: 'يُخصم من رصيدك كريدت واحد عن كل سؤال تُرسله إلى المساعد القانوني، ويتجدد الرصيد مع باقتك. يظهر رصيدك الحالي في أعلى الصفحة، ويمكنك زيادته من صفحة **الاشتراكات**.', }, { k: ['بحث', 'أبحث', 'محرك', 'نظام', 'مادة', 'لائحة', 'أجد'], a: 'استخدم **محرك البحث القانوني** من القائمة، واكتب رقم المادة أو جزءاً من نصها أو اسم النظام. تظهر النتائج مقرونةً بمصدرها الرسمي وتاريخ آخر تعديل عليها.', }, { k: ['ملف', 'ملفاتي', 'رفع', 'أرفع', 'عقد', 'مستند', 'pdf'], a: 'من **ملفاتي** يمكنك رفع عقودك ومستنداتك وتنظيمها في مجلدات، ثم سؤال المساعد عن أي ملف منها.', }, { k: ['حساب', 'بياناتي', 'الاسم', 'الجوال', 'صورة', 'الملف الشخصي', 'تعديل بياناتي'], a: 'تُعدَّل بياناتك من **الملف الشخصي**: اضغط صورتك في أعلى الصفحة، ثم اختر «الملف الشخصي».', }, { k: ['كلمة المرور', 'كلمة السر', 'نسيت', 'استعادة'], a: 'من شاشة تسجيل الدخول اضغط **«نسيت كلمة المرور؟»**، وسيصلك رابط الاستعادة على بريدك الإلكتروني.', }, { k: ['خروج', 'تسجيل الخروج'], a: 'لتسجيل الخروج: اضغط صورتك في أعلى الصفحة، ثم اختر **تسجيل الخروج**.', }, { k: ['محامي', 'محامين', 'استشارة', 'جلسة', 'حجز'], a: 'خدمة التواصل مع المحامين مؤجَّلة ولا تتوفر في هذه النسخة. المتاح الآن: المساعد القانوني، ومحرك البحث، وملفاتي.', }, { k: ['خطأ', 'مشكلة', 'لا يعمل', 'عطل', 'بطيء', 'توقف'], a: 'أعِد تحديث الصفحة أولاً. فإن استمرت المشكلة، افتح تبويب **«تذكرة دعم»** أعلاه واكتب تفاصيلها، ليطّلع عليها الفريق.', }, ]; const SUPPORT_GREETING = 'أهلاً بك 👋 أنا مساعد الدعم، وأجيب عن أسئلة استخدام المنصة: الاشتراكات، والكريدت، والبحث، والملفات، والحساب.\n\nتفضّل بسؤالك. وإن كان خارج هذا النطاق، فتحتُ لك تذكرةً لدى الفريق.'; const SUPPORT_UNKNOWN = 'ليست لديّ إجابة مؤكدة عن هذا السؤال، ولن أخمّن.\n\nافتح تبويب **«تذكرة دعم»** أعلاه واكتب سؤالك ليجيبك الفريق. أو اسألني عن: الاشتراكات · الكريدت · البحث · الملفات · الحساب.'; /** جوابُ مساعدِ الدعم — مطابقةُ كلماتٍ مفتاحية، بلا توليد. */ function askSupport(text) { const q = (text || '').toLowerCase(); let best = null, bestScore = 0; for (const item of SUPPORT_KB) { const score = item.k.reduce((n, w) => (q.includes(w) ? n + 1 : n), 0); if (score > bestScore) { best = item; bestScore = score; } } return bestScore > 0 ? best.a : SUPPORT_UNKNOWN; } /** عرضٌ بسيطٌ لـ**التغليظ** داخل نصّ الرسالة. */ function SupportText({ text }) { const parts = String(text).split(/(\*\*[^*]+\*\*)/g); return ( {parts.map((p, i) => p.startsWith('**') && p.endsWith('**') ? {p.slice(2, -2)} : {p} )} ); } function SupportWidget() { const [open, setOpen] = React.useState(false); const [tab, setTab] = React.useState('chat'); // chat | ticket const [form, setForm] = React.useState({ title: '', msg: '' }); const [sent, setSent] = React.useState(false); const [hov, setHov] = React.useState(false); const [msgs, setMsgs] = React.useState([{ role: 'bot', text: SUPPORT_GREETING }]); const [draft, setDraft] = React.useState(''); const [typing, setTyping] = React.useState(false); const endRef = React.useRef(null); // يفتحُها بندُ «الدعم الفني» في القائمة الجانبية React.useEffect(() => { const openChat = () => { setTab('chat'); setOpen(true); }; window.addEventListener('lexa:open-support', openChat); return () => window.removeEventListener('lexa:open-support', openChat); }, []); React.useEffect(() => { if (open && tab === 'chat') endRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [msgs, open, tab, typing]); const sendChat = () => { const text = draft.trim(); if (!text || typing) return; setMsgs(m => [...m, { role: 'me', text }]); setDraft(''); setTyping(true); // تأخيرٌ قصيرٌ ليقرأ المستخدمُ سؤالَه قبل ظهورِ الجواب setTimeout(() => { setMsgs(m => [...m, { role: 'bot', text: askSupport(text) }]); setTyping(false); }, 450); }; const sendTicket = () => { if (!form.title || !form.msg) return; setSent(true); setTimeout(() => { setSent(false); setForm({ title: '', msg: '' }); }, 2500); }; const PANEL_W = 380; return ( <> {/* ── اللوحةُ الجانبية ── */} {open && (
{/* الرأس */}
الدعم الفني
مساعد الدعم — أسئلة استخدام المنصة
{/* التبويبات */}
{[['chat', 'محادثة'], ['ticket', 'تذكرة دعم']].map(([id, label]) => ( ))}
{tab === 'chat' ? ( <> {/* الرسائل */}
{msgs.map((m, i) => (
))} {typing && (
…
)}
{/* الكتابة */}
setDraft(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') sendChat(); }} placeholder="اكتب سؤالك…" style={{ flex: 1, padding: '10px 12px', borderRadius: 10, border: `1px solid ${sanadColors.border}`, background: sanadColors.bg, fontFamily: sanadFonts.arabic, fontSize: 13, color: sanadColors.textPrimary, outline: 'none', direction: 'rtl' }} onFocus={e => e.target.style.border = `1px solid ${sanadColors.brand}`} onBlur={e => e.target.style.border = `1px solid ${sanadColors.border}`} />
) : ( /* تذكرةُ الدعم */
{sent ? (
✓

تم الإرسال!

سنرد عليك في أقرب وقت

) : (
وصف المشكلة
setForm(f => ({ ...f, title: e.target.value }))} placeholder="ما هي المشكلة التي تواجهها؟" style={{ width: '100%', padding: '9px 11px', borderRadius: 8, border: `1px solid ${sanadColors.border}`, background: sanadColors.bg, fontFamily: sanadFonts.arabic, fontSize: 13, color: sanadColors.textPrimary, outline: 'none', direction: 'rtl' }} onFocus={e => e.target.style.border = `1px solid ${sanadColors.brand}`} onBlur={e => e.target.style.border = `1px solid ${sanadColors.border}`} />
التفاصيل