diff --git a/AlloVictor.xcodeproj/project.pbxproj b/AlloVictor.xcodeproj/project.pbxproj index 9f06f59..d34a208 100644 --- a/AlloVictor.xcodeproj/project.pbxproj +++ b/AlloVictor.xcodeproj/project.pbxproj @@ -8,21 +8,113 @@ /* Begin PBXBuildFile section */ 524FA6002BCACDCE00133747 /* AlloVictorApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA5FF2BCACDCE00133747 /* AlloVictorApp.swift */; }; - 524FA6022BCACDCE00133747 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6012BCACDCE00133747 /* ContentView.swift */; }; + 524FA6022BCACDCE00133747 /* OffersListScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6012BCACDCE00133747 /* OffersListScreen.swift */; }; 524FA6042BCACDCF00133747 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 524FA6032BCACDCF00133747 /* Assets.xcassets */; }; 524FA6072BCACDCF00133747 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 524FA6062BCACDCF00133747 /* Preview Assets.xcassets */; }; 524FA60F2BCACF0500133747 /* Screen1.json in Resources */ = {isa = PBXBuildFile; fileRef = 524FA60E2BCACF0500133747 /* Screen1.json */; }; 524FA6112BCACF3A00133747 /* Screen2.json in Resources */ = {isa = PBXBuildFile; fileRef = 524FA6102BCACF3A00133747 /* Screen2.json */; }; + 524FA61B2BCAD04B00133747 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA61A2BCAD04B00133747 /* Constants.swift */; }; + 524FA61D2BCAD0F100133747 /* OfferListResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA61C2BCAD0F100133747 /* OfferListResponseDTO.swift */; }; + 524FA61F2BCAD0FD00133747 /* OfferDetailsResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA61E2BCAD0FD00133747 /* OfferDetailsResponseDTO.swift */; }; + 524FA6212BCAD22D00133747 /* HTTPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6202BCAD22D00133747 /* HTTPClient.swift */; }; + 524FA6232BCAD29000133747 /* AlloVictorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6222BCAD29000133747 /* AlloVictorViewModel.swift */; }; + 524FA6252BCAD58400133747 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6242BCAD58400133747 /* AppState.swift */; }; + 524FA6272BCAE1C500133747 /* OfferListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6262BCAE1C500133747 /* OfferListView.swift */; }; + 524FA62A2BCAEC0B00133747 /* CachedAsyncImage in Frameworks */ = {isa = PBXBuildFile; productRef = 524FA6292BCAEC0B00133747 /* CachedAsyncImage */; }; + 524FA62C2BCAF2CF00133747 /* AlloFlashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA62B2BCAF2CF00133747 /* AlloFlashView.swift */; }; + 524FA63D2BCBF4C300133747 /* tt_chocolates_light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 524FA62F2BCBF4C300133747 /* tt_chocolates_light.otf */; }; + 524FA63E2BCBF4C300133747 /* tt_chocolates_extralight.otf in Resources */ = {isa = PBXBuildFile; fileRef = 524FA6302BCBF4C300133747 /* tt_chocolates_extralight.otf */; }; + 524FA63F2BCBF4C300133747 /* tt_chocolates_regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 524FA6312BCBF4C300133747 /* tt_chocolates_regular.otf */; }; + 524FA6412BCBF4C300133747 /* tt_chocolates_demibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 524FA6332BCBF4C300133747 /* tt_chocolates_demibold.otf */; }; + 524FA6442BCBF4C300133747 /* tt_chocolates_extrabold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 524FA6362BCBF4C300133747 /* tt_chocolates_extrabold.otf */; }; + 524FA6452BCBF4C300133747 /* tt_chocolates_bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 524FA6372BCBF4C300133747 /* tt_chocolates_bold.otf */; }; + 524FA6492BCBF4C300133747 /* tt_chocolates_medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 524FA63B2BCBF4C300133747 /* tt_chocolates_medium.otf */; }; + 524FA64D2BCBFA3000133747 /* TextModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA64C2BCBFA3000133747 /* TextModifier.swift */; }; + 524FA64F2BCC0AA100133747 /* OfferDetailsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA64E2BCC0AA100133747 /* OfferDetailsScreen.swift */; }; + 524FA6512BCC115B00133747 /* OffererUserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6502BCC115B00133747 /* OffererUserView.swift */; }; + 524FA6532BCC326500133747 /* ShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6522BCC326500133747 /* ShareView.swift */; }; + 524FA6552BCC339A00133747 /* OfferDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6542BCC339A00133747 /* OfferDetailsView.swift */; }; + 524FA6572BCC34E900133747 /* OfferSocialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524FA6562BCC34E800133747 /* OfferSocialView.swift */; }; + 525ED7342BCD257C00FE6109 /* AvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525ED7332BCD257C00FE6109 /* AvatarView.swift */; }; + 52B222022BD1492600B55575 /* ShowFullPictureScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222012BD1492600B55575 /* ShowFullPictureScreen.swift */; }; + 52B222112BD1631600B55575 /* NotFoundScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222102BD1631600B55575 /* NotFoundScreen.swift */; }; + 52B222132BD16DC800B55575 /* OfferDetailsBodyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222122BD16DC800B55575 /* OfferDetailsBodyView.swift */; }; + 52B222172BD1737500B55575 /* Extension+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222162BD1737500B55575 /* Extension+View.swift */; }; + 52B222192BD173FF00B55575 /* OffererUserRatingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222182BD173FF00B55575 /* OffererUserRatingView.swift */; }; + 52B2221B2BD1749E00B55575 /* OffererUserInfos.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B2221A2BD1749E00B55575 /* OffererUserInfos.swift */; }; + 52B2221D2BD1756100B55575 /* OffererUserProStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B2221C2BD1756100B55575 /* OffererUserProStatusView.swift */; }; + 52B2221F2BD175E300B55575 /* OffererUserGallery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B2221E2BD175E300B55575 /* OffererUserGallery.swift */; }; + 52B222232BD1782700B55575 /* OfferHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222222BD1782700B55575 /* OfferHeaderView.swift */; }; + 52B222252BD178D000B55575 /* OfferBodyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222242BD178D000B55575 /* OfferBodyView.swift */; }; + 52B222292BD17A6300B55575 /* Offer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222282BD17A6300B55575 /* Offer.swift */; }; + 52B2222B2BD17A7F00B55575 /* Relationships.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B2222A2BD17A7F00B55575 /* Relationships.swift */; }; + 52B2222D2BD17A9100B55575 /* Leaseholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B2222C2BD17A9100B55575 /* Leaseholder.swift */; }; + 52B2222F2BD17AA100B55575 /* Social.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B2222E2BD17AA100B55575 /* Social.swift */; }; + 52B222312BD17ACB00B55575 /* OfferPicture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222302BD17ACB00B55575 /* OfferPicture.swift */; }; + 52B222332BD17ADC00B55575 /* OfferPictureUrls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222322BD17ADC00B55575 /* OfferPictureUrls.swift */; }; + 52B222352BD17AEB00B55575 /* OfferersUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222342BD17AEB00B55575 /* OfferersUser.swift */; }; + 52B222372BD17B0100B55575 /* OfferersUserMeta.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222362BD17B0100B55575 /* OfferersUserMeta.swift */; }; + 52B222392BD17B1200B55575 /* GalleryPicture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222382BD17B1200B55575 /* GalleryPicture.swift */; }; + 52B2223B2BD17BD100B55575 /* OfferDetailsAwnserCountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B2223A2BD17BD100B55575 /* OfferDetailsAwnserCountView.swift */; }; + 52B2223F2BD17D5800B55575 /* OfferDetailsGalleryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B2223E2BD17D5800B55575 /* OfferDetailsGalleryView.swift */; }; + 52B222412BD17DF100B55575 /* OfferDetailsLeaseholderInfosView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222402BD17DF100B55575 /* OfferDetailsLeaseholderInfosView.swift */; }; + 52B222432BD1864100B55575 /* OfferDetailsMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B222422BD1864100B55575 /* OfferDetailsMapView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 524FA5FC2BCACDCE00133747 /* AlloVictor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AlloVictor.app; sourceTree = BUILT_PRODUCTS_DIR; }; 524FA5FF2BCACDCE00133747 /* AlloVictorApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlloVictorApp.swift; sourceTree = ""; }; - 524FA6012BCACDCE00133747 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 524FA6012BCACDCE00133747 /* OffersListScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OffersListScreen.swift; sourceTree = ""; }; 524FA6032BCACDCF00133747 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 524FA6062BCACDCF00133747 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 524FA60E2BCACF0500133747 /* Screen1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Screen1.json; sourceTree = ""; }; 524FA6102BCACF3A00133747 /* Screen2.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Screen2.json; sourceTree = ""; }; + 524FA61A2BCAD04B00133747 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; + 524FA61C2BCAD0F100133747 /* OfferListResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferListResponseDTO.swift; sourceTree = ""; }; + 524FA61E2BCAD0FD00133747 /* OfferDetailsResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferDetailsResponseDTO.swift; sourceTree = ""; }; + 524FA6202BCAD22D00133747 /* HTTPClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPClient.swift; sourceTree = ""; }; + 524FA6222BCAD29000133747 /* AlloVictorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlloVictorViewModel.swift; sourceTree = ""; }; + 524FA6242BCAD58400133747 /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; }; + 524FA6262BCAE1C500133747 /* OfferListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferListView.swift; sourceTree = ""; }; + 524FA62B2BCAF2CF00133747 /* AlloFlashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlloFlashView.swift; sourceTree = ""; }; + 524FA62F2BCBF4C300133747 /* tt_chocolates_light.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = tt_chocolates_light.otf; sourceTree = ""; }; + 524FA6302BCBF4C300133747 /* tt_chocolates_extralight.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = tt_chocolates_extralight.otf; sourceTree = ""; }; + 524FA6312BCBF4C300133747 /* tt_chocolates_regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = tt_chocolates_regular.otf; sourceTree = ""; }; + 524FA6332BCBF4C300133747 /* tt_chocolates_demibold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = tt_chocolates_demibold.otf; sourceTree = ""; }; + 524FA6362BCBF4C300133747 /* tt_chocolates_extrabold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = tt_chocolates_extrabold.otf; sourceTree = ""; }; + 524FA6372BCBF4C300133747 /* tt_chocolates_bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = tt_chocolates_bold.otf; sourceTree = ""; }; + 524FA63B2BCBF4C300133747 /* tt_chocolates_medium.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = tt_chocolates_medium.otf; sourceTree = ""; }; + 524FA64A2BCBF78200133747 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 524FA64C2BCBFA3000133747 /* TextModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextModifier.swift; sourceTree = ""; }; + 524FA64E2BCC0AA100133747 /* OfferDetailsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferDetailsScreen.swift; sourceTree = ""; }; + 524FA6502BCC115B00133747 /* OffererUserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OffererUserView.swift; sourceTree = ""; }; + 524FA6522BCC326500133747 /* ShareView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareView.swift; sourceTree = ""; }; + 524FA6542BCC339A00133747 /* OfferDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferDetailsView.swift; sourceTree = ""; }; + 524FA6562BCC34E800133747 /* OfferSocialView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferSocialView.swift; sourceTree = ""; }; + 525ED7332BCD257C00FE6109 /* AvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarView.swift; sourceTree = ""; }; + 52B222012BD1492600B55575 /* ShowFullPictureScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowFullPictureScreen.swift; sourceTree = ""; }; + 52B222102BD1631600B55575 /* NotFoundScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotFoundScreen.swift; sourceTree = ""; }; + 52B222122BD16DC800B55575 /* OfferDetailsBodyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferDetailsBodyView.swift; sourceTree = ""; }; + 52B222162BD1737500B55575 /* Extension+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+View.swift"; sourceTree = ""; }; + 52B222182BD173FF00B55575 /* OffererUserRatingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OffererUserRatingView.swift; sourceTree = ""; }; + 52B2221A2BD1749E00B55575 /* OffererUserInfos.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OffererUserInfos.swift; sourceTree = ""; }; + 52B2221C2BD1756100B55575 /* OffererUserProStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OffererUserProStatusView.swift; sourceTree = ""; }; + 52B2221E2BD175E300B55575 /* OffererUserGallery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OffererUserGallery.swift; sourceTree = ""; }; + 52B222222BD1782700B55575 /* OfferHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferHeaderView.swift; sourceTree = ""; }; + 52B222242BD178D000B55575 /* OfferBodyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferBodyView.swift; sourceTree = ""; }; + 52B222282BD17A6300B55575 /* Offer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Offer.swift; sourceTree = ""; }; + 52B2222A2BD17A7F00B55575 /* Relationships.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Relationships.swift; sourceTree = ""; }; + 52B2222C2BD17A9100B55575 /* Leaseholder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Leaseholder.swift; sourceTree = ""; }; + 52B2222E2BD17AA100B55575 /* Social.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Social.swift; sourceTree = ""; }; + 52B222302BD17ACB00B55575 /* OfferPicture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferPicture.swift; sourceTree = ""; }; + 52B222322BD17ADC00B55575 /* OfferPictureUrls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferPictureUrls.swift; sourceTree = ""; }; + 52B222342BD17AEB00B55575 /* OfferersUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferersUser.swift; sourceTree = ""; }; + 52B222362BD17B0100B55575 /* OfferersUserMeta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferersUserMeta.swift; sourceTree = ""; }; + 52B222382BD17B1200B55575 /* GalleryPicture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryPicture.swift; sourceTree = ""; }; + 52B2223A2BD17BD100B55575 /* OfferDetailsAwnserCountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferDetailsAwnserCountView.swift; sourceTree = ""; }; + 52B2223E2BD17D5800B55575 /* OfferDetailsGalleryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferDetailsGalleryView.swift; sourceTree = ""; }; + 52B222402BD17DF100B55575 /* OfferDetailsLeaseholderInfosView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferDetailsLeaseholderInfosView.swift; sourceTree = ""; }; + 52B222422BD1864100B55575 /* OfferDetailsMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfferDetailsMapView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -30,6 +122,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 524FA62A2BCAEC0B00133747 /* CachedAsyncImage in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -55,9 +148,17 @@ 524FA5FE2BCACDCE00133747 /* AlloVictor */ = { isa = PBXGroup; children = ( + 524FA64A2BCBF78200133747 /* Info.plist */, + 52B222152BD1735F00B55575 /* Extensions */, + 52B222272BD17A5000B55575 /* Models */, + 524FA6192BCAD03600133747 /* DTO */, + 524FA6182BCAD02E00133747 /* Screens */, + 524FA6172BCAD02600133747 /* Utils */, + 524FA6162BCAD01E00133747 /* Views */, + 524FA6152BCAD01700133747 /* ViewModels */, 524FA60D2BCACE9400133747 /* Resources */, + 524FA6242BCAD58400133747 /* AppState.swift */, 524FA5FF2BCACDCE00133747 /* AlloVictorApp.swift */, - 524FA6012BCACDCE00133747 /* ContentView.swift */, 524FA6032BCACDCF00133747 /* Assets.xcassets */, 524FA6052BCACDCF00133747 /* Preview Content */, ); @@ -75,12 +176,154 @@ 524FA60D2BCACE9400133747 /* Resources */ = { isa = PBXGroup; children = ( + 524FA62D2BCBF4AD00133747 /* Fonts */, 524FA60E2BCACF0500133747 /* Screen1.json */, 524FA6102BCACF3A00133747 /* Screen2.json */, ); path = Resources; sourceTree = ""; }; + 524FA6152BCAD01700133747 /* ViewModels */ = { + isa = PBXGroup; + children = ( + 524FA6222BCAD29000133747 /* AlloVictorViewModel.swift */, + ); + path = ViewModels; + sourceTree = ""; + }; + 524FA6162BCAD01E00133747 /* Views */ = { + isa = PBXGroup; + children = ( + 52B222142BD16E5200B55575 /* Components */, + 524FA64B2BCBFA1900133747 /* Modifiers */, + 524FA62B2BCAF2CF00133747 /* AlloFlashView.swift */, + 524FA6262BCAE1C500133747 /* OfferListView.swift */, + 524FA6542BCC339A00133747 /* OfferDetailsView.swift */, + 524FA6502BCC115B00133747 /* OffererUserView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 524FA6172BCAD02600133747 /* Utils */ = { + isa = PBXGroup; + children = ( + 524FA61A2BCAD04B00133747 /* Constants.swift */, + 524FA6202BCAD22D00133747 /* HTTPClient.swift */, + ); + path = Utils; + sourceTree = ""; + }; + 524FA6182BCAD02E00133747 /* Screens */ = { + isa = PBXGroup; + children = ( + 52B222102BD1631600B55575 /* NotFoundScreen.swift */, + 524FA64E2BCC0AA100133747 /* OfferDetailsScreen.swift */, + 524FA6012BCACDCE00133747 /* OffersListScreen.swift */, + 52B222012BD1492600B55575 /* ShowFullPictureScreen.swift */, + ); + path = Screens; + sourceTree = ""; + }; + 524FA6192BCAD03600133747 /* DTO */ = { + isa = PBXGroup; + children = ( + 524FA61E2BCAD0FD00133747 /* OfferDetailsResponseDTO.swift */, + 524FA61C2BCAD0F100133747 /* OfferListResponseDTO.swift */, + ); + path = DTO; + sourceTree = ""; + }; + 524FA62D2BCBF4AD00133747 /* Fonts */ = { + isa = PBXGroup; + children = ( + 524FA6372BCBF4C300133747 /* tt_chocolates_bold.otf */, + 524FA6332BCBF4C300133747 /* tt_chocolates_demibold.otf */, + 524FA6362BCBF4C300133747 /* tt_chocolates_extrabold.otf */, + 524FA6302BCBF4C300133747 /* tt_chocolates_extralight.otf */, + 524FA62F2BCBF4C300133747 /* tt_chocolates_light.otf */, + 524FA63B2BCBF4C300133747 /* tt_chocolates_medium.otf */, + 524FA6312BCBF4C300133747 /* tt_chocolates_regular.otf */, + ); + path = Fonts; + sourceTree = ""; + }; + 524FA64B2BCBFA1900133747 /* Modifiers */ = { + isa = PBXGroup; + children = ( + 524FA64C2BCBFA3000133747 /* TextModifier.swift */, + ); + path = Modifiers; + sourceTree = ""; + }; + 52B222142BD16E5200B55575 /* Components */ = { + isa = PBXGroup; + children = ( + 52B222212BD1780F00B55575 /* Offer */, + 52B222262BD17A1A00B55575 /* OfferDetails */, + 52B222202BD1766E00B55575 /* OffererUser */, + 525ED7332BCD257C00FE6109 /* AvatarView.swift */, + 524FA6522BCC326500133747 /* ShareView.swift */, + ); + path = Components; + sourceTree = ""; + }; + 52B222152BD1735F00B55575 /* Extensions */ = { + isa = PBXGroup; + children = ( + 52B222162BD1737500B55575 /* Extension+View.swift */, + ); + path = Extensions; + sourceTree = ""; + }; + 52B222202BD1766E00B55575 /* OffererUser */ = { + isa = PBXGroup; + children = ( + 52B2221E2BD175E300B55575 /* OffererUserGallery.swift */, + 52B2221A2BD1749E00B55575 /* OffererUserInfos.swift */, + 52B2221C2BD1756100B55575 /* OffererUserProStatusView.swift */, + 52B222182BD173FF00B55575 /* OffererUserRatingView.swift */, + ); + path = OffererUser; + sourceTree = ""; + }; + 52B222212BD1780F00B55575 /* Offer */ = { + isa = PBXGroup; + children = ( + 52B222242BD178D000B55575 /* OfferBodyView.swift */, + 52B222222BD1782700B55575 /* OfferHeaderView.swift */, + 524FA6562BCC34E800133747 /* OfferSocialView.swift */, + ); + path = Offer; + sourceTree = ""; + }; + 52B222262BD17A1A00B55575 /* OfferDetails */ = { + isa = PBXGroup; + children = ( + 52B222122BD16DC800B55575 /* OfferDetailsBodyView.swift */, + 52B2223A2BD17BD100B55575 /* OfferDetailsAwnserCountView.swift */, + 52B2223E2BD17D5800B55575 /* OfferDetailsGalleryView.swift */, + 52B222402BD17DF100B55575 /* OfferDetailsLeaseholderInfosView.swift */, + 52B222422BD1864100B55575 /* OfferDetailsMapView.swift */, + ); + path = OfferDetails; + sourceTree = ""; + }; + 52B222272BD17A5000B55575 /* Models */ = { + isa = PBXGroup; + children = ( + 52B222382BD17B1200B55575 /* GalleryPicture.swift */, + 52B2222C2BD17A9100B55575 /* Leaseholder.swift */, + 52B222282BD17A6300B55575 /* Offer.swift */, + 52B222342BD17AEB00B55575 /* OfferersUser.swift */, + 52B222362BD17B0100B55575 /* OfferersUserMeta.swift */, + 52B222302BD17ACB00B55575 /* OfferPicture.swift */, + 52B222322BD17ADC00B55575 /* OfferPictureUrls.swift */, + 52B2222A2BD17A7F00B55575 /* Relationships.swift */, + 52B2222E2BD17AA100B55575 /* Social.swift */, + ); + path = Models; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -97,6 +340,9 @@ dependencies = ( ); name = AlloVictor; + packageProductDependencies = ( + 524FA6292BCAEC0B00133747 /* CachedAsyncImage */, + ); productName = AlloVictor; productReference = 524FA5FC2BCACDCE00133747 /* AlloVictor.app */; productType = "com.apple.product-type.application"; @@ -125,6 +371,9 @@ Base, ); mainGroup = 524FA5F32BCACDCE00133747; + packageReferences = ( + 524FA6282BCAEC0B00133747 /* XCRemoteSwiftPackageReference "swiftui-cached-async-image" */, + ); productRefGroup = 524FA5FD2BCACDCE00133747 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -139,8 +388,15 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 524FA63E2BCBF4C300133747 /* tt_chocolates_extralight.otf in Resources */, 524FA60F2BCACF0500133747 /* Screen1.json in Resources */, + 524FA6412BCBF4C300133747 /* tt_chocolates_demibold.otf in Resources */, 524FA6072BCACDCF00133747 /* Preview Assets.xcassets in Resources */, + 524FA6452BCBF4C300133747 /* tt_chocolates_bold.otf in Resources */, + 524FA6492BCBF4C300133747 /* tt_chocolates_medium.otf in Resources */, + 524FA6442BCBF4C300133747 /* tt_chocolates_extrabold.otf in Resources */, + 524FA63D2BCBF4C300133747 /* tt_chocolates_light.otf in Resources */, + 524FA63F2BCBF4C300133747 /* tt_chocolates_regular.otf in Resources */, 524FA6112BCACF3A00133747 /* Screen2.json in Resources */, 524FA6042BCACDCF00133747 /* Assets.xcassets in Resources */, ); @@ -153,8 +409,46 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 524FA6022BCACDCE00133747 /* ContentView.swift in Sources */, + 52B222252BD178D000B55575 /* OfferBodyView.swift in Sources */, + 52B222332BD17ADC00B55575 /* OfferPictureUrls.swift in Sources */, + 524FA6022BCACDCE00133747 /* OffersListScreen.swift in Sources */, + 52B222172BD1737500B55575 /* Extension+View.swift in Sources */, + 524FA61F2BCAD0FD00133747 /* OfferDetailsResponseDTO.swift in Sources */, + 52B222432BD1864100B55575 /* OfferDetailsMapView.swift in Sources */, + 52B2221D2BD1756100B55575 /* OffererUserProStatusView.swift in Sources */, + 52B2222B2BD17A7F00B55575 /* Relationships.swift in Sources */, + 52B2221B2BD1749E00B55575 /* OffererUserInfos.swift in Sources */, + 524FA6212BCAD22D00133747 /* HTTPClient.swift in Sources */, + 524FA64F2BCC0AA100133747 /* OfferDetailsScreen.swift in Sources */, + 524FA6272BCAE1C500133747 /* OfferListView.swift in Sources */, + 524FA6252BCAD58400133747 /* AppState.swift in Sources */, + 524FA6512BCC115B00133747 /* OffererUserView.swift in Sources */, + 52B2221F2BD175E300B55575 /* OffererUserGallery.swift in Sources */, + 52B222412BD17DF100B55575 /* OfferDetailsLeaseholderInfosView.swift in Sources */, 524FA6002BCACDCE00133747 /* AlloVictorApp.swift in Sources */, + 524FA6572BCC34E900133747 /* OfferSocialView.swift in Sources */, + 52B2222F2BD17AA100B55575 /* Social.swift in Sources */, + 524FA64D2BCBFA3000133747 /* TextModifier.swift in Sources */, + 52B222352BD17AEB00B55575 /* OfferersUser.swift in Sources */, + 524FA6552BCC339A00133747 /* OfferDetailsView.swift in Sources */, + 52B222192BD173FF00B55575 /* OffererUserRatingView.swift in Sources */, + 52B222392BD17B1200B55575 /* GalleryPicture.swift in Sources */, + 52B2222D2BD17A9100B55575 /* Leaseholder.swift in Sources */, + 52B222232BD1782700B55575 /* OfferHeaderView.swift in Sources */, + 524FA61D2BCAD0F100133747 /* OfferListResponseDTO.swift in Sources */, + 52B2223F2BD17D5800B55575 /* OfferDetailsGalleryView.swift in Sources */, + 52B222132BD16DC800B55575 /* OfferDetailsBodyView.swift in Sources */, + 524FA6532BCC326500133747 /* ShareView.swift in Sources */, + 524FA62C2BCAF2CF00133747 /* AlloFlashView.swift in Sources */, + 52B222292BD17A6300B55575 /* Offer.swift in Sources */, + 52B222022BD1492600B55575 /* ShowFullPictureScreen.swift in Sources */, + 52B222112BD1631600B55575 /* NotFoundScreen.swift in Sources */, + 524FA6232BCAD29000133747 /* AlloVictorViewModel.swift in Sources */, + 52B222372BD17B0100B55575 /* OfferersUserMeta.swift in Sources */, + 52B222312BD17ACB00B55575 /* OfferPicture.swift in Sources */, + 525ED7342BCD257C00FE6109 /* AvatarView.swift in Sources */, + 52B2223B2BD17BD100B55575 /* OfferDetailsAwnserCountView.swift in Sources */, + 524FA61B2BCAD04B00133747 /* Constants.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -291,11 +585,13 @@ DEVELOPMENT_TEAM = WVH3Y23X7X; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = AlloVictor/Info.plist; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UIUserInterfaceStyle = Light; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -320,11 +616,13 @@ DEVELOPMENT_TEAM = WVH3Y23X7X; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = AlloVictor/Info.plist; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UIUserInterfaceStyle = Light; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -360,6 +658,25 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 524FA6282BCAEC0B00133747 /* XCRemoteSwiftPackageReference "swiftui-cached-async-image" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/lorenzofiamingo/swiftui-cached-async-image"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.1.1; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 524FA6292BCAEC0B00133747 /* CachedAsyncImage */ = { + isa = XCSwiftPackageProductDependency; + package = 524FA6282BCAEC0B00133747 /* XCRemoteSwiftPackageReference "swiftui-cached-async-image" */; + productName = CachedAsyncImage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 524FA5F42BCACDCE00133747 /* Project object */; } diff --git a/AlloVictor.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/AlloVictor.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..c138097 --- /dev/null +++ b/AlloVictor.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,14 @@ +{ + "pins" : [ + { + "identity" : "swiftui-cached-async-image", + "kind" : "remoteSourceControl", + "location" : "https://github.com/lorenzofiamingo/swiftui-cached-async-image", + "state" : { + "revision" : "467a3d17479887943ab917a379e62bbaff60ac8a", + "version" : "2.1.1" + } + } + ], + "version" : 2 +} diff --git a/AlloVictor.xcodeproj/xcuserdata/bodinaudvictor.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/AlloVictor.xcodeproj/xcuserdata/bodinaudvictor.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..0d6b43a --- /dev/null +++ b/AlloVictor.xcodeproj/xcuserdata/bodinaudvictor.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/AlloVictor/AlloVictorApp.swift b/AlloVictor/AlloVictorApp.swift index 7f87f02..b890112 100644 --- a/AlloVictor/AlloVictorApp.swift +++ b/AlloVictor/AlloVictorApp.swift @@ -9,9 +9,36 @@ import SwiftUI @main struct AlloVictorApp: App { + + @StateObject private var viewModel = AlloVictorViewModel() + @StateObject private var appState = AppState() + + private func fetchOffers() async { + do { + try await viewModel.getDatas() + } catch { + print(error.localizedDescription) + } + } + var body: some Scene { WindowGroup { - ContentView() + NavigationStack(path: $appState.routes) { + OffersListScreen() + .navigationDestination(for: Route.self) { route in + switch route { + case .offers: + OffersListScreen() + case .detail(let offer): + OfferDetailsScreen(offerDetails: offer) + } + } + } + .task { + await fetchOffers() + } + .environmentObject(viewModel) + .environmentObject(appState) } } } diff --git a/AlloVictor/AppState.swift b/AlloVictor/AppState.swift new file mode 100644 index 0000000..ad4f033 --- /dev/null +++ b/AlloVictor/AppState.swift @@ -0,0 +1,17 @@ +// +// AppState.swift +// AlloVictor +// +// Created by Bodinaud Victor on 13/04/2024. +// + +import Foundation + +enum Route: Hashable { + case offers + case detail(Offer?) +} + +class AppState: ObservableObject { + @Published var routes: [Route] = [] +} diff --git a/AlloVictor/Assets.xcassets/AppIcon.appiconset/Contents.json b/AlloVictor/Assets.xcassets/AppIcon.appiconset/Contents.json index 13613e3..b3f44eb 100644 --- a/AlloVictor/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/AlloVictor/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,6 +1,7 @@ { "images" : [ { + "filename" : "Icon.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" diff --git a/AlloVictor/Assets.xcassets/AppIcon.appiconset/icon.png b/AlloVictor/Assets.xcassets/AppIcon.appiconset/icon.png new file mode 100644 index 0000000..2ec51e9 Binary files /dev/null and b/AlloVictor/Assets.xcassets/AppIcon.appiconset/icon.png differ diff --git a/AlloVictor/Assets.xcassets/Colors/Contents.json b/AlloVictor/Assets.xcassets/Colors/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/AlloVictor/Assets.xcassets/Colors/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVictor/Assets.xcassets/Colors/grape30.colorset/Contents.json b/AlloVictor/Assets.xcassets/Colors/grape30.colorset/Contents.json new file mode 100644 index 0000000..5d718c9 --- /dev/null +++ b/AlloVictor/Assets.xcassets/Colors/grape30.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0xF3", + "green" : "0xCF", + "red" : "0xE6" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0xF3", + "green" : "0xCF", + "red" : "0xE6" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVictor/Assets.xcassets/Colors/neutral20.colorset/Contents.json b/AlloVictor/Assets.xcassets/Colors/neutral20.colorset/Contents.json new file mode 100644 index 0000000..63baa93 --- /dev/null +++ b/AlloVictor/Assets.xcassets/Colors/neutral20.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.894", + "green" : "0.843", + "red" : "0.808" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.894", + "green" : "0.843", + "red" : "0.808" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVictor/Assets.xcassets/Colors/pillButtonColor.colorset/Contents.json b/AlloVictor/Assets.xcassets/Colors/pillButtonColor.colorset/Contents.json new file mode 100644 index 0000000..d30bafb --- /dev/null +++ b/AlloVictor/Assets.xcassets/Colors/pillButtonColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0x31", + "green" : "0x23", + "red" : "0x18" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0x31", + "green" : "0x23", + "red" : "0x18" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVictor/Assets.xcassets/Pictures/Avatar.imageset/Avatar.png b/AlloVictor/Assets.xcassets/Pictures/Avatar.imageset/Avatar.png new file mode 100644 index 0000000..da2a9fa Binary files /dev/null and b/AlloVictor/Assets.xcassets/Pictures/Avatar.imageset/Avatar.png differ diff --git a/AlloVictor/Assets.xcassets/Pictures/Avatar.imageset/Contents.json b/AlloVictor/Assets.xcassets/Pictures/Avatar.imageset/Contents.json new file mode 100644 index 0000000..04c9d3c --- /dev/null +++ b/AlloVictor/Assets.xcassets/Pictures/Avatar.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Avatar.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVictor/Assets.xcassets/Pictures/Contents.json b/AlloVictor/Assets.xcassets/Pictures/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/AlloVictor/Assets.xcassets/Pictures/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVictor/Assets.xcassets/Pictures/Icon.imageset/Contents.json b/AlloVictor/Assets.xcassets/Pictures/Icon.imageset/Contents.json new file mode 100644 index 0000000..1ffad00 --- /dev/null +++ b/AlloVictor/Assets.xcassets/Pictures/Icon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "icon.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVictor/Assets.xcassets/Pictures/Icon.imageset/icon.png b/AlloVictor/Assets.xcassets/Pictures/Icon.imageset/icon.png new file mode 100644 index 0000000..3a9902e Binary files /dev/null and b/AlloVictor/Assets.xcassets/Pictures/Icon.imageset/icon.png differ diff --git a/AlloVictor/Assets.xcassets/Pictures/SimpleLogo.imageset/Contents.json b/AlloVictor/Assets.xcassets/Pictures/SimpleLogo.imageset/Contents.json new file mode 100644 index 0000000..4b401e0 --- /dev/null +++ b/AlloVictor/Assets.xcassets/Pictures/SimpleLogo.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Logo Victor2.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVictor/Assets.xcassets/Pictures/SimpleLogo.imageset/Logo Victor2.png b/AlloVictor/Assets.xcassets/Pictures/SimpleLogo.imageset/Logo Victor2.png new file mode 100644 index 0000000..1493210 Binary files /dev/null and b/AlloVictor/Assets.xcassets/Pictures/SimpleLogo.imageset/Logo Victor2.png differ diff --git a/AlloVictor/Assets.xcassets/Pictures/oups.imageset/Contents.json b/AlloVictor/Assets.xcassets/Pictures/oups.imageset/Contents.json new file mode 100644 index 0000000..2286b77 --- /dev/null +++ b/AlloVictor/Assets.xcassets/Pictures/oups.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "oups.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVictor/Assets.xcassets/Pictures/oups.imageset/oups.svg b/AlloVictor/Assets.xcassets/Pictures/oups.imageset/oups.svg new file mode 100644 index 0000000..ac08126 --- /dev/null +++ b/AlloVictor/Assets.xcassets/Pictures/oups.imageset/oups.svg @@ -0,0 +1,59 @@ + + + + 6F323CAA-B7A5-4B13-98A5-A3266E99B020 + Created with sketchtool. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AlloVictor/ContentView.swift b/AlloVictor/ContentView.swift deleted file mode 100644 index 0b0656d..0000000 --- a/AlloVictor/ContentView.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// ContentView.swift -// AlloVictor -// -// Created by Bodinaud Victor on 13/04/2024. -// - -import SwiftUI - -struct ContentView: View { - var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundStyle(.tint) - Text("Hello, world!") - } - .padding() - } -} - -#Preview { - ContentView() -} diff --git a/AlloVictor/DTO/OfferDetailsResponseDTO.swift b/AlloVictor/DTO/OfferDetailsResponseDTO.swift new file mode 100644 index 0000000..1f20d4d --- /dev/null +++ b/AlloVictor/DTO/OfferDetailsResponseDTO.swift @@ -0,0 +1,13 @@ +// +// OfferDetailsResponseDTO.swift +// AlloVictor +// +// Created by Bodinaud Victor on 13/04/2024. +// + +import Foundation + +struct OfferDetailsResponseDTO: Codable { + let format: String + let data: Offer +} diff --git a/AlloVictor/DTO/OfferListResponseDTO.swift b/AlloVictor/DTO/OfferListResponseDTO.swift new file mode 100644 index 0000000..67e7e1e --- /dev/null +++ b/AlloVictor/DTO/OfferListResponseDTO.swift @@ -0,0 +1,13 @@ +// +// OfferListResponseDTO.swift +// AlloVictor +// +// Created by Bodinaud Victor on 13/04/2024. +// + +import Foundation + +struct OfferListResponseDTO: Codable { + let format: String + let data: [Offer] +} diff --git a/AlloVictor/Extensions/Extension+View.swift b/AlloVictor/Extensions/Extension+View.swift new file mode 100644 index 0000000..21214cb --- /dev/null +++ b/AlloVictor/Extensions/Extension+View.swift @@ -0,0 +1,16 @@ +// +// Extension+View.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI + +extension View { + public func addBorder(_ content: S, width: CGFloat = 1, cornerRadius: CGFloat) -> some View where S : ShapeStyle { + let roundedRect = RoundedRectangle(cornerRadius: cornerRadius) + return clipShape(roundedRect) + .overlay(roundedRect.strokeBorder(content, lineWidth: width)) + } + } diff --git a/AlloVictor/Info.plist b/AlloVictor/Info.plist new file mode 100644 index 0000000..b67325d --- /dev/null +++ b/AlloVictor/Info.plist @@ -0,0 +1,16 @@ + + + + + UIAppFonts + + tt_chocolates_extralight.otf + tt_chocolates_light.otf + tt_chocolates_medium.otf + tt_chocolates_regular.otf + tt_chocolates_demibold.otf + tt_chocolates_bold.otf + tt_chocolates_extrabold.otf + + + diff --git a/AlloVictor/Models/GalleryPicture.swift b/AlloVictor/Models/GalleryPicture.swift new file mode 100644 index 0000000..3f1d904 --- /dev/null +++ b/AlloVictor/Models/GalleryPicture.swift @@ -0,0 +1,20 @@ +// +// GalleryPicture.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import Foundation + +struct GalleryPicture: Codable, Identifiable { + let id: Int + let imageLarge: String + let imageSmall: String + + enum CodingKeys: String, CodingKey { + case id + case imageLarge + case imageSmall + } +} diff --git a/AlloVictor/Models/Leaseholder.swift b/AlloVictor/Models/Leaseholder.swift new file mode 100644 index 0000000..6d3259e --- /dev/null +++ b/AlloVictor/Models/Leaseholder.swift @@ -0,0 +1,22 @@ +// +// Leaseholder.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import Foundation + +struct Leaseholder: Codable, Identifiable { + let id: Int + let displayName: String + let avatarUrl: String + let userRatings: Int + + enum CodingKeys: String, CodingKey { + case id + case displayName + case avatarUrl + case userRatings + } +} diff --git a/AlloVictor/Models/Offer.swift b/AlloVictor/Models/Offer.swift new file mode 100644 index 0000000..c6dae81 --- /dev/null +++ b/AlloVictor/Models/Offer.swift @@ -0,0 +1,55 @@ +// +// Offer.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import Foundation + +enum CardType: String, Codable { + case alloFlash = "card_blog_alloflash" + case publicSearch = "card_search_public" +} + +struct Offer: Codable, Identifiable, Hashable { + var id: Int + let latitude: Double? + let longitude: Double? + let cardType: CardType? + let desc: String? + let objectName: String? + let sectionBackgroundImage: String? + let relationships: Relationships + let publishedAtFormatted: String? + let searchPictureUrl: String? + let locationFormatted: String? + let distanceFormatted: String? + let budgetFormatted: String? + let pictures: [OfferPicture]? + + enum CodingKeys: String, CodingKey { + case id = "refId" + case latitude + case longitude + case cardType + case desc = "description" + case objectName + case sectionBackgroundImage + case relationships + case publishedAtFormatted + case searchPictureUrl + case locationFormatted + case distanceFormatted + case budgetFormatted + case pictures + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } + + public static func == (lhs: Offer, rhs: Offer) -> Bool { + return lhs.id == rhs.id + } +} diff --git a/AlloVictor/Models/OfferPicture.swift b/AlloVictor/Models/OfferPicture.swift new file mode 100644 index 0000000..9c1580d --- /dev/null +++ b/AlloVictor/Models/OfferPicture.swift @@ -0,0 +1,18 @@ +// +// OfferPicture.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import Foundation + +struct OfferPicture: Codable, Identifiable { + let id: Int + let pictureUrls: OfferPictureUrls + + enum CodingKeys: String, CodingKey { + case id + case pictureUrls + } +} diff --git a/AlloVictor/Models/OfferPictureUrls.swift b/AlloVictor/Models/OfferPictureUrls.swift new file mode 100644 index 0000000..fc20262 --- /dev/null +++ b/AlloVictor/Models/OfferPictureUrls.swift @@ -0,0 +1,13 @@ +// +// OfferPictureUrls.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import Foundation + +struct OfferPictureUrls: Codable { + let large: String + let small: String +} diff --git a/AlloVictor/Models/OfferersUser.swift b/AlloVictor/Models/OfferersUser.swift new file mode 100644 index 0000000..46d1e92 --- /dev/null +++ b/AlloVictor/Models/OfferersUser.swift @@ -0,0 +1,42 @@ +// +// OfferersUser.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import Foundation + +struct OfferersUser: Codable, Identifiable { + let id: Int + let displayName: String + let firstName: String + let avatarUrl: String + let headline: String + let reviewsCount: Int + let averageRating: Double + let onlineLatestActivityAt: Int + let onlineLatestActivityAtFormatted: String + let distanceFormatted: String + let locationFormatted: String + let isIndependent: Bool + let relationships: Relationships + let meta: OfferersUserMeta + + enum CodingKeys: String, CodingKey { + case id = "refId" + case displayName + case firstName + case headline + case avatarUrl + case reviewsCount + case averageRating + case onlineLatestActivityAt + case onlineLatestActivityAtFormatted + case distanceFormatted + case locationFormatted + case isIndependent + case relationships + case meta + } +} diff --git a/AlloVictor/Models/OfferersUserMeta.swift b/AlloVictor/Models/OfferersUserMeta.swift new file mode 100644 index 0000000..c53dd0b --- /dev/null +++ b/AlloVictor/Models/OfferersUserMeta.swift @@ -0,0 +1,16 @@ +// +// OfferersUserMeta.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import Foundation + +struct OfferersUserMeta: Codable { + let answeredAtFormatted: String + + enum CodingKeys: String, CodingKey { + case answeredAtFormatted + } +} diff --git a/AlloVictor/Models/Relationships.swift b/AlloVictor/Models/Relationships.swift new file mode 100644 index 0000000..ca1f990 --- /dev/null +++ b/AlloVictor/Models/Relationships.swift @@ -0,0 +1,22 @@ +// +// Relationships.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import Foundation + +struct Relationships: Codable { + let leaseholder: Leaseholder? + let social: Social? + let offerersUsers: [OfferersUser]? + let galleryPictures: [GalleryPicture]? + + enum CodingKeys: String, CodingKey { + case leaseholder + case social + case offerersUsers + case galleryPictures + } +} diff --git a/AlloVictor/Models/Social.swift b/AlloVictor/Models/Social.swift new file mode 100644 index 0000000..fca5900 --- /dev/null +++ b/AlloVictor/Models/Social.swift @@ -0,0 +1,20 @@ +// +// Social.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import Foundation + +struct Social: Codable { + let likesCount: Int + let answerersCount: Int? + let shareLink: String? + + enum CodingKeys: String, CodingKey { + case likesCount + case answerersCount + case shareLink + } +} diff --git a/AlloVictor/Resources/Fonts/tt_chocolates_bold.otf b/AlloVictor/Resources/Fonts/tt_chocolates_bold.otf new file mode 100644 index 0000000..d963e86 Binary files /dev/null and b/AlloVictor/Resources/Fonts/tt_chocolates_bold.otf differ diff --git a/AlloVictor/Resources/Fonts/tt_chocolates_demibold.otf b/AlloVictor/Resources/Fonts/tt_chocolates_demibold.otf new file mode 100644 index 0000000..7938280 Binary files /dev/null and b/AlloVictor/Resources/Fonts/tt_chocolates_demibold.otf differ diff --git a/AlloVictor/Resources/Fonts/tt_chocolates_extrabold.otf b/AlloVictor/Resources/Fonts/tt_chocolates_extrabold.otf new file mode 100644 index 0000000..7493ce3 Binary files /dev/null and b/AlloVictor/Resources/Fonts/tt_chocolates_extrabold.otf differ diff --git a/AlloVictor/Resources/Fonts/tt_chocolates_extralight.otf b/AlloVictor/Resources/Fonts/tt_chocolates_extralight.otf new file mode 100644 index 0000000..6373fb5 Binary files /dev/null and b/AlloVictor/Resources/Fonts/tt_chocolates_extralight.otf differ diff --git a/AlloVictor/Resources/Fonts/tt_chocolates_light.otf b/AlloVictor/Resources/Fonts/tt_chocolates_light.otf new file mode 100644 index 0000000..dd8d713 Binary files /dev/null and b/AlloVictor/Resources/Fonts/tt_chocolates_light.otf differ diff --git a/AlloVictor/Resources/Fonts/tt_chocolates_medium.otf b/AlloVictor/Resources/Fonts/tt_chocolates_medium.otf new file mode 100644 index 0000000..5cc79ef Binary files /dev/null and b/AlloVictor/Resources/Fonts/tt_chocolates_medium.otf differ diff --git a/AlloVictor/Resources/Fonts/tt_chocolates_regular.otf b/AlloVictor/Resources/Fonts/tt_chocolates_regular.otf new file mode 100644 index 0000000..a26ed01 Binary files /dev/null and b/AlloVictor/Resources/Fonts/tt_chocolates_regular.otf differ diff --git a/AlloVictor/Screens/NotFoundScreen.swift b/AlloVictor/Screens/NotFoundScreen.swift new file mode 100644 index 0000000..988b46c --- /dev/null +++ b/AlloVictor/Screens/NotFoundScreen.swift @@ -0,0 +1,25 @@ +// +// NotFoundScreen.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI + +struct NotFoundScreen: View { + var body: some View { + ZStack { + VStack { + Spacer() + Image("oups") + .resizable() + .scaledToFit() + Text("L'annonce à laquelle vous essayez d'accéder est introuvable…") + .bold(16) + Spacer() + } + } + .background(Color.white) + } +} diff --git a/AlloVictor/Screens/OfferDetailsScreen.swift b/AlloVictor/Screens/OfferDetailsScreen.swift new file mode 100644 index 0000000..1d0c733 --- /dev/null +++ b/AlloVictor/Screens/OfferDetailsScreen.swift @@ -0,0 +1,50 @@ +// +// OfferDetailsScreen.swift +// AlloVictor +// +// Created by Bodinaud Victor on 14/04/2024. +// + +import SwiftUI + +struct OfferDetailsScreen: View { + @Environment(\.dismiss) var dismiss + + let offerDetails: Offer? + + var body: some View { + VStack { + if offerDetails != nil { + OfferDetailsView(offerDetails: offerDetails!) + } else { + NotFoundScreen() + } + } + .navigationBarBackButtonHidden() + .toolbar(content: { + ToolbarItem(placement: .navigation) { + Button(action: { + dismiss() + }, label: { + Image(systemName: "arrow.backward") + .resizable() + .foregroundStyle(Color.black) + .aspectRatio(contentMode: .fill) + .frame(width: 15, height: 15) + }) + } + + ToolbarItem(placement: .principal) { + Text("Demande publique") + .bold(16) + } + + if offerDetails != nil { + ToolbarItem(placement: .topBarTrailing) { + ShareView(link: offerDetails!.relationships.social?.shareLink ?? "") + } + } + }) + } +} + diff --git a/AlloVictor/Screens/OffersListScreen.swift b/AlloVictor/Screens/OffersListScreen.swift new file mode 100644 index 0000000..434e872 --- /dev/null +++ b/AlloVictor/Screens/OffersListScreen.swift @@ -0,0 +1,56 @@ +// +// OffersListScreen.swift +// AlloVictor +// +// Created by Bodinaud Victor on 13/04/2024. +// + +import SwiftUI + +struct OffersListScreen: View { + @EnvironmentObject private var viewModel: AlloVictorViewModel + + var body: some View { + ScrollView { + LazyVStack { + ForEach(viewModel.offersList) { offer in + if offer.cardType == .publicSearch { + OfferListView(offer: offer, offerDetails: viewModel.offerDetails[offer.id]) + } else if offer.cardType == .alloFlash { + AlloFlashView(offer: offer) + } + } + } + } + .background(Color.neutral20) + .toolbar(content: { + ToolbarItem(placement: .topBarLeading) { + Button(action: {}, label: { + AvatarView(avatarUrl: "", width: 35, height: 35) + }) + } + + ToolbarItem(placement: .principal) { + VStack { + Image("SimpleLogo") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(height: 25) + Text("Nantes (Procès)") + .medium(12) + .foregroundStyle(Color.gray) + } + } + + ToolbarItem(placement: .topBarTrailing) { + Button(action: {}, label: { + Image(systemName: "bell") + }) + .foregroundColor(.black) + } + }) + .navigationBarTitleDisplayMode(.inline) + .toolbarBackground(.white, for: .navigationBar) + .toolbarBackground(.visible, for: .navigationBar) + } +} diff --git a/AlloVictor/Screens/ShowFullPictureScreen.swift b/AlloVictor/Screens/ShowFullPictureScreen.swift new file mode 100644 index 0000000..98bbc54 --- /dev/null +++ b/AlloVictor/Screens/ShowFullPictureScreen.swift @@ -0,0 +1,26 @@ +// +// ShowFullPictureScreen.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI +import CachedAsyncImage + +struct ShowFullPictureScreen: View { + let pictureUrl: String + + var body: some View { + VStack(alignment: .trailing) { + CachedAsyncImage(url: URL(string: pictureUrl)) { image in + image + .resizable() + .scaledToFit() + + } placeholder: { + ProgressView() + } + } + } +} diff --git a/AlloVictor/Utils/Constants.swift b/AlloVictor/Utils/Constants.swift new file mode 100644 index 0000000..0c667a8 --- /dev/null +++ b/AlloVictor/Utils/Constants.swift @@ -0,0 +1,17 @@ +// +// Constants.swift +// AlloVictor +// +// Created by Bodinaud Victor on 13/04/2024. +// + +import Foundation + +struct Constants { + public static let baseUrl = "https://git.mahtan-melwasul.com/Mahtan/AlloVictor/raw/branch/develop/AlloVictor/Resources" + + struct Urls { + static let list = URL(string: "\(baseUrl)/Screen1.json")! + static let detail = URL(string: "\(baseUrl)/Screen2.json")! + } +} diff --git a/AlloVictor/Utils/HTTPClient.swift b/AlloVictor/Utils/HTTPClient.swift new file mode 100644 index 0000000..bf4d09b --- /dev/null +++ b/AlloVictor/Utils/HTTPClient.swift @@ -0,0 +1,74 @@ +// +// HTTPClient.swift +// AlloVictor +// +// Created by Bodinaud Victor on 13/04/2024. +// + +import Foundation + +enum NetworkError: Error { + case badRequest + case invalideResponse + case failedDecoding +} + +enum HTTPMethod { + case get + + var name: String { + switch self { + case .get: + return "GET" + } + } +} + +struct Resource { + let url: URL + var method: HTTPMethod = .get + var modelType: T.Type +} + +struct HTTPClient { + + private var defaultHeaders: [String: String] { + let headers = ["Content-Type": "application/json"] + + return headers + } + + public func load(_ resource: Resource) async throws -> T { + var request = URLRequest(url: resource.url) + + switch resource.method { + case .get: + let components = URLComponents(url: resource.url, resolvingAgainstBaseURL: false) + guard let url = components?.url else { + throw NetworkError.badRequest + } + + request = URLRequest(url: url) + } + + let configuration = URLSessionConfiguration.default + configuration.httpAdditionalHeaders = defaultHeaders + let session = URLSession(configuration: configuration) + + let (data, response) = try await session.data(for: request) + + guard let _ = response as? HTTPURLResponse else { + throw NetworkError.invalideResponse + } + + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + + guard let result = try? + decoder.decode(resource.modelType, from: data) else { + throw NetworkError.failedDecoding + } + + return result + } +} diff --git a/AlloVictor/ViewModels/AlloVictorViewModel.swift b/AlloVictor/ViewModels/AlloVictorViewModel.swift new file mode 100644 index 0000000..05b7147 --- /dev/null +++ b/AlloVictor/ViewModels/AlloVictorViewModel.swift @@ -0,0 +1,26 @@ +// +// AlloVictorViewModel.swift +// AlloVictor +// +// Created by Bodinaud Victor on 13/04/2024. +// + +import Foundation + +@MainActor +class AlloVictorViewModel: ObservableObject { + @Published var offersList: [Offer] = [] + @Published var offerDetails: [Int: Offer] = [:] + + let httpClient = HTTPClient() + + func getDatas() async throws { + let listResource = Resource(url: Constants.Urls.list, modelType: OfferListResponseDTO.self) + let detailsResource = Resource(url: Constants.Urls.detail, modelType: OfferDetailsResponseDTO.self) + + offersList = try await httpClient.load(listResource).data + let offer = try await httpClient.load(detailsResource).data + + offerDetails[offer.id] = offer + } +} diff --git a/AlloVictor/Views/AlloFlashView.swift b/AlloVictor/Views/AlloFlashView.swift new file mode 100644 index 0000000..37d3f27 --- /dev/null +++ b/AlloVictor/Views/AlloFlashView.swift @@ -0,0 +1,58 @@ +// +// AlloFlashView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 13/04/2024. +// + +import SwiftUI +import CachedAsyncImage + +struct AlloFlashView: View { + @State private var isLiked = false + let offer: Offer + + var body: some View { + VStack { + VStack(alignment: .leading) { + HStack { + Image("Icon") + .resizable() + .frame(width: 25, height: 25) + .aspectRatio(contentMode: .fit) + Text("AlloFlash") + .medium(13) + } + Divider() + } + .padding([.leading, .trailing]) + CachedAsyncImage(url: URL(string: offer.sectionBackgroundImage ?? "")) { image in + image + .resizable() + .aspectRatio(contentMode: .fit) + } placeholder: { + ProgressView() + } + VStack(alignment: .leading) { + HStack { + Text("\(offer.relationships.social?.likesCount ?? 0) j'aime") + .regular(12) + } + Divider() + Button(action: { + isLiked.toggle() + }, label: { + HStack { + Image(systemName: isLiked ? "heart.fill" : "heart") + .foregroundStyle(isLiked ? Color.red : Color.black) + Text("J'aime") + .medium(14) + } + }) + } + .padding([.leading, .trailing, .bottom]) + } + .buttonStyle(PlainButtonStyle()) + .background(Color.white) + } +} diff --git a/AlloVictor/Views/Components/AvatarView.swift b/AlloVictor/Views/Components/AvatarView.swift new file mode 100644 index 0000000..2a377bf --- /dev/null +++ b/AlloVictor/Views/Components/AvatarView.swift @@ -0,0 +1,31 @@ +// +// AvatarView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 15/04/2024. +// + +import SwiftUI +import CachedAsyncImage + +struct AvatarView: View { + let avatarUrl: String + let width: CGFloat + let height: CGFloat + + var body: some View { + CachedAsyncImage(url: URL(string: avatarUrl)) { image in + image + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: width, height: height) + .clipShape(Circle()) + } placeholder: { + Image("Avatar") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: width, height: height) + .clipShape(Circle()) + } + } +} diff --git a/AlloVictor/Views/Components/Offer/OfferBodyView.swift b/AlloVictor/Views/Components/Offer/OfferBodyView.swift new file mode 100644 index 0000000..a308bd3 --- /dev/null +++ b/AlloVictor/Views/Components/Offer/OfferBodyView.swift @@ -0,0 +1,45 @@ +// +// OfferBodyView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI +import CachedAsyncImage + +struct OfferBodyView: View { + let offer: Offer + + var body: some View { + HStack(alignment: .top) { + AvatarView(avatarUrl: offer.relationships.leaseholder?.avatarUrl ?? "", width: 50, height: 50) + + VStack(alignment: .leading, spacing: 8) { + Text(offer.relationships.leaseholder?.displayName ?? "") + .demiBold(16) + Text(offer.desc ?? "") + .regular(16) + + if offer.searchPictureUrl != nil { + CachedAsyncImage(url: URL(string: offer.searchPictureUrl!)) { image in + image + .resizable() + .cornerRadius(8) + .scaledToFit() + } placeholder: { + ProgressView() + .padding() + } + } + + VStack(alignment: .leading, spacing: 4) { + Text("\(offer.locationFormatted ?? "") - \(offer.distanceFormatted ?? "")") + .regular(12) + Text("Budget: \(offer.budgetFormatted ?? "")") + .regular(12) + } + } + } + } +} diff --git a/AlloVictor/Views/Components/Offer/OfferHeaderView.swift b/AlloVictor/Views/Components/Offer/OfferHeaderView.swift new file mode 100644 index 0000000..9098b9a --- /dev/null +++ b/AlloVictor/Views/Components/Offer/OfferHeaderView.swift @@ -0,0 +1,24 @@ +// +// OfferHeaderView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI + +struct OfferHeaderView: View { + let publishedAt: String + + var body: some View { + HStack { + Image(systemName: "globe.americas.fill") + .foregroundStyle(Color.black) + Text("Demande publique") + .medium(13) + Spacer() + Text(publishedAt) + .regular(12) + } + } +} diff --git a/AlloVictor/Views/Components/Offer/OfferSocialView.swift b/AlloVictor/Views/Components/Offer/OfferSocialView.swift new file mode 100644 index 0000000..f22763b --- /dev/null +++ b/AlloVictor/Views/Components/Offer/OfferSocialView.swift @@ -0,0 +1,54 @@ +// +// OfferSocialView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 14/04/2024. +// + +import SwiftUI + +struct OfferSocialView: View { + @State private var isLiked = false + let social: Social + + var body: some View { + VStack(spacing: 8) { + HStack { + Text("\(social.likesCount) j'aime") + .regular(12) + Spacer() + Text("\(social.answerersCount ?? 0) réponses") + .regular(12) + } + Divider() + HStack { + Button(action: { + isLiked.toggle() + }, label: { + Image(systemName: isLiked ? "heart.fill" : "heart") + .foregroundStyle(isLiked ? Color.red : Color.black) + Text("J'aime") + .medium(14) + }) + Spacer() + + Button(action: {}, label: { + Image(systemName: "person.3") + .foregroundStyle(Color.black) + Text("Recommander") + .medium(14) + }) + Spacer() + + Button(action: {}, label: { + Image(systemName: "ellipsis.message") + .foregroundStyle(Color.black) + Text("Répondre") + .medium(14) + }) + } + .buttonStyle(PlainButtonStyle()) + } + .padding() + } +} diff --git a/AlloVictor/Views/Components/OfferDetails/OfferDetailsAwnserCountView.swift b/AlloVictor/Views/Components/OfferDetails/OfferDetailsAwnserCountView.swift new file mode 100644 index 0000000..e00dc0f --- /dev/null +++ b/AlloVictor/Views/Components/OfferDetails/OfferDetailsAwnserCountView.swift @@ -0,0 +1,21 @@ +// +// OfferDetailsAwnserCountView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI + +struct OfferDetailsAwnserCountView: View { + let awnserCount: Int + + var body: some View { + HStack { + Image(systemName: "ellipsis.message") + Text("\(awnserCount) offreurs ont répondu") + } + .bold(18) + .padding([.leading, .trailing]) + } +} diff --git a/AlloVictor/Views/Components/OfferDetails/OfferDetailsBodyView.swift b/AlloVictor/Views/Components/OfferDetails/OfferDetailsBodyView.swift new file mode 100644 index 0000000..7890be9 --- /dev/null +++ b/AlloVictor/Views/Components/OfferDetails/OfferDetailsBodyView.swift @@ -0,0 +1,61 @@ +// +// OfferDetailsBodyView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI +import MapKit + +struct OfferDetailsBodyView: View { + let offerDetails: Offer + + var body: some View { + VStack { + HStack(alignment: .top) { + AvatarView(avatarUrl: offerDetails.relationships.leaseholder?.avatarUrl ?? "", width: 50, height: 50) + + VStack(alignment: .leading, spacing: 8) { + HStack { + if offerDetails.relationships.leaseholder != nil { + OfferDetailsLeaseholderInfosView(leaseholder: offerDetails.relationships.leaseholder!) + } + + Spacer() + + VStack(alignment: .trailing) { + Text("demande postée") + .medium(12) + Text(offerDetails.publishedAtFormatted ?? "") + .medium(12) + } + } + + Text(offerDetails.desc ?? "") + .regular(16) + + if offerDetails.pictures != nil { + OfferDetailsGalleryView(pictures: offerDetails.pictures!) + } + + OfferDetailsMapView(latitude: offerDetails.latitude!, longitude: offerDetails.longitude!) + .frame(height: 150) + .cornerRadius(8) + + VStack(alignment: .leading, spacing: 4) { + Text("\(offerDetails.locationFormatted!) - \(offerDetails.distanceFormatted!)") + .regular(12) + Text("Budget: \(offerDetails.budgetFormatted!)") + .regular(12) + Text("Catégorie : \(offerDetails.objectName!)") + .regular(12) + } + } + } + .padding([.leading, .trailing]) + + OfferSocialView(social: offerDetails.relationships.social!) + } + } +} diff --git a/AlloVictor/Views/Components/OfferDetails/OfferDetailsGalleryView.swift b/AlloVictor/Views/Components/OfferDetails/OfferDetailsGalleryView.swift new file mode 100644 index 0000000..248be21 --- /dev/null +++ b/AlloVictor/Views/Components/OfferDetails/OfferDetailsGalleryView.swift @@ -0,0 +1,35 @@ +// +// OfferDetailsGalleryView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI +import CachedAsyncImage + +struct OfferDetailsGalleryView: View { + @State var showFullScreenPicture = false + let pictures: [OfferPicture] + + var body: some View { + ForEach(pictures) { picture in + CachedAsyncImage(url: URL(string: picture.pictureUrls.large)) { image in + image + .resizable() + .cornerRadius(8) + .scaledToFit() + } placeholder: { + ProgressView() + .padding() + } + .sheet(isPresented: $showFullScreenPicture, content: { + ShowFullPictureScreen(pictureUrl: picture.pictureUrls.large) + }) + .onTapGesture { + showFullScreenPicture.toggle() + } + + } + } +} diff --git a/AlloVictor/Views/Components/OfferDetails/OfferDetailsLeaseholderInfosView.swift b/AlloVictor/Views/Components/OfferDetails/OfferDetailsLeaseholderInfosView.swift new file mode 100644 index 0000000..b21a79b --- /dev/null +++ b/AlloVictor/Views/Components/OfferDetails/OfferDetailsLeaseholderInfosView.swift @@ -0,0 +1,26 @@ +// +// OfferDetailsLeaseholderInfosView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI + +struct OfferDetailsLeaseholderInfosView: View { + var leaseholder: Leaseholder + + var body: some View { + VStack(alignment: .leading) { + Text(leaseholder.displayName) + .demiBold(16) + HStack { + Image(systemName: "star.fill") + .foregroundStyle(Color.neutral20) + Text("\(leaseholder.userRatings == 0 ? "-" : "\(leaseholder.userRatings)")/5") + .bold(14) + } + .regular(12) + } + } +} diff --git a/AlloVictor/Views/Components/OfferDetails/OfferDetailsMapView.swift b/AlloVictor/Views/Components/OfferDetails/OfferDetailsMapView.swift new file mode 100644 index 0000000..1845070 --- /dev/null +++ b/AlloVictor/Views/Components/OfferDetails/OfferDetailsMapView.swift @@ -0,0 +1,32 @@ +// +// OfferDetailsMapView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI +import MapKit + +struct OfferDetailsMapView: View { + let latitude: Double + let longitude: Double + + var body: some View { + Map(bounds: MapCameraBounds(minimumDistance: 8000), interactionModes: []) { + Annotation("", coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude)) { + AvatarView(avatarUrl: "", width: 40, height: 40) + } + } + .mapStyle( + .standard( + pointsOfInterest: .excludingAll, + showsTraffic: false + ) + ) + } +} + +#Preview { + OfferDetailsMapView(latitude: 47.2182, longitude: -1.55947) +} diff --git a/AlloVictor/Views/Components/OffererUser/OffererUserGallery.swift b/AlloVictor/Views/Components/OffererUser/OffererUserGallery.swift new file mode 100644 index 0000000..c7aa49b --- /dev/null +++ b/AlloVictor/Views/Components/OffererUser/OffererUserGallery.swift @@ -0,0 +1,31 @@ +// +// OffererUserGallery.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI +import CachedAsyncImage + +struct OffererUserGallery: View { + let gallery: [GalleryPicture] + + var body: some View { + ScrollView(.horizontal) { + HStack { + ForEach(gallery) { picture in + CachedAsyncImage(url: URL(string: picture.imageSmall)) { image in + image + .resizable() + .frame(width: 200, height: 100) + .scaledToFill() + } placeholder: { + ProgressView() + } + } + } + } + .scrollIndicators(.hidden) + } +} diff --git a/AlloVictor/Views/Components/OffererUser/OffererUserInfos.swift b/AlloVictor/Views/Components/OffererUser/OffererUserInfos.swift new file mode 100644 index 0000000..4185bbf --- /dev/null +++ b/AlloVictor/Views/Components/OffererUser/OffererUserInfos.swift @@ -0,0 +1,30 @@ +// +// OffererUserInfos.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI + +struct OffererUserInfos: View { + let offererUser: OfferersUser + + var body: some View { + VStack(alignment: .leading) { + HStack { + AvatarView(avatarUrl: offererUser.avatarUrl, width: 65, height: 65) + VStack(alignment: .leading) { + Text(offererUser.displayName) + .medium(15) + Text(offererUser.headline) + .medium(12) + Text("\(offererUser.locationFormatted) - à \(offererUser.distanceFormatted)") + .light(12) + Text(offererUser.onlineLatestActivityAtFormatted) + .light(12) + } + } + } + } +} diff --git a/AlloVictor/Views/Components/OffererUser/OffererUserProStatusView.swift b/AlloVictor/Views/Components/OffererUser/OffererUserProStatusView.swift new file mode 100644 index 0000000..c6fa00c --- /dev/null +++ b/AlloVictor/Views/Components/OffererUser/OffererUserProStatusView.swift @@ -0,0 +1,20 @@ +// +// OffererUserProStatusView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI + +struct OffererUserProStatusView: View { + let isIndependent: Bool + + var body: some View { + Text(isIndependent ? "Auto-entrepreneur" : "Particulier") + .demiBold(12) + .padding(4) + .background(isIndependent ? Color.grape30 : Color.neutral20) + .cornerRadius(5) + } +} diff --git a/AlloVictor/Views/Components/OffererUser/OffererUserRatingView.swift b/AlloVictor/Views/Components/OffererUser/OffererUserRatingView.swift new file mode 100644 index 0000000..601b2a3 --- /dev/null +++ b/AlloVictor/Views/Components/OffererUser/OffererUserRatingView.swift @@ -0,0 +1,24 @@ +// +// OffererUserRatingView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 18/04/2024. +// + +import SwiftUI + +struct OffererUserRatingView: View { + let averageRating: Double + let reviewsCount: Int + + var body: some View { + HStack { + Image(systemName: "star.fill") + .foregroundStyle(Color.yellow) + Text("\(String(format: "%.1f", averageRating))/5") + .demiBold(18) + Text("(\(reviewsCount) avis)") + .bold(14) + } + } +} diff --git a/AlloVictor/Views/Components/ShareView.swift b/AlloVictor/Views/Components/ShareView.swift new file mode 100644 index 0000000..20e0cb0 --- /dev/null +++ b/AlloVictor/Views/Components/ShareView.swift @@ -0,0 +1,25 @@ +// +// ShareView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 14/04/2024. +// + +import SwiftUI + +struct ShareView: View { + let link: String + + var body: some View { + HStack { + ShareLink(item: URL(string: link)!) { + Image(systemName: "square.and.arrow.up") + } + .foregroundColor(.black) + Button(action: {}, label: { + Image(systemName: "ellipsis.circle") + }) + .foregroundColor(.black) + } + } +} diff --git a/AlloVictor/Views/Modifiers/TextModifier.swift b/AlloVictor/Views/Modifiers/TextModifier.swift new file mode 100644 index 0000000..2ac6f89 --- /dev/null +++ b/AlloVictor/Views/Modifiers/TextModifier.swift @@ -0,0 +1,89 @@ +// +// TextModifier.swift +// AlloVictor +// +// Created by Bodinaud Victor on 14/04/2024. +// + +import Foundation +import SwiftUI + +struct AlloTextExtraLight: ViewModifier { + let size: CGFloat + + func body(content: Content) -> some View { + content + .font(.custom("TTChocolates-ExtraLight", size: size)) + } +} + +struct AlloTextLight: ViewModifier { + let size: CGFloat + + func body(content: Content) -> some View { + content + .font(.custom("TTChocolates-Light", size: size)) + } +} + +struct AlloTextRegular: ViewModifier { + let size: CGFloat + + func body(content: Content) -> some View { + content + .font(.custom("TTChocolates-Regular", size: size)) + } +} + +struct AlloTextMedium: ViewModifier { + let size: CGFloat + + func body(content: Content) -> some View { + content + .font(.custom("TTChocolates-Medium", size: size)) + } +} + +struct AlloTextDemiBold: ViewModifier { + let size: CGFloat + + func body(content: Content) -> some View { + content + .font(.custom("TTChocolates-DemiBold", size: size)) + } +} + +struct AlloTextBold: ViewModifier { + let size: CGFloat + + func body(content: Content) -> some View { + content + .font(.custom("TTChocolates-Bold", size: size)) + } +} + +extension View { + func extraLight(_ size: CGFloat) -> some View { + modifier(AlloTextExtraLight(size: size)) + } + + func light(_ size: CGFloat) -> some View { + modifier(AlloTextLight(size: size)) + } + + func regular(_ size: CGFloat) -> some View { + modifier(AlloTextRegular(size: size)) + } + + func medium(_ size: CGFloat) -> some View { + modifier(AlloTextMedium(size: size)) + } + + func demiBold(_ size: CGFloat) -> some View { + modifier(AlloTextDemiBold(size: size)) + } + + func bold(_ size: CGFloat) -> some View { + modifier(AlloTextBold(size: size)) + } +} diff --git a/AlloVictor/Views/OfferDetailsView.swift b/AlloVictor/Views/OfferDetailsView.swift new file mode 100644 index 0000000..c4f427b --- /dev/null +++ b/AlloVictor/Views/OfferDetailsView.swift @@ -0,0 +1,50 @@ +// +// OfferDetailsView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 14/04/2024. +// + +import SwiftUI +import MapKit + +struct OfferDetailsView: View { + let offerDetails: Offer + + var body: some View { + ScrollView { + LazyVStack(alignment: .leading) { + OfferDetailsBodyView(offerDetails: offerDetails) + + OfferDetailsAwnserCountView(awnserCount: offerDetails.relationships.social?.answerersCount ?? 0) + + ForEach(offerDetails.relationships.offerersUsers!) { offererUser in + OffererUserView(offererUser: offererUser) + .padding() + } + } + } + .background(Color.white) + .toolbar { + ToolbarItemGroup(placement: .bottomBar) { + HStack(alignment: .center) { + Button(action: {}, label: { + HStack { + Image(systemName: "ellipsis.message") + .foregroundStyle(Color.white) + Text("Répondre") + .bold(14) + .foregroundStyle(Color.white) + } + }) + .padding([.top, .bottom], 4) + .padding([.leading, .trailing], 16) + .background(Color.pillButton) + .clipShape(Capsule()) + .foregroundStyle(Color.white) + } + } + } + .toolbarColorScheme(.light) + } +} diff --git a/AlloVictor/Views/OfferListView.swift b/AlloVictor/Views/OfferListView.swift new file mode 100644 index 0000000..a65b83c --- /dev/null +++ b/AlloVictor/Views/OfferListView.swift @@ -0,0 +1,33 @@ +// +// OfferListView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 13/04/2024. +// + +import SwiftUI +import CachedAsyncImage + +struct OfferListView: View { + let offer: Offer + let offerDetails: Offer? + + var body: some View { + VStack { + NavigationLink(value: Route.detail(offerDetails)) { + VStack { + OfferHeaderView(publishedAt: offer.publishedAtFormatted ?? "") + + Divider() + + OfferBodyView(offer: offer) + } + } + .padding() + .buttonStyle(PlainButtonStyle()) + + OfferSocialView(social: offer.relationships.social!) + } + .background(Color.white) + } +} diff --git a/AlloVictor/Views/OffererUserView.swift b/AlloVictor/Views/OffererUserView.swift new file mode 100644 index 0000000..71f969f --- /dev/null +++ b/AlloVictor/Views/OffererUserView.swift @@ -0,0 +1,36 @@ +// +// OffererUserView.swift +// AlloVictor +// +// Created by Bodinaud Victor on 14/04/2024. +// + +import SwiftUI + +struct OffererUserView: View { + let offererUser: OfferersUser + + var body: some View { + VStack(alignment: .trailing) { + VStack(alignment: .trailing) { + OffererUserProStatusView(isIndependent: offererUser.isIndependent) + + VStack(alignment: .leading) { + OffererUserInfos(offererUser: offererUser) + .padding([.leading, .trailing]) + + if offererUser.relationships.galleryPictures != nil { + OffererUserGallery(gallery: offererUser.relationships.galleryPictures!) + } + + OffererUserRatingView(averageRating: offererUser.averageRating, reviewsCount: offererUser.reviewsCount) + .padding() + } + } + .background(Color.white) + .addBorder(Color.neutral20, cornerRadius: 5) + Text(offererUser.meta.answeredAtFormatted) + .regular(12) + } + } +}