Closer/iphone/Closer/Models/FirestoreModels.swift

135 lines
3.2 KiB
Swift

import Foundation
import FirebaseFirestore
struct User: Codable, Identifiable, Sendable {
let id: String
var email: String
var displayName: String
var photoUrl: String
var sex: String
var partnerId: String?
var coupleId: String?
var plan: String // "free" | "premium"
var createdAt: Date
var lastActiveAt: Date
enum CodingKeys: String, CodingKey {
case id
case email
case displayName
case photoUrl
case sex
case partnerId
case coupleId
case plan
case createdAt
case lastActiveAt
}
}
struct Couple: Codable, Identifiable, Sendable {
let id: String
var userIds: [String]
var inviteCode: String
var createdAt: Date
var currentQuestionId: String?
var streakCount: Int
var lastAnsweredAt: Date?
var activePackId: String?
// E2EE fields (optional MVP can skip)
var encryptionVersion: Int // 0=plaintext, 1=migrating, 2=strict
var wrappedCoupleKey: String?
var kdfSalt: String?
var kdfParams: String?
var encryptionMigrationUsers: [String: Bool]?
enum CodingKeys: String, CodingKey {
case id
case userIds
case inviteCode
case createdAt
case currentQuestionId
case streakCount
case lastAnsweredAt
case activePackId
case encryptionVersion
case wrappedCoupleKey
case kdfSalt
case kdfParams
case encryptionMigrationUsers
}
}
struct Invite: Codable, Identifiable, Sendable {
let id: String // = document ID (6-char code)
var code: String
var inviterUserId: String
var inviteeEmail: String?
var coupleId: String?
var status: String // "pending" | "accepted" | "expired"
var createdAt: Date
var expiresAt: Date
var acceptedAt: Date?
var acceptedByUserId: String?
// E2EE
var wrappedCoupleKey: String?
var kdfSalt: String?
var kdfParams: String?
enum CodingKeys: String, CodingKey {
case id
case code
case inviterUserId
case inviteeEmail
case coupleId
case status
case createdAt
case expiresAt
case acceptedAt
case acceptedByUserId
case wrappedCoupleKey
case kdfSalt
case kdfParams
}
}
struct Entitlement: Codable, Identifiable, Sendable {
let id: String
var userId: String
var source: String
var productId: String
var isActive: Bool
var expiresAt: Date?
var updatedAt: Date
enum CodingKeys: String, CodingKey {
case id
case userId
case source
case productId
case isActive
case expiresAt
case updatedAt
}
}
struct DailyQuestion: Codable, Identifiable, Sendable {
var id: String?
var questionId: String
var date: String // YYYY-MM-DD
var assignedAt: Date
var expiresAt: Date
}
struct DailyAnswer: Codable, Identifiable, Sendable {
var id: String? // = userId
var sealedAnswer: String? // "sealed:v1:{base64}"
var commitment: String? // "sha256:{urlsafe-base64}"
var questionType: String // "text" | "multiple_choice" | "scale"
var submittedAt: Date
}