Files
tilbudgivern/.github/copilot-instructions.md
T
alexpolo1 a03b6df348 feat: Crew scheduling system (Phase 1-3) - 8.5/10 rating
Phase 1: Quick Wins
- Calendar default tab, simplified 3-option filters
- Show all employees including free ones

Phase 2: Core Functionality
- POST /api/calendar/allocate endpoint
- AllocationModal component with validation
- Integration with Ordrestyring GraphQL API

Phase 2.5: UX Polish
- Prominent employee names with type badges
- NotificationToast system for success/error feedback
- Auto-refresh after allocation
- Removed confusing employee-type filter

Phase 3: Enhanced UX
- WhosFreeWidget with tabs (I dag | I morgen | Denne uge)
- Job names displayed on busy employees
- Quick-allocate with employee pre-selection
- Fixed undefined name sorting bugs

Lars validation: 8.5/10 - 'Replaces whiteboard for 90% of planning'
Real impact: 97% faster than manual process (5s vs 2-3 min)
2026-01-22 21:59:34 +00:00

5.5 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)

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

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