feat: Production-ready configurator with Dutch standards, pricing & visual UI
- Update door-models.ts: 7mm VSG 33.1 safety glass, 15mm offset, Taats pivot 60mm - Add pricing engine (lib/pricing.ts): steel €45/m + glass €140/m² + €650 base - Wire reactive pricing into Zustand store on every config change - Fix 3D materials: glass thickness 0.007m, corrected roughness/metalness - Upgrade scene: apartment environment, wider contact shadows - Add Dutch height presets: Renovatie 2015mm, Nieuwbouw 2315mm, Plafondhoog 2500mm - Replace text buttons with visual SVG tiles for door type & grid selection Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
31
lib/store.ts
31
lib/store.ts
@@ -9,6 +9,7 @@ import {
|
||||
type SidePanel,
|
||||
} from './calculations';
|
||||
import type { GlassPattern } from './glass-patterns';
|
||||
import { calculatePrice, type PriceBreakdown } from './pricing';
|
||||
|
||||
export type DoorType = 'taats' | 'scharnier' | 'paneel';
|
||||
export type GridType = '3-vlak' | '4-vlak' | 'geen';
|
||||
@@ -38,6 +39,9 @@ interface ConfiguratorState {
|
||||
minWidth: number;
|
||||
maxWidth: number;
|
||||
|
||||
// Pricing
|
||||
priceBreakdown: PriceBreakdown;
|
||||
|
||||
// Actions
|
||||
setDoorType: (type: DoorType) => void;
|
||||
setDoorConfig: (config: DoorConfig) => void;
|
||||
@@ -64,6 +68,13 @@ const recalculate = (get: () => ConfiguratorState, set: (state: Partial<Configur
|
||||
});
|
||||
};
|
||||
|
||||
// Helper function for price recalculation
|
||||
const recalculatePrice = (get: () => ConfiguratorState, set: (state: Partial<ConfiguratorState>) => void) => {
|
||||
const { doorLeafWidth, height, doorType, gridType, doorConfig, sidePanel, handle } = get();
|
||||
const priceBreakdown = calculatePrice(doorLeafWidth, height, doorType, gridType, doorConfig, sidePanel, handle);
|
||||
set({ priceBreakdown });
|
||||
};
|
||||
|
||||
export const useConfiguratorStore = create<ConfiguratorState>((set, get) => ({
|
||||
// Initial state
|
||||
doorType: 'taats',
|
||||
@@ -83,27 +94,39 @@ export const useConfiguratorStore = create<ConfiguratorState>((set, get) => ({
|
||||
minWidth: 860,
|
||||
maxWidth: 1360,
|
||||
|
||||
// Initial price (computed with defaults: taats, 3-vlak, enkele, geen, beugelgreep, 1000x2400)
|
||||
priceBreakdown: calculatePrice(1000, 2400, 'taats', '3-vlak', 'enkele', 'geen', 'beugelgreep'),
|
||||
|
||||
// Actions with automatic recalculation
|
||||
setDoorType: (doorType) => {
|
||||
set({ doorType });
|
||||
recalculate(get, set);
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setDoorConfig: (doorConfig) => {
|
||||
set({ doorConfig });
|
||||
recalculate(get, set);
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setSidePanel: (sidePanel) => {
|
||||
set({ sidePanel });
|
||||
recalculate(get, set);
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setGridType: (gridType) => set({ gridType }),
|
||||
setGridType: (gridType) => {
|
||||
set({ gridType });
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setFinish: (finish) => set({ finish }),
|
||||
|
||||
setHandle: (handle) => set({ handle }),
|
||||
setHandle: (handle) => {
|
||||
set({ handle });
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setGlassPattern: (glassPattern) => set({ glassPattern }),
|
||||
|
||||
@@ -112,16 +135,16 @@ export const useConfiguratorStore = create<ConfiguratorState>((set, get) => ({
|
||||
const minWidth = calculateHoleMinWidth(doorConfig, sidePanel);
|
||||
const maxWidth = calculateHoleMaxWidth(doorConfig, sidePanel);
|
||||
|
||||
// Clamp width to valid range
|
||||
const clampedWidth = Math.max(minWidth, Math.min(maxWidth, width));
|
||||
set({ width: clampedWidth });
|
||||
recalculate(get, set);
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setHeight: (height) => {
|
||||
// Clamp height to valid range
|
||||
const clampedHeight = Math.max(1800, Math.min(3000, height));
|
||||
set({ height: clampedHeight });
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setDimensions: (width, height) => {
|
||||
|
||||
Reference in New Issue
Block a user