import { StrictMode, Suspense } from 'react'; import { createRoot } from 'react-dom/client'; import AppWrapper from './AppWrapper.tsx'; import ErrorBoundary from './components/Shared/ErrorBoundary'; import './index.css'; import i18n from './i18n'; import { logger } from './utils/logger'; // المزودين import { CurrencyProvider } from './contexts/CurrencyContext.tsx'; import { ThemeProvider } from './contexts/ThemeContext.tsx'; import { AuthProvider } from './contexts/AuthContext.tsx'; import { InvoiceProvider } from './contexts/InvoiceContext.tsx'; // التكوين import { currentConfig, BUILD_INFO } from './config/appConfig'; // مكون شاشة التحميل المحسنة const LoadingFallback = () => (

ARWA GROUP

{i18n.t('common.loadingSubtitle')}

{i18n.t('common.loadingFeatures', { version: BUILD_INFO.version })}

); // تهيئة التطبيق const initializeApp = () => { logger.log(` 🏢 ARWA GROUP Accounting System v${BUILD_INFO.version} 📅 تاريخ البناء: ${new Date(BUILD_INFO.buildDate).toLocaleDateString(i18n.language)} 🌍 البيئة: ${BUILD_INFO.environment} 🔧 الميزات المفعلة: ${Object.entries(currentConfig.features) .filter(([_, enabled]) => enabled) .map(([feature]) => ` ✅ ${feature}`) .join('\n')} `); if (currentConfig.development.showPerformanceMetrics) { logger.log('📊 إعدادات الأداء:', { 'ذاكرة التخزين المؤقت': currentConfig.performance.enableCaching ? 'مفعل' : 'معطل', 'التحميل الكسول': currentConfig.performance.lazyLoading ? 'مفعل' : 'معطل', 'حجم الذاكرة المسموح': `${currentConfig.performance.maxMemoryUsage} MB` }); } if ('serviceWorker' in navigator && BUILD_INFO.environment === 'production') { navigator.serviceWorker.register('/sw.js') .then(() => logger.log('✅ Service Worker مسجل بنجاح')) .catch(error => logger.error('❌ فشل تسجيل Service Worker:', error)); } if (currentConfig.development.showPerformanceMetrics) { const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { if (entry.entryType === 'measure') { logger.log(`⚡ ${entry.name}: ${entry.duration.toFixed(2)}ms`); } } }); observer.observe({ entryTypes: ['measure'] }); } }; // توحيد تنسيق الأرقام/التواريخ في كل مكان: // - أرقام إنجليزية (Latin digits) فقط // - تاريخ ميلادي (Gregorian) فقط // // ملاحظة: بعض أجزاء الكود تستخدم `toLocaleString(i18n.language)` مباشرة، // لذلك نحتاج override موحّد بدل استبدال جميع الاستدعاءات يدوياً. const applyArwaLocaleOverrides = () => { const w = window as any; if (w.__arwaLocaleOverridesApplied) return; w.__arwaLocaleOverridesApplied = true; const getBaseLang = (): 'ar' | 'en' | 'zh' => { try { const lang = (document?.documentElement?.lang || i18n.language || '').toLowerCase(); if (lang.startsWith('ar')) return 'ar'; if (lang.startsWith('zh')) return 'zh'; } catch { // ignore } return 'en'; }; // إجباري: تقويم ميلادي + أرقام لاتينية في كل اللغات const getForcedDateLocale = (): string => { const base = getBaseLang(); if (base === 'ar') return 'ar-SA-u-ca-gregory-nu-latn'; if (base === 'zh') return 'zh-CN-u-ca-gregory-nu-latn'; return 'en-GB-u-ca-gregory-nu-latn'; }; const getForcedNumberLocale = (): string => { const base = getBaseLang(); if (base === 'ar') return 'ar-SA-u-nu-latn'; if (base === 'zh') return 'zh-CN-u-nu-latn'; return 'en-US-u-nu-latn'; }; const originalToLocaleDateString = Date.prototype.toLocaleDateString; Date.prototype.toLocaleDateString = function (locales?: unknown, options?: unknown): string { try { return originalToLocaleDateString.call(this, getForcedDateLocale(), options as any); } catch { return originalToLocaleDateString.call(this, 'en-GB', options as any); } }; const originalToLocaleTimeString = Date.prototype.toLocaleTimeString; Date.prototype.toLocaleTimeString = function (locales?: unknown, options?: unknown): string { try { return originalToLocaleTimeString.call(this, getForcedNumberLocale(), options as any); } catch { return originalToLocaleTimeString.call(this, locales as any, options as any); } }; const originalToLocaleString = Date.prototype.toLocaleString; Date.prototype.toLocaleString = function (locales?: unknown, options?: unknown): string { try { return originalToLocaleString.call(this, getForcedDateLocale(), options as any); } catch { return originalToLocaleString.call(this, locales as any, options as any); } }; const originalNumberToLocaleString = Number.prototype.toLocaleString; Number.prototype.toLocaleString = function (locales?: unknown, options?: unknown): string { try { return originalNumberToLocaleString.call(this, getForcedNumberLocale(), options as any); } catch { return originalNumberToLocaleString.call(this, locales as any, options as any); } }; // بعض المكونات تستخدم Intl مباشرة بدل toLocale*، لذلك نطبّعها هنا أيضاً. try { const OriginalNumberFormat = Intl.NumberFormat; const PatchedNumberFormat = function (this: Intl.NumberFormat, locales?: unknown, options?: Intl.NumberFormatOptions) { return new OriginalNumberFormat(getForcedNumberLocale() as Intl.LocalesArgument, options); } as unknown as typeof Intl.NumberFormat; // Note: نتجنب تعديل `prototype`/خصائص static لأن TypeScript يراها read-only. Intl.NumberFormat = PatchedNumberFormat as any; } catch { // ignore when runtime doesn't allow patching Intl.NumberFormat } try { const OriginalDateTimeFormat = Intl.DateTimeFormat; const PatchedDateTimeFormat = function (this: Intl.DateTimeFormat, locales?: unknown, options?: Intl.DateTimeFormatOptions) { return new OriginalDateTimeFormat(getForcedDateLocale() as Intl.LocalesArgument, options); } as unknown as typeof Intl.DateTimeFormat; // Note: نتجنب تعديل `prototype`/خصائص static لأن TypeScript يراها read-only. Intl.DateTimeFormat = PatchedDateTimeFormat as any; } catch { // ignore when runtime doesn't allow patching Intl.DateTimeFormat } }; // تشغيل التطبيق const rootElement = document.getElementById('root'); if (!rootElement) { throw new Error('عنصر الجذر غير موجود في HTML'); } // تهيئة التطبيق applyArwaLocaleOverrides(); initializeApp(); // إشارة جاهزية التطبيق لإخفاء شاشة التحميل الأولى (تعمل مع الحد الأدنى للوقت في index.html) const signalAppReady = () => { window.dispatchEvent(new CustomEvent('arwa:app-ready')); }; // إنشاء التطبيق createRoot(rootElement).render( }> ); // إخفاء شاشة التحميل عند جاهزية React (بعد أول رسم) requestAnimationFrame(() => { requestAnimationFrame(() => { setTimeout(signalAppReady, 50); }); }); window.addEventListener('error', (event) => { logger.error('خطأ في التطبيق:', { message: event.message, filename: event.filename, lineno: event.lineno, colno: event.colno, error: event.error }); }); window.addEventListener('unhandledrejection', (event) => { logger.error('رفض غير معالج:', event.reason); event.preventDefault(); }); // تصدير معلومات النظام للوصول العام (window as any).ARWA_SYSTEM = { version: BUILD_INFO.version, config: currentConfig, build: BUILD_INFO };