Sprint 11: Freunde & Chat + Phosphor-Icon-Vollmigration
- Freundschaften (pending/accepted), Nutzersuche, Anfragen per Push - Direktnachrichten mit Polling, iMessage-Stil, Deep-Links aus Push - Alle Seiten (map, places, diary, health, dog-profile, sitting, knigge, forum, wiki, walks) vollständig auf Phosphor-Icons migriert - Wikidata-Rassen-Scraper (~833 neue Rassen, lokal gespiegelte Fotos) - TheDogAPI lokal gespiegelt (169 Rassen + Fotos) - Quiz-Result-Cards horizontal (korrekte Bildproportionen) - SW by-v89
This commit is contained in:
parent
96bd57f0ad
commit
097295c628
44 changed files with 9980 additions and 300 deletions
|
|
@ -9,10 +9,10 @@ window.Page_sitting = (() => {
|
|||
// Konstanten
|
||||
// ----------------------------------------------------------
|
||||
const SERVICES = [
|
||||
{ id: 'tagesbetreuung', label: 'Tagesbetreuung', icon: '☀️' },
|
||||
{ id: 'uebernachtung', label: 'Übernachtung', icon: '🌙' },
|
||||
{ id: 'gassi', label: 'Gassi gehen', icon: '🦮' },
|
||||
{ id: 'hausbesuch', label: 'Hausbesuch', icon: '🏠' },
|
||||
{ id: 'tagesbetreuung', label: 'Tagesbetreuung', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#sun"></use></svg>' },
|
||||
{ id: 'uebernachtung', label: 'Übernachtung', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#moon"></use></svg>' },
|
||||
{ id: 'gassi', label: 'Gassi gehen', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#dog"></use></svg>' },
|
||||
{ id: 'hausbesuch', label: 'Hausbesuch', icon: '<svg class="ph-icon" aria-hidden="true"><use href="/icons/phosphor.svg#house-line"></use></svg>' },
|
||||
];
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
|
@ -44,10 +44,10 @@ window.Page_sitting = (() => {
|
|||
function _render() {
|
||||
_container.innerHTML = `
|
||||
<div class="sitting-tabs" id="sit-tabs">
|
||||
<button class="sitting-tab active" data-sit-tab="suchen">🔍 Sitter finden</button>
|
||||
<button class="sitting-tab active" data-sit-tab="suchen">${UI.icon('magnifying-glass')} Sitter finden</button>
|
||||
${_state.user ? `
|
||||
<button class="sitting-tab" data-sit-tab="profil">👤 Mein Profil</button>
|
||||
<button class="sitting-tab" data-sit-tab="anfragen">📬 Anfragen</button>
|
||||
<button class="sitting-tab" data-sit-tab="profil">${UI.icon('user')} Mein Profil</button>
|
||||
<button class="sitting-tab" data-sit-tab="anfragen">${UI.icon('bell')} Anfragen</button>
|
||||
` : ''}
|
||||
</div>
|
||||
<div id="sit-content" class="sitting-content"></div>
|
||||
|
|
@ -95,7 +95,7 @@ window.Page_sitting = (() => {
|
|||
// ---- Tab: Sitter suchen ----
|
||||
function _renderSuchen(el) {
|
||||
if (!_sitters.length) {
|
||||
el.innerHTML = UI.emptyState({ icon: '🐕', title: 'Keine Sitter', text: 'Noch keine Sitter in deiner Nähe registriert.' });
|
||||
el.innerHTML = UI.emptyState({ icon: 'dog', title: 'Keine Sitter', text: 'Noch keine Sitter in deiner Nähe registriert.' });
|
||||
return;
|
||||
}
|
||||
el.innerHTML = `
|
||||
|
|
@ -115,10 +115,10 @@ window.Page_sitting = (() => {
|
|||
: '';
|
||||
return `
|
||||
<div class="sitting-card" data-sit-id="${s.id}">
|
||||
<div class="sitting-card-avatar">🐾</div>
|
||||
<div class="sitting-card-avatar">${UI.icon('paw-print')}</div>
|
||||
<div class="sitting-card-body">
|
||||
<div class="sitting-card-name">${UI.escHtml(s.sitter_name)}</div>
|
||||
${dist ? `<div class="sitting-card-dist">📍 ${dist} entfernt</div>` : ''}
|
||||
${dist ? `<div class="sitting-card-dist">${UI.icon('map-pin')} ${dist} entfernt</div>` : ''}
|
||||
${s.beschreibung ? `<div class="sitting-card-desc">${UI.escHtml(s.beschreibung)}</div>` : ''}
|
||||
<div class="sitting-services">${svcs}</div>
|
||||
</div>
|
||||
|
|
@ -135,7 +135,7 @@ window.Page_sitting = (() => {
|
|||
if (!_mySitter) {
|
||||
el.innerHTML = `
|
||||
<div class="sitting-empty-profil">
|
||||
<div style="font-size:3rem">🐾</div>
|
||||
<div style="font-size:3rem">${UI.icon('paw-print')}</div>
|
||||
<h3>Werde Hundesitter</h3>
|
||||
<p>Biete anderen Hundebesitzern deine Dienste an und verdiene etwas dazu.</p>
|
||||
<button class="btn btn-primary" id="sit-create-profil-btn">Profil erstellen</button>
|
||||
|
|
@ -149,9 +149,9 @@ window.Page_sitting = (() => {
|
|||
<div class="sitting-my-profil">
|
||||
<div class="sitting-profil-header">
|
||||
<div class="sitting-profil-status ${s.aktiv ? 'active' : 'inactive'}">
|
||||
${s.aktiv ? '✅ Aktiv' : '⏸️ Pausiert'}
|
||||
${s.aktiv ? `${UI.icon('check')} Aktiv` : 'Pausiert'}
|
||||
</div>
|
||||
<button class="btn btn-secondary btn-sm" id="sit-edit-profil-btn">✏️ Bearbeiten</button>
|
||||
<button class="btn btn-secondary btn-sm" id="sit-edit-profil-btn">${UI.icon('pencil-simple')} Bearbeiten</button>
|
||||
</div>
|
||||
${s.beschreibung ? `<p>${UI.escHtml(s.beschreibung)}</p>` : ''}
|
||||
<div class="sitting-profil-facts">
|
||||
|
|
@ -172,17 +172,17 @@ window.Page_sitting = (() => {
|
|||
let html = '';
|
||||
|
||||
if (inbox.length) {
|
||||
html += `<div class="sitting-section-label">📬 Eingehende Anfragen (als Sitter)</div>`;
|
||||
html += `<div class="sitting-section-label">${UI.icon('bell')} Eingehende Anfragen (als Sitter)</div>`;
|
||||
html += inbox.map(r => _requestCardHTML(r, 'inbox')).join('');
|
||||
}
|
||||
|
||||
if (myReqs.length) {
|
||||
html += `<div class="sitting-section-label" style="margin-top:var(--space-4)">📤 Meine Anfragen</div>`;
|
||||
html += `<div class="sitting-section-label" style="margin-top:var(--space-4)">${UI.icon('upload')} Meine Anfragen</div>`;
|
||||
html += myReqs.map(r => _requestCardHTML(r, 'sent')).join('');
|
||||
}
|
||||
|
||||
if (!inbox.length && !myReqs.length) {
|
||||
html = UI.emptyState({ icon: '📬', title: 'Keine Anfragen', text: 'Noch keine Sitting-Anfragen vorhanden.' });
|
||||
html = UI.emptyState({ icon: 'bell', title: 'Keine Anfragen', text: 'Noch keine Sitting-Anfragen vorhanden.' });
|
||||
}
|
||||
|
||||
el.innerHTML = html;
|
||||
|
|
@ -198,7 +198,7 @@ window.Page_sitting = (() => {
|
|||
<span class="sitting-req-name">${UI.escHtml(name || '?')}</span>
|
||||
<span class="sitting-req-status" style="color:${color}">${r.status}</span>
|
||||
</div>
|
||||
<div class="sitting-req-dates">📅 ${r.von} – ${r.bis}</div>
|
||||
<div class="sitting-req-dates">${UI.icon('calendar-dots')} ${r.von} – ${r.bis}</div>
|
||||
${r.nachricht ? `<div class="sitting-req-msg">${UI.escHtml(r.nachricht)}</div>` : ''}
|
||||
${r.status === 'offen' ? _requestActions(r.id, mode) : ''}
|
||||
</div>
|
||||
|
|
@ -209,14 +209,14 @@ window.Page_sitting = (() => {
|
|||
if (mode === 'inbox') {
|
||||
return `
|
||||
<div class="sitting-req-actions">
|
||||
<button class="btn btn-primary btn-sm" data-sit-accept="${id}">✅ Annehmen</button>
|
||||
<button class="btn btn-danger btn-sm" data-sit-decline="${id}">❌ Ablehnen</button>
|
||||
<button class="btn btn-primary btn-sm" data-sit-accept="${id}">${UI.icon('check')} Annehmen</button>
|
||||
<button class="btn btn-danger btn-sm" data-sit-decline="${id}">${UI.icon('x')} Ablehnen</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return `
|
||||
<div class="sitting-req-actions">
|
||||
<button class="btn btn-secondary btn-sm" data-sit-cancel="${id}">🚫 Abbrechen</button>
|
||||
<button class="btn btn-secondary btn-sm" data-sit-cancel="${id}">${UI.icon('x')} Abbrechen</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
|
@ -236,9 +236,9 @@ window.Page_sitting = (() => {
|
|||
: null;
|
||||
|
||||
const body = `
|
||||
<div class="sitting-detail-avatar">🐾</div>
|
||||
<div class="sitting-detail-avatar">${UI.icon('paw-print')}</div>
|
||||
<h3 style="margin:var(--space-2) 0">${UI.escHtml(s.sitter_name)}</h3>
|
||||
${dist ? `<div style="color:var(--c-text-secondary);margin-bottom:var(--space-2)">📍 ${dist} entfernt</div>` : ''}
|
||||
${dist ? `<div style="color:var(--c-text-secondary);margin-bottom:var(--space-2)">${UI.icon('map-pin')} ${dist} entfernt</div>` : ''}
|
||||
${s.beschreibung ? `<p>${UI.escHtml(s.beschreibung)}</p>` : ''}
|
||||
<div class="sitting-services" style="margin:var(--space-3) 0">${svcs}</div>
|
||||
<div class="sitting-profil-facts">
|
||||
|
|
@ -249,7 +249,7 @@ window.Page_sitting = (() => {
|
|||
`;
|
||||
|
||||
const footer = _state.user && _mySitter?.user_id !== s.user_id ? `
|
||||
<button class="btn btn-primary" id="sit-anfrage-btn">📬 Anfrage senden</button>
|
||||
<button class="btn btn-primary" id="sit-anfrage-btn">${UI.icon('bell')} Anfrage senden</button>
|
||||
` : (!_state.user ? `<span style="color:var(--c-text-secondary)">Zum Anfragen bitte einloggen.</span>` : '');
|
||||
|
||||
UI.modal.open({ title: 'Sitter-Profil', body, footer });
|
||||
|
|
@ -368,7 +368,7 @@ window.Page_sitting = (() => {
|
|||
<input class="form-control" type="number" step="any" name="lon" id="sit-lon" value="${s?.lon || ''}">
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-secondary btn-sm" id="sit-gps-btn">📍 Meine Position</button>
|
||||
<button type="button" class="btn btn-secondary btn-sm" id="sit-gps-btn">${UI.icon('map-pin')} Meine Position</button>
|
||||
<div class="form-group" style="margin-top:var(--space-3)">
|
||||
<label class="form-label">Umkreis (km)</label>
|
||||
<input class="form-control" type="number" min="1" max="100" name="radius_km" value="${s?.radius_km ?? 20}">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue