import ReactDOM from 'react-dom' import { X, MapPin, Ticket, Check } from 'lucide-react' import { filesApi } from '../../api/client' import type { Place, Reservation, Day } from '../../types' import type { FileManagerState } from './useFileManager' import { TRANSPORT_TYPES } from './FileManager.constants' import { transportIcon } from './FileManager.helpers' export function AssignModal(S: FileManagerState) { const { files, assignFileId, setAssignFileId, t, days, assignments, places, reservations, tripId, handleAssign, refreshFiles } = S return ReactDOM.createPortal(
setAssignFileId(null)}>
e.stopPropagation()}>
{t('files.assignTitle')}
{files.find(f => f.id === assignFileId)?.original_name || ''}
{t('files.noteLabel') || 'Note'}
f.id === assignFileId)?.description || ''} onBlur={e => { const val = e.target.value.trim() const file = files.find(f => f.id === assignFileId) if (file && val !== (file.description || '')) { handleAssign(file.id, { description: val } as any) } }} onKeyDown={e => { if (e.key === 'Enter') (e.target as HTMLInputElement).blur() }} style={{ width: '100%', padding: '7px 10px', fontSize: 13, borderRadius: 8, border: '1px solid var(--border-primary)', background: 'var(--bg-secondary)', color: 'var(--text-primary)', fontFamily: 'inherit', outline: 'none', }} />
{(() => { const file = files.find(f => f.id === assignFileId) if (!file) return null const assignedPlaceIds = new Set() const dayGroups: { day: Day; dayPlaces: Place[] }[] = [] for (const day of days) { const da = assignments[String(day.id)] || [] const dayPlaces = da.map(a => places.find(p => p.id === a.place?.id || p.id === a.place_id)).filter(Boolean) as Place[] if (dayPlaces.length > 0) { dayGroups.push({ day, dayPlaces }) dayPlaces.forEach(p => assignedPlaceIds.add(p.id)) } } const unassigned = places.filter(p => !assignedPlaceIds.has(p.id)) const placeBtn = (p: Place, idx: number) => { const isLinked = file.place_id === p.id || (file.linked_place_ids || []).includes(p.id) return ( ) } const placesSection = places.length > 0 && (
{t('files.assignPlace')}
{dayGroups.map(({ day, dayPlaces }) => (
{day.title || t('dayplan.dayN', { n: day.day_number })} {(() => { const badge = day.date || (day.title ? t('dayplan.dayN', { n: day.day_number }) : null) return badge ? ( {badge} ) : null })()}
{dayPlaces.map(placeBtn)}
))} {unassigned.length > 0 && (
{dayGroups.length > 0 &&
{t('files.unassigned')}
} {unassigned.map(placeBtn)}
)}
) const bookingReservations = reservations.filter(r => !TRANSPORT_TYPES.has(r.type)) const transportReservations = reservations.filter(r => TRANSPORT_TYPES.has(r.type)) const reservationBtn = (r: Reservation) => { const isLinked = file.reservation_id === r.id || (file.linked_reservation_ids || []).includes(r.id) const Icon = TRANSPORT_TYPES.has(r.type) ? transportIcon(r.type) : Ticket return ( ) } const bookingsSection = reservations.length > 0 && (
{bookingReservations.length > 0 && ( <>
{t('files.assignBooking')}
{bookingReservations.map(reservationBtn)} )} {transportReservations.length > 0 && ( <>
0 ? 4 : 0 }}> {t('files.assignTransport')}
{transportReservations.map(reservationBtn)} )}
) const hasBoth = placesSection && bookingsSection return (
{placesSection}
{hasBoth &&
} {hasBoth &&
}
{bookingsSection}
) })()}
, document.body ) }