Compare commits
29 Commits
fix/partic
...
master
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 354 KiB |
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "blueFlame.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.4 KiB |
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "globe.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 39 KiB |
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "pinkFlame.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.5 KiB |
@ -0,0 +1,168 @@
|
||||
//
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
//
|
||||
// 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,35 +0,0 @@
|
||||
//
|
||||
// ParticipationCell.swift
|
||||
// AllIn
|
||||
//
|
||||
// Created by Lucas Delanier on 21/01/2024.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Model
|
||||
|
||||
struct ParticipationCell: View {
|
||||
var participation: Participation
|
||||
var body: some View {
|
||||
HStack(alignment: .center, spacing: 0){
|
||||
Circle()
|
||||
.frame(width: 30, height: 30)
|
||||
.foregroundColor(AllInColors.grey700Color)
|
||||
.padding(.trailing, 7)
|
||||
Text(participation.username)
|
||||
.font(.system(size: 15))
|
||||
.foregroundStyle(AllInColors.primaryTextColor)
|
||||
.fontWeight(.semibold)
|
||||
Spacer()
|
||||
Text(participation.stake.description)
|
||||
.font(.system(size: 18))
|
||||
.foregroundStyle(AllInColors.lightPurpleColor)
|
||||
.fontWeight(.bold)
|
||||
.padding(.trailing, 8)
|
||||
Image("PurpleAllCoin")
|
||||
.resizable()
|
||||
.frame(width: 11, height: 12)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
//
|
||||
// userPicture.swift
|
||||
// AllIn
|
||||
//
|
||||
// Created by Lucas Delanier on 04/06/2024.
|
||||
//
|
||||
|
||||
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
|
||||
image
|
||||
.resizable()
|
||||
.frame(width: size, height: size)
|
||||
.clipShape(Circle())
|
||||
} placeholder: {
|
||||
placeholderImage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var placeholderImage: some View {
|
||||
Circle()
|
||||
.foregroundColor(.gray)
|
||||
.frame(width: size, height: size)
|
||||
.overlay(
|
||||
Text(username.prefix(2).uppercased())
|
||||
.fontWeight(.medium)
|
||||
.foregroundStyle(.white)
|
||||
.font(.system(size: fontSize(for: size)))
|
||||
)
|
||||
}
|
||||
|
||||
private func fontSize(for diameter: CGFloat) -> CGFloat {
|
||||
let fontScaleFactor: CGFloat = 0.45
|
||||
return diameter * fontScaleFactor
|
||||
}
|
||||
}
|
||||
|
||||
struct UserPicture_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
UserPicture(picture: nil, username: "Lucas", size: 100)
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
//
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
//
|
||||
// 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
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
//
|
||||
// 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
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in new issue