Merge pull request 'fix/Model_Details' (#17) from fix/Model_Details into master

Reviewed-on: #17
feature/bet-ending
Lucas DELANIER 1 year ago
commit fb6c8b58c6

@ -1,38 +0,0 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x49",
"green" : "0x49",
"red" : "0x49"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x49",
"green" : "0x49",
"red" : "0x49"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 681 B

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "Group 107 (1).png",
"filename" : "PinkAllCoin.png",
"idiom" : "universal",
"scale" : "1x"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "Vector (1).png",
"filename" : "PinkBadge.png",
"idiom" : "universal",
"scale" : "1x"
},

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "UserPink.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

@ -1,6 +1,7 @@
{
"images" : [
{
"filename" : "Trophy.png",
"idiom" : "universal",
"scale" : "1x"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 975 B

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "allCoinBlack.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -38,57 +38,109 @@ struct BetLineLoading: View {
GeometryReader { geometry in
VStack(alignment: .leading,spacing: 0){
HStack(spacing: 5){
Text("OUI").font(.system(size: 25)).fontWeight(.bold).foregroundColor(AllInColors.bleue200)
Text("OUI")
.font(.system(size: 25))
.fontWeight(.bold)
.foregroundColor(AllInColors.blue200)
Spacer()
Text("NON").font(.system(size: 25)).fontWeight(.bold).foregroundColor(AllInColors.pink100)
Text("NON")
.font(.system(size: 25))
.fontWeight(.bold)
.foregroundColor(AllInColors.pink100)
}
ZStack(alignment: .leading) {
HStack{
Spacer()
Rectangle().frame(width: min(CGFloat(1-self.value)*geometry.size.width, geometry.size.width), height: 17)
Rectangle()
.frame(width: min(CGFloat(1-self.value)*geometry.size.width, geometry.size.width), height: 17)
.foregroundStyle(AllInColors.PinkBetGradiant).cornerRadius(999)
}
HStack(spacing: 0){
Rectangle().frame(width: min(CGFloat(self.value)*geometry.size.width, geometry.size.width), height: 17)
.foregroundStyle(AllInColors.BlueBetGradiant).cornerRadius(999)
Rectangle()
.frame(width: min(CGFloat(self.value)*geometry.size.width, geometry.size.width), height: 17)
.foregroundStyle(AllInColors.BlueBetGradiant)
.cornerRadius(999)
.animation(.linear)
Image("LoadingHeart").resizable().frame(width: 29, height: 32).padding(.leading, -10)
Image("loadingHeartIcon")
.resizable()
.frame(width: 29, height: 32)
.padding(.leading, -10)
}
}
VStack(spacing: 1){
HStack(spacing: 5){
Image("BlueAllCoinIcon").resizable().frame(width:12, height: 12)
Text(yesParticipations.reduce(0, {x,y in x + y.stake}).description).font(.system(size: 15)).fontWeight(.bold).foregroundColor(AllInColors.bleue200)
Image("blueAllCoinIcon")
.resizable()
.frame(width:12, height: 12)
Text(yesParticipations.reduce(0, {x,y in x + y.stake}).description)
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(AllInColors.blue200)
Spacer()
Text(noParticipations.reduce(0, {x,y in x + y.stake}).description).font(.system(size: 15)).fontWeight(.bold).foregroundColor(AllInColors.pink100)
Image("PinkBadge").resizable().frame(width:10, height: 14)
Text(noParticipations.reduce(0, {x,y in x + y.stake}).description)
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(AllInColors.pink100)
Image("pinkAllCoinIcon")
.resizable()
.frame(width:10, height: 14)
}
HStack(spacing: 5){
Image("BleuePersonIcon").resizable().frame(width:14, height: 12)
Text(yesParticipations.count.description).font(.system(size: 15)).fontWeight(.bold).foregroundColor(AllInColors.bleue200)
Image("bluePersonIcon")
.resizable()
.frame(width:14, height: 12)
Text(yesParticipations.count.description)
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(AllInColors.blue200)
Spacer()
Text(noParticipations.count.description).font(.system(size: 15)).fontWeight(.bold).foregroundColor(AllInColors.pink100)
Image("PinkBadge").resizable().frame(width:10, height: 14)
Text(noParticipations.count.description)
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(AllInColors.pink100)
Image("pinkPersonIcon")
.resizable()
.frame(width:10, height: 14)
}
HStack(spacing: 5){
Image("BleueBadge").resizable().frame(width:10, height: 14)
Text(yesParticipations.max(by: { $0.stake < $1.stake })?.stake.description ?? "0").font(.system(size: 15)).fontWeight(.bold).foregroundColor(AllInColors.bleue200)
Image("blueBadgeIcon")
.resizable()
.frame(width:10, height: 14)
Text(yesParticipations.max(by: { $0.stake < $1.stake })?.stake.description ?? "0")
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(AllInColors.blue200)
Spacer()
Text(noParticipations.max(by: { $0.stake < $1.stake })?.stake.description ?? "0").font(.system(size: 15)).fontWeight(.bold).foregroundColor(AllInColors.pink100)
Image("PinkBadge").resizable().frame(width:10, height: 14)
Text(noParticipations.max(by: { $0.stake < $1.stake })?.stake.description ?? "0")
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(AllInColors.pink100)
Image("pinkBadgeIcon")
.resizable()
.frame(width:10, height: 14)
}
HStack(spacing: 5){
Image("BleueTrophyIcon").resizable().frame(width:14, height: 13)
Text("1.2").font(.system(size: 15)).fontWeight(.bold).foregroundColor(AllInColors.bleue200)
Image("blueTrophyIcon")
.resizable()
.frame(width:14, height: 13)
Text("1.2")
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(AllInColors.blue200)
Spacer()
Text("1.2").font(.system(size: 15)).fontWeight(.bold).foregroundColor(AllInColors.pink100)
Image("PinkBadge").resizable().frame(width:10, height: 14)
Text("1.2")
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(AllInColors.pink100)
Image("pinkTrophyIcon")
.resizable()
.frame(width:10, height: 14)
}
}

@ -65,6 +65,10 @@ struct DropDownAnswerMenu: View {
.frame(width: .infinity)
.background(AllInColors.componentBackgroundColor)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10, style: .continuous)
.stroke(AllInColors.veryLightPurpleColor, lineWidth: 0.4)
)
}
}

@ -40,16 +40,16 @@ struct ParticipationModal: View {
HStack{
Text("Faites vos paris")
.font(.system(size: 18))
.foregroundColor(AllInColors.blackTitleColor)
.foregroundColor(AllInColors.primaryTextColor)
.fontWeight(.semibold)
Spacer()
AllcoinsCounter(backgroundColor: AllInColors.purpleAccentColor, foregroundColor: AllInColors.whiteColor)
AllcoinsCounter(backgroundColor: AllInColors.purpleAccentColor, foregroundColor: .white)
}
.padding(.leading, 15)
VStack(alignment: .leading){
Text(description)
.font(.system(size: 13))
.foregroundColor(AllInColors.grey100Color)
.foregroundColor(AllInColors.primaryTextColor)
.fontWeight(.light)
DropDownAnswerMenu(selectedOption: $selectedOption, options: options)
@ -66,7 +66,7 @@ struct ParticipationModal: View {
.frame(height: 40)
)
.frame(width: .infinity, height: 40)
.foregroundColor(AllInColors.primaryTextColor)
.foregroundColor(.black)
.overlay(
RoundedRectangle(cornerRadius: 10, style: .continuous)
.stroke(AllInColors.delimiterGrey, lineWidth: 1)
@ -80,12 +80,12 @@ struct ParticipationModal: View {
HStack{
Text("Gains possibles")
.font(.system(size: 13))
.foregroundColor(AllInColors.blackTitleColor)
.foregroundColor(AllInColors.primaryTextColor)
.fontWeight(.regular)
Spacer()
Text("231")
.font(.system(size: 13))
.foregroundColor(AllInColors.blackTitleColor)
.foregroundColor(AllInColors.primaryTextColor)
.fontWeight(.light)
}
.padding(.top, 10).padding(.bottom, 0)
@ -101,6 +101,7 @@ struct ParticipationModal: View {
}
.buttonStyle(.borderedProminent)
.tint(AllInColors.purpleAccentColor)
.disabled(checkAndSetError())
}
.padding(.horizontal, 10)
@ -109,4 +110,16 @@ struct ParticipationModal: View {
}
.background(AllInColors.underComponentBackgroundColor)
}
func checkAndSetError() -> Bool {
if let stake = Int(mise) {
if stake <= AppStateContainer.shared.user?.nbCoins ?? 0 {
return false
} else {
return true
}
} else {
return true
}
}
}

@ -29,6 +29,12 @@ struct AllInColors {
static let loginPurpleColor = Color("LoginPurpleColor")
static let whiteColor = Color("WhiteColor")
// Details
static let blue200 = Color("Blue200")
static let purple200 = Color("Purple200")
static let pink200 = Color("Pink200")
static let pink100 = Color("Pink100")
// Others
static let backgroundColor = Color("BackgroundColor")
static let darkBlueColor = Color("DarkBlueColor")
@ -48,11 +54,7 @@ struct AllInColors {
static let componentBackgroundColor = Color("ComponentBackgroundColor")
static let underComponentBackgroundColor = Color("UnderComponentBackgroundColor")
static let winBannerBackground = Color("WinBannerBackground")
static let blackTitleColor = Color("BlackTitleColor")
static let bleue200 = Color("Bleue200")
static let purple200 = Color("Purple200")
static let pink200 = Color("Pink200")
static let pink100 = Color("Pink100")
// Gradients
static let primaryGradient = LinearGradient(
gradient: Gradient(colors: [AllInColors.pinkAccentColor, AllInColors.blueAccentColor]),
@ -66,7 +68,7 @@ struct AllInColors {
)
static let BlueBetGradiant = LinearGradient(
gradient: Gradient(colors: [AllInColors.bleue200, AllInColors.purple200]),
gradient: Gradient(colors: [AllInColors.blue200, AllInColors.purple200]),
startPoint: .leading,
endPoint: .trailing
)

@ -25,6 +25,9 @@ class CreationBetViewModel: ObservableObject {
@Published var endRegisterDateFieldError: String?
@Published var endBetDateFieldError: String?
@Published var errorMessage: String?
@Published var showErrorMessage = false
func create() {
guard checkAndSetError(forTheme: true, forDescription: true, forEndRegisterDate: true, forEndBetDate: true) else {
@ -34,10 +37,15 @@ class CreationBetViewModel: ObservableObject {
resetAllFieldErrors()
if let user = AppStateContainer.shared.user {
manager.addBet(theme: theme, description: description, endRegister: endRegisterDate, endBet: endBetDate, isPublic: isPublic, creator: user)
manager.addBet(theme: theme, description: description, endRegister: endRegisterDate, endBet: endBetDate, isPublic: isPublic, creator: user) { statusCode in
switch statusCode {
case 201:
self.betAdded = true
default:
self.setErrorMessage(errorMessage: "Problème de connexion. Veuillez réessayer ultérieurement.")
}
}
}
betAdded = true
}
func checkAndSetError(forTheme checkTheme: Bool, forDescription checkDescription: Bool, forEndRegisterDate checkEndRegisterDate: Bool, forEndBetDate checkEndBetDate: Bool) -> Bool {
@ -95,4 +103,9 @@ class CreationBetViewModel: ObservableObject {
endBetDateFieldError = nil
}
}
func setErrorMessage(errorMessage: String) {
self.showErrorMessage = true
self.errorMessage = errorMessage
}
}

@ -38,7 +38,21 @@ class DetailsViewModel: ObservableObject {
} else {
rep = "No"
}
manager.addParticipation(withId: id, withAnswer: rep, andStake: stake)
manager.addParticipation(withId: id, withAnswer: rep, andStake: stake) { statusCode in
switch statusCode {
case 201:
AppStateContainer.shared.user?.nbCoins -= stake
self.getItem(withId: self.id)
default:
break
}
}
}
mise = ""
answer = 0
}
func checkAndSetError() {
}
}

@ -477,6 +477,9 @@ struct CreationBetView: View {
.onTapGesture {
hideKeyboard()
}
.alert(isPresented: $viewModel.showErrorMessage) {
Alert(title: Text("Erreur lors de la création d'un Bet"), message: Text(viewModel.errorMessage ?? ""), dismissButton: .default(Text("OK")))
}
.edgesIgnoringSafeArea(.bottom)
.background(AllInColors.backgroundColor)
}

@ -131,9 +131,12 @@ struct DetailsView: View {
.foregroundStyle(AllInColors.grey100Color)
.fontWeight(.bold)
.padding(.bottom, 10)
ScrollView(showsIndicators: false) {
ForEach(viewModel.betDetail?.participations ?? []) { (participation: Participation) in
ParticiationCell(participation: participation).padding(.horizontal, 10)
}
}
.padding(.bottom, 28)
Spacer()
}

@ -22,7 +22,7 @@ public struct UserApiManager: UserDataManager {
fatalError("Not implemented yet")
}
public func addBet(bet: Bet) {
public func addBet(bet: Bet, completion : @escaping (Int)-> ()) {
let url = URL(string: allInApi + "bets/add")!
var request = URLRequest(url: url)
@ -37,6 +37,7 @@ public struct UserApiManager: UserDataManager {
print ("ALLIN : Add BET")
if let httpResponse = response as? HTTPURLResponse {
print(httpResponse.statusCode)
completion(httpResponse.statusCode)
}
}.resume()
}
@ -50,7 +51,7 @@ public struct UserApiManager: UserDataManager {
fatalError("Not implemented yet")
}
public func addParticipation(withId id: String, withAnswer answer: String, andStake stake: Int) {
public func addParticipation(withId id: String, withAnswer answer: String, andStake stake: Int, completion : @escaping (Int)-> ()) {
let url = URL(string: allInApi + "participations/add")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
@ -68,6 +69,7 @@ public struct UserApiManager: UserDataManager {
print ("ALLIN : Add Participation")
if let httpResponse = response as? HTTPURLResponse {
print(httpResponse.statusCode)
completion(httpResponse.statusCode)
}
}.resume()
}

@ -28,6 +28,7 @@ public class Bet: ObservableObject, Identifiable {
/// Indicates whether the bet is public or private.
public private(set) var isPublic: Bool
/// The current status of the bet.
public private(set) var status: BetStatus
/// List of users who are invited to participate in the bet.
@ -49,6 +50,7 @@ public class Bet: ObservableObject, Identifiable {
/// - endRegisterDate: The deadline for users to register for the bet.
/// - endBetDate: The deadline for the actual betting to take place.
/// - isPublic: Indicates whether the bet is public or private.
/// - 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.
@ -73,6 +75,7 @@ public class Bet: ObservableObject, Identifiable {
/// - endRegisterDate: The deadline for users to register for the bet.
/// - endBetDate: The deadline for the actual betting to take place.
/// - isPublic: Indicates whether the bet is public or private.
/// - 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.
@ -89,6 +92,9 @@ public class Bet: ObservableObject, Identifiable {
self.registered = registered
}
/// Adds a new user to the list of registered participants for the bet.
///
/// - Parameter newUser: The user to be added to the list of registered participants.
public func addRegistered(newUser: User){
self.registered.append(newUser)
}

@ -19,6 +19,7 @@ public class BetDetail: ObservableObject {
/// List of user participations in the bet.
public private(set) var participations: [Participation]
/// The final answer selected for the bet, if available.
public private(set) var finalAnswer: String?
/// Custom Constructor
@ -27,7 +28,7 @@ public class BetDetail: ObservableObject {
/// - bet: The main bet information.
/// - answers: Details about the answers available for the bet.
/// - participations: List of user participations in the bet.
/// - userParticipation: The user's own participation in the bet.
/// - finalAnswer: The final answer selected for the bet, if available.
public init(bet: Bet, answers: [AnswerDetail], participations: [Participation], finalAnswer: String? = nil) {
self.bet = bet
self.answers = answers
@ -35,17 +36,23 @@ public class BetDetail: ObservableObject {
self.finalAnswer = finalAnswer
}
/// Updates the final answer selected for the bet.
///
/// - Parameter newFinalAnswer: The new final answer for the bet.
public func updateFinalAnswer(newFinalAnswer: String) {
self.finalAnswer = newFinalAnswer
}
/// Adds a new user participation to the list of participations for the bet.
///
/// - Parameter newParticipation: The new user participation to be added.
public func addParticipation(newParticipation: Participation){
if !self.bet.registered.contains(where: { existingUser in
return existingUser.email == newParticipation.user.email
}) {
self.bet.addRegistered(newUser: newParticipation.user)
}
self.participations.append(newParticipation)
}
}

@ -1,8 +1,8 @@
//
// File.swift
// BetStatus.swift
//
//
// Created by étudiant on 23/01/2024.
// Created by Emre on 23/01/2024.
//
import Foundation

@ -12,9 +12,11 @@ public class CustomBetResponse {
/// The name or description of the custom bet response.
public var name: String
/// Custom Constructor
///
/// - Parameter name: The name or description of the custom bet response.
/// - Parameters:
/// - name: The name or description of the custom bet response.
public init(name: String) {
self.name = name
}

@ -16,8 +16,10 @@ public struct Manager {
self.userDataManager = userDataManager
}
public func addBet(theme: String, description: String, endRegister: Date, endBet: Date, isPublic: Bool, creator: User) {
userDataManager.addBet(bet: BinaryBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPublic: isPublic, status: .IN_PROGRESS, invited: [], author: creator, registered: []))
public func addBet(theme: String, description: String, endRegister: Date, endBet: Date, isPublic: Bool, creator: User, completion : @escaping (Int)-> ()) {
userDataManager.addBet(bet: BinaryBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPublic: isPublic, status: .IN_PROGRESS, invited: [], author: creator, registered: [])) { status in
completion(status)
}
}
public func getBets(withIndex index: Int, withCount count: Int, completion: @escaping ([Bet]) -> Void) {
@ -38,7 +40,9 @@ public struct Manager {
}
}
public func addParticipation(withId id: String, withAnswer answer: String, andStake stake: Int) {
userDataManager.addParticipation(withId: id, withAnswer: answer, andStake: stake)
public func addParticipation(withId id: String, withAnswer answer: String, andStake stake: Int, completion : @escaping (Int)-> ()) {
userDataManager.addParticipation(withId: id, withAnswer: answer, andStake: stake) { status in
completion(status)
}
}
}

@ -23,8 +23,8 @@ public class MatchBet: Bet {
/// - phrase: The specific phrase or question related to the match bet.
/// - endRegisterDate: The deadline for users to register for the match bet.
/// - endBetDate: The deadline for the actual betting to take place for the match bet.
/// - totalStakes: The total stakes or amount involved in the match bet.
/// - isPublic: Indicates whether the match bet is public or private.
/// - 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.
@ -43,8 +43,8 @@ public class MatchBet: Bet {
/// - phrase: The specific phrase or question related to the match bet.
/// - endRegisterDate: The deadline for users to register for the match bet.
/// - endBetDate: The deadline for the actual betting to take place for the match bet.
/// - totalStakes: The total stakes or amount involved in the match bet.
/// - isPublic: Indicates whether the match bet is public or private.
/// - 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.

@ -7,12 +7,28 @@
import Foundation
/// A struct representing a user with details such as username, email, number of coins, and friends.
public struct User {
/// The username of the user.
public private(set) var username: String
/// The email address of the user.
public private(set) var email: String
public private(set) var nbCoins: Int
/// The number of coins associated with the user.
public var nbCoins: Int
/// List of friends associated with the user.
public private(set) var friends: [User]
/// Custom constructor to initialize a User instance.
///
/// - Parameters:
/// - username: The username of the user.
/// - email: The email address of the user.
/// - nbCoins: The number of coins associated with the user.
/// - friends: List of friends associated with the user.
public init(username: String, email: String, nbCoins: Int, friends: [User]) {
self.username = username
self.email = email
@ -20,10 +36,17 @@ public struct User {
self.friends = friends
}
/// Adds a new friend to the list of friends for the user.
///
/// - Parameter user: The user to be added as a friend.
public mutating func addFriend(user: User) {
self.friends.append(user)
}
/// Maps user data from a JSON dictionary to create a User instance.
///
/// - Parameter json: The JSON dictionary containing user data.
/// - Returns: An optional User instance if mapping is successful, otherwise nil.
public static func mapUser(from json: [String: Any]) -> User? {
guard let username = json["username"] as? String,
let email = json["email"] as? String,

@ -9,8 +9,8 @@ import Foundation
public protocol UserDataManager {
func getBets(withIndex index: Int, withCount count: Int) -> [Bet]
func addBet(bet: Bet)
func addBet(bet: Bet, completion : @escaping (Int)-> ())
func getFriends() -> [User]
func getOldBets(withIndex index: Int, withCount count: Int, completion: @escaping ([Bet]) -> Void)
func addParticipation(withId id: String, withAnswer answer: String, andStake stake: Int)
func addParticipation(withId id: String, withAnswer answer: String, andStake stake: Int, completion : @escaping (Int)-> ())
}

Loading…
Cancel
Save