af8b9fe00f
Full-featured house/apartment floor plan editor with: - Turborepo monorepo (React/Vite client, Fastify/Prisma server, shared Zod schemas) - 2D room editor with walls, doors, windows, furniture, electrical elements - 3D room preview with Three.js (auto-hide nearest walls, bird's eye default) - Wall projection views with interactive drag (elevation, position) - Apartment floor plan view with room positioning - Copy/paste, alignment tools, measurement tool, annotations - Item-attached annotations with leader lines (visible on projections) - Door open direction (LEFT/RIGHT/INWARD/OUTWARD) with swing arc - Floor type textures (wood, tile, concrete, laminate, herringbone) - Wall color picker for 3D view - Furniture: bed, desk, wardrobe, sofa, table, chair, shelf, nightstand, dresser, bookcase, TV (with stand toggle), AC unit - Furniture elevation support (wall-mounted items) - Auto-save with dirty state tracking, batch save API - Rotation-aware collision detection (SAT/OBB) with 3D elevation check - Rotation-aware hit testing - i18n (English/Russian) with locale-aware number formatting - Dark mode with system preference detection - Undo/redo, keyboard shortcuts, scale bar - PDF/PNG/JSON export and JSON import - Focus trap modal, toast notifications, tooltips - Responsive layout with overlay palettes
119 lines
3.2 KiB
TypeScript
119 lines
3.2 KiB
TypeScript
import type { Point, CreateRoomDto } from '@house-plan-maker/shared';
|
|
|
|
export interface RoomTemplate {
|
|
readonly id: string;
|
|
readonly name: string;
|
|
readonly description: string;
|
|
readonly icon: string;
|
|
readonly defaultWidth: number;
|
|
readonly defaultHeight: number;
|
|
readonly wallHeight: number;
|
|
readonly shape: readonly Point[];
|
|
/** Suggested door positions (positionAlongWall on wall index) */
|
|
readonly suggestedDoors: readonly { readonly wallIndex: number; readonly position: number }[];
|
|
/** Suggested window positions */
|
|
readonly suggestedWindows: readonly { readonly wallIndex: number; readonly position: number }[];
|
|
}
|
|
|
|
function rectangularShape(width: number, height: number): readonly Point[] {
|
|
return [
|
|
{ x: 0, y: 0 },
|
|
{ x: width, y: 0 },
|
|
{ x: width, y: height },
|
|
{ x: 0, y: height },
|
|
];
|
|
}
|
|
|
|
export const ROOM_TEMPLATES: readonly RoomTemplate[] = [
|
|
{
|
|
id: 'bedroom',
|
|
name: 'Bedroom',
|
|
description: 'Standard bedroom (4m x 3.5m) with door and window',
|
|
icon: '\u{1F6CF}',
|
|
defaultWidth: 4,
|
|
defaultHeight: 3.5,
|
|
wallHeight: 2.7,
|
|
shape: rectangularShape(4, 3.5),
|
|
suggestedDoors: [{ wallIndex: 3, position: 1 }],
|
|
suggestedWindows: [{ wallIndex: 1, position: 2 }],
|
|
},
|
|
{
|
|
id: 'kitchen',
|
|
name: 'Kitchen',
|
|
description: 'Kitchen (3.5m x 3m) with door',
|
|
icon: '\u{1F373}',
|
|
defaultWidth: 3.5,
|
|
defaultHeight: 3,
|
|
wallHeight: 2.7,
|
|
shape: rectangularShape(3.5, 3),
|
|
suggestedDoors: [{ wallIndex: 3, position: 1.5 }],
|
|
suggestedWindows: [{ wallIndex: 1, position: 1.5 }],
|
|
},
|
|
{
|
|
id: 'bathroom',
|
|
name: 'Bathroom',
|
|
description: 'Bathroom (2.5m x 2m)',
|
|
icon: '\u{1F6C1}',
|
|
defaultWidth: 2.5,
|
|
defaultHeight: 2,
|
|
wallHeight: 2.7,
|
|
shape: rectangularShape(2.5, 2),
|
|
suggestedDoors: [{ wallIndex: 3, position: 1 }],
|
|
suggestedWindows: [],
|
|
},
|
|
{
|
|
id: 'living-room',
|
|
name: 'Living Room',
|
|
description: 'Spacious living room (5m x 4m) with window',
|
|
icon: '\u{1F6CB}',
|
|
defaultWidth: 5,
|
|
defaultHeight: 4,
|
|
wallHeight: 2.7,
|
|
shape: rectangularShape(5, 4),
|
|
suggestedDoors: [{ wallIndex: 3, position: 1 }],
|
|
suggestedWindows: [{ wallIndex: 1, position: 2 }, { wallIndex: 2, position: 2.5 }],
|
|
},
|
|
{
|
|
id: 'office',
|
|
name: 'Office',
|
|
description: 'Home office (3m x 2.5m)',
|
|
icon: '\u{1F4BB}',
|
|
defaultWidth: 3,
|
|
defaultHeight: 2.5,
|
|
wallHeight: 2.7,
|
|
shape: rectangularShape(3, 2.5),
|
|
suggestedDoors: [{ wallIndex: 3, position: 1.25 }],
|
|
suggestedWindows: [{ wallIndex: 1, position: 1.25 }],
|
|
},
|
|
{
|
|
id: 'empty',
|
|
name: 'Empty Room',
|
|
description: 'Custom empty room (3m x 3m)',
|
|
icon: '\u25A1',
|
|
defaultWidth: 3,
|
|
defaultHeight: 3,
|
|
wallHeight: 2.7,
|
|
shape: rectangularShape(3, 3),
|
|
suggestedDoors: [],
|
|
suggestedWindows: [],
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Convert a room template into a CreateRoomDto.
|
|
*/
|
|
export function templateToCreateRoomDto(
|
|
template: RoomTemplate,
|
|
name?: string,
|
|
order?: number,
|
|
): CreateRoomDto {
|
|
return {
|
|
name: name ?? template.name,
|
|
shape: [...template.shape],
|
|
width: template.defaultWidth,
|
|
height: template.defaultHeight,
|
|
wallHeight: template.wallHeight,
|
|
order: order ?? 0,
|
|
};
|
|
}
|