Files
web-cad/frontend/src/tools/drawing/SeatingTemplateTool.ts
T
Agent Zero 05ccebad8d Replace frontend with deployed TS version from a08dd73
- Restore TS frontend source (canvas, tools, CRDT, components, services)
- Keep 5 JSX components that TS code depends on (CADCanvas, LayerPanel, BlockLibrary, PluginRegistry, Toolbar)
- Keep JS services (api.js, blockService.js) that components depend on
- Fix vite/plugin-react version mismatch (downgrade to v4 for vite 6)
- Add axios dependency
- Skip tsc in build script (vite/esbuild handles transpilation)
- Fix index.html lang=de, favicon path
- Add vite proxy config for /api and /ws
- Backend unchanged (already from deployed containers)
2026-06-28 02:16:58 +02:00

340 lines
9.9 KiB
TypeScript

import { Tool } from '../Tool';
import { YjsDocument } from '../../crdt/YjsDocument';
type SeatingTemplate = 'bankett' | 'gala' | 'stehempfang' | 'parlament' | 'klasse';
class SeatingTemplateTool extends Tool {
private template: SeatingTemplate = 'bankett';
private tableSpacing: number = 150; // Spacing between tables
private chairSpacing: number = 60; // Spacing between chairs
constructor(yjsDoc: YjsDocument, template: SeatingTemplate = 'bankett') {
super(yjsDoc);
this.name = 'SeatingTemplateTool';
this.template = template;
}
onMouseDown(event: MouseEvent): void {
// This tool creates templates at the click position
const x = event.clientX;
const y = event.clientY;
switch (this.template) {
case 'bankett':
this.createBankettTemplate(x, y);
break;
case 'gala':
this.createGalaTemplate(x, y);
break;
case 'stehempfang':
this.createStehempfangTemplate(x, y);
break;
case 'parlament':
this.createParlamentTemplate(x, y);
break;
case 'klasse':
this.createKlasseTemplate(x, y);
break;
}
}
onMouseMove(event: MouseEvent): void {
// Preview template at cursor position
}
onMouseUp(event: MouseEvent): void {
// Handle mouse up if needed
}
onKeyUp(event: KeyboardEvent): void {
// Handle key up events
if (event.key === 'Escape') {
this.reset();
}
}
reset(): void {
// Reset any state if needed
}
// Create Bankett template (long tables with chairs on both sides)
private createBankettTemplate(x: number, y: number): void {
const tableWidth = 240;
const tableHeight = 100;
const chairWidth = 45;
const chairHeight = 45;
const tablesCount = 3;
for (let i = 0; i < tablesCount; i++) {
const tableX = x + i * (tableWidth + this.tableSpacing);
const tableY = y;
// Create table
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_table_' + i,
type: 'rectangular_table',
layerId: 'default',
x: tableX,
y: tableY,
width: tableWidth,
height: tableHeight,
properties: {}
});
// Create chairs on both sides
const chairsPerSide = 4;
for (let j = 0; j < chairsPerSide; j++) {
const positionRatio = (j + 1) / (chairsPerSide + 1);
// Top side chairs
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_chair_top_' + i + '_' + j,
type: 'chair',
layerId: 'default',
x: tableX + positionRatio * tableWidth - chairWidth / 2,
y: tableY - this.chairSpacing - chairHeight,
width: chairWidth,
height: chairHeight,
properties: {}
});
// Bottom side chairs
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_chair_bottom_' + i + '_' + j,
type: 'chair',
layerId: 'default',
x: tableX + positionRatio * tableWidth - chairWidth / 2,
y: tableY + tableHeight + this.chairSpacing,
width: chairWidth,
height: chairHeight,
properties: {}
});
}
}
}
// Create Gala template (round tables with chairs around)
private createGalaTemplate(x: number, y: number): void {
const tableRadius = 50;
const tablesPerRow = 3;
const tablesRows = 2;
for (let i = 0; i < tablesRows; i++) {
for (let j = 0; j < tablesPerRow; j++) {
const tableX = x + j * (tableRadius * 2 + this.tableSpacing);
const tableY = y + i * (tableRadius * 2 + this.tableSpacing);
// Create round table
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_table_' + i + '_' + j,
type: 'round_table',
layerId: 'default',
x: tableX - tableRadius,
y: tableY - tableRadius,
width: tableRadius * 2,
height: tableRadius * 2,
properties: {
radius: tableRadius,
centerX: tableX,
centerY: tableY
}
});
// Create chairs around table
const chairsAround = 8;
for (let k = 0; k < chairsAround; k++) {
const angle = (2 * Math.PI * k) / chairsAround;
const chairX = tableX + (tableRadius + this.chairSpacing) * Math.cos(angle) - 22.5;
const chairY = tableY + (tableRadius + this.chairSpacing) * Math.sin(angle) - 22.5;
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_chair_' + i + '_' + j + '_' + k,
type: 'chair',
layerId: 'default',
x: chairX,
y: chairY,
width: 45,
height: 45,
properties: {}
});
}
}
}
}
// Create Stehempfang template (no chairs, just tables for drinks/food)
private createStehempfangTemplate(x: number, y: number): void {
const tableWidth = 120;
const tableHeight = 60;
const tablesPerRow = 4;
const tablesRows = 2;
for (let i = 0; i < tablesRows; i++) {
for (let j = 0; j < tablesPerRow; j++) {
const tableX = x + j * (tableWidth + this.tableSpacing);
const tableY = y + i * (tableHeight + this.tableSpacing);
// Create table
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_table_' + i + '_' + j,
type: 'rectangular_table',
layerId: 'default',
x: tableX,
y: tableY,
width: tableWidth,
height: tableHeight,
properties: {}
});
}
}
}
// Create Parlament template (U-shape with chairs)
private createParlamentTemplate(x: number, y: number): void {
const tableWidth = 200;
const tableHeight = 60;
const chairWidth = 45;
const chairHeight = 45;
// Create main table (president's table)
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_main_table',
type: 'rectangular_table',
layerId: 'default',
x: x + tableWidth / 2,
y: y,
width: tableWidth,
height: tableHeight,
properties: {}
});
// Create side tables (delegates' tables)
const sideTablesCount = 4;
for (let i = 0; i < sideTablesCount; i++) {
// Left side table
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_left_table_' + i,
type: 'rectangular_table',
layerId: 'default',
x: x,
y: y + (i + 1) * (tableHeight + this.tableSpacing),
width: tableWidth / 2,
height: tableHeight,
properties: {}
});
// Right side table
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_right_table_' + i,
type: 'rectangular_table',
layerId: 'default',
x: x + tableWidth + tableWidth / 2,
y: y + (i + 1) * (tableHeight + this.tableSpacing),
width: tableWidth / 2,
height: tableHeight,
properties: {}
});
// Create chairs for side tables
// Left side chairs
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_left_chair_' + i,
type: 'chair',
layerId: 'default',
x: x - this.chairSpacing - chairWidth,
y: y + (i + 1) * (tableHeight + this.tableSpacing) + tableHeight / 2 - chairHeight / 2,
width: chairWidth,
height: chairHeight,
properties: {}
});
// Right side chairs
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_right_chair_' + i,
type: 'chair',
layerId: 'default',
x: x + tableWidth + tableWidth / 2 + tableWidth / 2 + this.chairSpacing,
y: y + (i + 1) * (tableHeight + this.tableSpacing) + tableHeight / 2 - chairHeight / 2,
width: chairWidth,
height: chairHeight,
properties: {}
});
}
}
// Create Klasse template (U-shape classroom layout open at bottom)
private createKlasseTemplate(x: number, y: number): void {
const tableWidth = 120;
const tableHeight = 60;
const chairWidth = 45;
const chairHeight = 45;
// Create teacher's table
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_teacher_table',
type: 'rectangular_table',
layerId: 'default',
x: x + tableWidth,
y: y,
width: tableWidth,
height: tableHeight,
properties: {}
});
// Create student tables in U-shape (open at bottom)
const rows = 4;
const cols = 5;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
// Create U-shape that is open at the bottom
// Skip inner tables but keep the bottom row
if (i > 0 && i < rows - 1 && j > 0 && j < cols - 1) continue;
const tableX = x + j * (tableWidth + this.tableSpacing);
const tableY = y + (i + 1) * (tableHeight + this.tableSpacing);
// Create table
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_student_table_' + i + '_' + j,
type: 'rectangular_table',
layerId: 'default',
x: tableX,
y: tableY,
width: tableWidth,
height: tableHeight,
properties: {}
});
// Create chair behind each table
this.yjsDoc.createElement({
id: crypto.randomUUID() + '_student_chair_' + i + '_' + j,
type: 'chair',
layerId: 'default',
x: tableX + tableWidth / 2 - chairWidth / 2,
y: tableY + tableHeight + this.chairSpacing,
width: chairWidth,
height: chairHeight,
properties: {}
});
}
}
}
// Set template
setTemplate(template: SeatingTemplate): void {
this.template = template;
}
// Set table spacing
setTableSpacing(spacing: number): void {
this.tableSpacing = spacing;
}
// Set chair spacing
setChairSpacing(spacing: number): void {
this.chairSpacing = spacing;
}
}
export { SeatingTemplateTool };