- Page header gains the headline / subtitle pair and a primary "Neue Schaltung" CTA on the right that jumps back to the wizard. - Filter bar moves into a bordered white card with label-caps labels, compact 32px inputs, JetBrains Mono numeric inputs for ID/phone/date and a "Zurücksetzen" pill on the right. - Data table uses the Stitch shell: sticky surface-container-high header row with label-caps column titles, 40px body rows, zebra striping on the even rows and a hover highlight. The previously separate Eingabe/Schaltungs-Datum columns are merged into a single "Daten" cell (E:/A:), Anbieter renders as a primary pill, and the Bearbeiten/Löschen/Dokumente buttons become icon-only actions. - updateSchaltungenTable() now delegates to a single renderer used by both the initial load and the client-side filter, so the layout stays consistent after applying filters. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2145 lines
102 KiB
HTML
2145 lines
102 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Provisions-Tracker</title>
|
||
|
||
<!-- Tailwind via CDN + Stitch design theme. Preflight is disabled so the
|
||
remaining legacy inline CSS keeps applying to screens we haven't
|
||
migrated yet. -->
|
||
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||
<link href="https://fonts.googleapis.com" rel="preconnect">
|
||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect">
|
||
<link href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;600;700&family=JetBrains+Mono:wght@500&display=swap" rel="stylesheet">
|
||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet">
|
||
<script>
|
||
tailwind.config = {
|
||
corePlugins: { preflight: false },
|
||
theme: {
|
||
extend: {
|
||
colors: {
|
||
"primary": "#004ac6",
|
||
"primary-container": "#2563eb",
|
||
"primary-fixed": "#dbe1ff",
|
||
"primary-fixed-dim": "#b4c5ff",
|
||
"on-primary": "#ffffff",
|
||
"on-primary-container": "#eeefff",
|
||
"secondary": "#4e6073",
|
||
"secondary-container": "#cfe2f9",
|
||
"on-secondary": "#ffffff",
|
||
"tertiary": "#943700",
|
||
"tertiary-container": "#bc4800",
|
||
"on-tertiary": "#ffffff",
|
||
"error": "#ba1a1a",
|
||
"error-container": "#ffdad6",
|
||
"on-error": "#ffffff",
|
||
"on-error-container": "#93000a",
|
||
"background": "#f8f9ff",
|
||
"on-background": "#0b1c30",
|
||
"surface": "#f8f9ff",
|
||
"surface-bright": "#f8f9ff",
|
||
"surface-container-lowest": "#ffffff",
|
||
"surface-container-low": "#eff4ff",
|
||
"surface-container": "#e5eeff",
|
||
"surface-container-high": "#dce9ff",
|
||
"surface-container-highest": "#d3e4fe",
|
||
"surface-variant": "#d3e4fe",
|
||
"surface-dim": "#cbdbf5",
|
||
"on-surface": "#0b1c30",
|
||
"on-surface-variant": "#434655",
|
||
"inverse-surface": "#213145",
|
||
"inverse-on-surface": "#eaf1ff",
|
||
"outline": "#737686",
|
||
"outline-variant": "#c3c6d7"
|
||
},
|
||
spacing: {
|
||
"base": "4px", "xs": "4px", "sm": "8px", "md": "16px",
|
||
"lg": "24px", "xl": "32px", "gutter": "16px", "margin": "24px"
|
||
},
|
||
fontFamily: {
|
||
"body-md": ["Hanken Grotesk", "sans-serif"],
|
||
"body-sm": ["Hanken Grotesk", "sans-serif"],
|
||
"title-sm": ["Hanken Grotesk", "sans-serif"],
|
||
"headline-md": ["Hanken Grotesk", "sans-serif"],
|
||
"display-lg": ["Hanken Grotesk", "sans-serif"],
|
||
"label-caps": ["Hanken Grotesk", "sans-serif"],
|
||
"label-numeric": ["JetBrains Mono", "monospace"]
|
||
},
|
||
fontSize: {
|
||
"body-md": ["14px", { lineHeight: "20px", fontWeight: "400" }],
|
||
"body-sm": ["13px", { lineHeight: "18px", fontWeight: "400" }],
|
||
"title-sm": ["18px", { lineHeight: "24px", fontWeight: "600" }],
|
||
"headline-md": ["24px", { lineHeight: "32px", letterSpacing: "-0.01em", fontWeight: "600" }],
|
||
"display-lg": ["32px", { lineHeight: "40px", letterSpacing: "-0.02em", fontWeight: "700" }],
|
||
"label-caps": ["11px", { lineHeight: "16px", letterSpacing: "0.05em", fontWeight: "700" }],
|
||
"label-numeric": ["13px", { lineHeight: "16px", fontWeight: "500" }]
|
||
},
|
||
borderRadius: {
|
||
"DEFAULT": "0.25rem", "lg": "0.5rem", "xl": "0.75rem", "full": "9999px"
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
<style>
|
||
.material-symbols-outlined {
|
||
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
|
||
}
|
||
/* Tailwind preflight is disabled to keep legacy screens working,
|
||
but the border utilities expect Preflight's defaults. Restore
|
||
just the border slice: reset width to 0 and set a default
|
||
style+colour so Tailwind's `border` / `border-b` etc. work as
|
||
expected, while not turning every browser-default control
|
||
outline into a visible 2px border. Legacy CSS rules that set
|
||
shorthand `border: …` still win via their class specificity. */
|
||
*, ::before, ::after {
|
||
border-width: 0;
|
||
border-style: solid;
|
||
border-color: #c3c6d7;
|
||
}
|
||
</style>
|
||
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
line-height: 1.6;
|
||
color: #333;
|
||
background-color: #f4f4f4;
|
||
}
|
||
|
||
/* Layout primitives now use Tailwind in the markup; the legacy
|
||
.container/.tab-content keep working so non-migrated screens stay
|
||
styled. body padding-top reserves space for the fixed header. */
|
||
body {
|
||
padding-top: 56px;
|
||
}
|
||
.container {
|
||
max-width: 1440px;
|
||
margin: 0 auto;
|
||
padding: 24px;
|
||
}
|
||
.tab-content {
|
||
display: none;
|
||
}
|
||
.tab-content.active {
|
||
display: block;
|
||
}
|
||
|
||
/* Nav-tab states. The active tab gets a 2px underline anchored to
|
||
the bottom edge of the dark header via inset box-shadow. */
|
||
header .nav-tab {
|
||
display: flex;
|
||
align-items: center;
|
||
height: 100%;
|
||
padding: 0 8px;
|
||
background: transparent;
|
||
border: none;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
font-size: 14px;
|
||
line-height: 20px;
|
||
color: #c3c6d7;
|
||
transition: color 0.15s, box-shadow 0.15s;
|
||
}
|
||
header .nav-tab:hover {
|
||
color: #eaf1ff;
|
||
}
|
||
header .nav-tab.active {
|
||
color: #eaf1ff;
|
||
box-shadow: inset 0 -2px 0 0 #b4c5ff;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
label {
|
||
display: block;
|
||
margin-bottom: 5px;
|
||
font-weight: bold;
|
||
color: #2c3e50;
|
||
}
|
||
|
||
input, select, textarea {
|
||
width: 100%;
|
||
padding: 12px;
|
||
border: 2px solid #ddd;
|
||
border-radius: 6px;
|
||
font-size: 16px;
|
||
transition: border-color 0.3s;
|
||
}
|
||
|
||
input:focus, select:focus, textarea:focus {
|
||
outline: none;
|
||
border-color: #3498db;
|
||
}
|
||
|
||
.form-row {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 20px;
|
||
}
|
||
|
||
.form-row-thirds {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr 1fr;
|
||
gap: 20px;
|
||
}
|
||
|
||
button {
|
||
background: #3498db;
|
||
color: white;
|
||
padding: 12px 24px;
|
||
border: none;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font-size: 16px;
|
||
transition: background-color 0.3s;
|
||
}
|
||
|
||
button:hover {
|
||
background: #2980b9;
|
||
}
|
||
|
||
.btn-success {
|
||
background: #27ae60;
|
||
}
|
||
|
||
.btn-success:hover {
|
||
background: #229954;
|
||
}
|
||
|
||
.btn-danger {
|
||
background: #e74c3c;
|
||
}
|
||
|
||
.btn-danger:hover {
|
||
background: #c0392b;
|
||
}
|
||
|
||
.admin-section {
|
||
margin-bottom: 30px;
|
||
padding: 20px;
|
||
background: #f8f9fa;
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.admin-section h3 {
|
||
margin-bottom: 15px;
|
||
color: #2c3e50;
|
||
}
|
||
|
||
/* New Admin Interface Styles: sidebar + content */
|
||
.admin-layout {
|
||
display: grid;
|
||
grid-template-columns: 260px 1fr;
|
||
gap: 20px;
|
||
align-items: start;
|
||
}
|
||
|
||
.admin-sidebar {
|
||
background: white;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||
position: sticky;
|
||
top: 20px;
|
||
}
|
||
|
||
.admin-sidebar h2 {
|
||
margin: 0 0 16px 0;
|
||
color: #2c3e50;
|
||
text-align: left;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.admin-main {
|
||
min-width: 0;
|
||
}
|
||
|
||
.admin-categories {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 6px;
|
||
}
|
||
|
||
.admin-cat-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 10px 14px;
|
||
background: #ffffff;
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
text-align: left;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
color: #2c3e50;
|
||
width: 100%;
|
||
}
|
||
|
||
.admin-cat-btn:hover {
|
||
background: #e3f2fd;
|
||
border-color: #2196f3;
|
||
}
|
||
|
||
.admin-cat-btn.active {
|
||
background: #2196f3;
|
||
color: white;
|
||
border-color: #1976d2;
|
||
}
|
||
|
||
.admin-icon {
|
||
font-size: 18px;
|
||
line-height: 1;
|
||
}
|
||
|
||
@media (max-width: 900px) {
|
||
.admin-layout {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
.admin-sidebar {
|
||
position: static;
|
||
}
|
||
.admin-categories {
|
||
flex-direction: row;
|
||
flex-wrap: wrap;
|
||
}
|
||
.admin-cat-btn {
|
||
width: auto;
|
||
}
|
||
}
|
||
|
||
/* Compact buttons for tables and action cells */
|
||
table button,
|
||
td button,
|
||
.btn-sm {
|
||
padding: 5px 10px !important;
|
||
font-size: 13px !important;
|
||
border-radius: 4px !important;
|
||
}
|
||
|
||
td.actions, .action-cell, table th:last-child, table td:last-child {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
table button + button,
|
||
td button + button,
|
||
.btn-row button + button {
|
||
margin-left: 5px;
|
||
}
|
||
|
||
.admin-category {
|
||
display: none;
|
||
animation: fadeIn 0.3s ease-in;
|
||
}
|
||
|
||
.admin-category.active {
|
||
display: block;
|
||
}
|
||
|
||
.admin-page {
|
||
background: white;
|
||
border-radius: 12px;
|
||
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.admin-header {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 30px;
|
||
text-align: center;
|
||
}
|
||
|
||
.admin-header h3 {
|
||
margin: 0 0 10px 0;
|
||
font-size: 24px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.admin-header p {
|
||
margin: 0;
|
||
opacity: 0.9;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.admin-form-section {
|
||
padding: 30px;
|
||
border-bottom: 1px solid #eee;
|
||
background: #f8f9fa;
|
||
}
|
||
|
||
.admin-form-section h4 {
|
||
margin: 0 0 20px 0;
|
||
color: #495057;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.admin-content-section {
|
||
padding: 30px;
|
||
}
|
||
|
||
.admin-content-section h4 {
|
||
margin: 0 0 20px 0;
|
||
color: #495057;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.form-row {
|
||
display: flex;
|
||
gap: 15px;
|
||
margin-bottom: 15px;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.form-row label {
|
||
min-width: 120px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.form-row input, .form-row select {
|
||
flex: 1;
|
||
min-width: 200px;
|
||
}
|
||
|
||
.form-row small {
|
||
flex-basis: 100%;
|
||
color: #6c757d;
|
||
font-size: 12px;
|
||
margin-top: 5px;
|
||
}
|
||
|
||
/* Text readability improvements */
|
||
.text-muted {
|
||
color: #6c757d !important;
|
||
font-weight: 500;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.list-item {
|
||
color: #2c3e50 !important;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.list-item strong {
|
||
color: #2c3e50 !important;
|
||
font-weight: 700;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.list-item small {
|
||
color: #495057 !important;
|
||
font-weight: 500;
|
||
font-size: 13px;
|
||
}
|
||
|
||
/* Admin text improvements */
|
||
.admin-card-content {
|
||
color: #2c3e50;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.admin-list p {
|
||
color: #495057 !important;
|
||
font-weight: 500;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.admin-list {
|
||
display: grid;
|
||
gap: 10px;
|
||
}
|
||
|
||
.admin-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.admin-table th,
|
||
.admin-table td {
|
||
padding: 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid #dee2e6;
|
||
}
|
||
|
||
.admin-table th {
|
||
background: #f8f9fa;
|
||
font-weight: 600;
|
||
color: #495057;
|
||
}
|
||
|
||
.admin-table tr:hover {
|
||
background: #f8f9fa;
|
||
}
|
||
|
||
.table-container {
|
||
overflow-x: auto;
|
||
border-radius: 6px;
|
||
border: 1px solid #dee2e6;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; transform: translateY(20px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.admin-categories {
|
||
grid-template-columns: 1fr 1fr;
|
||
}
|
||
|
||
.form-row {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
}
|
||
|
||
.form-row label {
|
||
min-width: auto;
|
||
}
|
||
}
|
||
|
||
.add-form {
|
||
display: flex;
|
||
gap: 10px;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.list-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 10px;
|
||
margin-bottom: 5px;
|
||
background: white;
|
||
border-radius: 4px;
|
||
border: 1px solid #ddd;
|
||
}
|
||
|
||
.table-container {
|
||
overflow-x: auto;
|
||
}
|
||
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
th, td {
|
||
text-align: left;
|
||
padding: 12px;
|
||
border-bottom: 1px solid #ddd;
|
||
}
|
||
|
||
th {
|
||
background: #34495e;
|
||
color: white;
|
||
}
|
||
|
||
tr:hover {
|
||
background: #f5f5f5;
|
||
}
|
||
|
||
.file-upload-area {
|
||
border: 2px dashed #bdc3c7;
|
||
border-radius: 6px;
|
||
padding: 40px;
|
||
text-align: center;
|
||
background: #f8f9fa;
|
||
transition: border-color 0.3s;
|
||
}
|
||
|
||
.file-upload-area:hover {
|
||
border-color: #3498db;
|
||
}
|
||
|
||
.file-upload-area.dragover {
|
||
border-color: #3498db;
|
||
background: #e3f2fd;
|
||
}
|
||
|
||
.message {
|
||
padding: 15px;
|
||
margin: 15px 0;
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.message.success {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
border: 1px solid #c3e6cb;
|
||
}
|
||
|
||
.message.error {
|
||
background: #f8d7da;
|
||
color: #721c24;
|
||
border: 1px solid #f5c6cb;
|
||
}
|
||
|
||
.documents-list {
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.document-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 10px;
|
||
margin-bottom: 5px;
|
||
background: #f8f9fa;
|
||
border-radius: 4px;
|
||
border: 1px solid #dee2e6;
|
||
}
|
||
|
||
.required {
|
||
color: #e74c3c;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.form-row, .form-row-thirds {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.nav-tabs {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.add-form {
|
||
flex-direction: column;
|
||
}
|
||
}
|
||
|
||
/* Document Modal Styles */
|
||
.documents-modal {
|
||
display: none;
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(0, 0, 0, 0.6);
|
||
z-index: 2000;
|
||
animation: fadeIn 0.3s ease;
|
||
}
|
||
|
||
.documents-modal.show {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.documents-modal-content {
|
||
background: white;
|
||
border-radius: 12px;
|
||
max-width: 600px;
|
||
width: 90%;
|
||
max-height: 80vh;
|
||
overflow: hidden;
|
||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
||
animation: slideIn 0.3s ease;
|
||
}
|
||
|
||
.documents-modal-header {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 20px;
|
||
text-align: center;
|
||
position: relative;
|
||
}
|
||
|
||
.documents-modal-header h3 {
|
||
margin: 0;
|
||
font-size: 20px;
|
||
}
|
||
|
||
.documents-modal-close {
|
||
position: absolute;
|
||
top: 15px;
|
||
right: 20px;
|
||
background: none;
|
||
border: none;
|
||
color: white;
|
||
font-size: 24px;
|
||
cursor: pointer;
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: background 0.3s ease;
|
||
}
|
||
|
||
.documents-modal-close:hover {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
}
|
||
|
||
.documents-modal-body {
|
||
padding: 20px;
|
||
max-height: 400px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.document-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 15px;
|
||
border: 2px solid #e0e0e0;
|
||
border-radius: 8px;
|
||
margin-bottom: 10px;
|
||
transition: all 0.3s ease;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.document-item:hover {
|
||
border-color: #3498db;
|
||
background: #f8f9fa;
|
||
transform: translateX(5px);
|
||
}
|
||
|
||
.document-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 15px;
|
||
}
|
||
|
||
.document-icon {
|
||
font-size: 24px;
|
||
color: #3498db;
|
||
}
|
||
|
||
.document-details {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.document-name {
|
||
font-weight: bold;
|
||
color: #2c3e50;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.document-meta {
|
||
font-size: 12px;
|
||
color: #7f8c8d;
|
||
}
|
||
|
||
.download-btn {
|
||
background: #27ae60;
|
||
color: white;
|
||
border: none;
|
||
padding: 8px 16px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
transition: background 0.3s ease;
|
||
}
|
||
|
||
.download-btn:hover {
|
||
background: #219a52;
|
||
}
|
||
|
||
.no-documents {
|
||
text-align: center;
|
||
padding: 40px 20px;
|
||
color: #7f8c8d;
|
||
font-style: italic;
|
||
}
|
||
|
||
.no-documents-icon {
|
||
font-size: 48px;
|
||
margin-bottom: 15px;
|
||
color: #bdc3c7;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
|
||
@keyframes slideIn {
|
||
from { transform: translateY(-50px); opacity: 0; }
|
||
to { transform: translateY(0); opacity: 1; }
|
||
}
|
||
|
||
/* PDF Viewer Styles */
|
||
.pdf-viewer-modal {
|
||
display: none;
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(0, 0, 0, 0.8);
|
||
z-index: 3000;
|
||
animation: fadeIn 0.3s ease;
|
||
}
|
||
|
||
.pdf-viewer-modal.show {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.pdf-viewer-content {
|
||
background: white;
|
||
border-radius: 12px;
|
||
width: 90%;
|
||
height: 90%;
|
||
max-width: 1200px;
|
||
max-height: 800px;
|
||
overflow: hidden;
|
||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||
animation: slideIn 0.3s ease;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.pdf-viewer-header {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 15px 20px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.pdf-viewer-title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
margin: 0;
|
||
}
|
||
|
||
.pdf-viewer-close {
|
||
background: none;
|
||
border: none;
|
||
color: white;
|
||
font-size: 24px;
|
||
cursor: pointer;
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: background 0.3s ease;
|
||
}
|
||
|
||
.pdf-viewer-close:hover {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
}
|
||
|
||
.pdf-viewer-body {
|
||
flex: 1;
|
||
overflow: auto;
|
||
padding: 20px;
|
||
background: #f5f5f5;
|
||
}
|
||
|
||
.pdf-canvas-container {
|
||
text-align: center;
|
||
background: white;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.pdf-controls {
|
||
background: white;
|
||
padding: 15px;
|
||
border-top: 1px solid #ddd;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 15px;
|
||
}
|
||
|
||
.pdf-nav-btn {
|
||
background: #3498db;
|
||
color: white;
|
||
border: none;
|
||
padding: 8px 16px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
transition: background 0.3s ease;
|
||
}
|
||
|
||
.pdf-nav-btn:hover {
|
||
background: #2980b9;
|
||
}
|
||
|
||
.pdf-nav-btn:disabled {
|
||
background: #bdc3c7;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
.pdf-page-info {
|
||
font-size: 14px;
|
||
color: #2c3e50;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.pdf-zoom-controls {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
}
|
||
|
||
.pdf-zoom-btn {
|
||
background: #27ae60;
|
||
color: white;
|
||
border: none;
|
||
padding: 6px 12px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.pdf-zoom-btn:hover {
|
||
background: #219a52;
|
||
}
|
||
|
||
.view-btn {
|
||
background: #3498db;
|
||
color: white;
|
||
border: none;
|
||
padding: 6px 12px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 12px;
|
||
margin-left: 8px;
|
||
}
|
||
|
||
.view-btn:hover {
|
||
background: #2980b9;
|
||
}
|
||
|
||
/* Enhanced Tarifoptionen Styling */
|
||
.tarifoption-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 8px 12px;
|
||
margin: 5px 0;
|
||
background: white;
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 6px;
|
||
transition: all 0.2s ease;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.tarifoption-item:hover {
|
||
background: #e3f2fd;
|
||
border-color: #2196f3;
|
||
transform: translateX(2px);
|
||
}
|
||
|
||
.tarifoption-item input[type="checkbox"] {
|
||
width: 18px;
|
||
height: 18px;
|
||
margin: 0;
|
||
cursor: pointer;
|
||
accent-color: #3498db;
|
||
}
|
||
|
||
.tarifoption-label {
|
||
flex: 1;
|
||
font-weight: 500;
|
||
color: #2c3e50;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
}
|
||
|
||
.tarifoption-price {
|
||
font-size: 12px;
|
||
color: #27ae60;
|
||
font-weight: 600;
|
||
background: #e8f5e8;
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.tarifoption-price.negative {
|
||
color: #e74c3c;
|
||
background: #fde8e8;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body class="bg-background min-h-screen text-on-background" style="font-family: 'Hanken Grotesk', sans-serif;">
|
||
|
||
<!-- Stitch-style top nav: dark slate header with brand on the left,
|
||
tab navigation in the middle, user pill on the right. The nav-tab
|
||
class is kept as a JS hook; CSS is now Tailwind. -->
|
||
<header class="bg-inverse-surface border-b border-outline-variant fixed top-0 left-0 right-0 z-50 h-14">
|
||
<div class="flex justify-between items-center w-full px-lg h-full max-w-[1440px] mx-auto">
|
||
<div class="flex items-center gap-sm">
|
||
<span class="material-symbols-outlined text-inverse-on-surface">monitoring</span>
|
||
<span class="text-title-sm font-semibold text-inverse-on-surface">Provisions-Tracker</span>
|
||
</div>
|
||
<nav class="hidden md:flex items-stretch h-full">
|
||
<ul class="flex gap-lg h-full">
|
||
<li class="h-full flex"><button class="nav-tab active" onclick="showTab('schaltung')">Schaltung erfassen</button></li>
|
||
<li class="h-full flex"><button class="nav-tab" onclick="showTab('overview')">Übersicht</button></li>
|
||
<li class="h-full flex"><button class="nav-tab" onclick="showTab('provisionen')">Provisionen</button></li>
|
||
<li class="h-full flex"><button class="nav-tab" onclick="showTab('geloeschte')">Gelöschte Schaltungen</button></li>
|
||
<li class="h-full flex"><button class="nav-tab" onclick="showTab('admin')">Administration</button></li>
|
||
<li class="h-full flex admin-only" style="display:none"><button class="nav-tab" onclick="showTab('users')">Benutzer</button></li>
|
||
</ul>
|
||
</nav>
|
||
<div class="flex items-center gap-md">
|
||
<span id="headerUserName" class="text-body-sm text-inverse-on-surface/90 hidden lg:inline-block"></span>
|
||
<div class="h-6 w-px bg-outline-variant/30"></div>
|
||
<button id="headerLogoutBtn" class="text-body-md text-primary-fixed-dim hover:text-inverse-on-surface transition-colors flex items-center gap-xs">
|
||
<span class="material-symbols-outlined text-[18px]">logout</span>
|
||
Abmelden
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="container">
|
||
|
||
<!-- Schaltung erfassen Tab (2-step wizard) -->
|
||
<div id="schaltung" class="tab-content active">
|
||
|
||
<!-- Step 1: Anbieter wählen -->
|
||
<div id="wizardStep1" class="bg-surface-container-lowest border border-outline-variant rounded-lg p-lg shadow-[0_2px_4px_rgba(0,0,0,0.04)]">
|
||
<div class="mb-lg border-b border-outline-variant pb-md">
|
||
<h1 class="text-headline-md text-on-surface mb-xs">Neue Schaltung</h1>
|
||
<p class="text-body-sm text-on-surface-variant">Schritt 1 von 2: Anbieter wählen</p>
|
||
</div>
|
||
<div id="wizardAnbieterButtons" class="grid grid-cols-2 lg:grid-cols-3 gap-md"></div>
|
||
</div>
|
||
|
||
<!-- Step 2: VO + Tarif + Tarifoptionen + Kundendaten -->
|
||
<div id="wizardStep2" style="display:none;" class="bg-surface-container-lowest border border-outline-variant rounded-lg p-lg shadow-[0_2px_4px_rgba(0,0,0,0.04)]">
|
||
<div class="mb-lg border-b border-outline-variant pb-md flex justify-between items-start gap-md">
|
||
<div>
|
||
<h2 class="text-headline-md text-on-surface mb-xs">Neue Schaltung</h2>
|
||
<p class="text-body-sm text-on-surface-variant">Schritt 2 von 2: Vertragsdetails erfassen<span id="wizardAnbieterLabel" class="text-primary"></span></p>
|
||
</div>
|
||
<button type="button" onclick="wizardBackToStep1()" class="px-md py-sm rounded-lg border border-outline-variant bg-surface text-on-surface text-body-sm hover:bg-surface-container-low transition-colors flex items-center gap-xs">
|
||
<span class="material-symbols-outlined text-[18px]">arrow_back</span>
|
||
Anbieter ändern
|
||
</button>
|
||
</div>
|
||
|
||
<form id="schaltungForm">
|
||
<div class="flex flex-col xl:flex-row gap-lg">
|
||
<!-- Linke Spalte: Aktivierungsdaten -->
|
||
<div class="flex-1 flex flex-col gap-md">
|
||
<h3 class="text-title-sm text-on-surface border-b border-outline-variant pb-xs">Aktivierungsdaten</h3>
|
||
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="wizardVo">VO-Auswahl <span class="text-primary">*</span></label>
|
||
<select id="wizardVo" required onchange="loadTarifeForWizard()"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm text-body-md text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
<option value="">VO wählen...</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="wizardTarif">Tarif <span class="text-primary">*</span></label>
|
||
<select id="wizardTarif" name="tarif_id" required onchange="loadTarifoptionenForWizard()"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm text-body-md text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
<option value="">Erst VO wählen...</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="flex flex-col gap-base" id="tarifoptionenSection" style="display:none;">
|
||
<label class="text-label-caps text-on-surface-variant">Tarifoptionen</label>
|
||
<div id="tarifoptionenList" class="grid grid-cols-1 gap-xs"></div>
|
||
<div id="noTarifoptionen" style="display:none;" class="text-body-sm text-on-surface-variant italic">Keine Tarifoptionen verfügbar</div>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-2 gap-md">
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="eingabeDatum">Erfassung <span class="text-primary">*</span></label>
|
||
<input type="date" id="eingabeDatum" name="eingabe_datum" required
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm font-label-numeric text-label-numeric text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="schaltungsDatum">Vertragsbeginn <span class="text-primary">*</span></label>
|
||
<input type="date" id="schaltungsDatum" name="schaltungs_datum" required
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm font-label-numeric text-label-numeric text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant">Erfasser</label>
|
||
<input type="text" id="wizardErfasser" readonly
|
||
class="w-full bg-surface-container-low border border-outline-variant rounded-lg h-10 px-sm text-body-md text-on-surface-variant outline-none">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Rechte Spalte: Vertragsdaten -->
|
||
<div class="flex-1 flex flex-col gap-md">
|
||
<h3 class="text-title-sm text-on-surface border-b border-outline-variant pb-xs">Vertragsdaten</h3>
|
||
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="schaltungsId">Schaltungs-ID <span class="text-primary">*</span></label>
|
||
<input type="text" id="schaltungsId" name="schaltungs_id" required
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm font-label-numeric text-label-numeric text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="firma">Firma (optional)</label>
|
||
<input type="text" id="firma" name="firma"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm text-body-md text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
|
||
<div class="grid grid-cols-2 gap-md">
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="vorname">Vorname <span class="text-primary">*</span></label>
|
||
<input type="text" id="vorname" name="vorname" required
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm text-body-md text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="nachname">Nachname <span class="text-primary">*</span></label>
|
||
<input type="text" id="nachname" name="nachname" required
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm text-body-md text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="rufnummer">Rufnummer (optional)</label>
|
||
<input type="text" id="rufnummer" name="rufnummer"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm font-label-numeric text-label-numeric text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="hardware">Hardware (optional, 15 Zeichen)</label>
|
||
<input type="text" id="hardware" name="hardware" onchange="toggleHardwarePricing()"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm text-body-md text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
|
||
<div id="hardwarePricingFields" style="display:none;" class="grid grid-cols-2 gap-md">
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="hardwareEk">Hardware-EK</label>
|
||
<input type="number" id="hardwareEk" name="hardware_ek" step="0.01" min="0" placeholder="0.00"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm font-label-numeric text-label-numeric text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant" for="kundenverkaufspreis">Kundenverkaufspreis</label>
|
||
<input type="number" id="kundenverkaufspreis" name="kundenverkaufspreis_netto" step="0.01" min="0" placeholder="0.00"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded-lg h-10 px-sm font-label-numeric text-label-numeric text-on-surface focus:border-primary focus:ring-4 focus:ring-primary/20 outline-none">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex flex-col gap-base">
|
||
<label class="text-label-caps text-on-surface-variant">Dokumente hochladen</label>
|
||
<div class="file-upload-area border border-dashed border-outline-variant rounded-lg p-md flex flex-col items-center justify-center bg-surface-container-lowest hover:bg-surface-container-low transition-colors cursor-pointer" id="fileUploadArea">
|
||
<span class="material-symbols-outlined text-on-surface-variant text-[28px] mb-xs">upload_file</span>
|
||
<p class="text-body-sm text-on-surface-variant">Dateien hier ablegen oder klicken</p>
|
||
<input type="file" id="documentUpload" multiple accept=".pdf,.jpg,.jpeg,.png,.doc,.docx" style="display:none;">
|
||
</div>
|
||
<div id="uploadedFiles" class="flex flex-col gap-xs mt-xs"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<input type="hidden" id="anbieter" name="anbieter_id">
|
||
|
||
<div class="mt-xl pt-md border-t border-outline-variant flex justify-end">
|
||
<button type="submit" class="px-md py-sm rounded-lg bg-primary-container text-on-primary text-title-sm hover:bg-primary transition-colors flex items-center gap-xs shadow-sm">
|
||
<span class="material-symbols-outlined text-[18px]">save</span>
|
||
Schaltung speichern
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Übersicht Tab -->
|
||
<div id="overview" class="tab-content">
|
||
<div class="flex flex-col gap-lg">
|
||
|
||
<!-- Page header -->
|
||
<div class="flex justify-between items-end flex-wrap gap-md">
|
||
<div>
|
||
<h1 class="text-headline-md text-on-background mb-xs">Schaltungs-Übersicht</h1>
|
||
<p class="text-body-sm text-on-surface-variant">Verwaltung und Kontrolle aller erfassten Schaltungen.</p>
|
||
</div>
|
||
<button type="button" onclick="showTab('schaltung')" class="bg-primary-container text-on-primary hover:bg-primary transition-colors rounded-lg px-md py-sm text-body-sm flex items-center gap-sm shadow-sm">
|
||
<span class="material-symbols-outlined text-[18px]">add</span>
|
||
Neue Schaltung
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Filter bar -->
|
||
<div class="bg-surface-container-lowest border border-outline-variant rounded-lg p-md shadow-[0_2px_4px_rgba(0,0,0,0.04)] flex flex-wrap items-end gap-md">
|
||
<div class="flex flex-col gap-xs flex-grow min-w-[150px]">
|
||
<label class="text-label-caps text-on-surface-variant uppercase" for="filterAnbieterOverview">Anbieter</label>
|
||
<select id="filterAnbieterOverview" class="w-full bg-surface-container-lowest border border-outline-variant rounded h-8 px-sm text-body-sm text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary">
|
||
<option value="">Alle Anbieter</option>
|
||
</select>
|
||
</div>
|
||
<div class="flex flex-col gap-xs flex-grow min-w-[150px]">
|
||
<label class="text-label-caps text-on-surface-variant uppercase" for="filterTarifOverview">Tarif</label>
|
||
<select id="filterTarifOverview" class="w-full bg-surface-container-lowest border border-outline-variant rounded h-8 px-sm text-body-sm text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary">
|
||
<option value="">Alle Tarife</option>
|
||
</select>
|
||
</div>
|
||
<div class="flex flex-col gap-xs flex-grow min-w-[150px]">
|
||
<label class="text-label-caps text-on-surface-variant uppercase" for="filterSchaltungsIdOverview">Schaltungs-ID</label>
|
||
<input type="text" id="filterSchaltungsIdOverview" placeholder="ID1, ID2…"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded h-8 px-sm font-label-numeric text-label-numeric text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary">
|
||
</div>
|
||
<div class="flex flex-col gap-xs flex-grow min-w-[150px]">
|
||
<label class="text-label-caps text-on-surface-variant uppercase" for="filterRufnummerOverview">Rufnummer</label>
|
||
<input type="text" id="filterRufnummerOverview" placeholder="Suche…"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded h-8 px-sm font-label-numeric text-label-numeric text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary">
|
||
</div>
|
||
<div class="flex flex-col gap-xs w-[240px]">
|
||
<label class="text-label-caps text-on-surface-variant uppercase">Zeitraum</label>
|
||
<div class="flex items-center gap-sm">
|
||
<input type="date" id="filterDatumVonOverview"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded h-8 px-sm font-label-numeric text-[12px] text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary">
|
||
<span class="text-outline-variant">–</span>
|
||
<input type="date" id="filterDatumBisOverview"
|
||
class="w-full bg-surface-container-lowest border border-outline-variant rounded h-8 px-sm font-label-numeric text-[12px] text-on-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary">
|
||
</div>
|
||
</div>
|
||
<button type="button" onclick="clearFiltersOverview()"
|
||
class="bg-surface-container-high text-on-surface border border-outline-variant hover:bg-surface-variant transition-colors rounded px-md h-8 text-body-sm flex items-center gap-xs ml-auto">
|
||
<span class="material-symbols-outlined text-[16px]">restart_alt</span>
|
||
Zurücksetzen
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Data table -->
|
||
<div class="bg-surface-container-lowest border border-outline-variant rounded-lg shadow-[0_2px_4px_rgba(0,0,0,0.04)] overflow-hidden">
|
||
<div class="overflow-x-auto">
|
||
<table id="schaltungenTable" class="w-full text-left border-collapse">
|
||
<thead class="bg-surface-container-high border-b-2 border-outline-variant">
|
||
<tr>
|
||
<th class="px-md py-sm text-label-caps text-on-surface-variant uppercase text-right w-[80px]">ID</th>
|
||
<th class="px-md py-sm text-label-caps text-on-surface-variant uppercase">Daten</th>
|
||
<th class="px-md py-sm text-label-caps text-on-surface-variant uppercase">Kunde / Firma</th>
|
||
<th class="px-md py-sm text-label-caps text-on-surface-variant uppercase">Rufnummer</th>
|
||
<th class="px-md py-sm text-label-caps text-on-surface-variant uppercase">Anbieter</th>
|
||
<th class="px-md py-sm text-label-caps text-on-surface-variant uppercase">Tarif</th>
|
||
<th class="px-md py-sm text-label-caps text-on-surface-variant uppercase">Hardware</th>
|
||
<th class="px-md py-sm text-label-caps text-on-surface-variant uppercase text-center w-[80px]">Dokumente</th>
|
||
<th class="px-md py-sm text-label-caps text-on-surface-variant uppercase text-center w-[80px]">Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="text-body-sm text-on-surface"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Provisionen Tab -->
|
||
<div id="provisionen" class="tab-content">
|
||
<h2>Provisions-Übersicht</h2>
|
||
|
||
<!-- Filter für Provisionen -->
|
||
<div class="filter-section" style="margin-bottom: 20px; padding: 20px; background: #f8f9fa; border-radius: 8px;">
|
||
<h3 style="margin-bottom: 15px; color: #2c3e50;">Filter</h3>
|
||
<div style="display: grid; grid-template-columns: repeat(6, 1fr) auto; gap: 15px; align-items: end;">
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label for="filterAnbieterProvisionen">Anbieter</label>
|
||
<select id="filterAnbieterProvisionen">
|
||
<option value="">Alle Anbieter</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label for="filterTarifProvisionen">Tarif</label>
|
||
<select id="filterTarifProvisionen">
|
||
<option value="">Alle Tarife</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label for="filterSchaltungsIdProvisionen">Schaltungs-ID</label>
|
||
<input type="text" id="filterSchaltungsIdProvisionen" placeholder="ID1, ID2, ID3... (kommagetrennt)">
|
||
</div>
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label for="filterRufnummerProvisionen">Rufnummer</label>
|
||
<input type="text" id="filterRufnummerProvisionen" placeholder="Rufnummer suchen...">
|
||
</div>
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label for="filterDatumVonProvisionen">Datum von</label>
|
||
<input type="date" id="filterDatumVonProvisionen">
|
||
</div>
|
||
<div class="form-group" style="margin-bottom: 0;">
|
||
<label for="filterDatumBisProvisionen">Datum bis</label>
|
||
<input type="date" id="filterDatumBisProvisionen">
|
||
</div>
|
||
<div>
|
||
<button type="button" onclick="clearFiltersProvisionen()" class="btn-secondary" style="padding: 12px 20px;">Zurücksetzen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-section">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||
<div>
|
||
<h3>Shop-Provision: <span id="totalShopProvision">0,00 €</span></h3>
|
||
<h3>Mitarbeiter-Provision: <span id="totalMitarbeiterProvision">0,00 €</span></h3>
|
||
</div>
|
||
<div>
|
||
<button onclick="exportProvisionenToPdf()" class="btn-success" style="padding: 12px 20px; font-size: 14px;">
|
||
📄 PDF Export
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="table-container">
|
||
<table id="provisionenTable">
|
||
<thead>
|
||
<tr>
|
||
<th rowspan="2">Schaltungs-ID</th>
|
||
<th rowspan="2">Datum</th>
|
||
<th rowspan="2">Kunde</th>
|
||
<th rowspan="2">Anbieter</th>
|
||
<th rowspan="2">Tarif</th>
|
||
<th style="text-align: center; border-bottom: 1px solid #ccc;">Shop-Provision</th>
|
||
<th style="text-align: center; border-bottom: 1px solid #ccc;">Mitarbeiter-Provision</th>
|
||
</tr>
|
||
<tr>
|
||
<th>Betrag</th>
|
||
<th>Betrag</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Gelöschte Schaltungen Tab -->
|
||
<div id="geloeschte" class="tab-content">
|
||
<h2>Gelöschte Schaltungen</h2>
|
||
<div class="table-container">
|
||
<table id="geloeschteSchaltungenTable">
|
||
<thead>
|
||
<tr>
|
||
<th>Schaltungs-ID</th>
|
||
<th>Eingabe-Datum</th>
|
||
<th>Schaltungs-Datum</th>
|
||
<th>Name</th>
|
||
<th>Firma</th>
|
||
<th>Rufnummer</th>
|
||
<th>Anbieter</th>
|
||
<th>Tarif</th>
|
||
<th>Hardware</th>
|
||
<th>Löschgrund</th>
|
||
<th>Gelöscht am</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Administration Tab -->
|
||
<div id="admin" class="tab-content">
|
||
<div class="admin-layout">
|
||
<!-- Sidebar -->
|
||
<aside class="admin-sidebar">
|
||
<h2>Administration</h2>
|
||
<div class="admin-categories">
|
||
<button class="admin-cat-btn active" onclick="showAdminCategory('anbieter')">
|
||
<span class="admin-icon">🏢</span>
|
||
<span>Anbieter</span>
|
||
</button>
|
||
<button class="admin-cat-btn" onclick="showAdminCategory('vos')">
|
||
<span class="admin-icon">🔢</span>
|
||
<span>VOs (Vertriebspartner)</span>
|
||
</button>
|
||
<button class="admin-cat-btn" onclick="showAdminCategory('tarife')">
|
||
<span class="admin-icon">📋</span>
|
||
<span>Tarife</span>
|
||
</button>
|
||
<button class="admin-cat-btn" onclick="showAdminCategory('tarifoptionen')">
|
||
<span class="admin-icon">⚙️</span>
|
||
<span>Tarifoptionen</span>
|
||
</button>
|
||
<button class="admin-cat-btn" onclick="showAdminCategory('mitarbeiter-prozentsaetze')">
|
||
<span class="admin-icon">📊</span>
|
||
<span>Mitarbeiter-Prozentsätze</span>
|
||
</button>
|
||
<button class="admin-cat-btn" onclick="showAdminCategory('mitarbeiter-provisionen')">
|
||
<span class="admin-icon">👤</span>
|
||
<span>Mitarbeiter-Provisionen</span>
|
||
</button>
|
||
<button class="admin-cat-btn" onclick="showAdminCategory('provisionsregeln')">
|
||
<span class="admin-icon">📝</span>
|
||
<span>Provisionsregeln</span>
|
||
</button>
|
||
<button class="admin-cat-btn" onclick="showAdminCategory('global-provisionsregeln')">
|
||
<span class="admin-icon">🌐</span>
|
||
<span>Globale Provisionsregeln</span>
|
||
</button>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- Content -->
|
||
<main class="admin-main">
|
||
|
||
<!-- Anbieter Management -->
|
||
<div id="admin-anbieter" class="admin-category active">
|
||
<div class="admin-page">
|
||
<div class="admin-header">
|
||
<h3>Anbieter verwalten</h3>
|
||
<p>Hier können Sie Telekommunikationsanbieter hinzufügen und verwalten.</p>
|
||
</div>
|
||
|
||
<div class="admin-form-section">
|
||
<h4>Neuen Anbieter hinzufügen</h4>
|
||
<div class="add-form">
|
||
<input type="text" id="newAnbieter" placeholder="Name des Anbieters (z.B. Telekom, Vodafone)">
|
||
<button onclick="addAnbieter()" class="btn-success">Hinzufügen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-content-section">
|
||
<h4>Bestehende Anbieter</h4>
|
||
<div class="table-container">
|
||
<table class="admin-table">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>Anbieter-Name</th>
|
||
<th>Erstellt am</th>
|
||
<th>Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="anbieterList">
|
||
<!-- Content loaded dynamically -->
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- VOs Management -->
|
||
<div id="admin-vos" class="admin-category">
|
||
<div class="admin-page">
|
||
<div class="admin-header">
|
||
<h3>VOs (Vertriebspartner-Nummern) verwalten</h3>
|
||
<p>Pro Anbieter können beliebig viele VOs angelegt werden. Jeder Tarif wird genau einer VO zugeordnet.</p>
|
||
</div>
|
||
|
||
<div class="admin-form-section">
|
||
<h4>Neue VO hinzufügen</h4>
|
||
<div class="add-form">
|
||
<select id="voAnbieter" style="margin-right:8px;">
|
||
<option value="">Anbieter wählen...</option>
|
||
</select>
|
||
<input type="text" id="voNummer" placeholder="VO-Nummer (z.B. 27518900)" style="margin-right:8px;">
|
||
<input type="text" id="voBezeichnung" placeholder="Bezeichnung (z.B. Fachhandel)" style="margin-right:8px;">
|
||
<button onclick="addVo()" class="btn-success">Hinzufügen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-content-section">
|
||
<h4>Bestehende VOs</h4>
|
||
<p style="color:#666; font-size:13px;">Die mit ★ markierte VO wird bei der Schaltungserfassung automatisch vorausgewählt.</p>
|
||
<div class="table-container">
|
||
<table class="admin-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Anbieter</th>
|
||
<th>Nummer</th>
|
||
<th>Bezeichnung</th>
|
||
<th>Aktiv</th>
|
||
<th>Standard</th>
|
||
<th>Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="vosList"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tarife Management -->
|
||
<div id="admin-tarife" class="admin-category">
|
||
<div class="admin-page">
|
||
<div class="admin-header">
|
||
<h3>Tarife verwalten</h3>
|
||
<p>Verwalten Sie Tarife und deren Provisionen für jeden Anbieter.</p>
|
||
</div>
|
||
|
||
<div class="admin-form-section">
|
||
<h4>Neuen Tarif hinzufügen</h4>
|
||
<div class="tarif-form">
|
||
<div class="form-row">
|
||
<select id="tarifAnbieter" onchange="loadVosForTarifForm()">
|
||
<option value="">Anbieter wählen...</option>
|
||
</select>
|
||
<select id="tarifVo">
|
||
<option value="">VO wählen...</option>
|
||
</select>
|
||
<input type="text" id="newTarif" placeholder="Name des Tarifs">
|
||
</div>
|
||
<div class="form-row">
|
||
<label>Provision (€):</label>
|
||
<input type="number" id="tarifProvisionBetrag" placeholder="Betrag in Euro" step="0.01" min="0">
|
||
</div>
|
||
<div class="form-row">
|
||
<label>Beschreibung:</label>
|
||
<input type="text" id="tarifBeschreibung" placeholder="Beschreibung (optional)">
|
||
</div>
|
||
<button onclick="addTarif()" class="btn-success">Tarif hinzufügen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-content-section">
|
||
<h4>Bestehende Tarife</h4>
|
||
<div class="table-container">
|
||
<table class="admin-table">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>Anbieter</th>
|
||
<th>VO</th>
|
||
<th>Tarif-Name</th>
|
||
<th>Provision (€)</th>
|
||
<th>Beschreibung</th>
|
||
<th>Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="tarifeList">
|
||
<!-- Content loaded dynamically -->
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tarifoptionen Management -->
|
||
<div id="admin-tarifoptionen" class="admin-category">
|
||
<div class="admin-page">
|
||
<div class="admin-header">
|
||
<h3>Tarifoptionen verwalten</h3>
|
||
<p>Verwalten Sie Zusatzoptionen und Aktionscodes für Tarife.</p>
|
||
</div>
|
||
|
||
<div class="admin-form-section">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||
<div>
|
||
<h4>Tarifoptionen verwalten</h4>
|
||
<p style="margin: 0; color: #6c757d; font-size: 14px;">Erstellen und verwalten Sie Zusatzoptionen für Tarife</p>
|
||
</div>
|
||
<button onclick="openAddTarifoptionModal()" style="background: #28a745; color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 8px;">
|
||
<span style="font-size: 16px;">+</span>
|
||
Neue Tarifoption
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-content-section">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||
<h4>Bestehende Tarifoptionen</h4>
|
||
<div style="display: flex; gap: 15px; align-items: center;">
|
||
<input type="text" id="tarifoptionSearch" placeholder="Nach Tarif oder Option suchen..." style="padding: 8px 12px; border: 2px solid #e1e5e9; border-radius: 6px; width: 250px; font-size: 14px;" oninput="filterTarifoptionenAdmin()">
|
||
<button onclick="clearTarifoptionSearch()" style="background: #6c757d; color: white; border: none; padding: 8px 12px; border-radius: 6px; cursor: pointer; font-size: 13px;">Löschen</button>
|
||
<div id="tarifoptionSearchCounter" style="font-size: 13px; color: #6c757d; min-width: 120px;"></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-container">
|
||
<table class="admin-table">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>Anbieter</th>
|
||
<th>Tarif</th>
|
||
<th>Option</th>
|
||
<th>Code</th>
|
||
<th>Provision (€)</th>
|
||
<th>Beschreibung</th>
|
||
<th>Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="tarifoptionenAdminList">
|
||
<!-- Content loaded dynamically -->
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Mitarbeiter Prozentsätze Management -->
|
||
<div id="admin-mitarbeiter-prozentsaetze" class="admin-category">
|
||
<div class="admin-page">
|
||
<div class="admin-header">
|
||
<h3>Mitarbeiter-Provisionen</h3>
|
||
<p>Verwalten Sie die Prozentsätze für Mitarbeiter-Provisionen pro Anbieter.</p>
|
||
</div>
|
||
|
||
<div class="admin-form-section">
|
||
<h4>Mitarbeiter-Prozentsatz festlegen</h4>
|
||
<div class="mitarbeiter-form">
|
||
<div class="form-row">
|
||
<select id="mitarbeiterAnbieter">
|
||
<option value="">Anbieter wählen...</option>
|
||
</select>
|
||
<input type="number" id="mitarbeiterProzentsatz" placeholder="Prozentsatz" step="0.01" min="0" max="100">
|
||
<span>%</span>
|
||
</div>
|
||
<div class="form-row">
|
||
<input type="date" id="mitarbeiterGueltigAb" placeholder="Gültig ab">
|
||
<input type="text" id="mitarbeiterBeschreibung" placeholder="Beschreibung (optional)">
|
||
</div>
|
||
<button onclick="addMitarbeiterProzentsatz()" class="btn-success">Prozentsatz festlegen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-content-section">
|
||
<h4>Aktuelle Mitarbeiter-Prozentsätze</h4>
|
||
<div id="mitarbeiterProzentsaetzeList" class="admin-list"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Mitarbeiter Provisionen Management -->
|
||
<div id="admin-mitarbeiter-provisionen" class="admin-category">
|
||
<div class="admin-page">
|
||
<div class="admin-header">
|
||
<h3>Mitarbeiter-Provisionen pro Tarif</h3>
|
||
<p>Legen Sie für jeden Tarif individuell die Mitarbeiter-Provision fest.</p>
|
||
</div>
|
||
|
||
<div class="admin-content-section">
|
||
<h4>Tarife und Mitarbeiter-Provisionen</h4>
|
||
<div id="tarifProvisionsList" class="admin-list"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Provisionsregeln Management -->
|
||
<div id="admin-provisionsregeln" class="admin-category">
|
||
<div class="admin-page">
|
||
<div class="admin-header">
|
||
<h3>Provisionsregeln verwalten</h3>
|
||
<p>Verwalten Sie spezifische Provisionsregeln für Tarife.</p>
|
||
</div>
|
||
|
||
<div class="admin-form-section">
|
||
<h4>Neue Provisionsregel hinzufügen</h4>
|
||
<div class="add-form">
|
||
<select id="provisionTarif">
|
||
<option value="">Tarif wählen...</option>
|
||
</select>
|
||
<input type="number" id="provisionBetrag" placeholder="Provision in Euro" step="0.01" min="0">
|
||
<button onclick="addProvisionRule()" class="btn btn-primary">Regel hinzufügen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-content-section">
|
||
<h4>Bestehende Provisionsregeln</h4>
|
||
<div id="provisionsregelnList" class="admin-list"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Globale Provisionsregeln Management -->
|
||
<div id="admin-global-provisionsregeln" class="admin-category">
|
||
<div class="admin-page">
|
||
<div class="admin-header">
|
||
<h3>Globale Provisionsregeln verwalten</h3>
|
||
<p>Verwalten Sie globale Provisionsregeln für Anbieter.</p>
|
||
</div>
|
||
|
||
<div class="admin-form-section">
|
||
<h4>Neue globale Provisionsregel hinzufügen</h4>
|
||
<div class="add-form">
|
||
<select id="globalProvisionAnbieter">
|
||
<option value="">Anbieter wählen...</option>
|
||
</select>
|
||
<input type="number" id="globalProvisionBetrag" placeholder="Provision in Euro" step="0.01" min="0">
|
||
<button onclick="addGlobalProvisionRule()" class="btn btn-primary">Globale Regel hinzufügen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-content-section">
|
||
<h4>Bestehende globale Provisionsregeln</h4>
|
||
<div id="globalProvisionsregelnList" class="admin-list"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Benutzer-Verwaltung Tab (admin only) -->
|
||
<div id="users" class="tab-content">
|
||
<h2>Benutzer-Verwaltung</h2>
|
||
<div style="margin-bottom: 20px;">
|
||
<button type="button" class="btn-success" onclick="openUserModal()">+ Neuer Benutzer</button>
|
||
</div>
|
||
<table class="data-table" style="width:100%; border-collapse: collapse;">
|
||
<thead>
|
||
<tr>
|
||
<th>Username</th>
|
||
<th>Anzeigename</th>
|
||
<th>Admin</th>
|
||
<th>Erstellt</th>
|
||
<th>Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="usersTableBody"></tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- Modal: Benutzer anlegen / bearbeiten -->
|
||
<div id="userModal" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:1000;">
|
||
<div style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); background:white; border-radius:8px; width:90%; max-width:500px; padding:24px; box-shadow:0 10px 30px rgba(0,0,0,0.2);">
|
||
<h3 id="userModalTitle" style="margin-top:0;">Neuer Benutzer</h3>
|
||
<input type="hidden" id="userModalUuid">
|
||
<div class="form-group" style="margin-bottom:14px;">
|
||
<label for="userModalUsername">Username</label>
|
||
<input type="text" id="userModalUsername" style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px;">
|
||
</div>
|
||
<div class="form-group" style="margin-bottom:14px;">
|
||
<label for="userModalDisplay">Anzeigename</label>
|
||
<input type="text" id="userModalDisplay" style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px;">
|
||
</div>
|
||
<div class="form-group" style="margin-bottom:14px;">
|
||
<label for="userModalPassword">Passwort <span id="userModalPasswordHint" style="color:#666; font-size:12px;">(min. 8 Zeichen)</span></label>
|
||
<input type="password" id="userModalPassword" autocomplete="new-password" style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px;">
|
||
<small id="userModalPasswordEditHint" style="color:#666; display:none;">Leer lassen, um Passwort unverändert zu lassen</small>
|
||
</div>
|
||
<div class="form-group" style="margin-bottom:18px;">
|
||
<label style="display:flex; align-items:center; gap:8px; cursor:pointer;">
|
||
<input type="checkbox" id="userModalIsAdmin"> Administrator
|
||
</label>
|
||
</div>
|
||
<div style="text-align:right;">
|
||
<button type="button" onclick="closeUserModal()" style="margin-right:8px;">Abbrechen</button>
|
||
<button type="button" class="btn-success" onclick="saveUserFromModal()">Speichern</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Modal: VO bearbeiten -->
|
||
<div id="voEditModal" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:1000;">
|
||
<div style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); background:white; border-radius:8px; width:90%; max-width:480px; padding:24px; box-shadow:0 10px 30px rgba(0,0,0,0.2);">
|
||
<h3 style="margin-top:0;">VO bearbeiten</h3>
|
||
<input type="hidden" id="voEditId">
|
||
<div class="form-group" style="margin-bottom:12px;">
|
||
<label>Anbieter</label>
|
||
<input type="text" id="voEditAnbieter" readonly style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f5f5f5;">
|
||
</div>
|
||
<div class="form-group" style="margin-bottom:12px;">
|
||
<label for="voEditNummer">VO-Nummer</label>
|
||
<input type="text" id="voEditNummer" style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px;">
|
||
</div>
|
||
<div class="form-group" style="margin-bottom:12px;">
|
||
<label for="voEditBezeichnung">Bezeichnung</label>
|
||
<input type="text" id="voEditBezeichnung" placeholder="z.B. Fachhandel (leer = keine)" style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px;">
|
||
</div>
|
||
<div class="form-group" style="margin-bottom:18px;">
|
||
<label style="display:flex; align-items:center; gap:8px; cursor:pointer;">
|
||
<input type="checkbox" id="voEditAktiv"> Aktiv
|
||
</label>
|
||
</div>
|
||
<div style="text-align:right;">
|
||
<button type="button" onclick="closeVoEditModal()" style="margin-right:8px;">Abbrechen</button>
|
||
<button type="button" class="btn-success" onclick="saveVoFromModal()">Speichern</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="messages"></div>
|
||
</div>
|
||
|
||
<!-- Edit Tarifoption Modal -->
|
||
<div id="editTarifoptionModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 1000;">
|
||
<div style="position: absolute; top: 5%; left: 50%; transform: translateX(-50%); background: white; border-radius: 12px; width: 90%; max-width: 1200px; height: 90%; box-shadow: 0 20px 40px rgba(0,0,0,0.3); display: flex; flex-direction: column;">
|
||
|
||
<!-- Header -->
|
||
<div style="padding: 25px 35px 15px; border-bottom: 1px solid #eee; flex-shrink: 0;">
|
||
<div style="display: flex; justify-content: between; align-items: center;">
|
||
<h2 style="margin: 0; color: #333; font-size: 24px;">Tarifoption bearbeiten</h2>
|
||
<span style="position: absolute; top: 15px; right: 25px; font-size: 28px; cursor: pointer; color: #999; hover: #333;" onclick="closeModal('editTarifoptionModal')">×</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Content -->
|
||
<div style="flex: 1; overflow-y: auto; padding: 25px 35px;">
|
||
<form id="editTarifoptionForm">
|
||
<input type="hidden" id="editTarifoptionId">
|
||
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px; height: 100%;">
|
||
<!-- Left Column -->
|
||
<div>
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="editTarifoptionAnbieter" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Anbieter</label>
|
||
<select id="editTarifoptionAnbieter" onchange="loadTarifeForEditOptions()" style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px; background: white;">
|
||
<option value="">Anbieter wählen...</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label style="display: flex; align-items: center; gap: 12px; padding: 15px; background: #f8f9fa; border-radius: 8px; cursor: pointer; border: 2px solid transparent; transition: all 0.2s;">
|
||
<input type="checkbox" id="editTarifoptionAnbieterWeit" onchange="toggleEditTarifSelection()" style="width: 18px; height: 18px; cursor: pointer;">
|
||
<span style="font-weight: 500; color: #495057;">Für alle Tarife des Anbieters (Anbieter-weit)</span>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="editTarifoptionName" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Name der Option</label>
|
||
<input type="text" id="editTarifoptionName" required style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px;">
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="editTarifoptionCode" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Code (optional)</label>
|
||
<input type="text" id="editTarifoptionCode" style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px;">
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="editTarifoptionProvisionBetrag" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Zusätzliche Provision (€)</label>
|
||
<input type="number" id="editTarifoptionProvisionBetrag" step="0.01" required style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px;">
|
||
<small style="color: #6c757d; font-size: 12px; margin-top: 5px; display: block;">Wird zur Tarif-Provision hinzugefügt (negativ = Abzug)</small>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="editTarifoptionBeschreibung" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Beschreibung (optional)</label>
|
||
<textarea id="editTarifoptionBeschreibung" rows="3" style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px; resize: vertical;"></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Right Column - Tarif Selection -->
|
||
<div>
|
||
<div id="editTarifSelectionContainer">
|
||
<label style="display: block; font-weight: 600; margin-bottom: 15px; color: #333; font-size: 16px;">Tarife auswählen:</label>
|
||
|
||
<div style="margin-bottom: 15px;">
|
||
<button type="button" onclick="selectAllEditTarifs()" style="background: #28a745; color: white; border: none; padding: 8px 16px; border-radius: 6px; margin-right: 8px; cursor: pointer; font-size: 13px; font-weight: 500;">Alle auswählen</button>
|
||
<button type="button" onclick="deselectAllEditTarifs()" style="background: #dc3545; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: 500;">Alle abwählen</button>
|
||
<input type="text" id="editTarifSearch" placeholder="Tarife filtern..." style="float: right; padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; width: 180px;" oninput="filterEditTarifs()">
|
||
</div>
|
||
|
||
<div id="editTarifCheckboxContainer" style="height: 400px; overflow-y: auto; border: 2px solid #e1e5e9; border-radius: 8px; background: #fefefe;">
|
||
<div style="padding: 40px; text-align: center; color: #6c757d; font-style: italic;">Erst Anbieter wählen...</div>
|
||
</div>
|
||
|
||
<div id="editTarifCounter" style="margin-top: 10px; font-size: 13px; color: #6c757d; text-align: right;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<div style="padding: 20px 35px; border-top: 1px solid #eee; background: #f8f9fa; border-bottom-left-radius: 12px; border-bottom-right-radius: 12px; flex-shrink: 0;">
|
||
<div style="display: flex; justify-content: flex-end; gap: 15px;">
|
||
<button type="button" onclick="closeModal('editTarifoptionModal')" style="background: #6c757d; color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500;">Abbrechen</button>
|
||
<button type="submit" form="editTarifoptionForm" style="background: #007bff; color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500;">Speichern</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Edit Tariff Modal -->
|
||
<div id="editTariffModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000;">
|
||
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 30px; border-radius: 8px; width: 600px; max-width: 90%; max-height: 90vh; overflow-y: auto;">
|
||
<h3>Tarif bearbeiten</h3>
|
||
<form id="editTariffForm">
|
||
<input type="hidden" id="editTariffId">
|
||
<div class="form-group">
|
||
<label>Tarif-Name:</label>
|
||
<input type="text" id="editTariffName" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>VO:</label>
|
||
<select id="editTariffVo">
|
||
<option value="">VO wählen...</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Shop-Provision (€):</label>
|
||
<input type="number" id="editTariffProvisionBetrag" step="0.01" min="0" placeholder="Betrag in Euro">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Tarifoptionen (Anbieter-weit):</label>
|
||
<div id="editTariffOptionenContainer" style="border:1px solid #ddd; border-radius:6px; padding:10px; max-height:200px; overflow-y:auto; background:#fafafa;">
|
||
<small style="color:#666;">Keine Tarifoptionen für diesen Anbieter vorhanden</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 10px; margin-top: 20px;">
|
||
<button type="submit" class="btn-success">Speichern</button>
|
||
<button type="button" onclick="closeModal('editTariffModal')">Abbrechen</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Edit Schaltung Modal -->
|
||
<div id="editSchaltungModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000;">
|
||
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 30px; border-radius: 12px; width: 800px; max-width: 95%; max-height: 90%; overflow-y: auto; box-shadow: 0 10px 30px rgba(0,0,0,0.3);">
|
||
<h3>Schaltung bearbeiten</h3>
|
||
<form id="editSchaltungForm">
|
||
<input type="hidden" id="editSchaltungId">
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>Schaltungs-ID:</label>
|
||
<input type="text" id="editSchaltungsId" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Eingabe-Datum:</label>
|
||
<input type="date" id="editEingabeDatum" required>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Schaltungs-/Aktivierungsdatum:</label>
|
||
<input type="date" id="editSchaltungsDatum" required>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>Vorname:</label>
|
||
<input type="text" id="editVorname" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Nachname:</label>
|
||
<input type="text" id="editNachname" required>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Firma (optional):</label>
|
||
<input type="text" id="editFirma">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Rufnummer/Kundennummer:</label>
|
||
<input type="text" id="editRufnummer" required>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>Anbieter:</label>
|
||
<select id="editAnbieter" required onchange="loadTarifeForEdit()">
|
||
<option value="">Bitte wählen...</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Tarif:</label>
|
||
<select id="editTarif" required>
|
||
<option value="">Erst Anbieter wählen...</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Hardware:</label>
|
||
<input type="text" id="editHardware" onchange="toggleEditHardwarePricing()">
|
||
</div>
|
||
|
||
<!-- Hardware Pricing Fields -->
|
||
<div id="editHardwarePricingFields" style="display: none;">
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>Hardware-EK (Einkaufspreis) €:</label>
|
||
<input type="number" id="editHardwareEk" step="0.01" placeholder="0.00">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Kundenverkaufspreis (netto) €:</label>
|
||
<input type="number" id="editKundenverkaufspreis" step="0.01" placeholder="0.00">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tarifoptionen -->
|
||
<div class="form-group">
|
||
<label style="font-weight: 600; color: #2c3e50; margin-bottom: 10px; display: block;">Tarifoptionen/Aktionscodes:</label>
|
||
<div id="editTarifoptionenContainer" style="background: #f8f9fa; border: 2px solid #e9ecef; border-radius: 8px; padding: 15px; max-height: 250px; overflow-y: auto; box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);">
|
||
<div style="color: #6c757d; font-style: italic; text-align: center; padding: 20px;">Erst Tarif wählen...</div>
|
||
</div>
|
||
<small style="color: #6c757d; font-size: 12px; margin-top: 5px; display: block;">Wählen Sie die gewünschten Optionen aus. Mehrfachauswahl möglich.</small>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 10px; margin-top: 20px;">
|
||
<button type="submit" class="btn-success">Speichern</button>
|
||
<button type="button" onclick="closeModal('editSchaltungModal')">Abbrechen</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Delete Schaltung Modal -->
|
||
<div id="deleteSchaltungModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000;">
|
||
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 30px; border-radius: 8px; width: 500px; max-width: 90%;">
|
||
<h3>Schaltung löschen</h3>
|
||
<p>Sind Sie sicher, dass Sie diese Schaltung löschen möchten?</p>
|
||
<p><strong id="deleteSchaltungInfo"></strong></p>
|
||
<div class="form-group" style="margin-top: 20px;">
|
||
<label>Grund für die Löschung <span class="required">*</span></label>
|
||
<textarea id="deleteReason" rows="3" placeholder="Bitte geben Sie den Grund für die Löschung ein..." required style="resize: vertical;"></textarea>
|
||
</div>
|
||
<div style="display: flex; gap: 10px; margin-top: 20px;">
|
||
<button onclick="confirmDeleteSchaltung()" class="btn-danger">Löschen</button>
|
||
<button onclick="closeModal('deleteSchaltungModal')">Abbrechen</button>
|
||
</div>
|
||
<input type="hidden" id="deleteSchaltungId">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Documents Modal -->
|
||
<div id="documentsModal" class="documents-modal">
|
||
<div class="documents-modal-content">
|
||
<div class="documents-modal-header">
|
||
<h3>📄 Dokumente</h3>
|
||
<button class="documents-modal-close" onclick="closeDocumentsModal()">×</button>
|
||
</div>
|
||
<div class="documents-modal-body" id="documentsModalBody">
|
||
<!-- Documents will be loaded here -->
|
||
</div>
|
||
<div class="documents-modal-footer" style="padding: 15px 20px; border-top: 1px solid #e0e0e0; background: #f8f9fa;">
|
||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||
<div>
|
||
<input type="file" id="additionalDocumentUpload" multiple accept=".pdf,.jpg,.jpeg,.png,.doc,.docx" style="display: none;">
|
||
<button class="btn btn-primary" onclick="document.getElementById('additionalDocumentUpload').click()" style="background: #28a745; border-color: #28a745;">
|
||
📎 Dokumente hinzufügen
|
||
</button>
|
||
</div>
|
||
<button class="btn btn-secondary" onclick="closeDocumentsModal()">Schließen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- PDF Viewer Modal -->
|
||
<div id="pdfViewerModal" class="pdf-viewer-modal">
|
||
<div class="pdf-viewer-content">
|
||
<div class="pdf-viewer-header">
|
||
<h3 class="pdf-viewer-title" id="pdfViewerTitle">📋 PDF Viewer</h3>
|
||
<button class="pdf-viewer-close" onclick="closePdfViewer()">×</button>
|
||
</div>
|
||
<div class="pdf-viewer-body">
|
||
<div class="pdf-canvas-container">
|
||
<canvas id="pdfCanvas"></canvas>
|
||
</div>
|
||
</div>
|
||
<div class="pdf-controls">
|
||
<button class="pdf-nav-btn" id="prevPageBtn" onclick="prevPage()">◀ Vorherige</button>
|
||
<div class="pdf-page-info">
|
||
Seite <span id="currentPage">1</span> von <span id="totalPages">1</span>
|
||
</div>
|
||
<button class="pdf-nav-btn" id="nextPageBtn" onclick="nextPage()">Nächste ▶</button>
|
||
<div class="pdf-zoom-controls">
|
||
<button class="pdf-zoom-btn" onclick="zoomOut()">-</button>
|
||
<span id="zoomLevel">100%</span>
|
||
<button class="pdf-zoom-btn" onclick="zoomIn()">+</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Add Tarifoption Modal -->
|
||
<div id="addTarifoptionModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 1000;">
|
||
<div style="position: absolute; top: 5%; left: 50%; transform: translateX(-50%); background: white; border-radius: 12px; width: 90%; max-width: 1200px; height: 90%; box-shadow: 0 20px 40px rgba(0,0,0,0.3); display: flex; flex-direction: column;">
|
||
|
||
<!-- Header -->
|
||
<div style="padding: 25px 35px 15px; border-bottom: 1px solid #eee; flex-shrink: 0;">
|
||
<div style="display: flex; justify-content: between; align-items: center;">
|
||
<h2 style="margin: 0; color: #333; font-size: 24px;">Neue Tarifoption hinzufügen</h2>
|
||
<span style="position: absolute; top: 15px; right: 25px; font-size: 28px; cursor: pointer; color: #999; hover: #333;" onclick="closeModal('addTarifoptionModal')">×</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Content -->
|
||
<div style="flex: 1; overflow-y: auto; padding: 25px 35px;">
|
||
<form id="addTarifoptionForm">
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px; height: 100%;">
|
||
<!-- Left Column -->
|
||
<div>
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="addTarifoptionAnbieter" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Anbieter</label>
|
||
<select id="addTarifoptionAnbieter" onchange="loadTarifeForAddOptions()" style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px; background: white;">
|
||
<option value="">Anbieter wählen...</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label style="display: flex; align-items: center; gap: 12px; padding: 15px; background: #f8f9fa; border-radius: 8px; cursor: pointer; border: 2px solid transparent; transition: all 0.2s;">
|
||
<input type="checkbox" id="addTarifoptionAnbieterWeit" onchange="toggleAddTarifSelection()" checked style="width: 18px; height: 18px; cursor: pointer;">
|
||
<span style="font-weight: 500; color: #495057;">Für alle Tarife des Anbieters (Anbieter-weit)</span>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="addTarifoptionName" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Name der Option</label>
|
||
<input type="text" id="addTarifoptionName" placeholder="z.B. Anschlusspreisrabatt" required style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px;">
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="addTarifoptionCode" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Code (optional)</label>
|
||
<input type="text" id="addTarifoptionCode" placeholder="z.B. RABATT2024" style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px;">
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="addTarifoptionProvisionBetrag" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Zusätzliche Provision (€)</label>
|
||
<input type="number" id="addTarifoptionProvisionBetrag" step="0.01" placeholder="Kann auch negativ sein" required style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px;">
|
||
<small style="color: #6c757d; font-size: 12px; margin-top: 5px; display: block;">Wird zur Tarif-Provision hinzugefügt (negativ = Abzug)</small>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="addTarifoptionBeschreibung" style="display: block; font-weight: 600; margin-bottom: 8px; color: #333;">Beschreibung (optional)</label>
|
||
<textarea id="addTarifoptionBeschreibung" rows="3" placeholder="Beschreibung der Tarifoption..." style="width: 100%; padding: 12px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px; resize: vertical;"></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Right Column - Tarif Selection -->
|
||
<div>
|
||
<div id="addTarifSelectionContainer" style="display: none;">
|
||
<label style="display: block; font-weight: 600; margin-bottom: 15px; color: #333; font-size: 16px;">Tarife auswählen:</label>
|
||
|
||
<div style="margin-bottom: 15px;">
|
||
<button type="button" onclick="selectAllAddTarifs()" style="background: #28a745; color: white; border: none; padding: 8px 16px; border-radius: 6px; margin-right: 8px; cursor: pointer; font-size: 13px; font-weight: 500;">Alle auswählen</button>
|
||
<button type="button" onclick="deselectAllAddTarifs()" style="background: #dc3545; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: 500;">Alle abwählen</button>
|
||
<input type="text" id="addTarifSearch" placeholder="Tarife filtern..." style="float: right; padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; width: 180px;" oninput="filterAddTarifs()">
|
||
</div>
|
||
|
||
<div id="addTarifCheckboxContainer" style="height: 400px; overflow-y: auto; border: 2px solid #e1e5e9; border-radius: 8px; background: #fefefe;">
|
||
<div style="padding: 40px; text-align: center; color: #6c757d; font-style: italic;">Erst Anbieter wählen...</div>
|
||
</div>
|
||
|
||
<div id="addTarifCounter" style="margin-top: 10px; font-size: 13px; color: #6c757d; text-align: right;"></div>
|
||
</div>
|
||
|
||
<div id="addAnbieterWeitInfo" style="padding: 30px; text-align: center; color: #6c757d; border: 2px dashed #dee2e6; border-radius: 8px; background: #f8f9fa;">
|
||
<div style="font-size: 48px; margin-bottom: 15px; opacity: 0.5;">🏢</div>
|
||
<div style="font-weight: 500; margin-bottom: 8px;">Anbieter-weite Tarifoption</div>
|
||
<div style="font-size: 13px;">Diese Option wird automatisch allen Tarifen des gewählten Anbieters zugeordnet.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<div style="padding: 20px 35px; border-top: 1px solid #eee; background: #f8f9fa; border-bottom-left-radius: 12px; border-bottom-right-radius: 12px; flex-shrink: 0;">
|
||
<div style="display: flex; justify-content: flex-end; gap: 15px;">
|
||
<button type="button" onclick="closeModal('addTarifoptionModal')" style="background: #6c757d; color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500;">Abbrechen</button>
|
||
<button type="submit" form="addTarifoptionForm" style="background: #28a745; color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500;">Tarifoption hinzufügen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
||
<script src="script.js"></script>
|
||
</body>
|
||
</html> |