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
};