club_update
Razmig Sarkissian 1 year ago
parent a972dbfdd9
commit 72d143759d
  1. 14
      PadelClub.xcodeproj/project.pbxproj
  2. 3
      PadelClub/Data/DataStore.swift
  3. 13
      PadelClub/Data/Match.swift
  4. 6
      PadelClub/Data/PlayerRegistration.swift
  5. 6
      PadelClub/Data/Round.swift
  6. 10
      PadelClub/Data/TeamRegistration.swift
  7. 173
      PadelClub/Views/Match/EditSharingView.swift
  8. 12
      PadelClub/Views/Match/MatchDetailView.swift
  9. 8
      PadelClub/Views/Match/MatchRowView.swift
  10. 5
      PadelClub/Views/Navigation/MainView.swift
  11. 2
      PadelClub/Views/Navigation/Ongoing/OngoingView.swift
  12. 6
      PadelClub/Views/Navigation/Umpire/PadelClubView.swift
  13. 5
      PadelClub/Views/Round/RoundSettingsView.swift
  14. 59
      PadelClub/Views/Shared/ImagePickerView.swift

@ -242,6 +242,8 @@
FFDB1C732BB2CFE900F1E467 /* MySortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDB1C722BB2CFE900F1E467 /* MySortDescriptor.swift */; };
FFDDD40C2B93B2BB00C91A49 /* DeferredViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.swift */; };
FFE103082C353B7600684FC9 /* EventClubSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE103072C353B7600684FC9 /* EventClubSettingsView.swift */; };
FFE103102C366DCD00684FC9 /* EditSharingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE1030F2C366DCD00684FC9 /* EditSharingView.swift */; };
FFE103122C366E5900684FC9 /* ImagePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE103112C366E5900684FC9 /* ImagePickerView.swift */; };
FFE2D2E22C231BEE00D0C7BE /* SupportButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE2D2E12C231BEE00D0C7BE /* SupportButtonView.swift */; };
FFEF7F4E2BDE69130033D0F0 /* MenuWarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */; };
FFF0241E2BF48B15001F14B4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = FFF0241D2BF48B15001F14B4 /* Localizable.strings */; };
@ -574,6 +576,8 @@
FFDB1C722BB2CFE900F1E467 /* MySortDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MySortDescriptor.swift; sourceTree = "<group>"; };
FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredViewModifier.swift; sourceTree = "<group>"; };
FFE103072C353B7600684FC9 /* EventClubSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EventClubSettingsView.swift; path = PadelClub/Views/Tournament/Screen/Components/EventClubSettingsView.swift; sourceTree = SOURCE_ROOT; };
FFE1030F2C366DCD00684FC9 /* EditSharingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditSharingView.swift; sourceTree = "<group>"; };
FFE103112C366E5900684FC9 /* ImagePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePickerView.swift; sourceTree = "<group>"; };
FFE2D2E12C231BEE00D0C7BE /* SupportButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportButtonView.swift; sourceTree = "<group>"; };
FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuWarningView.swift; sourceTree = "<group>"; };
FFF0241C2BF48B15001F14B4 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -1076,6 +1080,7 @@
FFCFC0192BBC5A8500B82851 /* MatchTypeSmallSelectionView.swift */,
FF663FBD2BE019EC0031AE83 /* TournamentFilterView.swift */,
FFE2D2E12C231BEE00D0C7BE /* SupportButtonView.swift */,
FFE103112C366E5900684FC9 /* ImagePickerView.swift */,
);
path = Shared;
sourceTree = "<group>";
@ -1164,6 +1169,7 @@
FF967D052BAF3C4200A9A3BD /* MatchSetupView.swift */,
FF967D002BAEF0B400A9A3BD /* MatchSummaryView.swift */,
FF967D022BAEF0C000A9A3BD /* MatchDetailView.swift */,
FFE1030F2C366DCD00684FC9 /* EditSharingView.swift */,
FF025AD92BD0C2BD00A86CF8 /* Components */,
);
path = Match;
@ -1506,6 +1512,7 @@
FF8F26412BADFC8700650388 /* TournamentInitView.swift in Sources */,
C4A47D8A2B7BBB6500ADC637 /* SubscriptionView.swift in Sources */,
FF1DC5572BAB3AED00FD8220 /* ClubsView.swift in Sources */,
FFE103122C366E5900684FC9 /* ImagePickerView.swift in Sources */,
FF8F264F2BAE0B9600650388 /* MatchTypeSelectionView.swift in Sources */,
FF967D062BAF3C4200A9A3BD /* MatchSetupView.swift in Sources */,
FF4AB6B52B9248200002987F /* NetworkManager.swift in Sources */,
@ -1520,6 +1527,7 @@
FF9268012BCE94920080F940 /* SeedsCallingView.swift in Sources */,
FF9268092BCEDC2C0080F940 /* CallView.swift in Sources */,
FF5D0D742BB41DF8005CB568 /* Color+Extensions.swift in Sources */,
FFE103102C366DCD00684FC9 /* EditSharingView.swift in Sources */,
FF7091682B90F79F00AB08DA /* TournamentCellView.swift in Sources */,
FF6EC9042B9479F500EA7F5A /* Sequence+Extensions.swift in Sources */,
FF9267FA2BCE78EC0080F940 /* CashierDetailView.swift in Sources */,
@ -1894,7 +1902,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 85;
CURRENT_PROJECT_VERSION = 86;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
@ -1907,6 +1915,7 @@
INFOPLIST_KEY_CFBundleDisplayName = "Padel Club";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.sports";
INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES;
INFOPLIST_KEY_NSCameraUsageDescription = "En autorisant l'application à utiliser la caméra, vous pourrez prendre des photos des rencontres";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Padel Club a besoin de votre position pour rechercher les clubs autour de vous.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
@ -1937,7 +1946,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 85;
CURRENT_PROJECT_VERSION = 86;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;
@ -1948,6 +1957,7 @@
INFOPLIST_KEY_CFBundleDisplayName = "Padel Club";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.sports";
INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES;
INFOPLIST_KEY_NSCameraUsageDescription = "En autorisant l'application à utiliser la caméra, vous pourrez prendre des photos des rencontres";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Padel Club a besoin de votre position pour rechercher les clubs autour de vous.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;

