WIP: map route updates and custom item drag/drop fixes (broken)
- Fixed map header not updating in ItineraryTableViewWrapper using Coordinator pattern - Added routeVersion UUID to force Map re-render when routes change - Fixed determineAnchor to scan backwards for correct anchor context - Added location support to CustomItineraryItem (lat/lng/address) - Added MapKit place search to AddItemSheet - Added extensive debug logging for route waypoint calculation Known issues: - Custom items still not routing correctly after drag/drop - Anchor type determination may still have bugs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -436,21 +436,51 @@ final class ItineraryTableViewController: UITableViewController {
|
||||
// MARK: - Helper Methods
|
||||
|
||||
private func determineAnchor(at row: Int) -> (CustomItineraryItem.AnchorType, String?) {
|
||||
if row > 0 {
|
||||
let previousItem = flatItems[row - 1]
|
||||
switch previousItem {
|
||||
// Scan backwards to find the day's context
|
||||
// Structure: travel (optional) -> dayHeader -> items
|
||||
var foundTravel: TravelSegment?
|
||||
var foundDayGames: [RichGame] = []
|
||||
|
||||
for i in stride(from: row - 1, through: 0, by: -1) {
|
||||
switch flatItems[i] {
|
||||
case .travel(let segment, _):
|
||||
// Found travel - if this is the first significant item, use afterTravel
|
||||
// But only if we haven't passed a day header yet
|
||||
if foundDayGames.isEmpty {
|
||||
foundTravel = segment
|
||||
}
|
||||
// Travel marks the boundary - stop scanning
|
||||
let travelId = "travel:\(segment.fromLocation.name.lowercased())->\(segment.toLocation.name.lowercased())"
|
||||
return (.afterTravel, travelId)
|
||||
// If the drop is right after travel (no day header between), use afterTravel
|
||||
if foundDayGames.isEmpty {
|
||||
return (.afterTravel, travelId)
|
||||
}
|
||||
// Otherwise we already passed a day header, use that context
|
||||
break
|
||||
|
||||
case .dayHeader(_, _, let games):
|
||||
// Found the day header for this section
|
||||
foundDayGames = games
|
||||
// If day has games, items dropped after should be afterGame
|
||||
if let lastGame = games.last {
|
||||
return (.afterGame, lastGame.game.id)
|
||||
}
|
||||
return (.startOfDay, nil)
|
||||
default:
|
||||
return (.startOfDay, nil)
|
||||
// No games - check if there's travel before this day
|
||||
// Continue scanning to find travel
|
||||
continue
|
||||
|
||||
case .customItem, .addButton:
|
||||
// Skip these, keep scanning backwards
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// If we found travel but no games, use afterTravel
|
||||
if let segment = foundTravel {
|
||||
let travelId = "travel:\(segment.fromLocation.name.lowercased())->\(segment.toLocation.name.lowercased())"
|
||||
return (.afterTravel, travelId)
|
||||
}
|
||||
|
||||
return (.startOfDay, nil)
|
||||
}
|
||||
|
||||
@@ -664,10 +694,29 @@ struct CustomItemRowView: View {
|
||||
Text(item.category.icon)
|
||||
.font(.title3)
|
||||
|
||||
Text(item.title)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
.lineLimit(2)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
HStack(spacing: 4) {
|
||||
Text(item.title)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Theme.textPrimary(colorScheme))
|
||||
.lineLimit(1)
|
||||
|
||||
// Map pin for mappable items
|
||||
if item.isMappable {
|
||||
Image(systemName: "mappin.circle.fill")
|
||||
.font(.caption)
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
}
|
||||
}
|
||||
|
||||
// Address subtitle for mappable items
|
||||
if let address = item.address, !address.isEmpty {
|
||||
Text(address)
|
||||
.font(.caption)
|
||||
.foregroundStyle(Theme.textMuted(colorScheme))
|
||||
.lineLimit(1)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user