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/Views/Cashier/CashierDetailView.swift

189 lines
6.2 KiB

//
// CashierDetailView.swift
// Padel Tournament
//
// Created by Razmig Sarkissian on 31/03/2024.
//
import SwiftUI
struct CashierDetailView: View {
var tournaments : [Tournament]
@State private var earnings: Double? = nil
@State private var paidCompletion: Double? = nil
init(tournaments: [Tournament]) {
self.tournaments = tournaments
}
init(tournament: Tournament) {
self.tournaments = [tournament]
}
var body: some View {
List {
if tournaments.count > 1 {
Section {
LabeledContent {
if let earnings {
Text(earnings.formatted(.currency(code: Locale.defaultCurrency()).precision(.fractionLength(0))))
} else {
ProgressView()
}
} label: {
Text("Encaissement")
if let paidCompletion {
Text(paidCompletion.formatted(.percent.precision(.fractionLength(0)))).foregroundStyle(.secondary)
}
}
_tournamentsCashierDetailView(tournaments)
} header: {
Text("Bilan")
}
}
ForEach(tournaments) { tournament in
CashierSectionView(tournament: tournament, showTournamentTitle: tournaments.count > 1)
}
}
.headerProminence(.increased)
.onAppear {
Task {
if earnings == nil {
_getEarnings()
}
if paidCompletion == nil {
_getPaidCompletion()
}
}
}
}
private func _getEarnings() {
earnings = tournaments.map { $0.earnings() }.reduce(0,+)
}
private func _getPaidCompletion() {
let selectedPlayers = tournaments.flatMap { $0.selectedPlayers() }
if selectedPlayers.isEmpty {
paidCompletion = 0
} else {
paidCompletion = Double(selectedPlayers.filter { $0.hasPaid() }.count) / Double(selectedPlayers.count)
}
}
private func _tournamentsCashierDetailView(_ tournaments: [Tournament]) -> some View {
DisclosureGroup {
ForEach(PlayerPaymentType.allCases) { type in
PaymentTypeCashierRowView(tournaments: tournaments, type: type)
}
} label: {
Text("Voir le détail")
}
}
struct CashierSectionView: View {
let tournament: Tournament
let showTournamentTitle: Bool
@State private var earnings: Double? = nil
@State private var paidCompletion: Double? = nil
@State private var presence: Double? = nil
var body: some View {
Section {
LabeledContent {
if let earnings {
Text(earnings.formatted(.currency(code: Locale.defaultCurrency()).precision(.fractionLength(0))))
} else {
ProgressView()
}
} label: {
Text(tournament.isFree() ? "Présence" : "Encaissement")
if tournament.isFree() {
if let presence {
Text(presence.formatted(.percent.precision(.fractionLength(0)))).foregroundStyle(.secondary)
}
} else {
if let paidCompletion {
Text(paidCompletion.formatted(.percent.precision(.fractionLength(0)))).foregroundStyle(.secondary)
}
}
}
CashierDetailDisclosureView(tournament: tournament)
} header: {
if showTournamentTitle {
Text(tournament.tournamentTitle())
}
}
.onAppear {
Task {
if earnings == nil {
earnings = tournament.earnings()
}
if paidCompletion == nil {
paidCompletion = tournament.paidCompletion()
}
if presence == nil {
presence = tournament.presenceStatus()
}
}
}
}
}
struct PaymentTypeCashierRowView: View {
let tournaments: [Tournament]
let type: PlayerPaymentType
@State private var value: Double?
var body: some View {
LabeledContent {
if let value {
Text(value.formatted(.currency(code: Locale.defaultCurrency())))
} else {
ProgressView()
}
} label: {
Text(type.localizedLabel())
}
.onAppear {
Task {
if value == nil {
value = tournaments.compactMap({ $0.paidSelectedPlayers(type: type) }).reduce(0,+)
}
}
}
}
}
struct CashierDetailDisclosureView: View {
let tournament: Tournament
var body: some View {
DisclosureGroup {
let selectedPlayers = tournament.selectedPlayers()
ForEach(PlayerPaymentType.allCases) { type in
let count = selectedPlayers.filter({ $0.paymentType == type }).count
if count > 0 {
LabeledContent {
if let entryFee = tournament.entryFee {
let sum = Double(count) * entryFee
Text(sum.formatted(.currency(code: Locale.defaultCurrency())))
}
} label: {
Text(type.localizedLabel())
Text(count.formatted())
}
}
}
} label: {
Text("Voir le détail")
}
}
}
}