Compare commits

..

9 Commits

Author SHA1 Message Date
Lucas DELANIER a0a1b4b30f Merge branch 'master'
11 months ago
Lucas DELANIER ce4e858cc1 review cards
11 months ago
Lucas DELANIER 209205c1bd Merge branch 'fix/change-page-order'
11 months ago
Lucas DELANIER b32a4efe51 fix review card
11 months ago
Lucas DELANIER ee7ed587b0 Merge branch 'fix/final-view-detail'
11 months ago
Lucas DELANIER ba09fafef5 background color
11 months ago
Lucas DELANIER c3f4ac0a68 fix mistake ispublic
11 months ago
Lucas DELANIER c4263d3ad1 Fix menu order to be sync with android client
11 months ago
Lucas DELANIER 7a41d5379f final banner now working and bind with the wonparticipation on the betdetail
11 months ago

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

@ -8,12 +8,11 @@
import SwiftUI
struct AllcoinsCapsule: View {
var gains: Int
var body: some View {
Text("Vous remportez")
.foregroundColor(.white)
HStack{
Text(gains.description)
Text("2340")
.textStyle(weight: .bold, color: .white, size: 60)
Image("allcoinWhiteIcon")
.resizable()
@ -31,6 +30,6 @@ struct AllcoinsCapsule: View {
struct AllcoinsCapsule_Previews: PreviewProvider {
static var previews: some View {
AllcoinsCapsule(gains: 100)
AllcoinsCapsule()
}
}

@ -11,12 +11,12 @@ import Model
struct BetLineLoading: View {
@State var showInfos: Bool = false
var bet: BetDetail
var participations: [Participation]
var value: CGFloat {
let totalParticipations = bet.participations.count
let numberOfYes = bet.participations.filter { $0.answer.uppercased() == "YES" }.count
let numberOfNo = bet.participations.filter { $0.answer.uppercased() == "NO" }.count
let totalParticipations = participations.count
let numberOfYes = participations.filter { $0.answer.uppercased() == "YES" }.count
let numberOfNo = participations.filter { $0.answer.uppercased() == "NO" }.count
if(numberOfNo == 0 && numberOfYes == 0){
return 0.5
}
@ -25,21 +25,143 @@ struct BetLineLoading: View {
}
var yesParticipations: [Participation] {
bet.participations.filter { $0.answer.uppercased() == "YES" }
participations.filter { $0.answer.uppercased() == "YES" }
}
var noParticipations: [Participation] {
bet.participations.filter { $0.answer.uppercased() == "NO" }
participations.filter { $0.answer.uppercased() == "NO" }
}
var body: some View {
switch bet.bet {
case is BinaryBet:
BinaryBetLine(bet: bet)
case is CustomBet:
CustomBetLine(bet: bet)
default:
BinaryBetLine(bet: bet)
VStack(alignment: .leading, spacing: 0) {
HStack(spacing: 5) {
Text("OUI")
.font(.system(size: 25))
.fontWeight(.bold)
.foregroundColor(AllInColors.blue200)
Spacer()
Text("NON")
.font(.system(size: 25))
.fontWeight(.bold)
.foregroundColor(AllInColors.pink100)
}
GeometryReader { geometry in
ZStack(alignment: .leading) {
HStack{
Spacer()
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)
Image("loadingHeartIcon")
.resizable()
.frame(width: 29, height: 32)
.padding(.leading, -10)
}
}
.padding(.bottom, 5)
}
.frame(height: 40)
HStack {
Spacer()
Text("bet_status_details_drawer")
.textStyle(weight: .medium, color: AllInColors.primaryTextColor, size: 10)
Image(showInfos ? "chevronUpIcon" : "chevronDownIcon")
.resizable()
.frame(width: 10, height: 7)
.scaledToFill()
}
.onTapGesture {
withAnimation {
showInfos.toggle()
}
}
.padding(.bottom, 5)
.padding(.trailing, 5)
if showInfos {
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.blue200)
Spacer()
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: 12, height: 12)
}
HStack(spacing: 5){
Image("bluePersonIcon")
.resizable()
.frame(width: 12, 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("pinkPersonIcon")
.resizable()
.frame(width: 12, height: 12)
}
HStack(spacing: 5){
Image("blueBadgeIcon")
.resizable()
.frame(width: 12, height: 12)
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("pinkBadgeIcon")
.resizable()
.frame(width: 12, height: 12)
}
HStack(spacing: 5){
Image("blueTrophyIcon")
.resizable()
.frame(width: 12, height: 12)
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("pinkTrophyIcon")
.resizable()
.frame(width:12, height: 12)
}
}
}
}
}
}

@ -1,168 +0,0 @@
//
// BinaryBetLine.swift
// AllIn
//
// Created by Lucas Delanier on 10/06/2024.
//
import SwiftUI
import Model
struct BinaryBetLine: View {
@State var showInfos: Bool = false
var bet: BetDetail
var value: CGFloat {
let totalParticipations = bet.participations.count
let numberOfYes = bet.participations.filter { $0.answer.uppercased() == "YES" }.count
let numberOfNo = bet.participations.filter { $0.answer.uppercased() == "NO" }.count
if(numberOfNo == 0 && numberOfYes == 0){
return 0.5
}
return totalParticipations > 0 ? CGFloat(numberOfYes) / CGFloat(totalParticipations) : 0.0
}
var yesParticipations: [Participation] {
bet.participations.filter { $0.answer.uppercased() == "YES" }
}
var noParticipations: [Participation] {
bet.participations.filter { $0.answer.uppercased() == "NO" }
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
HStack(spacing: 5) {
Text("OUI")
.font(.system(size: 25))
.fontWeight(.bold)
.foregroundColor(AllInColors.blue200)
Spacer()
Text("NON")
.font(.system(size: 25))
.fontWeight(.bold)
.foregroundColor(AllInColors.pink100)
}
GeometryReader { geometry in
ZStack(alignment: .leading) {
HStack{
Spacer()
Rectangle()
.frame(width: min(CGFloat(1-self.value) * geometry.size.width, geometry.size.width-20), height: 17)
.foregroundStyle(AllInColors.PinkBetGradiant).cornerRadius(999)
}
HStack(spacing: 0) {
Rectangle()
.frame(width: min(CGFloat(self.value) * geometry.size.width, geometry.size.width-20), height: 17)
.foregroundStyle(AllInColors.BlueBetGradiant)
.cornerRadius(999)
Image("loadingHeartIcon")
.resizable()
.frame(width: 29, height: 32)
.padding(.leading, -10)
}
}
.padding(.bottom, 5)
}
.frame(height: 40)
HStack {
Spacer()
Text("bet_status_details_drawer")
.textStyle(weight: .medium, color: AllInColors.primaryTextColor, size: 10)
Image(showInfos ? "chevronUpIcon" : "chevronDownIcon")
.resizable()
.frame(width: 10, height: 7)
.scaledToFill()
}
.onTapGesture {
withAnimation {
showInfos.toggle()
}
}
.padding(.bottom, 5)
.padding(.trailing, 5)
if showInfos {
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.blue200)
Spacer()
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: 12, height: 12)
}
HStack(spacing: 5){
Image("bluePersonIcon")
.resizable()
.frame(width: 12, 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("pinkPersonIcon")
.resizable()
.frame(width: 12, height: 12)
}
HStack(spacing: 5){
Image("blueBadgeIcon")
.resizable()
.frame(width: 12, height: 12)
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("pinkBadgeIcon")
.resizable()
.frame(width: 12, height: 12)
}
HStack(spacing: 5){
Image("blueTrophyIcon")
.resizable()
.frame(width: 12, height: 12)
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("pinkTrophyIcon")
.resizable()
.frame(width:12, height: 12)
}
}
}
}
}
}

