Integrate self-hosted PostHog (SPM) with AnalyticsManager singleton wrapping all SDK calls. Adds ~40 type-safe events covering trip planning, schedule, progress, IAP, settings, polls, export, and share flows. Includes session replay, autocapture, network telemetry, privacy opt-out toggle in Settings, and super properties (app version, device, pro status, selected sports). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
79 lines
2.0 KiB
Swift
79 lines
2.0 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)
|
|
AnalyticsManager.shared.track(.pollCreated(optionCount: selectedTrips.count))
|
|
} 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
|
|
}
|
|
}
|