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)
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
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 };
|
||||
Reference in New Issue
Block a user