feat: redesigned dashboard UI with editorial aesthetic and RTL support
Deploy HiHala Dashboard / deploy (push) Successful in 9s

- Replace Dashboard/Comparison with DashboardDemo/PeriodSelectorDemo as primary pages at / and /comparison
- New editorial design: DM Serif Display + Outfit fonts, inline period picker, multi-select filters for museum/channel/district
- Full Arabic RTL support with IBM Plex Sans Arabic; EN/AR toggle synced to global LanguageContext
- Bar/pie chart toggle + absolute/percent toggle for museum, channel, district charts
- Refined top nav: transparent inactive links, accent active state, visual separator between nav links and utilities
- DateRangePicker, MultiSelect, FilterControls shared components added
- NavDemo: sidebar layout alternative (accessible at /nav-demo)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
fahed
2026-04-19 17:58:33 +03:00
parent 0f6881309c
commit c8c3465233
13 changed files with 2819 additions and 178 deletions
+23 -16
View File
@@ -1,7 +1,7 @@
import React, { useState, useMemo, useCallback, useRef } from 'react';
import { useSearchParams } from 'react-router-dom';
import { Line, Bar } from 'react-chartjs-2';
import { EmptyState, FilterControls, MultiSelect, PeriodPicker } from './shared';
import { EmptyState, FilterControls, MultiSelect, DateRangePicker } from './shared';
import { ExportableChart } from './ChartExport';
import { chartColors, createBaseOptions } from '../config/chartConfig';
import { useLanguage } from '../contexts/LanguageContext';
@@ -525,15 +525,32 @@ function Comparison({ data, seasons, showDataLabels, setShowDataLabels, includeV
</div>
</div>
<FilterControls title={t('comparison.currentPeriod')} onReset={null}>
<FilterControls.Row>
<PeriodPicker
<div className="comparison-periods">
<div className="comparison-period-block">
<div className="comparison-period-label curr-label">{t('comparison.currentPeriod')}</div>
<DateRangePicker
startDate={currStart}
endDate={currEnd}
onChange={handleCurrChange}
availableYears={availableYears}
seasons={seasons}
/>
</div>
<div className="comparison-period-vs">{t('comparison.vs')}</div>
<div className="comparison-period-block">
<div className="comparison-period-label prev-label">{t('comparison.previousPeriod')}</div>
<DateRangePicker
startDate={prevStart}
endDate={prevEnd}
onChange={handlePrevChange}
availableYears={availableYears}
seasons={seasons}
/>
</div>
</div>
<FilterControls title={t('filters.title')} onReset={resetFilters}>
<FilterControls.Row>
<FilterControls.Group label={t('filters.district')}>
<select value={filters.district} onChange={e => setFilters({...filters, district: e.target.value, museum: []})}>
<option value="all">{t('filters.allDistricts')}</option>
@@ -542,6 +559,7 @@ function Comparison({ data, seasons, showDataLabels, setShowDataLabels, includeV
</FilterControls.Group>
<FilterControls.Group label={t('filters.channel')}>
<MultiSelect
label={t('filters.channel')}
options={channels}
selected={filters.channel}
onChange={selected => setFilters({...filters, channel: selected})}
@@ -550,6 +568,7 @@ function Comparison({ data, seasons, showDataLabels, setShowDataLabels, includeV
</FilterControls.Group>
<FilterControls.Group label={t('filters.museum')}>
<MultiSelect
label={t('filters.museum')}
options={availableMuseums}
selected={filters.museum}
onChange={selected => setFilters({...filters, museum: selected})}
@@ -559,18 +578,6 @@ function Comparison({ data, seasons, showDataLabels, setShowDataLabels, includeV
</FilterControls.Row>
</FilterControls>
<FilterControls title={t('comparison.previousPeriod')} onReset={null}>
<FilterControls.Row>
<PeriodPicker
startDate={prevStart}
endDate={prevEnd}
onChange={handlePrevChange}
availableYears={availableYears}
seasons={seasons}
/>
</FilterControls.Row>
</FilterControls>
<div className="period-display-banner" id="comparison-period">
<div className="period-box prev">
<div className="period-label">{t('comparison.previousPeriod')}</div>