# Copilot Instructions for TJWater Frontend ## Project Overview A Next.js 16 + TypeScript water network management system built with Refine framework, featuring real-time hydraulic simulation, SCADA data management, and GIS visualization using OpenLayers and Deck.gl. ## Build, Test, and Lint Commands ```bash # Development npm run dev # Start dev server (uses 4GB memory allocation) # Production npm run build # Build for production (standalone output) npm run start # Start production server # Testing npm run test # Run all tests npm run test:watch # Run tests in watch mode npm run test:coverage # Generate coverage report # Linting npm run lint # Run ESLint ``` **Run single test file:** ```bash npm test -- path/to/test-file.test.ts ``` ## Architecture ### Framework Stack - **Next.js 16** with App Router (not Pages Router) - **Refine** framework for admin/CRUD operations - **NextAuth.js** with Keycloak for SSO authentication - **Material-UI (MUI) v6** for UI components - **OpenLayers** + **Deck.gl** for map visualization ### Route Structure - `src/app/layout.tsx` - Root layout with RefineContext - `src/app/(main)/` - Protected routes with shared layout - `/network-simulation` - Real-time network simulation - `/scada-data-cleaning` - SCADA data management - `/monitoring-place-optimization` - Sensor placement optimization - `/health-risk-analysis` - Health risk assessment - `/risk-analysis-location` - Risk location analysis - `/network-partition-optimization` - Network partitioning - `src/app/OlMap/` - Standalone map route with custom controls - `src/app/login/` - Public authentication pages ### Key Directories - `src/app/_refine_context.tsx` - Refine configuration with resources, auth provider, and data provider - `src/providers/data-provider/` - REST API data provider (currently mock, update API_URL for production) - `src/contexts/color-mode/` - Theme switching (light/dark mode persisted in cookies) - `src/components/` - Reusable UI components (header, loading, olmap, title) - `src/utils/` - Map utilities (layers.ts, mapQueryService.ts, color parsing) - `src/config/config.ts` - Environment-based configuration with fallback defaults ### Path Aliases (TypeScript) ```typescript @app/* -> src/app/* @assets/* -> src/assets/* @components/* -> src/components/* @config/* -> src/config/* @contexts/* -> src/contexts/* @interfaces/* -> src/interfaces/* @libs/* -> src/libs/* @providers/* -> src/providers/* @utils/* -> src/utils/* @/* -> src/* ``` ### Map Architecture The map system uses a hybrid approach: - **OpenLayers** as the base map engine (vector tiles from GeoServer) - **Deck.gl** overlays for advanced visualizations (trips, contours, text labels) - **DeckLayer** custom class bridges OL and Deck.gl (`@utils/layers`) - Map data sourced from GeoServer MVT tiles (configured in `@config/config.ts`) - Layers: junctions, pipes, valves, reservoirs, pumps, tanks, scada ### Client vs Server Components - Most interactive components use `"use client"` directive (~35 files) - Map components are always client-side (OpenLayers requires browser APIs) - Layout and page files without interactivity can be server components ## Key Conventions ### Authentication Flow - Keycloak SSO via NextAuth.js (`src/app/api/auth/[...nextauth]/`) - Session managed with `SessionProvider` wrapper - Auth check redirects to `/login` if unauthenticated - Use `useSession()` hook for current user data ### Environment Variables - All frontend-accessible variables must have `NEXT_PUBLIC_` prefix - Backend URL: `NEXT_PUBLIC_BACKEND_URL` (defaults to http://192.168.1.42:8000) - GeoServer URL: `NEXT_PUBLIC_MAP_URL` (defaults to http://127.0.0.1:8080/geoserver) - Map layers: `NEXT_PUBLIC_MAP_AVAILABLE_LAYERS` (comma-separated) - Keycloak config in `.env.local` (not committed) ### Refine Resources Resources defined in `_refine_context.tsx` use Chinese labels and route to pages in `(main)/`: - Each resource has: name (Chinese), list (route path), meta (icon + label) - Icons from `react-icons` library - No CRUD operations defined (list-only pages) ### Map Styling - Default styles in `config.MAP_DEFAULT_STYLE` (stroke, circle, colors) - Circle radius uses zoom-based interpolation (1px at z12, 8px at z24) - WebGL rendering for vector tiles - Style legends generated dynamically in map controls ### TypeScript Configuration - Strict mode enabled - Path aliases match jest.config.js mappings - Target ES5 for broader compatibility - Incremental builds enabled ### Next.js Configuration - **Standalone output** for Docker deployment - SVG files handled by `@svgr/webpack` (imported as React components) - No custom server or middleware ### Testing Setup - Jest with React Testing Library - jsdom environment for component testing - Path aliases configured to match tsconfig.json - Setup file at `jest.setup.js` ## Common Patterns ### Adding a New Route 1. Create directory in `src/app/(main)/your-route/` 2. Add `page.tsx` and optional `loading.tsx` 3. Register resource in `src/app/_refine_context.tsx` resources array 4. Import icon from `react-icons` ### Working with Maps - Use `MapComponent` from `src/app/OlMap/MapComponent.tsx` - Access map context via `useMapData()` hook - Vector tile layers auto-load from GeoServer workspace - Custom overlays use Deck.gl layers (TextLayer, TripsLayer, ContourLayer) ### API Calls - Update `dataProvider` in `src/providers/data-provider/index.ts` for real backend - Currently points to `https://api.fake-rest.refine.dev` - Use Refine hooks (`useList`, `useOne`, etc.) for data fetching ### Theme Management - Theme stored in cookies (not localStorage) - Toggle via `ColorModeContext` from `@contexts/color-mode` - Supports light/dark modes only - Default mode read from cookie in root layout (server-side)