updated code
This commit is contained in:
@@ -9,6 +9,8 @@
|
|||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
AC136A092DB96847009D478F /* ObjectMapper in Frameworks */ = {isa = PBXBuildFile; productRef = AC136A082DB96847009D478F /* ObjectMapper */; };
|
AC136A092DB96847009D478F /* ObjectMapper in Frameworks */ = {isa = PBXBuildFile; productRef = AC136A082DB96847009D478F /* ObjectMapper */; };
|
||||||
AC53DEAA2DB9476D003445AD /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = AC53DEA92DB9476D003445AD /* Alamofire */; };
|
AC53DEAA2DB9476D003445AD /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = AC53DEA92DB9476D003445AD /* Alamofire */; };
|
||||||
|
AC8826F32E6F5A6700ECEF0D /* CropViewController in Frameworks */ = {isa = PBXBuildFile; productRef = AC8826F22E6F5A6700ECEF0D /* CropViewController */; };
|
||||||
|
AC8826F52E6F5A6700ECEF0D /* TOCropViewController in Frameworks */ = {isa = PBXBuildFile; productRef = AC8826F42E6F5A6700ECEF0D /* TOCropViewController */; };
|
||||||
ACAC2DEB2D9F2C1900869E5C /* CalendarKit in Frameworks */ = {isa = PBXBuildFile; productRef = ACAC2DEA2D9F2C1900869E5C /* CalendarKit */; };
|
ACAC2DEB2D9F2C1900869E5C /* CalendarKit in Frameworks */ = {isa = PBXBuildFile; productRef = ACAC2DEA2D9F2C1900869E5C /* CalendarKit */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
@@ -30,6 +32,8 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
AC136A092DB96847009D478F /* ObjectMapper in Frameworks */,
|
AC136A092DB96847009D478F /* ObjectMapper in Frameworks */,
|
||||||
|
AC8826F52E6F5A6700ECEF0D /* TOCropViewController in Frameworks */,
|
||||||
|
AC8826F32E6F5A6700ECEF0D /* CropViewController in Frameworks */,
|
||||||
ACAC2DEB2D9F2C1900869E5C /* CalendarKit in Frameworks */,
|
ACAC2DEB2D9F2C1900869E5C /* CalendarKit in Frameworks */,
|
||||||
AC53DEAA2DB9476D003445AD /* Alamofire in Frameworks */,
|
AC53DEAA2DB9476D003445AD /* Alamofire in Frameworks */,
|
||||||
);
|
);
|
||||||
@@ -77,6 +81,8 @@
|
|||||||
ACAC2DEA2D9F2C1900869E5C /* CalendarKit */,
|
ACAC2DEA2D9F2C1900869E5C /* CalendarKit */,
|
||||||
AC53DEA92DB9476D003445AD /* Alamofire */,
|
AC53DEA92DB9476D003445AD /* Alamofire */,
|
||||||
AC136A082DB96847009D478F /* ObjectMapper */,
|
AC136A082DB96847009D478F /* ObjectMapper */,
|
||||||
|
AC8826F22E6F5A6700ECEF0D /* CropViewController */,
|
||||||
|
AC8826F42E6F5A6700ECEF0D /* TOCropViewController */,
|
||||||
);
|
);
|
||||||
productName = "Club Portal";
|
productName = "Club Portal";
|
||||||
productReference = ACAC2DCF2D9F271300869E5C /* Club Portal.app */;
|
productReference = ACAC2DCF2D9F271300869E5C /* Club Portal.app */;
|
||||||
@@ -110,6 +116,7 @@
|
|||||||
ACAC2DE92D9F2C1900869E5C /* XCRemoteSwiftPackageReference "CalendarKit" */,
|
ACAC2DE92D9F2C1900869E5C /* XCRemoteSwiftPackageReference "CalendarKit" */,
|
||||||
AC53DEA82DB9476D003445AD /* XCRemoteSwiftPackageReference "Alamofire" */,
|
AC53DEA82DB9476D003445AD /* XCRemoteSwiftPackageReference "Alamofire" */,
|
||||||
AC136A072DB96847009D478F /* XCRemoteSwiftPackageReference "ObjectMapper" */,
|
AC136A072DB96847009D478F /* XCRemoteSwiftPackageReference "ObjectMapper" */,
|
||||||
|
AC8826F12E6F5A6700ECEF0D /* XCRemoteSwiftPackageReference "TOCropViewController" */,
|
||||||
);
|
);
|
||||||
preferredProjectObjectVersion = 77;
|
preferredProjectObjectVersion = 77;
|
||||||
productRefGroup = ACAC2DD02D9F271300869E5C /* Products */;
|
productRefGroup = ACAC2DD02D9F271300869E5C /* Products */;
|
||||||
@@ -267,16 +274,18 @@
|
|||||||
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 = 3;
|
CURRENT_PROJECT_VERSION = 4;
|
||||||
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;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "Club-Portal-Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Club Portal";
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -300,16 +309,18 @@
|
|||||||
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 = 3;
|
CURRENT_PROJECT_VERSION = 4;
|
||||||
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;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "Club-Portal-Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Club Portal";
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -367,6 +378,14 @@
|
|||||||
minimumVersion = 5.10.2;
|
minimumVersion = 5.10.2;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
AC8826F12E6F5A6700ECEF0D /* XCRemoteSwiftPackageReference "TOCropViewController" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/TimOliver/TOCropViewController";
|
||||||
|
requirement = {
|
||||||
|
kind = upToNextMajorVersion;
|
||||||
|
minimumVersion = 2.7.4;
|
||||||
|
};
|
||||||
|
};
|
||||||
ACAC2DE92D9F2C1900869E5C /* XCRemoteSwiftPackageReference "CalendarKit" */ = {
|
ACAC2DE92D9F2C1900869E5C /* XCRemoteSwiftPackageReference "CalendarKit" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/richardtop/CalendarKit";
|
repositoryURL = "https://github.com/richardtop/CalendarKit";
|
||||||
@@ -388,6 +407,16 @@
|
|||||||
package = AC53DEA82DB9476D003445AD /* XCRemoteSwiftPackageReference "Alamofire" */;
|
package = AC53DEA82DB9476D003445AD /* XCRemoteSwiftPackageReference "Alamofire" */;
|
||||||
productName = Alamofire;
|
productName = Alamofire;
|
||||||
};
|
};
|
||||||
|
AC8826F22E6F5A6700ECEF0D /* CropViewController */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = AC8826F12E6F5A6700ECEF0D /* XCRemoteSwiftPackageReference "TOCropViewController" */;
|
||||||
|
productName = CropViewController;
|
||||||
|
};
|
||||||
|
AC8826F42E6F5A6700ECEF0D /* TOCropViewController */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = AC8826F12E6F5A6700ECEF0D /* XCRemoteSwiftPackageReference "TOCropViewController" */;
|
||||||
|
productName = TOCropViewController;
|
||||||
|
};
|
||||||
ACAC2DEA2D9F2C1900869E5C /* CalendarKit */ = {
|
ACAC2DEA2D9F2C1900869E5C /* CalendarKit */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = ACAC2DE92D9F2C1900869E5C /* XCRemoteSwiftPackageReference "CalendarKit" */;
|
package = ACAC2DE92D9F2C1900869E5C /* XCRemoteSwiftPackageReference "CalendarKit" */;
|
||||||
|
|||||||
+10
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"originHash" : "60390f3252b346980a2b0f96582e92fec2c37e9487d7b684f3d58a001c214046",
|
"originHash" : "b1b0353358422b4fa2ea090c1b3ed8788cceebbcf36fc271f832e564b41e6da4",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "alamofire",
|
"identity" : "alamofire",
|
||||||
@@ -27,6 +27,15 @@
|
|||||||
"revision" : "6021c6035e83a306047348666f6400dc61445d3b",
|
"revision" : "6021c6035e83a306047348666f6400dc61445d3b",
|
||||||
"version" : "4.4.3"
|
"version" : "4.4.3"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "tocropviewcontroller",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/TimOliver/TOCropViewController",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "a634cb7cdfd580006e79a6e74e64417fe9e9783b",
|
||||||
|
"version" : "2.7.4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version" : 3
|
"version" : 3
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
enum APIConstants {
|
enum APIConstants {
|
||||||
static let baseURL = "https://courtmatchup.mkdlabs.com"
|
static let baseURL = "http://199.241.139.243:3048" //"https://courtmatchup.mkdlabs.com"
|
||||||
static let xProject = "Y291cnRtYXRjaHVwOmczbmp1OTlpZjR3enk4Z3V0bHEwYmUwZDI1Nzk1MTNsbTg="
|
static let xProject = "Y291cnRtYXRjaHVwOmczbmp1OTlpZjR3enk4Z3V0bHEwYmUwZDI1Nzk1MTNsbTg="
|
||||||
static var commonHeaders: [String: String] {
|
static var commonHeaders: [String: String] {
|
||||||
var headers = ["Content-Type": "application/json",
|
var headers = ["Content-Type": "application/json",
|
||||||
|
|||||||
+18
@@ -35,3 +35,21 @@ struct ReservationListEndpoint: Endpoint {
|
|||||||
var isMultipart: Bool { false }
|
var isMultipart: Bool { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Search reservations by user first name (contains)
|
||||||
|
struct ReservationSearchEndpoint: Endpoint {
|
||||||
|
var urlQueryItems: [URLQueryItem] = []
|
||||||
|
var path: String {
|
||||||
|
"/v4/api/records/reservation?join=booking|booking_id&join=user|user_id&join=buddy|buddy_id&join=clubs|club_id&join=clinics|clinic_id&order=id,desc&filter=courtmatchup_user.first_name,cs,\(query)"
|
||||||
|
}
|
||||||
|
|
||||||
|
var method: HTTPMethod { .get }
|
||||||
|
|
||||||
|
let query: String
|
||||||
|
|
||||||
|
var customHeaders: [String: String]? { nil }
|
||||||
|
|
||||||
|
var body: Data? { nil }
|
||||||
|
|
||||||
|
var isMultipart: Bool { false }
|
||||||
|
}
|
||||||
|
|||||||
+61
-3
@@ -24,14 +24,19 @@ struct AvailabliltyRsp: Codable {
|
|||||||
|
|
||||||
// MARK: - Coaches
|
// MARK: - Coaches
|
||||||
struct Coaches: Codable {
|
struct Coaches: Codable {
|
||||||
|
// legacy shape
|
||||||
let available: [CoachesAvailable]?
|
let available: [CoachesAvailable]?
|
||||||
let unavailable: [CoachesAvailable]?
|
let unavailable: [CoachesAvailable]?
|
||||||
let total: Int?
|
let total: Int?
|
||||||
|
// new shape
|
||||||
|
let items: [CoachesAvailable]?
|
||||||
|
let counts: JSONAny?
|
||||||
|
let pagination: JSONAny?
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - CoachesAvailable
|
// MARK: - CoachesAvailable
|
||||||
struct CoachesAvailable: Codable , Identifiable, Hashable {
|
struct CoachesAvailable: Codable , Identifiable, Hashable {
|
||||||
let id = UUID().uuidString
|
let id: Int?
|
||||||
let coachID, userID: Int?
|
let coachID, userID: Int?
|
||||||
let bio, hourlyRate, availability, firstName: String?
|
let bio, hourlyRate, availability, firstName: String?
|
||||||
let lastName, phone, email: String?
|
let lastName, phone, email: String?
|
||||||
@@ -114,9 +119,14 @@ struct Sport: Codable, Identifiable, Hashable{
|
|||||||
|
|
||||||
// MARK: - Courts
|
// MARK: - Courts
|
||||||
struct Courts: Codable {
|
struct Courts: Codable {
|
||||||
|
// Old payload support
|
||||||
let available: [CourtsAvailable]?
|
let available: [CourtsAvailable]?
|
||||||
let unavailable: [JSONAny]?
|
let unavailable: [JSONAny]?
|
||||||
let total: Int?
|
let total: Int?
|
||||||
|
// New payload support
|
||||||
|
let items: [CourtsAvailable]?
|
||||||
|
let counts: JSONAny?
|
||||||
|
let pagination: JSONAny?
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - CourtsAvailable
|
// MARK: - CourtsAvailable
|
||||||
@@ -127,6 +137,9 @@ struct CourtsAvailable: Codable, Identifiable , Hashable{
|
|||||||
let availability, sportName: String?
|
let availability, sportName: String?
|
||||||
let surfaceName: String?
|
let surfaceName: String?
|
||||||
let availabilityData: AvailabilityData?
|
let availabilityData: AvailabilityData?
|
||||||
|
// New payload fields
|
||||||
|
let availabilitySlots: [Availability]?
|
||||||
|
let unavailabilitySlots: [JSONAny]?
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case id, name, type, subtype
|
case id, name, type, subtype
|
||||||
@@ -136,6 +149,8 @@ struct CourtsAvailable: Codable, Identifiable , Hashable{
|
|||||||
case sportName = "sport_name"
|
case sportName = "sport_name"
|
||||||
case surfaceName = "surface_name"
|
case surfaceName = "surface_name"
|
||||||
case availabilityData
|
case availabilityData
|
||||||
|
case availabilitySlots = "availability_slots"
|
||||||
|
case unavailabilitySlots = "unavailability_slots"
|
||||||
}
|
}
|
||||||
func hash(into hasher: inout Hasher) {
|
func hash(into hasher: inout Hasher) {
|
||||||
hasher.combine(id)
|
hasher.combine(id)
|
||||||
@@ -153,15 +168,53 @@ struct Range: Codable {
|
|||||||
|
|
||||||
// MARK: - Hours
|
// MARK: - Hours
|
||||||
struct Hours: Codable {
|
struct Hours: Codable {
|
||||||
let available: [String]?
|
// New payload fields
|
||||||
let total: Int?
|
let available: [HourSlot]? // e.g., [{start:"11:00:00", end:"11:30:00"}]
|
||||||
|
let unavailable: [UnavailableHour]?
|
||||||
let range: Range?
|
let range: Range?
|
||||||
|
let unavailableRange: Range?
|
||||||
let byDate: [ByDate]?
|
let byDate: [ByDate]?
|
||||||
|
let unavailableByDate: [ByDateUnavailable]?
|
||||||
|
// Legacy support
|
||||||
|
let total: Int?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case available, unavailable, range, byDate
|
||||||
|
case unavailableRange = "unavailable_range"
|
||||||
|
case unavailableByDate = "unavailable_byDate"
|
||||||
|
case total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - HourSlot
|
||||||
|
struct HourSlot: Codable, Hashable {
|
||||||
|
let start: String?
|
||||||
|
let end: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UnavailableHour
|
||||||
|
struct UnavailableHour: Codable, Hashable {
|
||||||
|
let start: String?
|
||||||
|
let end: String?
|
||||||
|
let reason: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - ByDate
|
// MARK: - ByDate
|
||||||
struct ByDate: Codable {
|
struct ByDate: Codable {
|
||||||
let date: String?
|
let date: String?
|
||||||
|
let ranges: [HourSlot]?
|
||||||
|
let slots: [String]?
|
||||||
|
let from, until: String?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case date, ranges, slots, from, until
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - ByDateUnavailable
|
||||||
|
struct ByDateUnavailable: Codable {
|
||||||
|
let date: String?
|
||||||
|
let ranges: [UnavailableHour]?
|
||||||
let slots: [String]?
|
let slots: [String]?
|
||||||
let from, until: String?
|
let from, until: String?
|
||||||
}
|
}
|
||||||
@@ -169,9 +222,14 @@ struct ByDate: Codable {
|
|||||||
// MARK: - Staff
|
// MARK: - Staff
|
||||||
struct Staff: Codable, Identifiable, Hashable {
|
struct Staff: Codable, Identifiable, Hashable {
|
||||||
var id: Int?
|
var id: Int?
|
||||||
|
// legacy
|
||||||
let available: [StaffAvailable]?
|
let available: [StaffAvailable]?
|
||||||
let unavailable: [JSONAny]?
|
let unavailable: [JSONAny]?
|
||||||
let total: Int?
|
let total: Int?
|
||||||
|
// new
|
||||||
|
let items: [StaffAvailable]?
|
||||||
|
let counts: JSONAny?
|
||||||
|
let pagination: JSONAny?
|
||||||
|
|
||||||
static func == (lhs: Staff, rhs: Staff) -> Bool {
|
static func == (lhs: Staff, rhs: Staff) -> Bool {
|
||||||
lhs.id == rhs.id
|
lhs.id == rhs.id
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import SwiftUI
|
|||||||
struct AvailabilityCardView: View {
|
struct AvailabilityCardView: View {
|
||||||
var tab: AvailabilityTab
|
var tab: AvailabilityTab
|
||||||
var courts: [CourtsAvailable] = []
|
var courts: [CourtsAvailable] = []
|
||||||
var hours: [String]?
|
var hours: [HourSlot]?
|
||||||
var coaches: [CoachesAvailable]?
|
var coaches: [CoachesAvailable]?
|
||||||
var stsff: [StaffAvailable]?
|
var stsff: [StaffAvailable]?
|
||||||
@State var name : String = ""
|
@State var name : String = ""
|
||||||
@@ -44,7 +44,7 @@ struct AvailabilityCardView: View {
|
|||||||
}
|
}
|
||||||
case .hours:
|
case .hours:
|
||||||
ForEach(hours ?? [] , id: \.self) { hour in
|
ForEach(hours ?? [] , id: \.self) { hour in
|
||||||
Text("\(hour)")
|
Text("\(hour.start ?? "") - \(hour.end ?? "")")
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
showSheet.toggle()
|
showSheet.toggle()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ struct AvailabilityScreen: View {
|
|||||||
ScrollView {
|
ScrollView {
|
||||||
AvailabilityCardView(
|
AvailabilityCardView(
|
||||||
tab: selectedTab,
|
tab: selectedTab,
|
||||||
courts: viewModel.availRsp?.courts?.available ?? [] ,
|
courts: viewModel.availRsp?.courts?.items ?? viewModel.availRsp?.courts?.available ?? [] ,
|
||||||
hours: viewModel.availRsp?.hours?.available ?? [] ,
|
hours: viewModel.availRsp?.hours?.available ?? [] ,
|
||||||
coaches: viewModel.availRsp?.coaches?.available ?? [],
|
coaches: viewModel.availRsp?.coaches?.items ?? viewModel.availRsp?.coaches?.available ?? [],
|
||||||
stsff: viewModel.availRsp?.staff?.available ?? []
|
stsff: viewModel.availRsp?.staff?.items ?? viewModel.availRsp?.staff?.available ?? []
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ struct ScheduleView: View {
|
|||||||
|
|
||||||
@State private var selectedCourtName: String? = nil
|
@State private var selectedCourtName: String? = nil
|
||||||
@State private var selectedCourtId: Int? = nil
|
@State private var selectedCourtId: Int? = nil
|
||||||
|
@State private var searchQuery: String = ""
|
||||||
|
|
||||||
@EnvironmentObject var viewModel : DashViewModel
|
@EnvironmentObject var viewModel : DashViewModel
|
||||||
|
|
||||||
@@ -173,8 +174,12 @@ struct ScheduleView: View {
|
|||||||
Image(systemName: "magnifyingglass")
|
Image(systemName: "magnifyingglass")
|
||||||
.foregroundColor(.gray)
|
.foregroundColor(.gray)
|
||||||
|
|
||||||
TextField("search player", text: .constant(""))
|
TextField("Search player", text: $searchQuery)
|
||||||
.foregroundColor(.primary)
|
.foregroundColor(.primary)
|
||||||
|
.submitLabel(.search)
|
||||||
|
.onSubmit {
|
||||||
|
viewModel.searchDailySched(query: searchQuery)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.padding(5)
|
.padding(5)
|
||||||
.background(Color(.white))
|
.background(Color(.white))
|
||||||
@@ -184,6 +189,13 @@ struct ScheduleView: View {
|
|||||||
.stroke(Color(.systemGray4), lineWidth: 1)
|
.stroke(Color(.systemGray4), lineWidth: 1)
|
||||||
)
|
)
|
||||||
//.padding(.horizontal)
|
//.padding(.horizontal)
|
||||||
|
.onChange(of: searchQuery) { newVal in
|
||||||
|
let q = newVal.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
if q.isEmpty {
|
||||||
|
// restore list for selected court when clearing search
|
||||||
|
if let cid = selectedCourtId { viewModel.getDailySched(clubId: cid) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ struct SummaryView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// viewModel.getClubProfile()
|
// viewModel.getClubProfile()
|
||||||
// viewModel.getProfile()
|
viewModel.getProfile()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ struct SideMenuView: View {
|
|||||||
func ProfileHead() -> some View {
|
func ProfileHead() -> some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
HStack {
|
HStack {
|
||||||
ProfileImageView(imageUrl: AppSettings.photo, size: 50)
|
ProfileImageView(imageUrl: AppSettings.photo.isEmpty ? AppSettings.clubLogo : AppSettings.photo, size: 50)
|
||||||
.padding(.leading)
|
.padding(.leading)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
//
|
||||||
|
// PhotoPickerWithCrop.swift
|
||||||
|
// Club Portal
|
||||||
|
//
|
||||||
|
// Created by Umer Tahir on 23/05/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PhotoPickerWithCrop.swift
|
||||||
|
// Club Portal
|
||||||
|
//
|
||||||
|
// Created by Umer Tahir on 23/05/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import PhotosUI
|
||||||
|
import TOCropViewController
|
||||||
|
|
||||||
|
struct PhotoPickerWithCrop: UIViewControllerRepresentable {
|
||||||
|
@Binding var selectedImage: UIImage?
|
||||||
|
|
||||||
|
func makeCoordinator() -> Coordinator {
|
||||||
|
Coordinator(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeUIViewController(context: Context) -> PHPickerViewController {
|
||||||
|
var config = PHPickerConfiguration()
|
||||||
|
config.filter = .images
|
||||||
|
config.selectionLimit = 1
|
||||||
|
|
||||||
|
let picker = PHPickerViewController(configuration: config)
|
||||||
|
picker.delegate = context.coordinator
|
||||||
|
return picker
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {}
|
||||||
|
|
||||||
|
class Coordinator: NSObject, PHPickerViewControllerDelegate, TOCropViewControllerDelegate {
|
||||||
|
var parent: PhotoPickerWithCrop
|
||||||
|
var imageToCrop: UIImage?
|
||||||
|
|
||||||
|
init(_ parent: PhotoPickerWithCrop) {
|
||||||
|
self.parent = parent
|
||||||
|
}
|
||||||
|
|
||||||
|
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
|
||||||
|
picker.dismiss(animated: true)
|
||||||
|
|
||||||
|
guard let provider = results.first?.itemProvider,
|
||||||
|
provider.canLoadObject(ofClass: UIImage.self) else { return }
|
||||||
|
|
||||||
|
provider.loadObject(ofClass: UIImage.self) { [weak self] object, _ in
|
||||||
|
guard let self = self, let image = object as? UIImage else { return }
|
||||||
|
self.imageToCrop = image
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
guard let root = UIApplication.shared.windows.first?.rootViewController else { return }
|
||||||
|
let cropVC = TOCropViewController(image: image)
|
||||||
|
cropVC.delegate = self
|
||||||
|
root.present(cropVC, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cropViewController(_ cropViewController: TOCropViewController, didCropTo image: UIImage, with cropRect: CGRect, angle: Int) {
|
||||||
|
cropViewController.dismiss(animated: true)
|
||||||
|
parent.selectedImage = image
|
||||||
|
}
|
||||||
|
|
||||||
|
func cropViewControllerDidCancel(_ cropViewController: TOCropViewController) {
|
||||||
|
cropViewController.dismiss(animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -71,6 +71,20 @@ class DashViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func searchDailySched(query: String){
|
||||||
|
guard !query.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return }
|
||||||
|
let endpoint = ReservationSearchEndpoint(query: query)
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
let result = try await APIService.shared.requestReservation(endpoint, responseType: ProfileRsp.self)
|
||||||
|
dailyReservations = result?.list ?? []
|
||||||
|
print("Search Reservations:", result?.list)
|
||||||
|
} catch {
|
||||||
|
print("Error searching reservations:", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getAvailability(
|
func getAvailability(
|
||||||
startDate: String? = "2024-10-25",
|
startDate: String? = "2024-10-25",
|
||||||
endDate: String? = "2024-11-25",
|
endDate: String? = "2024-11-25",
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSAppTransportSecurity</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
Reference in New Issue
Block a user