From ab4aa3313acd60e7648b1d6c7d011bb812c8d8a6 Mon Sep 17 00:00:00 2001
From: "emre.kartal" <emre.kartal@etu.uca.fr>
Date: Thu, 6 Jun 2024 13:29:26 +0200
Subject: [PATCH] Add private friends invitation

---
 .../AllInApp/AllIn/Components/BetCard.swift   |  7 ++--
 .../AllIn/Components/DropDownFriends.swift    | 36 +++++++------------
 .../AllIn/Components/TrendingBetCard.swift    |  3 +-
 .../Ressources/en.lproj/Localizable.strings   |  2 +-
 .../Ressources/fr.lproj/Localizable.strings   |  2 +-
 .../AllIn/ViewModels/BetViewModel.swift       |  4 +++
 .../ViewModels/CreationBetViewModel.swift     | 33 +++++++++++++----
 .../AllIn/Views/CreationBetView.swift         |  2 +-
 .../Sources/Api/Factory/FactoryApiBet.swift   |  3 ++
 Sources/Model/Sources/Model/Bet.swift         | 13 ++-----
 Sources/Model/Sources/Model/MatchBet.swift    | 10 +++---
 Sources/Model/Sources/Model/User.swift        |  6 ++--
 Sources/StubLib/Sources/StubLib/Stub.swift    | 16 ++++-----
 13 files changed, 68 insertions(+), 69 deletions(-)

diff --git a/Sources/AllInApp/AllIn/Components/BetCard.swift b/Sources/AllInApp/AllIn/Components/BetCard.swift
index 599e537..b77b91d 100644
--- a/Sources/AllInApp/AllIn/Components/BetCard.swift
+++ b/Sources/AllInApp/AllIn/Components/BetCard.swift
@@ -44,8 +44,8 @@ struct BetCard: View {
             VStack(alignment: .leading,spacing: 2){
                 HStack{
                     Spacer()
-                    UsersPreview(users: bet.registered)
-                    Text("bet_players_waiting_format \(bet.registered.count.description)")
+                    UsersPreview(users: [])
+                    Text("bet_players_waiting_format \(bet.invited.count.description)")
                         .font(.system(size: 15))
                         .foregroundColor(AllInColors.grey800Color)
                         .fontWeight(.medium)
@@ -80,8 +80,7 @@ struct BetCard_Previews: PreviewProvider {
                                isPrivate: false,
                                status: .inProgress,
                                invited: [],
-                               author: "Imri",
-                               registered: []))
+                               author: "Imri"))
         .preferredColorScheme(.dark)
     }
 }
diff --git a/Sources/AllInApp/AllIn/Components/DropDownFriends.swift b/Sources/AllInApp/AllIn/Components/DropDownFriends.swift
index f9b3382..1154bde 100644
--- a/Sources/AllInApp/AllIn/Components/DropDownFriends.swift
+++ b/Sources/AllInApp/AllIn/Components/DropDownFriends.swift
@@ -6,25 +6,19 @@
 //
 
 import SwiftUI
