diff --git a/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj b/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj index 4594e049..e6ab40df 100644 --- a/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj +++ b/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj @@ -71,6 +71,37 @@ 365CD6D82B7E4D0700245CDD /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 365CD6D72B7E4D0700245CDD /* Kingfisher */; }; 365CD6DB2B7E4D3600245CDD /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 365CD6DA2B7E4D3600245CDD /* SnapKit */; }; 365CD6DE2B7E4D4E00245CDD /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = 365CD6DD2B7E4D4E00245CDD /* Then */; }; + 367243D12BEDE9F6007A5A7B /* NetworkHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243CA2BEDE9F5007A5A7B /* NetworkHelper.swift */; }; + 367243D22BEDE9F6007A5A7B /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243CB2BEDE9F5007A5A7B /* Config.swift */; }; + 367243D32BEDE9F6007A5A7B /* ResponseData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243CC2BEDE9F5007A5A7B /* ResponseData.swift */; }; + 367243D42BEDE9F6007A5A7B /* NetworkResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243CD2BEDE9F5007A5A7B /* NetworkResult.swift */; }; + 367243D62BEDE9F6007A5A7B /* APIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243CF2BEDE9F6007A5A7B /* APIConstants.swift */; }; + 367243D72BEDE9F6007A5A7B /* MoyaLoggerPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243D02BEDE9F6007A5A7B /* MoyaLoggerPlugin.swift */; }; + 367243E22BEDEAF8007A5A7B /* SocialLoginRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243DB2BEDEAF7007A5A7B /* SocialLoginRequestDTO.swift */; }; + 367243E32BEDEAF8007A5A7B /* SocialLoginResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243DC2BEDEAF7007A5A7B /* SocialLoginResponseDTO.swift */; }; + 367243E42BEDEAF8007A5A7B /* SignUpResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243DD2BEDEAF7007A5A7B /* SignUpResponseDTO.swift */; }; + 367243E62BEDEAF8007A5A7B /* SignUpRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243DF2BEDEAF8007A5A7B /* SignUpRequestDTO.swift */; }; + 367243E72BEDEAF8007A5A7B /* RefreshTokenResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243E02BEDEAF8007A5A7B /* RefreshTokenResponseDTO.swift */; }; + 367243F42BEDEB32007A5A7B /* AddAppResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243E92BEDEB30007A5A7B /* AddAppResponseDTO.swift */; }; + 367243F52BEDEB32007A5A7B /* AddAppRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243EA2BEDEB31007A5A7B /* AddAppRequestDTO.swift */; }; + 367243F62BEDEB32007A5A7B /* DeleteAppRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243EB2BEDEB31007A5A7B /* DeleteAppRequestDTO.swift */; }; + 367243F72BEDEB32007A5A7B /* CreateChallengeResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243EC2BEDEB31007A5A7B /* CreateChallengeResponseDTO.swift */; }; + 367243F82BEDEB32007A5A7B /* GetChallengeResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243ED2BEDEB31007A5A7B /* GetChallengeResponseDTO.swift */; }; + 367243FA2BEDEB32007A5A7B /* GetHomeChallengeResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243EF2BEDEB31007A5A7B /* GetHomeChallengeResponseDTO.swift */; }; + 367243FB2BEDEB32007A5A7B /* CreateChallengeRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243F02BEDEB31007A5A7B /* CreateChallengeRequestDTO.swift */; }; + 367243FC2BEDEB32007A5A7B /* HomeChallengeResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243F12BEDEB31007A5A7B /* HomeChallengeResponseDTO.swift */; }; + 367243FD2BEDEB32007A5A7B /* EmptyResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243F22BEDEB32007A5A7B /* EmptyResponseDTO.swift */; }; + 367243FE2BEDEB32007A5A7B /* MidnightRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367243F32BEDEB32007A5A7B /* MidnightRequestDTO.swift */; }; + 367244012BEDEBD8007A5A7B /* GetUserDataResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367244002BEDEBD8007A5A7B /* GetUserDataResponseDTO.swift */; }; + 367244052BEDEC4A007A5A7B /* AuthRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367244022BEDEC4A007A5A7B /* AuthRouter.swift */; }; + 367244062BEDEC4A007A5A7B /* ChallengeRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367244032BEDEC4A007A5A7B /* ChallengeRouter.swift */; }; + 367244072BEDEC4A007A5A7B /* MyPageRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367244042BEDEC4A007A5A7B /* MyPageRouter.swift */; }; + 367244092BEDEC7F007A5A7B /* Providers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367244082BEDEC7F007A5A7B /* Providers.swift */; }; + 3672440B2BF0845B007A5A7B /* Config.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 3672440A2BF0845B007A5A7B /* Config.xcconfig */; }; + 3672440D2BF0863E007A5A7B /* BaseTargetType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3672440C2BF0863E007A5A7B /* BaseTargetType.swift */; }; + 3672440F2BF08664007A5A7B /* NetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3672440E2BF08664007A5A7B /* NetworkProvider.swift */; }; + 367244112BF08684007A5A7B /* BaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367244102BF08684007A5A7B /* BaseModel.swift */; }; + 367244132BF086A7007A5A7B /* AuthInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367244122BF086A7007A5A7B /* AuthInterceptor.swift */; }; 368C5D972BCC41990035A1AC /* HMHDeviceActivityReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 368C5D962BCC41990035A1AC /* HMHDeviceActivityReport.swift */; }; 368C5D992BCC41990035A1AC /* TotalActivityReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 368C5D982BCC41990035A1AC /* TotalActivityReport.swift */; }; 368C5D9B2BCC41990035A1AC /* TotalActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 368C5D9A2BCC41990035A1AC /* TotalActivityView.swift */; }; @@ -163,6 +194,37 @@ 365CD6BE2B7E4C4F00245CDD /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 365CD6C02B7E4C5100245CDD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 365CD6C32B7E4C5100245CDD /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 367243CA2BEDE9F5007A5A7B /* NetworkHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkHelper.swift; sourceTree = ""; }; + 367243CB2BEDE9F5007A5A7B /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; + 367243CC2BEDE9F5007A5A7B /* ResponseData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResponseData.swift; sourceTree = ""; }; + 367243CD2BEDE9F5007A5A7B /* NetworkResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkResult.swift; sourceTree = ""; }; + 367243CF2BEDE9F6007A5A7B /* APIConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIConstants.swift; sourceTree = ""; }; + 367243D02BEDE9F6007A5A7B /* MoyaLoggerPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoyaLoggerPlugin.swift; sourceTree = ""; }; + 367243DB2BEDEAF7007A5A7B /* SocialLoginRequestDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocialLoginRequestDTO.swift; sourceTree = ""; }; + 367243DC2BEDEAF7007A5A7B /* SocialLoginResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocialLoginResponseDTO.swift; sourceTree = ""; }; + 367243DD2BEDEAF7007A5A7B /* SignUpResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpResponseDTO.swift; sourceTree = ""; }; + 367243DF2BEDEAF8007A5A7B /* SignUpRequestDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignUpRequestDTO.swift; sourceTree = ""; }; + 367243E02BEDEAF8007A5A7B /* RefreshTokenResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshTokenResponseDTO.swift; sourceTree = ""; }; + 367243E92BEDEB30007A5A7B /* AddAppResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddAppResponseDTO.swift; sourceTree = ""; }; + 367243EA2BEDEB31007A5A7B /* AddAppRequestDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddAppRequestDTO.swift; sourceTree = ""; }; + 367243EB2BEDEB31007A5A7B /* DeleteAppRequestDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteAppRequestDTO.swift; sourceTree = ""; }; + 367243EC2BEDEB31007A5A7B /* CreateChallengeResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateChallengeResponseDTO.swift; sourceTree = ""; }; + 367243ED2BEDEB31007A5A7B /* GetChallengeResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetChallengeResponseDTO.swift; sourceTree = ""; }; + 367243EF2BEDEB31007A5A7B /* GetHomeChallengeResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetHomeChallengeResponseDTO.swift; sourceTree = ""; }; + 367243F02BEDEB31007A5A7B /* CreateChallengeRequestDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateChallengeRequestDTO.swift; sourceTree = ""; }; + 367243F12BEDEB31007A5A7B /* HomeChallengeResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeChallengeResponseDTO.swift; sourceTree = ""; }; + 367243F22BEDEB32007A5A7B /* EmptyResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyResponseDTO.swift; sourceTree = ""; }; + 367243F32BEDEB32007A5A7B /* MidnightRequestDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MidnightRequestDTO.swift; sourceTree = ""; }; + 367244002BEDEBD8007A5A7B /* GetUserDataResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetUserDataResponseDTO.swift; sourceTree = ""; }; + 367244022BEDEC4A007A5A7B /* AuthRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthRouter.swift; sourceTree = ""; }; + 367244032BEDEC4A007A5A7B /* ChallengeRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChallengeRouter.swift; sourceTree = ""; }; + 367244042BEDEC4A007A5A7B /* MyPageRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyPageRouter.swift; sourceTree = ""; }; + 367244082BEDEC7F007A5A7B /* Providers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Providers.swift; sourceTree = ""; }; + 3672440A2BF0845B007A5A7B /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = ""; }; + 3672440C2BF0863E007A5A7B /* BaseTargetType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTargetType.swift; sourceTree = ""; }; + 3672440E2BF08664007A5A7B /* NetworkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProvider.swift; sourceTree = ""; }; + 367244102BF08684007A5A7B /* BaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseModel.swift; sourceTree = ""; }; + 367244122BF086A7007A5A7B /* AuthInterceptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthInterceptor.swift; sourceTree = ""; }; 368C5D942BCC41990035A1AC /* HMHDeviceActivityReport.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.extensionkit-extension"; includeInIndex = 0; path = HMHDeviceActivityReport.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 368C5D962BCC41990035A1AC /* HMHDeviceActivityReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMHDeviceActivityReport.swift; sourceTree = ""; }; 368C5D982BCC41990035A1AC /* TotalActivityReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TotalActivityReport.swift; sourceTree = ""; }; @@ -378,6 +440,7 @@ 368CAADD2BB97FE000FA83B3 /* HMH_iOS.entitlements */, 0BD2D6762B9F393400733843 /* HMH-iOS-Info.plist */, 0B8693882BE8B865000D7CE1 /* Config.xcconfig */, + 3672440A2BF0845B007A5A7B /* Config.xcconfig */, 365CD6DF2B7E4ECC00245CDD /* Global */, 365CD6E22B7E4F4300245CDD /* Presentation */, 365CD6E12B7E4F2D00245CDD /* Network */, @@ -442,6 +505,10 @@ 365CD6E32B7E4F7A00245CDD /* Base */ = { isa = PBXGroup; children = ( + 3672440C2BF0863E007A5A7B /* BaseTargetType.swift */, + 3672440E2BF08664007A5A7B /* NetworkProvider.swift */, + 367244102BF08684007A5A7B /* BaseModel.swift */, + 367244122BF086A7007A5A7B /* AuthInterceptor.swift */, ); path = Base; sourceTree = ""; @@ -481,6 +548,9 @@ 365CD6E82B7E501000245CDD /* DTO */ = { isa = PBXGroup; children = ( + 367243D82BEDEAC9007A5A7B /* Auth */, + 367243D92BEDEAD2007A5A7B /* Challenge */, + 367243FF2BEDEBC6007A5A7B /* MyPage */, ); path = DTO; sourceTree = ""; @@ -488,6 +558,12 @@ 365CD6E92B7E501E00245CDD /* Foundation */ = { isa = PBXGroup; children = ( + 367243CF2BEDE9F6007A5A7B /* APIConstants.swift */, + 367243CB2BEDE9F5007A5A7B /* Config.swift */, + 367243D02BEDE9F6007A5A7B /* MoyaLoggerPlugin.swift */, + 367243CA2BEDE9F5007A5A7B /* NetworkHelper.swift */, + 367243CD2BEDE9F5007A5A7B /* NetworkResult.swift */, + 367243CC2BEDE9F5007A5A7B /* ResponseData.swift */, ); path = Foundation; sourceTree = ""; @@ -495,6 +571,9 @@ 365CD6EB2B7E504000245CDD /* Router */ = { isa = PBXGroup; children = ( + 367244022BEDEC4A007A5A7B /* AuthRouter.swift */, + 367244032BEDEC4A007A5A7B /* ChallengeRouter.swift */, + 367244042BEDEC4A007A5A7B /* MyPageRouter.swift */, ); path = Router; sourceTree = ""; @@ -502,10 +581,48 @@ 365CD6EE2B7E524300245CDD /* Service */ = { isa = PBXGroup; children = ( + 367244082BEDEC7F007A5A7B /* Providers.swift */, ); path = Service; sourceTree = ""; }; + 367243D82BEDEAC9007A5A7B /* Auth */ = { + isa = PBXGroup; + children = ( + 367243E02BEDEAF8007A5A7B /* RefreshTokenResponseDTO.swift */, + 367243DF2BEDEAF8007A5A7B /* SignUpRequestDTO.swift */, + 367243DD2BEDEAF7007A5A7B /* SignUpResponseDTO.swift */, + 367243DB2BEDEAF7007A5A7B /* SocialLoginRequestDTO.swift */, + 367243DC2BEDEAF7007A5A7B /* SocialLoginResponseDTO.swift */, + ); + path = Auth; + sourceTree = ""; + }; + 367243D92BEDEAD2007A5A7B /* Challenge */ = { + isa = PBXGroup; + children = ( + 367243EA2BEDEB31007A5A7B /* AddAppRequestDTO.swift */, + 367243E92BEDEB30007A5A7B /* AddAppResponseDTO.swift */, + 367243F02BEDEB31007A5A7B /* CreateChallengeRequestDTO.swift */, + 367243EC2BEDEB31007A5A7B /* CreateChallengeResponseDTO.swift */, + 367243EB2BEDEB31007A5A7B /* DeleteAppRequestDTO.swift */, + 367243F22BEDEB32007A5A7B /* EmptyResponseDTO.swift */, + 367243ED2BEDEB31007A5A7B /* GetChallengeResponseDTO.swift */, + 367243EF2BEDEB31007A5A7B /* GetHomeChallengeResponseDTO.swift */, + 367243F12BEDEB31007A5A7B /* HomeChallengeResponseDTO.swift */, + 367243F32BEDEB32007A5A7B /* MidnightRequestDTO.swift */, + ); + path = Challenge; + sourceTree = ""; + }; + 367243FF2BEDEBC6007A5A7B /* MyPage */ = { + isa = PBXGroup; + children = ( + 367244002BEDEBD8007A5A7B /* GetUserDataResponseDTO.swift */, + ); + path = MyPage; + sourceTree = ""; + }; 368C5D6C2BCC1BA00035A1AC /* Home */ = { isa = PBXGroup; children = ( @@ -661,6 +778,7 @@ 365CD6C12B7E4C5100245CDD /* Assets.xcassets in Resources */, 0BB2E6372BE9EC1400E13096 /* Logo_wordmark_white.json in Resources */, 0B9ACF382BA14FDB00EC0BDE /* Main-D-final.json in Resources */, + 3672440B2BF0845B007A5A7B /* Config.xcconfig in Resources */, 0BD2D6732B9F385100733843 /* Pretendard-SemiBold.otf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -687,11 +805,19 @@ 0BF56C972BC3B871003ECFB1 /* StoryContentView.swift in Sources */, 0B3C296D2BA01C2000435B30 /* ChallengeView.swift in Sources */, 3601C8362BC6E8FB005790F7 /* HomeViewModel.swift in Sources */, + 367243FC2BEDEB32007A5A7B /* HomeChallengeResponseDTO.swift in Sources */, 365CD6BF2B7E4C4F00245CDD /* ContentView.swift in Sources */, 0B82ECB22BC916C6002D5CF3 /* MyPageButton.swift in Sources */, 368CAAE22BB9B26000FA83B3 /* CustomNavigationBarModifier.swift in Sources */, + 367243D42BEDE9F6007A5A7B /* NetworkResult.swift in Sources */, + 367243D32BEDE9F6007A5A7B /* ResponseData.swift in Sources */, + 367244132BF086A7007A5A7B /* AuthInterceptor.swift in Sources */, + 367243F62BEDEB32007A5A7B /* DeleteAppRequestDTO.swift in Sources */, 368CAADF2BB9975C00FA83B3 /* NavigationBarView.swift in Sources */, 0B3C296B2BA01BD200435B30 /* TabBarView.swift in Sources */, + 367243F42BEDEB32007A5A7B /* AddAppResponseDTO.swift in Sources */, + 367243F72BEDEB32007A5A7B /* CreateChallengeResponseDTO.swift in Sources */, + 367244052BEDEC4A007A5A7B /* AuthRouter.swift in Sources */, 0BF56C952BC39BE9003ECFB1 /* OnboardingCompleteView.swift in Sources */, 0B3C296F2BA01C2800435B30 /* HomeView.swift in Sources */, 0B5140542BE3A2D600C78B9F /* LoginView.swift in Sources */, @@ -699,9 +825,13 @@ 0BC0E5B32BB04BC600FB0330 /* GoalPeriodView.swift in Sources */, 0B86937D2BE727E5000D7CE1 /* LoginViewModel.swift in Sources */, 0B86937F2BE87A5F000D7CE1 /* LoginButton.swift in Sources */, + 367243E22BEDEAF8007A5A7B /* SocialLoginRequestDTO.swift in Sources */, + 367244012BEDEBD8007A5A7B /* GetUserDataResponseDTO.swift in Sources */, 0BC0E5AF2BB04B7100FB0330 /* SurveyView.swift in Sources */, 365CD6BD2B7E4C4F00245CDD /* HMH_iOSApp.swift in Sources */, + 367244062BEDEC4A007A5A7B /* ChallengeRouter.swift in Sources */, 0BD2D67C2B9F5A7B00733843 /* String.swift in Sources */, + 367244112BF08684007A5A7B /* BaseModel.swift in Sources */, 0BC0E5BD2BB0571E00FB0330 /* NextButtonView.swift in Sources */, 0BC0E5A92BB03EE400FB0330 /* OnboardingModel.swift in Sources */, 0B8693772BE5CB46000D7CE1 /* SwipeView.swift in Sources */, @@ -710,15 +840,33 @@ 0B7646BB2BB13F6100C56D7A /* SurveyButton.swift in Sources */, 0BC0E5B52BB04BD100FB0330 /* GoalTimeView.swift in Sources */, 0BC0E5AB2BB03F8100FB0330 /* OnboardingViewModel.swift in Sources */, + 3672440F2BF08664007A5A7B /* NetworkProvider.swift in Sources */, + 367243F52BEDEB32007A5A7B /* AddAppRequestDTO.swift in Sources */, + 3672440D2BF0863E007A5A7B /* BaseTargetType.swift in Sources */, 0B82ECB02BC9152F002D5CF3 /* MyPageViewModel.swift in Sources */, 0BF56C932BC39127003ECFB1 /* PickerView.swift in Sources */, + 367243D12BEDE9F6007A5A7B /* NetworkHelper.swift in Sources */, + 367243FD2BEDEB32007A5A7B /* EmptyResponseDTO.swift in Sources */, + 367243FB2BEDEB32007A5A7B /* CreateChallengeRequestDTO.swift in Sources */, + 367243F82BEDEB32007A5A7B /* GetChallengeResponseDTO.swift in Sources */, 0B9834DC2BC8234700A1457A /* SplashView.swift in Sources */, + 367243E32BEDEAF8007A5A7B /* SocialLoginResponseDTO.swift in Sources */, 3601C8382BC6EC5C005790F7 /* UsageTimeListItemView.swift in Sources */, + 367243FA2BEDEB32007A5A7B /* GetHomeChallengeResponseDTO.swift in Sources */, + 367244072BEDEC4A007A5A7B /* MyPageRouter.swift in Sources */, 0BC0E5B12BB04BA800FB0330 /* SurveyProblemView.swift in Sources */, + 367243D72BEDE9F6007A5A7B /* MoyaLoggerPlugin.swift in Sources */, + 367243E62BEDEAF8007A5A7B /* SignUpRequestDTO.swift in Sources */, + 367244092BEDEC7F007A5A7B /* Providers.swift in Sources */, + 367243D22BEDE9F6007A5A7B /* Config.swift in Sources */, + 367243D62BEDE9F6007A5A7B /* APIConstants.swift in Sources */, 0B3C29712BA01C3000435B30 /* MyPageView.swift in Sources */, 0B3C29732BA01DCE00435B30 /* CustomTabView.swift in Sources */, + 367243FE2BEDEB32007A5A7B /* MidnightRequestDTO.swift in Sources */, 0BC0E5AD2BB0404500FB0330 /* OnboardingContentView.swift in Sources */, 0BC0E5BB2BB04C0B00FB0330 /* AppGoalTimeView.swift in Sources */, + 367243E72BEDEAF8007A5A7B /* RefreshTokenResponseDTO.swift in Sources */, + 367243E42BEDEAF8007A5A7B /* SignUpResponseDTO.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/HMH_iOS/HMH_iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/HMH_iOS/HMH_iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 389d6eed..aa9d4582 100644 --- a/HMH_iOS/HMH_iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/HMH_iOS/HMH_iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "3663af6b3771454c566b7793eb68be359aa8d364c59392086cf004cc9b916b1e", + "originHash" : "d3e9876ec49ca5b50bad5ca2775b7dd98532bd02ac823cca0b3be78c33780f04", "pins" : [ { "identity" : "alamofire", diff --git a/HMH_iOS/HMH_iOS/Network/Base/AuthInterceptor.swift b/HMH_iOS/HMH_iOS/Network/Base/AuthInterceptor.swift new file mode 100644 index 00000000..f991b69d --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Base/AuthInterceptor.swift @@ -0,0 +1,65 @@ +// +// AuthInterceptor.swift +// HMH_iOS +// +// Created by 이지희 on 5/12/24. +// +// + +import Foundation + +import Alamofire +import Moya + +///// 토큰 만료 시 자동으로 refresh를 위한 서버 통신 +final class AuthInterceptor: RequestInterceptor { + + private var retryLimit = 2 + static let shared = AuthInterceptor() + + private init() {} + + func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result) -> Void) { + print("---adater 진입----") + completion(.success(urlRequest)) + } + + func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) { + print("-------🔧retry 시작🔧-------") + guard + let statusCode = request.response?.statusCode, + request.retryCount < retryLimit + else { + print("🚨재시도 횟수가 너무 많습니다🚨") + return completion(.doNotRetry) + } + + if let statusCode = request.response?.statusCode, + request.retryCount < retryLimit { + if statusCode == 401 { + let provider = Providers.AuthProvider + provider.request(target: .tokenRefresh, instance: BaseResponse.self) { result in + if result.status == 200 { + if let data = result.data { +// UserManager.shared.updateToken(data.token.accessToken, data.token.refreshToken) + } + print("🪄토큰 재발급에 성공했습니다🪄") + completion(.retry) + } else if statusCode == 401 { + /// 리프레쉬 토큰도 만료된 상황 + } + } + } + } else if statusCode == 404 { + /// 유저를 찾을 수 없는 상태 + } else { + if request.retryCount > retryLimit { + print("🚨재시도 횟수가 너무 많습니다🚨") + } + completion(.doNotRetryWithError(error)) + return + } + } +} + + diff --git a/HMH_iOS/HMH_iOS/Network/Base/BaseModel.swift b/HMH_iOS/HMH_iOS/Network/Base/BaseModel.swift new file mode 100644 index 00000000..b0f08f9e --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Base/BaseModel.swift @@ -0,0 +1,14 @@ +// +// BaseModel.swift +// HMH_iOS +// +// Created by 이지희 on 5/12/24. +// + +import Foundation + +struct BaseResponse: Decodable { + var status: Int + var message: String? + var data: T? +} diff --git a/HMH_iOS/HMH_iOS/Network/Base/BaseTargetType.swift b/HMH_iOS/HMH_iOS/Network/Base/BaseTargetType.swift new file mode 100644 index 00000000..76e54b8a --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Base/BaseTargetType.swift @@ -0,0 +1,32 @@ +// +// BaseTargetType.swift +// HMH_iOS +// +// Created by 이지희 on 5/12/24. +// + + +import Foundation +import Moya + +protocol BaseTargetType: TargetType {} + + +extension BaseTargetType { + typealias Parameters = [String: String] + var baseURL: URL { + guard let baseURL = URL(string: Config.baseURL) else { + print("🚨🚨BASEURL ERROR🚨🚨") + fatalError() + } + return baseURL + } + + var sampleData: Data { + return Data() + } + + var validationType: ValidationType { + return .successCodes + } +} diff --git a/HMH_iOS/HMH_iOS/Network/Base/NetworkProvider.swift b/HMH_iOS/HMH_iOS/Network/Base/NetworkProvider.swift new file mode 100644 index 00000000..248dc339 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Base/NetworkProvider.swift @@ -0,0 +1,71 @@ +// +// NetworkProvider.swift +// HMH_iOS +// +// Created by 이지희 on 5/12/24. +// +// + +import SwiftUI +import Moya + +class NetworkProvider : MoyaProvider { + func request(target : Provider, instance : BaseResponse.Type , viewController: UIViewController, completion : @escaping(BaseResponse) -> ()){ + self.request(target) { result in + switch result { + /// 서버 통신 성공 + case .success(let response): + if (200..<300).contains(response.statusCode) || + response.statusCode == 403 { + if let decodeData = try? JSONDecoder().decode(instance, from: response.data) { + completion(decodeData) + } else{ + print("🚨 decoding Error 발생") + } + } else { + print("🚨 Client Error") + } + /// 서버 통신 실패 + case .failure(let error): + if let response = error.response { + if let responseData = String(data: response.data, encoding: .utf8) { + print(responseData) + } else { + print(error.localizedDescription) + } + } else { + print(error.localizedDescription) + } + } + } + } + + func request(target : Provider, instance : BaseResponse.Type , completion : @escaping(BaseResponse) -> ()){ + self.request(target) { result in + switch result { + /// 서버 통신 성공 + case .success(let response): + if (200..<300).contains(response.statusCode) { + if let decodeData = try? JSONDecoder().decode(instance, from: response.data) { + completion(decodeData) + } else{ + print("🚨 decoding Error 발생") + } + } else { + print("🚨 Client Error") + } + /// 서버 통신 실패 + case .failure(let error): + if let response = error.response { + if let responseData = String(data: response.data, encoding: .utf8) { + print(responseData) + } else { + print(error.localizedDescription) + } + } else { + print(error.localizedDescription) + } + } + } + } +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Auth/RefreshTokenResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Auth/RefreshTokenResponseDTO.swift new file mode 100644 index 00000000..11deebdd --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Auth/RefreshTokenResponseDTO.swift @@ -0,0 +1,12 @@ +// +// RefreshTokenResponseDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 1/15/24. +// + +import Foundation + +struct RefreshTokebResponseDTO: Codable { + let token: Token +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Auth/SignUpRequestDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Auth/SignUpRequestDTO.swift new file mode 100644 index 00000000..f2633e94 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Auth/SignUpRequestDTO.swift @@ -0,0 +1,31 @@ +// +// SignUpRequestDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 1/14/24. +// + +import Foundation + +struct SignUpRequestDTO: Codable { + let socialPlatform: String + let name: String + let onboarding: Onboarding + let challenge: Challenge +} + +struct Onboarding: Codable { + let averageUseTime: String + let problem: [String] +} + +struct Challenge: Codable { + let period: Int + let goalTime: Int + let apps: [Apps] +} + +struct Apps: Codable { + let appCode: String + let goalTime: Int +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Auth/SignUpResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Auth/SignUpResponseDTO.swift new file mode 100644 index 00000000..e024fafb --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Auth/SignUpResponseDTO.swift @@ -0,0 +1,13 @@ +// +// SignUpResponseDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 1/14/24. +// + +import Foundation + +struct SignUpResponseDTO: Codable { + let userId: Int + let token: Token +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Auth/SocialLoginRequestDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Auth/SocialLoginRequestDTO.swift new file mode 100644 index 00000000..4d61118e --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Auth/SocialLoginRequestDTO.swift @@ -0,0 +1,12 @@ +// +// SocialLoginRequestDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 1/14/24. +// + +import Foundation + +struct SocialLoginRequestDTO: Codable { + let socialPlatform: String +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Auth/SocialLoginResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Auth/SocialLoginResponseDTO.swift new file mode 100644 index 00000000..af6494ef --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Auth/SocialLoginResponseDTO.swift @@ -0,0 +1,18 @@ +// +// SocialLoginResponseDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 1/14/24. +// + +import Foundation + +struct SocialLogineResponseDTO: Codable { + let userId: Int + let token: Token +} + +struct Token: Codable { + let accessToken: String + let refreshToken: String +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/AddAppRequestDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/AddAppRequestDTO.swift new file mode 100644 index 00000000..8f84c1b1 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/AddAppRequestDTO.swift @@ -0,0 +1,12 @@ +// +// AddAppRequestDTO.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/16/24. +// + +import Foundation + +struct AddAppRequestDTO: Codable { + let apps: [Apps] +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/AddAppResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/AddAppResponseDTO.swift new file mode 100644 index 00000000..3071374e --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/AddAppResponseDTO.swift @@ -0,0 +1,12 @@ +// +// AddAppResponseDTO.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/16/24. +// + +import Foundation + +struct AddAppResponseDTO: Codable { + let apps: [Apps] +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/CreateChallengeRequestDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/CreateChallengeRequestDTO.swift new file mode 100644 index 00000000..aaf92cdf --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/CreateChallengeRequestDTO.swift @@ -0,0 +1,12 @@ +// +// CreateChallengeRequestDTO.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/12/24. +// + +import Foundation + +struct CreateChallengeRequestDTO: Codable { + let period, goalTime: Int +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/CreateChallengeResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/CreateChallengeResponseDTO.swift new file mode 100644 index 00000000..7bbe635c --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/CreateChallengeResponseDTO.swift @@ -0,0 +1,16 @@ +// +// CreateChallengeResponseDTO.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/12/24. +// + +import Foundation + +struct CreateChallengeResponseDTO: Codable { + let challengeID: Int + + enum CodingKeys: String, CodingKey { + case challengeID = "challengeId" + } +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/DeleteAppRequestDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/DeleteAppRequestDTO.swift new file mode 100644 index 00000000..757d2c73 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/DeleteAppRequestDTO.swift @@ -0,0 +1,12 @@ +// +// DeleteAppRequestDTO.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/16/24. +// + +import Foundation + +struct DeleteAppRequestDTO: Codable { + let appCode: String +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/EmptyResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/EmptyResponseDTO.swift new file mode 100644 index 00000000..49f5ddbe --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/EmptyResponseDTO.swift @@ -0,0 +1,10 @@ +// +// EmptyResponseDTO.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/16/24. +// + +import Foundation + +struct EmptyResponseDTO: Codable { } diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/GetChallengeResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/GetChallengeResponseDTO.swift new file mode 100644 index 00000000..73c2d0bc --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/GetChallengeResponseDTO.swift @@ -0,0 +1,16 @@ +// +// getChallengeResponseDTO.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/16/24. +// + +import Foundation + +struct GetChallengeResponseDTO: Codable { + let period: Int + let statuses: [String] + let todayIndex: Int + let goalTime: Int + let apps: [Apps] +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/GetHomeChallengeResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/GetHomeChallengeResponseDTO.swift new file mode 100644 index 00000000..c919d9da --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/GetHomeChallengeResponseDTO.swift @@ -0,0 +1,14 @@ +// +// GetHomeChallengeResponseDTO.swift +// HMH_iOS +// +// Created by 김보연 on 1/18/24. +// + +import Foundation + +struct GetHomeChallengeResponseDTO: Codable { + let status: String + let goalTime: Int + let apps: [Apps] +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/HomeChallengeResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/HomeChallengeResponseDTO.swift new file mode 100644 index 00000000..2ab2f2d3 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/HomeChallengeResponseDTO.swift @@ -0,0 +1,12 @@ +// +// HomeChallengeResponseDTO.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/16/24. +// + +import Foundation + +struct HomeChallengeResponseDTO: Codable { + let apps: [Apps] +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Challenge/MidnightRequestDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/MidnightRequestDTO.swift new file mode 100644 index 00000000..7ef73dd9 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Challenge/MidnightRequestDTO.swift @@ -0,0 +1,12 @@ +// +// Midnight.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/16/24. +// + +import Foundation + +struct MidnightRequestDTO: Codable { + let apps: [Apps] +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/MyPage/GetUserDataResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/MyPage/GetUserDataResponseDTO.swift new file mode 100644 index 00000000..f66b8f97 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/MyPage/GetUserDataResponseDTO.swift @@ -0,0 +1,18 @@ +// +// GetUserDataResponseDTO.swift +// HMH_iOS +// +// Created by 김보연 on 1/14/24. +// + +import Foundation + +struct GetUserDataResponseDTO: Codable { + let name: String + let point: Int + + enum CodingKeys: CodingKey { + case name + case point + } +} diff --git a/HMH_iOS/HMH_iOS/Network/Foundation/APIConstants.swift b/HMH_iOS/HMH_iOS/Network/Foundation/APIConstants.swift new file mode 100644 index 00000000..a5c2ba1b --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Foundation/APIConstants.swift @@ -0,0 +1,37 @@ +// +// APIConstants.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/11/24. +// + +import Foundation +import Moya + +struct APIConstants{ + static let contentType = "Content-Type" + static let applicationJSON = "application/json" + static let auth = "Authorization" + // 아래 주석은 네트워크 연결할 때 해제해주세요! + static let accessToken = "Bearer " + static let refreshToken = "Bearer " + static let appleAccessToken = "" + // static let accessToken = "Bearer " + UserManager.shared.accessTokenValue + // static let refreshToken = "Bearer " + UserManager.shared.refreshTokenValue + // static let appleAccessToken = UserManager.shared.appleTokenValue + static let OS = "OS" + static let iOS = "iOS" +} + +extension APIConstants{ + static let hasSocialTokenHeader = [contentType: applicationJSON, + auth : appleAccessToken] + static let hasTokenHeader = [contentType: applicationJSON, + OS: iOS, + auth : accessToken] + static let hasRefreshTokenHeader = [contentType: applicationJSON, + auth : refreshToken] + static let signUpHeader = [contentType: applicationJSON, + auth : appleAccessToken, + OS: iOS,] +} diff --git a/HMH_iOS/HMH_iOS/Network/Foundation/Config.swift b/HMH_iOS/HMH_iOS/Network/Foundation/Config.swift new file mode 100644 index 00000000..bc6ca621 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Foundation/Config.swift @@ -0,0 +1,30 @@ +// +// Config.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/11/24. +// + +import Foundation + +enum Config { + enum Keys { + enum Plist { + static let baseURL = "BASE_URL" + } + } + + private static let infoDictionary: [String: Any] = { + guard let dict = Bundle.main.infoDictionary else { + fatalError("plist cannot found.") + } + return dict + }() + + static let baseURL: String = { + guard let key = Config.infoDictionary[Keys.Plist.baseURL] as? String else { + fatalError("Base URL is not set in plist for this configuration.") + } + return key + }() +} diff --git a/HMH_iOS/HMH_iOS/Network/Foundation/MoyaLoggerPlugin.swift b/HMH_iOS/HMH_iOS/Network/Foundation/MoyaLoggerPlugin.swift new file mode 100644 index 00000000..7eb25662 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Foundation/MoyaLoggerPlugin.swift @@ -0,0 +1,71 @@ +// +// MoyaLoggerPlugin.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/11/24. +// + +import Foundation + +import Foundation +import Moya + +final class MoyaLoggingPlugin: PluginType { + // Request를 보낼 때 호출 + func willSend(_ request: RequestType, target: TargetType) { + guard let httpRequest = request.request else { + print("❌-->유효하지 않은 요청") + return + } + let url = httpRequest.description + let method = httpRequest.httpMethod ?? "unknown method" + var log = "✨✨✨✨✨✨✨✨✨✨✨✨✨✨\n\n[\(method)] \(url)\n\n✨✨✨✨✨✨✨✨✨✨✨✨✨✨\n" + log.append("API: \(target)\n") + if let headers = httpRequest.allHTTPHeaderFields, !headers.isEmpty { + log.append("header: \(headers)\n") + } + if let body = httpRequest.httpBody, let bodyString = String(bytes: body, encoding: String.Encoding.utf8) { + log.append("\(bodyString)\n") + } + log.append("✨✨✨✨✨✨✨✨ END \(method) ✨✨✨✨✨✨✨✨") + print(log) + } + // Response가 왔을 때 + func didReceive(_ result: Result, target: TargetType) { + switch result { + case let .success(response): + onSuceed(response, target: target, isFromError: false) + case let .failure(error): + onFail(error, target: target) + } + } + + func onSuceed(_ response: Response, target: TargetType, isFromError: Bool) { + let request = response.request + let url = request?.url?.absoluteString ?? "nil" + let statusCode = response.statusCode + var log = "✅✅✅✅✅ 네트워크 통신 성공 ✅✅✅✅✅" + log.append("\n[\(statusCode)] \(url)\n----------------------------------------------------\n") + log.append("API: \(target)\n") + response.response?.allHeaderFields.forEach { + log.append("\($0): \($1)\n") + } + if let reString = String(bytes: response.data, encoding: String.Encoding.utf8) { + log.append("\(reString)\n") + } + log.append("✅✅✅✅✅ END HTTP (\(response.data.count)-byte body) ✅✅✅✅✅") + print(log) + } + + func onFail(_ error: MoyaError, target: TargetType) { + if let response = error.response { + onSuceed(response, target: target, isFromError: true) + return + } + var log = "네트워크 오류" + log.append("😭 <-- \(error.errorCode) \(target)\n") + log.append("\(error.failureReason ?? error.errorDescription ?? "unknown error")\n") + log.append("😭 <-- END HTTP") + print(log) + } +} diff --git a/HMH_iOS/HMH_iOS/Network/Foundation/NetworkHelper.swift b/HMH_iOS/HMH_iOS/Network/Foundation/NetworkHelper.swift new file mode 100644 index 00000000..30c119e5 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Foundation/NetworkHelper.swift @@ -0,0 +1,39 @@ +// +// Encodable.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/11/24. +// + +import Foundation + +extension Encodable { + func toDictionary() -> [String: Any] { + do { + let data = try JSONEncoder().encode(self) + let dic = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] + return dic ?? [:] + } catch { + return [:] + } + } +} + +struct NetworkHelper { + private init() {} + + // 상태 코드와 데이터, decoding type을 가지고 통신의 결과를 핸들링하는 함수 + static func parseJSON (by statusCode: Int, data: Data, type: T.Type) -> NetworkResult { + let decoder = JSONDecoder() + + guard let decodedData = try? decoder.decode(BaseResponse.self, from: data) else { return .pathErr } + + switch statusCode { + case 200..<300: return .success(decodedData.data as Any) + case 400..<500: return .requestErr(decodedData.data as Any) + case 500..<600: return .serverErr + default: return .networkFail + } + } + +} diff --git a/HMH_iOS/HMH_iOS/Network/Foundation/NetworkResult.swift b/HMH_iOS/HMH_iOS/Network/Foundation/NetworkResult.swift new file mode 100644 index 00000000..61378b2c --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Foundation/NetworkResult.swift @@ -0,0 +1,68 @@ +// +// NetworkResult.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/11/24. +// + +import Foundation + +import Moya +import Alamofire + +enum NetworkResult { + case success(T) // 서버 통신 성공했을 때, + case requestErr(T) // 요청 에러 발생했을 때, + case decodedErr // 디코딩 오류 발생했을 때, + case pathErr // 경로 에러 발생했을 때, + case authorizationFail(T) // 토큰 인증 오류, + case serverErr // 서버의 내부적 에러가 발생했을 때, + case networkFail // 네트워크 연결 실패했을 때 +} + +enum NetworkError: Error { + case empty + case timeout(Error) + case internetConnection(Error) + case restError(errorCode: String?, errorMessage: String?) +} + +extension NetworkError { + /// `Error` 타입을 `URLError`로 바꿉니다. + static func convertToURLError(_ error: Error) -> URLError? { + switch error { + case let MoyaError.underlying(afError as AFError, _): + fallthrough + case let afError as AFError: + return afError.underlyingError as? URLError + case let MoyaError.underlying(urlError as URLError, _): + fallthrough + case let urlError as URLError: + return urlError + default: + return nil + } + } + + /// 인터넷에 연결되어 있는지를 판별합니다. + static func isNotConnection(error: Error) -> Bool { + Self.convertToURLError(error)?.code == .notConnectedToInternet + } + + /// 중간에 인터넷 연결이 끊어졌는지를 판별합니다. + static func isLostConnection(error: Error) -> Bool { + switch error { + case let AFError.sessionTaskFailed(error: posixError as POSIXError) + where posixError.code == .ECONNABORTED: // eConnAboarted: Software caused connection abort. + break + case let MoyaError.underlying(urlError as URLError, _): + fallthrough + case let urlError as URLError: + guard urlError.code == URLError.networkConnectionLost else { fallthrough } // A client or server connection was severed in the middle of an in-progress load. + break + default: + return false + } + return true + } +} diff --git a/HMH_iOS/HMH_iOS/Network/Foundation/ResponseData.swift b/HMH_iOS/HMH_iOS/Network/Foundation/ResponseData.swift new file mode 100644 index 00000000..e670109f --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Foundation/ResponseData.swift @@ -0,0 +1,49 @@ +// +// ResponseData.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/11/24. +// + +import Foundation +import Moya + +struct ResponseData { + struct CommonResponse: Codable { + let result: Model + } + + static func processResponse(_ result: Result) -> Result { + switch result { + case .success(let response): + do { + // status code가 200...299인 경우만 success로 체크 (아니면 예외발생) + _ = try response.filterSuccessfulStatusCodes() + + let commonResponse = try JSONDecoder().decode(CommonResponse.self, from: response.data) + return .success(commonResponse.result) + } catch { + return .failure(error) + } + + case .failure(let error): + return .failure(error) + } + } + + static func processJSONResponse(_ result: Result) -> Result { + switch result { + case .success(let response): + do { + let model = try JSONDecoder().decode(Model.self, from: response.data) + return .success(model) + } catch { + return .failure(error) + } + case .failure(let error): + + return .failure(error) + } + } + +} diff --git a/HMH_iOS/HMH_iOS/Network/Router/AuthRouter.swift b/HMH_iOS/HMH_iOS/Network/Router/AuthRouter.swift new file mode 100644 index 00000000..f4c73c79 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Router/AuthRouter.swift @@ -0,0 +1,95 @@ +// +// AuthRouter.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 1/14/24. +// + +import Foundation + +import Moya + +enum AuthRouter { + case socialLogin(data: SocialLoginRequestDTO) + case signUp(data: SignUpRequestDTO) + case tokenRefresh + case revoke + case logout +} + +extension AuthRouter: BaseTargetType { + var headers: Parameters? { + switch self { + case .socialLogin: + return APIConstants.hasSocialTokenHeader + case .signUp: + return APIConstants.signUpHeader + case .tokenRefresh: + return APIConstants.hasRefreshTokenHeader + case .revoke: + return APIConstants.hasTokenHeader + case .logout: + return APIConstants.hasTokenHeader + } + } + + var path: String { + switch self { + case .socialLogin: + return "user/login" + case .signUp: + return "user/signup" + case .tokenRefresh: + return "user/reissue" + case .revoke: + return "user" + case .logout: + return "user/logout" + } + } + + var method: Moya.Method { + switch self { + case .socialLogin: + return .post + case .signUp: + return .post + case .tokenRefresh: + return .post + case .revoke: + return .delete + case .logout: + return .post + } + } + + var task: Moya.Task { + switch self { + case .socialLogin(let data): + return .requestJSONEncodable(data) + case .signUp(let data): + return .requestJSONEncodable(data) + case .tokenRefresh: + return .requestPlain + case .revoke: + return .requestPlain + case .logout: + return .requestPlain + } + } + + var validationType: ValidationType { + switch self { + case .socialLogin(data:_) : + return .none + case .signUp(data:_): + return .successCodes + case .tokenRefresh: + return .successCodes + case .revoke: + return .successCodes + case .logout: + return .successCodes + } + } +} diff --git a/HMH_iOS/HMH_iOS/Network/Router/ChallengeRouter.swift b/HMH_iOS/HMH_iOS/Network/Router/ChallengeRouter.swift new file mode 100644 index 00000000..9f4bbcd8 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Router/ChallengeRouter.swift @@ -0,0 +1,98 @@ +// +// ChallengeRouter.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/12/24. +// + +import Foundation + +import Moya + +enum ChallengeRouter { + case createChallenge(data: CreateChallengeRequestDTO) + case dailyChallengeFail + case getChallenge + case getdailyChallenge + case addApp(data: AddAppRequestDTO) + case deleteApp(data: DeleteAppRequestDTO) + case patchdailyChallenge(data: MidnightRequestDTO) +} + +extension ChallengeRouter: BaseTargetType { + var headers: [String : String]? { + switch self { + case .createChallenge: + return APIConstants.hasTokenHeader + case .dailyChallengeFail : + return APIConstants.hasTokenHeader + case .getChallenge: + return APIConstants.hasTokenHeader + case .getdailyChallenge: + return APIConstants.hasTokenHeader + case .addApp: + return APIConstants.hasTokenHeader + case .deleteApp: + return APIConstants.hasTokenHeader + case .patchdailyChallenge: + return APIConstants.hasTokenHeader + } + } + + var path: String { + switch self { + case .createChallenge: + return "challenge" + case .dailyChallengeFail: + return "dailychallenge/failure" + case .getChallenge: + return "challenge" + case .getdailyChallenge: + return "dailychallenge" + case .addApp: + return "app" + case .deleteApp: + return "app" + case .patchdailyChallenge: + return "dailychallenge" + } + } + + var method: Moya.Method { + switch self { + case .createChallenge: + return .post + case .dailyChallengeFail: + return .patch + case .getChallenge: + return .get + case .getdailyChallenge: + return .get + case .addApp: + return .post + case .deleteApp: + return .delete + case .patchdailyChallenge: + return .patch + } + } + + var task: Moya.Task { + switch self { + case .createChallenge(let data): + return .requestJSONEncodable(data) + case .dailyChallengeFail: + return .requestPlain + case .getChallenge: + return .requestPlain + case .getdailyChallenge: + return .requestPlain + case .addApp(let data): + return .requestJSONEncodable(data) + case .deleteApp(let data): + return .requestJSONEncodable(data) + case .patchdailyChallenge(let data): + return .requestJSONEncodable(data) + } + } +} diff --git a/HMH_iOS/HMH_iOS/Network/Router/MyPageRouter.swift b/HMH_iOS/HMH_iOS/Network/Router/MyPageRouter.swift new file mode 100644 index 00000000..9ff31f5d --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Router/MyPageRouter.swift @@ -0,0 +1,46 @@ +// +// MyPageRouter.swift +// HMH_iOS +// +// Created by 김보연 on 1/14/24. +// + +import Foundation + +import Moya + +enum MyPageRouter { + case getUserData +} + +extension MyPageRouter: BaseTargetType { + + var headers: [String : String]? { + switch self { + case .getUserData: + return APIConstants.hasTokenHeader + } + } + + var path: String { + switch self { + case .getUserData: + return "user" + } + } + + var method: Moya.Method { + switch self { + case .getUserData: + return .get + } + } + + var task: Moya.Task { + switch self { + case .getUserData: + return .requestPlain + } + } +} + diff --git a/HMH_iOS/HMH_iOS/Network/Service/Providers.swift b/HMH_iOS/HMH_iOS/Network/Service/Providers.swift new file mode 100644 index 00000000..eea990cf --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Service/Providers.swift @@ -0,0 +1,26 @@ +// +// Providers.swift +// HMH_iOS +// +// Created by 지희의 MAC on 1/12/24. +// + +import Foundation +import Moya + +struct Providers { + static let challengeProvider = NetworkProvider(withAuth: true) + static let myPageProvider = NetworkProvider(withAuth: true) + static let AuthProvider = NetworkProvider(withAuth: false) +} + +extension MoyaProvider { + convenience init(withAuth: Bool) { + if withAuth { + self.init(session: Session(interceptor: AuthInterceptor.shared), + plugins: [MoyaLoggingPlugin()]) + } else { + self.init(plugins: [MoyaLoggingPlugin()]) + } + } +}