You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
PadelClub/PadelClub/Data/Club.swift

226 lines
6.5 KiB

//
// Club.swift
// PadelClub
//
// Created by Laurent Morvillier on 02/02/2024.
//
import Foundation
import SwiftUI
import LeStorage
@Observable
class Club : ModelObject, Storable, Hashable {
static func resourceName() -> String { return "clubs" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [.get] }
static func == (lhs: Club, rhs: Club) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
return hasher.combine(id)
}
var id: String = Store.randomId()
var creator: String?
var name: String
var acronym: String
var phone: String?
var code: String?
//var federalClubData: Data?
var address: String?
var city: String?
var zipCode: String?
var latitude: Double?
var longitude: Double?
var courtCount: Int = 2
// var alphabeticalName: Bool = false
internal init(creator: String? = nil, name: String, acronym: String? = nil, phone: String? = nil, code: String? = nil, address: String? = nil, city: String? = nil, zipCode: String? = nil, latitude: Double? = nil, longitude: Double? = nil, courtCount: Int = 2) {
self.creator = creator
self.name = name
self.acronym = acronym ?? name.acronym()
self.phone = phone
self.code = code
self.address = address
self.city = city
self.zipCode = zipCode
self.latitude = latitude
self.longitude = longitude
self.courtCount = courtCount
}
func clubTitle(_ displayStyle: DisplayStyle = .wide) -> String {
switch displayStyle {
case .wide:
return name
case .short:
return acronym
}
}
func shareURL() -> URL? {
return URLs.main.url.appending(path: "?club=\(id)")
}
var customizedCourts: [Court] {
Store.main.filter { $0.club == self.id }.sorted(by: \.index)
}
override func deleteDependencies() throws {
try Store.main.deleteDependencies(items: self.customizedCourts)
}
enum CodingKeys: String, CodingKey {
case _id = "id"
case _creator = "creator"
case _name = "name"
case _acronym = "acronym"
case _phone = "phone"
case _code = "code"
case _address = "address"
case _city = "city"
case _zipCode = "zipCode"
case _latitude = "latitude"
case _longitude = "longitude"
case _courtCount = "courtCount"
// case _alphabeticalName = "alphabeticalName"
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: ._id)
if let creator = creator {
try container.encode(creator, forKey: ._creator)
} else {
try container.encodeNil(forKey: ._creator)
}
try container.encode(name, forKey: ._name)
try container.encode(acronym, forKey: ._acronym)
if let phone = phone {
try container.encode(phone, forKey: ._phone)
} else {
try container.encodeNil(forKey: ._phone)
}
if let code = code {
try container.encode(code, forKey: ._code)
} else {
try container.encodeNil(forKey: ._code)
}
if let address = address {
try container.encode(address, forKey: ._address)
} else {
try container.encodeNil(forKey: ._address)
}
if let city = city {
try container.encode(city, forKey: ._city)
} else {
try container.encodeNil(forKey: ._city)
}
if let zipCode = zipCode {
try container.encode(zipCode, forKey: ._zipCode)
} else {
try container.encodeNil(forKey: ._zipCode)
}
if let latitude = latitude {
try container.encode(latitude, forKey: ._latitude)
} else {
try container.encodeNil(forKey: ._latitude)
}
if let longitude = longitude {
try container.encode(longitude, forKey: ._longitude)
} else {
try container.encodeNil(forKey: ._longitude)
}
try container.encode(courtCount, forKey: ._courtCount)
// try container.encode(alphabeticalName, forKey: ._alphabeticalName)
}
}
extension Club {
var isValid: Bool {
name.isEmpty == false && acronym.isEmpty == false
}
func automaticShortName() -> String {
name.acronym()
}
enum AcronymMode: String, CaseIterable {
case automatic = "Automatique"
case custom = "Personalisée"
}
func shortNameMode() -> AcronymMode {
(acronym.isEmpty || acronym == automaticShortName()) ? .automatic : .custom
}
func hasTenupId() -> Bool {
code != nil
}
func federalLink() -> URL? {
guard let code else { return nil }
return URL(string: "https://tenup.fft.fr/club/\(code)")
}
func courtName(atIndex courtIndex: Int) -> String {
courtNameIfAvailable(atIndex: courtIndex) ?? Court.courtIndexedTitle(atIndex: courtIndex)
}
func courtNameIfAvailable(atIndex courtIndex: Int) -> String? {
customizedCourts.first(where: { $0.index == courtIndex })?.name
}
func update(fromClub club: Club) {
self.acronym = club.acronym
self.name = club.name
self.phone = club.phone
self.code = club.code
self.address = club.address
self.city = club.city
self.zipCode = club.zipCode
self.latitude = club.latitude
self.longitude = club.longitude
}
func hasBeenCreated(by creatorId: String?) -> Bool {
guard let creatorId else { return false }
guard let creator else { return false }
return creatorId == creator
}
func isFavorite() -> Bool {
return DataStore.shared.user.clubs.contains(where: { $0 == id })
}
static func findOrCreate(name: String, code: String?, city: String? = nil, zipCode: String? = nil) -> Club {
/*
identify a club : code, name, ??
*/
let clubs: [Club] = Store.main.filter(isIncluded: { (code == nil && $0.name == name && $0.city == city && $0.zipCode == zipCode) || $0.code == code })
if clubs.isEmpty == false {
return clubs.first!
} else {
return Club(creator: DataStore.shared.user.id, name: name, code: code)
}
}
}