mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
feat: collapse days hides map markers, Immich test-before-save (#216)
Map markers: - Collapsing a day in the sidebar hides its places from the map - Places assigned to multiple days only hide when all days collapsed - Unplanned places always stay visible Immich settings: - New POST /integrations/immich/test endpoint validates credentials without saving them - Save button disabled until test connection passes - Changing URL or API key resets test status - i18n: testFirst key for all 12 languages
This commit is contained in:
@@ -157,13 +157,36 @@ export default function TripPlannerPage(): React.ReactElement | null {
|
||||
|
||||
const [mapCategoryFilter, setMapCategoryFilter] = useState<string>('')
|
||||
|
||||
const [expandedDayIds, setExpandedDayIds] = useState<Set<number> | null>(null)
|
||||
|
||||
const mapPlaces = useMemo(() => {
|
||||
// Build set of place IDs assigned to collapsed days
|
||||
const hiddenPlaceIds = new Set<number>()
|
||||
if (expandedDayIds) {
|
||||
for (const [dayId, dayAssignments] of Object.entries(assignments)) {
|
||||
if (!expandedDayIds.has(Number(dayId))) {
|
||||
for (const a of dayAssignments) {
|
||||
if (a.place?.id) hiddenPlaceIds.add(a.place.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Don't hide places that are also assigned to an expanded day
|
||||
for (const [dayId, dayAssignments] of Object.entries(assignments)) {
|
||||
if (expandedDayIds.has(Number(dayId))) {
|
||||
for (const a of dayAssignments) {
|
||||
hiddenPlaceIds.delete(a.place?.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return places.filter(p => {
|
||||
if (!p.lat || !p.lng) return false
|
||||
if (mapCategoryFilter && String(p.category_id) !== String(mapCategoryFilter)) return false
|
||||
if (hiddenPlaceIds.has(p.id)) return false
|
||||
return true
|
||||
})
|
||||
}, [places, mapCategoryFilter])
|
||||
}, [places, mapCategoryFilter, assignments, expandedDayIds])
|
||||
|
||||
const { route, routeSegments, routeInfo, setRoute, setRouteInfo, updateRouteForDay } = useRouteCalculation({ assignments } as any, selectedDayId)
|
||||
|
||||
@@ -526,6 +549,7 @@ export default function TripPlannerPage(): React.ReactElement | null {
|
||||
onDeletePlace={(placeId) => handleDeletePlace(placeId)}
|
||||
accommodations={tripAccommodations}
|
||||
onNavigateToFiles={() => handleTabChange('dateien')}
|
||||
onExpandedDaysChange={setExpandedDayIds}
|
||||
/>
|
||||
{!leftCollapsed && (
|
||||
<div
|
||||
@@ -738,7 +762,7 @@ export default function TripPlannerPage(): React.ReactElement | null {
|
||||
</div>
|
||||
<div style={{ flex: 1, overflow: 'auto' }}>
|
||||
{mobileSidebarOpen === 'left'
|
||||
? <DayPlanSidebar tripId={tripId} trip={trip} days={days} places={places} categories={categories} assignments={assignments} selectedDayId={selectedDayId} selectedPlaceId={selectedPlaceId} selectedAssignmentId={selectedAssignmentId} onSelectDay={(id) => { handleSelectDay(id); setMobileSidebarOpen(null) }} onPlaceClick={(placeId, assignmentId) => { handlePlaceClick(placeId, assignmentId); setMobileSidebarOpen(null) }} onReorder={handleReorder} onUpdateDayTitle={handleUpdateDayTitle} onAssignToDay={handleAssignToDay} onRouteCalculated={(r) => { if (r) { setRoute(r.coordinates); setRouteInfo({ distance: r.distanceText, duration: r.durationText }) } }} reservations={reservations} onAddReservation={(dayId) => { setEditingReservation(null); tripActions.setSelectedDay(dayId); setShowReservationModal(true); setMobileSidebarOpen(null) }} onDayDetail={(day) => { setShowDayDetail(day); setSelectedPlaceId(null); setSelectedAssignmentId(null); setMobileSidebarOpen(null) }} accommodations={tripAccommodations} onNavigateToFiles={() => { setMobileSidebarOpen(null); handleTabChange('dateien') }} />
|
||||
? <DayPlanSidebar tripId={tripId} trip={trip} days={days} places={places} categories={categories} assignments={assignments} selectedDayId={selectedDayId} selectedPlaceId={selectedPlaceId} selectedAssignmentId={selectedAssignmentId} onSelectDay={(id) => { handleSelectDay(id); setMobileSidebarOpen(null) }} onPlaceClick={(placeId, assignmentId) => { handlePlaceClick(placeId, assignmentId); setMobileSidebarOpen(null) }} onReorder={handleReorder} onUpdateDayTitle={handleUpdateDayTitle} onAssignToDay={handleAssignToDay} onRouteCalculated={(r) => { if (r) { setRoute(r.coordinates); setRouteInfo({ distance: r.distanceText, duration: r.durationText }) } }} reservations={reservations} onAddReservation={(dayId) => { setEditingReservation(null); tripActions.setSelectedDay(dayId); setShowReservationModal(true); setMobileSidebarOpen(null) }} onDayDetail={(day) => { setShowDayDetail(day); setSelectedPlaceId(null); setSelectedAssignmentId(null); setMobileSidebarOpen(null) }} accommodations={tripAccommodations} onNavigateToFiles={() => { setMobileSidebarOpen(null); handleTabChange('dateien') }} onExpandedDaysChange={setExpandedDayIds} />
|
||||
: <PlacesSidebar tripId={tripId} places={places} categories={categories} assignments={assignments} selectedDayId={selectedDayId} selectedPlaceId={selectedPlaceId} onPlaceClick={(placeId) => { handlePlaceClick(placeId); setMobileSidebarOpen(null) }} onAddPlace={() => { setEditingPlace(null); setShowPlaceForm(true); setMobileSidebarOpen(null) }} onAssignToDay={handleAssignToDay} onEditPlace={(place) => { setEditingPlace(place); setEditingAssignmentId(null); setShowPlaceForm(true); setMobileSidebarOpen(null) }} onDeletePlace={(placeId) => handleDeletePlace(placeId)} days={days} isMobile onCategoryFilterChange={setMapCategoryFilter} />
|
||||
}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user