@ -15,29 +15,22 @@ struct ChoiceFinalAnswerCell: View {
var answer: AnswerDetail
var rawColor = AllInColors.blueAccentColor
var body: some View {
ZStack {
HStack {
ZStack{
HStack{
Spacer()
Text(answer.response)
.textStyle(weight: .bold, color: selected ? .white : rawColor, size: 40)
.padding(.vertical, 10)
.textStyle(weight: .bold, color: selected ? .white :rawColor, size: 40).padding(.vertical, 10)
Spacer()
}
HStack {
HStack{
Spacer()
OddCapsule(
backgroundColor: selected ? .white : AllInColors.purpleAccentColor,
foregroundColor: selected ? AllInColors.purpleAccentColor : .white,
odd: answer.odds
)
.padding(.trailing, 20)
.scaleEffect(0.9)
OddCapsule(backgroundColor: selected ? .white : AllInColors.purpleAccentColor, foregroundColor: selected ? AllInColors.purpleAccentColor : .white ,odd: answer.odds ).padding(.trailing,20).scaleEffect(0.9)
}
}
.background(selected ? AllInColors.purpleAccentColor : .white)
.cornerRadius(17)
.scaleEffect(selected ? 1.02 : 1)
.animation(.easeInOut(duration: 0.3), value: selected)
}.background(selected ? AllInColors.purpleAccentColor : .white).cornerRadius(17).scaleEffect(selected ? 1.02 : 1).animation(
.easeInOut(duration: 0.3),
value: selected
)
}
}

@ -1,141 +0,0 @@
//
// CustomBetLine.swift
// AllIn
//
// Created by Lucas Delanier on 10/06/2024.
//
import SwiftUI
import Model
struct CustomBetLine: View {
@State var showInfos: [String: Bool] = [:]
var bet: BetDetail
var participationsForAnswer: [String: [Participation]] {
Dictionary(grouping: bet.participations, by: { $0.answer.uppercased() })
}
var sortedAnswers: [AnswerDetail] {
bet.answers.sorted { $0.totalParticipants > $1.totalParticipants }
}
func getTextStyle(for answer: AnswerDetail) -> Font.Weight {
return answer == sortedAnswers.first ? .bold : .light
}
func getColor(for answer: AnswerDetail) -> Color {
return answer == sortedAnswers.first ? AllInColors.pinkAccentColor : AllInColors.blueAccentColor
}
func getGradiant(for answer: AnswerDetail) -> LinearGradient {
return answer == sortedAnswers.first ? AllInColors.PinkBetGradiant : AllInColors.BlueBetLineGradiant
}
func getFlameImage(for answer: AnswerDetail) -> String {
return answer == sortedAnswers.first ? "pinkFlameIcon" : "blueFlameIcon"
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
ForEach(sortedAnswers, id: \.response) { answer in
let participations = participationsForAnswer[answer.response.uppercased()] ?? []
let totalParticipations = bet.participations.count
let percentage = totalParticipations > 0 ? CGFloat(participations.count) / CGFloat(totalParticipations) : 0.0
VStack {
HStack {
Text(answer.response)
.font(.system(size: 15))
.fontWeight(getTextStyle(for: answer))
.foregroundColor(getColor(for: answer))
Spacer()
}
GeometryReader { geometry in
ZStack(alignment: .leading) {
HStack(spacing: 0) {
Rectangle()
.frame(width: min(percentage * geometry.size.width, geometry.size.width-20), height: 17)
.foregroundStyle(getGradiant(for: answer))
.cornerRadius(999, corners: [.topLeft, .bottomLeft])
Image(getFlameImage(for: answer))
.resizable()
.frame(width: 29, height: 32)
.padding(.leading, -6)
Text("\(Int(percentage * 100))%")
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundStyle(getColor(for: answer))
.padding(.leading, 2)
}
}
.padding(.bottom, 5)
}
.frame(height: 40)
HStack {
Spacer()
Text("bet_status_details_drawer")
.textStyle(weight: .medium, color: AllInColors.primaryTextColor, size: 10)
Image(showInfos[answer.response] ?? false ? "chevronUpIcon" : "chevronDownIcon")
.resizable()
.frame(width: 10, height: 7)
.scaledToFill()
}
.onTapGesture {
withAnimation {
showInfos[answer.response, default: false].toggle()
}
}
.padding(.trailing, 5)
if showInfos[answer.response] ?? false {
HStack{
VStack(alignment: .leading,spacing: 1) {
HStack(spacing: 5) {
Image(answer == sortedAnswers.first ? "pinkAllCoinIcon" : "blueAllCoinIcon")
.resizable()
.frame(width: 12, height: 12)
Text(participations.reduce(0, { x, y in x + y.stake }).description)
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(getColor(for: answer))
}
HStack(spacing: 5) {
Image(answer == sortedAnswers.first ? "pinkPersonIcon" : "bluePersonIcon")
.resizable()
.frame(width: 12, height: 12)
Text(participations.count.description)
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(getColor(for: answer))
}
HStack(spacing: 5) {
Image(answer == sortedAnswers.first ? "pinkBadgeIcon" : "blueBadgeIcon")
.resizable()
.frame(width: 12, height: 12)
Text(participations.max(by: { $0.stake < $1.stake })?.stake.description ?? "0")
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(getColor(for: answer))
}
HStack(spacing: 5) {
Image(answer == sortedAnswers.first ? "pinkTrophyIcon" : "blueTrophyIcon")
.resizable()
.frame(width: 12, height: 12)
Text(String(format: "%.2f", answer.odds))
.font(.system(size: 15))
.fontWeight(.bold)
.foregroundColor(getColor(for: answer))
}
}
Spacer()
}
}
}
}
}
}
}

@ -1,3 +1,12 @@
//
// DropDownAnswerMenu.swift
// AllIn
//
// Created by Lucas Delanier on 16/01/2024.
//
import SwiftUI
//
// DropDownMenu.swift
// AllIn
@ -6,21 +15,20 @@
//
import SwiftUI
import Model
struct DropDownAnswerMenu: View {
@State var expand = false
@Binding var selectedAnswer: AnswerDetail
var answers: [AnswerDetail]
@Binding var selectedOption: Int
var options: [(Int, String, Float)]
var body: some View {
VStack(spacing: 0, content: {
Button(action: { withTransaction(Transaction(animation: nil)) { self.expand.toggle() } }) {
Button(action: { self.expand.toggle() }) {
HStack{
Text(selectedAnswer.response)
Text(options[selectedOption].1.description)
.textStyle(weight: .bold, color: AllInColors.blueAccentColor, size: 20)
Text("\(selectedAnswer.odds, specifier: "%.2f")")
Text(options[selectedOption].2.description)
.textStyle(weight: .bold, color: AllInColors.lightPurpleColor, size: 10)
Spacer()
@ -35,16 +43,14 @@ struct DropDownAnswerMenu: View {
.foregroundColor(AllInColors.delimiterGrey)
.padding(.bottom, 18)
VStack(spacing: 0) {
ForEach(answers) { (answer: AnswerDetail) in
if answer != selectedAnswer {
Button(action: {
self.selectedAnswer = answer
self.expand.toggle()}
) {
ForEach(0..<options.count, id: \.self) { index in
if options[index].0 != selectedOption {
Button(action: {self.selectedOption = options[index].0
self.expand.toggle()}) {
HStack{
Text(answer.response)
Text(options[index].1.description)
.textStyle(weight: .bold, color: AllInColors.blueAccentColor, size: 20)
Text("\(answer.odds, specifier: "%.2f")")
Text(options[index].2.description)
.textStyle(weight: .bold, color: AllInColors.lightPurpleColor, size: 10)
Spacer()
}
@ -64,3 +70,15 @@ struct DropDownAnswerMenu: View {
)
}
}
struct DropDownAnswerMenu_Previews: PreviewProvider {
static var previews: some View {
DropDownAnswerMenu(selectedOption: .constant(0), options: [
(0, "questionMarkIcon", 1.2),
(1, "footballIcon", 2.2),
(2, "paintbrushIcon", 3.3)
])
.preferredColorScheme(.dark)
}
}

@ -29,7 +29,7 @@ struct Friend: View {
var body: some View {
HStack{
UserPicture(picture: user.image,username: user.username, size: 45)
UserPicture(picture: nil,username: user.username, size: 45)
Text(user.username)
.fontWeight(.medium)
.padding(.leading, 5)

@ -12,6 +12,7 @@ struct Menu: View {
@Inject var authService: IAuthService
let parameters: [(String, String, String, String)] = [
("videoGameImage", String(localized: "drawer_create_a_bet"), String(localized: "drawer_create_a_bet_subtitle"), "CreationBet"),
("globeImage", String(localized: "drawer_public_bets"), String(localized: "drawer_public_bets_subtitle"), "Bet"),
@ -39,7 +40,7 @@ struct Menu: View {
HStack(spacing: 30) {
Spacer()
VStack(){
Text(AppStateContainer.shared.user?.bestWin ?? 0, format: .number)
Text(AppStateContainer.shared.user?.bestWin.description ?? "0")
.fontWeight(.heavy)
.font(.system(size: 15))
.foregroundColor(.white)
@ -49,7 +50,7 @@ struct Menu: View {
.foregroundColor(AllInColors.grey600Color)
}
VStack(){
Text(AppStateContainer.shared.user!.bestWin, format: .number)
Text(AppStateContainer.shared.user?.bestWin.description ?? "0")
.fontWeight(.heavy)
.font(.system(size: 15))
.foregroundColor(.white)
@ -59,7 +60,7 @@ struct Menu: View {
.foregroundColor(AllInColors.grey600Color)
}
VStack(){
Text(AppStateContainer.shared.user!.nbFriends, format: .number)
Text(AppStateContainer.shared.user?.nbFriends.description ?? "0")
.fontWeight(.heavy)
.font(.system(size: 15))
.foregroundColor(.white)
@ -103,9 +104,6 @@ struct Menu: View {
.frame(maxWidth: .infinity,alignment: .leading)
.background(AllInColors.primaryColor)
.edgesIgnoringSafeArea(.bottom)
.onAppear {
authService.refreshAuthentication()
}
}
}

@ -14,7 +14,7 @@ struct OddCapsule: View {
var odd: Float = 0.0
var body: some View {
HStack(alignment: .center) {
Text("x\(odd, specifier: "%.2f")")
Text("x\(odd.description)")
.fontWeight(.bold)
.foregroundColor(foregroundColor)
}

@ -6,25 +6,33 @@
//
import SwiftUI
import Model
struct ParticipationModal: View {
@Binding var selectedAnswer: AnswerDetail
@Binding var mise: String
var phrase: String
var answers: [AnswerDetail]
var participationAddedCallback: () -> Void
var checkAndSetError: () -> Bool
@Binding private var selectedOption: Int
@Binding private var mise: String
private var description: String
var participationAddedCallback: (() -> Void)?
var possibleGain: Int {
if let stake = Float(mise) {
return Int(round(stake * selectedAnswer.odds))
if let stake = Float(mise), let selectedOption = options.first(where: { $0.0 == self.selectedOption }) {
return Int(round(stake * selectedOption.2))
} else {
return 0
}
}
init(answer: Binding<Int>, mise: Binding<String>, description: String, participationAddedCallback: (() -> Void)? = nil) {
self._selectedOption = answer
self._mise = mise
self.description = description
self.participationAddedCallback = participationAddedCallback
}
let options: [(Int, String, Float)] = [
(0, "OUI", 1.2),
(1, "NON", 3.3),
]
var body: some View {
GeometryReader { geometry in
VStack(alignment: .leading){
@ -48,12 +56,12 @@ struct ParticipationModal: View {
}
.padding(.leading, 15)
VStack(alignment: .leading){
Text(phrase)
Text(description)
.font(.system(size: 13))
.foregroundColor(AllInColors.primaryTextColor)
.fontWeight(.light)
DropDownAnswerMenu(selectedAnswer: $selectedAnswer, answers: answers)
DropDownAnswerMenu(selectedOption: $selectedOption, options: options)
TextField("", text: $mise, prompt: Text("generic_stake")
.foregroundColor(AllInColors.lightGrey300Color)
@ -96,7 +104,7 @@ struct ParticipationModal: View {
.padding(.top, 10)
.padding(.bottom, 0)
Button {
participationAddedCallback()
participationAddedCallback?()
} label: {
Text("Miser")
.font(.system(size: 23))
@ -117,4 +125,16 @@ struct ParticipationModal: View {
.background(AllInColors.underComponentBackgroundColor)
}
}
func checkAndSetError() -> Bool {
if let stake = Int(mise) {
if stake <= AppStateContainer.shared.user?.nbCoins ?? 0 && stake > 0 {
return false
} else {
return true
}
} else {
return true
}
}
}

@ -10,7 +10,7 @@ import SwiftUI
struct RankingRow: View {
var number: Int
var image: String?
var image: String
var pseudo: String
var allCoins: Int
@ -18,12 +18,12 @@ struct RankingRow: View {
HStack(){
Text(number.description)
.textStyle(weight: .bold, color: AllInColors.lightPurpleColor, size: 18)
UserInfo(username: pseudo, picture: image, value: allCoins)
.padding(.leading, 15)
UserInfo(username: pseudo, value: allCoins)
}
.padding(10)
.padding(.horizontal, 5)
.background(AllInColors.componentBackgroundColor)
.cornerRadius(8)
.padding([.leading,.trailing],20)
.frame(maxWidth: 750)
}
}

@ -6,11 +6,9 @@
//
import SwiftUI
import Model
struct RecapBetCard: View {
var betResult: BetResultDetail
@GestureState private var longPressTap = false
@State private var isPressed = false
@State var showDetails: Bool = false
@ -21,22 +19,22 @@ struct RecapBetCard: View {
VStack(alignment: .leading,spacing: 2){
HStack{
Spacer()
Text("bet_proposed_by_format \(betResult.bet.author)")
Text("bet_proposed_by_format \("Lucas")")
.font(.system(size: 10))
.foregroundColor(AllInColors.grey800Color)
}
Text(betResult.bet.theme)
Text("Etudes")
.font(.system(size: 15))
.foregroundColor(AllInColors.grey800Color)
Text(betResult.bet.phrase)
Text("Emre va réussir son TP de CI/CD mercredi?")
.font(.system(size: 20))
.fontWeight(.bold)
HStack{
Text("bet_ends")
.font(.system(size: 15))
.foregroundColor(AllInColors.grey800Color)
TextCapsule(date: betResult.bet.endBetDate)
TextCapsule(date: Date())
Spacer()
}
}
@ -50,7 +48,7 @@ struct RecapBetCard: View {
Text("Mise")
.textStyle(weight: .regular, color: AllInColors.grey800Color, size: 15)
Spacer()
Text(betResult.participation.stake.description)
Text("1630")
.textStyle(weight: .regular, color: AllInColors.grey800Color, size: 15)
Image("Allcoins")
.resizable()
@ -67,13 +65,13 @@ struct RecapBetCard: View {
Text("Gains")
.textStyle(weight: .medium, color: AllInColors.lightPurpleColor, size: 15)
Spacer()
Text(betResult.amount.description)
Text("1630")
.font(.system(size: 15))
.fontWeight(.medium)
.overlay {
AllInColors.primaryGradient.frame(width: 50)
.mask(
Text(betResult.amount.description).font(.system(size: 15)).fontWeight(.medium)
Text("1630").font(.system(size: 15)).fontWeight(.medium)
)
}
.padding(0)
@ -89,8 +87,7 @@ struct RecapBetCard: View {
HStack{
Text("Côte totale").font(.system(size: 15)).fontWeight(.medium)
Spacer()
// TODO bind le odd
Text("1,0")
Text("3,46")
.textStyle(weight: .bold, color: .white, size: 18)
.padding([.leading,.trailing],10)
.padding([.top,.bottom],5)
@ -111,7 +108,7 @@ struct RecapBetCard: View {
.onTapGesture {
showDetails.toggle()
}.fullScreenCover(isPresented: $showDetails) {
DetailsView(isModalPresented: $showDetails, isModalParticipated: $showPartipated, id: betResult.bet.id)
DetailsView(isModalPresented: $showDetails, isModalParticipated: $showPartipated,id: "1")
}
.gesture(
LongPressGesture(minimumDuration: 0.5)
@ -121,3 +118,10 @@ struct RecapBetCard: View {
)
}
}
struct RecapBetCard_Previews: PreviewProvider {
static var previews: some View {
RecapBetCard()
.preferredColorScheme(.dark)
}
}

@ -19,16 +19,16 @@ struct ResultBanner: View {
}.frame(height: 80)
HStack(spacing: 20){
HStack{
Image("blueAllCoinIcon").resizable().frame(maxWidth: 12, maxHeight: 12)
Image("BlueAllCoinIcon").resizable().frame(maxWidth: 12, maxHeight: 12)
Text(finalAnswer.stake.description).font(.system(size: 16)).fontWeight(.semibold).foregroundStyle(AllInColors.blueGrey800Color)
}
HStack{
Image("bluePersonIcon").resizable().frame(maxWidth: 15, maxHeight: 12)
Image("BleuePersonIcon").resizable().frame(maxWidth: 15, maxHeight: 12)
Text(finalAnswer.username).font(.system(size: 16)).fontWeight(.semibold).foregroundStyle(AllInColors.blueGrey800Color)
}
HStack{
Image("blueTrophyIcon").resizable().frame(maxWidth: 15, maxHeight: 12)
Text("\(odds, specifier: "%.2f")").font(.system(size: 16)).fontWeight(.semibold).foregroundStyle(AllInColors.blueGrey800Color)
Image("BleueTrophyIcon").resizable().frame(maxWidth: 15, maxHeight: 12)
Text(odds.description).font(.system(size: 16)).fontWeight(.semibold).foregroundStyle(AllInColors.blueGrey800Color)
}
}
}

@ -12,25 +12,26 @@ struct ReviewCard: View {
@State var showDetails: Bool = false
@State var showPartipated: Bool = false
var bet: Bet
var amount: Int
var isWin: Bool
@State var betDetail: BetDetail
var amountBetted: Int
var isAWin: Bool
var body: some View {
VStack(spacing: 0){
VStack(alignment: .leading,spacing: 2){
HStack{
Spacer()
Text("bet_proposed_by_format \(bet.author)")
Text("bet_proposed_by_format \(betDetail.bet.author)")
.font(.system(size: 10))
.foregroundColor(AllInColors.grey800Color)
}
Text(bet.theme).font(.system(size: 15)).foregroundColor(AllInColors.grey800Color)
Text(bet.phrase).font(.system(size: 20)).fontWeight(.bold)
Text(betDetail.bet.theme).font(.system(size: 15)).foregroundColor(AllInColors.grey800Color)
Text(betDetail.bet.phrase).font(.system(size: 20)).fontWeight(.bold)
HStack{
Text("bet_ends").font(.system(size: 15)).foregroundColor(AllInColors.grey800Color)
TextCapsule(date: bet.endBetDate)
TextCapsule(date: betDetail.bet.endBetDate)
Spacer()
}
@ -39,11 +40,12 @@ struct ReviewCard: View {
.padding(.all,15)
.background(AllInColors.componentBackgroundColor)
.cornerRadius(20, corners: [.topLeft,.topRight]).padding(.bottom,0)
VStack(alignment: .center,spacing:0){
HStack(){
Spacer()
if bet.status == .finished {
Text(amount.description)
if(betDetail.userParticipation != nil){
Text((betDetail.userParticipation?.stake.description ?? ""))
.foregroundColor(.white)
.font(.system(size: 25))
.fontWeight(.bold)
@ -51,8 +53,7 @@ struct ReviewCard: View {
.resizable()
.frame(width: 18, height: 20)
}
switch bet.status {
switch betDetail.bet.status {
case .waiting, .inProgress:
Text("bet_status_stake")
.foregroundColor(.white)
@ -64,7 +65,14 @@ struct ReviewCard: View {
.font(.system(size: 25))
.fontWeight(.bold)
case .finished:
Text(isWin ? "Gagnés!" : "Perdus!")
Text(amountBetted.description)
.foregroundColor(.white)
.font(.system(size: 25))
.fontWeight(.bold)
Image("allcoinWhiteIcon")
.resizable()
.frame(width: 20, height: 20, alignment: .bottom)
Text(isAWin ? "Gagnés!" : "Perdus!")
.foregroundColor(.white)
.font(.system(size: 25))
.fontWeight(.bold)
@ -83,31 +91,24 @@ struct ReviewCard: View {
}
.frame(width: .infinity)
.padding(.all,2)
.background(backgroundColor())
.cornerRadius(20, corners: [.bottomLeft,.bottomRight])
}
.onTapGesture {
showDetails.toggle()
}.fullScreenCover(isPresented: $showDetails) {
DetailsView(isModalPresented: $showDetails, isModalParticipated: $showPartipated, id: bet.id)
}
}
private func backgroundColor() -> some View {
Group {
if bet.status == .finished && isWin {
AllInColors.primaryGradient
} else {
switch bet.status {
.background({
switch betDetail.bet.status {
case .inProgress, .waiting, .closing:
AllInColors.grey50Color
return AllInColors.grey50Color
case .finished:
Color.black
return Color.black
case .cancelled:
Color.red
return Color.red
}
}())
.cornerRadius(20, corners: [.bottomLeft,.bottomRight])
.border(width: 1, edges: [.top], color: AllInColors.delimiterGrey)
}
.onTapGesture {
showDetails.toggle()
}.fullScreenCover(isPresented: $showDetails) {
DetailsView(isModalPresented: $showDetails, isModalParticipated: $showPartipated, id: betDetail.bet.id)
}
}
}

@ -10,11 +10,10 @@ import Model
struct UserInfo: View {
var username: String
var picture: String?
var value: Int
var body: some View {
HStack {
UserPicture(picture: picture, username: username, size: 35)
UserPicture(username: username, size: 35)
.padding(.trailing, 7)
Text(username)
.font(.system(size: 15))
@ -25,10 +24,10 @@ struct UserInfo: View {
.font(.system(size: 18))
.foregroundStyle(AllInColors.lightPurpleColor)
.fontWeight(.bold)
.padding(.trailing, 4)
.padding(.trailing, 8)
Image("PurpleAllCoin")
.resizable()
.frame(width: 15, height: 16)
.frame(width: 11, height: 12)
}
}
}

@ -6,11 +6,9 @@
//
import SwiftUI
import Model
struct WinModal: View {
@Environment(\.dismiss) var dismiss
var betResult: BetResultDetail
@State var xOffset: CGFloat = 0
var body: some View {
@ -37,15 +35,15 @@ struct WinModal: View {
}
HStack{
Text("FÉLICITATIONS").font(.system(size: 20)).foregroundColor(.white).fontWeight(.semibold).italic()
Text(AppStateContainer.shared.user?.username ?? "").padding(.top,9).font(.system(size: 33)).fontWeight(.heavy).foregroundColor(.white)
Text("PSEUDO!").padding(.top,9).font(.system(size: 33)).fontWeight(.heavy).foregroundColor(.white)
}
.rotationEffect(.degrees(-4))
.padding(.top,40)
Spacer()
AllcoinsCapsule(gains: betResult.amount)
AllcoinsCapsule()
Spacer()
RecapBetCard(betResult: betResult)
RecapBetCard()
Spacer()
}
.padding([.all],20)
@ -60,6 +58,12 @@ struct WinModal: View {
}
}
struct WinModal_Previews: PreviewProvider {
static var previews: some View {
WinModal()
}
}
struct InfiniteScroller<Content: View>: View {
var contentWidth: CGFloat
var content: (() -> Content)

@ -6,34 +6,27 @@
//
import SwiftUI
struct UserPicture: View {
var picture: String?
var username: String
var size: CGFloat
var body: some View {
ZStack {
if let pictureURL = picture {
userImage(url: pictureURL)
} else {
placeholderImage
}
}
}
@MainActor private func userImage(url: String) -> some View {
AsyncCachedImage(url: URL(string: url)) { image in
if picture != nil {
AsyncImage(
url: URL(string:picture!),
content: { image in
image
.resizable()
.frame(width: size, height: size)
.aspectRatio(contentMode: .fit)
.clipShape(Circle())
} placeholder: {
placeholderImage
},
placeholder: {
ProgressView()
}
}
private var placeholderImage: some View {
)
} else {
Circle()
.foregroundColor(.gray)
.frame(width: size, height: size)
@ -44,8 +37,10 @@ struct UserPicture: View {
.font(.system(size: fontSize(for: size)))
)
}
}
}
private func fontSize(for diameter: CGFloat) -> CGFloat {
func fontSize(for diameter: CGFloat) -> CGFloat {
let fontScaleFactor: CGFloat = 0.45
return diameter * fontScaleFactor
}

@ -77,12 +77,6 @@ struct AllInColors {
endPoint: .trailing
)
static let BlueBetLineGradiant = LinearGradient(
gradient: Gradient(colors: [AllInColors.blue200, AllInColors.blueAccentColor]),
startPoint: .leading,
endPoint: .trailing
)
static let PinkBetGradiant = LinearGradient(
gradient: Gradient(colors: [AllInColors.pink100, AllInColors.pink200]),
startPoint: .leading,

@ -178,7 +178,7 @@
/// Notification
"notification_title_end_bet_date" = "Who will be the winners?";
"notification_subtitle_end_bet_date %@" = "The %@ bet has reached its deadline. Go to the app to enter the winning answer.";
"notification_subtitle_end_bet_date %@" = "The %@ bet has reached its deadline. Go to the app to enter the winning answer.";`
/// Empty Views
@ -187,8 +187,3 @@
"empty_bets_title"= "No bet matches your search";
"empty_friends_title" = "You don't have any friends yet";
"empty_friends_explain" = "Add them from this screen";
/// Error Messages
"error_title" = "Error: Failed to Load Content.";
"error_message" = "The content you are trying to load could not be retrieved. Please check your internet connection and try again";

@ -28,7 +28,6 @@
"network_error_text" = "Assurez-vous d\'être bien connecté au réseau puis réessayez.";
/// Bet type
"bet_type_binary" = "Oui / Non";
"bet_type_match" = "Match sportif";
"bet_type_custom" = "Réponses personnalisées";
@ -187,8 +186,3 @@
"empty_bets_title"= "Aucun Bet ne correspond à votre recherche";
"empty_friends_title" = "Vous navez pas encore damis";
"empty_friends_explain" = "Ajoutez les depuis cet écran";
/// Error Messages
"error_title" = "Erreur : Échec du chargement du contenu.";
"error_message" = "Le contenu que vous essayez de charger n'a pas pu être récupéré. Veuillez vérifier votre connexion internet et réessayer.";

@ -1,71 +0,0 @@
//
// asyncCachedImage.swift
// AllIn
//
// Created by Lucas Delanier on 06/06/2024.
//
import SwiftUI
@MainActor
struct AsyncCachedImage<ImageView: View, PlaceholderView: View>: View {
// Input dependencies
var url: URL?
@ViewBuilder var content: (Image) -> ImageView
@ViewBuilder var placeholder: () -> PlaceholderView
// Downloaded image
@State var image: UIImage? = nil
init(
url: URL?,
@ViewBuilder content: @escaping (Image) -> ImageView,
@ViewBuilder placeholder: @escaping () -> PlaceholderView
) {
self.url = url
self.content = content
self.placeholder = placeholder
}
var body: some View {
VStack {
if let uiImage = image {
content(Image(uiImage: uiImage))
} else {
placeholder()
.onAppear {
Task {
image = await downloadPhoto()
}
}
}
}
}
// Downloads if the image is not cached already
// Otherwise returns from the cache
private func downloadPhoto() async -> UIImage? {
do {
guard let url else { return nil }
// Check if the image is cached already
if let cachedResponse = URLCache.shared.cachedResponse(for: .init(url: url)) {
return UIImage(data: cachedResponse.data)
} else {
let (data, response) = try await URLSession.shared.data(from: url)
// Save returned image data into the cache
URLCache.shared.storeCachedResponse(.init(response: response, data: data), for: .init(url: url))
guard let image = UIImage(data: data) else {
return nil
}
return image
}
} catch {
print("Error downloading: \(error)")
return nil
}
}
}

@ -13,13 +13,11 @@ import Combine
class BetViewModel: ObservableObject {
@Inject var manager: Manager
@Inject var authService: IAuthService
@Published var popularBet: Bet?
@Published private(set) var bets: [Bet] = []
@Published var betsOver: [BetDetail] = []
@Published var betsWon: [BetResultDetail] = []
@Published var showingSheetOver: Bool = false
@Published var showingSheetWon: Bool = false
@Published var showingSheet: Bool = false
@Published var filters: Set<BetFilter> = [] {
didSet {
getItems()
@ -30,7 +28,6 @@ class BetViewModel: ObservableObject {
getItems()
getPopularBet()
getBetsOver()
getBetsWon()
}
func getItems() {
@ -46,19 +43,7 @@ class BetViewModel: ObservableObject {
DispatchQueue.main.async {
self.betsOver = bets
if !self.betsOver.isEmpty {
self.showingSheetOver = true
}
}
}
}
func getBetsWon() {
manager.getBetsWon() { bets in
DispatchQueue.main.async {
self.betsWon = bets
if !self.betsWon.isEmpty {
self.showingSheetWon = true
self.authService.refreshAuthentication()
self.showingSheet = true
}
}
}

@ -23,36 +23,19 @@ class CreationBetViewModel: ObservableObject {
@Published var endRegisterDate = Date()
@Published var endBetDate = Date()
@Published var betAdded = false
@Published var selectedTypeBet = 0 {
didSet {
values.removeAll()
groupedItems.removeAll()
response = ""
}
}
@Published var values: [String] = []
@Published var selectedOption = 0
@Published var invited: Set<String> = []
@Published var themeFieldError: String?
@Published var descriptionFieldError: String?
@Published var endRegisterDateFieldError: String?
@Published var endBetDateFieldError: String?
@Published var responsesFieldError: String?
@Published var errorMessage: String?
@Published var showErrorMessage = false
@Published var friends: [User] = []
let options: [(Int, String, String)] = [
(0, "questionMarkIcon", String(localized: "bet_type_binary")),
(1, "footballIcon", String(localized: "bet_type_match")),
(2, "paintbrushIcon", String(localized: "bet_type_custom"))
]
@Published var response = ""
@Published var groupedItems: [[String]] = [[String]] ()
init() {
getFriends()
}
@ -67,14 +50,14 @@ class CreationBetViewModel: ObservableObject {
func create() {
guard checkAndSetError(forTheme: true, forDescription: true, forEndRegisterDate: true, forEndBetDate: true, forResponse: true) else {
guard checkAndSetError(forTheme: true, forDescription: true, forEndRegisterDate: true, forEndBetDate: true) else {
return
}
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, invited: Array(invited), type: selectedTypeBet)) { 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:
@ -89,13 +72,12 @@ class CreationBetViewModel: ObservableObject {
}
}
func checkAndSetError(forTheme checkTheme: Bool, forDescription checkDescription: Bool, forEndRegisterDate checkEndRegisterDate: Bool, forEndBetDate checkEndBetDate: Bool, forResponse checkResponse: Bool) -> Bool {
func checkAndSetError(forTheme checkTheme: Bool, forDescription checkDescription: Bool, forEndRegisterDate checkEndRegisterDate: Bool, forEndBetDate checkEndBetDate: Bool) -> Bool {
var newThemeFieldError: String?
var newDescriptionFieldError: String?
var newEndRegisterDateFieldError: String?
var newEndBetDateFieldError: String?
var newResponsesFieldError: String?
var hasError = false
@ -123,19 +105,6 @@ class CreationBetViewModel: ObservableObject {
hasError = true
}
if checkResponse, selectedTypeBet == 2 {
if values.count < 2 {
newResponsesFieldError = "Il doit y'avoir 2 réponses minimum"
hasError = true
} else {
let uniqueValues = Set(values)
if uniqueValues.count != values.count {
newResponsesFieldError = "Les réponses doivent être uniques"
hasError = true
}
}
}
if !hasError {
// No error
return true
@ -146,7 +115,6 @@ class CreationBetViewModel: ObservableObject {
descriptionFieldError = newDescriptionFieldError
endRegisterDateFieldError = newEndRegisterDateFieldError
endBetDateFieldError = newEndBetDateFieldError
responsesFieldError = newResponsesFieldError
}
return false
}
@ -157,7 +125,6 @@ class CreationBetViewModel: ObservableObject {
descriptionFieldError = nil
endRegisterDateFieldError = nil
endBetDateFieldError = nil
responsesFieldError = nil
}
}
@ -173,11 +140,7 @@ class CreationBetViewModel: ObservableObject {
case 1:
return MatchBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: invited, author: creator, nameTeam1: "", nameTeam2: "")
case 2:
var bet = CustomBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPrivate: isPrivate, status: status, invited: invited, author: creator)
for answer in values {
bet.addCustomResponse(answer)
}
return bet
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: invited, author: creator)
}

@ -15,7 +15,7 @@ class DetailsViewModel: ObservableObject {
@Inject var manager: Manager
var id: String
@Published var selectedAnswer = AnswerDetail(response: "", totalStakes: 0, totalParticipants: 0, highestStake: 0, odds: 0)
@Published var answer = 0
@Published var mise: String = ""
@Published var betDetail: BetDetail?
@ -26,26 +26,25 @@ class DetailsViewModel: ObservableObject {
}
func getItem(withId id: String) {
let semaphore = DispatchSemaphore(value: 0)
manager.getBet(withId: id) { bet in
self.betDetail = bet
if let firstAnswer = bet.answers.first {
self.selectedAnswer = firstAnswer
DispatchQueue.main.async {
for par in bet.participations {
print(par.id)
}
semaphore.signal()
self.betDetail = bet
}
let result = semaphore.wait(timeout: DispatchTime.now() + .seconds(2))
if result == .timedOut {
print("The request has exceeded the deadline")
return
}
}
func addParticipate() {
if let stake = Int(mise) {
manager.addParticipation(withId: id, withAnswer: selectedAnswer.response, andStake: stake) { statusCode in
var rep: String = ""
if answer == 0 {
rep = "Yes"
} else {
rep = "No"
}
manager.addParticipation(withId: id, withAnswer: rep, andStake: stake) { statusCode in
switch statusCode {
case 201:
AppStateContainer.shared.user?.nbCoins -= stake
@ -58,20 +57,10 @@ class DetailsViewModel: ObservableObject {
}
}
mise = ""
if let firstAnswer = betDetail!.answers.first {
self.selectedAnswer = firstAnswer
}
answer = 0
}
func checkAndSetError() -> Bool {
if let stake = Int(mise) {
if stake <= AppStateContainer.shared.user?.nbCoins ?? 0 && stake > 0 {
return false
} else {
return true
}
} else {
return true
}
func checkAndSetError() {
}
}

@ -13,7 +13,7 @@ class HistoricBetViewModel: ObservableObject {
@Inject var manager: Manager
@Published private(set) var bets: [BetResultDetail] = []
@Published private(set) var bets: [BetDetail] = []
init() {
getItems()

@ -15,10 +15,10 @@ struct BetEndingValidationView: View {
@Environment(\.dismiss) var dismiss
@StateObject private var viewModel: BetEndingValidationViewModel
var betDetail: BetDetail
var bet: BetDetail
init(bet: BetDetail) {
self.betDetail = bet
self.bet = bet
self._viewModel = StateObject(wrappedValue: BetEndingValidationViewModel(id: bet.bet.id))
}
@ -48,7 +48,7 @@ struct BetEndingValidationView: View {
dismiss()
}
}
ReviewCard(bet: betDetail.bet, amount: 0, isWin: false)
ReviewCard(betDetail: bet, amountBetted: 0, isAWin: false)
.padding(.top, 20)
.padding(.bottom, 10)
Text("bet_confirmation_text")
@ -64,7 +64,7 @@ struct BetEndingValidationView: View {
.frame(maxWidth: .infinity, alignment: .leading)
VStack(spacing: 14){
ForEach(betDetail.answers) { answer in
ForEach(bet.answers) { answer in
ChoiceFinalAnswerCell(selected : answer.response == viewModel.selectedAnswer, answer: answer).onTapGesture {
if(viewModel.selectedAnswer == answer.response){
viewModel.selectedAnswer = nil

@ -59,22 +59,14 @@ struct BetView: View {
.refreshable {
viewModel.getItems()
}
.sheet(isPresented: $viewModel.showingSheetOver, onDismiss: {
.sheet(isPresented: $viewModel.showingSheet, onDismiss: {
viewModel.betsOver.removeFirst()
viewModel.showingSheetOver = !viewModel.betsOver.isEmpty
viewModel.showingSheet = !viewModel.betsOver.isEmpty
}) {
if let firstBetDetail = viewModel.betsOver.first {
BetEndingValidationView(bet: firstBetDetail)
}
}
.sheet(isPresented: $viewModel.showingSheetWon, onDismiss: {
viewModel.betsWon.removeFirst()
viewModel.showingSheetWon = !viewModel.betsWon.isEmpty
}) {
if let firstBetResultDetail = viewModel.betsWon.first {
WinModal(betResult: firstBetResultDetail)
}
}
Spacer()
}
.edgesIgnoringSafeArea(.bottom)

@ -28,6 +28,17 @@ struct CreationBetView: View {
}()
let screenWidth = UIScreen.main.bounds.width
@State private var response = ""
@State private var values: [String] = []
let options: [(Int, String, String)] = [
(0, "questionMarkIcon", String(localized: "bet_type_binary")),
(1, "footballIcon", String(localized: "bet_type_match")),
(2, "paintbrushIcon", String(localized: "bet_type_custom"))
]
@State var groupedItems: [[String]] = [[String]] ()
private func updateGroupedItems() {
var updatedGroupedItems: [[String]] = [[String]] ()
@ -35,7 +46,7 @@ struct CreationBetView: View {
var width: CGFloat = 0
var dynamicWidthLimit: CGFloat
for value in viewModel.values {
for value in values {
let label = UILabel()
label.text = value
label.sizeToFit()
@ -54,7 +65,7 @@ struct CreationBetView: View {
}
updatedGroupedItems.append(tempItems)
viewModel.groupedItems = updatedGroupedItems
groupedItems = updatedGroupedItems
}
var body: some View {
@ -97,7 +108,6 @@ struct CreationBetView: View {
.foregroundColor(AllInColors.lightGrey300Color)
.font(.system(size: 14))
.fontWeight(.light))
.autocorrectionDisabled(true)
.padding()
.background(
RoundedRectangle(cornerRadius: 9)
@ -141,7 +151,6 @@ struct CreationBetView: View {
.foregroundColor(AllInColors.lightGrey300Color)
.font(.system(size: 14))
.fontWeight(.light), axis: .vertical)
.autocorrectionDisabled(true)
.lineLimit(4, reservesSpace: true)
.padding()
.background(
@ -351,14 +360,14 @@ struct CreationBetView: View {
VStack(spacing: 5) {
VStack() {
DropDownMenu(selectedOption: $viewModel.selectedTypeBet, options: viewModel.options)
DropDownMenu(selectedOption: $viewModel.selectedOption, options: options)
}
.padding([.bottom], 15)
.frame(width: 340)
Group {
switch viewModel.selectedTypeBet {
switch viewModel.selectedOption {
case 0:
Text("bet_creation_yes_no_bottom_text_1")
.textStyle(weight: .bold, color: AllInColors.veryLightPurpleColor, size: 13)
@ -376,18 +385,12 @@ struct CreationBetView: View {
.textStyle(weight: .bold, color: AllInColors.veryLightPurpleColor, size: 13)
.padding(.bottom, 15)
if let responseError = $viewModel.responsesFieldError.wrappedValue {
Text(responseError)
.textStyle(weight: .bold, color: .red, size: 10)
}
VStack(spacing: 5) {
HStack(spacing: 0) {
TextField("", text: $viewModel.response, prompt: Text("bet_creation_response_title")
TextField("", text: $response, prompt: Text("bet_creation_response_title")
.foregroundColor(AllInColors.lightGrey200Color)
.font(.system(size: 16))
.fontWeight(.medium))
.autocorrectionDisabled(true)
.padding()
.background(
Rectangle()
@ -397,17 +400,17 @@ struct CreationBetView: View {
)
.frame(width: 250, height: 38)
.foregroundColor(.black)
.onChange(of: viewModel.response) { newValue in
.onChange(of: response) { newValue in
if newValue.count > 20 {
viewModel.response = String(newValue.prefix(20))
response = String(newValue.prefix(20))
}
}
Button(action: {
if !viewModel.response.isEmpty && viewModel.values.count < 5 {
viewModel.values.append(viewModel.response)
if !response.isEmpty && values.count < 5 {
values.append(response)
updateGroupedItems()
viewModel.response = ""
response = ""
}
}) {
Text("generic_add")
@ -420,12 +423,12 @@ struct CreationBetView: View {
}
HStack {
Spacer()
Text(String(localized: "bet_creation_max_answers \(5 - viewModel.values.count)"))
Text(String(localized: "bet_creation_max_answers \(5 - values.count)"))
.textStyle(weight: .regular, color: AllInColors.primaryTextColor, size: 12)
}
VStack(spacing: 10) {
ForEach(viewModel.groupedItems, id: \.self) { items in
ForEach(groupedItems, id: \.self) { items in
HStack {
ForEach(items, id: \.self) { text in
HStack {
@ -433,8 +436,8 @@ struct CreationBetView: View {
.foregroundColor(.white)
.lineLimit(1)
Button(action: {
if let index = viewModel.values.firstIndex(of: text) {
viewModel.values.remove(at: index)
if let index = values.firstIndex(of: text) {
values.remove(at: index)
updateGroupedItems()
}
}) {

@ -23,8 +23,8 @@ struct CurrentBetView: View {
.textStyle(weight: .bold, color: AllInColors.grey500Color, size: 25)
.padding([.top],15)
VStack(spacing: 20){
ForEach(viewModel.bets, id: \.bet.id) { (betDetail: BetDetail) in
ReviewCard(bet: betDetail.bet, amount: betDetail.userParticipation?.stake ?? 0, isWin: false)
ForEach(viewModel.bets, id: \.bet.id) { (bet: BetDetail) in
ReviewCard(betDetail: bet, amountBetted: 110, isAWin: false)
}
}
.padding([.trailing, .leading, .bottom],25)

@ -57,9 +57,9 @@ struct DetailsView: View {
}
.padding(.horizontal, 15)
.background(StatusValues.1)
if viewModel.betDetail != nil{
ScrollView {
VStack(alignment: .leading, spacing: 0) {
VStack(spacing: 0) {
VStack(alignment: .leading, spacing: 5) {
HStack(spacing: 3) {
Spacer()
Text("bet_proposed_by_format")
@ -105,69 +105,49 @@ struct DetailsView: View {
}
}
.padding(.all, 15)
.padding(.top, 6)
.border(width: 1, edges: [.bottom], color: AllInColors.delimiterGrey)
.padding(.vertical, 10)
.background(AllInColors.componentBackgroundColor)
.cornerRadius(20, corners: [.topLeft,.topRight])
.cornerRadius(20, corners: [.topLeft,.topRight]).padding(.bottom,0)
if isFinished {
ResultBanner(finalAnswer: (viewModel.betDetail?.wonParticipation)!, odds: (viewModel.betDetail?.odds)!)
}
VStack(alignment: .leading, spacing: 0) {
if let bet = viewModel.betDetail{
BetLineLoading(bet: bet).padding(.vertical, 20)
}
VStack(alignment: .leading, spacing: 5) {
BetLineLoading(participations: viewModel.betDetail?.participations ?? [])
.padding(.vertical,15)
Text("bet_status_participants_list")
.font(.system(size: 18))
.foregroundStyle(AllInColors.grey100Color)
.fontWeight(.bold)
.padding(.bottom, 10)
ScrollView(showsIndicators: false) {
ForEach(viewModel.betDetail?.participations ?? []) { participation in
UserInfo(username: participation.username, picture: nil , value: participation.stake).padding(.horizontal, 10)
UserInfo(username: participation.username, value: participation.stake).padding(.horizontal, 10)
}
.padding(.bottom)
Spacer()
}
.padding([.trailing,.leading], 15)
.padding(.bottom, 100)
.padding(.bottom, geometry.safeAreaInsets.bottom + 28)
}
.frame(maxWidth: .infinity, maxHeight: (geometry.size.height + geometry.safeAreaInsets.bottom) - 50)
.background(AllInColors.underComponentBackgroundColor)
.cornerRadius(15, corners: [.topLeft, .topRight])
}
else{
ScrollView {
HStack(alignment: .center){
Spacer()
Image(systemName: "exclamationmark.triangle.fill").font(.system(size: 45))
VStack(alignment:.leading){
Text("error_title").font(.system(size: 10))
Text("error_message").font(.system(size: 10))
}
.padding([.bottom,.trailing,.leading], 15)
.background(AllInColors.underComponentBackgroundColor)
.border(width: 1, edges: [.top], color: AllInColors.delimiterGrey)
Spacer()
}.opacity(0.6)
.padding(.vertical, 20)
}
.frame(maxWidth: .infinity, maxHeight: (geometry.size.height + geometry.safeAreaInsets.bottom) - 50)
.background(AllInColors.underComponentBackgroundColor)
.background(AllInColors.componentBackgroundColor)
.cornerRadius(15, corners: [.topLeft, .topRight])
}
ParticipateButton(isOpen: $isModalPresented, isParticapatedOpen: $isModalParticipated, bet: viewModel.betDetail?.bet)
.padding(.bottom, geometry.safeAreaInsets.bottom + 5)
.padding(.horizontal, 10)
}
.sheet(isPresented: $isModalParticipated) {
ParticipationModal(selectedAnswer: $viewModel.selectedAnswer, mise: $viewModel.mise, phrase: viewModel.betDetail?.bet.phrase ?? "", answers: viewModel.betDetail?.answers ?? [], participationAddedCallback: {
ParticipationModal(answer: $viewModel.answer, mise: $viewModel.mise, description: viewModel.betDetail?.bet.phrase ?? "Not loaded", participationAddedCallback: {
viewModel.addParticipate()
isModalParticipated.toggle()
},
checkAndSetError: viewModel.checkAndSetError)
})
.presentationDetents([.fraction(0.55)])
}
.edgesIgnoringSafeArea(.bottom)

@ -64,7 +64,6 @@ struct FriendsView: View {
}
.padding(.top, 50)
.tag(0)
ScrollView{
VStack(alignment: .center, spacing: 0) {
if(viewModel.requests.isEmpty){
EmptyInfo(emoji:"📬", title: "Aucune demande d'amis en attente", explain: "").padding(.top, 40)
@ -82,9 +81,6 @@ struct FriendsView: View {
}
Spacer()
}
}.refreshable {
viewModel.getRequests()
}
.padding(.top, 50)
.tag(1)
}

@ -24,8 +24,8 @@ struct HistoricBetView: View {
.textStyle(weight: .bold, color: AllInColors.grey500Color, size: 25)
.padding([.top],15)
VStack(spacing: 20){
ForEach(viewModel.bets, id: \.bet.id) { (betDetail: BetResultDetail) in
ReviewCard(bet: betDetail.bet, amount: betDetail.participation.stake, isWin: betDetail.won)
ForEach(viewModel.bets, id: \.bet.id) { (bet: BetDetail) in
ReviewCard(betDetail: bet, amountBetted: 110, isAWin: false)
}
}
.padding([.trailing, .leading, .bottom],25)

@ -60,8 +60,8 @@ struct MainView: View {
if self.showMenu {
Menu()
.transition(.move(edge: .leading))
.frame(width: geometry.size.width*0.83)
.transition(.move(edge: .leading))
}
}

@ -51,7 +51,7 @@ struct RankingView: View {
.cornerRadius(41.5, corners: .topLeft)
.cornerRadius(8, corners: .topRight)
.cornerRadius(15, corners: [.bottomLeft, .bottomRight])
UserPicture(picture: viewModel.friends[0].image, username: viewModel.friends[0].username, size: 70)
UserPicture(picture: nil, username: viewModel.friends[0].username, size: 70)
.offset(x: 0, y: -55)
Text("1")
@ -95,7 +95,7 @@ struct RankingView: View {
.cornerRadius(8, corners: .topLeft)
.cornerRadius(15, corners: [.bottomLeft, .bottomRight])
UserPicture(picture: viewModel.friends[1].image, username: viewModel.friends[1].username, size: 50)
UserPicture(picture: nil, username: viewModel.friends[1].username, size: 50)
.offset(x: 0, y: -50)
Text("2")
@ -122,14 +122,13 @@ struct RankingView: View {
let friend = viewModel.friends[index]
RankingRow(
number: index + 1,
image: friend.image,
image: "defaultUserImage",
pseudo: friend.username,
allCoins: friend.nbCoins
)
}
}
.padding(.top, 10)
.padding(.horizontal, 20)
}
Spacer()
}

@ -9,15 +9,12 @@
/* Begin PBXBuildFile section */
120919182B56D0AE00D0FA29 /* ParticipationModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 120919172B56D0AE00D0FA29 /* ParticipationModal.swift */; };
1209191A2B56DC6C00D0FA29 /* DropDownAnswerMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 120919192B56DC6C00D0FA29 /* DropDownAnswerMenu.swift */; };
12228A212C1760D2008524F4 /* BinaryBetLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12228A202C1760D2008524F4 /* BinaryBetLine.swift */; };
12228A232C176117008524F4 /* CustomBetLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12228A222C176117008524F4 /* CustomBetLine.swift */; };
123225D92B67B46100D30BB3 /* BetEndingValidationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123225D82B67B46100D30BB3 /* BetEndingValidationView.swift */; };
123225DB2B67E41400D30BB3 /* ChoiceFinalAnswerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123225DA2B67E41400D30BB3 /* ChoiceFinalAnswerCell.swift */; };
123590B42B51792000F7AEBD /* DetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123590B32B51792000F7AEBD /* DetailsView.swift */; };
123590B62B5537E200F7AEBD /* ResultBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123590B52B5537E200F7AEBD /* ResultBanner.swift */; };
123590B82B5541BA00F7AEBD /* ParticipateButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123590B72B5541BA00F7AEBD /* ParticipateButton.swift */; };
123F31DB2C0F26E8009B6D65 /* userPicture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123F31DA2C0F26E8009B6D65 /* userPicture.swift */; };
123F31E02C11E99E009B6D65 /* asyncCachedImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123F31DF2C11E99E009B6D65 /* asyncCachedImage.swift */; };
1244EF602B4EC31E00374ABF /* HistoricBetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1244EF5F2B4EC31E00374ABF /* HistoricBetView.swift */; };
1244EF622B4EC67000374ABF /* ReviewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1244EF612B4EC67000374ABF /* ReviewCard.swift */; };
129D051D2B6E7FF0003D3E08 /* OddCapsule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 129D051C2B6E7FF0003D3E08 /* OddCapsule.swift */; };
@ -151,15 +148,12 @@
120919192B56DC6C00D0FA29 /* DropDownAnswerMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownAnswerMenu.swift; sourceTree = "<group>"; };
122278B72B4BDE1100E632AA /* DependencyInjection.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DependencyInjection.framework; sourceTree = BUILT_PRODUCTS_DIR; };
122278B92B4BDE9500E632AA /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Package.swift; path = ../Model/Package.swift; sourceTree = "<group>"; };
12228A202C1760D2008524F4 /* BinaryBetLine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinaryBetLine.swift; sourceTree = "<group>"; };
12228A222C176117008524F4 /* CustomBetLine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomBetLine.swift; sourceTree = "<group>"; };
123225D82B67B46100D30BB3 /* BetEndingValidationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BetEndingValidationView.swift; sourceTree = "<group>"; };
123225DA2B67E41400D30BB3 /* ChoiceFinalAnswerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChoiceFinalAnswerCell.swift; sourceTree = "<group>"; };
123590B32B51792000F7AEBD /* DetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailsView.swift; sourceTree = "<group>"; };
123590B52B5537E200F7AEBD /* ResultBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultBanner.swift; sourceTree = "<group>"; };
123590B72B5541BA00F7AEBD /* ParticipateButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParticipateButton.swift; sourceTree = "<group>"; };
123F31DA2C0F26E8009B6D65 /* userPicture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = userPicture.swift; sourceTree = "<group>"; };
123F31DF2C11E99E009B6D65 /* asyncCachedImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = asyncCachedImage.swift; sourceTree = "<group>"; };
1244EF5F2B4EC31E00374ABF /* HistoricBetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoricBetView.swift; sourceTree = "<group>"; };
1244EF612B4EC67000374ABF /* ReviewCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewCard.swift; sourceTree = "<group>"; };
129D051C2B6E7FF0003D3E08 /* OddCapsule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OddCapsule.swift; sourceTree = "<group>"; };
@ -280,14 +274,6 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
123F31DE2C11E979009B6D65 /* Utils */ = {
isa = PBXGroup;
children = (
123F31DF2C11E99E009B6D65 /* asyncCachedImage.swift */,
);
path = Utils;
sourceTree = "<group>";
};
EC1D15402B715A7A0094833E /* Protocols */ = {
isa = PBXGroup;
children = (
@ -323,7 +309,6 @@
EC6B969A2B24B4CC00FC1C58 /* AllIn */ = {
isa = PBXGroup;
children = (
123F31DE2C11E979009B6D65 /* Utils */,
ECF872852B93B9D900F9D240 /* AllIn.entitlements */,
EC7EF7462B87E3470022B5D9 /* QuickActions */,
ECB7BC662B2F1AAD002A6654 /* ViewModels */,
@ -448,8 +433,6 @@
129D051C2B6E7FF0003D3E08 /* OddCapsule.swift */,
12A9E4932C07132600AB8677 /* EmptyInfo.swift */,
123F31DA2C0F26E8009B6D65 /* userPicture.swift */,
12228A202C1760D2008524F4 /* BinaryBetLine.swift */,
12228A222C176117008524F4 /* CustomBetLine.swift */,
);
path = Components;
sourceTree = "<group>";
@ -681,7 +664,6 @@
files = (
EC6B96CC2B24B7E500FC1C58 /* IAuthService.swift in Sources */,
ECB26A172B4073F100FE06B3 /* CreationBetViewModel.swift in Sources */,
12228A232C176117008524F4 /* CustomBetLine.swift in Sources */,
EC3077092B24CF7F0060E34D /* Colors.swift in Sources */,
EC6B969E2B24B4CC00FC1C58 /* ContentView.swift in Sources */,
EC89F7BD2B250D66003821CE /* LoginView.swift in Sources */,
@ -694,7 +676,6 @@
EC6B969C2B24B4CC00FC1C58 /* AllInApp.swift in Sources */,
123590B42B51792000F7AEBD /* DetailsView.swift in Sources */,
ECB26A192B40744F00FE06B3 /* RankingViewModel.swift in Sources */,
123F31E02C11E99E009B6D65 /* asyncCachedImage.swift in Sources */,
EC650A502B2793D5003AFCAD /* TextCapsule.swift in Sources */,
EC650A482B25DCFF003AFCAD /* UsersPreview.swift in Sources */,
EC17A15E2B6A955E008A8679 /* CurrentBetView.swift in Sources */,
@ -728,7 +709,6 @@
EC01937E2B25C52E005D81E6 /* TopBar.swift in Sources */,
ECA9D1CB2B2DA2320076E0EC /* DropDownFriends.swift in Sources */,
123590B82B5541BA00F7AEBD /* ParticipateButton.swift in Sources */,
12228A212C1760D2008524F4 /* BinaryBetLine.swift in Sources */,
EC01FCC32B56650400BB2390 /* DetailsViewModel.swift in Sources */,
ECB26A1B2B40746C00FE06B3 /* FriendsViewModel.swift in Sources */,
ECB7BC682B2F1ADF002A6654 /* LoginViewModel.swift in Sources */,
@ -936,7 +916,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"AllIn/Preview Content\"";
DEVELOPMENT_TEAM = P39ZK4GA2T;
DEVELOPMENT_TEAM = 35KQ5BDC64;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "All In";
@ -970,7 +950,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"AllIn/Preview Content\"";
DEVELOPMENT_TEAM = P39ZK4GA2T;
DEVELOPMENT_TEAM = 35KQ5BDC64;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "All In";
@ -1074,7 +1054,7 @@
CODE_SIGN_ENTITLEMENTS = AllInWidgetsExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = P39ZK4GA2T;
DEVELOPMENT_TEAM = 35KQ5BDC64;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = AllInWidgets/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AllInWidgets;
@ -1102,7 +1082,7 @@
CODE_SIGN_ENTITLEMENTS = AllInWidgetsExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = P39ZK4GA2T;
DEVELOPMENT_TEAM = 35KQ5BDC64;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = AllInWidgets/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AllInWidgets;

@ -77,7 +77,6 @@ public struct BetApiManager: BetDataManager {
do {
if let httpResponse = response as? HTTPURLResponse, let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
print(httpResponse.statusCode)
print(json)
if let betDetail = FactoryApiBet().toBetDetail(from: json) {
completion(betDetail)
}

@ -24,7 +24,7 @@ public class FactoryApiBet: FactoryBet {
"endRegistration": formatZonedDateTime(dateTime: bet.endRegisterDate),
"endBet": formatZonedDateTime(dateTime: bet.endBetDate),
"isPrivate": String(bet.isPrivate),
"response": bet.getResponses(),
"response": ["Yes","No"],
"userInvited": bet.invited,
"type": betTypeString(fromType: String(describing: type(of: bet)))
]
@ -88,51 +88,20 @@ public class FactoryApiBet: FactoryBet {
do {
wonParticipation = try JSONDecoder().decode(Participation.self, from: JSONSerialization.data(withJSONObject: participationJson))
} catch {
print("Error decoding participation: \(error)")
print("Error decoding participations: \(error)")
}
}
if let participationUserJson = json["userParticipation"] as? [String: Any] {
do {
userParticipation = try JSONDecoder().decode(Participation.self, from: JSONSerialization.data(withJSONObject: participationUserJson))
} catch {
print("Error decoding participation: \(error)")
print("Error decoding participations: \(error)")
}
}
return BetDetail(bet: bet, answers: answers, participations: participations, wonParticipation: wonParticipation, userParticipation: userParticipation)
}
public func toBetResultDetail(from json: [String: Any]) -> BetResultDetail? {
guard let amount = json["amount"] as? Int,
let won = json["won"] as? Bool else {
return nil
}
guard let betJson = json["bet"] as? [String: Any],
let bet = self.toBet(from: betJson) else {
return nil
}
let decoder = JSONDecoder()
guard let betResultJson = json["betResult"] as? [String: Any],
let betResultData = try? JSONSerialization.data(withJSONObject: betResultJson),
let betResult = try? decoder.decode(BetResult.self, from: betResultData) else {
print("Error decoding bet result")
return nil
}
guard let participationJson = json["participation"] as? [String: Any],
let participationData = try? JSONSerialization.data(withJSONObject: participationJson),
let participation = try? decoder.decode(Participation.self, from: participationData) else {
print("Error decoding participation")
return nil
}
return BetResultDetail(betResult: betResult, bet: bet, participation: participation, amount: amount, won: won)
}
public func betTypeString(fromType type: String) -> String {
switch type {
case "BinaryBet":

@ -52,38 +52,6 @@ public struct UserApiManager: UserDataManager {
}.resume()
}
public func getBetsWon(completion : @escaping ([BetResultDetail])-> ()) {
let url = URL(string: url + "bets/getWon")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
var bets: [BetResultDetail] = []
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
print ("ALLIN : get bets won")
do {
if let httpResponse = response as? HTTPURLResponse, let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
for json in jsonArray {
if let bet = FactoryApiBet().toBetResultDetail(from: json) {
print(bet)
bets.append(bet)
}
}
print(httpResponse.statusCode)
completion(bets)
}
} catch {
print("Error parsing JSON: \(error)")
}
}
}.resume()
}
public func addBet(bet: Bet, completion : @escaping (Int)-> ()) {
let url = URL(string: url + "bets/add")!
@ -250,7 +218,7 @@ public struct UserApiManager: UserDataManager {
}.resume()
}
public func getOldBets(withIndex index: Int, withCount count: Int, completion: @escaping ([BetResultDetail]) -> Void) {
public func getOldBets(withIndex index: Int, withCount count: Int, completion: @escaping ([BetDetail]) -> Void) {
let url = URL(string: url + "bets/history")!
var request = URLRequest(url: url)
@ -258,16 +226,15 @@ public struct UserApiManager: UserDataManager {
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
var bets: [BetResultDetail] = []
var bets: [BetDetail] = []
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
print ("ALLIN : get old bets")
do {
if let httpResponse = response as? HTTPURLResponse, let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
print(jsonArray)
for json in jsonArray {
if let bet = FactoryApiBet().toBetResultDetail(from: json) {
if let bet = FactoryApiBet().toBetDetail(from: json) {
bets.append(bet)
}
}

@ -343,7 +343,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = P39ZK4GA2T;
DEVELOPMENT_TEAM = 35KQ5BDC64;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
@ -382,7 +382,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = P39ZK4GA2T;
DEVELOPMENT_TEAM = 35KQ5BDC64;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";

@ -8,7 +8,7 @@
import Foundation
/// A class representing detailed information about a specific answer option for a bet.
public class AnswerDetail: ObservableObject, Codable, Equatable, Identifiable, Hashable {
public class AnswerDetail: ObservableObject, Identifiable, Codable {
/// The response or outcome associated with this answer.
public private(set) var response: String
@ -41,19 +41,4 @@ public class AnswerDetail: ObservableObject, Codable, Equatable, Identifiable, H
self.odds = odds
}
public static func == (lhs: AnswerDetail, rhs: AnswerDetail) -> Bool {
return lhs.response == rhs.response &&
lhs.totalStakes == rhs.totalStakes &&
lhs.totalParticipants == rhs.totalParticipants &&
lhs.highestStake == rhs.highestStake &&
lhs.odds == rhs.odds
}
public func hash(into hasher: inout Hasher) {
hasher.combine(response)
hasher.combine(totalStakes)
hasher.combine(totalParticipants)
hasher.combine(highestStake)
hasher.combine(odds)
}
}

@ -8,7 +8,7 @@
import Foundation
/// A class representing a betting entity, including details about the bet theme, participants, and deadlines.
public class Bet: ObservableObject, Codable {
public class Bet: ObservableObject, Identifiable, Codable {
/// The id for the bet.
public private(set) var id: String
@ -112,11 +112,4 @@ public class Bet: ObservableObject, Codable {
self.author = author
}
/// Function that returns an empty list of responses
///
/// - Returns: An empty list of responses
public func getResponses() -> [String] {
return []
}
}

@ -1,21 +0,0 @@
//
// BetResult.swift
//
//
// Created by Emre on 06/06/2024.
//
import Foundation
public class BetResult: Codable {
public private(set) var betId: String
public private(set) var result: String
public init(betId: String, result: String) {
self.betId = betId
self.result = result
}
}

@ -1,30 +0,0 @@
//
// BetResultDetail.swift
//
//
// Created by Emre on 06/06/2024.
//
import Foundation
public class BetResultDetail: Codable {
public private(set) var betResult: BetResult
public private(set) var bet: Bet
public private(set) var participation: Participation
public private(set) var amount: Int
public private(set) var won: Bool
public init(betResult: BetResult, bet: Bet, participation: Participation, amount: Int, won: Bool) {
self.betResult = betResult
self.bet = bet
self.participation = participation
self.amount = amount
self.won = won
}
}

@ -10,21 +10,4 @@ import Foundation
/// A subclass of Bet that represents a custom bet, allowing users to define their own parameters and rules.
public class CustomBet: Bet {
/// List of custom responses
private var customResponses: [String] = []
/// Override the getResponses function to return custom responses
///
/// - Returns: A list of custom responses
public override func getResponses() -> [String] {
return customResponses
}
/// Add a custom response
///
/// - Parameter response: The custom response to add
public func addCustomResponse(_ response: String) {
customResponses.append(response)
}
}

@ -11,5 +11,4 @@ public protocol FactoryBet {
func toResponse(bet: Bet) -> [String: Any]
func toBet(from json: [String: Any]) -> Bet?
func toBetDetail(from json: [String: Any]) -> BetDetail?
func toBetResultDetail(from json: [String: Any]) -> BetResultDetail?
}

@ -46,12 +46,6 @@ public struct Manager {
}
}
public func getBetsWon(completion: @escaping ([BetResultDetail]) -> Void) {
userDataManager.getBetsWon() { bets in
completion(bets)
}
}
public func getBet(withId id: String, completion: @escaping (BetDetail) -> Void) {
betDataManager.getBet(withId: id) { bet in
completion(bet)
@ -76,7 +70,7 @@ public struct Manager {
}
}
public func getHistoricBets(withIndex index: Int, withCount count: Int, completion: @escaping ([BetResultDetail]) -> Void) {
public func getHistoricBets(withIndex index: Int, withCount count: Int, completion: @escaping ([BetDetail]) -> Void) {
userDataManager.getOldBets(withIndex: index, withCount: count) { bets in
completion(bets)
}

@ -10,7 +10,6 @@ import Foundation
public protocol UserDataManager {
func getBets(withIndex index: Int, withCount count: Int) -> [Bet]
func getBetsOver(completion: @escaping ([BetDetail]) -> Void)
func getBetsWon(completion : @escaping ([BetResultDetail])-> ())
func addBet(bet: Bet, completion : @escaping (Int)-> ())
func addFriend(username: String, completion : @escaping (Int)-> ())
func removeFriend(username: String, completion : @escaping (Int)-> ())
@ -18,7 +17,7 @@ public protocol UserDataManager {
func getRequests(completion: @escaping ([User]) -> Void)
func getUsers(withName name: String, completion: @escaping ([User]) -> Void)
func getGifts(completion : @escaping (Int, Int)-> ())
func getOldBets(withIndex index: Int, withCount count: Int, completion: @escaping ([BetResultDetail]) -> Void)
func getOldBets(withIndex index: Int, withCount count: Int, completion: @escaping ([BetDetail]) -> Void)
func getCurrentBets(withIndex index: Int, withCount count: Int, completion: @escaping ([BetDetail]) -> Void)
func addParticipation(withId id: String, withAnswer answer: String, andStake stake: Int, completion : @escaping (Int)-> ())
func addResponse(withIdBet id: String, andResponse responseBet: String)

Loading…
Cancel
Save