93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
|
|
/**
|
|||
|
|
* Task CAD-9 – Stuecklisten-Dialog fuer Traversen-Systeme.
|
|||
|
|
*
|
|||
|
|
* Zeigt die gruppierte Stueckliste (Traversen + Eck-Traversen)
|
|||
|
|
* als Tabelle mit Summenzeile; CSV-Download als Datei.
|
|||
|
|
*/
|
|||
|
|
import React, { useMemo } from 'react';
|
|||
|
|
import { buildBOM, exportBOMCsv } from '../services/bomService';
|
|||
|
|
|
|||
|
|
interface BOMDialogProps {
|
|||
|
|
elements: import('../types/cad.types').CADElement[];
|
|||
|
|
onClose: () => void;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const BOMDialog: React.FC<BOMDialogProps> = ({ elements, onClose }) => {
|
|||
|
|
const bom = useMemo(() => buildBOM(elements), [elements]);
|
|||
|
|
|
|||
|
|
const handleDownload = () => {
|
|||
|
|
const csv = exportBOMCsv(bom);
|
|||
|
|
const blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8' });
|
|||
|
|
const url = URL.createObjectURL(blob);
|
|||
|
|
const a = document.createElement('a');
|
|||
|
|
a.href = url;
|
|||
|
|
a.download = `stueckliste-traversen-${new Date().toISOString().slice(0, 10)}.csv`;
|
|||
|
|
a.click();
|
|||
|
|
URL.revokeObjectURL(url);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="bom-dialog-overlay" onClick={onClose}>
|
|||
|
|
<div className="bom-dialog" onClick={(e) => e.stopPropagation()}>
|
|||
|
|
<div className="bom-dialog-header">
|
|||
|
|
<h3>Stückliste – Traversen</h3>
|
|||
|
|
<button className="bom-close" onClick={onClose} title="Schließen">✕
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
{bom.rows.length === 0 ? (
|
|||
|
|
<div className="bom-empty">
|
|||
|
|
Keine Traversen oder Eck-Traversen in der Zeichnung gefunden.
|
|||
|
|
<br />
|
|||
|
|
Platziere zuerst Traversen mit dem Traverse- oder Eck-Traverse-Werkzeug.
|
|||
|
|
</div>
|
|||
|
|
) : (
|
|||
|
|
<>
|
|||
|
|
<table className="bom-table">
|
|||
|
|
<thead>
|
|||
|
|
<tr>
|
|||
|
|
<th>Pos</th>
|
|||
|
|
<th>Typ</th>
|
|||
|
|
<th>Länge (cm)</th>
|
|||
|
|
<th>Breite (cm)</th>
|
|||
|
|
<th>Anzahl</th>
|
|||
|
|
<th>Gesamt</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{bom.rows.map((r) => (
|
|||
|
|
<tr key={`${r.pos}-${r.label}`}>
|
|||
|
|
<td>{r.pos}</td>
|
|||
|
|
<td>{r.type}</td>
|
|||
|
|
<td>{r.length}</td>
|
|||
|
|
<td>{r.width}</td>
|
|||
|
|
<td>{r.count}</td>
|
|||
|
|
<td>{(r.totalCm / 100).toFixed(2)} m</td>
|
|||
|
|
</tr>
|
|||
|
|
))}
|
|||
|
|
<tr className="bom-sum-row">
|
|||
|
|
<td colSpan={5}>
|
|||
|
|
<strong>SUMME</strong>
|
|||
|
|
</td>
|
|||
|
|
<td>
|
|||
|
|
<strong>{bom.totalLengthM.toFixed(2)} m</strong>
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
<div className="bom-dialog-actions">
|
|||
|
|
<button className="bom-btn-primary" onClick={handleDownload}>
|
|||
|
|
CSV herunterladen
|
|||
|
|
</button>
|
|||
|
|
<button className="bom-btn-secondary" onClick={onClose}>
|
|||
|
|
Schließen
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default BOMDialog;
|