Files
Sportstime/SportsTime/Features/Trip/Views/CustomItemRow.swift
Trey t 495ef88303 feat(itinerary): add custom itinerary items with drag-to-reorder
- Add CustomItineraryItem domain model with sortOrder for ordering
- Add CKCustomItineraryItem CloudKit wrapper for persistence
- Create CustomItemService for CRUD operations
- Create CustomItemSubscriptionService for real-time sync
- Add AppDelegate for push notification handling
- Add AddItemSheet for creating/editing items
- Add CustomItemRow with drag handle
- Update TripDetailView with continuous vertical timeline
- Enable drag-to-reorder using .draggable/.dropDestination
- Add inline "Add" buttons after games and travel segments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 00:31:44 -06:00

90 lines
2.3 KiB
Swift

//
// CustomItemRow.swift
// SportsTime
//
// Row component for custom itinerary items with drag handle
//
import SwiftUI
struct CustomItemRow: View {
@Environment(\.colorScheme) private var colorScheme
let item: CustomItineraryItem
var onTap: () -> Void
var onDelete: () -> Void
// Drag handle visible - users can drag to reorder using .draggable/.dropDestination
var body: some View {
Button(action: onTap) {
HStack(spacing: 12) {
// Drag handle
Image(systemName: "line.3.horizontal")
.foregroundStyle(.tertiary)
.font(.caption)
// Category icon
Text(item.category.icon)
.font(.title3)
// Title
Text(item.title)
.font(.subheadline)
.foregroundStyle(Theme.textPrimary(colorScheme))
.lineLimit(2)
Spacer()
// Chevron to indicate tappable (tap to edit)
Image(systemName: "chevron.right")
.foregroundStyle(.tertiary)
.font(.caption)
}
.padding(.horizontal, Theme.Spacing.md)
.padding(.vertical, Theme.Spacing.sm)
.background(Theme.warmOrange.opacity(0.08))
.cornerRadius(8)
}
.buttonStyle(.plain)
.contextMenu {
Button {
onTap()
} label: {
Label("Edit", systemImage: "pencil")
}
Button(role: .destructive) {
onDelete()
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}
#Preview {
VStack {
CustomItemRow(
item: CustomItineraryItem(
tripId: UUID(),
category: .restaurant,
title: "Joe's BBQ - Best brisket in Texas!",
anchorDay: 1
),
onTap: {},
onDelete: {}
)
CustomItemRow(
item: CustomItineraryItem(
tripId: UUID(),
category: .hotel,
title: "Hilton Downtown",
anchorDay: 1
),
onTap: {},
onDelete: {}
)
}
.padding()
}