Files
vda-to-edifact-converter/index.html

798 lines
45 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ERP EDI Bridge | VDA ↔ EDIFACT</title>
<link rel="stylesheet" href="styles.css">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&family=Fira+Code&display=swap"
rel="stylesheet">
<!-- Icons (External) - Error Handled -->
<script src="https://unpkg.com/lucide@latest"></script>
<script>
window.onerror = function (msg, url, line) {
console.error('Global Error: ' + msg + '\nline: ' + line);
return false;
};
</script>
</head>
<body>
<div class="dashboard">
<header>
<h1>ERP EDI Bridge</h1>
<p class="subtitle">Konvertieren Sie VDA 4913, 4905 und EDIFACT Nachrichten</p>
</header>
<!-- ═══ Page Navigation ═══ -->
<nav class="page-nav">
<button class="page-nav-btn active" data-page="converter" onclick="app.showPage('converter')">
<i data-lucide="repeat"></i>
Converter
</button>
<button class="page-nav-btn" data-page="viewer" onclick="app.showPage('viewer')">
<i data-lucide="file-text"></i>
EDI Viewer
</button>
<button class="page-nav-btn" data-page="editor" onclick="app.showPage('editor')">
<i data-lucide="edit-3"></i>
Editor
</button>
<button class="page-nav-btn" data-page="history" onclick="app.showPage('history')">
<i data-lucide="database"></i>
Historie
</button>
<button class="page-nav-btn" data-page="settings" onclick="app.showPage('settings')">
<i data-lucide="settings"></i>
Settings
</button>
</nav>
<!-- Config Upload (Global) -->
<div class="config-bar" style="max-width: 1200px; margin: 0 auto 20px auto;">
<div class="config-status" id="configStatus">
<i data-lucide="settings-2"></i>
<span>Keine Konfiguration geladen</span>
</div>
<button class="btn-secondary" onclick="document.getElementById('configInput').click()">
<i data-lucide="upload"></i>
Konfig laden
</button>
<button class="btn-secondary" id="btnSaveConfig" onclick="app.saveConfig()" style="display:none">
<i data-lucide="save"></i>
Konfig speichern
</button>
<input type="file" id="configInput" accept=".txt,.ini,.cfg" class="hidden">
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: CONVERTER -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageConverter">
<!-- Mode Toggle 4 modes -->
<div class="mode-toggle">
<button id="btnOutboundBosch" class="mode-btn active" onclick="app.setMode('outbound-bosch')">
<i data-lucide="arrow-up-right"></i>
VDA 4913 → Bosch DESADV
</button>
<button id="btnOutboundZf" class="mode-btn" onclick="app.setMode('outbound-zf')">
<i data-lucide="arrow-up-right"></i>
VDA 4913 → ZF DESADV
</button>
<button id="btnOutboundIfm" class="mode-btn" onclick="app.setMode('outbound-ifm')">
<i data-lucide="arrow-up-right"></i>
VDA 4913 → IFM DELVRY03
</button>
<button id="btnInboundBosch" class="mode-btn" onclick="app.setMode('inbound-bosch')">
<i data-lucide="arrow-down-left"></i>
DELFOR → VDA 4905
</button>
<button id="btnInboundIfm" class="mode-btn" onclick="app.setMode('inbound-ifm')">
<i data-lucide="arrow-down-left"></i>
IFM DELFOR → VDA 4905
</button>
<button id="btnInboundInvrpt" class="mode-btn" onclick="app.setMode('inbound-invrpt')">
<i data-lucide="arrow-down-left"></i>
INVRPT → VDA 4913
</button>
<button id="btnValidateEdifact" class="mode-btn" onclick="app.setMode('validate-edifact')">
<i data-lucide="check-circle"></i>
EDIFACT Validieren
</button>
</div>
<!-- Drop Zone -->
<div id="dropZone" class="drop-zone">
<i data-lucide="upload-cloud"></i>
<h3>Datei hier ablegen oder klicken</h3>
<p id="dropText">VDA 4913 Datei auswählen für Konvertierung</p>
<input type="file" id="fileInput" class="hidden">
</div>
<!-- Enrichment Section (shown after VDA upload in outbound-bosch mode) -->
<div id="enrichmentSection" class="enrichment-section">
<!-- NAD Segment Editor -->
<div class="preview-header" style="margin-bottom: 20px;">
<h2>Partneradressen (NAD Segmente)</h2>
<span class="badge badge-edi" id="nadSourceBadge">Manuell</span>
</div>
<div class="nad-grid">
<!-- Buyer (BY) -->
<div class="nad-card">
<div class="nad-card-header"><span class="nad-qualifier">BY</span><span>Käufer (Buyer)</span>
</div>
<label>ID <input type="text" id="nad-by-id" class="nad-input" value="5060"></label>
<label>Qualifier <input type="text" id="nad-by-qual" class="nad-input" value="92"></label>
<label>Firma <input type="text" id="nad-by-name" class="nad-input wide"
value="Robert Bosch spol. s.r.o."></label>
<label>Firma 2 <input type="text" id="nad-by-name2" class="nad-input wide" value=""></label>
<label>Straße <input type="text" id="nad-by-street" class="nad-input wide"
value="Roberta Bosche 2678"></label>
<label>Stadt <input type="text" id="nad-by-city" class="nad-input"
value="Ceske Budejovicen"></label>
<label>PLZ <input type="text" id="nad-by-zip" class="nad-input" value="37004"></label>
<label>Land <input type="text" id="nad-by-country" class="nad-input" value="CZ"
maxlength="2"></label>
</div>
<!-- Seller (SE) -->
<div class="nad-card">
<div class="nad-card-header"><span class="nad-qualifier">SE</span><span>Lieferant
(Seller)</span></div>
<label>ID <input type="text" id="nad-se-id" class="nad-input" value="0000062671"></label>
<label>Qualifier <input type="text" id="nad-se-qual" class="nad-input" value="92"></label>
<label>Firma <input type="text" id="nad-se-name" class="nad-input wide"
value="Roechling Precision Components"></label>
<label>Firma 2 <input type="text" id="nad-se-name2" class="nad-input wide" value=""></label>
<label>Straße <input type="text" id="nad-se-street" class="nad-input wide"
value="Winter-Ring 3"></label>
<label>Stadt <input type="text" id="nad-se-city" class="nad-input" value="Weidenberg"></label>
<label>PLZ <input type="text" id="nad-se-zip" class="nad-input" value="95466"></label>
<label>Land <input type="text" id="nad-se-country" class="nad-input" value="DE"
maxlength="2"></label>
</div>
<!-- Ship-To (ST) -->
<div class="nad-card">
<div class="nad-card-header"><span class="nad-qualifier">ST</span><span>Warenempfänger
(Ship-To)</span></div>
<label>ID <input type="text" id="nad-st-id" class="nad-input" value="5060"></label>
<label>Qualifier <input type="text" id="nad-st-qual" class="nad-input" value="92"></label>
<label>Firma <input type="text" id="nad-st-name" class="nad-input wide"
value="Robert Bosch spol. s.r.o."></label>
<label>Firma 2 <input type="text" id="nad-st-name2" class="nad-input wide" value=""></label>
<label>Straße <input type="text" id="nad-st-street" class="nad-input wide"
value="Roberta Bosche 2678"></label>
<label>Stadt <input type="text" id="nad-st-city" class="nad-input"
value="Ceske Budejovicen"></label>
<label>PLZ <input type="text" id="nad-st-zip" class="nad-input" value="37004"></label>
<label>Land <input type="text" id="nad-st-country" class="nad-input" value="CZ"
maxlength="2"></label>
</div>
<!-- Ship-From (SF) -->
<div class="nad-card">
<div class="nad-card-header"><span class="nad-qualifier">SF</span><span>Versender
(Ship-From)</span></div>
<label>ID <input type="text" id="nad-sf-id" class="nad-input" value="0000062671"></label>
<label>Qualifier <input type="text" id="nad-sf-qual" class="nad-input" value="92"></label>
<label>Firma <input type="text" id="nad-sf-name" class="nad-input wide"
value="Roechling Precision Components"></label>
<label>Firma 2 <input type="text" id="nad-sf-name2" class="nad-input wide" value=""></label>
<label>Straße <input type="text" id="nad-sf-street" class="nad-input wide"
value="Winter-Ring 3"></label>
<label>Stadt <input type="text" id="nad-sf-city" class="nad-input" value="Weidenberg"></label>
<label>PLZ <input type="text" id="nad-sf-zip" class="nad-input" value="95466"></label>
<label>Land <input type="text" id="nad-sf-country" class="nad-input" value="DE"
maxlength="2"></label>
</div>
</div>
<!-- Material & Weight Enrichment -->
<div class="preview-header" style="margin-top: 40px;">
<h2>Positionen & Gewichte</h2>
<span class="badge badge-vda">VDA 4913</span>
</div>
<p class="subtitle">Artikel- und Packmittelgewichte können hier angepasst werden.</p>
<div class="table-container">
<table id="enrichmentTable">
<thead>
<tr>
<th>Kunden-Mat.</th>
<th>Lieferanten-Mat.</th>
<th>Menge</th>
<th>Einheit</th>
<th>Artikelgewicht (kg/Stk)</th>
<th>Status</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<!-- Packaging Weight & Dimensions Table -->
<div class="preview-header" style="margin-top: 30px;">
<h2>Packmittel (Gewichte & Maße)</h2>
</div>
<p class="subtitle">Alle Felder sind pflicht in DESADV. Fehlende Werte über Konfig-Datei ergänzen.</p>
<div class="table-container">
<table id="packagingTable">
<thead>
<tr>
<th>Packmittel (Kd)</th>
<th>Packmittel (Lief)</th>
<th>Anz.</th>
<th>Gewicht (kg)</th>
<th>Länge (cm)</th>
<th>Breite (cm)</th>
<th>Höhe (cm)</th>
<th>Status</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div style="margin-top: 30px; text-align: right;">
<button class="btn-primary" onclick="app.generateOutput()">
<i data-lucide="zap"></i>
JETZT KONVERTIEREN
</button>
</div>
</div>
<!-- Result Section -->
<div id="resultSection" class="result-section">
<!-- Stats Grid -->
<div id="stats-grid" class="stats-grid"></div>
<div class="preview-header">
<h2 id="resultTitle">Konvertierungsergebnis</h2>
<div class="viewer-actions">
<button class="btn-secondary" onclick="app.viewResult()">
<i data-lucide="eye"></i>
View
</button>
<button class="btn-secondary" onclick="app.editResult()">
<i data-lucide="edit-3"></i>
Edit
</button>
<button class="btn-primary" onclick="app.downloadResult()">
<i data-lucide="download"></i>
Download
</button>
</div>
</div>
<pre id="previewArea"></pre>
</div>
</main>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: SETTINGS -->
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: SETTINGS -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageSettings" style="display:none">
<!-- Settings Layout: Sidebar + Content -->
<div class="settings-layout">
<!-- ── Left Sidebar ── -->
<nav class="settings-sidebar">
<div class="settings-sidebar-header">
<i data-lucide="settings-2"></i>
<span>Einstellungen</span>
</div>
<button class="settings-nav-btn active" data-section="inbound" onclick="app.switchSettingsSection('inbound')">
<i data-lucide="arrow-down-to-line"></i>
<span>Eingehend</span>
</button>
<button class="settings-nav-btn" data-section="outbound" onclick="app.switchSettingsSection('outbound')">
<i data-lucide="arrow-up-from-line"></i>
<span>Ausgehend</span>
</button>
<button class="settings-nav-btn" data-section="werks" onclick="app.switchSettingsSection('werks')">
<i data-lucide="file-symlink"></i>
<span>Werksnummer</span>
</button>
<button class="settings-nav-btn" data-section="mapping" onclick="app.switchSettingsSection('mapping')">
<i data-lucide="git-merge"></i>
<span>Mapping</span>
</button>
<button class="settings-nav-btn" data-section="log" onclick="app.switchSettingsSection('log')">
<i data-lucide="scroll-text"></i>
<span>Log</span>
</button>
</nav>
<!-- ── Right Content Area ── -->
<div class="settings-content">
<!-- ─── SECTION: Eingehend ─────────────────────────── -->
<div class="settings-section" id="settingsSection-inbound">
<div class="settings-section-header">
<div>
<h2>Eingehende Dateien <span class="settings-section-sub">(Folder Watch)</span></h2>
<p class="subtitle">Überwacht einen Netzwerkordner auf neue Dateien, konvertiert sie automatisch und schreibt die Ergebnisse in den Output-Ordner.</p>
</div>
</div>
<!-- Electron notice -->
<div id="electronNotice" class="electron-notice" style="display:none">
<i data-lucide="alert-triangle"></i>
<span>Ordnerüberwachung ist nur in der Electron-App verfügbar. Bitte starten Sie die App mit <code>npm start</code>.</span>
</div>
<!-- Watcher Status Banner -->
<div class="watcher-banner" id="watcherBanner">
<div class="watcher-banner-left">
<span class="watcher-status-dot" id="watcherDot"></span>
<span id="watcherStatusText">Gestoppt</span>
</div>
<div class="watcher-buttons">
<button class="btn-primary btn-start" id="btnStartWatcher" onclick="app.startWatcher()">
<i data-lucide="play"></i> Starten
</button>
<button class="btn-secondary btn-pause" id="btnPauseWatcher" onclick="app.pauseWatcher()" disabled>
<i data-lucide="pause"></i> Pausieren
</button>
<button class="btn-secondary btn-resume" id="btnResumeWatcher" onclick="app.resumeWatcher()" style="display:none">
<i data-lucide="play"></i> Fortsetzen
</button>
<button class="btn-secondary btn-stop" id="btnStopWatcher" onclick="app.stopWatcher()" disabled>
<i data-lucide="square"></i> Stoppen
</button>
</div>
</div>
<!-- Folder Cards: 3-column -->
<div class="settings-grid-3">
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-input"></i>
<span>Input-Ordner</span>
</div>
<div class="folder-input-row">
<input type="text" id="inputDirPath" class="folder-path-input" placeholder="z.B. \\server\edi\input" readonly>
<button class="btn-secondary" id="btnSelectInput" onclick="app.selectInputFolder()">
<i data-lucide="folder-open"></i>
</button>
</div>
</div>
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-output"></i>
<span>Output-Ordner</span>
</div>
<div class="folder-input-row">
<input type="text" id="outputDirPath" class="folder-path-input" placeholder="z.B. \\server\edi\output" readonly>
<button class="btn-secondary" id="btnSelectOutput" onclick="app.selectOutputFolder()">
<i data-lucide="folder-open"></i>
</button>
</div>
</div>
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-output"></i>
<span>Output (INVRPT → VDA 4913)</span>
</div>
<div class="folder-input-row">
<input type="text" id="invrptOutputPath" class="folder-path-input" placeholder="Leer = gleicher Output-Ordner" readonly>
<button class="btn-secondary" id="btnSelectInvrptOutput" onclick="app.selectInvrptOutputFolder()">
<i data-lucide="folder-open"></i>
</button>
</div>
</div>
</div>
<!-- VDA 711 ID-Umschlüsselung -->
<div class="section-panel" style="margin-top: 24px;">
<div class="section-panel-header">
<i data-lucide="user-check"></i>
<div>
<h3>VDA 711 ID-Umschlüsselung</h3>
<p class="subtitle">Extrahierten IDs (Datenempfänger) eine eigene Kundennummer zuweisen.</p>
</div>
</div>
<div class="folder-input-row" style="margin-bottom: 16px; margin-top: 16px;">
<input type="text" id="newIdMapOriginal" class="folder-path-input" placeholder="Alt (z.B. 8810)" style="max-width: 180px;">
<input type="text" id="newIdMapTarget" class="folder-path-input" placeholder="Neu (z.B. 10305)" style="max-width: 180px;">
<button class="btn-primary" onclick="app.addIdMapping711()">
<i data-lucide="plus"></i> Hinzufügen
</button>
</div>
<div class="table-container">
<table id="idMapping711Table">
<thead>
<tr>
<th>Extrahierte ID (Alt)</th>
<th>Eigene ID (Neu)</th>
<th style="width: 100px;">Aktion</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<!-- ─── SECTION: Ausgehend ─────────────────────────── -->
<div class="settings-section" id="settingsSection-outbound" style="display:none">
<div class="settings-section-header">
<div>
<h2>Ausgehende Dateien <span class="settings-section-sub">(Folder Watch)</span></h2>
<p class="subtitle">Überwacht einen Netzwerkordner auf ausgehende Dateien, konvertiert sie automatisch und schreibt die Ergebnisse in den Output-Ordner.</p>
</div>
</div>
<!-- Watcher Status Banner -->
<div class="watcher-banner" id="outboundWatcherBanner">
<div class="watcher-banner-left">
<span class="watcher-status-dot" id="outboundWatcherDot"></span>
<span id="outboundWatcherStatusText">Gestoppt</span>
</div>
<div class="watcher-buttons">
<button class="btn-primary btn-start" id="btnStartOutboundWatcher" onclick="app.startOutboundWatcher()">
<i data-lucide="play"></i> Starten
</button>
<button class="btn-secondary btn-pause" id="btnPauseOutboundWatcher" onclick="app.pauseOutboundWatcher()" disabled>
<i data-lucide="pause"></i> Pausieren
</button>
<button class="btn-secondary btn-resume" id="btnResumeOutboundWatcher" onclick="app.resumeOutboundWatcher()" style="display:none">
<i data-lucide="play"></i> Fortsetzen
</button>
<button class="btn-secondary btn-stop" id="btnStopOutboundWatcher" onclick="app.stopOutboundWatcher()" disabled>
<i data-lucide="square"></i> Stoppen
</button>
</div>
</div>
<!-- Folder Cards: 2-column -->
<div class="settings-grid">
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-input"></i>
<span>Input-Ordner (Ausgehend)</span>
</div>
<div class="folder-input-row">
<input type="text" id="outboundInputPath" class="folder-path-input" placeholder="z.B. \\server\edi\outbound_in" readonly>
<button class="btn-secondary" onclick="app.selectOutboundInput()">
<i data-lucide="folder-open"></i>
</button>
</div>
</div>
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-output"></i>
<span>Output-Ordner (Ausgehend)</span>
</div>
<div class="folder-input-row">
<input type="text" id="outboundOutputPath" class="folder-path-input" placeholder="z.B. \\server\edi\outbound_out" readonly>
<button class="btn-secondary" onclick="app.selectOutboundOutput()">
<i data-lucide="folder-open"></i>
</button>
</div>
</div>
</div>
</div>
<!-- ─── SECTION: Werksnummer ───────────────────────── -->
<div class="settings-section" id="settingsSection-werks" style="display:none">
<div class="settings-section-header">
<div>
<h2>Werksnummer Umbenennung</h2>
<p class="subtitle">Überwacht VDA-Dateien (RA_VDA*) und benennt sie basierend auf der Werksnummer in Satzart 512 um (100 → LEIFERS, 280 → PITESTI).</p>
</div>
</div>
<!-- Watcher Status Banner -->
<div class="watcher-banner" id="werksWatcherBanner">
<div class="watcher-banner-left">
<span class="watcher-status-dot" id="werksWatcherDot"></span>
<span id="werksWatcherStatusText">Gestoppt</span>
</div>
<div class="watcher-buttons">
<button class="btn-primary btn-start" id="btnStartWerksWatcher" onclick="app.startWerksWatcher()">
<i data-lucide="play"></i> Starten
</button>
<button class="btn-secondary btn-pause" id="btnPauseWerksWatcher" onclick="app.pauseWerksWatcher()" disabled>
<i data-lucide="pause"></i> Pausieren
</button>
<button class="btn-secondary btn-resume" id="btnResumeWerksWatcher" onclick="app.resumeWerksWatcher()" style="display:none">
<i data-lucide="play"></i> Fortsetzen
</button>
<button class="btn-secondary btn-stop" id="btnStopWerksWatcher" onclick="app.stopWerksWatcher()" disabled>
<i data-lucide="square"></i> Stoppen
</button>
</div>
</div>
<!-- Folder Cards: 2-column -->
<div class="settings-grid">
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-input"></i>
<span>Input-Ordner (Werksnummer)</span>
</div>
<div class="folder-input-row">
<input type="text" id="werksInputPath" class="folder-path-input" placeholder="Input für Umbenennung" readonly>
<button class="btn-secondary" onclick="app.selectWerksInput()">
<i data-lucide="folder-open"></i>
</button>
</div>
</div>
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-output"></i>
<span>Output-Ordner (Werksnummer)</span>
</div>
<div class="folder-input-row">
<input type="text" id="werksOutputPath" class="folder-path-input" placeholder="Output für Umbenennung" readonly>
<button class="btn-secondary" onclick="app.selectWerksOutput()">
<i data-lucide="folder-open"></i>
</button>
</div>
</div>
</div>
</div>
<!-- ─── SECTION: Mapping ───────────────────────────── -->
<div class="settings-section" id="settingsSection-mapping" style="display:none">
<div class="settings-section-header">
<div>
<h2>Kundennummern-Zuordnung</h2>
<p class="subtitle">Weisen Sie Kundennummern automatisch einer Konvertierung zu.</p>
</div>
</div>
<div class="section-panel">
<div class="folder-input-row" style="margin-bottom: 16px;">
<input type="text" id="newMappingId" class="folder-path-input" placeholder="Kundennummer (z.B. 5060)" style="max-width: 200px;">
<select id="newMappingMode" class="folder-path-input" style="max-width: 260px;">
<option value="outbound-bosch">VDA 4913 → Bosch DESADV</option>
<option value="outbound-zf">VDA 4913 → ZF DESADV</option>
<option value="outbound-ifm">VDA 4913 → IFM DELVRY03</option>
<option value="inbound-bosch">DELFOR → VDA 4905</option>
<option value="inbound-ifm">IFM DELFOR → VDA 4905</option>
<option value="inbound-invrpt">INVRPT → VDA 4913</option>
<option value="validate-edifact">EDIFACT Validieren</option>
</select>
<button class="btn-primary" onclick="app.addMapping()">
<i data-lucide="plus"></i> Hinzufügen
</button>
</div>
<div class="table-container">
<table id="mappingTable">
<thead>
<tr>
<th>Kundennummer</th>
<th>Konvertierungs-Modus</th>
<th style="width: 100px;">Aktion</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<!-- ─── SECTION: Log ───────────────────────────────── -->
<div class="settings-section" id="settingsSection-log" style="display:none">
<div class="settings-section-header">
<div>
<h2>Konvertierungs-Log</h2>
<p class="subtitle">Echtzeit-Protokoll aller automatisierten Konvertierungen.</p>
</div>
<button class="btn-secondary" onclick="app.clearLog()">
<i data-lucide="trash-2"></i> Leeren
</button>
</div>
<div class="log-container" id="logContainer">
<div class="log-empty">Noch keine Aktivitäten.</div>
</div>
</div>
</div><!-- /settings-content -->
</div><!-- /settings-layout -->
</main>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: VIEWER -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageViewer" style="display:none">
<div class="preview-header no-print">
<h2>EDI Dokument Viewer</h2>
<div class="viewer-actions">
<button class="btn-secondary" onclick="app.viewer.reset()" id="btnViewerBack" style="display:none">
<i data-lucide="arrow-left"></i>
Zurück
</button>
<button class="btn-primary" onclick="app.viewer.printDocument()" id="btnViewerPrint"
style="display:none">
<i data-lucide="printer"></i>
Als PDF speichern / Drucken
</button>
</div>
</div>
<div id="viewerDropZone" class="drop-zone no-print">
<i data-lucide="file-search"></i>
<h3>Datei hier ablegen oder klicken zur Anzeige</h3>
<p id="viewerDropText">Unterstützt DELFOR und VDA 4905/4913 Dateien</p>
<input type="file" id="viewerFileInput" class="hidden">
</div>
<!-- This container will hold the rendered HTML document -->
<div id="viewerDocumentRender" class="document-render-area">
<!-- Content injected by JS -->
</div>
</main>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: EDITOR -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageEditor" style="display:none">
<div class="preview-header no-print">
<h2>EDI Dokument Editor</h2>
<div class="viewer-actions">
<button class="btn-secondary" onclick="app.editor.reset()" id="btnEditorBack" style="display:none">
<i data-lucide="arrow-left"></i>
Zurück
</button>
<button class="btn-primary" onclick="app.editor.downloadDocument()" id="btnEditorDownload"
style="display:none">
<i data-lucide="download"></i>
Speichern / Download
</button>
</div>
</div>
<div id="editorDropZone" class="drop-zone no-print">
<i data-lucide="edit"></i>
<h3>EDI Datei hier ablegen oder klicken zur Bearbeitung</h3>
<p id="editorDropText">Unterstützt EDIFACT und VDA Dateien</p>
<input type="file" id="editorFileInput" class="hidden">
</div>
<!-- This container will hold the editable segments -->
<div id="editorDocumentRender" class="editor-render-area" style="display:none;">
<!-- Content injected by JS -->
</div>
</main>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: HISTORY -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageHistory" style="display:none">
<h2 class="settings-title">
<i data-lucide="database"></i>
Konvertierungs-Historie
</h2>
<p class="subtitle" style="margin-bottom: 20px;">Vollständige Nachverfolgung aller durchgeführten
Konvertierungen.</p>
<!-- Stats -->
<div class="stats-grid" id="historyStats">
<div class="stat-card">
<div class="stat-value">-</div>
<div class="stat-label">Gesamt</div>
</div>
<div class="stat-card">
<div class="stat-value">-</div>
<div class="stat-label">Erfolgreich</div>
</div>
<div class="stat-card">
<div class="stat-value">-</div>
<div class="stat-label">Fehlerhaft</div>
</div>
<div class="stat-card">
<div class="stat-value">-</div>
<div class="stat-label">Heute</div>
</div>
</div>
<!-- Filter Bar -->
<div class="history-filter-bar">
<div class="history-filter-buttons">
<button class="btn-secondary history-filter-btn active" data-filter="ALL"
onclick="app.historyManager.setFilter('ALL')">
Alle
</button>
<button class="btn-secondary history-filter-btn" data-filter="ERFOLGREICH"
onclick="app.historyManager.setFilter('ERFOLGREICH')">
✅ Erfolgreich
</button>
<button class="btn-secondary history-filter-btn" data-filter="FEHLERHAFT"
onclick="app.historyManager.setFilter('FEHLERHAFT')">
❌ Fehlerhaft
</button>
</div>
<div class="history-search-row">
<input type="text" id="historySearch" class="folder-path-input"
placeholder="🔍 Suche nach Dateiname, Kunden-ID..."
oninput="app.historyManager.onSearch(this.value)" style="max-width:350px;">
<button class="btn-secondary" onclick="app.historyManager.exportCSV()">
<i data-lucide="download" style="width:14px;height:14px;"></i> CSV Export
</button>
</div>
</div>
<!-- Table -->
<div class="history-table-wrapper">
<table class="history-table">
<thead>
<tr>
<th style="width:50px;">ID</th>
<th style="width:140px;">Zeitstempel</th>
<th>Dateiname</th>
<th style="width:180px;">Modus</th>
<th style="width:90px;">Status</th>
<th style="width:50px;"></th>
</tr>
</thead>
<tbody id="historyTableBody">
<tr>
<td colspan="6"
style="text-align:center; padding:40px; color: var(--text-dim); font-style:italic;">Lade
Daten...</td>
</tr>
</tbody>
</table>
</div>
<!-- Pagination -->
<div class="history-pagination" id="historyPagination"></div>
</main>
<!-- History Detail Modal -->
<div id="historyDetailModal" class="history-detail-modal" style="display:none;">
<div class="history-detail-modal-content">
<div id="historyDetailContent"></div>
</div>
</div>
</div>
<!-- SCRIPTS -->
<script src="js/vda-parser.js"></script>
<script src="js/edifact-logic.js"></script>
<script src="js/config-parser.js"></script>
<script src="js/vda4913-to-desadv.js"></script>
<script src="js/vda4913-to-desadv-zf.js"></script>
<script src="js/vda4913-to-delvry03.js"></script>
<script src="js/delfor-parser.js"></script>
<script src="js/vda4905-generator.js"></script>
<script src="js/ifm_delfor-vda4905.js"></script>
<script src="js/invrpt-to-vda4913.js"></script>
<script src="js/watcher-bridge.js"></script>
<script src="js/outbound-watcher-bridge.js"></script>
<script src="js/werks-watcher-bridge.js"></script>
<script src="js/viewer.js"></script>
<script src="js/editor.js"></script>
<script src="js/history.js"></script>
<script src="js/app.js"></script>
<script>
// Init App safely
try {
window.app = new window.EDIBridge.App();
if (window.lucide) {
try { lucide.createIcons(); } catch (e) { console.warn("Lucide Error", e); }
}
} catch (e) {
console.error("App Fatal Error:", e);
alert("App Fatal Error: " + e.message);
}
</script>
</body>
</html>