- Implemented user notification preferences table for managing default notification settings. - Created sag_reminders table to define reminder rules with various trigger types and recipient configurations. - Developed sag_reminder_queue for processing reminder events triggered by status changes or scheduled times. - Added sag_reminder_logs to track reminder notifications and user interactions. - Introduced frontend notification system using Bootstrap 5 Toast for displaying reminders. - Created email template for sending reminders with case details and action links. - Implemented rate limiting for user notifications to prevent spamming. - Added triggers and functions for automatic updates and reminder processing.
460 lines
13 KiB
Markdown
460 lines
13 KiB
Markdown
# GitHub Copilot Instructions - BMC Webshop (Frontend)
|
|
|
|
## Project Overview
|
|
|
|
BMC Webshop er en kunde-styret webshop løsning, hvor **BMC Hub** ejer indholdet, **API Gateway** (`apigateway.bmcnetworks.dk`) styrer logikken, og **Webshoppen** (dette projekt) kun viser og indsamler input.
|
|
|
|
**Tech Stack**: React/Next.js/Vue.js (vælg én), TypeScript, Tailwind CSS eller Bootstrap 5
|
|
|
|
---
|
|
|
|
## 3-Lags Arkitektur
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ TIER 1: BMC HUB (Admin System) │
|
|
│ - Administrerer webshop-opsætning │
|
|
│ - Pusher data til Gateway │
|
|
│ - Poller Gateway for nye ordrer │
|
|
│ https://hub.bmcnetworks.dk │
|
|
└─────────────────────────────────────────────────────────┘
|
|
▼ (Push config)
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ TIER 2: API GATEWAY (Forretningslogik + Database) │
|
|
│ - Modtager og gemmer webshop-config fra Hub │
|
|
│ - Ejer PostgreSQL database med produkter, priser, ordrer│
|
|
│ - Håndterer email/OTP login │
|
|
│ - Beregner priser og filtrerer varer │
|
|
│ - Leverer sikre API'er til Webshoppen │
|
|
│ https://apigateway.bmcnetworks.dk │
|
|
└─────────────────────────────────────────────────────────┘
|
|
▲ (API calls)
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ TIER 3: WEBSHOP (Dette projekt - Kun Frontend) │
|
|
│ - Viser logo, tekster, produkter, priser │
|
|
│ - Shopping cart (kun i frontend state) │
|
|
│ - Sender ordre som payload til Gateway │
|
|
│ - INGEN forretningslogik eller datapersistering │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Webshoppens Ansvar
|
|
|
|
### ✅ Hvad Webshoppen GØR
|
|
- Viser kundens logo, header-tekst, intro-tekst (fra Gateway)
|
|
- Viser produktkatalog med navn, beskrivelse, pris (fra Gateway)
|
|
- Samler kurv i browser state (localStorage/React state)
|
|
- Sender ordre til Gateway ved checkout
|
|
- Email/OTP login flow (kalder Gateway's auth-endpoint)
|
|
|
|
### ❌ Hvad Webshoppen IKKE GØR
|
|
- Gemmer INGEN data (hverken kurv, produkter, eller ordrer)
|
|
- Beregner INGEN priser eller avance
|
|
- Håndterer INGEN produkt-filtrering (Gateway leverer klar liste)
|
|
- Snakker IKKE direkte med Hub eller e-conomic
|
|
- Håndterer IKKE betalingsgateway (Gateway's ansvar)
|
|
|
|
---
|
|
|
|
## API Gateway Kontrakt
|
|
|
|
Base URL: `https://apigateway.bmcnetworks.dk`
|
|
|
|
### 1. Login med Email + Engangskode
|
|
|
|
**Step 1: Anmod om engangskode**
|
|
```http
|
|
POST /webshop/auth/request-code
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"email": "kunde@firma.dk"
|
|
}
|
|
|
|
Response 200:
|
|
{
|
|
"success": true,
|
|
"message": "Engangskode sendt til kunde@firma.dk"
|
|
}
|
|
```
|
|
|
|
**Step 2: Verificer kode og få JWT token**
|
|
```http
|
|
POST /webshop/auth/verify-code
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"email": "kunde@firma.dk",
|
|
"code": "123456"
|
|
}
|
|
|
|
Response 200:
|
|
{
|
|
"success": true,
|
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"customer_id": 42,
|
|
"expires_at": "2026-01-13T15:00:00Z"
|
|
}
|
|
```
|
|
|
|
### 2. Hent Webshop Context (Komplet Webshop-Data)
|
|
|
|
```http
|
|
GET /webshop/{customer_id}/context
|
|
Authorization: Bearer {jwt_token}
|
|
|
|
Response 200:
|
|
{
|
|
"customer_id": 42,
|
|
"company_name": "Advokatfirma A/S",
|
|
"config_version": "2026-01-13T12:00:00Z",
|
|
"branding": {
|
|
"logo_url": "https://apigateway.bmcnetworks.dk/assets/logos/42.png",
|
|
"header_text": "Velkommen til vores webshop",
|
|
"intro_text": "Bestil nemt og hurtigt direkte her.",
|
|
"primary_color": "#0f4c75",
|
|
"accent_color": "#3282b8"
|
|
},
|
|
"products": [
|
|
{
|
|
"id": 101,
|
|
"ean": "5711045071324",
|
|
"product_number": "FIRE-001",
|
|
"name": "Cisco Firewall ASA 5506-X",
|
|
"description": "Next-generation firewall med 8 porte",
|
|
"unit": "stk",
|
|
"base_price": 8500.00,
|
|
"calculated_price": 9350.00,
|
|
"margin_percent": 10.0,
|
|
"currency": "DKK",
|
|
"stock_available": true,
|
|
"category": "Network Security"
|
|
},
|
|
{
|
|
"id": 102,
|
|
"ean": "5704174801740",
|
|
"product_number": "SW-024",
|
|
"name": "TP-Link 24-Port Gigabit Switch",
|
|
"description": "Managed switch med VLAN support",
|
|
"unit": "stk",
|
|
"base_price": 2100.00,
|
|
"calculated_price": 2310.00,
|
|
"margin_percent": 10.0,
|
|
"currency": "DKK",
|
|
"stock_available": true,
|
|
"category": "Switches"
|
|
}
|
|
],
|
|
"allowed_payment_methods": ["invoice", "card"],
|
|
"min_order_amount": 500.00,
|
|
"shipping_cost": 0.00
|
|
}
|
|
```
|
|
|
|
### 3. Opret Ordre
|
|
|
|
```http
|
|
POST /webshop/orders
|
|
Authorization: Bearer {jwt_token}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"customer_id": 42,
|
|
"order_items": [
|
|
{
|
|
"product_id": 101,
|
|
"quantity": 2,
|
|
"unit_price": 9350.00
|
|
},
|
|
{
|
|
"product_id": 102,
|
|
"quantity": 5,
|
|
"unit_price": 2310.00
|
|
}
|
|
],
|
|
"shipping_address": {
|
|
"company_name": "Advokatfirma A/S",
|
|
"street": "Hovedgaden 1",
|
|
"postal_code": "1000",
|
|
"city": "København K",
|
|
"country": "DK"
|
|
},
|
|
"delivery_note": "Levering til bagsiden, ring på døren",
|
|
"total_amount": 30250.00
|
|
}
|
|
|
|
Response 201:
|
|
{
|
|
"success": true,
|
|
"order_id": "ORD-2026-00123",
|
|
"status": "pending",
|
|
"total_amount": 30250.00,
|
|
"created_at": "2026-01-13T14:30:00Z",
|
|
"message": "Ordre modtaget. Du vil modtage en bekræftelse på email."
|
|
}
|
|
```
|
|
|
|
### 4. Hent Mine Ordrer (Optional)
|
|
|
|
```http
|
|
GET /webshop/orders?customer_id=42
|
|
Authorization: Bearer {jwt_token}
|
|
|
|
Response 200:
|
|
{
|
|
"orders": [
|
|
{
|
|
"order_id": "ORD-2026-00123",
|
|
"created_at": "2026-01-13T14:30:00Z",
|
|
"status": "pending",
|
|
"total_amount": 30250.00,
|
|
"item_count": 7
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Frontend Krav
|
|
|
|
### Mandatory Features
|
|
|
|
1. **Responsive Design**
|
|
- Mobile-first approach
|
|
- Breakpoints: 576px (mobile), 768px (tablet), 992px (desktop)
|
|
- Brug CSS Grid/Flexbox eller framework grid system
|
|
|
|
2. **Dark Mode Support**
|
|
- Toggle mellem light/dark theme
|
|
- Gem præference i localStorage
|
|
- CSS Variables for farver
|
|
|
|
3. **Shopping Cart**
|
|
- Gem kurv i localStorage (persist ved page reload)
|
|
- Vis antal varer i header badge
|
|
- Real-time opdatering af total pris
|
|
- Slet/rediger varer i kurv
|
|
|
|
4. **Login Flow**
|
|
- Email input → Send kode
|
|
- Vis countdown timer (5 minutter)
|
|
- Verificer kode → Få JWT token
|
|
- Gem token i localStorage
|
|
- Auto-logout ved token expiry
|
|
|
|
5. **Product Catalog**
|
|
- Vis produkter i grid layout (3-4 kolonner på desktop)
|
|
- Filtrer produkter efter kategori (hvis Gateway leverer kategorier)
|
|
- Søgning i produktnavn/beskrivelse
|
|
- "Tilføj til kurv" knap med antal-vælger
|
|
|
|
6. **Checkout Flow**
|
|
- Vis kurv-oversigt
|
|
- Leveringsadresse (kan være pre-udfyldt fra Gateway)
|
|
- Leveringsnotat (textarea)
|
|
- "Bekræft ordre" knap
|
|
- Loading state under ordre-oprettelse
|
|
- Success/error feedback
|
|
|
|
### Design Guidelines
|
|
|
|
**Stil**: Minimalistisk, clean, "Nordic" æstetik (inspireret af BMC Hub's Nordic Top design)
|
|
|
|
**Farver** (kan overskrives af Gateway's branding config):
|
|
- Primary: `#0f4c75` (Deep Blue)
|
|
- Accent: `#3282b8` (Bright Blue)
|
|
- Success: `#27ae60`
|
|
- Warning: `#f39c12`
|
|
- Danger: `#e74c3c`
|
|
|
|
**Typografi**:
|
|
- Font: System font stack (`-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, ...`)
|
|
- Headings: 500-600 weight
|
|
- Body: 400 weight
|
|
|
|
**Components**:
|
|
- Cards med subtil shadow/border
|
|
- Buttons med hover states
|
|
- Input fields med focus outline
|
|
- Loading spinners (ikke lange tekst-beskeder)
|
|
|
|
---
|
|
|
|
## State Management
|
|
|
|
### Local Storage Keys
|
|
```javascript
|
|
// Authentication
|
|
webshop_jwt_token // JWT token fra Gateway
|
|
webshop_customer_id // Customer ID
|
|
webshop_token_expires_at // ISO timestamp
|
|
|
|
// Shopping Cart
|
|
webshop_cart // JSON array af cart items
|
|
webshop_theme // "light" eller "dark"
|
|
|
|
// Cache (optional)
|
|
webshop_context // Cached webshop context (TTL: 5 minutter)
|
|
```
|
|
|
|
### Cart Item Format
|
|
```javascript
|
|
{
|
|
product_id: 101,
|
|
ean: "5711045071324",
|
|
name: "Cisco Firewall ASA 5506-X",
|
|
unit_price: 9350.00,
|
|
quantity: 2,
|
|
total: 18700.00
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
### Gateway API Errors
|
|
```javascript
|
|
// Eksempel på error response fra Gateway
|
|
{
|
|
"success": false,
|
|
"error": "invalid_code",
|
|
"message": "Ugyldig engangskode. Prøv igen."
|
|
}
|
|
```
|
|
|
|
**Error Codes** (forventet fra Gateway):
|
|
- `invalid_email` - Email ikke fundet eller ikke whitelisted
|
|
- `invalid_code` - Forkert engangskode
|
|
- `code_expired` - Engangskode udløbet (>5 min)
|
|
- `token_expired` - JWT token udløbet
|
|
- `unauthorized` - Manglende/ugyldig Authorization header
|
|
- `product_not_found` - Produkt ID findes ikke
|
|
- `min_order_not_met` - Ordre under minimum beløb
|
|
- `out_of_stock` - Produkt ikke på lager
|
|
|
|
**Handling**:
|
|
- Vis brugervenlig fejlbesked i UI (ikke tekniske detaljer)
|
|
- Log tekniske fejl til console (kun i development)
|
|
- Redirect til login ved `token_expired` eller `unauthorized`
|
|
|
|
---
|
|
|
|
## Security
|
|
|
|
1. **HTTPS Only**
|
|
- Al kommunikation med Gateway over HTTPS
|
|
- Ingen hardcoded credentials
|
|
|
|
2. **JWT Token**
|
|
- Gem i localStorage (ikke cookie)
|
|
- Send i `Authorization: Bearer {token}` header
|
|
- Check expiry før hver API call
|
|
- Auto-logout ved expiry
|
|
|
|
3. **Input Validation**
|
|
- Validér email format (client-side)
|
|
- Validér antal > 0 ved "Tilføj til kurv"
|
|
- Validér leveringsadresse udfyldt ved checkout
|
|
- Sanitize input (brug library som DOMPurify hvis nødvendigt)
|
|
|
|
4. **CORS**
|
|
- Gateway skal have `Access-Control-Allow-Origin` header
|
|
- Webshoppen kalder altid Gateway (ikke Hub direkte)
|
|
|
|
---
|
|
|
|
## Deployment
|
|
|
|
### Environment Variables
|
|
```bash
|
|
# .env.production
|
|
NEXT_PUBLIC_API_GATEWAY_URL=https://apigateway.bmcnetworks.dk
|
|
NEXT_PUBLIC_WEBSHOP_NAME="BMC Networks Webshop"
|
|
```
|
|
|
|
### Build Process
|
|
```bash
|
|
# Development
|
|
npm run dev
|
|
|
|
# Production build
|
|
npm run build
|
|
npm run start
|
|
|
|
# Docker (optional)
|
|
docker build -t bmc-webshop .
|
|
docker run -p 3000:3000 bmc-webshop
|
|
```
|
|
|
|
### Static Hosting (Anbefalet)
|
|
- Vercel, Netlify, eller Cloudflare Pages
|
|
- Deploy fra Git repository
|
|
- Automatisk HTTPS og CDN
|
|
- Environment variables i hosting provider UI
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
### Manual Testing Checklist
|
|
- [ ] Login med email/OTP virker
|
|
- [ ] Token gemmes og bruges i efterfølgende API calls
|
|
- [ ] Webshop context hentes og vises korrekt
|
|
- [ ] Produkter vises i grid
|
|
- [ ] "Tilføj til kurv" opdaterer cart badge
|
|
- [ ] Cart viser korrekte varer og total pris
|
|
- [ ] Checkout sender korrekt payload til Gateway
|
|
- [ ] Success message vises ved succesfuld ordre
|
|
- [ ] Error handling virker (test med ugyldig kode, udløbet token)
|
|
- [ ] Dark mode toggle virker
|
|
- [ ] Responsive design på mobil/tablet/desktop
|
|
|
|
---
|
|
|
|
## Common Pitfalls to Avoid
|
|
|
|
1. **Gem IKKE data i Webshoppen** - alt kommer fra Gateway
|
|
2. **Beregn IKKE priser selv** - Gateway leverer `calculated_price`
|
|
3. **Snakker IKKE direkte med Hub** - kun via Gateway
|
|
4. **Gem IKKE kurv i database** - kun localStorage
|
|
5. **Hardcode IKKE customer_id** - hent fra JWT token
|
|
6. **Valider IKKE produkter selv** - Gateway filtrerer allerede
|
|
7. **Implementer IKKE betalingsgateway** - Gateway's ansvar
|
|
|
|
---
|
|
|
|
## Quick Reference
|
|
|
|
### API Endpoints
|
|
```
|
|
POST /webshop/auth/request-code # Anmod engangskode
|
|
POST /webshop/auth/verify-code # Verificer kode → JWT
|
|
GET /webshop/{customer_id}/context # Hent webshop data
|
|
POST /webshop/orders # Opret ordre
|
|
GET /webshop/orders?customer_id={id} # Hent mine ordrer
|
|
```
|
|
|
|
### Typical Flow
|
|
```
|
|
1. User indtaster email → POST /auth/request-code
|
|
2. User indtaster kode → POST /auth/verify-code → Gem JWT token
|
|
3. App henter webshop context → GET /context (med JWT header)
|
|
4. User browser produkter, tilføjer til kurv (localStorage)
|
|
5. User går til checkout → POST /orders (med cart data)
|
|
6. Gateway behandler ordre → Success message vises
|
|
```
|
|
|
|
---
|
|
|
|
## Support & Documentation
|
|
|
|
**Hub Repository**: `/Users/christianthomas/DEV/bmc_hub_dev`
|
|
**Hub API Docs**: `https://hub.bmcnetworks.dk/api/docs`
|
|
**Gateway API Docs**: `https://apigateway.bmcnetworks.dk/docs` (når implementeret)
|
|
|
|
**Kontakt**: ct@bmcnetworks.dk
|