UX: Modal-Rand, Icon-Farben, Adresse aufgeteilt
- Tierarzt-Adresse: strasse / plz / ort statt einzeiligem Freitext - Modal: Rand in Primärfarbe + kein versehentliches Schließen beim Klick auf Hintergrund - Nav/Sidebar-Icons: inaktiv gedämpft, aktiv amber-getönt (CSS filter) - Datums-Kalender-Icon: ebenfalls amber statt Schwarz - SW-Cache → by-v8
This commit is contained in:
parent
fc0f48c6d0
commit
dee8d10496
7 changed files with 59 additions and 14 deletions
|
|
@ -254,7 +254,9 @@ def init_db():
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
adresse TEXT,
|
strasse TEXT,
|
||||||
|
plz TEXT,
|
||||||
|
ort TEXT,
|
||||||
telefon TEXT,
|
telefon TEXT,
|
||||||
notfall_telefon TEXT,
|
notfall_telefon TEXT,
|
||||||
email TEXT,
|
email TEXT,
|
||||||
|
|
@ -295,6 +297,10 @@ def _migrate(conn_factory):
|
||||||
("health", "datei_url", "TEXT"),
|
("health", "datei_url", "TEXT"),
|
||||||
("health", "datei_typ", "TEXT"),
|
("health", "datei_typ", "TEXT"),
|
||||||
("health", "tierarzt_id", "INTEGER"),
|
("health", "tierarzt_id", "INTEGER"),
|
||||||
|
# Tierärzte: Adresse aufgeteilt in Strasse/PLZ/Ort
|
||||||
|
("tieraerzte", "strasse", "TEXT"),
|
||||||
|
("tieraerzte", "plz", "TEXT"),
|
||||||
|
("tieraerzte", "ort", "TEXT"),
|
||||||
]
|
]
|
||||||
with conn_factory() as conn:
|
with conn_factory() as conn:
|
||||||
for table, column, col_type in migrations:
|
for table, column, col_type in migrations:
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,9 @@ router = APIRouter()
|
||||||
|
|
||||||
class TierarztCreate(BaseModel):
|
class TierarztCreate(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
adresse: Optional[str] = None
|
strasse: Optional[str] = None
|
||||||
|
plz: Optional[str] = None
|
||||||
|
ort: Optional[str] = None
|
||||||
telefon: Optional[str] = None
|
telefon: Optional[str] = None
|
||||||
notfall_telefon: Optional[str] = None
|
notfall_telefon: Optional[str] = None
|
||||||
email: Optional[str] = None
|
email: Optional[str] = None
|
||||||
|
|
@ -22,7 +24,9 @@ class TierarztCreate(BaseModel):
|
||||||
|
|
||||||
class TierarztUpdate(BaseModel):
|
class TierarztUpdate(BaseModel):
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
adresse: Optional[str] = None
|
strasse: Optional[str] = None
|
||||||
|
plz: Optional[str] = None
|
||||||
|
ort: Optional[str] = None
|
||||||
telefon: Optional[str] = None
|
telefon: Optional[str] = None
|
||||||
notfall_telefon: Optional[str] = None
|
notfall_telefon: Optional[str] = None
|
||||||
email: Optional[str] = None
|
email: Optional[str] = None
|
||||||
|
|
@ -48,11 +52,11 @@ async def create_tierarzt(data: TierarztCreate, user=Depends(get_current_user)):
|
||||||
with db() as conn:
|
with db() as conn:
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT INTO tieraerzte
|
"""INSERT INTO tieraerzte
|
||||||
(user_id, name, adresse, telefon, notfall_telefon,
|
(user_id, name, strasse, plz, ort, telefon, notfall_telefon,
|
||||||
email, website, notizen, ist_notfallpraxis)
|
email, website, notizen, ist_notfallpraxis)
|
||||||
VALUES (?,?,?,?,?,?,?,?,?)""",
|
VALUES (?,?,?,?,?,?,?,?,?,?,?)""",
|
||||||
(user["id"], data.name, data.adresse, data.telefon,
|
(user["id"], data.name, data.strasse, data.plz, data.ort,
|
||||||
data.notfall_telefon, data.email, data.website,
|
data.telefon, data.notfall_telefon, data.email, data.website,
|
||||||
data.notizen, int(data.ist_notfallpraxis))
|
data.notizen, int(data.ist_notfallpraxis))
|
||||||
)
|
)
|
||||||
row = conn.execute(
|
row = conn.execute(
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,14 @@
|
||||||
|
|
||||||
.form-control::placeholder { color: var(--c-text-muted); }
|
.form-control::placeholder { color: var(--c-text-muted); }
|
||||||
|
|
||||||
|
/* Kalender-Icon in Datumseingaben: Amber statt Schwarz */
|
||||||
|
input[type="date"]::-webkit-calendar-picker-indicator,
|
||||||
|
input[type="time"]::-webkit-calendar-picker-indicator {
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0.85;
|
||||||
|
filter: sepia(0.7) saturate(1.8) hue-rotate(-8deg) brightness(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
.form-control:focus {
|
.form-control:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: var(--c-primary);
|
border-color: var(--c-primary);
|
||||||
|
|
@ -450,6 +458,7 @@ textarea.form-control {
|
||||||
.modal {
|
.modal {
|
||||||
background: var(--c-surface);
|
background: var(--c-surface);
|
||||||
border-radius: var(--radius-xl) var(--radius-xl) 0 0;
|
border-radius: var(--radius-xl) var(--radius-xl) 0 0;
|
||||||
|
border: 2px solid var(--c-primary);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 480px;
|
max-width: 480px;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,11 @@
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
filter: saturate(0.35) brightness(0.75);
|
||||||
|
transition: filter var(--transition-fast);
|
||||||
|
}
|
||||||
|
.nav-item.active .nav-item-icon {
|
||||||
|
filter: sepia(0.7) saturate(1.8) hue-rotate(-8deg) brightness(0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ungelesen-Badge auf Nav-Icon */
|
/* Ungelesen-Badge auf Nav-Icon */
|
||||||
|
|
@ -308,6 +313,11 @@
|
||||||
width: 24px;
|
width: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
filter: saturate(0.35) brightness(0.75);
|
||||||
|
transition: filter var(--transition-fast);
|
||||||
|
}
|
||||||
|
.sidebar-item.active .sidebar-item-icon {
|
||||||
|
filter: sepia(0.7) saturate(1.8) hue-rotate(-8deg) brightness(0.9);
|
||||||
}
|
}
|
||||||
.sidebar-item-badge {
|
.sidebar-item-badge {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
|
|
||||||
|
|
@ -812,7 +812,10 @@ window.Page_health = (() => {
|
||||||
${_esc(p.name)}
|
${_esc(p.name)}
|
||||||
${!p.aktiv ? '<span style="font-size:var(--text-xs);color:var(--c-text-secondary);font-weight:400"> · Ehemalig</span>' : ''}
|
${!p.aktiv ? '<span style="font-size:var(--text-xs);color:var(--c-text-secondary);font-weight:400"> · Ehemalig</span>' : ''}
|
||||||
</div>
|
</div>
|
||||||
${p.adresse ? `<div class="health-card-meta">${_esc(p.adresse)}</div>` : ''}
|
${(p.strasse || p.plz || p.ort) ? `
|
||||||
|
<div class="health-card-meta">
|
||||||
|
${[p.strasse, [p.plz, p.ort].filter(Boolean).join(' ')].filter(Boolean).map(_esc).join(', ')}
|
||||||
|
</div>` : ''}
|
||||||
<div style="display:flex;gap:var(--space-2);margin-top:var(--space-2);flex-wrap:wrap">
|
<div style="display:flex;gap:var(--space-2);margin-top:var(--space-2);flex-wrap:wrap">
|
||||||
${p.telefon ? `
|
${p.telefon ? `
|
||||||
<a href="tel:${_esc(p.telefon)}" class="btn btn-secondary btn-sm"
|
<a href="tel:${_esc(p.telefon)}" class="btn btn-secondary btn-sm"
|
||||||
|
|
@ -861,9 +864,21 @@ window.Page_health = (() => {
|
||||||
value="${_esc(praxis?.name || '')}" placeholder="Dr. Muster Tierarztpraxis" required>
|
value="${_esc(praxis?.name || '')}" placeholder="Dr. Muster Tierarztpraxis" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">Adresse</label>
|
<label class="form-label">Straße & Hausnummer</label>
|
||||||
<input class="form-control" type="text" name="adresse"
|
<input class="form-control" type="text" name="strasse"
|
||||||
value="${_esc(praxis?.adresse || '')}" placeholder="Musterstraße 1, 12345 Stadt">
|
value="${_esc(praxis?.strasse || '')}" placeholder="Musterstraße 1">
|
||||||
|
</div>
|
||||||
|
<div style="display:grid;grid-template-columns:120px 1fr;gap:var(--space-3)">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">PLZ</label>
|
||||||
|
<input class="form-control" type="text" name="plz" inputmode="numeric"
|
||||||
|
value="${_esc(praxis?.plz || '')}" placeholder="12345">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">Ort</label>
|
||||||
|
<input class="form-control" type="text" name="ort"
|
||||||
|
value="${_esc(praxis?.ort || '')}" placeholder="Musterstadt">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)">
|
<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
@ -918,7 +933,9 @@ window.Page_health = (() => {
|
||||||
await UI.asyncButton(btn, async () => {
|
await UI.asyncButton(btn, async () => {
|
||||||
const payload = {
|
const payload = {
|
||||||
name: fd.name?.trim(),
|
name: fd.name?.trim(),
|
||||||
adresse: fd.adresse || null,
|
strasse: fd.strasse || null,
|
||||||
|
plz: fd.plz || null,
|
||||||
|
ort: fd.ort || null,
|
||||||
telefon: fd.telefon || null,
|
telefon: fd.telefon || null,
|
||||||
notfall_telefon: fd.notfall_telefon || null,
|
notfall_telefon: fd.notfall_telefon || null,
|
||||||
email: fd.email || null,
|
email: fd.email || null,
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,6 @@ const UI = (() => {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
overlay.querySelector('.modal-close-btn')?.addEventListener('click', close);
|
overlay.querySelector('.modal-close-btn')?.addEventListener('click', close);
|
||||||
overlay.addEventListener('click', e => { if (e.target === overlay) close(); });
|
|
||||||
|
|
||||||
document.getElementById('modal-container').appendChild(overlay);
|
document.getElementById('modal-container').appendChild(overlay);
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Offline-Cache + Push Notifications
|
Offline-Cache + Push Notifications
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const CACHE_VERSION = 'by-v7';
|
const CACHE_VERSION = 'by-v8';
|
||||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||||
|
|
||||||
// Diese Dateien werden beim Install gecacht (App Shell)
|
// Diese Dateien werden beim Install gecacht (App Shell)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue