Files
Cable-consolidation/src/taskpane/components/App.tsx

167 lines
5.6 KiB
TypeScript

import * as React from "react";
import { useState, useEffect } from "react";
import { makeStyles } from "@fluentui/react-components";
import { SheetInfo, SheetMappingStatus, ConsolidateSettings } from "../models";
import SheetSelector from "./SheetSelector";
import ColumnMapper from "./ColumnMapper";
import StatusNotifier from "./StatusNotifier";
import { getAvailableSheets, detectHeadersAndColumns, detectHeadersForSingleSheetRow, consolidateData } from "../excelLogic";
interface AppProps {
title: string;
}
declare const DEV_MODE: boolean;
const useStyles = makeStyles({
root: {
minHeight: "100vh",
display: "flex",
flexDirection: "column",
},
});
const App: React.FC<AppProps> = () => {
const styles = useStyles();
type WizardStep = "select_sheets" | "map_columns" | "done";
const [step, setStep] = useState<WizardStep>("select_sheets");
const [sheets, setSheets] = useState<SheetInfo[]>([]);
const [selectedSheetIds, setSelectedSheetIds] = useState<string[]>([]);
const [sheetMappings, setSheetMappings] = useState<SheetMappingStatus[]>([]);
const [status, setStatus] = useState<"idle" | "success" | "warning" | "error">("idle");
const [statusMessage, setStatusMessage] = useState("");
const [isConsolidating, setIsConsolidating] = useState(false);
const [settings, setSettings] = useState<ConsolidateSettings>({
colorNew: "#d4edda", // light green
colorChanged: "#fff3cd", // light yellow/orange
colorDeleted: "#f8d7da", // light red
});
useEffect(() => {
// Load internal sheets on mount
getAvailableSheets().then(setSheets).catch(err => {
setStatus("error");
setStatusMessage("Fehler beim Laden der Arbeitsblätter: " + String(err));
});
}, []);
const handleExternalSheetsLoaded = (newExternalSheets: SheetInfo[]) => {
setSheets(prev => [...prev, ...newExternalSheets]);
};
const handleNextToMapping = async () => {
const selectedSheets = sheets.filter(s => selectedSheetIds.includes(s.id));
if (selectedSheets.length === 0) return;
try {
const mappings = await detectHeadersAndColumns(selectedSheets);
setSheetMappings(mappings);
setStep("map_columns");
setStatus("idle");
setStatusMessage("");
} catch (err) {
setStatus("error");
setStatusMessage("Fehler beim Analysieren der Blätter: " + String(err));
}
};
const handleHeaderRowChange = async (sheetName: string, newRowIndex: number) => {
try {
// Wir müssen das richtige SheetInfo Objekt finden (für isExternal check)
const sheetInfo = sheets.find(s => s.name === sheetName);
if (!sheetInfo) return;
// Re-detect columns for exactly this row
const newMapping = await detectHeadersForSingleSheetRow(sheetInfo, newRowIndex);
setSheetMappings(prev => prev.map(m => m.sheetName === sheetName ? newMapping : m));
} catch (err) {
setStatus("error");
setStatusMessage("Fehler beim Neuladen der Zeile " + newRowIndex + " für Blatt " + sheetName);
}
};
const handleMappingChange = (sheetName: string, targetCol: string, sourceColIndex: number) => {
setSheetMappings(prev => prev.map(sheet => {
if (sheet.sheetName !== sheetName) return sheet;
const newMappings = sheet.mappings.map(m =>
m.targetColumn === targetCol ? { ...m, sourceColumnIndex: sourceColIndex } : m
);
return { ...sheet, mappings: newMappings };
}));
};
const handleConsolidate = async () => {
setIsConsolidating(true);
setStatus("idle");
try {
const rowsCount = await consolidateData(sheetMappings, settings);
setStatus("success");
setStatusMessage(`Erfolgreich! Es wurden ${rowsCount} Zeilen aus ${sheetMappings.length} Blättern zusammengefasst.`);
setStep("done");
} catch (err: any) {
setStatus("error");
setStatusMessage(err.message || "Fehler bei der Konsolidierung: " + String(err));
} finally {
setIsConsolidating(false);
}
};
return (
<div className={styles.root}>
{typeof DEV_MODE !== "undefined" && DEV_MODE && (
<div style={{ backgroundColor: "#ffc107", color: "#000", textAlign: "center", padding: "4px", fontWeight: "bold", fontSize: "12px" }}>
DEV ENVIRONMENT
</div>
)}
<StatusNotifier status={status} message={statusMessage} />
{step === "select_sheets" && (
<SheetSelector
sheets={sheets}
selectedSheetIds={selectedSheetIds}
onSelectionChange={setSelectedSheetIds}
onNext={handleNextToMapping}
onExternalSheetsLoaded={handleExternalSheetsLoaded}
/>
)}
{step === "map_columns" && (
<ColumnMapper
sheetMappings={sheetMappings}
settings={settings}
onSettingsChange={setSettings}
onHeaderRowChange={handleHeaderRowChange}
onMappingChange={handleMappingChange}
onBack={() => setStep("select_sheets")}
onConsolidate={handleConsolidate}
isConsolidating={isConsolidating}
/>
)}
{step === "done" && (
<div style={{ padding: "10px", textAlign: "center", marginTop: "40px" }}>
<h2>Fertig!</h2>
<p>Die Daten wurden in die 'Gesamtliste' geschrieben.</p>
<button
style={{ padding: "8px 16px", marginTop: "10px", cursor: "pointer" }}
onClick={() => {
setStep("select_sheets");
setSelectedSheetIds([]);
setStatus("idle");
}}
>
Neuen Durchlauf starten
</button>
</div>
)}
</div>
);
};
export default App;