@ -249,7 +249,8 @@ class DataStore: ObservableObject {
// MARK: - Convenience
func runningMatches() -> [Match] {
let lastTournaments = self.tournaments.sorted(by: \Tournament.startDate).prefix(10)
let dateNow : Date = Date()
let lastTournaments = self.tournaments.filter { $0.isDeleted == false && $0.startDate <= dateNow }.sorted(by: \Tournament.startDate, order: .descending).prefix(10)
var runningMatches: [Match] = []
for tournament in lastTournaments {

@ -541,6 +541,10 @@ defer {
startDate = fromStartDate
switch fieldSetup {
case .fullRandom:
if let _courtIndex = allCourts().randomElement() {
setCourt(_courtIndex)
}
case .random:
if let _courtIndex = availableCourts().randomElement() {
setCourt(_courtIndex)
@ -579,10 +583,14 @@ defer {
return false
}
func allCourts() -> [Int] {
let availableCourts = Array(0..<courtCount())
return availableCourts
}
func availableCourts() -> [Int] {
let courtUsed = currentTournament()?.courtUsed() ?? []
let availableCourts = Array(0..<courtCount())
return Array(Set(availableCourts.map { $0 }).subtracting(Set(courtUsed)))
return Array(Set(allCourts().map { $0 }).subtracting(Set(courtUsed)))
}
func removeCourt() {
@ -896,6 +904,7 @@ enum MatchDateSetup: Hashable, Identifiable {
enum MatchFieldSetup: Hashable, Identifiable {
case random
case fullRandom
// case firstAvailable
case field(Int)

@ -220,8 +220,10 @@ final class PlayerRegistration: ModelObject, Storable {
@MainActor
func updateRank(from sources: [CSVParser], lastRank: Int) async throws {
if let value = try await history(from: sources)?.rank {
rank = value
if let dataFound = try await history(from: sources) {
rank = dataFound.rankValue?.toInt()
points = dataFound.points
tournamentPlayed = dataFound.tournamentCountValue?.toInt()
} else {
rank = lastRank
}

@ -494,7 +494,11 @@ defer {
func roundTitle(_ displayStyle: DisplayStyle = .wide) -> String {
if parent != nil {
return seedInterval()?.localizedLabel(displayStyle) ?? "Round pas trouvé"
if let seedInterval = seedInterval() {
return seedInterval.localizedLabel(displayStyle)
}
print("Round pas trouvé", id, parent, index)
return "Round pas trouvé"
}
return RoundRule.roundName(fromRoundIndex: index, displayStyle: displayStyle)
}

@ -183,6 +183,16 @@ final class TeamRegistration: ModelObject, Storable {
return players().map { $0.playerLabel(displayStyle) }.joined(separator: twoLines ? "\n" : " & ")
}
func teamLabelRanked(displayRank: Bool, displayTeamName: Bool) -> String {
[displayTeamName ? name : nil, displayRank ? seedIndex() : nil, displayTeamName ? (name == nil ? teamLabel() : name) : teamLabel()].compactMap({ $0 }).joined(separator: " ")
}
func seedIndex() -> String? {
guard let tournament = tournamentObject() else { return nil }
guard let index = index(in: tournament.selectedSortedTeams()) else { return nil }
return "(\(index + 1))"
}
func index(in teams: [TeamRegistration]) -> Int? {
return teams.firstIndex(where: { $0.id == id })
}

@ -0,0 +1,173 @@
//
// EditSharingView.swift
// Padel Tournament
//
// Created by Razmig Sarkissian on 03/02/2024.
//
import SwiftUI
import TipKit
import CoreTransferable
struct EditSharingView: View {
@Environment(Tournament.self) var tournament: Tournament
var match: Match
@State private var displayRank: Bool = false
@State private var displayTeamTitle: Bool = false
@State private var showCamera: Bool = false
@State private var newImage: UIImage?
@State private var copied: Bool = false
var shareMessage: String {
shareMessage(displayRank: displayRank, displayTeamName: displayTeamTitle)
}
func shareMessage(displayRank: Bool, displayTeamName: Bool) -> String {
var messageData: [String] = []
var locAndTime: String = ""
if let courtName = match.courtName() {
locAndTime.append("\(courtName)")
}
if let startDate = match.startDate {
locAndTime = locAndTime + " à " + startDate.formattedAsHourMinute()
}
if locAndTime.isEmpty == false {
messageData.append(locAndTime)
}
messageData.append(tournament.tournamentTitle())
let message = [match.isLoserBracket ? "Classement" : nil, match.roundTitle(), match.isLoserBracket ? nil : ((match.index > 0 || match.isGroupStage()) ? match.matchTitle(.short) : nil)].compactMap({ $0 }).joined(separator: " ")
messageData.append(message)
guard let labelOne = match.team(.one)?.teamLabelRanked(displayRank: displayRank, displayTeamName: displayTeamName), let labelTwo = match.team(.two)?.teamLabelRanked(displayRank: displayRank, displayTeamName: displayTeamName) else {
return messageData.joined(separator: "\n")
}
let players = "\(labelOne)\ncontre\n\(labelTwo)"
messageData.append(players)
return messageData.joined(separator: "\n")
}
var body: some View {
List {
if let newImage {
Section {
let tip = SharePictureTip()
TipView(tip)
.tipStyle(tint: .green)
}
Section {
ZStack {
Color.black
.ignoresSafeArea()
Image(uiImage: newImage)
.resizable()
.scaledToFit()
.frame(height: 200, alignment: .center)
.frame(maxWidth: .infinity, alignment: .center)
}
.listRowInsets(EdgeInsets())
} footer: {
HStack {
Spacer()
Button("effacer", role: .destructive) {
self.newImage = nil
}
}
}
} else {
Button {
showCamera = true
} label: {
Label("Prendre une photo", systemImage: "camera")
}
}
Section {
Toggle(isOn: $displayRank) {
Text("Afficher leurs rangs dans ce tournoi")
}
Toggle(isOn: $displayTeamTitle) {
Text("Afficher plutôt le nom de l'équipe")
}
} header: {
Text("Options")
}
Section {
Text(shareMessage)
} header: {
Text("Message type généré")
} footer: {
HStack {
Spacer()
Button {
UIPasteboard.general.string = shareMessage
copied = true
} label: {
Label(copied ? "copié" : "copier", systemImage: "doc.on.doc")
}
if shareMessage == UIPasteboard.general.string || copied == true {
Image(systemName: "checkmark")
}
}
}
}
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
if let newImage {
let photo = Photo(image: Image(uiImage:newImage), caption: shareMessage)
ShareLink(
item: photo,
preview: SharePreview(
photo.caption,
image: photo.image)) {
Text("Partager")
}
.onAppear {
UIPasteboard.general.string = shareMessage
copied = true
}
} else {
ShareLink("Partager", item: shareMessage)
}
}
}
.navigationTitle("Préparation")
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar)
.fullScreenCover(isPresented: $showCamera) {
ImagePickerView(image: $newImage)
.background(Color.black.edgesIgnoringSafeArea(.all))
}
.onChange(of: displayRank) {
copied = false
}
.onChange(of: displayTeamTitle) {
copied = false
}
}
}
struct Photo: Transferable {
static var transferRepresentation: some TransferRepresentation {
ProxyRepresentation(exporting: \.image)
ProxyRepresentation(exporting: \.caption)
}
public var image: Image
public var caption: String
}

@ -351,8 +351,11 @@ struct MatchDetailView: View {
}
}
//todo
//shareView
NavigationLink {
EditSharingView(match: match)
} label: {
Text("Partage sur les réseaux sociaux")
}
// if let followUpMatch = match.followUpMatch {
// Section {
@ -415,7 +418,8 @@ struct MatchDetailView: View {
Picker(selection: $fieldSetup) {
Text("Au hasard").tag(MatchFieldSetup.random)
Text("Au hasard parmi les libres").tag(MatchFieldSetup.random)
Text("Au hasard").tag(MatchFieldSetup.fullRandom)
//Text("Premier disponible").tag(MatchFieldSetup.firstAvailable)
if let club = match.currentTournament()?.club() {
ForEach(0..<club.courtCount, id: \.self) { courtIndex in
@ -431,7 +435,7 @@ struct MatchDetailView: View {
}
}
} label: {
Text("Choix du terrain")
Text("Terrain")
}
RowButtonView("Valider") {

@ -62,6 +62,14 @@ struct MatchRowView: View {
.environment(self.tournament)
} label: {
MatchSummaryView(match: match, matchViewStyle: matchViewStyle, title: title)
.contextMenu {
NavigationLink {
EditSharingView(match: match)
.environment(self.tournament)
} label: {
Text("Partage sur les réseaux sociaux")
}
}
}
//.modifier(BroadcastViewModifier(isBroadcasted: match.isBroadcasted()))
}

@ -176,13 +176,14 @@ struct MainView: View {
importingFiles = true
Task {
let lastDataSource = await FileImportManager.shared.importDataFromFFT()
await MainActor.run {
importingFiles = false
}
dataStore.appSettings.lastDataSource = lastDataSource
dataStore.appSettingsStorage.write()
if let lastDataSource, let mostRecentDate = URL.importDateFormatter.date(from: lastDataSource) {
await MonthData.calculateCurrentUnrankedValues(mostRecentDateAvailable: mostRecentDate)
}
importingFiles = false
await _downloadPreviousDate()
}
}

@ -26,7 +26,6 @@ struct OngoingView: View {
var body: some View {
@Bindable var navigation = navigation
NavigationStack(path: $navigation.ongoingPath) {
let matches = matches.filter { $0.currentTournament()?.isDeleted == false }
List {
ForEach(matches) { match in
@ -34,6 +33,7 @@ struct OngoingView: View {
Section {
MatchRowView(match: match, tournament: tournament, matchViewStyle: .standardStyle)
.environment(tournament)
} header: {
HStack {
Text(tournament.tournamentTitle(.short))

@ -83,7 +83,7 @@ struct PadelClubView: View {
}
}
if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, _lastDataSourceDate.isEarlierThan(mostRecentDateAvailable) {
if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, _lastDataSourceDate.isEarlierThan(mostRecentDateAvailable), importingFiles == false {
Section {
RowButtonView("Importer \(mostRecentDateAvailable.monthYearFormatted)") {
_startImporting()
@ -229,12 +229,14 @@ struct PadelClubView: View {
importingFiles = true
Task {
let lastDataSource = await FileImportManager.shared.importDataFromFFT()
await MainActor.run {
importingFiles = false
}
dataStore.appSettings.lastDataSource = lastDataSource
dataStore.appSettingsStorage.write()
if let lastDataSource, let mostRecentDate = URL.importDateFormatter.date(from: lastDataSource) {
await MonthData.calculateCurrentUnrankedValues(mostRecentDateAvailable: mostRecentDate)
}
importingFiles = false
viewContext.refreshAllObjects()
}
}

@ -140,6 +140,11 @@ struct RoundSettingsView: View {
if let lastRound = tournament.rounds().first { // first is final, last round
RowButtonView("Supprimer " + lastRound.roundTitle(), role: .destructive) {
do {
let teams = lastRound.seeds()
teams.forEach { team in
team.resetBracketPosition()
}
try tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teams)
try tournamentStore.rounds.delete(instance: lastRound)
} catch {
Logger.error(error)

@ -0,0 +1,59 @@
//
// ImagePicker.swift
// Poker Analytics 6
//
// Created by Razmig Sarkissian on 22/09/2021.
//
import SwiftUI
#if targetEnvironment(simulator)
struct ImagePickerView: View {
@Binding var image: UIImage?
var body: some View {
EmptyView()
.onAppear {
image = UIImage(systemName: "star.fill")
}
}
}
#else
struct ImagePickerView: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentationMode
@Binding var image: UIImage?
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let parent: ImagePickerView
init(_ parent: ImagePickerView) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let uiImage = info[.originalImage] as? UIImage {
parent.image = uiImage
}
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePickerView>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = .camera
picker.allowsEditing = true
picker.showsCameraControls = true
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePickerView>) { }
}
#endif
Loading…
Cancel
Save