diff --git a/src/assets/profile.png b/src/assets/profile.png new file mode 100644 index 0000000..b577a04 Binary files /dev/null and b/src/assets/profile.png differ diff --git a/src/lib/timeline/detail/EditForm.svelte b/src/lib/timeline/detail/EditForm.svelte index 6b68705..65591dd 100644 --- a/src/lib/timeline/detail/EditForm.svelte +++ b/src/lib/timeline/detail/EditForm.svelte @@ -5,6 +5,12 @@ import { getCitiesForCountry, ALL_CITIES } from '../../shared/cities.js'; import SearchInput from '../../shared/SearchInput.svelte'; import PhotoEditor from './PhotoEditor.svelte'; + import airplaneImg from '../../../assets/airplane.png'; + import trainImg from '../../../assets/train.png'; + import busImg from '../../../assets/bus.png'; + import carImg from '../../../assets/car.png'; + import shipImg from '../../../assets/ship.png'; + import walkImg from '../../../assets/walk.png'; /** * entry = null โ "new entry" mode @@ -25,6 +31,8 @@ let memo = $state(entry?.memo ?? ''); let transport = $state(entry?.transport ?? ''); + let step = $state(1); // 1 | 2 | 3 + let errors = $state({ country: '', cities: '', date: '', days: '', tripType: '', transport: '' }); @@ -34,12 +42,12 @@ } const transportOptions = [ - { value: 'flight', label: 'โ Flight' }, - { value: 'train', label: '๐ Train' }, - { value: 'bus', label: '๐ Bus' }, - { value: 'car', label: '๐ Car' }, - { value: 'ship', label: '๐ข Ship' }, - { value: 'walk', label: '๐ถ Walk' }, + { value: 'flight', label: 'Flight', img: airplaneImg }, + { value: 'train', label: 'Train', img: trainImg }, + { value: 'bus', label: 'Bus', img: busImg }, + { value: 'car', label: 'Car', img: carImg }, + { value: 'ship', label: 'Ship', img: shipImg }, + { value: 'walk', label: 'Walk', img: walkImg }, ]; const MEMO_MAX = 100; @@ -50,7 +58,6 @@ const raw = e.currentTarget.value; const words = raw.trim() === '' ? [] : raw.trim().split(/\s+/); if (words.length > MEMO_MAX) { - // keep first 100 words, preserve trailing space if user is mid-word memo = words.slice(0, MEMO_MAX).join(' '); e.currentTarget.value = memo; } else { @@ -58,7 +65,6 @@ } } - // Suggest cities โ when a country is selected show only cities from that country. let allEntries = $derived(getEntries()); let cityOptions = $derived( country.trim() @@ -78,17 +84,27 @@ cities = cities.filter(x => x !== c); } - async function save() { - clearErrors(); - let hasError = false; - if (!country.trim()) { errors.country = 'Country is required.'; hasError = true; } - if (cities.length === 0) { errors.cities = 'Add at least one city.'; hasError = true; } - if (!date) { errors.date = 'Date is required.'; hasError = true; } - if (!days || Number(days) < 1) { errors.days = 'Enter a valid number of days.'; hasError = true; } - if (!tripType) { errors.tripType = 'Select a trip type.'; hasError = true; } - if (!transport) { errors.transport = 'Select how you got there.'; hasError = true; } - if (hasError) return; + function nextStep() { + if (step === 1) { + clearErrors(); + let hasError = false; + if (!country.trim()) { errors.country = 'Country is required.'; hasError = true; } + if (cities.length === 0) { errors.cities = 'Add at least one city.'; hasError = true; } + if (!date) { errors.date = 'Date is required.'; hasError = true; } + if (!days || Number(days) < 1) { errors.days = 'Enter a valid number of days.'; hasError = true; } + if (!tripType) { errors.tripType = 'Select a trip type.'; hasError = true; } + if (!transport) { errors.transport = 'Select how you got there.'; hasError = true; } + if (hasError) return; + } + step++; + } + function prevStep() { + if (step === 1) onBack(); + else step--; + } + + async function save() { try { if (isNew) { await addEntry({ @@ -119,149 +135,162 @@ } -