diff --git a/score-ios.xcodeproj/project.pbxproj b/score-ios.xcodeproj/project.pbxproj index f8a2cf3..a60ef41 100644 --- a/score-ios.xcodeproj/project.pbxproj +++ b/score-ios.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 136A359F2F6B328F004EFFA6 /* TopHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 136A359E2F6B328C004EFFA6 /* TopHeader.swift */; }; + 13859D642F61C63300ECC335 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13859D632F61C62F00ECC335 /* User.swift */; }; + 13859D662F61C67200ECC335 /* ProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13859D652F61C66B00ECC335 /* ProfileViewModel.swift */; }; + 13A311E72F47E3160065010E /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13A311E62F47E30F0065010E /* ProfileView.swift */; }; 1C87865D2D8CD76900EBDF74 /* TrailingFadeGradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C87865C2D8CD76900EBDF74 /* TrailingFadeGradient.swift */; }; 1C87865F2D8CDADC00EBDF74 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C87865E2D8CDADC00EBDF74 /* String+Extension.swift */; }; 2384C7B81B22428D94240957 /* Highlight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840304A20FA141C291346BA8 /* Highlight.swift */; }; @@ -130,6 +134,10 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 136A359E2F6B328C004EFFA6 /* TopHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopHeader.swift; sourceTree = ""; }; + 13859D632F61C62F00ECC335 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; + 13859D652F61C66B00ECC335 /* ProfileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewModel.swift; sourceTree = ""; }; + 13A311E62F47E30F0065010E /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; 1C87865C2D8CD76900EBDF74 /* TrailingFadeGradient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrailingFadeGradient.swift; sourceTree = ""; }; 1C87865E2D8CDADC00EBDF74 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = ""; }; 2C1375CA2E7233390089EBC7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; @@ -277,6 +285,7 @@ CE335CCC2C9226F90037F572 /* Models */ = { isa = PBXGroup; children = ( + 13859D632F61C62F00ECC335 /* User.swift */, D89102052CED6A1E004CE226 /* GraphQL */, CE335CD82C9244230037F572 /* Game.swift */, CE8ED4F52D6BF35F00A274DE /* Team.swift */, @@ -421,6 +430,7 @@ CE8ED50A2D6C385E00A274DE /* MainViews */ = { isa = PBXGroup; children = ( + 13A311E62F47E30F0065010E /* ProfileView.swift */, CE725D3D2C89120200386943 /* ScoreApp.swift */, D86347DE2CE98B3C003DD8F6 /* MainTabView.swift */, D86347E02CE98D37003DD8F6 /* TabViewIcon.swift */, @@ -433,6 +443,7 @@ CE8ED50B2D6C386B00A274DE /* DetailedViews */ = { isa = PBXGroup; children = ( + 136A359E2F6B328C004EFFA6 /* TopHeader.swift */, D858020F2D6C38670075B036 /* DynamicScoreBox.swift */, D83EE8852CC9917C008B693C /* ScoreSummaryTile.swift */, 76101F692E981E37006D6EDD /* DetailedHighlightView.swift */, @@ -502,6 +513,7 @@ D87787C62CFFAE3D00EA79E1 /* ViewModels */ = { isa = PBXGroup; children = ( + 13859D652F61C66B00ECC335 /* ProfileViewModel.swift */, D87787C72CFFAE5200EA79E1 /* GamesViewModel.swift */, 7665A4062EB00528004A9903 /* HighlightsViewModel.swift */, D864B5AA2D793A7400A3A50E /* PastGameViewModel.swift */, @@ -724,6 +736,7 @@ CE8ED5022D6BF4E800A274DE /* TimeUpdate.swift in Sources */, D89102132CF10CA9004CE226 /* NetworkManager.swift in Sources */, CE725D3E2C89120200386943 /* ScoreApp.swift in Sources */, + 13859D642F61C63300ECC335 /* User.swift in Sources */, D836AD922CB62C8800BD1545 /* NoGameView.swift in Sources */, 7626AD682E973D9B002149CD /* SearchView.swift in Sources */, 7626AD692E973D9B002149CD /* HighlightView.swift in Sources */, @@ -737,8 +750,10 @@ D85802102D6C38700075B036 /* DynamicScoreBox.swift in Sources */, D8B1C9D32CD2D20A0095E563 /* PastGameTile.swift in Sources */, 7626AD6F2E973E08002149CD /* View+CornerRadius.swift in Sources */, + 136A359F2F6B328F004EFFA6 /* TopHeader.swift in Sources */, CE528FA22C9651C800C238B5 /* UpcomingGameTile.swift in Sources */, FD5A38DD2D8F30CC00CF5E30 /* GameErrorView.swift in Sources */, + 13A311E72F47E3160065010E /* ProfileView.swift in Sources */, CEA25A932D75279A00B9837A /* ScoreEnvironment.swift in Sources */, FD5A38DB2D8F2BDD00CF5E30 /* GameLoadingView.swift in Sources */, B136701ECD164EE9AC64667F /* Article.swift in Sources */, @@ -767,6 +782,7 @@ CE335CD32C922E8D0037F572 /* PrimaryColors.swift in Sources */, FD27F4232DC0A68900CC172E /* GamesCacheManager.swift in Sources */, CE725D3C2C89120200386943 /* Home.swift in Sources */, + 13859D662F61C67200ECC335 /* ProfileViewModel.swift in Sources */, FD5A38DF2D8F3E1400CF5E30 /* ShimmerModifier.swift in Sources */, CE528FA02C96420700C238B5 /* PickerView.swift in Sources */, CE528FA42C9653C200C238B5 /* Error.swift in Sources */, @@ -946,7 +962,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 26; DEVELOPMENT_ASSET_PATHS = "\"score-ios/Preview Content\""; - DEVELOPMENT_TEAM = W7U2WA4D54; + DEVELOPMENT_TEAM = H5ZTDCQ89H; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "score-ios/Info.plist"; @@ -980,7 +996,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 26; DEVELOPMENT_ASSET_PATHS = "\"score-ios/Preview Content\""; - DEVELOPMENT_TEAM = W7U2WA4D54; + DEVELOPMENT_TEAM = H5ZTDCQ89H; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "score-ios/Info.plist"; diff --git a/score-ios/Models/User.swift b/score-ios/Models/User.swift new file mode 100644 index 0000000..2678204 --- /dev/null +++ b/score-ios/Models/User.swift @@ -0,0 +1,12 @@ +// +// User.swift +// score-ios +// +// Created by Duru Alayli on 3/11/26. +// + +struct User { + var name: String + var username: String + var profileImage: String +} diff --git a/score-ios/Resources/Assets.xcassets/Arrowhead.imageset/Arrowhead.png b/score-ios/Resources/Assets.xcassets/Arrowhead.imageset/Arrowhead.png new file mode 100644 index 0000000..728c34e Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/Arrowhead.imageset/Arrowhead.png differ diff --git a/score-ios/Resources/Assets.xcassets/Arrowhead.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/Arrowhead.imageset/Contents.json new file mode 100644 index 0000000..abf5735 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/Arrowhead.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Arrowhead.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/BookmarkGame.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/BookmarkGame.imageset/Contents.json new file mode 100644 index 0000000..2548403 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/BookmarkGame.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "image 6.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/BookmarkGame.imageset/image 6.png b/score-ios/Resources/Assets.xcassets/BookmarkGame.imageset/image 6.png new file mode 100644 index 0000000..afcc6ee Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/BookmarkGame.imageset/image 6.png differ diff --git a/score-ios/Resources/Assets.xcassets/check.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/check.imageset/Contents.json new file mode 100644 index 0000000..bd23e48 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/check.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "check.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/check.imageset/check.png b/score-ios/Resources/Assets.xcassets/check.imageset/check.png new file mode 100644 index 0000000..c3f9182 Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/check.imageset/check.png differ diff --git a/score-ios/Resources/Assets.xcassets/cross.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/cross.imageset/Contents.json new file mode 100644 index 0000000..3fec761 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/cross.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Group 8.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/cross.imageset/Group 8.png b/score-ios/Resources/Assets.xcassets/cross.imageset/Group 8.png new file mode 100644 index 0000000..040075e Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/cross.imageset/Group 8.png differ diff --git a/score-ios/Resources/Assets.xcassets/dehaze.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/dehaze.imageset/Contents.json new file mode 100644 index 0000000..b467fe7 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/dehaze.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "dehaze.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/dehaze.imageset/dehaze.png b/score-ios/Resources/Assets.xcassets/dehaze.imageset/dehaze.png new file mode 100644 index 0000000..5326ebf Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/dehaze.imageset/dehaze.png differ diff --git a/score-ios/Resources/Assets.xcassets/notifications.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/notifications.imageset/Contents.json new file mode 100644 index 0000000..b1f33b6 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/notifications.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "line-md_bell.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/notifications.imageset/line-md_bell.png b/score-ios/Resources/Assets.xcassets/notifications.imageset/line-md_bell.png new file mode 100644 index 0000000..7be4e7f Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/notifications.imageset/line-md_bell.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile.imageset/Contents.json new file mode 100644 index 0000000..37bf4c2 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "profile (1).png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile.imageset/profile (1).png b/score-ios/Resources/Assets.xcassets/profile.imageset/profile (1).png new file mode 100644 index 0000000..f5a1b9a Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile.imageset/profile (1).png differ diff --git a/score-ios/Resources/Assets.xcassets/profile0.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile0.imageset/Contents.json new file mode 100644 index 0000000..24c474e --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile0.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "image.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile0.imageset/image.png b/score-ios/Resources/Assets.xcassets/profile0.imageset/image.png new file mode 100644 index 0000000..3ed14cb Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile0.imageset/image.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile1.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile1.imageset/Contents.json new file mode 100644 index 0000000..3caee0d --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 18.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile1.imageset/Ellipse 18.png b/score-ios/Resources/Assets.xcassets/profile1.imageset/Ellipse 18.png new file mode 100644 index 0000000..94af83f Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile1.imageset/Ellipse 18.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile10.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile10.imageset/Contents.json new file mode 100644 index 0000000..dc2b6b6 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile10.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 15.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile10.imageset/Ellipse 15.png b/score-ios/Resources/Assets.xcassets/profile10.imageset/Ellipse 15.png new file mode 100644 index 0000000..2de0c5d Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile10.imageset/Ellipse 15.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile11.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile11.imageset/Contents.json new file mode 100644 index 0000000..a4d16b1 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile11.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 19.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile11.imageset/Ellipse 19.png b/score-ios/Resources/Assets.xcassets/profile11.imageset/Ellipse 19.png new file mode 100644 index 0000000..23d8d30 Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile11.imageset/Ellipse 19.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile2.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile2.imageset/Contents.json new file mode 100644 index 0000000..d55426b --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 9.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile2.imageset/Ellipse 9.png b/score-ios/Resources/Assets.xcassets/profile2.imageset/Ellipse 9.png new file mode 100644 index 0000000..63ef187 Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile2.imageset/Ellipse 9.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile3.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile3.imageset/Contents.json new file mode 100644 index 0000000..70df62d --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 10.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile3.imageset/Ellipse 10.png b/score-ios/Resources/Assets.xcassets/profile3.imageset/Ellipse 10.png new file mode 100644 index 0000000..3b1229f Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile3.imageset/Ellipse 10.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile4.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile4.imageset/Contents.json new file mode 100644 index 0000000..ec24db2 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 11.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile4.imageset/Ellipse 11.png b/score-ios/Resources/Assets.xcassets/profile4.imageset/Ellipse 11.png new file mode 100644 index 0000000..b0ae5b8 Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile4.imageset/Ellipse 11.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile5.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile5.imageset/Contents.json new file mode 100644 index 0000000..592081c --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile5.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 13 (1).png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile5.imageset/Ellipse 13 (1).png b/score-ios/Resources/Assets.xcassets/profile5.imageset/Ellipse 13 (1).png new file mode 100644 index 0000000..23eda19 Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile5.imageset/Ellipse 13 (1).png differ diff --git a/score-ios/Resources/Assets.xcassets/profile6.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile6.imageset/Contents.json new file mode 100644 index 0000000..9432d95 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile6.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 14.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile6.imageset/Ellipse 14.png b/score-ios/Resources/Assets.xcassets/profile6.imageset/Ellipse 14.png new file mode 100644 index 0000000..a6b7770 Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile6.imageset/Ellipse 14.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile7.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile7.imageset/Contents.json new file mode 100644 index 0000000..6fe54a9 --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile7.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 16.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile7.imageset/Ellipse 16.png b/score-ios/Resources/Assets.xcassets/profile7.imageset/Ellipse 16.png new file mode 100644 index 0000000..c5d38ff Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile7.imageset/Ellipse 16.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile8.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile8.imageset/Contents.json new file mode 100644 index 0000000..67ea8cc --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile8.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 17.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile8.imageset/Ellipse 17.png b/score-ios/Resources/Assets.xcassets/profile8.imageset/Ellipse 17.png new file mode 100644 index 0000000..643b22a Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile8.imageset/Ellipse 17.png differ diff --git a/score-ios/Resources/Assets.xcassets/profile9.imageset/Contents.json b/score-ios/Resources/Assets.xcassets/profile9.imageset/Contents.json new file mode 100644 index 0000000..a375f1d --- /dev/null +++ b/score-ios/Resources/Assets.xcassets/profile9.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ellipse 12.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/score-ios/Resources/Assets.xcassets/profile9.imageset/Ellipse 12.png b/score-ios/Resources/Assets.xcassets/profile9.imageset/Ellipse 12.png new file mode 100644 index 0000000..3429a7c Binary files /dev/null and b/score-ios/Resources/Assets.xcassets/profile9.imageset/Ellipse 12.png differ diff --git a/score-ios/Utils/Constants.swift b/score-ios/Utils/Constants.swift index 1b50649..c8376bd 100644 --- a/score-ios/Utils/Constants.swift +++ b/score-ios/Utils/Constants.swift @@ -22,6 +22,7 @@ struct Constants { static let gray_liner = Color(hex: 0xC2C2C2) static let gray_border = Color(hex: 0xEAEAEA) static let gray_icons = Color(hex: 0x777777) + static let primary_gray = Color(hex: 0x333333) // static let graybg = Color(hex: 0xF0F1F2) // static let gray00 = Color(hex: 0xF7F7F7) // static let gray01 = Color(hex: 0xEFF1F4) diff --git a/score-ios/ViewModels/ProfileViewModel.swift b/score-ios/ViewModels/ProfileViewModel.swift new file mode 100644 index 0000000..d52698f --- /dev/null +++ b/score-ios/ViewModels/ProfileViewModel.swift @@ -0,0 +1,34 @@ +// +// ProfileViewModel.swift +// score-ios +// +// Created by Duru Alayli on 3/11/26. +// + +import SwiftUI + +// MARK: - ViewModel +class ProfileViewModel: ObservableObject { + @Published var user: User + + static let shared = ProfileViewModel() + + // MARK: - Functions + init() { + let name = UserDefaults.standard.string(forKey: "name") ?? "Name" + let username = UserDefaults.standard.string(forKey: "username") ?? "username" + let profileImage = UserDefaults.standard.string(forKey: "profileImage") ?? "profile0" + + self.user = User(name: name, username: username, profileImage: profileImage) + } + + func saveUser(name: String, username: String, profileImage: String) { + user.name = name + user.username = username + user.profileImage = profileImage + + UserDefaults.standard.set(name, forKey: "name") + UserDefaults.standard.set(username, forKey: "username") + UserDefaults.standard.set(profileImage, forKey: "profileImage") + } +} diff --git a/score-ios/Views/DetailedViews/TopHeader.swift b/score-ios/Views/DetailedViews/TopHeader.swift new file mode 100644 index 0000000..e99d798 --- /dev/null +++ b/score-ios/Views/DetailedViews/TopHeader.swift @@ -0,0 +1,40 @@ +// +// TopHeader.swift +// score-ios +// +// Created by Duru Alaylı on 3/18/26. +// + +import SwiftUI + +struct TopHeader: View { + let title: String + let onProfileTap: () -> Void + + var body: some View { + HStack { + Text(title) + .font(Constants.Fonts.semibold24) + + Spacer() + + Button { + // notifications + } label: { + Image("notifications") + .resizable() + .frame(width: 36, height: 36) + } + + Button { + onProfileTap() + } label: { + Image("profile") + .resizable() + .frame(width: 28, height: 28) + } + } + .padding(.top, 24) + .background(Color.white) + } +} diff --git a/score-ios/Views/ListViews/CarouselView.swift b/score-ios/Views/ListViews/CarouselView.swift index 5e1042f..f79b38b 100644 --- a/score-ios/Views/ListViews/CarouselView.swift +++ b/score-ios/Views/ListViews/CarouselView.swift @@ -8,6 +8,7 @@ import SwiftUI struct CarouselView: View { + @Binding var showProfile: Bool @State private var selectedCardIndex: Int = 0 var games: [Game] var title: String @@ -16,11 +17,12 @@ struct CarouselView: View { var body: some View { VStack (alignment: .center) { - Text(title) - .font(Constants.Fonts.semibold24) - .foregroundStyle(Constants.Colors.black) - .frame(maxWidth: .infinity, alignment: .leading) // Align to the left - .padding(.top, 24) + TopHeader( + title: title, + onProfileTap: { + showProfile = true + } + ) // Carousel TabView(selection: $selectedCardIndex) { diff --git a/score-ios/Views/ListViews/HighlightView.swift b/score-ios/Views/ListViews/HighlightView.swift index 6299c86..bf3add2 100644 --- a/score-ios/Views/ListViews/HighlightView.swift +++ b/score-ios/Views/ListViews/HighlightView.swift @@ -9,6 +9,7 @@ import SwiftUI struct HighlightView: View { @EnvironmentObject var viewModel: HighlightsViewModel + @Binding var showProfile: Bool var body: some View { @@ -38,13 +39,13 @@ struct HighlightView: View { var headerView: some View { VStack { - Text("Highlights") - .font(Constants.Fonts.semibold24) - .foregroundStyle(Constants.Colors.black) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.top, 24) - .padding(.horizontal, 24) - + TopHeader( + title: "Highlights", + onProfileTap: { + showProfile = true + } + ) + .padding(.horizontal, 20) SearchView(title: "Search All Highlights", scope: .all) .padding(.horizontal, 20) .padding(.top, 12) @@ -153,6 +154,6 @@ struct HighlightSectionView: View { // MARK: - Preview #Preview { - HighlightView() + HighlightView(showProfile: .constant(false)) .environmentObject(HighlightsViewModel.shared) } diff --git a/score-ios/Views/ListViews/PastGamesView.swift b/score-ios/Views/ListViews/PastGamesView.swift index 6e855c1..4b8cb6b 100644 --- a/score-ios/Views/ListViews/PastGamesView.swift +++ b/score-ios/Views/ListViews/PastGamesView.swift @@ -12,6 +12,7 @@ struct PastGamesView: View { // State variables @StateObject private var vm = GamesViewModel.shared + @Binding var showProfile: Bool var body: some View { ZStack { @@ -19,7 +20,7 @@ struct PastGamesView: View { ScrollView(.vertical, showsIndicators: false) { ZStack { LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) { - CarouselView(games: vm.topPastGames, title: "Latest", + CarouselView(showProfile: $showProfile, games: vm.topPastGames, title: "Latest", cardView: { game in PastGameCard(game: game, viewModel: PastGameViewModel(game: game)) }, @@ -75,5 +76,5 @@ struct PastGamesView: View { } #Preview { - PastGamesView() + PastGamesView(showProfile: .constant(false)) } diff --git a/score-ios/Views/ListViews/UpcomingGamesView.swift b/score-ios/Views/ListViews/UpcomingGamesView.swift index b6061ac..91e32d4 100644 --- a/score-ios/Views/ListViews/UpcomingGamesView.swift +++ b/score-ios/Views/ListViews/UpcomingGamesView.swift @@ -11,6 +11,7 @@ struct UpcomingGamesView: View { // State variables var paddingMain: CGFloat = 20 + @Binding var showProfile: Bool @State private var selectedCardIndex: Int = 0 @StateObject private var vm = GamesViewModel.shared @@ -22,7 +23,7 @@ struct UpcomingGamesView: View { ZStack { LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) { if !vm.topUpcomingGames.isEmpty { - CarouselView(games: vm.topUpcomingGames, title: "Upcoming", + CarouselView(showProfile: $showProfile, games: vm.topUpcomingGames, title: "Upcoming", cardView: { game in UpcomingGameCard(game: game) }, @@ -78,5 +79,5 @@ struct UpcomingGamesView: View { } #Preview { - UpcomingGamesView() + UpcomingGamesView(showProfile: .constant(false)) } diff --git a/score-ios/Views/MainViews/MainTabView.swift b/score-ios/Views/MainViews/MainTabView.swift index adbb84f..10be4c2 100644 --- a/score-ios/Views/MainViews/MainTabView.swift +++ b/score-ios/Views/MainViews/MainTabView.swift @@ -12,6 +12,7 @@ struct MainTabView: View { // MARK: Properties @Binding var selectedTab: MainTab + @State private var showProfile = false @StateObject private var gamesViewModel = GamesViewModel.shared @StateObject private var highlightViewModel = HighlightsViewModel.shared @@ -19,16 +20,16 @@ struct MainTabView: View { NavigationStack { ZStack(alignment: .bottom) { switch selectedTab { - case .schedule: - UpcomingGamesView() - .environmentObject(gamesViewModel) - case .highlights: - HighlightView() - .environmentObject(highlightViewModel) - case .scores: - PastGamesView() - .environmentObject(gamesViewModel) - } + case .schedule: + UpcomingGamesView(showProfile: $showProfile) + .environmentObject(gamesViewModel) + case .highlights: + HighlightView(showProfile: $showProfile) + .environmentObject(highlightViewModel) + case .scores: + PastGamesView(showProfile: $showProfile) + .environmentObject(gamesViewModel) + } HStack { ForEach(MainTab.allCases) { tab in @@ -50,6 +51,9 @@ struct MainTabView: View { ) } + .navigationDestination(isPresented: $showProfile) { + ProfileView() + } .ignoresSafeArea(edges: .bottom) .background(Color.white) .toolbar(.hidden) diff --git a/score-ios/Views/MainViews/ProfileView.swift b/score-ios/Views/MainViews/ProfileView.swift new file mode 100644 index 0000000..47a6db7 --- /dev/null +++ b/score-ios/Views/MainViews/ProfileView.swift @@ -0,0 +1,340 @@ +// +// ProfileView.swift +// score-ios +// +// Created by Duru Alaylı on 2/19/26. +// + +import SwiftUI + +struct ProfileView: View { + + // MARK: - Properties + @StateObject var profileViewModel = ProfileViewModel.shared + @Environment(\.dismiss) private var dismiss + @State private var isSheet = false + @State private var isEdit = false + @State private var editedName: String = "" + @State private var editedUsername: String = "" + @State private var editedImage: String = "" + + // MARK: - UI + var body: some View { + ScrollView { + VStack (spacing: 24) { + header + profileNameSection + bookmarksSection + likedGamesSection + } + } + .navigationDestination(isPresented: $isEdit) { + editProfileView + } + } + + private var header: some View { + HStack (spacing: 8) { + Text ("Profile") + .font(Constants.Fonts.Header.h1) + .foregroundStyle(Constants.Colors.primary_gray) + Spacer() + HStack { + Button(action: { + // TODO: notifications button + }) { + Image ("notifications") + .resizable() + .frame(width: 27,height: 27) + } + Button(action: { + // TODO: three lines button + }) { + Image ("dehaze") + .resizable() + .frame(width: 24,height: 24) + } + } + } + .padding(.horizontal,24) + } + + private var profileNameSection: some View { + HStack (spacing: 18){ + Image (profileViewModel.user.profileImage) + .resizable() + .frame(width: 124,height: 124) + + VStack (alignment: .leading){ + Text (profileViewModel.user.name) + .font(Constants.Fonts.semibold18) + .foregroundStyle(Constants.Colors.primary_gray) + Text (profileViewModel.user.username) + .font(Constants.Fonts.medium18) + .foregroundStyle(Constants.Colors.primary_gray) + Button(action: { + isEdit = true + }) { + Text ("Edit profile") + .font(Constants.Fonts.Body.normal) + .foregroundStyle(Constants.Colors.primary_gray) + .padding(.horizontal,12) + .padding(.vertical,4) + .background( + RoundedRectangle(cornerRadius: 100) + .stroke(Constants.Colors.gray_border, lineWidth: 1) + ) + } + } + Spacer() + } + .padding(.horizontal, 24) + } + + private var bookmarksSection: some View { + VStack (spacing: 16){ + HStack { + Text ("Bookmarks") + .font(Constants.Fonts.Header.h2) + .foregroundStyle(Constants.Colors.primary_gray) + Spacer() + Text ("4 Results") + .font(Constants.Fonts.Body.normal) + .foregroundStyle(Constants.Colors.gray_icons) + Button(action: { + // TODO: all bookmarks button + }) { + Image ("Arrowhead") + .resizable() + .frame(width: 20,height: 20) + } + } + ScrollView(.horizontal) { + LazyHStack (spacing: 16){ + bookmarkGameCard + bookmarkGameCard + bookmarkGameCard + bookmarkGameCard + bookmarkGameCard + } + } + } + .padding(.horizontal,24) + } + + private var likedGamesSection: some View { + VStack (spacing: 16){ + HStack { + Text ("Games You Might Like") + .font(Constants.Fonts.Header.h2) + .foregroundStyle(Constants.Colors.primary_gray) + Spacer() + Text ("4 Results") + .font(Constants.Fonts.Body.normal) + .foregroundStyle(Constants.Colors.gray_icons) + Button(action: { + // TODO: all games like button + }) { + Image ("Arrowhead") + .resizable() + .frame(width: 20,height: 20) + } + } + ScrollView(.horizontal) { + LazyHStack (spacing: 16){ + bookmarkGameCard + bookmarkGameCard + bookmarkGameCard + bookmarkGameCard + bookmarkGameCard + } + } + } + .padding(.horizontal, 24) + } + + private var bookmarkGameCard: some View { + Button(action: { + // TODO: settings button + }) { + VStack (spacing: 8){ + Image ("BookmarkGame") + .resizable() + .frame(height: 116) + VStack { + HStack { + Text ("Cornell vs. Columbia") + .font(Constants.Fonts.Header.h2) + .foregroundStyle(Constants.Colors.black) + Spacer() + } + HStack { + Image ("Soccer-g") + .resizable() + .frame(width: 24, height: 24) + Image ("Men's-g") + .resizable() + .frame(width: 19, height: 19) + Spacer() + Text ("11/09") + .font(Constants.Fonts.Label.normal) + .foregroundStyle(Constants.Colors.gray_icons) + + } + .padding(.bottom, 8) + } + .padding(.horizontal, 16) + } + .background(Constants.Colors.white) + .clipShape(RoundedRectangle(cornerRadius: 12)) + .background( + RoundedRectangle(cornerRadius: 12) + .stroke(Constants.Colors.gray_border, lineWidth: 1) + .shadow(radius: 5) + ) + .padding(.vertical, 10) + } + } + + + private var editProfileView: some View { + VStack (spacing: 48){ + Divider() + VStack (spacing: 16){ + Image (profileViewModel.user.profileImage) + .resizable() + .frame(width: 120,height: 120) + Button(action: { + isSheet.toggle() + }) { + Text ("Edit photo") + .font(Constants.Fonts.semibold18) + .foregroundStyle(Constants.Colors.primary_red) + } + .sheet(isPresented: $isSheet) { + imageChooserView + .presentationDetents([.fraction(0.75)]) + .presentationBackground(.white) + } + } + VStack (spacing: 24) { + HStack { + Text ("Name") + .font(Constants.Fonts.semibold18) + .foregroundStyle(Constants.Colors.primary_gray) + Spacer() + TextField (profileViewModel.user.name, text: $editedName) + .multilineTextAlignment(.trailing) + .font(Constants.Fonts.Header.h2) + .foregroundStyle(Constants.Colors.primary_gray) + } + HStack { + Text ("Username") + .font(Constants.Fonts.semibold18) + .foregroundStyle(Constants.Colors.primary_gray) + Spacer() + TextField (profileViewModel.user.username, text: $editedUsername) + .multilineTextAlignment(.trailing) + .font(Constants.Fonts.Header.h2) + .foregroundStyle(Constants.Colors.primary_gray) + } + } + .padding(.horizontal, 24) + Spacer() + Button(action: { + profileViewModel.saveUser( + name: editedName, + username: editedUsername, + profileImage: editedImage + ) + isEdit = false + }) { + Text ("Save") + .font(Constants.Fonts.Header.h1) + .foregroundStyle(Constants.Colors.white) + .padding(.horizontal,40) + .padding(.vertical,8) + .background( + RoundedRectangle(cornerRadius: 50) + .fill(Constants.Colors.primary_red) + ) + } + .onAppear { + editedName = profileViewModel.user.name + editedUsername = profileViewModel.user.username + editedImage = profileViewModel.user.profileImage + } + } + .navigationTitle("Edit Profile") + .navigationBarTitleDisplayMode(.inline) + } + + private var imageChooserView: some View { + VStack (spacing: 12){ + let profile_picture = (0...11).map { "profile\($0)" } + + let columns = Array(repeating: GridItem(.flexible(), spacing: 16), count: 3) + HStack { + Button(action: { + isSheet.toggle() + }) { + Image ("cross") + .resizable() + .frame(width: 13,height: 13) + .padding(.horizontal,15) + .padding(.vertical,5.6) + .background( + Circle() + .fill(Constants.Colors.gray_liner) + ) + } + Spacer() + } + LazyVGrid (columns: columns, spacing: 14) { + ForEach(profile_picture, id: \.self) { profile in + Button(action: { + editedImage = profile + }) {ZStack { + Image (profile) + .resizable() + .frame(width: 100,height: 100) + .opacity(editedImage == profile ? 0.5 : 1) + if editedImage == profile { + Image ("check") + .resizable() + .frame(width: 32,height: 24) + } + } + } + } + } + Button(action: { + profileViewModel.saveUser( + name: editedName, + username: editedUsername, + profileImage: editedImage + ) + isSheet.toggle() + }) { + Text ("Save") + .font(Constants.Fonts.Header.h1) + .foregroundStyle(Constants.Colors.white) + .padding(.horizontal,40) + .padding(.vertical,8) + .background( + RoundedRectangle(cornerRadius: 50) + .fill(editedImage != profileViewModel.user.profileImage ? Constants.Colors.primary_red : Constants.Colors.gray_liner) + ) + } + } + .padding(.horizontal,16) + .onAppear { + editedImage = profileViewModel.user.profileImage + } + } +} + +// MARK: - Preview +#Preview { + ProfileView() +}