UI & Styling
Rules
- No footer: This app does not have a footer. Put support/contact links in Settings page instead.
- Minimal chrome: Prioritize content over navigation/decoration.
Tailwind Classes
| Element | Classes |
|---|---|
| Inputs | w-full px-3 py-2 border border-slate-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 |
| Primary buttons | px-4 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700 text-sm font-medium disabled:opacity-50 |
| Secondary buttons | px-4 py-2 bg-slate-100 text-slate-700 rounded-lg hover:bg-slate-200 text-sm font-medium |
| Cards | bg-white rounded-lg shadow p-4 |
| Labels | block text-sm font-medium text-slate-700 mb-1 |
| Page titles | text-2xl font-bold text-slate-800 |
| Breadcrumbs | text-sm text-slate-500 with hover:text-brand-600 links |
Page Patterns
- List pages: Fetch collection on mount, display as card grid, link to detail/editor
- Create pages: Form in card with validation,
serverTimestamp()for dates, navigate to editor on success - Editor pages: Load entity + subcollection, render Toolbar + Editor component, CRUD via custom hook
CRUD Hooks
Admin (API-backed): All admin CRUD goes through Cloud Functions REST API via admin/src/services/apiClient.ts with Firebase Bearer token auth, retry with backoff. Domain hooks: useMallApi, useFloorApi, useStoreApi, useStreetApi, useBrandApi.
Web (Firestore-direct): Consumer PWA reads Firestore directly for performance. useFloorData loads vector map from API first, falls back to direct Firestore reads.