import React, { useState } from 'react' import { Smartphone, BookOpen, Zap, UserPlus, KeyRound, AlertCircle, Users, ShieldCheck, Activity, ShieldAlert, MessageSquare, FileCode, Settings, Search, X, ExternalLink } from 'lucide-react' import { Switch } from './components/ui/switch' import { Tooltip, TooltipContent, TooltipTrigger, } from './components/ui/tooltip' import { toast } from "sonner" import type { DashboardData } from './types' import { SettingsLayout, SettingsHeader, SnapshotStat, FeatSection, FeatRow, SecondaryButton } from './components/ui/settings-ui'; // ─── Dashboard ──────────────────────────────────────────────────────────────── export default function Dashboard({ data: initialData }: { data: DashboardData }) { const [data, setData] = useState(initialData) const [searchQuery, setSearchQuery] = useState('') const [isSearchOpen, setIsSearchOpen] = useState(false) const searchRef = React.useRef(null) React.useEffect(() => { if (isSearchOpen && searchRef.current) { searchRef.current.focus(); } }, [isSearchOpen]); const [prevInitialData, setPrevInitialData] = useState(initialData); const [savingItems, setSavingItems] = useState>({}); if (initialData !== prevInitialData) { setPrevInitialData(initialData); if (JSON.stringify(initialData?.features) !== JSON.stringify(prevInitialData?.features)) { setData(initialData); } } const toggle = async (key: string) => { if (!data || savingItems[key]) return; const feat = data.features[key]; const isActuallyEnabled = Number(feat.enabled) === 1 || feat.enabled === true; const next = isActuallyEnabled ? 0 : 1; setSavingItems(prev => ({ ...prev, [key]: true })); // Optimistic UI update setData(prev => prev ? { ...prev, features: { ...prev.features, [key]: { ...feat, enabled: next } } } : prev); try { const res = await fetch(`${data.global.settingsRestUrl}?_=${Date.now()}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': data.global.wpRestNonce }, body: JSON.stringify({ settings: { [feat.option]: next } }) }); const json = await res.json(); if (json.success) { toast.success(data.i18n.successTitle || 'Success', { description: data.i18n.success }); // Dispatch global refresh event with a small delay to allow transients to settle setTimeout(() => { window.dispatchEvent(new CustomEvent('wawp-refresh-data', { detail: { section: 'dashboard' } })); }, 150); // Notify sidebar about section visibility const sidebarMapping: Record = { 'wawp_otp_enabled': 'otp', 'wawp_chat_widget_enabled': 'chatWidget', 'wawp_notifications_enabled': 'notifications', 'wawp_system_info_enabled': 'systemInfo', 'wawp_countrycode_enabled': 'phoneField', 'wawp_google_recaptcha_enabled': 'recaptcha', 'wawp_passwordless_login_enabled': 'otpLogin', 'wawp_signup_enabled': 'signupOtp', 'wawp_custom_pages_enabled': 'authPages', 'wawp_unified_log_enabled': 'activityHub', 'wawp_email_templates_enabled': 'emailTemplates' }; const sidebarKey = sidebarMapping[feat.option]; if (sidebarKey) { window.dispatchEvent(new CustomEvent('wawp-sections-updated', { detail: { [sidebarKey]: next === 1 } })); // If child OTP feature is enabled, ensure master OTP group is also shown in sidebar if (['otpLogin', 'signupOtp', 'customPages'].includes(sidebarKey) && next === 1) { window.dispatchEvent(new CustomEvent('wawp-sections-updated', { detail: { otp: true } })); } } } else { throw new Error(json.data || 'Action failed'); } } catch (err) { // Revert on error setData(prev => prev ? { ...prev, features: { ...prev.features, [key]: { ...feat, enabled: isActuallyEnabled ? 1 : 0 } } } : prev); toast.error(data.i18n.errorTitle || 'Error', { description: (err as Error).message }); } finally { setSavingItems(prev => ({ ...prev, [key]: false })); } }; const t = React.useCallback((key: string, fallback: string = ''): string => { const val = (data?.i18n as Record)?.[key]; return typeof val === 'string' ? val : fallback; }, [data.i18n]); const stats = data?.stats || { totalWpUsers: 0, usersWithPhone: 0, verified: 0, percentAdded: '0%', percentVerified: '0%' }; // Build help URL: AR → help.wawp.net/ar/articles/..., EN → help.wawp.net/en/articles/... const docsUrl = (slug: string): string => { const lang = data.rtl ? 'ar' : 'en'; return `https://help.wawp.net/${lang}/articles/${slug}`; }; const translations = { labelPro: t('proVersion', 'PRO'), btnSettings: t('btnSettings', 'Settings'), btnUpgrade: t('btnUpgrade', 'Upgrade'), btnActivate: t('btnActivate', 'Activate'), }; // Fallback if i18n is partially missing to prevent white page const pageTitle = t('pageTitle', 'Dashboard'); const pageSubtitle = t('pageSubtitle', 'Manage your automated workflows, track delivery performance, and monitor system health in one centralized location.'); if (!data) return null; const f = (key: string) => data?.features?.[key] || { enabled: false, allowed: false, option: '', error: undefined, pluginLink: undefined }; const isEnabled = (key: string) => { const feat = f(key); return Number(feat.enabled) === 1 || feat.enabled === true; }; const isAllowed = (key: string) => { const feat = f(key); return feat.allowed === true || Number(feat.allowed) === 1; }; const getError = (key: string) => f(key).error as string | undefined; const hasFeature = (key: string) => !!data.features[key as keyof typeof data.features]; const hasEngagement = (['chatWidget', 'notifications', 'emailTemplates'] as (keyof typeof data.features)[]).some(k => !!data?.features?.[k]); const hasAuth = (['countryCode', 'otpLogin', 'signupOtp', 'customPages', 'recaptcha'] as (keyof typeof data.features)[]).some(k => !!data?.features?.[k]); const matchesSearch = (title: string = '', desc: string = '') => { if (!searchQuery) return true; const q = searchQuery.toLowerCase(); return title.toLowerCase().includes(q) || desc.toLowerCase().includes(q); }; return (
<> {/* WooCommerce Missing Global Notice */}
{isSearchOpen ? (
setSearchQuery(e.target.value)} onKeyDown={(e) => { if (e.key === 'Escape') { setSearchQuery(''); setIsSearchOpen(false); } }} />
) : ( setIsSearchOpen(true)} > )} window.open(data.urls.usersAdmin, '_blank')} > {t('viewAllUsers', 'View Users')} window.open(docsUrl('wawp-plugin-dashboard'), '_blank')} title={data.rtl ? 'دليل لوحة التحكم' : 'Dashboard Guide'} >
{/* Free Edition: Upgrade / Features Comparison Notice */}

