Merge branch 'custom_ish'
This commit is contained in:
@@ -20,6 +20,7 @@ enum CKRecordType {
|
||||
static let stadiumAlias = "StadiumAlias"
|
||||
static let tripPoll = "TripPoll"
|
||||
static let pollVote = "PollVote"
|
||||
static let customItineraryItem = "CustomItineraryItem"
|
||||
}
|
||||
|
||||
// MARK: - CKTeam
|
||||
@@ -622,3 +623,74 @@ struct CKPollVote {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CKCustomItineraryItem
|
||||
|
||||
struct CKCustomItineraryItem {
|
||||
static let itemIdKey = "itemId"
|
||||
static let tripIdKey = "tripId"
|
||||
static let categoryKey = "category"
|
||||
static let titleKey = "title"
|
||||
static let anchorTypeKey = "anchorType"
|
||||
static let anchorIdKey = "anchorId"
|
||||
static let anchorDayKey = "anchorDay"
|
||||
static let sortOrderKey = "sortOrder"
|
||||
static let createdAtKey = "createdAt"
|
||||
static let modifiedAtKey = "modifiedAt"
|
||||
|
||||
let record: CKRecord
|
||||
|
||||
init(record: CKRecord) {
|
||||
self.record = record
|
||||
}
|
||||
|
||||
init(item: CustomItineraryItem) {
|
||||
let record = CKRecord(
|
||||
recordType: CKRecordType.customItineraryItem,
|
||||
recordID: CKRecord.ID(recordName: item.id.uuidString)
|
||||
)
|
||||
record[CKCustomItineraryItem.itemIdKey] = item.id.uuidString
|
||||
record[CKCustomItineraryItem.tripIdKey] = item.tripId.uuidString
|
||||
record[CKCustomItineraryItem.categoryKey] = item.category.rawValue
|
||||
record[CKCustomItineraryItem.titleKey] = item.title
|
||||
record[CKCustomItineraryItem.anchorTypeKey] = item.anchorType.rawValue
|
||||
record[CKCustomItineraryItem.anchorIdKey] = item.anchorId
|
||||
record[CKCustomItineraryItem.anchorDayKey] = item.anchorDay
|
||||
record[CKCustomItineraryItem.sortOrderKey] = item.sortOrder
|
||||
record[CKCustomItineraryItem.createdAtKey] = item.createdAt
|
||||
record[CKCustomItineraryItem.modifiedAtKey] = item.modifiedAt
|
||||
self.record = record
|
||||
}
|
||||
|
||||
func toItem() -> CustomItineraryItem? {
|
||||
guard let itemIdString = record[CKCustomItineraryItem.itemIdKey] as? String,
|
||||
let itemId = UUID(uuidString: itemIdString),
|
||||
let tripIdString = record[CKCustomItineraryItem.tripIdKey] as? String,
|
||||
let tripId = UUID(uuidString: tripIdString),
|
||||
let categoryString = record[CKCustomItineraryItem.categoryKey] as? String,
|
||||
let category = CustomItineraryItem.ItemCategory(rawValue: categoryString),
|
||||
let title = record[CKCustomItineraryItem.titleKey] as? String,
|
||||
let anchorTypeString = record[CKCustomItineraryItem.anchorTypeKey] as? String,
|
||||
let anchorType = CustomItineraryItem.AnchorType(rawValue: anchorTypeString),
|
||||
let anchorDay = record[CKCustomItineraryItem.anchorDayKey] as? Int,
|
||||
let createdAt = record[CKCustomItineraryItem.createdAtKey] as? Date,
|
||||
let modifiedAt = record[CKCustomItineraryItem.modifiedAtKey] as? Date
|
||||
else { return nil }
|
||||
|
||||
let anchorId = record[CKCustomItineraryItem.anchorIdKey] as? String
|
||||
let sortOrder = record[CKCustomItineraryItem.sortOrderKey] as? Int ?? 0
|
||||
|
||||
return CustomItineraryItem(
|
||||
id: itemId,
|
||||
tripId: tripId,
|
||||
category: category,
|
||||
title: title,
|
||||
anchorType: anchorType,
|
||||
anchorId: anchorId,
|
||||
anchorDay: anchorDay,
|
||||
sortOrder: sortOrder,
|
||||
createdAt: createdAt,
|
||||
modifiedAt: modifiedAt
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
83
SportsTime/Core/Models/Domain/CustomItineraryItem.swift
Normal file
83
SportsTime/Core/Models/Domain/CustomItineraryItem.swift
Normal file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// CustomItineraryItem.swift
|
||||
// SportsTime
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct CustomItineraryItem: Identifiable, Codable, Hashable {
|
||||
let id: UUID
|
||||
let tripId: UUID
|
||||
var category: ItemCategory
|
||||
var title: String
|
||||
var anchorType: AnchorType
|
||||
var anchorId: String?
|
||||
var anchorDay: Int
|
||||
var sortOrder: Int // For ordering within same anchor position
|
||||
let createdAt: Date
|
||||
var modifiedAt: Date
|
||||
|
||||
init(
|
||||
id: UUID = UUID(),
|
||||
tripId: UUID,
|
||||
category: ItemCategory,
|
||||
title: String,
|
||||
anchorType: AnchorType = .startOfDay,
|
||||
anchorId: String? = nil,
|
||||
anchorDay: Int,
|
||||
sortOrder: Int = 0,
|
||||
createdAt: Date = Date(),
|
||||
modifiedAt: Date = Date()
|
||||
) {
|
||||
self.id = id
|
||||
self.tripId = tripId
|
||||
self.category = category
|
||||
self.title = title
|
||||
self.anchorType = anchorType
|
||||
self.anchorId = anchorId
|
||||
self.anchorDay = anchorDay
|
||||
self.sortOrder = sortOrder
|
||||
self.createdAt = createdAt
|
||||
self.modifiedAt = modifiedAt
|
||||
}
|
||||
|
||||
enum ItemCategory: String, Codable, CaseIterable {
|
||||
case restaurant
|
||||
case hotel
|
||||
case activity
|
||||
case note
|
||||
|
||||
var icon: String {
|
||||
switch self {
|
||||
case .restaurant: return "🍽️"
|
||||
case .hotel: return "🏨"
|
||||
case .activity: return "🎯"
|
||||
case .note: return "📝"
|
||||
}
|
||||
}
|
||||
|
||||
var label: String {
|
||||
switch self {
|
||||
case .restaurant: return "Restaurant"
|
||||
case .hotel: return "Hotel"
|
||||
case .activity: return "Activity"
|
||||
case .note: return "Note"
|
||||
}
|
||||
}
|
||||
|
||||
var systemImage: String {
|
||||
switch self {
|
||||
case .restaurant: return "fork.knife"
|
||||
case .hotel: return "bed.double.fill"
|
||||
case .activity: return "figure.run"
|
||||
case .note: return "note.text"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum AnchorType: String, Codable {
|
||||
case startOfDay
|
||||
case afterGame
|
||||
case afterTravel
|
||||
}
|
||||
}
|
||||
@@ -101,6 +101,79 @@ final class TripVote {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Local Custom Item (Cache)
|
||||
|
||||
@Model
|
||||
final class LocalCustomItem {
|
||||
@Attribute(.unique) var id: UUID
|
||||
var tripId: UUID
|
||||
var category: String
|
||||
var title: String
|
||||
var anchorType: String
|
||||
var anchorId: String?
|
||||
var anchorDay: Int
|
||||
var createdAt: Date
|
||||
var modifiedAt: Date
|
||||
var pendingSync: Bool // True if needs to sync to CloudKit
|
||||
|
||||
init(
|
||||
id: UUID = UUID(),
|
||||
tripId: UUID,
|
||||
category: CustomItineraryItem.ItemCategory,
|
||||
title: String,
|
||||
anchorType: CustomItineraryItem.AnchorType = .startOfDay,
|
||||
anchorId: String? = nil,
|
||||
anchorDay: Int,
|
||||
createdAt: Date = Date(),
|
||||
modifiedAt: Date = Date(),
|
||||
pendingSync: Bool = false
|
||||
) {
|
||||
self.id = id
|
||||
self.tripId = tripId
|
||||
self.category = category.rawValue
|
||||
self.title = title
|
||||
self.anchorType = anchorType.rawValue
|
||||
self.anchorId = anchorId
|
||||
self.anchorDay = anchorDay
|
||||
self.createdAt = createdAt
|
||||
self.modifiedAt = modifiedAt
|
||||
self.pendingSync = pendingSync
|
||||
}
|
||||
|
||||
var toItem: CustomItineraryItem? {
|
||||
guard let category = CustomItineraryItem.ItemCategory(rawValue: category),
|
||||
let anchorType = CustomItineraryItem.AnchorType(rawValue: anchorType)
|
||||
else { return nil }
|
||||
|
||||
return CustomItineraryItem(
|
||||
id: id,
|
||||
tripId: tripId,
|
||||
category: category,
|
||||
title: title,
|
||||
anchorType: anchorType,
|
||||
anchorId: anchorId,
|
||||
anchorDay: anchorDay,
|
||||
createdAt: createdAt,
|
||||
modifiedAt: modifiedAt
|
||||
)
|
||||
}
|
||||
|
||||
static func from(_ item: CustomItineraryItem, pendingSync: Bool = false) -> LocalCustomItem {
|
||||
LocalCustomItem(
|
||||
id: item.id,
|
||||
tripId: item.tripId,
|
||||
category: item.category,
|
||||
title: item.title,
|
||||
anchorType: item.anchorType,
|
||||
anchorId: item.anchorId,
|
||||
anchorDay: item.anchorDay,
|
||||
createdAt: item.createdAt,
|
||||
modifiedAt: item.modifiedAt,
|
||||
pendingSync: pendingSync
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - User Preferences
|
||||
|
||||
@Model
|
||||
|
||||
Reference in New Issue
Block a user