Sprint 8: Events + Hundesitting

Events:
- Backend events.py: CRUD, Typen (ausstellung/training/treffen/markt/wettkampf/sonstiges)
  Haversine-Filter, Monats-Gruppierung in der Liste
- Frontend events.js: Liste/Karte-Toggle, Typ-Filter-Chips, farbige Marker,
  Detail-Modal, Erstellen/Bearbeiten-Formular mit GPS-Button

Hundesitting:
- Backend sitting.py: Sitter-Profile (create/update/me), Anfragen (send/accept/decline/cancel),
  Inbox für Sitter, Haversine-Sortierung, Service-Filter
- Frontend sitting.js: 3 Tabs (Suchen/Profil/Anfragen), Sitter-Karten mit Distanz,
  Detail-Modal + Anfrage-Formular, Profil-Verwaltung

DB: events, sitters, sitting_requests Tabellen hinzugefügt
SW-Cache: by-v21 → by-v22
This commit is contained in:
rene 2026-04-14 06:19:15 +02:00
parent ec17dfb029
commit 5f8fd3bd51
9 changed files with 1680 additions and 2 deletions

View file

@ -1740,3 +1740,285 @@ textarea.form-control {
.walks-participant:last-child { border-bottom: none; }
.walks-participant-name { font-weight: var(--weight-semibold); }
.walks-participant-dogs { color: var(--c-text-secondary); }
/* ------------------------------------------------------------
EVENTS (events.js)
------------------------------------------------------------ */
.events-toolbar {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
background: var(--c-surface);
border-bottom: 1px solid var(--c-border);
flex-shrink: 0;
}
.events-view-toggle {
display: flex;
gap: var(--space-1);
background: var(--c-bg);
border-radius: var(--radius-md);
padding: 2px;
border: 1px solid var(--c-border);
}
.events-view-btn {
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-sm);
border: none;
background: transparent;
color: var(--c-text-secondary);
font-size: var(--text-sm);
cursor: pointer;
transition: all 0.15s;
}
.events-view-btn.active {
background: var(--c-surface);
color: var(--c-text);
box-shadow: var(--shadow-xs);
}
.events-filter-bar {
display: flex;
gap: var(--space-2);
padding: var(--space-2) var(--space-4);
overflow-x: auto;
background: var(--c-surface);
border-bottom: 1px solid var(--c-border);
flex-shrink: 0;
scrollbar-width: none;
}
.events-filter-bar::-webkit-scrollbar { display: none; }
.events-filter-btn {
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-full);
border: 1.5px solid var(--c-border);
background: var(--c-surface);
color: var(--c-text-secondary);
font-size: var(--text-sm);
cursor: pointer;
white-space: nowrap;
transition: all 0.15s;
flex-shrink: 0;
}
.events-filter-btn.active {
background: var(--c-primary);
color: #fff;
border-color: var(--c-primary);
}
.events-list {
flex: 1;
overflow-y: auto;
padding: var(--space-4);
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.events-map {
flex: 1;
position: relative;
}
.events-month-label {
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
color: var(--c-text-secondary);
padding: var(--space-2) 0 var(--space-1);
}
.events-card {
background: var(--c-surface);
border-radius: var(--radius-lg);
border: 1px solid var(--c-border);
border-left: 3px solid var(--c-primary);
padding: var(--space-3) var(--space-4);
display: grid;
grid-template-columns: 52px 1fr auto;
gap: var(--space-3);
cursor: pointer;
transition: box-shadow 0.15s;
align-items: center;
box-shadow: var(--shadow-xs);
}
.events-card:hover { box-shadow: var(--shadow-md); }
.events-date-badge {
display: flex;
flex-direction: column;
align-items: center;
background: var(--c-bg);
border-radius: var(--radius-md);
padding: var(--space-1);
}
.events-date-badge .day { font-size: var(--text-xs); color: var(--c-text-secondary); }
.events-date-badge .num { font-size: 1.5rem; font-weight: var(--weight-bold); line-height: 1.1; }
.events-date-badge .month { font-size: var(--text-xs); color: var(--c-text-secondary); }
.events-card-body { min-width: 0; }
.events-card-title {
font-weight: var(--weight-semibold);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: var(--space-1);
}
.events-card-meta {
font-size: var(--text-sm);
color: var(--c-text-secondary);
display: flex;
align-items: center;
gap: var(--space-1);
flex-wrap: wrap;
}
.events-badge {
display: inline-block;
padding: 2px var(--space-2);
border-radius: var(--radius-full);
font-size: var(--text-xs);
font-weight: var(--weight-semibold);
}
.events-detail-row {
margin-bottom: var(--space-2);
color: var(--c-text);
}
.events-detail-desc {
background: var(--c-bg);
border-radius: var(--radius-md);
padding: var(--space-3);
margin: var(--space-3) 0;
color: var(--c-text-secondary);
white-space: pre-wrap;
}
/* ------------------------------------------------------------
SITTING (sitting.js)
------------------------------------------------------------ */
.sitting-tabs {
display: flex;
border-bottom: 1px solid var(--c-border);
background: var(--c-surface);
flex-shrink: 0;
}
.sitting-tab {
flex: 1;
padding: var(--space-3);
border: none;
background: transparent;
color: var(--c-text-secondary);
font-size: var(--text-sm);
font-weight: var(--weight-medium);
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all 0.15s;
}
.sitting-tab.active {
color: var(--c-primary);
border-bottom-color: var(--c-primary);
}
.sitting-content {
flex: 1;
overflow-y: auto;
padding: var(--space-4);
}
.sitting-list {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.sitting-card {
background: var(--c-surface);
border-radius: var(--radius-lg);
border: 1px solid var(--c-border);
padding: var(--space-4);
display: grid;
grid-template-columns: 48px 1fr auto;
gap: var(--space-3);
align-items: flex-start;
cursor: pointer;
transition: box-shadow 0.15s;
box-shadow: var(--shadow-xs);
}
.sitting-card:hover { box-shadow: var(--shadow-md); }
.sitting-card-avatar {
width: 48px;
height: 48px;
background: var(--c-bg);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
}
.sitting-card-name { font-weight: var(--weight-semibold); margin-bottom: var(--space-1); }
.sitting-card-dist { font-size: var(--text-xs); color: var(--c-text-muted); margin-bottom: var(--space-1); }
.sitting-card-desc { font-size: var(--text-sm); color: var(--c-text-secondary); margin-bottom: var(--space-2); }
.sitting-price { font-weight: var(--weight-bold); color: var(--c-primary); }
.sitting-dogs { font-size: var(--text-xs); color: var(--c-text-muted); margin-top: var(--space-1); }
.sitting-services {
display: flex;
flex-wrap: wrap;
gap: var(--space-1);
}
.sit-service-badge {
background: var(--c-primary-light, #dbeafe);
color: var(--c-primary);
padding: 2px var(--space-2);
border-radius: var(--radius-full);
font-size: var(--text-xs);
font-weight: var(--weight-medium);
}
.sitting-empty-profil {
text-align: center;
padding: var(--space-8) var(--space-4);
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-3);
}
.sitting-my-profil { display: flex; flex-direction: column; gap: var(--space-3); }
.sitting-profil-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.sitting-profil-status {
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-full);
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
}
.sitting-profil-status.active { background: #d1fae5; color: #065f46; }
.sitting-profil-status.inactive { background: #f3f4f6; color: #6b7280; }
.sitting-profil-facts {
display: flex;
gap: var(--space-4);
}
.sitting-profil-fact { font-size: var(--text-sm); color: var(--c-text-secondary); }
.sitting-section-label {
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
color: var(--c-text-secondary);
margin-bottom: var(--space-2);
}
.sitting-request-card {
background: var(--c-surface);
border-radius: var(--radius-lg);
border: 1px solid var(--c-border);
padding: var(--space-3) var(--space-4);
margin-bottom: var(--space-2);
box-shadow: var(--shadow-xs);
}
.sitting-req-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-1);
}
.sitting-req-name { font-weight: var(--weight-semibold); }
.sitting-req-status { font-size: var(--text-sm); font-weight: var(--weight-semibold); text-transform: capitalize; }
.sitting-req-dates { font-size: var(--text-sm); color: var(--c-text-secondary); }
.sitting-req-msg { font-size: var(--text-sm); color: var(--c-text-secondary); margin-top: var(--space-1); }
.sitting-req-actions {
display: flex;
gap: var(--space-2);
margin-top: var(--space-2);
}
.sitting-detail-avatar {
font-size: 4rem;
text-align: center;
margin-bottom: var(--space-2);
}