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/Score/EditScoreView.swift

256 lines
9.2 KiB

//
// EditScoreView.swift
// Padel Tournament
//
// Created by Razmig Sarkissian on 27/02/2023.
//
import SwiftUI
import LeStorage
struct ArrowView: View {
var direction: ArrowDirection // Enum for left or right direction
var isActive: Bool // Whether the arrow is visible
var color: Color
@State private var isAnimating = false
enum ArrowDirection {
case left, right
}
var body: some View {
Image(systemName: direction == .left ? "arrow.left" : "arrow.right")
.font(.title)
.foregroundColor(isActive ? color : .clear) // Arrow visible only when active
.opacity(isAnimating ? 1.0 : 0.4) // Animate opacity between 1.0 and 0.4
.offset(x: isAnimating ? (direction == .left ? -5 : 5) : 0) // Slight left/right movement
.animation(
Animation.easeInOut(duration: 0.7).repeatForever(autoreverses: true),
value: isAnimating
)
.onAppear {
isAnimating = true
}
.onDisappear {
isAnimating = false
}
.padding()
}
}
struct EditScoreView: View {
@EnvironmentObject var dataStore: DataStore
@StateObject var matchDescriptor: MatchDescriptor
@Binding var confirmScoreEdition: Bool
@Environment(\.dismiss) private var dismiss
@State private var showSetInputView: Bool = true
@State private var showTieBreakInputView: Bool = false
let colorTeamOne: Color = .teal
let colorTeamTwo: Color = .indigo
init(match: Match, confirmScoreEdition: Binding<Bool>) {
let matchDescriptor = MatchDescriptor(match: match)
_matchDescriptor = .init(wrappedValue: matchDescriptor)
_confirmScoreEdition = confirmScoreEdition
}
func walkout(_ team: TeamPosition) {
self.matchDescriptor.match?.setWalkOut(team)
save()
dismiss()
}
func pointRange(winner: Bool) -> Int? {
guard let match = matchDescriptor.match else { return nil }
guard let tournament = match.currentTournament() else {
return nil
}
let teamsCount = tournament.teamCount
guard let round = match.roundObject else { return nil }
guard let seedInterval = round.seedInterval(), match.index == 0 else {
return nil
}
return winner ? tournament.tournamentLevel.points(for: seedInterval.first - 1, count: teamsCount) : tournament.tournamentLevel.points(for: seedInterval.last - 1, count: teamsCount)
}
var body: some View {
Form {
Section {
VStack(alignment: .leading) {
Text(matchDescriptor.teamLabelOne)
if matchDescriptor.hasEnded, let pointRange = pointRange(winner: matchDescriptor.winner == .one) {
Text(pointRange.formatted(.number.sign(strategy: .always())) + " pts")
.bold()
}
}
.listRowView(isActive: teamOneSetupIsActive, color: colorTeamOne, hideColorVariation: false)
HStack {
Spacer()
VStack(alignment: .trailing) {
Text(matchDescriptor.teamLabelTwo).multilineTextAlignment(.trailing)
if matchDescriptor.hasEnded, let pointRange = pointRange(winner: matchDescriptor.winner == .two) {
Text(pointRange.formatted(.number.sign(strategy: .always())) + " pts")
.bold()
}
}
}
.listRowView(isActive: teamTwoSetupIsActive, color: colorTeamTwo, hideColorVariation: false, alignment: .trailing)
} header: {
if let roundTitle = matchDescriptor.match?.roundAndMatchTitle() {
Text(roundTitle)
}
} footer: {
HStack {
Menu {
Button {
walkout(.one)
} label: {
Text(matchDescriptor.teamLabelOne)
}
Button {
walkout(.two)
} label: {
Text(matchDescriptor.teamLabelTwo)
}
} label: {
Text("Forfait d'une équipe ?")
.underline()
}
Spacer()
MatchTypeSmallSelectionView(selectedFormat: $matchDescriptor.matchFormat, format: "Format")
.onChange(of: matchDescriptor.matchFormat) {
matchDescriptor.setDescriptors.removeAll()
matchDescriptor.addNewSet()
}
}
}
ForEach($matchDescriptor.setDescriptors) { $setDescriptor in
SetInputView(setDescriptor: $setDescriptor, showSetInputView: $showSetInputView, showTieBreakInputView: $showTieBreakInputView)
.onChange(of: setDescriptor.hasEnded) {
if setDescriptor.hasEnded {
if matchDescriptor.hasEnded == false {
matchDescriptor.addNewSet()
}
} else {
let index = matchDescriptor.setDescriptors.firstIndex(where: { $0 == setDescriptor }) ?? 0
matchDescriptor.setDescriptors = Array(matchDescriptor.setDescriptors[0...index])
}
}
.tint(getColor())
}
if matchDescriptor.hasEnded {
Section {
HStack {
Spacer()
VStack {
Text(matchDescriptor.winnerLabel)
}
.multilineTextAlignment(.center)
Spacer()
}
RowButtonView("Victoire") {
matchDescriptor.match?.setScore(fromMatchDescriptor: matchDescriptor)
save()
dismiss()
}
} footer: {
Text("Termine la rencontre sur ce score")
}
}
if matchDescriptor.match?.hasEnded() == false {
Section {
RowButtonView("Mise à jour") {
matchDescriptor.match?.updateScore(fromMatchDescriptor: matchDescriptor)
save()
dismiss()
}
} footer: {
Text("Met à jour le score, ne termine pas la rencontre")
}
}
}
}
func save() {
self.confirmScoreEdition = true
if let match = matchDescriptor.match {
do {
try match.tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
}
}
var teamOneSetupIsActive: Bool {
if matchDescriptor.hasEnded && showSetInputView == false && showTieBreakInputView == false {
return false
}
guard let setDescriptor = matchDescriptor.setDescriptors.last else {
return false
}
if setDescriptor.valueTeamOne == nil {
return true
} else if setDescriptor.valueTeamTwo == nil {
return false
} else if setDescriptor.tieBreakValueTeamOne == nil, setDescriptor.shouldTieBreak {
return true
} else if setDescriptor.tieBreakValueTeamTwo == nil, setDescriptor.shouldTieBreak {
return false
}
return false
}
var teamTwoSetupIsActive: Bool {
if matchDescriptor.hasEnded && showSetInputView == false && showTieBreakInputView == false {
return false
}
guard let setDescriptor = matchDescriptor.setDescriptors.last else {
return false
}
if setDescriptor.valueTeamOne == nil {
return false
} else if setDescriptor.valueTeamTwo == nil {
return true
} else if setDescriptor.tieBreakValueTeamOne == nil, setDescriptor.shouldTieBreak {
return false
} else if setDescriptor.tieBreakValueTeamTwo == nil, setDescriptor.shouldTieBreak {
return true
}
return true
}
func getColor() -> Color {
guard let setDescriptor = matchDescriptor.setDescriptors.last else {
return .master
}
if setDescriptor.valueTeamOne == nil {
return colorTeamOne
} else if setDescriptor.valueTeamTwo == nil {
return colorTeamTwo
} else if setDescriptor.tieBreakValueTeamOne == nil, setDescriptor.shouldTieBreak {
return colorTeamOne
} else if setDescriptor.tieBreakValueTeamTwo == nil, setDescriptor.shouldTieBreak {
return colorTeamTwo
}
return colorTeamTwo
}
}