updated code

This commit is contained in:
umer
2025-11-18 02:33:31 +05:00
parent 3ff65fe17b
commit e9e2bc5d3a
9 changed files with 657 additions and 3 deletions
@@ -12,6 +12,18 @@
AC8826F32E6F5A6700ECEF0D /* CropViewController in Frameworks */ = {isa = PBXBuildFile; productRef = AC8826F22E6F5A6700ECEF0D /* CropViewController */; }; AC8826F32E6F5A6700ECEF0D /* CropViewController in Frameworks */ = {isa = PBXBuildFile; productRef = AC8826F22E6F5A6700ECEF0D /* CropViewController */; };
AC8826F52E6F5A6700ECEF0D /* TOCropViewController in Frameworks */ = {isa = PBXBuildFile; productRef = AC8826F42E6F5A6700ECEF0D /* TOCropViewController */; }; 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 */; };
ACF3DEC52EC490D000E72587 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DEC42EC490D000E72587 /* FirebaseAuth */; };
ACF3DEC72EC490D000E72587 /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DEC62EC490D000E72587 /* FirebaseCore */; };
ACF3DEC92EC490D000E72587 /* FirebaseInAppMessaging-Beta in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DEC82EC490D000E72587 /* FirebaseInAppMessaging-Beta */; };
ACF3DECB2EC490D000E72587 /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DECA2EC490D000E72587 /* FirebaseMessaging */; };
ACF3DECD2EC4917600E72587 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DECC2EC4917600E72587 /* FirebaseAnalytics */; };
ACF3DECF2EC4917600E72587 /* FirebaseAnalyticsCore in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DECE2EC4917600E72587 /* FirebaseAnalyticsCore */; };
ACF3DED12EC4917600E72587 /* FirebaseAuthCombine-Community in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DED02EC4917600E72587 /* FirebaseAuthCombine-Community */; };
ACF3DED32EC4917600E72587 /* FirebaseDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DED22EC4917600E72587 /* FirebaseDatabase */; };
ACF3DED52EC4917600E72587 /* FirebaseFirestoreCombine-Community in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DED42EC4917600E72587 /* FirebaseFirestoreCombine-Community */; };
ACF3DED72EC4917600E72587 /* FirebaseFunctionsCombine-Community in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DED62EC4917600E72587 /* FirebaseFunctionsCombine-Community */; };
ACF3DED92EC4917600E72587 /* FirebaseStorage in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DED82EC4917600E72587 /* FirebaseStorage */; };
ACF3DEDB2EC4917600E72587 /* FirebaseStorageCombine-Community in Frameworks */ = {isa = PBXBuildFile; productRef = ACF3DEDA2EC4917600E72587 /* FirebaseStorageCombine-Community */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@@ -31,11 +43,23 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
ACF3DED32EC4917600E72587 /* FirebaseDatabase in Frameworks */,
ACF3DECB2EC490D000E72587 /* FirebaseMessaging in Frameworks */,
AC136A092DB96847009D478F /* ObjectMapper in Frameworks */, AC136A092DB96847009D478F /* ObjectMapper in Frameworks */,
ACF3DEC52EC490D000E72587 /* FirebaseAuth in Frameworks */,
AC8826F52E6F5A6700ECEF0D /* TOCropViewController in Frameworks */, AC8826F52E6F5A6700ECEF0D /* TOCropViewController in Frameworks */,
ACF3DED92EC4917600E72587 /* FirebaseStorage in Frameworks */,
ACF3DEDB2EC4917600E72587 /* FirebaseStorageCombine-Community in Frameworks */,
ACF3DEC92EC490D000E72587 /* FirebaseInAppMessaging-Beta in Frameworks */,
AC8826F32E6F5A6700ECEF0D /* CropViewController in Frameworks */, AC8826F32E6F5A6700ECEF0D /* CropViewController in Frameworks */,
ACF3DEC72EC490D000E72587 /* FirebaseCore in Frameworks */,
ACF3DED72EC4917600E72587 /* FirebaseFunctionsCombine-Community in Frameworks */,
ACF3DED12EC4917600E72587 /* FirebaseAuthCombine-Community in Frameworks */,
ACF3DECF2EC4917600E72587 /* FirebaseAnalyticsCore in Frameworks */,
ACAC2DEB2D9F2C1900869E5C /* CalendarKit in Frameworks */, ACAC2DEB2D9F2C1900869E5C /* CalendarKit in Frameworks */,
ACF3DECD2EC4917600E72587 /* FirebaseAnalytics in Frameworks */,
AC53DEAA2DB9476D003445AD /* Alamofire in Frameworks */, AC53DEAA2DB9476D003445AD /* Alamofire in Frameworks */,
ACF3DED52EC4917600E72587 /* FirebaseFirestoreCombine-Community in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -46,6 +70,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
ACAC2DD12D9F271300869E5C /* Club Portal */, ACAC2DD12D9F271300869E5C /* Club Portal */,
ACF3DEDC2EC493E800E72587 /* Frameworks */,
ACAC2DD02D9F271300869E5C /* Products */, ACAC2DD02D9F271300869E5C /* Products */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
@@ -58,6 +83,13 @@
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
ACF3DEDC2EC493E800E72587 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@@ -83,6 +115,18 @@
AC136A082DB96847009D478F /* ObjectMapper */, AC136A082DB96847009D478F /* ObjectMapper */,
AC8826F22E6F5A6700ECEF0D /* CropViewController */, AC8826F22E6F5A6700ECEF0D /* CropViewController */,
AC8826F42E6F5A6700ECEF0D /* TOCropViewController */, AC8826F42E6F5A6700ECEF0D /* TOCropViewController */,
ACF3DEC42EC490D000E72587 /* FirebaseAuth */,
ACF3DEC62EC490D000E72587 /* FirebaseCore */,
ACF3DEC82EC490D000E72587 /* FirebaseInAppMessaging-Beta */,
ACF3DECA2EC490D000E72587 /* FirebaseMessaging */,
ACF3DECC2EC4917600E72587 /* FirebaseAnalytics */,
ACF3DECE2EC4917600E72587 /* FirebaseAnalyticsCore */,
ACF3DED02EC4917600E72587 /* FirebaseAuthCombine-Community */,
ACF3DED22EC4917600E72587 /* FirebaseDatabase */,
ACF3DED42EC4917600E72587 /* FirebaseFirestoreCombine-Community */,
ACF3DED62EC4917600E72587 /* FirebaseFunctionsCombine-Community */,
ACF3DED82EC4917600E72587 /* FirebaseStorage */,
ACF3DEDA2EC4917600E72587 /* FirebaseStorageCombine-Community */,
); );
productName = "Club Portal"; productName = "Club Portal";
productReference = ACAC2DCF2D9F271300869E5C /* Club Portal.app */; productReference = ACAC2DCF2D9F271300869E5C /* Club Portal.app */;
@@ -117,6 +161,7 @@
AC53DEA82DB9476D003445AD /* XCRemoteSwiftPackageReference "Alamofire" */, AC53DEA82DB9476D003445AD /* XCRemoteSwiftPackageReference "Alamofire" */,
AC136A072DB96847009D478F /* XCRemoteSwiftPackageReference "ObjectMapper" */, AC136A072DB96847009D478F /* XCRemoteSwiftPackageReference "ObjectMapper" */,
AC8826F12E6F5A6700ECEF0D /* XCRemoteSwiftPackageReference "TOCropViewController" */, AC8826F12E6F5A6700ECEF0D /* XCRemoteSwiftPackageReference "TOCropViewController" */,
ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
); );
preferredProjectObjectVersion = 77; preferredProjectObjectVersion = 77;
productRefGroup = ACAC2DD02D9F271300869E5C /* Products */; productRefGroup = ACAC2DD02D9F271300869E5C /* Products */;
@@ -273,6 +318,7 @@
buildSettings = { buildSettings = {
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_ENTITLEMENTS = "Club Portal/Club Portal.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 4; CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_ASSET_PATHS = "\"Club Portal/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Club Portal/Preview Content\"";
@@ -308,6 +354,7 @@
buildSettings = { buildSettings = {
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_ENTITLEMENTS = "Club Portal/Club Portal.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 4; CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_ASSET_PATHS = "\"Club Portal/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Club Portal/Preview Content\"";
@@ -394,6 +441,14 @@
minimumVersion = 1.1.11; minimumVersion = 1.1.11;
}; };
}; };
ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/firebase/firebase-ios-sdk.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 12.5.0;
};
};
/* End XCRemoteSwiftPackageReference section */ /* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
@@ -422,6 +477,66 @@
package = ACAC2DE92D9F2C1900869E5C /* XCRemoteSwiftPackageReference "CalendarKit" */; package = ACAC2DE92D9F2C1900869E5C /* XCRemoteSwiftPackageReference "CalendarKit" */;
productName = CalendarKit; productName = CalendarKit;
}; };
ACF3DEC42EC490D000E72587 /* FirebaseAuth */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseAuth;
};
ACF3DEC62EC490D000E72587 /* FirebaseCore */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseCore;
};
ACF3DEC82EC490D000E72587 /* FirebaseInAppMessaging-Beta */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = "FirebaseInAppMessaging-Beta";
};
ACF3DECA2EC490D000E72587 /* FirebaseMessaging */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseMessaging;
};
ACF3DECC2EC4917600E72587 /* FirebaseAnalytics */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseAnalytics;
};
ACF3DECE2EC4917600E72587 /* FirebaseAnalyticsCore */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseAnalyticsCore;
};
ACF3DED02EC4917600E72587 /* FirebaseAuthCombine-Community */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = "FirebaseAuthCombine-Community";
};
ACF3DED22EC4917600E72587 /* FirebaseDatabase */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseDatabase;
};
ACF3DED42EC4917600E72587 /* FirebaseFirestoreCombine-Community */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = "FirebaseFirestoreCombine-Community";
};
ACF3DED62EC4917600E72587 /* FirebaseFunctionsCombine-Community */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = "FirebaseFunctionsCombine-Community";
};
ACF3DED82EC4917600E72587 /* FirebaseStorage */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseStorage;
};
ACF3DEDA2EC4917600E72587 /* FirebaseStorageCombine-Community */ = {
isa = XCSwiftPackageProductDependency;
package = ACF3DEC32EC48ECD00E72587 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = "FirebaseStorageCombine-Community";
};
/* End XCSwiftPackageProductDependency section */ /* End XCSwiftPackageProductDependency section */
}; };
rootObject = ACAC2DC72D9F271300869E5C /* Project object */; rootObject = ACAC2DC72D9F271300869E5C /* Project object */;
@@ -1,6 +1,15 @@
{ {
"originHash" : "b1b0353358422b4fa2ea090c1b3ed8788cceebbcf36fc271f832e564b41e6da4", "originHash" : "28827aa8b1b4853bac5668c904753f1251153146a70f33dbdbae6b7398bba144",
"pins" : [ "pins" : [
{
"identity" : "abseil-cpp-binary",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/abseil-cpp-binary.git",
"state" : {
"revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5",
"version" : "1.2024072200.0"
}
},
{ {
"identity" : "alamofire", "identity" : "alamofire",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
@@ -10,6 +19,15 @@
"version" : "5.10.2" "version" : "5.10.2"
} }
}, },
{
"identity" : "app-check",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/app-check.git",
"state" : {
"revision" : "61b85103a1aeed8218f17c794687781505fbbef5",
"version" : "11.2.0"
}
},
{ {
"identity" : "calendarkit", "identity" : "calendarkit",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
@@ -19,6 +37,96 @@
"version" : "1.1.11" "version" : "1.1.11"
} }
}, },
{
"identity" : "firebase-ios-sdk",
"kind" : "remoteSourceControl",
"location" : "https://github.com/firebase/firebase-ios-sdk.git",
"state" : {
"revision" : "793b67f4652e1a39d03fab6650033768afe6d15e",
"version" : "12.5.0"
}
},
{
"identity" : "google-ads-on-device-conversion-ios-sdk",
"kind" : "remoteSourceControl",
"location" : "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk",
"state" : {
"revision" : "35b601a60fbbea2de3ea461f604deaaa4d8bbd0c",
"version" : "3.2.0"
}
},
{
"identity" : "googleappmeasurement",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/GoogleAppMeasurement.git",
"state" : {
"revision" : "c2d59acf17a8ba7ed80a763593c67c9c7c006ad1",
"version" : "12.5.0"
}
},
{
"identity" : "googledatatransport",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/GoogleDataTransport.git",
"state" : {
"revision" : "617af071af9aa1d6a091d59a202910ac482128f9",
"version" : "10.1.0"
}
},
{
"identity" : "googleutilities",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/GoogleUtilities.git",
"state" : {
"revision" : "60da361632d0de02786f709bdc0c4df340f7613e",
"version" : "8.1.0"
}
},
{
"identity" : "grpc-binary",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/grpc-binary.git",
"state" : {
"revision" : "75b31c842f664a0f46a2e590a570e370249fd8f6",
"version" : "1.69.1"
}
},
{
"identity" : "gtm-session-fetcher",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/gtm-session-fetcher.git",
"state" : {
"revision" : "fb7f2740b1570d2f7599c6bb9531bf4fad6974b7",
"version" : "5.0.0"
}
},
{
"identity" : "interop-ios-for-google-sdks",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/interop-ios-for-google-sdks.git",
"state" : {
"revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe",
"version" : "101.0.0"
}
},
{
"identity" : "leveldb",
"kind" : "remoteSourceControl",
"location" : "https://github.com/firebase/leveldb.git",
"state" : {
"revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1",
"version" : "1.22.5"
}
},
{
"identity" : "nanopb",
"kind" : "remoteSourceControl",
"location" : "https://github.com/firebase/nanopb.git",
"state" : {
"revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1",
"version" : "2.30910.0"
}
},
{ {
"identity" : "objectmapper", "identity" : "objectmapper",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
@@ -28,6 +136,24 @@
"version" : "4.4.3" "version" : "4.4.3"
} }
}, },
{
"identity" : "promises",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/promises.git",
"state" : {
"revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac",
"version" : "2.4.0"
}
},
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-protobuf.git",
"state" : {
"revision" : "c169a5744230951031770e27e475ff6eefe51f9d",
"version" : "1.33.3"
}
},
{ {
"identity" : "tocropviewcontroller", "identity" : "tocropviewcontroller",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
@@ -50,6 +50,36 @@
endingLineNumber = "74" endingLineNumber = "74"
landmarkName = "body" landmarkName = "body"
landmarkType = "24"> landmarkType = "24">
<Locations>
<Location
uuid = "40F6EF95-AF67-4F44-8D78-9C818848D826 - fde7150bc1a2f4d3"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "closure #5 (Club_Portal.StaffAvailable) -&gt; SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(Club_Portal.ProfileImageView, SwiftUI.Text, SwiftUI.Spacer, &lt;&lt;opaque return type of SwiftUI.View.onTapGesture(count: Swift.Int, perform: () -&gt; ()) -&gt; some&gt;&gt;.0)&gt;&gt;, SwiftUI.Divider)&gt; in closure #1 () -&gt; SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(SwiftUI.Label&lt;SwiftUI.Text, SwiftUI.Image&gt;, SwiftUI.Spacer, &lt;&lt;opaque return type of SwiftUI.View.clipShape&lt;&#x3c4;_0_0 where &#x3c4;_1_0: SwiftUI.Shape&gt;(_: &#x3c4;_1_0, style: SwiftUI.FillStyle) -&gt; some&gt;&gt;.0)&gt;&gt;, SwiftUI._ConditionalContent&lt;SwiftUI._ConditionalContent&lt;SwiftUI.ForEach&lt;Swift.Array&lt;Club_Portal.CourtsAvailable&gt;, Club_Portal.CourtsAvailable, SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(SwiftUI.Text, SwiftUI.Text, SwiftUI.Spacer)&gt;&gt;, SwiftUI.Divider)&gt;&gt;, SwiftUI.ForEach&lt;Swift.Array&lt;Club_Portal.HourSlot&gt;, Club_Portal.HourSlot, SwiftUI.TupleView&lt;(&lt;&lt;opaque return type of SwiftUI.View.onTapGesture(count: Swift.Int, perform: () -&gt; ()) -&gt; some&gt;&gt;.0, SwiftUI.Divider)&gt;&gt;&gt;, SwiftUI._ConditionalContent&lt;SwiftUI.ForEach&lt;Swift.Array&lt;Club_Portal.CoachesAvailable&gt;, Swift.Optional&lt;Swift.Int&gt;, SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(Club_Portal.ProfileImageView, SwiftUI.Text, SwiftUI.Spacer, &lt;&lt;opaque return type of SwiftUI.View.onTapGesture(count: Swift.Int, perform: () -&gt; ()) -&gt; some&gt;&gt;.0)&gt;&gt;, SwiftUI.Divider)&gt;&gt;, SwiftUI.ForEach&lt;Swift.Array&lt;Club_Portal.StaffAvailable&gt;, Swift.Optional&lt;Swift.Int&gt;, SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(Club_Portal.ProfileImageView, SwiftUI.Text, SwiftUI.Spacer, &lt;&lt;opaque return type of SwiftUI.View.onTapGesture(count: Swift.Int, perform: () -&gt; ()) -&gt; some&gt;&gt;.0)&gt;&gt;, SwiftUI.Divider)&gt;&gt;&gt;&gt;)&gt; in Club_Portal.AvailabilityCardView.body.getter : some"
moduleName = "Club Portal.debug.dylib"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/umertahir/Projects/MKD/club_portal_ios/Club_portal/Club%20Portal/Club%20Portal/UI/Availbility/AvailabilityCardView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "74"
endingLineNumber = "74">
</Location>
<Location
uuid = "40F6EF95-AF67-4F44-8D78-9C818848D826 - 13b9a9303560d13a"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "closure #1 () -&gt; SwiftUI.TupleView&lt;(Club_Portal.ProfileImageView, SwiftUI.Text, SwiftUI.Spacer, &lt;&lt;opaque return type of SwiftUI.View.onTapGesture(count: Swift.Int, perform: () -&gt; ()) -&gt; some&gt;&gt;.0)&gt; in closure #5 (Club_Portal.StaffAvailable) -&gt; SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(Club_Portal.ProfileImageView, SwiftUI.Text, SwiftUI.Spacer, &lt;&lt;opaque return type of SwiftUI.View.onTapGesture(count: Swift.Int, perform: () -&gt; ()) -&gt; some&gt;&gt;.0)&gt;&gt;, SwiftUI.Divider)&gt; in closure #1 () -&gt; SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(SwiftUI.Label&lt;SwiftUI.Text, SwiftUI.Image&gt;, SwiftUI.Spacer, &lt;&lt;opaque return type of SwiftUI.View.clipShape&lt;&#x3c4;_0_0 where &#x3c4;_1_0: SwiftUI.Shape&gt;(_: &#x3c4;_1_0, style: SwiftUI.FillStyle) -&gt; some&gt;&gt;.0)&gt;&gt;, SwiftUI._ConditionalContent&lt;SwiftUI._ConditionalContent&lt;SwiftUI.ForEach&lt;Swift.Array&lt;Club_Portal.CourtsAvailable&gt;, Club_Portal.CourtsAvailable, SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(SwiftUI.Text, SwiftUI.Text, SwiftUI.Spacer)&gt;&gt;, SwiftUI.Divider)&gt;&gt;, SwiftUI.ForEach&lt;Swift.Array&lt;Club_Portal.HourSlot&gt;, Club_Portal.HourSlot, SwiftUI.TupleView&lt;(&lt;&lt;opaque return type of SwiftUI.View.onTapGesture(count: Swift.Int, perform: () -&gt; ()) -&gt; some&gt;&gt;.0, SwiftUI.Divider)&gt;&gt;&gt;, SwiftUI._ConditionalContent&lt;SwiftUI.ForEach&lt;Swift.Array&lt;Club_Portal.CoachesAvailable&gt;, Swift.Optional&lt;Swift.Int&gt;, SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(Club_Portal.ProfileImageView, SwiftUI.Text, SwiftUI.Spacer, &lt;&lt;opaque return type of SwiftUI.View.onTapGesture(count: Swift.Int, perform: () -&gt; ()) -&gt; some&gt;&gt;.0)&gt;&gt;, SwiftUI.Divider)&gt;&gt;, SwiftUI.ForEach&lt;Swift.Array&lt;Club_Portal.StaffAvailable&gt;, Swift.Optional&lt;Swift.Int&gt;, SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;SwiftUI.TupleView&lt;(Club_Portal.ProfileImageView, SwiftUI.Text, SwiftUI.Spacer, &lt;&lt;opaque return type of SwiftUI.View.onTapGesture(count: Swift.Int, perform: () -&gt; ()) -&gt; some&gt;&gt;.0)&gt;&gt;, SwiftUI.Divider)&gt;&gt;&gt;&gt;)&gt; in Club_Portal.AvailabilityCardView.body.getter : some"
moduleName = "Club Portal.debug.dylib"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/umertahir/Projects/MKD/club_portal_ios/Club_portal/Club%20Portal/Club%20Portal/UI/Availbility/AvailabilityCardView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "75"
endingLineNumber = "75">
</Location>
</Locations>
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>
<BreakpointProxy <BreakpointProxy
@@ -66,6 +96,36 @@
endingLineNumber = "92" endingLineNumber = "92"
landmarkName = "body" landmarkName = "body"
landmarkType = "24"> landmarkType = "24">
<Locations>
<Location
uuid = "77A0E8D4-D5E6-4609-9344-05A557E18094 - 6ba4a7d6d1837463"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "Club_Portal.PieChartCard.body.getter : some"
moduleName = "Club Portal.debug.dylib"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/umertahir/Projects/MKD/club_portal_ios/Club_portal/Club%20Portal/Club%20Portal/UI/Dashboard/AnalyticsView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "92"
endingLineNumber = "92">
</Location>
<Location
uuid = "77A0E8D4-D5E6-4609-9344-05A557E18094 - 68a3d412f207866"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "closure #2 () -&gt; SwiftUI.VStack&lt;SwiftUI.TupleView&lt;(SwiftUI.HStack&lt;&lt;&lt;opaque return type of SwiftUI.View.padding(SwiftUI.Edge.Set, Swift.Optional&lt;CoreGraphics.CGFloat&gt;) -&gt; some&gt;&gt;.0&gt;, &lt;&lt;opaque return type of SwiftUI.View.frame(width: Swift.Optional&lt;CoreGraphics.CGFloat&gt;, height: Swift.Optional&lt;CoreGraphics.CGFloat&gt;, alignment: SwiftUI.Alignment) -&gt; some&gt;&gt;.0)&gt;&gt; in Club_Portal.PieChartCard.body.getter : some"
moduleName = "Club Portal.debug.dylib"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/umertahir/Projects/MKD/club_portal_ios/Club_portal/Club%20Portal/Club%20Portal/UI/Dashboard/AnalyticsView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "93"
endingLineNumber = "93">
</Location>
</Locations>
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>
<BreakpointProxy <BreakpointProxy
@@ -82,6 +142,36 @@
endingLineNumber = "88" endingLineNumber = "88"
landmarkName = "body" landmarkName = "body"
landmarkType = "24"> landmarkType = "24">
<Locations>
<Location
uuid = "C83F37A1-9F08-46E4-AE95-CF8DB346F8D4 - 6ba4a7d6d18373ef"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "Club_Portal.PieChartCard.body.getter : some"
moduleName = "Club Portal.debug.dylib"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/umertahir/Projects/MKD/club_portal_ios/Club_portal/Club%20Portal/Club%20Portal/UI/Dashboard/AnalyticsView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "88"
endingLineNumber = "88">
</Location>
<Location
uuid = "C83F37A1-9F08-46E4-AE95-CF8DB346F8D4 - ff416623d141cafd"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "closure #1 (Club_Portal.RevenueByModule) -&gt; (name: Swift.Optional&lt;Swift.String&gt;, value: Swift.Int, color: SwiftUI.Color) in Club_Portal.PieChartCard.body.getter : some"
moduleName = "Club Portal.debug.dylib"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/umertahir/Projects/MKD/club_portal_ios/Club_portal/Club%20Portal/Club%20Portal/UI/Dashboard/AnalyticsView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "89"
endingLineNumber = "89">
</Location>
</Locations>
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>
<BreakpointProxy <BreakpointProxy
@@ -164,5 +254,21 @@
landmarkType = "24"> landmarkType = "24">
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "C22D5618-362D-4F06-BD7D-85D0410A5A8B"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Club Portal/Services/NotificationService.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "80"
endingLineNumber = "80"
landmarkName = "sendTokenToServer(token:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints> </Breakpoints>
</Bucket> </Bucket>
@@ -0,0 +1,8 @@
<?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>aps-environment</key>
<string>development</string>
</dict>
</plist>
@@ -0,0 +1,30 @@
<?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>API_KEY</key>
<string>AIzaSyBdzkpF0c0ZFyh3Js-K8wEOPR5sHnNV--8</string>
<key>GCM_SENDER_ID</key>
<string>1016302979918</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.app.Club-Portal</string>
<key>PROJECT_ID</key>
<string>court-matchup-aa3e3</string>
<key>STORAGE_BUCKET</key>
<string>court-matchup-aa3e3.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:1016302979918:ios:10e9be076f05b83c80ac1f</string>
</dict>
</plist>
@@ -0,0 +1,64 @@
import Foundation
// MARK: - Register Device Endpoint
struct RegisterDeviceEndpoint: Endpoint {
var urlQueryItems: [URLQueryItem] = []
var customHeaders: [String: String]? { nil }
var isMultipart: Bool
let deviceToken: String
let deviceId: String
let deviceName: String
let appVersion: String
var path: String {
return "/v3/api/custom/courtmatchup/push/register-device"
}
var method: HTTPMethod {
return .post
}
var headers: [String: String]? {
return ["Content-Type": "application/json"]
}
var body: Data? {
let params: [String: Any] = [
"device_token": deviceToken,
"platform": "ios",
"device_id": deviceId,
"device_name": deviceName,
"app_version": appVersion
]
return try? JSONSerialization.data(withJSONObject: params)
}
}
// MARK: - Unregister Device Endpoint
struct UnregisterDeviceEndpoint: Endpoint {
var urlQueryItems: [URLQueryItem] = []
var customHeaders: [String: String]? { nil }
var isMultipart: Bool
let deviceToken: String
var path: String {
return "/v3/api/custom/courtmatchup/push/unregister-device"
}
var method: HTTPMethod {
return .post
}
var headers: [String: String]? {
return ["Content-Type": "application/json"]
}
var body: Data? {
let params: [String: String] = ["device_token": deviceToken]
return try? JSONSerialization.data(withJSONObject: params)
}
}
@@ -0,0 +1,148 @@
import Foundation
import SwiftUI
import FirebaseCore
import FirebaseMessaging
import UserNotifications
// MARK: - Empty Response Model
struct EmptyResponse: Codable {
// This is a placeholder for API responses that don't return any data
}
class NotificationService: NSObject, ObservableObject {
static let shared = NotificationService()
@Published var fcmToken: String = ""
func requestNotificationPermission() {
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().getNotificationSettings { settings in
if settings.authorizationStatus == .notDetermined {
// Request permission if not determined
UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { granted, error in
if let error = error {
print("Error requesting notification permission: \(error.localizedDescription)")
return
}
if granted {
print("Notification permission granted")
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
} else {
print("Notification permission denied")
}
}
} else if settings.authorizationStatus == .authorized {
// Already authorized, register for remote notifications
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
}
func updateFCMToken() {
Messaging.messaging().token { [weak self] token, error in
if let error = error {
print("Error fetching FCM token: \(error.localizedDescription)")
return
}
if let token = token {
print("FCM Token: \(token)")
self?.fcmToken = token
AppSettings.fcm = token
// TODO: Send this token to your backend
self?.sendTokenToServer(token: token)
}
}
}
private func sendTokenToServer(token: String) {
let deviceId = UIDevice.current.identifierForVendor?.uuidString ?? ""
let deviceName = UIDevice.current.name
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0"
let endpoint = RegisterDeviceEndpoint(
isMultipart: false,
deviceToken: token,
deviceId: deviceId,
deviceName: deviceName,
appVersion: appVersion
)
Task {
do {
_ = try await APIService.shared.request(endpoint, responseType: EmptyResponse.self)
print("Successfully registered FCM token with server")
} catch {
print("Failed to register FCM token: \(error.localizedDescription)")
}
}
}
func unregisterDevice(completion: (() -> Void)? = nil) {
guard !fcmToken.isEmpty else {
completion?()
return
}
let endpoint = UnregisterDeviceEndpoint(isMultipart: false, deviceToken: fcmToken)
Task {
do {
_ = try await APIService.shared.request(endpoint, responseType: EmptyResponse.self)
print("Successfully unregistered FCM token from server")
} catch {
print("Failed to unregister FCM token: \(error.localizedDescription)")
}
completion?()
}
}
}
// MARK: - UNUserNotificationCenterDelegate
extension NotificationService: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
print("Received notification: \(userInfo)")
// Show the notification even when the app is in the foreground
completionHandler([.banner, .sound, .badge])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
print("User tapped on notification: \(userInfo)")
// Handle the notification tap here
handleNotification(userInfo: userInfo)
completionHandler()
}
private func handleNotification(userInfo: [AnyHashable: Any]) {
// Handle the notification data here
// You can navigate to specific screens based on the notification data
print("Handling notification with data: \(userInfo)")
}
}
// MARK: - MessagingDelegate
extension NotificationService: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("Firebase registration token: \(String(describing: fcmToken))")
if let token = fcmToken {
self.fcmToken = token
sendTokenToServer(token: token)
}
}
}
@@ -6,10 +6,15 @@
// //
import SwiftUI import SwiftUI
import FirebaseCore
import FirebaseMessaging
import UIKit
@main @main
struct Club_PortalApp: App { struct Club_PortalApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
// Initialize notification service
@StateObject var notificationService = NotificationService()
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
WelcomeView() WelcomeView()
@@ -21,3 +26,46 @@ struct Club_PortalApp: App {
} }
} }
class AppDelegate: NSObject, UIApplicationDelegate {
let gcmMessageIDKey = "gcm.message_id"
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// Configure Firebase
FirebaseApp.configure()
// Set up notifications
UNUserNotificationCenter.current().delegate = NotificationService.shared
Messaging.messaging().delegate = NotificationService.shared
// Request notification permissions
NotificationService.shared.requestNotificationPermission()
// Register for remote notifications
application.registerForRemoteNotifications()
return true
}
// Handle remote notification registration
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
NotificationService.shared.updateFCMToken()
}
// Handle notification tap when app is in background or terminated
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
}
@@ -41,6 +41,7 @@ final class AppSettings {
case lastReserveTime case lastReserveTime
case lastReservationTotal case lastReservationTotal
case isLoggedin case isLoggedin
case fcm
@@ -81,6 +82,14 @@ final class AppSettings {
USERDEFAULTS_SET_STRING_KEY(object: newValue, key: SettingKey.plan_name.rawValue) USERDEFAULTS_SET_STRING_KEY(object: newValue, key: SettingKey.plan_name.rawValue)
} }
} }
static var fcm: String {
get {
return USERDEFAULTS_GET_STRING_KEY(key: SettingKey.fcm.rawValue)
}
set {
USERDEFAULTS_SET_STRING_KEY(object: newValue, key: SettingKey.fcm.rawValue)
}
}
static var price: Double { static var price: Double {
get { get {
return USERDEFAULTS_GET_DOUBLE_KEY(key: SettingKey.price.rawValue) return USERDEFAULTS_GET_DOUBLE_KEY(key: SettingKey.price.rawValue)