This commit introduces a new Advanced Dashboard feature, which provides enhanced analytics and system health monitoring. Additionally, this commit includes a general repository cleanup, which consists of: - Removal of a duplicate file from the root directory. - Addition of temporary report and documentation files to . - Relocation of several test files from the root to the directory. - Staging of various other modified files that were previously uncommitted. The new Advanced Dashboard feature includes: - and for the UI. - for the backend API. - for API documentation. New tests for smart packages and autosave functionality have also been added.
10 KiB
GitHub Copilot Instructions for Tilbudgivern
Project Overview
Tilbudgivern is an AI-powered quote calculator for the Danish carpentry trade (tømrerfaget). It generates detailed professional quotes for roofing and construction work using OpenAI GPT-4.
Primary Users: Danish carpenters creating quotes for roofing projects
Tech Stack
- Frontend: React 18 with Material-UI, served as static build from
frontend/build/ - Backend: Node.js/Express unified server (
backend/unified-server.js) - Database: MariaDB/MySQL on localhost:3306, database name
tilbudgivern - AI: OpenAI GPT-4 API (budget: $9/month)
- Process Manager: PM2 (process:
tilbudgivern-unified) - Testing: Playwright (primary), Selenium (backup), Jest (unit tests)
Copilot Agent Optimization
Use these focused patterns so Copilot generates changes that fit the repo’s architecture, style, and workflows.
Prompt Patterns (copy/paste-ready)
- Implement API route: "Create
POST /api/smart-packages/recalculatein backend unified server withasyncHandler, correlation ID logging,{ success, data/error }response, and unit + Playwright tests." - Add service method: "Add
calculateRoofMetrics({ roofType, geometry })inbackend/src/services/geometryService.jswith input validation and structured logging." - React component change: "Update
frontend/src/components/InlineSmartPackageto display recalculated prices, using Material-UI and existing hook patterns." - Database migration: "Create migration to add
package_materials.extra_cost_pctwith default 0, update service to include it in totals, and write a rollback." - Playwright test: "Write a test for selecting
Valmtagand verifying ridge length and price recalculation on the quote page." - Ordrestyring integration: "Add GraphQL query for cases with token from
.envORDRESTYRING_API_TOKEN, wrap with retry and error types."
Task Playbooks
-
New API endpoint
- Add route in
backend/src/routes/usingasyncHandlerand correlation IDs from request. - Implement logic in
backend/src/services/with pure, testable functions. - Return
{ success: true/false, data/error }and Danish error messages. - Add Jest unit tests for service + route.
- Add Playwright E2E covering happy path and error states.
- Add route in
-
Smart Package update (pricing/logic)
- Adjust schema in
migrations/and ensure MariaDB compatibility. - Update
openaiService,databaseService, orsmartPackagesServiceaccordingly. - Reflect changes in React components under
frontend/src/components/. - Seed/update fixtures for tests; verify totals and materials.
- Adjust schema in
-
Roof geometry calculators
- Add calculator functions per roof type in
geometryService. - Validate inputs (tagareal, rygningslængde, facadelængde).
- Log with correlation IDs; return deterministic results for tests.
- UI: expose selectors and results in existing components.
- Add calculator functions per roof type in
-
Ordrestyring API usage
- Create GraphQL client wrapper with token from
.env. - Add typed responses and error typing.
- Backoff/retry for transient failures.
- Map into internal DTOs; log external request IDs.
- Create GraphQL client wrapper with token from
Coding Guardrails
- Async/await: Use
asyncHandlerfor all route handlers; no rawtry/catchwithout logging. - Structured logging: Always call
logger.logInfo()/logger.logError()with correlation IDs and contextual fields. - Response format: Strictly return
{ success: true/false, data/error }with Danish user-facing errors. - Naming: Prefer domain names (quote, roof-type, smart-package, carpenter) and avoid cross-cutting helpers.
- React: Functional components + hooks with Material-UI; follow patterns in
frontend/src/components/. - DB: Keep services small, pure, and tested; avoid coupling route logic with DB queries.
- AI costs: Respect budget; avoid unnecessary OpenAI calls. Cache or batch when feasible.
Testing Expectations
- Unit (Jest): Add tests per service and route; aim for deterministic outputs and 80%+ coverage for new modules.
- E2E (Playwright): Cover critical user flows (select roof type, calculate, save quote) and common error states.
- Local runs: Ensure unified server on port 4032; use env vars from
backend/.env. - Artifacts: Attach screenshots and logs for failures in
playwright-report/.
Danish Terminology & UX
- Use domain-correct Danish terms (Tag, Spær, Tagrende, Nedløb, Vindsked, Sternbræt, Tagareal, Rygningslængde, Facadelængde).
- Keep UI labels concise and professional; prioritize carpenters’ workflows.
- Error messages in Danish; logs in English/Danish mixed are acceptable if consistent.
Security & Secrets
- Read secrets from
backend/.envonly; never commit credentials. - Validate all user inputs for endpoints; sanitize query params and payloads.
- Use the logging + correlation ID checklist for sensitive operations (customers, offers, materials pricing).
Pull Requests & Commits
- Favor Conventional Commits (e.g.,
feat: smart package recalculation endpoint). - Include a summary, test evidence (commands + results), and UI screenshots for relevant changes.
Architecture
Unified Server Pattern
The application uses a single server file (backend/unified-server.js) that:
- Serves React frontend from
frontend/build/ - Provides all API endpoints on port 4032
- Handles WebSocket via Socket.IO
- Includes structured logging with correlation IDs
Key Directories
backend/src/services/ # Business logic (openaiService, databaseService, etc.)
backend/src/routes/ # API endpoints (smartPackagesRoutes, customerProjects, etc.)
frontend/src/components/ # React components (InlineSmartPackage, EnhancedGeometry, etc.)
tests/ # Playwright and Selenium tests
docs/ # Project documentation
Smart Packages System
15 pre-configured carpenter packages for roofing work:
- Auto-calculation based on geometry (tagareal, rygningslængde, facadelængde)
- Categories: Tagdækning, Tagrende/Nedløb, Tagvinduer, Brædder, Specialarbejde
- Database tables:
smart_packages,package_tasks,package_materials
Roof Types (7 supported)
- Sadeltag (pitched roof) - default
- Valmtag (hip roof)
- Københavnertag (Copenhagen roof)
- Fladtag (flat roof)
- Pulttag (shed roof)
- Tag med Kviste (roof with dormers)
- Mansardtag (mansard roof)
External Integrations
Ordrestyring API
- GraphQL endpoint:
https://beta7-api.ordrestyring.dk/graphql - Used for: customers, cases, offers, calendar, hours tracking
- Token:
ORDRESTYRING_API_TOKENin.env
Material Suppliers
- Bygma: Price book import, installation manuals
- Stark: CSV catalog import via
/api/stark/upload
Code Style Guidelines
JavaScript/Node.js
- Use async/await for asynchronous operations
- Use structured logging via
logger.logInfo(),logger.logError() - Include correlation IDs in log calls
- Wrap route handlers with
asyncHandlerfor error handling
React Components
- Use functional components with hooks
- Use Material-UI components for consistency
- Follow existing patterns in
frontend/src/components/
API Endpoints
- Return
{ success: true/false, data/error }format - Use Danish error messages for user-facing errors
- Log errors with context and correlation IDs
Danish Language
The codebase and UI are in Danish. Key terminology:
- Tilbud = Quote/Offer
- Tømrer = Carpenter
- Materiale = Material
- Pakke = Package
- Pris = Price
- Tag = Roof
- Spær = Rafters
- Tagrende = Rain gutter
- Nedløb = Downspout
- Vindsked = Barge board
- Sternbræt = Fascia board
- Tagareal = Roof area
- Rygningslængde = Ridge length
- Facadelængde = Facade length
Common Commands
npm run dev # Development with hot reload
npm run build # Build frontend
pm2 restart tilbudgivern-unified # Restart server
npm run test:pw # Playwright tests
cd backend && npm test # Jest unit tests
Test & Dev Helpers
# Local Playwright against unified server
npm run test:pw:local
# Selenium UI tests against localhost
npm run test:selenium:local
# Full test + build + PM2 restart
./test-build-deploy.sh
# Quick deploy for small changes
./quick-deploy.sh
Environment Variables
Required in backend/.env:
OPENAI_API_KEY- for AI featuresDB_HOST,DB_USER,DB_PASSWORD,DB_NAME- database
Optional:
ORDRESTYRING_API_TOKEN- order managementOPENAI_ADMIN_KEY- cost tracking
Custom Agents
carpenter-user-tester
When to use: Need realistic user testing from a carpenter's perspective, evaluating UI/UX for trade professionals, validating that carpentry terminology and workflows make sense, or getting feedback on features from the viewpoint of a busy tømrer (carpenter) running their own business.
Persona: Lars, a 47-year-old Danish master carpenter (tømrermester) with 22 years of business experience in Jylland, specializing in roofing work.
Expertise:
- Expert in all 7 roof types (sadeltag, valmtag, københavnertag, fladtag, pulttag, tag med kviste, mansardtag)
- Deep knowledge of materials and suppliers (Bygma, Stark)
- Creates 5-10 quotes weekly, often after long workdays
- Prefers simple, practical software that "just works"
Testing Focus:
- Praktisk anvendelighed - Can I use this after a long day on the roof?
- Faglig korrekthed - Is the terminology correct for Danish carpenters?
- Forretningsforståelse - Will this help win jobs without losing money?
- Hverdagssituationer - How does it handle real-world scenarios?
Use Examples:
- After implementing new UI components for quote generation
- When adding or changing Danish carpentry terminology
- Testing workflow changes to Smart Packages
- Validating roof geometry calculators
- Reviewing quote presentation to customers
Output Format:
- Førsteindtryk (First Impression)
- Det der virker (What Works)
- Udfordringer (Challenges)
- Forslag (Suggestions)
- Faglig vurdering (Professional Assessment)
- Samlet dom (Overall Verdict)
Invoke with: "@carpenter-user-tester" or mention need for trade-professional UX feedback