feat: Latest production version with interior scene and glass
Includes room interior with floor, walls, glass you can see through, and all uncommitted production changes that were running live. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
88
lib/store.ts
88
lib/store.ts
@@ -12,8 +12,20 @@ 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';
|
||||
export type Finish = 'zwart' | 'brons' | 'grijs';
|
||||
export type GridType =
|
||||
| 'geen'
|
||||
| '2-vlak'
|
||||
| '3-vlak'
|
||||
| '4-vlak'
|
||||
| '6-vlak'
|
||||
| '8-vlak'
|
||||
| 'kruis'
|
||||
| 'ongelijk-3'
|
||||
| 'boerderij'
|
||||
| 'herenhuis';
|
||||
export type Finish = 'zwart' | 'brons' | 'grijs' | 'goud' | 'beige' | 'ral';
|
||||
export type GlassColor = 'helder' | 'grijs' | 'brons' | 'mat-blank' | 'mat-brons' | 'mat-zwart';
|
||||
export type FrameSize = 20 | 30 | 40;
|
||||
export type Handle = 'beugelgreep' | 'hoekgreep' | 'maangreep' | 'ovaalgreep' | 'klink' | 'u-greep' | 'geen';
|
||||
|
||||
interface ConfiguratorState {
|
||||
@@ -25,8 +37,10 @@ interface ConfiguratorState {
|
||||
// Styling
|
||||
gridType: GridType;
|
||||
finish: Finish;
|
||||
glassColor: GlassColor;
|
||||
handle: Handle;
|
||||
glassPattern: GlassPattern;
|
||||
frameSize: FrameSize;
|
||||
|
||||
// Dimensions (in mm)
|
||||
width: number;
|
||||
@@ -42,17 +56,37 @@ interface ConfiguratorState {
|
||||
// Pricing
|
||||
priceBreakdown: PriceBreakdown;
|
||||
|
||||
// Contact info
|
||||
name: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
note: string;
|
||||
|
||||
// Extra options
|
||||
extraOptions: string[];
|
||||
|
||||
// Screenshot
|
||||
screenshotDataUrl: string | null;
|
||||
|
||||
// Actions
|
||||
setDoorType: (type: DoorType) => void;
|
||||
setDoorConfig: (config: DoorConfig) => void;
|
||||
setSidePanel: (panel: SidePanel) => void;
|
||||
setGridType: (type: GridType) => void;
|
||||
setFinish: (finish: Finish) => void;
|
||||
setGlassColor: (color: GlassColor) => void;
|
||||
setHandle: (handle: Handle) => void;
|
||||
setGlassPattern: (pattern: GlassPattern) => void;
|
||||
setFrameSize: (size: FrameSize) => void;
|
||||
setWidth: (width: number) => void;
|
||||
setHeight: (height: number) => void;
|
||||
setDimensions: (width: number, height: number) => void;
|
||||
setName: (name: string) => void;
|
||||
setEmail: (email: string) => void;
|
||||
setPhone: (phone: string) => void;
|
||||
setNote: (note: string) => void;
|
||||
toggleExtraOption: (option: string) => void;
|
||||
setScreenshotDataUrl: (url: string | null) => void;
|
||||
}
|
||||
|
||||
// Helper function for recalculation
|
||||
@@ -70,8 +104,8 @@ 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);
|
||||
const { doorLeafWidth, height, doorType, gridType, doorConfig, sidePanel, handle, finish, frameSize } = get();
|
||||
const priceBreakdown = calculatePrice(doorLeafWidth, height, doorType, gridType, doorConfig, sidePanel, handle, finish, frameSize);
|
||||
set({ priceBreakdown });
|
||||
};
|
||||
|
||||
@@ -82,8 +116,10 @@ export const useConfiguratorStore = create<ConfiguratorState>((set, get) => ({
|
||||
sidePanel: 'geen',
|
||||
gridType: '3-vlak',
|
||||
finish: 'zwart',
|
||||
glassColor: 'helder',
|
||||
handle: 'beugelgreep',
|
||||
glassPattern: 'standard',
|
||||
frameSize: 40,
|
||||
width: 1000,
|
||||
height: 2400,
|
||||
|
||||
@@ -94,8 +130,20 @@ 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'),
|
||||
// Initial price
|
||||
priceBreakdown: calculatePrice(1000, 2400, 'taats', '3-vlak', 'enkele', 'geen', 'beugelgreep', 'zwart', 40),
|
||||
|
||||
// Contact info
|
||||
name: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
note: '',
|
||||
|
||||
// Extra options
|
||||
extraOptions: [],
|
||||
|
||||
// Screenshot
|
||||
screenshotDataUrl: null,
|
||||
|
||||
// Actions with automatic recalculation
|
||||
setDoorType: (doorType) => {
|
||||
@@ -121,7 +169,12 @@ export const useConfiguratorStore = create<ConfiguratorState>((set, get) => ({
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setFinish: (finish) => set({ finish }),
|
||||
setFinish: (finish) => {
|
||||
set({ finish });
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setGlassColor: (glassColor) => set({ glassColor }),
|
||||
|
||||
setHandle: (handle) => {
|
||||
set({ handle });
|
||||
@@ -130,6 +183,11 @@ export const useConfiguratorStore = create<ConfiguratorState>((set, get) => ({
|
||||
|
||||
setGlassPattern: (glassPattern) => set({ glassPattern }),
|
||||
|
||||
setFrameSize: (frameSize) => {
|
||||
set({ frameSize });
|
||||
recalculatePrice(get, set);
|
||||
},
|
||||
|
||||
setWidth: (width) => {
|
||||
const { doorConfig, sidePanel } = get();
|
||||
const minWidth = calculateHoleMinWidth(doorConfig, sidePanel);
|
||||
@@ -151,4 +209,20 @@ export const useConfiguratorStore = create<ConfiguratorState>((set, get) => ({
|
||||
get().setWidth(width);
|
||||
get().setHeight(height);
|
||||
},
|
||||
|
||||
setName: (name) => set({ name }),
|
||||
setEmail: (email) => set({ email }),
|
||||
setPhone: (phone) => set({ phone }),
|
||||
setNote: (note) => set({ note }),
|
||||
|
||||
toggleExtraOption: (option) => {
|
||||
const { extraOptions } = get();
|
||||
if (extraOptions.includes(option)) {
|
||||
set({ extraOptions: extraOptions.filter((o) => o !== option) });
|
||||
} else {
|
||||
set({ extraOptions: [...extraOptions, option] });
|
||||
}
|
||||
},
|
||||
|
||||
setScreenshotDataUrl: (screenshotDataUrl) => set({ screenshotDataUrl }),
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user