This commit is contained in:
Maurice
2026-03-31 23:18:12 +02:00
2 changed files with 33 additions and 15 deletions

View File

@@ -4,11 +4,17 @@ import { useTranslation } from '../../i18n'
import CustomSelect from '../shared/CustomSelect' import CustomSelect from '../shared/CustomSelect'
const CURRENCIES = [ const CURRENCIES = [
'EUR','USD','GBP','JPY','CHF','CAD','AUD','NZD','CNY','HKD', 'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN', 'BAM', 'BBD', 'BDT', 'BGN', 'BHD',
'SGD','THB','TRY','SEK','NOK','DKK','PLN','CZK','HUF','RON', 'BIF', 'BMD', 'BND', 'BOB', 'BRL', 'BSD', 'BTN', 'BWP', 'BYN', 'BZD', 'CAD', 'CDF', 'CHF', 'CLF', 'CLP',
'BGN','HRK','ISK','RUB','UAH','BRL','MXN','ARS','CLP','COP', 'CNH', 'CNY', 'COP', 'CRC', 'CUP', 'CVE', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD', 'EGP', 'ERN', 'ETB', 'EUR',
'INR','IDR','MYR','PHP','KRW','TWD','VND','ZAR','EGP','MAD', 'FJD', 'FKP', 'FOK', 'GBP', 'GEL', 'GGP', 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ', 'GYD', 'HKD', 'HNL', 'HRK',
'NGN','KES','AED','SAR','QAR','KWD','BHD','OMR','ILS', 'HTG', 'HUF', 'IDR', 'ILS', 'IMP', 'INR', 'IQD', 'ISK', 'JEP', 'JMD', 'JOD', 'JPY', 'KES', 'KGS', 'KHR',
'KID', 'KMF', 'KRW', 'KWD', 'KYD', 'KZT', 'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA',
'MKD', 'MMK', 'MNT', 'MOP', 'MRU', 'MUR', 'MVR', 'MWK', 'MXN', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO', 'NOK',
'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', 'RSD', 'RUB', 'RWF',
'SAR', 'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP', 'SLE', 'SOS', 'SRD', 'SSP', 'STN', 'SYP', 'SZL', 'THB',
'TJS', 'TMT', 'TND', 'TOP', 'TRY', 'TTD', 'TVD', 'TWD', 'TZS', 'UAH', 'UGX', 'USD', 'UYU', 'UZS', 'VES',
'VND', 'VUV', 'WST', 'XAF', 'XCD', 'XDR', 'XOF', 'XPF', 'YER', 'ZAR', 'ZMW', 'ZWL'
] ]
const CURRENCY_OPTIONS = CURRENCIES.map(c => ({ value: c, label: c })) const CURRENCY_OPTIONS = CURRENCIES.map(c => ({ value: c, label: c }))

View File

