The theme set minimumSize: Size(double.infinity, 52) which creates
an internal ConstrainedBox(w=Infinity) inside every button. This
crashes when any button is placed in unbounded width context (Row).
Changed to Size(0, 52) — GenexButton's LayoutBuilder handles width.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use LayoutBuilder to detect whether parent provides bounded width.
When fullWidth=true in an unbounded context (e.g. Row without
Expanded), gracefully fall back to content-sized width instead of
forcing SizedBox(width: double.infinity) which triggers
"BoxConstraints forces an infinite width" assertion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create (admin) route group with AdminLayout wrapper
- Add page.tsx route files for all 25 view pages (dashboard, issuers,
users, trading, risk, compliance, system, disputes, coupons, finance,
chain, reports, merchant, agent, insurance, analytics sub-pages,
compliance sub-pages)
- Update AdminLayout to use Next.js usePathname/useRouter for real
URL-based navigation instead of internal state
- Add 'use client' directive to view components using useState hooks
- Fix 404 on /dashboard by creating proper App Router route structure
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Next.js treats `src/pages/` as the Pages Router and requires every file
to have a default export. Our page components use named exports
(e.g. `export const DashboardPage`) since they are UI view components,
not Next.js route handlers.
Rename to `src/views/` so Next.js only uses the App Router (`src/app/`).
The App Router page.tsx files will import from `@/views/` as needed.
24 files moved: src/pages/**/*.tsx → src/views/**/*.tsx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The milestones array only had 'progress' and 'pending' status values,
causing TS to infer the status type as 'progress' | 'pending'. The
template code then compared m.status === 'done' which TS flagged as
unreachable. Fix by explicitly typing the array to include all three
possible status values: 'done' | 'progress' | 'pending'.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The initial project has no node_modules or package-lock.json yet.
Use wildcard COPY for lock file and fallback to `npm install`
when lock file doesn't exist. Once lock file is generated and
committed, it will automatically use the faster `npm ci`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add complete deployment toolchain for the Genex Admin Web (React + Next.js),
mirroring the proven deployment pattern from the rwadurian project.
## Files added
### deploy.sh — One-click deployment script
- Commands: build / start / stop / restart / logs / status / clean
- Auto-detects `docker compose` vs `docker-compose`
- Port conflict detection with auto-stop of old service
- Health check verification after startup
- Supports PORT env override (default: 3000)
### Dockerfile — Multi-stage production build
- Stage 1 (deps): node:20-alpine, npm ci for deterministic installs
- Stage 2 (builder): Next.js production build with telemetry disabled
- Stage 3 (runner): Minimal runtime with standalone output
- Non-root user (nextjs:nodejs) for security
- curl installed for container health checks
### docker-compose.yml — Container orchestration
- Service: genex-admin-web on genex-network bridge
- Health check: GET /api/health every 30s, 3 retries
- Auto-restart: unless-stopped policy
- Timezone: Asia/Shanghai
### .env.development — Local dev environment
- API: http://localhost:8080/api
### .env.production — Production environment
- API: https://api.gogenex.com/api
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>