fixed some issues
This commit is contained in:
@@ -267,7 +267,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Club Portal/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Club Portal/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = BSGYUG5U29;
|
DEVELOPMENT_TEAM = BSGYUG5U29;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -300,7 +300,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Club Portal/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Club Portal/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = BSGYUG5U29;
|
DEVELOPMENT_TEAM = BSGYUG5U29;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
|
|||||||
-16
@@ -100,22 +100,6 @@
|
|||||||
landmarkType = "24">
|
landmarkType = "24">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
<BreakpointProxy
|
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
||||||
<BreakpointContent
|
|
||||||
uuid = "1D973B51-0BF4-4CAE-9D3D-08BB2000E001"
|
|
||||||
shouldBeEnabled = "No"
|
|
||||||
ignoreCount = "0"
|
|
||||||
continueAfterRunningActions = "No"
|
|
||||||
filePath = "Club Portal/UI/Dashboard/DashboardView.swift"
|
|
||||||
startingColumnNumber = "9223372036854775807"
|
|
||||||
endingColumnNumber = "9223372036854775807"
|
|
||||||
startingLineNumber = "66"
|
|
||||||
endingLineNumber = "66"
|
|
||||||
landmarkName = "body"
|
|
||||||
landmarkType = "24">
|
|
||||||
</BreakpointContent>
|
|
||||||
</BreakpointProxy>
|
|
||||||
<BreakpointProxy
|
<BreakpointProxy
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
<BreakpointContent
|
<BreakpointContent
|
||||||
|
|||||||
@@ -256,6 +256,52 @@ final class APIService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func requestStatics(_ endpoint: Endpoint) async throws -> ClubStatisticsResponse? {
|
||||||
|
guard let request = endpoint.urlRequest else {
|
||||||
|
throw APIError.invalidURL
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Request URL: \(request.url?.absoluteString ?? "Invalid URL")")
|
||||||
|
|
||||||
|
let (data, response) = try await URLSession.shared.data(for: request)
|
||||||
|
|
||||||
|
guard let httpResponse = response as? HTTPURLResponse else {
|
||||||
|
throw APIError.invalidResponse(0, "No HTTP response received")
|
||||||
|
}
|
||||||
|
|
||||||
|
print("HTTP Status Code: \(httpResponse.statusCode)")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if !(200..<300).contains(httpResponse.statusCode) {
|
||||||
|
if let errorResponse = try? JSONDecoder().decode(ErrorResponse.self, from: data) {
|
||||||
|
if errorResponse.message == "TOKEN_EXPIRED" {
|
||||||
|
// Perform logout
|
||||||
|
throw APIError.logout
|
||||||
|
}
|
||||||
|
throw APIError.serverError(errorResponse.message)
|
||||||
|
} else {
|
||||||
|
throw APIError.invalidResponse(httpResponse.statusCode, "Unknown server error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if let responseString = String(data: data, encoding: .utf8) {
|
||||||
|
print("Response: \(responseString)")
|
||||||
|
if let resp = ClubStatisticsResponse(JSONString: responseString) {
|
||||||
|
print(resp)
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
throw APIError.decodingError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func requestCoach(_ endpoint: Endpoint) async throws -> CoacheList? {
|
func requestCoach(_ endpoint: Endpoint) async throws -> CoacheList? {
|
||||||
guard let request = endpoint.urlRequest else {
|
guard let request = endpoint.urlRequest else {
|
||||||
throw APIError.invalidURL
|
throw APIError.invalidURL
|
||||||
|
|||||||
+290
-41
@@ -4,65 +4,314 @@
|
|||||||
//
|
//
|
||||||
// Created by Umer Tahir on 11/04/2025.
|
// Created by Umer Tahir on 11/04/2025.
|
||||||
//
|
//
|
||||||
|
import ObjectMapper
|
||||||
|
|
||||||
|
|
||||||
struct ClubStatisticsResponse: Decodable {
|
class ClubStatisticsResponse : Mappable {
|
||||||
let error: Bool
|
var error : Bool?
|
||||||
let model: ClubStatisticsModel
|
var model : ClubStatisticsModel?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ClubStatisticsModel: Decodable {
|
func mapping(map: Map) {
|
||||||
let clinicReservations: [ReservationStats]
|
|
||||||
let coachReservations: [ReservationStats]
|
error <- map["error"]
|
||||||
let totalReservations: [ReservationStats]
|
model <- map["model"]
|
||||||
let revenueHeatMap: [RevenueHeatMap]
|
|
||||||
let revenueByDateRange: [RevenueByDateRange]
|
|
||||||
let revenueByModule: [RevenueByModule]
|
|
||||||
let buddyStatistics: [ReservationStats]
|
|
||||||
let totalExpenses: [ExpenseStats]
|
|
||||||
let totalRevenue: [RevenueStats]
|
|
||||||
let totalProfit: [ProfitStats]
|
|
||||||
let courtUtilization: [CourtUtilizationStats]
|
|
||||||
let lessonReservations: [ReservationStats]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ReservationStats: Decodable {
|
|
||||||
let total_hours: Double?
|
|
||||||
let total_revenue: Double?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RevenueHeatMap: Decodable {
|
class ClubStatisticsModel : Mappable {
|
||||||
let date: String
|
var clinicReservations : [ClinicReservations]?
|
||||||
let total_revenue: Double
|
var coachReservations : [CoachReservations]?
|
||||||
|
var totalReservations : [TotalReservations]?
|
||||||
|
var revenueHeatMap : [RevenueHeatMap]?
|
||||||
|
var revenueByDateRange : [RevenueByDateRange]?
|
||||||
|
var revenueByModule : [RevenueByModule]?
|
||||||
|
var buddyStatistics : [BuddyStatistics]?
|
||||||
|
var totalExpenses : [TotalExpenses]?
|
||||||
|
var totalRevenue : [TotalRevenue]?
|
||||||
|
var totalProfit : [TotalProfit]?
|
||||||
|
var courtUtilization : [CourtUtilization]?
|
||||||
|
var lessonReservations : [LessonReservations]?
|
||||||
|
var revenueByDay : [RevenueByDay]?
|
||||||
|
var revenueBarChart : RevenueBarChart?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RevenueByDateRange: Decodable {
|
func mapping(map: Map) {
|
||||||
// Add fields if needed
|
|
||||||
|
clinicReservations <- map["clinicReservations"]
|
||||||
|
coachReservations <- map["coachReservations"]
|
||||||
|
totalReservations <- map["totalReservations"]
|
||||||
|
revenueHeatMap <- map["revenueHeatMap"]
|
||||||
|
revenueByDateRange <- map["revenueByDateRange"]
|
||||||
|
revenueByModule <- map["revenueByModule"]
|
||||||
|
buddyStatistics <- map["buddyStatistics"]
|
||||||
|
totalExpenses <- map["totalExpenses"]
|
||||||
|
totalRevenue <- map["totalRevenue"]
|
||||||
|
totalProfit <- map["totalProfit"]
|
||||||
|
courtUtilization <- map["courtUtilization"]
|
||||||
|
lessonReservations <- map["lessonReservations"]
|
||||||
|
revenueByDay <- map["revenueByDay"]
|
||||||
|
revenueBarChart <- map["revenueBarChart"]
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RevenueByModule: Decodable {
|
|
||||||
let module: String
|
|
||||||
let revenue: Double?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExpenseStats: Decodable {
|
class BuddyStatistics : Mappable {
|
||||||
let total_hours: Double?
|
var total_hours : String?
|
||||||
let total_expense: Double?
|
var total_revenue : String?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RevenueStats: Decodable {
|
func mapping(map: Map) {
|
||||||
let total_hours: Double?
|
|
||||||
let total_revenue: Double?
|
total_hours <- map["total_hours"]
|
||||||
|
total_revenue <- map["total_revenue"]
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ProfitStats: Decodable {
|
|
||||||
let total_profit: Double?
|
|
||||||
let total_revenue: Double?
|
|
||||||
let total_expense: Double?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CourtUtilizationStats: Decodable {
|
class ClinicReservations : Mappable {
|
||||||
let utilization_percentage: Double?
|
var total_hours : String?
|
||||||
let total_used_hours: Double?
|
var total_revenue : String?
|
||||||
let total_available_hours: Double?
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
total_hours <- map["total_hours"]
|
||||||
|
total_revenue <- map["total_revenue"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CoachReservations : Mappable {
|
||||||
|
var total_hours : String?
|
||||||
|
var total_revenue : String?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
total_hours <- map["total_hours"]
|
||||||
|
total_revenue <- map["total_revenue"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class CourtUtilization : Mappable {
|
||||||
|
var utilization_percentage : String?
|
||||||
|
var total_used_hours : String?
|
||||||
|
var total_available_hours : String?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
utilization_percentage <- map["utilization_percentage"]
|
||||||
|
total_used_hours <- map["total_used_hours"]
|
||||||
|
total_available_hours <- map["total_available_hours"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class BarData : Mappable {
|
||||||
|
var clinic : [Int]?
|
||||||
|
var coach : [Double]?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
clinic <- map["clinic"]
|
||||||
|
coach <- map["coach"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class LessonReservations : Mappable {
|
||||||
|
var total_hours : String?
|
||||||
|
var total_revenue : String?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
total_hours <- map["total_hours"]
|
||||||
|
total_revenue <- map["total_revenue"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class RevenueBarChart : Mappable {
|
||||||
|
var days : [String]?
|
||||||
|
var data : BarData?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
days <- map["days"]
|
||||||
|
data <- map["data"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class RevenueByDateRange : Mappable {
|
||||||
|
var date : String?
|
||||||
|
var clinic_revenue : String?
|
||||||
|
var coach_revenue : String?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
date <- map["date"]
|
||||||
|
clinic_revenue <- map["clinic_revenue"]
|
||||||
|
coach_revenue <- map["coach_revenue"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class RevenueByDay : Mappable {
|
||||||
|
var day : String?
|
||||||
|
var module : String?
|
||||||
|
var revenue : Double?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
day <- map["day"]
|
||||||
|
module <- map["module"]
|
||||||
|
revenue <- map["revenue"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class RevenueByModule : Mappable {
|
||||||
|
var module : String!
|
||||||
|
var revenue : Int!
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
module <- map["module"]
|
||||||
|
revenue <- map["revenue"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class RevenueHeatMap : Mappable {
|
||||||
|
var date : String?
|
||||||
|
var total_revenue : Double?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
date <- map["date"]
|
||||||
|
total_revenue <- map["total_revenue"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TotalExpenses : Mappable {
|
||||||
|
var total_hours : String?
|
||||||
|
var total_expense : String?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
total_hours <- map["total_hours"]
|
||||||
|
total_expense <- map["total_expense"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TotalProfit : Mappable {
|
||||||
|
var total_profit : Int?
|
||||||
|
var total_revenue : Double?
|
||||||
|
var total_expense : Double?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
total_profit <- map["total_profit"]
|
||||||
|
total_revenue <- map["total_revenue"]
|
||||||
|
total_expense <- map["total_expense"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TotalReservations : Mappable {
|
||||||
|
var total_hours : String?
|
||||||
|
var total_revenue : String?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
total_hours <- map["total_hours"]
|
||||||
|
total_revenue <- map["total_revenue"]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TotalRevenue : Mappable {
|
||||||
|
var total_hours : String?
|
||||||
|
var total_revenue : String?
|
||||||
|
|
||||||
|
required init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapping(map: Map) {
|
||||||
|
|
||||||
|
total_hours <- map["total_hours"]
|
||||||
|
total_revenue <- map["total_revenue"]
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+3
@@ -101,6 +101,7 @@ class Booking : Mappable, Identifiable {
|
|||||||
var create_at : String?
|
var create_at : String?
|
||||||
var update_at : String?
|
var update_at : String?
|
||||||
var coach_ids : String?
|
var coach_ids : String?
|
||||||
|
var sport_name : String?
|
||||||
|
|
||||||
required init?(map: Map) {
|
required init?(map: Map) {
|
||||||
|
|
||||||
@@ -144,6 +145,8 @@ class Booking : Mappable, Identifiable {
|
|||||||
create_at <- map["create_at"]
|
create_at <- map["create_at"]
|
||||||
update_at <- map["update_at"]
|
update_at <- map["update_at"]
|
||||||
coach_ids <- map["coach_ids"]
|
coach_ids <- map["coach_ids"]
|
||||||
|
sport_name <- map["sport_name"]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,12 @@ struct AvailabilityScreen: View {
|
|||||||
.onChange(of: endDate) { _ in
|
.onChange(of: endDate) { _ in
|
||||||
viewModel.getAvailability(startDate: startDate.toCustomString, endDate: endDate.toCustomString, startTime: startTime.toTimeString, endTime: endTime.toTimeString)
|
viewModel.getAvailability(startDate: startDate.toCustomString, endDate: endDate.toCustomString, startTime: startTime.toTimeString, endTime: endTime.toTimeString)
|
||||||
}
|
}
|
||||||
|
.onChange(of: startTime) { _ in
|
||||||
|
viewModel.getAvailability(startDate: startDate.toCustomString, endDate: endDate.toCustomString, startTime: startTime.toTimeString, endTime: endTime.toTimeString)
|
||||||
|
}
|
||||||
|
.onChange(of: endTime) { _ in
|
||||||
|
viewModel.getAvailability(startDate: startDate.toCustomString, endDate: endDate.toCustomString, startTime: startTime.toTimeString, endTime: endTime.toTimeString)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,29 +8,47 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct CoachesTab: View {
|
struct CoachesTab: View {
|
||||||
|
@EnvironmentObject var viewModel : DashViewModel
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading, spacing: 12) {
|
VStack(alignment: .leading, spacing: 12) {
|
||||||
ForEach(0..<3, id: \.self) { _ in
|
|
||||||
HStack(spacing: 12) {
|
|
||||||
ProfileImageView(imageUrl: "", size: 40)
|
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
if let players = viewModel.coaches {
|
||||||
Text("Steve Jobs")
|
|
||||||
|
|
||||||
|
ForEach(players, id: \.id) { index in
|
||||||
|
HStack(spacing: 12) {
|
||||||
|
ProfileImageView(imageUrl: index.user?.photo ?? "", size: 40)
|
||||||
|
|
||||||
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
|
Text("\(index.user?.first_name ?? "") \(index.user?.last_name ?? "" )")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
Text("Hours playing: 9:00 AM – 10:00 AM")
|
|
||||||
.font(.caption)
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color(.systemGray6))
|
|
||||||
.cornerRadius(10)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
|
.onAppear(){
|
||||||
|
if let ids = viewModel.selectedReservation?.booking?.coach_ids?.toCommaSeparated {
|
||||||
|
|
||||||
|
viewModel.getCoaches(playerIds: ids)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ struct DetailsTab: View {
|
|||||||
DetailRow(title: "Reservation date", value: viewModel.selectedReservation?.booking?.date ?? "16 April, 2024")
|
DetailRow(title: "Reservation date", value: viewModel.selectedReservation?.booking?.date ?? "16 April, 2024")
|
||||||
DetailRow(title: "Time", value: "\(viewModel.selectedReservation?.booking?.start_time ?? "16:00:00" ) - \(viewModel.selectedReservation?.booking?.end_time ?? "16:00:00" ) ")
|
DetailRow(title: "Time", value: "\(viewModel.selectedReservation?.booking?.start_time ?? "16:00:00" ) - \(viewModel.selectedReservation?.booking?.end_time ?? "16:00:00" ) ")
|
||||||
DetailRow(title: "Event type", value: "Lesson")
|
DetailRow(title: "Event type", value: "Lesson")
|
||||||
DetailRow(title: "Sport/type", value: "\(viewModel.selectedReservation?.booking?.sport_id ?? 1) • \(viewModel.selectedReservation?.booking?.type ?? "") • \(viewModel.selectedReservation?.booking?.subtype ?? "") ")
|
DetailRow(title: "Sport/type", value: "\(viewModel.selectedReservation?.booking?.sport_name ?? "") • \(viewModel.selectedReservation?.booking?.type ?? "") • \(viewModel.selectedReservation?.booking?.subtype ?? "") ")
|
||||||
DetailRow(title: "Repeating", value: "Every week")
|
DetailRow(title: "Repeating", value: "Every week")
|
||||||
DetailRow(title: "Space assigned", value: "Court #5")
|
DetailRow(title: "Space assigned", value: "Court #5")
|
||||||
DetailRow(title: "Court fee", value: "$\(viewModel.selectedReservation?.booking?.court_fee ?? "10")")
|
DetailRow(title: "Court fee", value: "$\(viewModel.selectedReservation?.booking?.court_fee ?? "10")")
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ struct ScheduleFilterView: View {
|
|||||||
}
|
}
|
||||||
.padding(.top, 10)
|
.padding(.top, 10)
|
||||||
} label: {
|
} label: {
|
||||||
Text("Club")
|
Text("Courts")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
|
|||||||
@@ -13,34 +13,44 @@ struct PlayersTab: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading, spacing: 12) {
|
VStack(alignment: .leading, spacing: 12) {
|
||||||
ForEach(0..<5, id: \.self) { index in
|
if let players = viewModel.players {
|
||||||
|
ForEach(players, id: \.id) { index in
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
ProfileImageView(imageUrl: "", size: 40)
|
ProfileImageView(imageUrl: index.photo, size: 40)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 2) {
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
Text("Steve Jobs")
|
Text("\(index.first_name ?? "") \(index.last_name ?? "" )")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
|
|
||||||
if index == 0 {
|
// if index == 0 {
|
||||||
Text("Guardian sign-in: Steve Jobs")
|
// Text("Guardian sign-in: Steve Jobs")
|
||||||
.font(.caption)
|
// .font(.caption)
|
||||||
.foregroundColor(.gray)
|
// .foregroundColor(.gray)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
if index == 0 {
|
// if index == 0 {
|
||||||
Image(systemName: "checkmark.seal.fill")
|
// Image(systemName: "checkmark.seal.fill")
|
||||||
.foregroundColor(.green)
|
// .foregroundColor(.green)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color(.systemGray6))
|
.background(Color(.systemGray6))
|
||||||
.cornerRadius(10)
|
.cornerRadius(10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.padding()
|
.padding()
|
||||||
|
.onAppear(){
|
||||||
|
if let ids = viewModel.selectedReservation?.booking?.player_ids?.toCommaSeparated {
|
||||||
|
|
||||||
|
viewModel.getPlayers(playerIds: ids)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ struct ScheduleView: View {
|
|||||||
let hours = Array(0...23)
|
let hours = Array(0...23)
|
||||||
let calendar = Calendar.current
|
let calendar = Calendar.current
|
||||||
|
|
||||||
|
@State private var selectedCourtName: String? = nil
|
||||||
|
@State private var selectedCourtId: Int? = nil
|
||||||
|
|
||||||
@EnvironmentObject var viewModel : DashViewModel
|
@EnvironmentObject var viewModel : DashViewModel
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -43,7 +46,28 @@ struct ScheduleView: View {
|
|||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(courtName)
|
if let clubs = self.viewModel.profile?.model?.courts {
|
||||||
|
ScrollView(.horizontal, showsIndicators: false) {
|
||||||
|
HStack(spacing: 16) {
|
||||||
|
ForEach(clubs, id: \.self) { court in
|
||||||
|
if let clubName = court.name {
|
||||||
|
Button(action: {
|
||||||
|
selectedCourtName = clubName
|
||||||
|
selectedCourtId = court.id
|
||||||
|
viewModel.getDailySched(clubId: court.id ?? 0)
|
||||||
|
}) {
|
||||||
|
Text(clubName)
|
||||||
|
.padding(5)
|
||||||
|
.background(selectedCourtName == clubName ? Colorr.themeBlueColor : Color.gray.opacity(0.2))
|
||||||
|
.foregroundColor(selectedCourtName == clubName ? .white : .primary)
|
||||||
|
.cornerRadius(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
}
|
||||||
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
// Time Slots with Events
|
// Time Slots with Events
|
||||||
@@ -221,6 +245,7 @@ struct ScheduleView: View {
|
|||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
selectedDate = date
|
selectedDate = date
|
||||||
|
viewModel.getDailySched(clubId: selectedCourtId ?? 0)
|
||||||
}
|
}
|
||||||
.id(calendar.startOfDay(for: date))
|
.id(calendar.startOfDay(for: date))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ struct AnalyticsView: View {
|
|||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(spacing: 15) {
|
VStack(spacing: 15) {
|
||||||
PieChartCard(data: self.viewModel.statResponse?.revenueByModule ?? [])
|
PieChartCard(data: self.viewModel.statResponse?.revenueByModule ?? [])
|
||||||
// BarChartCard(data: self.viewModel.statResponse?.revenueHeatMap ?? [])
|
BarChartCard(data: self.viewModel.statResponse?.revenueHeatMap ?? [])
|
||||||
// PieChartCard1()
|
// PieChartCard1()
|
||||||
BarChartCard1()
|
// BarChartCard1()
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
}
|
}
|
||||||
@@ -86,14 +86,14 @@ struct PieChartCard: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let chartData = data.map {
|
let chartData = data.map {
|
||||||
(name: $0.module, value: $0.revenue ?? 0, color: randomColor())
|
(name: $0.module, value: $0.revenue ?? 0, color: randomColor(module: $0.module))
|
||||||
}
|
}
|
||||||
|
|
||||||
CardView(title: "% made through each module") {
|
CardView(title: "% made through each module") {
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
ForEach(chartData, id: \.name) { item in
|
ForEach(chartData, id: \.name) { item in
|
||||||
LegendView(color: item.color, text: item.name)
|
LegendView(color: item.color, text: item.name ?? "")
|
||||||
}
|
}
|
||||||
.padding(.top, 5)
|
.padding(.top, 5)
|
||||||
}
|
}
|
||||||
@@ -111,9 +111,16 @@ struct PieChartCard: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func randomColor() -> Color {
|
func randomColor(module: String) -> Color {
|
||||||
let colors: [Color] = [Colorr.pieBlue, Colorr.pieGreen, .orange, .purple, .pink, .mint]
|
switch(module){
|
||||||
return colors.randomElement() ?? .blue
|
case "Clinics":
|
||||||
|
return Colorr.pieBlue
|
||||||
|
case "Coaching":
|
||||||
|
return Colorr.greenColor
|
||||||
|
default:
|
||||||
|
return .orange
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,10 +163,10 @@ struct BarChartCard: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let barData: [ModuleRevenue] = data.map {
|
let barData: [ModuleRevenue] = data.map {
|
||||||
ModuleRevenue(day: $0.date.toWeekday()!, module: $0.date.toWeekday()!, value: $0.total_revenue )
|
ModuleRevenue(day: $0.date?.toWeekday()! ?? "", module: $0.date?.toWeekday() ?? "", value: $0.total_revenue ?? 0.0 )
|
||||||
}
|
}
|
||||||
|
|
||||||
CardView(title: "Revenue from each module") {
|
CardView(title: "Revenue from each day") {
|
||||||
Chart(barData) { data in
|
Chart(barData) { data in
|
||||||
BarMark(
|
BarMark(
|
||||||
x: .value("Day", data.day),
|
x: .value("Day", data.day),
|
||||||
|
|||||||
@@ -27,20 +27,52 @@ struct SummaryView: View {
|
|||||||
|
|
||||||
if selectedTab == 0 {
|
if selectedTab == 0 {
|
||||||
FilterView(navigationPaths: $navigationPaths, filterCount: $filterCount)
|
FilterView(navigationPaths: $navigationPaths, filterCount: $filterCount)
|
||||||
CourtUtilizationView(utilization: "\(self.viewModel.statResponse?.courtUtilization.first?.utilization_percentage ?? 10.0)%" )
|
CourtUtilizationView(utilization: "\(self.viewModel.statResponse?.courtUtilization?.first?.utilization_percentage ?? "10.0")%" )
|
||||||
|
|
||||||
ScrollView {
|
ScrollView {
|
||||||
LazyVStack(spacing: 10) {
|
LazyVStack(spacing: 10) {
|
||||||
|
|
||||||
ReservationCard(title: "Court reservations", hours: "\(self.viewModel.statResponse?.coachReservations.first?.total_hours ?? 0 )", revenue: "$\(self.viewModel.statResponse?.coachReservations.first?.total_revenue ?? 0 )")
|
ReservationCard(
|
||||||
ReservationCard(title: "Clinic reservations", hours: "\(self.viewModel.statResponse?.clinicReservations.first?.total_hours ?? 0 )", revenue: "$\(self.viewModel.statResponse?.clinicReservations.first?.total_revenue ?? 0 )")
|
title: "Court reservations",
|
||||||
ReservationCard(title: "Find a Buddy", hours: "\(self.viewModel.statResponse?.buddyStatistics.first?.total_hours ?? 0 )", revenue: "$\(self.viewModel.statResponse?.buddyStatistics.first?.total_revenue ?? 0 )")
|
hours: String(format: "%.2f", self.viewModel.statResponse?.coachReservations?.first?.total_hours ?? 0),
|
||||||
ReservationCard(title: "Lesson reservation", hours: "\(self.viewModel.statResponse?.lessonReservations.first?.total_hours ?? 0 )", revenue: "$\(self.viewModel.statResponse?.lessonReservations.first?.total_revenue ?? 0 )")
|
revenue: "$" + String(format: "%.2f", self.viewModel.statResponse?.coachReservations?.first?.total_revenue ?? 0)
|
||||||
|
)
|
||||||
|
|
||||||
ReservationCard(title: "Total expenses", hours: "\(self.viewModel.statResponse?.totalExpenses.first?.total_hours ?? 0 )", revenue:"$\(self.viewModel.statResponse?.totalExpenses.first?.total_expense ?? 0 )")
|
ReservationCard(
|
||||||
ReservationCard(title: "Total profit", hours: "\(self.viewModel.statResponse?.totalProfit.first?.total_profit ?? 0 )", revenue: "$\(self.viewModel.statResponse?.totalProfit.first?.total_revenue ?? 0 )")
|
title: "Clinic reservations",
|
||||||
ReservationCard(title: "Total revenue", hours: "\(self.viewModel.statResponse?.totalRevenue.first?.total_hours ?? 0 )", revenue: "$\(self.viewModel.statResponse?.totalRevenue.first?.total_revenue ?? 0 )")
|
hours: String(format: "%.2f", self.viewModel.statResponse?.clinicReservations?.first?.total_hours ?? 0),
|
||||||
|
revenue: "$" + String(format: "%.2f", self.viewModel.statResponse?.clinicReservations?.first?.total_revenue ?? 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
ReservationCard(
|
||||||
|
title: "Find a Buddy",
|
||||||
|
hours: String(format: "%.2f", self.viewModel.statResponse?.buddyStatistics?.first?.total_hours ?? 0),
|
||||||
|
revenue: "$" + String(format: "%.2f", self.viewModel.statResponse?.buddyStatistics?.first?.total_revenue ?? 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
ReservationCard(
|
||||||
|
title: "Lesson reservation",
|
||||||
|
hours: String(format: "%.2f", self.viewModel.statResponse?.lessonReservations?.first?.total_hours ?? 0),
|
||||||
|
revenue: "$" + String(format: "%.2f", self.viewModel.statResponse?.lessonReservations?.first?.total_revenue ?? 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
ReservationCard(
|
||||||
|
title: "Total expenses",
|
||||||
|
hours: String(format: "%.2f", self.viewModel.statResponse?.totalExpenses?.first?.total_hours ?? 0),
|
||||||
|
revenue: "$" + String(format: "%.2f", self.viewModel.statResponse?.totalExpenses?.first?.total_expense ?? 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
ReservationCard(
|
||||||
|
title: "Total profit",
|
||||||
|
hours: String(format: "%.2f", self.viewModel.statResponse?.totalProfit?.first?.total_profit ?? 0),
|
||||||
|
revenue: "$" + String(format: "%.2f", self.viewModel.statResponse?.totalProfit?.first?.total_revenue ?? 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
ReservationCard(
|
||||||
|
title: "Total revenue",
|
||||||
|
hours: String(format: "%.2f", self.viewModel.statResponse?.totalRevenue?.first?.total_hours ?? 0),
|
||||||
|
revenue: "$" + String(format: "%.2f", self.viewModel.statResponse?.totalRevenue?.first?.total_revenue ?? 0)
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
@@ -57,7 +89,7 @@ struct SummaryView: View {
|
|||||||
if value == "FilterScreen" {
|
if value == "FilterScreen" {
|
||||||
FilterScreen(navigationPaths: $navigationPaths) { startDate, endDate, startTime, endTime, filterCount in
|
FilterScreen(navigationPaths: $navigationPaths) { startDate, endDate, startTime, endTime, filterCount in
|
||||||
self.filterCount = filterCount
|
self.filterCount = filterCount
|
||||||
viewModel.getStats ( startDate: startDate, endDate: endDate, startTime: startTime, endTime: endTime, completion: {})
|
// viewModel.getStats ( startDate: startDate, endDate: endDate, startTime: startTime, endTime: endTime, completion: {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +141,9 @@ struct HeaderView: View {
|
|||||||
AppSettings.token = ""
|
AppSettings.token = ""
|
||||||
|
|
||||||
}
|
}
|
||||||
Button("Cancel", role: .cancel) { }
|
Button("Cancel", role: .cancel) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ struct FilterScreen: View {
|
|||||||
@State private var endTime: Date = Date()
|
@State private var endTime: Date = Date()
|
||||||
@State private var startDate: Date = Date()
|
@State private var startDate: Date = Date()
|
||||||
@State private var endDate: Date = Date()
|
@State private var endDate: Date = Date()
|
||||||
|
@EnvironmentObject var viewModel : DashViewModel
|
||||||
|
|
||||||
@State private var selectedDuration: String = "This Day"
|
@State private var selectedDuration: String = "This Day"
|
||||||
let durationOptions = ["This Day", "This Week", "This Month", "This Year"]
|
let durationOptions = ["This Day", "This Week", "This Month", "This Year"]
|
||||||
@@ -33,14 +34,14 @@ struct FilterScreen: View {
|
|||||||
DatePicker("End Date", selection: $endDate, displayedComponents: .date)
|
DatePicker("End Date", selection: $endDate, displayedComponents: .date)
|
||||||
}
|
}
|
||||||
|
|
||||||
Section(header: Text("Duration")) {
|
// Section(header: Text("Duration")) {
|
||||||
Picker("Duration", selection: $selectedDuration) {
|
// Picker("Duration", selection: $selectedDuration) {
|
||||||
ForEach(durationOptions, id: \.self) { duration in
|
// ForEach(durationOptions, id: \.self) { duration in
|
||||||
Text(duration)
|
// Text(duration)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
.pickerStyle(MenuPickerStyle())
|
// .pickerStyle(MenuPickerStyle())
|
||||||
}
|
// }
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
@@ -66,17 +67,17 @@ struct FilterScreen: View {
|
|||||||
let timeFormatter = DateFormatter()
|
let timeFormatter = DateFormatter()
|
||||||
timeFormatter.dateFormat = "HH:mm:ss"
|
timeFormatter.dateFormat = "HH:mm:ss"
|
||||||
|
|
||||||
let startDateStr = dateFormatter.string(from: startDate)
|
viewModel.dashStartDate = dateFormatter.string(from: startDate)
|
||||||
let endDateStr = dateFormatter.string(from: endDate)
|
viewModel.dashEndDate = dateFormatter.string(from: endDate)
|
||||||
let startTimeStr = timeFormatter.string(from: startTime)
|
viewModel.dashStartTime = timeFormatter.string(from: startTime)
|
||||||
let endTimeStr = timeFormatter.string(from: endTime)
|
viewModel.dashEndTime = timeFormatter.string(from: endTime)
|
||||||
|
|
||||||
let query = """
|
// let query = """
|
||||||
start_date=\(startDateStr)&\
|
// start_date=\(startDateStr)&\
|
||||||
end_date=\(endDateStr)&\
|
// end_date=\(endDateStr)&\
|
||||||
start_time=\(startTimeStr)&\
|
// start_time=\(startTimeStr)&\
|
||||||
end_time=\(endTimeStr)
|
// end_time=\(endTimeStr)
|
||||||
"""
|
// """
|
||||||
|
|
||||||
// 🔢 Count how many filters are applied
|
// 🔢 Count how many filters are applied
|
||||||
var filterCount = 0
|
var filterCount = 0
|
||||||
@@ -86,10 +87,10 @@ struct FilterScreen: View {
|
|||||||
if !Calendar.current.isDate(endTime, equalTo: Date(), toGranularity: .minute) { filterCount += 1 }
|
if !Calendar.current.isDate(endTime, equalTo: Date(), toGranularity: .minute) { filterCount += 1 }
|
||||||
if selectedDuration != "This Day" { filterCount += 1 }
|
if selectedDuration != "This Day" { filterCount += 1 }
|
||||||
|
|
||||||
print("Generated Filter Query: \(query)")
|
// print("Generated Filter Query: \(query)")
|
||||||
print("Filter count: \(filterCount)")
|
print("Filter count: \(filterCount)")
|
||||||
|
|
||||||
self.filterBlock?(startDateStr, endDateStr, startTimeStr, endTimeStr, filterCount)
|
// self.filterBlock?(startDateStr, endDateStr, startTimeStr, endTimeStr, filterCount)
|
||||||
self.navigationPaths.removeLast()
|
self.navigationPaths.removeLast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ struct SideMenuView: View {
|
|||||||
AppSettings.token = ""
|
AppSettings.token = ""
|
||||||
presentSideMenu = false
|
presentSideMenu = false
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -368,3 +368,13 @@ extension Date {
|
|||||||
return formatter.string(from: self)
|
return formatter.string(from: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
extension String {
|
||||||
|
var toCommaSeparated: String {
|
||||||
|
self.trimmingCharacters(in: CharacterSet(charactersIn: "[]"))
|
||||||
|
.split(separator: ",")
|
||||||
|
.map { $0.trimmingCharacters(in: .whitespaces) }
|
||||||
|
.joined(separator: ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,25 +22,28 @@ class DashViewModel: ObservableObject {
|
|||||||
@Published var players : [UserMap]?
|
@Published var players : [UserMap]?
|
||||||
@Published var coaches : [PlayerList]?
|
@Published var coaches : [PlayerList]?
|
||||||
|
|
||||||
|
@Published var dashStartDate : String = "2025-04-01"
|
||||||
|
@Published var dashEndDate : String = "2025-04-30"
|
||||||
|
@Published var dashStartTime : String = "08:30"
|
||||||
|
@Published var dashEndTime : String = "17:00"
|
||||||
|
|
||||||
func getStats(
|
func getStats(
|
||||||
startDate: String? = "2024-10-25",
|
|
||||||
endDate: String? = "2024-11-25",
|
|
||||||
startTime: String? = "17:30:20",
|
|
||||||
endTime: String? = "19:20:30",
|
|
||||||
completion: @escaping () -> ()) {
|
completion: @escaping () -> ()) {
|
||||||
let endpoint = ClubStatisticsEndpoint(
|
let endpoint = ClubStatisticsEndpoint(
|
||||||
startDate: startDate!,
|
startDate: dashStartDate,
|
||||||
endDate: endDate!,
|
endDate: dashEndDate,
|
||||||
startTime: startTime!,
|
startTime: dashStartTime,
|
||||||
endTime: endTime!
|
endTime: dashEndTime
|
||||||
)
|
)
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
let response: ClubStatisticsResponse = try await APIService.shared.request(endpoint, responseType: ClubStatisticsResponse.self)
|
let result = try await APIService.shared.requestStatics(endpoint)
|
||||||
print("Statistics fetched: \(response.model)")
|
print("Statistics fetched: \(result?.model)")
|
||||||
if !response.error {
|
|
||||||
self.statResponse = response.model
|
if !result!.error! {
|
||||||
|
self.statResponse = result?.model
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user