initial feature/react-migration commit
This commit is contained in:
258
dashboard-dash-backup/components/appointment_modal.py
Normal file
258
dashboard-dash-backup/components/appointment_modal.py
Normal file
@@ -0,0 +1,258 @@
|
||||
from dash import html, dcc
|
||||
import dash_mantine_components as dmc
|
||||
from dash_iconify import DashIconify
|
||||
import dash_quill
|
||||
|
||||
def create_input_with_tooltip_full(component, tooltip_text):
|
||||
return dmc.Stack([
|
||||
dmc.Group([
|
||||
component,
|
||||
dmc.Tooltip(
|
||||
children=[
|
||||
dmc.ActionIcon(
|
||||
DashIconify(icon="mdi:help-circle-outline", width=16),
|
||||
variant="subtle",
|
||||
color="gray",
|
||||
size="sm"
|
||||
)
|
||||
],
|
||||
label=tooltip_text,
|
||||
position="top",
|
||||
multiline=True,
|
||||
w=300
|
||||
)
|
||||
], gap="xs", align="flex-end")
|
||||
], gap=0)
|
||||
|
||||
def create_input_with_tooltip_time(component, tooltip_text):
|
||||
return dmc.Group([
|
||||
component,
|
||||
dmc.Tooltip(
|
||||
children=[
|
||||
dmc.ActionIcon(
|
||||
DashIconify(icon="mdi:help-circle-outline", width=16),
|
||||
variant="subtle",
|
||||
color="gray",
|
||||
size="sm"
|
||||
)
|
||||
],
|
||||
label=tooltip_text,
|
||||
position="top",
|
||||
multiline=True,
|
||||
w=300
|
||||
)
|
||||
], gap="xs", align="flex-end")
|
||||
|
||||
def get_appointment_modal():
|
||||
weekday_options = [
|
||||
{"value": "0", "label": "Montag"},
|
||||
{"value": "1", "label": "Dienstag"},
|
||||
{"value": "2", "label": "Mittwoch"},
|
||||
{"value": "3", "label": "Donnerstag"},
|
||||
{"value": "4", "label": "Freitag"},
|
||||
{"value": "5", "label": "Samstag"},
|
||||
{"value": "6", "label": "Sonntag"}
|
||||
]
|
||||
time_options = [
|
||||
{"value": f"{h:02d}:{m:02d}", "label": f"{h:02d}:{m:02d}"}
|
||||
for h in range(6, 24) for m in [0, 30]
|
||||
]
|
||||
return dmc.Modal(
|
||||
id="appointment-modal",
|
||||
title="Neuen Termin anlegen",
|
||||
centered=True,
|
||||
size="auto", # oder "80vw"
|
||||
children=[
|
||||
dmc.Container([
|
||||
dmc.Grid([
|
||||
dmc.GridCol([
|
||||
dmc.Paper([
|
||||
dmc.Title("Termindetails", order=3, className="mb-3"),
|
||||
dmc.Stack([
|
||||
create_input_with_tooltip_full(
|
||||
dmc.TextInput(
|
||||
label="Titel",
|
||||
placeholder="Terminbezeichnung eingeben",
|
||||
leftSection=DashIconify(icon="mdi:calendar-text"),
|
||||
id="title-input",
|
||||
required=True,
|
||||
style={"flex": 1}
|
||||
),
|
||||
"Geben Sie eine aussagekräftige Bezeichnung für den Termin ein"
|
||||
),
|
||||
create_input_with_tooltip_full(
|
||||
dmc.DatePickerInput(
|
||||
label="Startdatum",
|
||||
id="start-date-input",
|
||||
firstDayOfWeek=1,
|
||||
weekendDays=[0, 6],
|
||||
valueFormat="DD.MM.YYYY",
|
||||
placeholder="Datum auswählen",
|
||||
leftSection=DashIconify(icon="mdi:calendar"),
|
||||
clearable=False,
|
||||
style={"flex": 1}
|
||||
),
|
||||
"Wählen Sie das Datum für den Termin aus dem Kalender"
|
||||
),
|
||||
dmc.Grid([
|
||||
dmc.GridCol([
|
||||
dmc.Stack([
|
||||
create_input_with_tooltip_time(
|
||||
dmc.Select(
|
||||
label="Startzeit",
|
||||
placeholder="Zeit auswählen",
|
||||
data=time_options,
|
||||
searchable=True,
|
||||
clearable=True,
|
||||
id="time-start",
|
||||
value="09:00",
|
||||
required=True,
|
||||
style={"flex": 1}
|
||||
),
|
||||
"Eingabe: 10:25, 10.25, 1025 oder 10 (wird automatisch formatiert)"
|
||||
),
|
||||
html.Div(id="start-time-feedback")
|
||||
], gap="xs")
|
||||
], span=6),
|
||||
dmc.GridCol([
|
||||
dmc.Stack([
|
||||
create_input_with_tooltip_time(
|
||||
dmc.Select(
|
||||
label="Endzeit",
|
||||
placeholder="Zeit auswählen",
|
||||
data=time_options,
|
||||
searchable=True,
|
||||
clearable=True,
|
||||
id="time-end",
|
||||
required=True,
|
||||
style={"flex": 1}
|
||||
),
|
||||
"Endzeit muss nach der Startzeit am selben Tag liegen. Termine können nicht über Mitternacht hinausgehen."
|
||||
),
|
||||
html.Div(id="end-time-feedback")
|
||||
], gap="xs")
|
||||
], span=6)
|
||||
]),
|
||||
create_input_with_tooltip_full(
|
||||
dmc.Select(
|
||||
label="Termintyp",
|
||||
placeholder="Typ auswählen",
|
||||
data=[
|
||||
{"value": "presentation", "label": "Präsentation"},
|
||||
{"value": "website", "label": "Website"},
|
||||
{"value": "video", "label": "Video"},
|
||||
{"value": "message", "label": "Nachricht"},
|
||||
{"value": "webuntis", "label": "WebUntis"},
|
||||
{"value": "other", "label": "Sonstiges"}
|
||||
],
|
||||
id="type-input",
|
||||
required=True,
|
||||
style={"flex": 1}
|
||||
),
|
||||
"Wählen Sie die Art der Präsentation aus."
|
||||
),
|
||||
html.Div(id="type-specific-fields"),
|
||||
create_input_with_tooltip_full(
|
||||
dmc.Textarea(
|
||||
label="Beschreibung",
|
||||
placeholder="Zusätzliche Informationen...",
|
||||
minRows=3,
|
||||
autosize=True,
|
||||
id="description-input",
|
||||
style={"flex": 1}
|
||||
),
|
||||
"Optionale Beschreibung mit weiteren Details zum Termin"
|
||||
)
|
||||
], gap="md")
|
||||
], p="md", shadow="sm")
|
||||
], span=6),
|
||||
dmc.GridCol([
|
||||
dmc.Paper([
|
||||
dmc.Title("Wiederholung", order=3, className="mb-3"),
|
||||
dmc.Stack([
|
||||
create_input_with_tooltip_full(
|
||||
dmc.Checkbox(
|
||||
label="Wiederholender Termin",
|
||||
id="repeat-checkbox",
|
||||
description="Aktivieren für wöchentliche Wiederholung"
|
||||
),
|
||||
"Aktivieren Sie diese Option, um den Termin an mehreren Wochentagen zu wiederholen"
|
||||
),
|
||||
html.Div(id="repeat-options", children=[
|
||||
create_input_with_tooltip_full(
|
||||
dmc.MultiSelect(
|
||||
label="Wochentage",
|
||||
placeholder="Wochentage auswählen",
|
||||
data=weekday_options,
|
||||
id="weekdays-select",
|
||||
description="An welchen Wochentagen soll der Termin stattfinden?",
|
||||
disabled=True,
|
||||
style={"flex": 1}
|
||||
),
|
||||
"Wählen Sie mindestens einen Wochentag für die Wiederholung aus"
|
||||
),
|
||||
dmc.Space(h="md"),
|
||||
create_input_with_tooltip_full(
|
||||
dmc.DatePickerInput(
|
||||
label="Wiederholung bis",
|
||||
id="repeat-until-date",
|
||||
firstDayOfWeek=1,
|
||||
weekendDays=[0, 6],
|
||||
valueFormat="DD.MM.YYYY",
|
||||
placeholder="Enddatum auswählen",
|
||||
leftSection=DashIconify(icon="mdi:calendar-end"),
|
||||
description="Letzter Tag der Wiederholung",
|
||||
disabled=True,
|
||||
clearable=True,
|
||||
style={"flex": 1}
|
||||
),
|
||||
"Datum bis wann die Wiederholung stattfinden soll. Muss nach dem Startdatum liegen."
|
||||
),
|
||||
dmc.Space(h="lg"),
|
||||
create_input_with_tooltip_full(
|
||||
dmc.Checkbox(
|
||||
label="Ferientage berücksichtigen",
|
||||
id="skip-holidays-checkbox",
|
||||
description="Termine an Feiertagen und in Schulferien auslassen",
|
||||
disabled=True
|
||||
),
|
||||
"Aktivieren Sie diese Option, um Termine an deutschen Feiertagen und in Schulferien automatisch zu überspringen"
|
||||
)
|
||||
])
|
||||
], gap="md")
|
||||
], p="md", shadow="sm"),
|
||||
dmc.Paper([
|
||||
dmc.Title("Aktionen", order=3, className="mb-3"),
|
||||
dmc.Stack([
|
||||
dmc.Button(
|
||||
"Termin(e) speichern",
|
||||
color="green",
|
||||
leftSection=DashIconify(icon="mdi:content-save"),
|
||||
id="btn-save",
|
||||
size="lg",
|
||||
fullWidth=True
|
||||
),
|
||||
dmc.Button(
|
||||
"Zurücksetzen",
|
||||
color="gray",
|
||||
variant="outline",
|
||||
leftSection=DashIconify(icon="mdi:refresh"),
|
||||
id="btn-reset",
|
||||
fullWidth=True
|
||||
),
|
||||
dmc.Button(
|
||||
"Schließen",
|
||||
id="close-appointment-modal-btn",
|
||||
color="red", # oder "danger"
|
||||
leftSection=DashIconify(icon="mdi:close"),
|
||||
variant="filled",
|
||||
style={"marginBottom": 10}
|
||||
),
|
||||
html.Div(id="save-feedback", className="mt-3")
|
||||
], gap="md")
|
||||
], p="md", shadow="sm", className="mt-3")
|
||||
], span=6)
|
||||
])
|
||||
], size="lg")
|
||||
]
|
||||
)
|
||||
13
dashboard-dash-backup/components/header.py
Normal file
13
dashboard-dash-backup/components/header.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# dashboard/components/header.py
|
||||
from dash import html
|
||||
|
||||
def Header():
|
||||
return html.Div(
|
||||
className="app-header",
|
||||
children=[
|
||||
html.Img(src="/assets/logo.png", className="logo"),
|
||||
html.Span("Infoscreen-Manager", className="app-title"),
|
||||
html.Span(" – Organisationsname", className="org-name"),
|
||||
html.Div(id="header-right", className="header-right") # Platzhalter für Login/Profil‐Button
|
||||
]
|
||||
)
|
||||
72
dashboard-dash-backup/components/sidebar.py
Normal file
72
dashboard-dash-backup/components/sidebar.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# dashboard/components/sidebar.py
|
||||
|
||||
from dash import html
|
||||
import dash_bootstrap_components as dbc
|
||||
from dash_iconify import DashIconify
|
||||
|
||||
def Sidebar(collapsed: bool = False):
|
||||
"""
|
||||
Gibt nur den Inhalt der Sidebar zurück (ohne das äußere div mit id="sidebar").
|
||||
Das äußere div wird bereits in app.py definiert.
|
||||
"""
|
||||
|
||||
nav_items = [
|
||||
{"label": "Übersicht", "href": "/overview", "icon": "mdi:view-dashboard"},
|
||||
{"label": "Termine", "href": "/appointments","icon": "mdi:calendar"},
|
||||
{"label": "Bildschirme", "href": "/clients", "icon": "mdi:monitor"},
|
||||
{"label": "Einstellungen","href": "/settings", "icon": "mdi:cog"},
|
||||
{"label": "Benutzer", "href": "/users", "icon": "mdi:account"},
|
||||
]
|
||||
|
||||
if collapsed:
|
||||
nav_links = [
|
||||
dbc.NavLink(
|
||||
DashIconify(icon=item["icon"], width=24),
|
||||
href=item["href"],
|
||||
active="exact",
|
||||
className="sidebar-item-collapsed",
|
||||
id={"type": "nav-item", "index": item["label"]},
|
||||
)
|
||||
for item in nav_items
|
||||
]
|
||||
else:
|
||||
nav_links = [
|
||||
dbc.NavLink(
|
||||
[
|
||||
DashIconify(icon=item["icon"], width=24),
|
||||
html.Span(item["label"], className="ms-2 sidebar-label"),
|
||||
],
|
||||
href=item["href"],
|
||||
active="exact",
|
||||
className="sidebar-item",
|
||||
id={"type": "nav-item", "index": item["label"]},
|
||||
)
|
||||
for item in nav_items
|
||||
]
|
||||
|
||||
return [
|
||||
html.Div(
|
||||
className="sidebar-toggle",
|
||||
children=html.Button(
|
||||
DashIconify(icon="mdi:menu", width=28),
|
||||
id="btn-toggle-sidebar",
|
||||
className="toggle-button",
|
||||
)
|
||||
),
|
||||
dbc.Collapse(
|
||||
dbc.Nav(
|
||||
nav_links,
|
||||
vertical=True,
|
||||
pills=True,
|
||||
className="sidebar-nav",
|
||||
),
|
||||
is_open=not collapsed,
|
||||
className="sidebar-nav",
|
||||
) if not collapsed else
|
||||
dbc.Nav(
|
||||
nav_links,
|
||||
vertical=True,
|
||||
pills=True,
|
||||
className="sidebar-nav-collapsed",
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user