@@ -10,6 +10,7 @@ import DemoBanner from '../components/Layout/DemoBanner'
import CurrencyWidget from '../components/Dashboard/CurrencyWidget' import CurrencyWidget from '../components/Dashboard/CurrencyWidget'
import TimezoneWidget from '../components/Dashboard/TimezoneWidget' import TimezoneWidget from '../components/Dashboard/TimezoneWidget'
import TripFormModal from '../components/Trips/TripFormModal' import TripFormModal from '../components/Trips/TripFormModal'
import ConfirmDialog from '../components/shared/ConfirmDialog'
import { useToast } from '../components/shared/Toast' import { useToast } from '../components/shared/Toast'
import { import {
Plus, Calendar, Trash2, Edit2, Map, ChevronDown, ChevronUp, Plus, Calendar, Trash2, Edit2, Map, ChevronDown, ChevronUp,
@@ -435,11 +436,11 @@ function ArchivedRow({ trip, onEdit, onUnarchive, onDelete, onClick, t, locale,
return ( return (
<div onClick={() => onClick(trip)} style={{ <div onClick={() => onClick(trip)} style={{
display: 'flex', alignItems: 'center', gap: 12, padding: '10px 16px', display: 'flex', alignItems: 'center', gap: 12, padding: '10px 16px',
borderRadius: 12, border: '1px solid #f3f4f6', background: 'white', cursor: 'pointer', borderRadius: 12, border: '1px solid var(--border-faint)', background: 'var(--bg-card)', cursor: 'pointer',
transition: 'border-color 0.12s', transition: 'border-color 0.12s',
}} }}
onMouseEnter={e => e.currentTarget.style.borderColor = '#e5e7eb'} onMouseEnter={e => e.currentTarget.style.borderColor = 'var(--border-primary)'}
onMouseLeave={e => e.currentTarget.style.borderColor = '#f3f4f6'}> onMouseLeave={e => e.currentTarget.style.borderColor = 'var(--border-faint)'}>
{/* Mini cover */} {/* Mini cover */}
<div style={{ <div style={{
width: 40, height: 40, borderRadius: 10, flexShrink: 0, width: 40, height: 40, borderRadius: 10, flexShrink: 0,
@@ -448,8 +449,8 @@ function ArchivedRow({ trip, onEdit, onUnarchive, onDelete, onClick, t, locale,
}} /> }} />
<div style={{ flex: 1, minWidth: 0 }}> <div style={{ flex: 1, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}> <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<span style={{ fontSize: 13, fontWeight: 600, color: '#6b7280', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{trip.title}</span> <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--text-muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{trip.title}</span>
{!trip.is_owner && <span style={{ fontSize: 10, color: '#9ca3af', background: '#f3f4f6', padding: '1px 6px', borderRadius: 99, flexShrink: 0 }}>{t('dashboard.shared')}</span>} {!trip.is_owner && <span style={{ fontSize: 10, color: 'var(--text-faint)', background: 'var(--bg-tertiary)', padding: '1px 6px', borderRadius: 99, flexShrink: 0 }}>{t('dashboard.shared')}</span>}
</div> </div>
{trip.start_date && ( {trip.start_date && (
<div style={{ fontSize: 11, color: '#9ca3af', marginTop: 1 }}> <div style={{ fontSize: 11, color: '#9ca3af', marginTop: 1 }}>
@@ -537,6 +538,7 @@ export default function DashboardPage(): React.ReactElement {
const [showArchived, setShowArchived] = useState<boolean>(false) const [showArchived, setShowArchived] = useState<boolean>(false)
const [showWidgetSettings, setShowWidgetSettings] = useState<boolean | 'mobile'>(false) const [showWidgetSettings, setShowWidgetSettings] = useState<boolean | 'mobile'>(false)
const [viewMode, setViewMode] = useState<'grid' | 'list'>(() => (localStorage.getItem('trek_dashboard_view') as 'grid' | 'list') || 'grid') const [viewMode, setViewMode] = useState<'grid' | 'list'>(() => (localStorage.getItem('trek_dashboard_view') as 'grid' | 'list') || 'grid')
const [deleteTrip, setDeleteTrip] = useState<DashboardTrip | null>(null)
const toggleViewMode = () => { const toggleViewMode = () => {
setViewMode(prev => { setViewMode(prev => {
@@ -606,16 +608,18 @@ export default function DashboardPage(): React.ReactElement {
} }
} }
const handleDelete = async (trip) => { const handleDelete = (trip) => setDeleteTrip(trip)
if (!confirm(t('dashboard.confirm.delete', { title: trip.title }))) return const confirmDelete = async () => {
if (!deleteTrip) return
try { try {
await tripsApi.delete(trip.id) await tripsApi.delete(deleteTrip.id)
setTrips(prev => prev.filter(t => t.id !== trip.id)) setTrips(prev => prev.filter(t => t.id !== deleteTrip.id))
setArchivedTrips(prev => prev.filter(t => t.id !== trip.id)) setArchivedTrips(prev => prev.filter(t => t.id !== deleteTrip.id))
toast.success(t('dashboard.toast.deleted')) toast.success(t('dashboard.toast.deleted'))
} catch { } catch {
toast.error(t('dashboard.toast.deleteError')) toast.error(t('dashboard.toast.deleteError'))
} }
setDeleteTrip(null)
} }
const handleArchive = async (id) => { const handleArchive = async (id) => {
@@ -904,6 +908,14 @@ export default function DashboardPage(): React.ReactElement {
onCoverUpdate={handleCoverUpdate} onCoverUpdate={handleCoverUpdate}
/> />
<ConfirmDialog
isOpen={!!deleteTrip}
onClose={() => setDeleteTrip(null)}
onConfirm={confirmDelete}
title={t('common.delete')}
message={t('dashboard.confirm.delete', { title: deleteTrip?.title || '' })}
/>
<style>{` <style>{`
@keyframes pulse { @keyframes pulse {
0%, 100% { opacity: 1 } 0%, 100% { opacity: 1 }