13 Commits

Author SHA1 Message Date
fahed
b8d33f4f8c feat: deploy Express server via CI/CD with systemd + nginx proxy
Some checks failed
Deploy HiHala Dashboard / deploy (push) Failing after 51m18s
- Update deploy.yml to rsync server/, install deps, write .env from
  Gitea secrets, and restart hihala-dashboard.service
- Move tsx to regular dependencies for production use
- Remove unused SESSION_SECRET from config
- Accept PORT env var as fallback for SERVER_PORT

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 17:59:34 +03:00
fahed
70af4962a6 feat: multi-user auth with role-based access
All checks were successful
Deploy HiHala Dashboard / deploy (push) Successful in 6s
- Server checks PIN against env (super admin) + NocoDB Users table
- Session stores name + role (admin/viewer)
- Admin: sees Settings page (seasons + users management)
- Viewer: sees Dashboard + Comparison only, no Settings
- Users CRUD on Settings page: add name + PIN + role, delete
- Settings link + nav hidden for non-admin users

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 22:17:44 +03:00
fahed
8cf6f9eedd feat: add PIN-based login with server-side cookie sessions
All checks were successful
Deploy HiHala Dashboard / deploy (push) Successful in 6s
- Server: POST /auth/login (verify PIN, set httpOnly cookie)
- Server: GET /auth/check, POST /auth/logout
- Client: Login page shown when not authenticated
- Session persists 7 days via httpOnly cookie
- PIN stored server-side only (ADMIN_PIN env var)
- Dashboard loads data only after successful auth

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 22:02:34 +03:00
fahed
ef48372033 feat: add Settings page with hijri seasons CRUD
- Server: seasons CRUD routes + generic NocoDB helpers
- Client: Settings page at /settings with inline add/edit/delete
- Seasons stored in NocoDB Seasons table
- Vite proxy: /api/seasons routed to Express server
- Nav links added (desktop + mobile)
- Locale keys for EN + AR
- Seasons loaded non-blocking on app mount

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 16:03:50 +03:00
fahed
04789ea9a1 fix: B2C visitor count uses UnitQuantity (1 ticket = 1 visitor)
All checks were successful
Deploy HiHala Dashboard / deploy (push) Successful in 8s
B2C generates one PDF ticket per person, so UnitQuantity = visitors.
Other channels (POS, Safiyyah POS, etc.) use PeopleCount for visitors
since group tickets cover multiple people.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:41:51 +03:00
fahed
219680fb5e feat: add district filter (Hiraa/AsSaffiyah) from static mapping
- ETL writes District column to NocoDB DailySales
- Museums mapped: Hiraa (Revelation, Holy Quraan, Trail, Makkah, VIP)
  AsSaffiyah (Creation Story, Best of Creation)
- District filter added to Dashboard and Comparison (cascades to museum)
- District Performance chart added (desktop + mobile)
- Locale keys added for both EN and AR

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:08:16 +03:00
fahed
4f4559023b feat: combo ticket 50/50 split + Best of Creation museum
- 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>
2026-03-31 13:53:25 +03:00
fahed
1f1e0756d0 feat: add server-side ETL pipeline, revert client to NocoDB reads
ETL Pipeline (server):
- POST /api/etl/sync?mode=full|incremental — fetches ERP, aggregates, writes NocoDB
- nocodbClient.ts: table discovery, paginated delete/insert
- etlSync.ts: orchestrates fetch → aggregate → upsert
- museumMapping.ts moved from client to server
- Auth via ETL_SECRET bearer token

Client:
- dataService.ts reverts to reading NocoDB DailySales table
- Paginated fetch via fetchNocoDBTable (handles >1000 rows)
- Suspicious data check: prefers cache if NocoDB returns <10 rows
- Deleted erpService.ts and client-side museumMapping.ts

First full sync: 391K transactions → 5,760 daily records in 108s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:25:50 +03:00
fahed
b4f4104e3e chore: remove Slides page and Salla console output
- 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>
2026-03-26 17:16:40 +03:00
fahed
ea71e54058 fix: change server port to 3002 to avoid conflict with rawaj-v2
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 16:49:59 +03:00
fahed
f6b7d4ba8d feat: migrate museum sales from NocoDB to Hono ERP API
- 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>
2026-03-26 16:43:34 +03:00
fahed
e84d961536 feat: convert server to TypeScript + add ERP API proxy
- Migrate server/index.js → modular TS structure (config, routes, services)
- Add ERP proxy: GET /api/erp/sales proxies Hono ERP API with server-side auth
- JWT token cached server-side, auto-refreshes on 401
- ERP credentials stay server-side only (no VITE_ prefix)
- Vite dev proxy routes /api/erp → localhost:3001
- Preserve existing Salla OAuth integration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 14:58:35 +03:00
fahed
9bb4ecb0dd last changes 2026-02-16 10:59:55 +03:00