{data.rtl ? "أطلق القوة الكاملة لـ Wawp (برو)" : "Unlock Wawp Full Power & Features"}

{data.rtl ? "اكتشف الفروق بين إصدارات الإضافة المختلفة وقارن الميزات لتفعيل الأتمتة المتقدمة لمتجرك." : "Explore differences between plugin editions and compare advanced features to grow your WooCommerce store."}

{data.rtl ? "مقارنة الميزات والإصدارات" : "Compare Features & Editions"}
{/* User Stats Snapshot */} {/* System Information Switch */}
{t('featSysInfoTitle', 'System Info')} {t('featSysInfoDesc', 'Monitor your server health and WordPress environment in real-time to ensure seamless performance for all automation tasks.')}
{isEnabled('systemInfo') && ( window.dispatchEvent(new CustomEvent('wawp-navigate', { detail: 'system_info' }))} > {t('btnSettings', 'Settings')} )} toggle('systemInfo')} />
{/* Feature Sections */} {hasEngagement && (matchesSearch(t('featChatTitle', ''), t('featChatDesc', '')) || matchesSearch("Dashboard", "Centralized command center") || matchesSearch(t('emailTemplates', ''), t('emailTemplatesDesc', '')) || matchesSearch(t('featMultiTitle', ''), t('featMultiDesc', '')) || matchesSearch(t('featSubTitle', ''), t('featSubDesc', ''))) && ( {hasFeature('chatWidget') && matchesSearch(t('featChatTitle', ''), t('featChatDesc', '')) && toggle('chatWidget')} docs={docsUrl('whatsapp-chat-button')} settingsUrl={data.urls.chatWidget} upgradeUrl={data.urls.pricing} t={translations} />} {hasFeature('notifications') && matchesSearch(t('featNotifTitle', ''), t('featNotifDesc', '')) && toggle('notifications')} docs={docsUrl('automated-notifications')} settingsUrl={data.urls.notifications} upgradeUrl={data.urls.pricing} t={translations} />} )} {hasAuth && (matchesSearch(t('featCountryTitle', ''), t('featCountryDesc', '')) || matchesSearch(t('featLoginTitle', ''), t('featLoginDesc', '')) || matchesSearch(t('featSignupTitle', ''), t('featSignupDesc', '')) || matchesSearch(t('featPagesTitle', ''), t('featPagesDesc', '')) || matchesSearch(t('featRecaptchaTitle', ''), t('featRecaptchaDesc', ''))) && ( {matchesSearch(t('featCountryTitle', ''), t('featCountryDesc', '')) && toggle('countryCode')} docs={docsUrl('advanced-country-code')} settingsUrl={data.urls.phoneField} upgradeUrl={data.urls.pricing} t={translations} />} {matchesSearch(t('featLoginTitle', ''), t('featLoginDesc', '')) && toggle('otpLogin')} docs={docsUrl('passwordless-login')} settingsUrl={data.urls.otpLogin} upgradeUrl={data.urls.pricing} t={translations} />} {matchesSearch(t('featSignupTitle', ''), t('featSignupDesc', '')) && toggle('signupOtp')} docs={docsUrl('registration-form')} settingsUrl={data.urls.registration} upgradeUrl={data.urls.pricing} t={translations} />} {matchesSearch(t('featPagesTitle', ''), t('featPagesDesc', '')) && toggle('customPages')} docs={docsUrl('about-authentication-pages-settings')} settingsUrl={data.urls.pages} upgradeUrl={data.urls.pricing} t={translations} />} {matchesSearch(t('featRecaptchaTitle', ''), t('featRecaptchaDesc', '')) && toggle('recaptcha')} docs={docsUrl('google-recaptcha')} settingsUrl={data.urls.recaptcha} upgradeUrl={data.urls.pricing} t={translations} />} )}
) }