/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ interface DragDataPayload { placeId?: string; assignmentId?: string; noteId?: string; reservationId?: string; fromDayId?: string; phase?: 'single' | 'start' | 'middle' | 'end' } declare global { interface Window { __dragData: DragDataPayload | null } } import React, { useState, useEffect, useRef, useMemo } from 'react' import ReactDOM from 'react-dom' import { ChevronDown, ChevronRight, ChevronUp, ChevronsDownUp, ChevronsUpDown, Navigation, RotateCcw, ExternalLink, Clock, Pencil, GripVertical, Ticket, Plus, FileText, Check, Trash2, Info, MapPin, Star, Heart, Camera, Lightbulb, Flag, Bookmark, Train, Bus, Plane, Car, Ship, Coffee, ShoppingBag, AlertTriangle, FileDown, Lock, Hotel, Utensils, Users, Undo2, X, Route as RouteIcon } from 'lucide-react' const RES_ICONS = { flight: Plane, hotel: Hotel, restaurant: Utensils, train: Train, car: Car, cruise: Ship, event: Ticket, tour: Users, other: FileText } import { assignmentsApi, reservationsApi } from '../../api/client' import { downloadTripPDF } from '../PDF/TripPDF' import { calculateRoute, generateGoogleMapsUrl, optimizeRoute } from '../Map/RouteCalculator' import PlaceAvatar from '../shared/PlaceAvatar' import { useContextMenu, ContextMenu } from '../shared/ContextMenu' import Markdown from 'react-markdown' import remarkGfm from 'remark-gfm' import WeatherWidget from '../Weather/WeatherWidget' import { useToast } from '../shared/Toast' import { getCategoryIcon } from '../shared/categoryIcons' import { useTripStore } from '../../store/tripStore' import { useCanDo } from '../../store/permissionsStore' import { useSettingsStore } from '../../store/settingsStore' import { useTranslation } from '../../i18n' import { formatDate, formatTime, dayTotalCost, currencyDecimals } from '../../utils/formatters' import { useDayNotes } from '../../hooks/useDayNotes' import Tooltip from '../shared/Tooltip' import type { Trip, Day, Place, Category, Assignment, Reservation, AssignmentsMap, RouteResult } from '../../types' const NOTE_ICONS = [ { id: 'FileText', Icon: FileText }, { id: 'Info', Icon: Info }, { id: 'Clock', Icon: Clock }, { id: 'MapPin', Icon: MapPin }, { id: 'Navigation', Icon: Navigation }, { id: 'Train', Icon: Train }, { id: 'Plane', Icon: Plane }, { id: 'Bus', Icon: Bus }, { id: 'Car', Icon: Car }, { id: 'Ship', Icon: Ship }, { id: 'Coffee', Icon: Coffee }, { id: 'Ticket', Icon: Ticket }, { id: 'Star', Icon: Star }, { id: 'Heart', Icon: Heart }, { id: 'Camera', Icon: Camera }, { id: 'Flag', Icon: Flag }, { id: 'Lightbulb', Icon: Lightbulb }, { id: 'AlertTriangle', Icon: AlertTriangle }, { id: 'ShoppingBag', Icon: ShoppingBag }, { id: 'Bookmark', Icon: Bookmark }, ] const NOTE_ICON_MAP = Object.fromEntries(NOTE_ICONS.map(({ id, Icon }) => [id, Icon])) function getNoteIcon(iconId) { return NOTE_ICON_MAP[iconId] || FileText } const TYPE_ICONS = { flight: '✈️', hotel: '🏨', restaurant: '🍽️', train: '🚆', car: '🚗', cruise: '🚢', event: '🎫', other: '📋', } function MobileAddPlaceButton({ dayId, places, assignments, onAssign, onAddNew }: { dayId: number places: Place[] assignments: AssignmentsMap onAssign?: (placeId: number, dayId: number) => void onAddNew?: () => void }) { const { t } = useTranslation() const [open, setOpen] = useState(false) const [search, setSearch] = useState('') // Find places not assigned to this day const assignedToDay = new Set((assignments[String(dayId)] || []).map(a => a.place_id)) const available = places.filter(p => !assignedToDay.has(p.id)) const filtered = search.trim() ? available.filter(p => p.name.toLowerCase().includes(search.toLowerCase())) : available return (