- Combo tickets (matching multiple museums) split revenue/visits evenly
- Each museum gets its own row tagged with TicketType=combo, ComboWith
- Added Best of Creation (متحف خير الخلق) to museum mapping
- Holy Quraan Museum now shows 3.3M total (was 971K without combo share)
- ComboMuseums column tracks split factor for auditing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove Slides route, import, and mobile nav link from App.tsx
- Remove Salla route mounting and console output from server
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The ERP API can't handle concurrent requests — switch from batched
parallel (4 at a time) to sequential fetching.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace NocoDB museum data (Districts/Museums/DailyStats) with ERP API
- Client fetches via server proxy (/api/erp/sales) — no credentials in browser
- Aggregate transaction-level ERP data into daily/museum/channel records
- Replace "district" dimension with "channel" (B2C/HiHala, POS, B2B, etc.)
- Add product-to-museum mapping (46 products → 6 museums)
- NocoDB retained only for PilgrimStats
- Remove old server/index.js (replaced by modular TS in server/src/)
- Update all components, types, and locale files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Preserves current NocoDB-based state before switching museum
sales data source to the Hono ERP API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Default to light theme instead of system preference, and update
dashboard subtitle to reflect VivaTicket as the data source.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Stat cards lift on hover (translateY -2px + shadow elevation)
- Metric cards lift on hover
- Chart cards fade-up with staggered delays on mount
- All animations respect prefers-reduced-motion (already in place)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add prefers-color-scheme: dark media query for automatic dark mode
- Add data-theme attribute for manual override (persisted to localStorage)
- 3-state cycle: system → dark → light → system
- Theme toggle button in nav with contextual icon (sun/moon/half)
- Dark palette: slate-900 bg, slate-800 surfaces, adjusted text/accent/success/danger
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add aria-labels to icon-only buttons (refresh, language toggle)
- Add aria-hidden to decorative SVGs
- Add aria-label to data source select
- Replace outline:none with visible focus rings on all inputs/selects
- Add <main> landmark for screen reader navigation
- Add prefers-reduced-motion: disable all animations for vestibular safety
- Move error message inline style to CSS class
- Add aria-label to both nav landmarks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Enable strict: true in tsconfig.json (was false)
- Add proper interfaces for all component props (Dashboard, Comparison, Slides)
- Add SlideConfig, ChartTypeOption, MetricOption types
- Type all function parameters, callbacks, and state variables
- Fix dynamic property access with proper keyof assertions
- 233 type errors resolved across 5 files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Lazy-load Dashboard, Comparison, Slides via React.lazy + Suspense
- Main bundle reduced from 606KB to 256KB
- Replace full-screen spinner with skeleton cards during load
- Skeleton used for both initial data fetch and route transitions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Table IDs are now fetched at runtime via the NocoDB meta API using
VITE_NOCODB_BASE_ID, so the same code works against any NocoDB instance
(local or Cloudron). Also adds a migration script for moving data between
instances with correct FK remapping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Production NocoDB uses DistrictId/MuseumId columns instead of
nc_epk____ link columns. Code now checks both column names.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vite inlines env vars at build time, so they must be available
during the build step via Gitea secrets.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove server deployment, dependency install, and systemd restart.
The app connects directly to NocoDB from the browser.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CRA (react-scripts 5.0.1) is abandoned and incompatible with TypeScript 5.x.
Vite provides faster builds, active maintenance, and native TS5 support.
- Replace react-scripts with vite + @vitejs/plugin-react
- Move index.html to root with script module entry point
- Replace setupProxy.js with vite.config.ts proxy config
- Rename env vars from REACT_APP_ to VITE_ prefix
- Update tsconfig for bundler module resolution
- Add nginx setup script for deployment
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Convert all .js files to .tsx/.ts
- Add types for data structures (MuseumRecord, Metrics, etc.)
- Add type declarations for react-chartjs-2
- Configure tsconfig with relaxed strictness for gradual adoption
- All components now use TypeScript
- Rename Revenue to GrossRevenue, add NetRevenue (excl. VAT)
- Add VAT toggle (Incl/Excl) on Dashboard and Comparison pages
- Add offline mode with localStorage caching (24h validity)
- Add refresh button and offline indicator in nav
- Remove Google Sheets fallback (archived to dataService.legacy.js)
- Add AR/EN translations for new UI elements
- Force LTR direction on chart canvas elements via CSS
- Add locale: 'en-US' to chart options for consistent number formatting
- Add textDirection: 'ltr' to datalabels and tooltip configs
- Fixes background/text misalignment in Arabic RTL mode
- Add globe icon to language toggle
- Style with border, proper padding, and hover effects
- Match overall nav design language
- Use Inter font for Arabic mode to show 'EN' consistently
- Add .exportable-chart.chart-container rule with flex:none and height:380px
- This overrides the flex:1 that was preventing height from being applied
- Also fixed .chart-section .chart-container to 380px
- Increase chart height from 280px to 380px (more square-like)
- Move controls below chart title (column layout)
- Spread two control groups left/right with space-between
- Make controls more compact (smaller padding, font-size)
- Move export button outside header-actions to enable absolute positioning
- Button now positioned at top-right (LTR) / top-left (RTL)
- Switch from Tajawal to IBM Plex Sans Arabic (slicker, more technical)
- Add RTL-specific font-family in CSS