Initial Project
This commit is contained in:
151
src/taskpane/components/App.tsx
Normal file
151
src/taskpane/components/App.tsx
Normal file
@@ -0,0 +1,151 @@
|
||||
import * as React from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { makeStyles } from "@fluentui/react-components";
|
||||
import { SheetInfo, SheetMappingStatus } 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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}>
|
||||
<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}
|
||||
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;
|
||||
Reference in New Issue
Block a user