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.
256 lines
9.2 KiB
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
|
|
}
|
|
|
|
}
|
|
|