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