Files
tilbudgivern/.github/copilot-instructions.md
alexpolo1 bbb75ccce2 feat: Add Advanced Dashboard and perform repo cleanup
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.
2026-02-28 17:38:23 +00:00

10 KiB
Raw Blame History

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 repos architecture, style, and workflows.

Prompt Patterns (copy/paste-ready)

  • Implement API route: "Create POST /api/smart-packages/recalculate in backend unified server with asyncHandler, correlation ID logging, { success, data/error } response, and unit + Playwright tests."
  • Add service method: "Add calculateRoofMetrics({ roofType, geometry }) in backend/src/services/geometryService.js with input validation and structured logging."
  • React component change: "Update frontend/src/components/InlineSmartPackage to display recalculated prices, using Material-UI and existing hook patterns."
  • Database migration: "Create migration to add package_materials.extra_cost_pct with default 0, update service to include it in totals, and write a rollback."
  • Playwright test: "Write a test for selecting Valmtag and verifying ridge length and price recalculation on the quote page."
  • Ordrestyring integration: "Add GraphQL query for cases with token from .env ORDRESTYRING_API_TOKEN, wrap with retry and error types."

Task Playbooks

  • New API endpoint

    1. Add route in backend/src/routes/ using asyncHandler and correlation IDs from request.
    2. Implement logic in backend/src/services/ with pure, testable functions.
    3. Return { success: true/false, data/error } and Danish error messages.
    4. Add Jest unit tests for service + route.
    5. Add Playwright E2E covering happy path and error states.
  • Smart Package update (pricing/logic)

    1. Adjust schema in migrations/ and ensure MariaDB compatibility.
    2. Update openaiService, databaseService, or smartPackagesService accordingly.
    3. Reflect changes in React components under frontend/src/components/.
    4. Seed/update fixtures for tests; verify totals and materials.
  • Roof geometry calculators

    1. Add calculator functions per roof type in geometryService.
    2. Validate inputs (tagareal, rygningslængde, facadelængde).
    3. Log with correlation IDs; return deterministic results for tests.
    4. UI: expose selectors and results in existing components.
  • Ordrestyring API usage

    1. Create GraphQL client wrapper with token from .env.
    2. Add typed responses and error typing.
    3. Backoff/retry for transient failures.
    4. Map into internal DTOs; log external request IDs.

Coding Guardrails

  • Async/await: Use asyncHandler for all route handlers; no raw try/catch without 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/.env only; 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)

  1. Sadeltag (pitched roof) - default
  2. Valmtag (hip roof)
  3. Københavnertag (Copenhagen roof)
  4. Fladtag (flat roof)
  5. Pulttag (shed roof)
  6. Tag med Kviste (roof with dormers)
  7. 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_TOKEN in .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 asyncHandler for 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 features
  • DB_HOST, DB_USER, DB_PASSWORD, DB_NAME - database

Optional:

  • ORDRESTYRING_API_TOKEN - order management
  • OPENAI_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:

  1. Praktisk anvendelighed - Can I use this after a long day on the roof?
  2. Faglig korrekthed - Is the terminology correct for Danish carpenters?
  3. Forretningsforståelse - Will this help win jobs without losing money?
  4. 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