refactor(itinerary): replace anchor-based positioning with day/sortOrder
Replace complex anchor system (anchorType, anchorId, anchorDay) with simple (day: Int, sortOrder: Double) positioning for custom items. Changes: - CustomItineraryItem: Remove anchor fields, add day and sortOrder - CKModels: Add migration fallback from old CloudKit fields - ItineraryTableViewController: Add calculateSortOrder() for midpoint insertion - TripDetailView: Simplify callbacks, itinerarySections, and routeWaypoints - AddItemSheet: Take simple day parameter instead of anchor - SavedTrip: Update LocalCustomItem SwiftData model Benefits: - Items freely movable via drag-and-drop - Route waypoints follow exact visual order - Simpler mental model: position = (day, sortOrder) - Midpoint insertion allows unlimited reordering Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -55,10 +55,8 @@ actor CustomItemService {
|
||||
let now = Date()
|
||||
existingRecord[CKCustomItineraryItem.categoryKey] = item.category.rawValue
|
||||
existingRecord[CKCustomItineraryItem.titleKey] = item.title
|
||||
existingRecord[CKCustomItineraryItem.anchorTypeKey] = item.anchorType.rawValue
|
||||
existingRecord[CKCustomItineraryItem.anchorIdKey] = item.anchorId
|
||||
existingRecord[CKCustomItineraryItem.anchorDayKey] = item.anchorDay
|
||||
existingRecord[CKCustomItineraryItem.sortOrderKey] = item.sortOrder
|
||||
existingRecord[CKCustomItineraryItem.dayKey] = item.day
|
||||
existingRecord[CKCustomItineraryItem.sortOrderDoubleKey] = item.sortOrder
|
||||
existingRecord[CKCustomItineraryItem.modifiedAtKey] = now
|
||||
// Location fields (nil values clear the field in CloudKit)
|
||||
existingRecord[CKCustomItineraryItem.latitudeKey] = item.latitude
|
||||
@@ -77,16 +75,16 @@ actor CustomItemService {
|
||||
}
|
||||
}
|
||||
|
||||
/// Batch update sortOrder for multiple items (for reordering)
|
||||
/// Batch update day+sortOrder for multiple items (for reordering)
|
||||
func updateSortOrders(_ items: [CustomItineraryItem]) async throws {
|
||||
guard !items.isEmpty else { return }
|
||||
print("☁️ [CloudKit] Batch updating sortOrder for \(items.count) items")
|
||||
print("☁️ [CloudKit] Batch updating day+sortOrder for \(items.count) items")
|
||||
|
||||
// Fetch all records
|
||||
let recordIDs = items.map { CKRecord.ID(recordName: $0.id.uuidString) }
|
||||
let fetchResults = try await publicDatabase.records(for: recordIDs)
|
||||
|
||||
// Update each record's sortOrder
|
||||
// Update each record's day and sortOrder
|
||||
var recordsToSave: [CKRecord] = []
|
||||
let now = Date()
|
||||
|
||||
@@ -94,7 +92,8 @@ actor CustomItemService {
|
||||
let recordID = CKRecord.ID(recordName: item.id.uuidString)
|
||||
guard case .success(let record) = fetchResults[recordID] else { continue }
|
||||
|
||||
record[CKCustomItineraryItem.sortOrderKey] = item.sortOrder
|
||||
record[CKCustomItineraryItem.dayKey] = item.day
|
||||
record[CKCustomItineraryItem.sortOrderDoubleKey] = item.sortOrder
|
||||
record[CKCustomItineraryItem.modifiedAtKey] = now
|
||||
recordsToSave.append(record)
|
||||
}
|
||||
@@ -107,7 +106,7 @@ actor CustomItemService {
|
||||
modifyOp.modifyRecordsResultBlock = { result in
|
||||
switch result {
|
||||
case .success:
|
||||
print("☁️ [CloudKit] Batch sortOrder update complete")
|
||||
print("☁️ [CloudKit] Batch day+sortOrder update complete")
|
||||
continuation.resume()
|
||||
case .failure(let error):
|
||||
print("☁️ [CloudKit] Batch update failed: \(error)")
|
||||
@@ -156,7 +155,7 @@ actor CustomItemService {
|
||||
print("☁️ [CloudKit] Failed to parse record: \(record.recordID.recordName)")
|
||||
}
|
||||
return item
|
||||
}.sorted { ($0.anchorDay, $0.sortOrder) < ($1.anchorDay, $1.sortOrder) }
|
||||
}.sorted { ($0.day, $0.sortOrder) < ($1.day, $1.sortOrder) }
|
||||
|
||||
print("☁️ [CloudKit] Parsed \(items.count) valid items")
|
||||
return items
|
||||
|
||||
Reference in New Issue
Block a user