+import Model
 
 struct DropDownFriends: View {
     
-    @State private var selectedItems: Set<Int> = []
+    @Binding var selectedItems: Set<String>
     @State var expand = false
-    let friends: [(Int, Int, String, String)] = [
-        (0, 541, "David", "defaultUserImage"),
-        (1, 541, "David", "defaultUserImage"),
-        (2, 541, "David", "defaultUserImage"),
-        (3, 541, "David", "defaultUserImage"),
-        (4, 541, "David", "defaultUserImage"),
-        (5, 541, "David", "defaultUserImage")
-    ]
+    var friends: [User]
     
     var body: some View {
         VStack(spacing: 0, content: {
             Button(action: { self.expand.toggle() }) {
                 HStack(spacing: 3){
-                    Text("41")
+                    Text(friends.count.description)
                         .textStyle(weight: .bold, color: AllInColors.primaryTextColor, size: 15)
                     Text("bet_creation_friends_available_format")
                         .textStyle(weight: .regular, color: AllInColors.grey800Color, size: 15)
@@ -42,33 +36,33 @@ struct DropDownFriends: View {
                     .foregroundColor(AllInColors.delimiterGrey)
                 ScrollView(.vertical) {
                     VStack(spacing: 0) {
-                        ForEach(0..<friends.count, id: \.self) { item in
+                        ForEach(friends, id: \.self) {  (friend: User) in
                             HStack {
                                 Circle()
-                                    .fill(selectedItems.contains(friends[item].0) ? AllInColors.lightPurpleColor : Color.clear)
+                                    .fill(selectedItems.contains(friend.id) ? AllInColors.lightPurpleColor : Color.clear)
                                     .overlay(
                                         Circle()
-                                            .stroke(selectedItems.contains(friends[item].0) ? Color.clear : AllInColors.skyBlueColor, lineWidth: 1)
+                                            .stroke(selectedItems.contains(friend.id) ? Color.clear : AllInColors.skyBlueColor, lineWidth: 1)
                                     )
                                     .frame(width: 15, height: 15)
                                     .padding(.trailing, 5)
-                                UserInfo(username: "", value: 0)
+                                UserInfo(username: friend.username, value: friend.nbCoins)
                                     .contentShape(Rectangle())
                             }
                             .padding([.leading, .trailing], 15)
                             .padding([.top, .bottom], 5)
                             .overlay(
-                                selectedItems.contains(friends[item].0) ?
+                                selectedItems.contains(friend.id) ?
                                         Rectangle()
                                             .fill(AllInColors.lightPurpleColor.opacity(0.13))
                                         : nil
                             )
                             .opacity(1.0)
                             .onTapGesture {
-                                if selectedItems.contains(friends[item].0) {
-                                    selectedItems.remove(friends[item].0)
+                                if selectedItems.contains(friend.id) {
+                                    selectedItems.remove(friend.id)
                                 } else {
-                                    selectedItems.insert(friends[item].0)
+                                    selectedItems.insert(friend.id)
                                 }
                             }
                             Rectangle()
@@ -90,9 +84,3 @@ struct DropDownFriends: View {
         )
     }
 }
-
-struct DropDownFriends_Previews: PreviewProvider {
-    static var previews: some View {
-        DropDownFriends()
-    }
-}
diff --git a/Sources/AllInApp/AllIn/Components/TrendingBetCard.swift b/Sources/AllInApp/AllIn/Components/TrendingBetCard.swift
index 3db03e4..7ce0319 100644
--- a/Sources/AllInApp/AllIn/Components/TrendingBetCard.swift
+++ b/Sources/AllInApp/AllIn/Components/TrendingBetCard.swift
@@ -80,7 +80,6 @@ struct TrendingBetCard_Previews: PreviewProvider {
                                        isPrivate: true,
                                        status: .inProgress,
                                        invited: [],
-                                       author: "Imri",
-                                       registered: []))
+                                       author: "Imri"))
     }
 }
diff --git a/Sources/AllInApp/AllIn/Ressources/en.lproj/Localizable.strings b/Sources/AllInApp/AllIn/Ressources/en.lproj/Localizable.strings
index bbe1d1f..2126be0 100644
--- a/Sources/AllInApp/AllIn/Ressources/en.lproj/Localizable.strings
+++ b/Sources/AllInApp/AllIn/Ressources/en.lproj/Localizable.strings
@@ -135,7 +135,7 @@
 "bet_participate" = "Participate";
 "bet_proposed_by_format %@" = "Proposed by %@";
 "bet_proposed_by_format" = "Proposed by";
-"bet_players_waiting_format %@" = "%@ joueurs en attente";
+"bet_players_waiting_format %@" = "%@ players waiting";
 "bet_players_format" = "players";
 "bet_points_at_stake_format" = "points at stake";
 
diff --git a/Sources/AllInApp/AllIn/Ressources/fr.lproj/Localizable.strings b/Sources/AllInApp/AllIn/Ressources/fr.lproj/Localizable.strings
index c93b188..2d595b1 100644
--- a/Sources/AllInApp/AllIn/Ressources/fr.lproj/Localizable.strings
+++ b/Sources/AllInApp/AllIn/Ressources/fr.lproj/Localizable.strings
@@ -135,7 +135,7 @@
 "bet_participate" = "Participer";
 "bet_proposed_by_format %@" = "Proposé par %@";
 "bet_proposed_by_format" = "Proposé par";
-"bet_players_waiting_format %@" = "%@ players waiting";
+"bet_players_waiting_format %@" = "%@ joueurs en attente";
 "bet_players_format" = "joueurs";
 "bet_points_at_stake_format" = "points en jeu";
 
diff --git a/Sources/AllInApp/AllIn/ViewModels/BetViewModel.swift b/Sources/AllInApp/AllIn/ViewModels/BetViewModel.swift
index 4b73477..13d3f23 100644
--- a/Sources/AllInApp/AllIn/ViewModels/BetViewModel.swift
+++ b/Sources/AllInApp/AllIn/ViewModels/BetViewModel.swift
@@ -27,6 +27,7 @@ class BetViewModel: ObservableObject {
     init() {
         getItems()
         getPopularBet()
+        getBetsOver()
     }
     
     func getItems() {
@@ -35,6 +36,9 @@ class BetViewModel: ObservableObject {
                 self.bets = bets
             }
         }
+    }
+    
+    func getBetsOver() {
         manager.getBetsOver() { bets in
             DispatchQueue.main.async {
                 self.betsOver = bets
diff --git a/Sources/AllInApp/AllIn/ViewModels/CreationBetViewModel.swift b/Sources/AllInApp/AllIn/ViewModels/CreationBetViewModel.swift
index 6456378..cba9c44 100644
--- a/Sources/AllInApp/AllIn/ViewModels/CreationBetViewModel.swift
+++ b/Sources/AllInApp/AllIn/ViewModels/CreationBetViewModel.swift
@@ -15,11 +15,16 @@ class CreationBetViewModel: ObservableObject {
     @Inject var manager: Manager
     @Published var theme: String = ""
     @Published var description: String = ""
-    @Published var isPrivate = false
+    @Published var isPrivate = false {
+        didSet {
+            invited.removeAll()
+        }
+    }
     @Published var endRegisterDate = Date()
     @Published var endBetDate = Date()
     @Published var betAdded = false
     @Published var selectedOption = 0
+    @Published var invited: Set<String> = []
     
     @Published var themeFieldError: String?
     @Published var descriptionFieldError: String?
@@ -29,6 +34,20 @@ class CreationBetViewModel: ObservableObject {
     @Published var errorMessage: String?
     @Published var showErrorMessage = false
     
+    @Published var friends: [User] = []
+    
+    init() {
+        getFriends()
+    }
+    
+    func getFriends() {
+        manager.getFriends() { friends in
+            DispatchQueue.main.async {
+                self.friends = friends
+            }
+        }
+    }
+    
     func create() {
         
         guard checkAndSetError(forTheme: true, forDescription: true, forEndRegisterDate: true, forEndBetDate: true) else {
@@ -38,7 +57,7 @@ class CreationBetViewModel: ObservableObject {
         resetAllFieldErrors()
         
         if let user = AppStateContainer.shared.user {
-            manager.addBet(bet: toBet(theme: theme, description: description, endRegister: endRegisterDate, endBet: endBetDate, isPrivate: isPrivate, status: .inProgress, creator: user.username, type: selectedOption)) { statusCode in
+            manager.addBet(bet: toBet(theme: theme, description: description, endRegister: endRegisterDate, endBet: endBetDate, isPrivate: isPrivate, status: .inProgress, creator: user.username, invited: Array(invited), type: selectedOption)) { statusCode in
                 print(statusCode)
                 switch statusCode {
                 case 201:
@@ -114,16 +133,16 @@ class CreationBetViewModel: ObservableObject {
         self.errorMessage = errorMessage
     }
     
-    func toBet(theme: String, description: String, endRegister: Date, endBet: Date, isPrivate: Bool, status: BetStatus, creator: String, type: Int) -> Bet {
+    func toBet(theme: String, description: String, endRegister: Date, endBet: Date, isPrivate: Bool, status: BetStatus, creator: String, invited: [String], type: Int) -> Bet {
         switch type {
         case 0:
-            return BinaryBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: [], author: creator, registered: [])
+            return BinaryBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: invited, author: creator)
         case 1:
-            return MatchBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: [], author: creator, registered: [], nameTeam1: "", nameTeam2: "")
+            return MatchBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: invited, author: creator, nameTeam1: "", nameTeam2: "")
         case 2:
-            return CustomBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: [], author: creator, registered: [])
+            return CustomBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: invited, author: creator)
         default:
-            return BinaryBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: [], author: creator, registered: [])
+            return BinaryBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: invited, author: creator)
         }
     }
 }
diff --git a/Sources/AllInApp/AllIn/Views/CreationBetView.swift b/Sources/AllInApp/AllIn/Views/CreationBetView.swift
index 36cbf47..4d033c5 100644
--- a/Sources/AllInApp/AllIn/Views/CreationBetView.swift
+++ b/Sources/AllInApp/AllIn/Views/CreationBetView.swift
@@ -277,7 +277,7 @@ struct CreationBetView: View {
                         VStack(spacing: 10) {
                             
                             if self.viewModel.isPrivate {
-                                DropDownFriends()
+                                DropDownFriends(selectedItems: $viewModel.invited, friends: viewModel.friends)
                                     .padding(.bottom, 30)
                                 
                                 HStack() {
diff --git a/Sources/Api/Sources/Api/Factory/FactoryApiBet.swift b/Sources/Api/Sources/Api/Factory/FactoryApiBet.swift
index 9f4b584..bc95ae9 100644
--- a/Sources/Api/Sources/Api/Factory/FactoryApiBet.swift
+++ b/Sources/Api/Sources/Api/Factory/FactoryApiBet.swift
@@ -25,9 +25,12 @@ public class FactoryApiBet: FactoryBet {
             "endBet": formatZonedDateTime(dateTime: bet.endBetDate),
             "isPrivate": String(bet.isPrivate),
             "response": ["Yes","No"],
+            "userInvited": bet.invited,
             "type": betTypeString(fromType: String(describing: type(of: bet)))
         ]
         
+        print(json)
+        
         return json
     }
     
diff --git a/Sources/Model/Sources/Model/Bet.swift b/Sources/Model/Sources/Model/Bet.swift
index c48c540..ba016a6 100644
--- a/Sources/Model/Sources/Model/Bet.swift
+++ b/Sources/Model/Sources/Model/Bet.swift
@@ -32,14 +32,11 @@ public class Bet: ObservableObject, Identifiable, Codable {
     public private(set) var status: BetStatus
     
     /// List of users who are invited to participate in the bet.
-    public private(set) var invited: [User] = []
+    public private(set) var invited: [String] = []
     
     /// The user who created the bet.
     public private(set) var author: String
     
-    /// List of users who have registered for the bet.
-    public private(set) var registered: [User] = []
-    
     private enum CodingKeys: String, CodingKey {
         case id
         case theme
@@ -80,8 +77,7 @@ public class Bet: ObservableObject, Identifiable, Codable {
     ///   - status: The current status of the bet.
     ///   - invited: List of users who are invited to participate in the bet.
     ///   - author: The user who created the bet.
-    ///   - registered: List of users who have registered for the bet.
-    public init(id: String, theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPrivate: Bool, status: BetStatus, invited: [User], author: String, registered: [User]) {
+    public init(id: String, theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPrivate: Bool, status: BetStatus, invited: [String], author: String) {
         self.id = id
         self.theme = theme
         self.phrase = phrase
@@ -91,7 +87,6 @@ public class Bet: ObservableObject, Identifiable, Codable {
         self.status = status
         self.invited = invited
         self.author = author
-        self.registered = registered
     }
     
     /// Custom Constructor without Id
@@ -105,8 +100,7 @@ public class Bet: ObservableObject, Identifiable, Codable {
     ///   - status: The current status of the bet.
     ///   - invited: List of users who are invited to participate in the bet.
     ///   - author: The user who created the bet.
-    ///   - registered: List of users who have registered for the bet.
-    public init(theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPrivate: Bool, status: BetStatus, invited: [User], author: String, registered: [User]) {
+    public init(theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPrivate: Bool, status: BetStatus, invited: [String], author: String) {
         self.id = UUID().uuidString
         self.theme = theme
         self.phrase = phrase
@@ -116,7 +110,6 @@ public class Bet: ObservableObject, Identifiable, Codable {
         self.status = status
         self.invited = invited
         self.author = author
-        self.registered = registered
     }
     
 }
diff --git a/Sources/Model/Sources/Model/MatchBet.swift b/Sources/Model/Sources/Model/MatchBet.swift
index b68844c..cb19d31 100644
--- a/Sources/Model/Sources/Model/MatchBet.swift
+++ b/Sources/Model/Sources/Model/MatchBet.swift
@@ -33,13 +33,12 @@ public class MatchBet: Bet {
     ///   - status: The current status of the match bet.
     ///   - invited: List of users who are invited to participate in the match bet.
     ///   - author: The user who created the match bet.
-    ///   - registered: List of users who have registered for the match bet.
     ///   - nameTeam1: The name of the first team involved in the match.
     ///   - nameTeam2: The name of the second team involved in the match.
-    public init(id: String, theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPrivate: Bool, status: BetStatus, invited: [User], author: String, registered: [User], nameTeam1: String, nameTeam2: String) {
+    public init(id: String, theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPrivate: Bool, status: BetStatus, invited: [String], author: String, nameTeam1: String, nameTeam2: String) {
         self.nameTeam1 = nameTeam1
         self.nameTeam2 = nameTeam2
-        super.init(id: id, theme: theme, phrase: phrase, endRegisterDate: endRegisterDate, endBetDate: endBetDate, isPrivate: isPrivate, status: status, invited: invited, author: author, registered: registered)
+        super.init(id: id, theme: theme, phrase: phrase, endRegisterDate: endRegisterDate, endBetDate: endBetDate, isPrivate: isPrivate, status: status, invited: invited, author: author)
     }
     
     /// Custom Constructor without Id
@@ -53,13 +52,12 @@ public class MatchBet: Bet {
     ///   - status: The current status of the match bet.
     ///   - invited: List of users who are invited to participate in the match bet.
     ///   - author: The user who created the match bet.
-    ///   - registered: List of users who have registered for the match bet.
     ///   - nameTeam1: The name of the first team involved in the match.
     ///   - nameTeam2: The name of the second team involved in the match.
-    public init(theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPrivate: Bool, status: BetStatus, invited: [User], author: String, registered: [User], nameTeam1: String, nameTeam2: String) {
+    public init(theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPrivate: Bool, status: BetStatus, invited: [String], author: String, nameTeam1: String, nameTeam2: String) {
         self.nameTeam1 = nameTeam1
         self.nameTeam2 = nameTeam2
-        super.init(theme: theme, phrase: phrase, endRegisterDate: endRegisterDate, endBetDate: endBetDate, isPrivate: isPrivate, status: status, invited: invited, author: author, registered: registered)
+        super.init(theme: theme, phrase: phrase, endRegisterDate: endRegisterDate, endBetDate: endBetDate, isPrivate: isPrivate, status: status, invited: invited, author: author)
     }
     
     public required init(from decoder: Decoder) throws {
diff --git a/Sources/Model/Sources/Model/User.swift b/Sources/Model/Sources/Model/User.swift
index e3f7833..b28d6fb 100644
--- a/Sources/Model/Sources/Model/User.swift
+++ b/Sources/Model/Sources/Model/User.swift
@@ -10,9 +10,8 @@ import Foundation
 /// A struct representing a user with details such as username, email, number of coins, and friends.
 public struct User: Codable, Hashable, Identifiable {
     
-    public var id: String {
-            return email
-    }
+    public var id: String
+    
     /// The username of the user.
     public private(set) var username: String
     
@@ -49,6 +48,7 @@ public struct User: Codable, Hashable, Identifiable {
     ///   - nbFriends: The number of friends the user has.
     ///   - bestWin: The user's best win.
     public init(username: String, email: String, nbCoins: Int, friendStatus: FriendStatus? = nil, image: String? = nil, nbBets: Int, nbFriends: Int, bestWin: Int) {
+        self.id = UUID().description
         self.username = username
         self.email = email
         self.nbCoins = nbCoins
diff --git a/Sources/StubLib/Sources/StubLib/Stub.swift b/Sources/StubLib/Sources/StubLib/Stub.swift
index 1af9f7f..d3539ac 100644
--- a/Sources/StubLib/Sources/StubLib/Stub.swift
+++ b/Sources/StubLib/Sources/StubLib/Stub.swift
@@ -38,8 +38,7 @@ struct Stub {
             isPrivate: false,
             status: .inProgress,
             invited: [],
-            author: "Lucas",
-            registered: [user2]
+            author: "Lucas"
         )
         self.bets.append(bet1)
         
@@ -50,9 +49,8 @@ struct Stub {
             endBetDate: Date().addingTimeInterval(259200),
             isPrivate: false,
             status: .inProgress,
-            invited: [user3],
-            author: "Lucas",
-            registered: [user2]
+            invited: [],
+            author: "Lucas"
         )
         self.bets.append(bet2)
         
@@ -64,8 +62,7 @@ struct Stub {
             isPrivate: true,
             status: .finished,
             invited: [],
-            author: "Lucas",
-            registered: [user2, user1, user3]
+            author: "Lucas"
         )
         self.bets.append(bet3)
         
@@ -76,9 +73,8 @@ struct Stub {
             endBetDate: Date().addingTimeInterval(432000),
             isPrivate: false,
             status: .finished,
-            invited: [user1],
-            author: "Lucase",
-            registered: [user3]
+            invited: [],
+            author: "Lucase"
         )
         self.bets.append(bet4)
 
-- 
2.36.3