Reisen: Wohnorte mit Datum, Anreise je Besuch, Umzüge in der Kilometer-Rechnung
- Wohnorte als Liste mit "seit"-Datum (Tabelle travel_homes, ersetzt den einzelnen Wohnort; Migration Schritt 5 übernimmt ihn): Reisen starten beim damals gültigen Wohnort, Wechsel zählen als Umzug, Tage am Wohnort nicht als Reisetage - "In dieser Zeit hier gewohnt" im Besuch: legt Wohnort ab Beginn und den vorherigen wieder ab Ende + 1 Tag an - Anreise je Besuch (automatisch / von zuhause / vom vorherigen Ort): Rundreisen auch mit mehreren Tagen zwischen den Orten - Fix: Besuche bleiben bearbeitbar, auch wenn eine Fotodatei fehlt; Speicherfehler erscheinen im Dialog statt verdeckt dahinter Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
56c4f38ef0
commit
1d7497bead
11 files changed
+343
-113
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import LAENDER from '../../data/laender.json';
|
||||
import CitySearch from './CitySearch.jsx';
|
||||
import { BY_CODE, CONTINENTS, continentOf, countryName, num } from './laender.js';
|
||||
import { BY_CODE, CONTINENTS, continentOf, countryName, fmtDay, num } from './laender.js';
|
||||
import { travelDays, travelRoute } from './route.js';
|
||||
|
||||
const pct = (part, total) => (total ? (part / total) * 100 : 0);
|
||||
@@ -11,7 +12,8 @@ const TOTAL_AREA = LAENDER.reduce((s, c) => s + (c.area || 0), 0);
|
||||
* Statistik: Länder (Welt und je Kontinent), Fläche, äußerste Punkte, Kilometer entlang der Zeitleiste.
|
||||
* Grundlage für "Welt": alle Länder und Gebiete der Länderdaten (world-countries).
|
||||
*/
|
||||
export default function TravelStats({ visited, cities, visits, wishes, home, onSetHome, onRemoveHome, busy, onSelectCity }) {
|
||||
export default function TravelStats({ visited, cities, visits, wishes, homes, onAddHome, onRemoveHome, busy, onSelectCity }) {
|
||||
const [since, setSince] = useState('');
|
||||
const codes = [...visited].filter((c) => BY_CODE.has(c));
|
||||
const area = codes.reduce((s, c) => s + (BY_CODE.get(c).area || 0), 0);
|
||||
const continents = CONTINENTS.map((name) => {
|
||||
@@ -30,10 +32,10 @@ export default function TravelStats({ visited, cities, visits, wishes, home, onS
|
||||
];
|
||||
|
||||
// Kilometer: Reisen ab Wohnort, Rundreisen und Ausflüge (siehe route.js)
|
||||
const route = travelRoute(visits, cities, home);
|
||||
const days = travelDays(visits);
|
||||
const route = travelRoute(visits, cities, homes);
|
||||
const days = travelDays(visits, cities, homes);
|
||||
const summary = [
|
||||
`${route.trips} ${route.trips === 1 ? 'Reise' : 'Reisen'}${home ? ` ab ${home.name}` : ''}`,
|
||||
`${route.trips} ${route.trips === 1 ? 'Reise' : 'Reisen'}${homes.length ? ' ab Wohnort' : ''}`,
|
||||
route.excursions && `${route.excursions} ${route.excursions === 1 ? 'Ausflug' : 'Ausflüge'}`,
|
||||
`${days} Reisetage`,
|
||||
].filter(Boolean).join(' · ');
|
||||
@@ -51,16 +53,30 @@ export default function TravelStats({ visited, cities, visits, wishes, home, onS
|
||||
</div>
|
||||
|
||||
<section className="stat-home" aria-labelledby="stat-wohnort">
|
||||
<h2 className="section-title" id="stat-wohnort">Wohnort</h2>
|
||||
{home ? (
|
||||
<p className="stat-home-current">
|
||||
⌂ <strong>{home.name}</strong> <small>{countryName(home.country)}</small>
|
||||
<button className="link-btn danger" type="button" disabled={busy} onClick={onRemoveHome}>Entfernen</button>
|
||||
</p>
|
||||
<h2 className="section-title" id="stat-wohnort">Wohnorte</h2>
|
||||
{homes.length ? (
|
||||
<ul className="stat-homes">
|
||||
{homes.map((h) => (
|
||||
<li key={h.id}>
|
||||
⌂ <strong>{h.name}</strong> <small>{countryName(h.country)} · {h.since ? `seit ${fmtDay(h.since)}` : 'von Anfang an'}</small>
|
||||
<button className="link-btn danger" type="button" disabled={busy} onClick={() => onRemoveHome(h)} aria-label={`Wohnort ${h.name} entfernen`}>✕</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p className="hint">Mit Wohnort zählt jede Reise als Hin- und Rückweg ab zuhause.</p>
|
||||
)}
|
||||
<CitySearch mode="home" cities={[]} onAdd={onSetHome} busy={busy} />
|
||||
<div className="stat-home-add">
|
||||
<label className="stat-home-since">
|
||||
<span>Seit</span>
|
||||
<input type="date" value={since} onChange={(e) => setSince(e.target.value)} aria-describedby="since-hint" />
|
||||
</label>
|
||||
<CitySearch mode="home" cities={[]} onAdd={async (r) => { if (await onAddHome({ ...r, since: since || null })) setSince(''); }} busy={busy} />
|
||||
</div>
|
||||
<p className="hint" id="since-hint">
|
||||
„Seit“ leer = von Anfang an. Zog man um oder wohnte länger im Ausland, einen weiteren Wohnort mit Datum eintragen –
|
||||
oder beim Besuch „In dieser Zeit hier gewohnt“ wählen.
|
||||
</p>
|
||||
{route.legs.length > 0 && (
|
||||
<details className="stat-route">
|
||||
<summary>Wie gerechnet? ({route.legs.length} Teilstrecken)</summary>
|
||||
@@ -73,7 +89,7 @@ export default function TravelStats({ visited, cities, visits, wishes, home, onS
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
{!home && <p className="hint">Ohne Wohnort fehlen Hin- und Heimwege; die Reisen werden direkt nacheinander verbunden.</p>}
|
||||
{!homes.length && <p className="hint">Ohne Wohnort fehlen Hin- und Heimwege; die Reisen werden direkt nacheinander verbunden.</p>}
|
||||
</details>
|
||||
)}
|
||||
</section>
|
||||
|
||||
Reference in new issue
Block a user