Add complete group trip polling feature allowing users to share trips
with friends for voting using Borda count scoring.
New components:
- TripPoll and PollVote domain models with share codes and rankings
- LocalTripPoll and LocalPollVote SwiftData models for persistence
- CKTripPoll and CKPollVote CloudKit record wrappers
- PollService actor for CloudKit CRUD operations and subscriptions
- PollCreation/Detail/Voting views and view models
- Deep link handling for sportstime://poll/{code} URLs
- Debug Pro status override toggle in Settings
Integration:
- HomeView shows polls section in My Trips
- SportsTimeApp registers SwiftData models and handles deep links
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
78 lines
1.9 KiB
Swift
78 lines
1.9 KiB
Swift
//
|
|
// PollCreationViewModel.swift
|
|
// SportsTime
|
|
//
|
|
// ViewModel for creating trip polls
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
|
|
@Observable
|
|
@MainActor
|
|
final class PollCreationViewModel {
|
|
var title: String = ""
|
|
var selectedTripIds: Set<UUID> = []
|
|
var isLoading = false
|
|
var error: PollError?
|
|
var createdPoll: TripPoll?
|
|
|
|
private let pollService = PollService.shared
|
|
|
|
var canCreate: Bool {
|
|
!title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
|
&& selectedTripIds.count >= 2
|
|
}
|
|
|
|
var validationMessage: String? {
|
|
if title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
|
return "Enter a title for your poll"
|
|
}
|
|
if selectedTripIds.count < 2 {
|
|
return "Select at least 2 trips to create a poll"
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func createPoll(trips: [Trip]) async {
|
|
guard canCreate else { return }
|
|
|
|
isLoading = true
|
|
error = nil
|
|
|
|
do {
|
|
let userId = try await pollService.getCurrentUserRecordID()
|
|
let selectedTrips = trips.filter { selectedTripIds.contains($0.id) }
|
|
|
|
let poll = TripPoll(
|
|
title: title.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
ownerId: userId,
|
|
tripSnapshots: selectedTrips
|
|
)
|
|
|
|
createdPoll = try await pollService.createPoll(poll)
|
|
} catch let pollError as PollError {
|
|
error = pollError
|
|
} catch {
|
|
self.error = .unknown(error)
|
|
}
|
|
|
|
isLoading = false
|
|
}
|
|
|
|
func toggleTrip(_ tripId: UUID) {
|
|
if selectedTripIds.contains(tripId) {
|
|
selectedTripIds.remove(tripId)
|
|
} else {
|
|
selectedTripIds.insert(tripId)
|
|
}
|
|
}
|
|
|
|
func reset() {
|
|
title = ""
|
|
selectedTripIds = []
|
|
error = nil
|
|
createdPoll = nil
|
|
}
|
|
}
|