Files
hihala-dashboard/src/lib/locale.ts
T
fahed 30cdb5064a refactor: extract shared locale, date helpers, and components (H6)
~300 lines of code that were independently duplicated in Dashboard.tsx
and Comparison.tsx are now in shared modules:

- src/lib/locale.ts — LC interface, EN and AR language configs (merged
  fields from both pages into one unified interface)
- src/lib/dateHelpers.ts — MONTH_KEYS, isLeap, makePresets, guessPreset,
  periodNameL, dateRangeTextL, currentMonth, shiftYear
- src/components/shared/PeriodPicker.tsx — InlinePicker + PeriodHero
- src/components/shared/AltMultiSelect.tsx — AltMultiSelect
- src/components/shared/MetricCard.tsx — MetricCard

Dashboard.tsx and Comparison.tsx now import from these shared modules.
Zero behavioral changes — all props, ARIA, and render output unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:53:35 +03:00

140 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ─── language config ──────────────────────────────────────────────
// Shared LC interface used by Dashboard and Comparison.
// Fields marked with a comment are only consumed by one page but kept
// here so both components share a single type.
export interface LC {
dir: 'ltr' | 'rtl';
/** @deprecated Fonts are now loaded from index.html; kept for compatibility */
fontImport: string;
bodyFont: string;
displayFont: string;
monoFont: string;
monthFull: string[];
monthShort: string[];
periods: Record<string, string>;
fullYearLabel: (y: number) => string;
dateRangeSep: string;
backLink: string;
backTo: string;
pageTitle: string;
pageSub: string;
// Dashboard
changePeriod: string;
close: string;
apply: string;
filter: string;
allDistricts: string;
allChannels: string;
allMuseums: string;
countDistricts: (n: number) => string;
countChannels: (n: number) => string;
countMuseums: (n: number) => string;
reset: string;
exclVAT: string;
inclVAT: string;
keyMetrics: string;
revenue: string;
visitors: string;
tickets: string;
avgRev: string;
pilgrims: string;
captureRate: string;
charts: string;
trendTitle: string;
museumTitle: string;
channelTitle: string;
districtTitle: string;
daily: string;
weekly: string;
monthly: string;
newLabel: string;
clearSel: string;
monthSection: string;
periodSection: string;
from: string;
to: string;
vsLabel: string;
barLabel: string;
pieLabel: string;
absLabel: string;
pctLabel: string;
// Comparison-specific
currentRole: string;
previousRole: string;
currentHint: string;
previousHint: string;
vs: string;
}
export const EN: LC = {
dir: 'ltr',
fontImport: `@import url('https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=Outfit:wght@300;400;500;600;700&display=swap');`,
bodyFont: "'Outfit', sans-serif",
displayFont: "'DM Serif Display', serif",
monoFont: "ui-monospace, 'Cascadia Code', monospace",
monthFull: ['January','February','March','April','May','June','July','August','September','October','November','December'],
monthShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
periods: { q1:'Q1', q2:'Q2', q3:'Q3', q4:'Q4', h1:'H1', h2:'H2', full:'Full Year' },
fullYearLabel: (y) => String(y),
dateRangeSep: '→',
backLink: 'Back to Dashboard', backTo: '/',
pageTitle: 'Overview', pageSub: 'Museum performance at a glance.',
changePeriod: 'Change period', close: 'Cancel', apply: 'Apply',
filter: 'Filter',
allDistricts: 'All districts', allChannels: 'All channels', allMuseums: 'All museums',
countDistricts: (n) => `${n} districts`,
countChannels: (n) => `${n} channels`,
countMuseums: (n) => `${n} museums`,
reset: 'Reset', exclVAT: 'Excl. VAT', inclVAT: 'Incl. VAT',
keyMetrics: 'Key Metrics',
revenue: 'Revenue', visitors: 'Visitors', tickets: 'Tickets',
avgRev: 'Avg Rev / Visitor', pilgrims: 'Pilgrims', captureRate: 'Capture Rate %',
charts: 'Charts',
trendTitle: 'Trend over time', museumTitle: 'By museum',
channelTitle: 'By channel', districtTitle: 'By district',
daily: 'Daily', weekly: 'Weekly', monthly: 'Monthly',
newLabel: 'New', clearSel: 'Clear selection',
monthSection: 'Month', periodSection: 'Quarter · Half · Year',
from: 'From', to: 'To', vsLabel: 'vs',
barLabel: 'Bar', pieLabel: 'Pie', absLabel: '#', pctLabel: '%',
currentRole: 'This period', previousRole: 'Compared to',
currentHint: 'primary', previousHint: 'auto year 1',
vs: 'vs',
};
export const AR: LC = {
dir: 'rtl',
fontImport: `@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@300;400;500;600;700&display=swap');`,
bodyFont: "'IBM Plex Sans Arabic', sans-serif",
displayFont: "'IBM Plex Sans Arabic', sans-serif",
monoFont: "'IBM Plex Sans Arabic', sans-serif",
monthFull: ['يناير','فبراير','مارس','أبريل','مايو','يونيو','يوليو','أغسطس','سبتمبر','أكتوبر','نوفمبر','ديسمبر'],
monthShort: ['ينا','فبر','مار','أبر','ماي','يون','يول','أغس','سبت','أكت','نوف','ديس'],
periods: { q1:'ر١', q2:'ر٢', q3:'ر٣', q4:'ر٤', h1:'ن١', h2:'ن٢', full:'السنة' },
fullYearLabel: (y) => `${y} كاملاً`,
dateRangeSep: '',
backLink: 'العودة إلى لوحة التحكم', backTo: '/ar',
pageTitle: 'نظرة عامة', pageSub: 'أداء المتاحف في لمحة.',
changePeriod: 'تغيير الفترة', close: 'إلغاء', apply: 'تطبيق',
filter: 'تصفية',
allDistricts: 'كل المناطق', allChannels: 'كل القنوات', allMuseums: 'كل المتاحف',
countDistricts: (n) => `${n} مناطق`,
countChannels: (n) => `${n} قنوات`,
countMuseums: (n) => `${n} متاحف`,
reset: 'إعادة ضبط', exclVAT: 'بدون ضريبة', inclVAT: 'مع ضريبة',
keyMetrics: 'المؤشرات الرئيسية',
revenue: 'الإيرادات', visitors: 'الزوار', tickets: 'التذاكر',
avgRev: 'متوسط الإيراد / زائر', pilgrims: 'الحجاج والمعتمرون', captureRate: 'معدل الاستيعاب %',
charts: 'المخططات',
trendTitle: 'الاتجاه عبر الزمن', museumTitle: 'حسب المتحف',
channelTitle: 'حسب القناة', districtTitle: 'حسب المنطقة',
daily: 'يومي', weekly: 'أسبوعي', monthly: 'شهري',
newLabel: 'جديد', clearSel: 'مسح التحديد',
monthSection: 'الشهر', periodSection: 'ربع · نصف · سنة',
from: 'من', to: 'إلى', vsLabel: 'مقابل',
barLabel: 'أعمدة', pieLabel: 'دائرة', absLabel: '#', pctLabel: '%',
currentRole: 'الفترة الحالية', previousRole: 'مقارنةً بـ',
currentHint: 'رئيسية', previousHint: 'تلقائياً −١ سنة',
vs: 'مقابل',
};