diff --git a/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj b/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj index c10ceee..7bef4ef 100644 --- a/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj +++ b/HMH_iOS/HMH_iOS.xcodeproj/project.pbxproj @@ -14,6 +14,14 @@ 0B3C29712BA01C3000435B30 /* MyPageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C29702BA01C3000435B30 /* MyPageView.swift */; }; 0B3C29732BA01DCE00435B30 /* CustomTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C29722BA01DCE00435B30 /* CustomTabView.swift */; }; 0B5140542BE3A2D600C78B9F /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B5140532BE3A2D600C78B9F /* LoginView.swift */; }; + 0B6A835C2C085EFD0095060C /* PointRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6A835B2C085EFD0095060C /* PointRouter.swift */; }; + 0B6A835F2C0861B20095060C /* PointRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6A835E2C0861B20095060C /* PointRequestDTO.swift */; }; + 0B6A83632C0864010095060C /* UsagePointResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6A83622C0864010095060C /* UsagePointResponseDTO.swift */; }; + 0B6A83652C08641D0095060C /* EarnPointResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6A83642C08641D0095060C /* EarnPointResponseDTO.swift */; }; + 0B6A83672C08643B0095060C /* PointListResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6A83662C08643B0095060C /* PointListResponseDTO.swift */; }; + 0B6A83692C08644F0095060C /* UsePointResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6A83682C08644F0095060C /* UsePointResponseDTO.swift */; }; + 0B6A836B2C0864640095060C /* UserPointResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6A836A2C0864640095060C /* UserPointResponseDTO.swift */; }; + 0B6A836E2C08C0520095060C /* HMHToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6A836D2C08C0520095060C /* HMHToastView.swift */; }; 0B719C382BF1C45D00DF1D92 /* CustomAlertModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B719C372BF1C45D00DF1D92 /* CustomAlertModifier.swift */; }; 0B7646BB2BB13F6100C56D7A /* SurveyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B7646BA2BB13F6100C56D7A /* SurveyButton.swift */; }; 0B82ECB02BC9152F002D5CF3 /* MyPageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B82ECAF2BC9152F002D5CF3 /* MyPageViewModel.swift */; }; @@ -260,6 +268,14 @@ 0B3C29702BA01C3000435B30 /* MyPageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageView.swift; sourceTree = ""; }; 0B3C29722BA01DCE00435B30 /* CustomTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTabView.swift; sourceTree = ""; usesTabs = 0; }; 0B5140532BE3A2D600C78B9F /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; + 0B6A835B2C085EFD0095060C /* PointRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointRouter.swift; sourceTree = ""; }; + 0B6A835E2C0861B20095060C /* PointRequestDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointRequestDTO.swift; sourceTree = ""; }; + 0B6A83622C0864010095060C /* UsagePointResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsagePointResponseDTO.swift; sourceTree = ""; }; + 0B6A83642C08641D0095060C /* EarnPointResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EarnPointResponseDTO.swift; sourceTree = ""; }; + 0B6A83662C08643B0095060C /* PointListResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointListResponseDTO.swift; sourceTree = ""; }; + 0B6A83682C08644F0095060C /* UsePointResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsePointResponseDTO.swift; sourceTree = ""; }; + 0B6A836A2C0864640095060C /* UserPointResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPointResponseDTO.swift; sourceTree = ""; }; + 0B6A836D2C08C0520095060C /* HMHToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMHToastView.swift; sourceTree = ""; }; 0B719C372BF1C45D00DF1D92 /* CustomAlertModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAlertModifier.swift; sourceTree = ""; }; 0B7646BA2BB13F6100C56D7A /* SurveyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurveyButton.swift; sourceTree = ""; }; 0B82ECAF2BC9152F002D5CF3 /* MyPageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageViewModel.swift; sourceTree = ""; }; @@ -458,6 +474,27 @@ path = Login; sourceTree = ""; }; + 0B6A835D2C0861930095060C /* Point */ = { + isa = PBXGroup; + children = ( + 0B6A835E2C0861B20095060C /* PointRequestDTO.swift */, + 0B6A83622C0864010095060C /* UsagePointResponseDTO.swift */, + 0B6A83642C08641D0095060C /* EarnPointResponseDTO.swift */, + 0B6A83662C08643B0095060C /* PointListResponseDTO.swift */, + 0B6A83682C08644F0095060C /* UsePointResponseDTO.swift */, + 0B6A836A2C0864640095060C /* UserPointResponseDTO.swift */, + ); + path = Point; + sourceTree = ""; + }; + 0B6A836C2C08C03C0095060C /* Toast */ = { + isa = PBXGroup; + children = ( + 0B6A836D2C08C0520095060C /* HMHToastView.swift */, + ); + path = Toast; + sourceTree = ""; + }; 0B82ECAA2BC9141D002D5CF3 /* MyPage */ = { isa = PBXGroup; children = ( @@ -526,6 +563,7 @@ 0BBF287B2BF2F7EF00101F40 /* Common */ = { isa = PBXGroup; children = ( + 0B6A836C2C08C03C0095060C /* Toast */, 0B205B332BFCC15C00B0FB83 /* Manager */, 0BBF287C2BF2F7F400101F40 /* Alert */, ); @@ -761,6 +799,7 @@ 365CD6E82B7E501000245CDD /* DTO */ = { isa = PBXGroup; children = ( + 0B6A835D2C0861930095060C /* Point */, 367243D82BEDEAC9007A5A7B /* Auth */, 367243D92BEDEAD2007A5A7B /* Challenge */, 367243FF2BEDEBC6007A5A7B /* MyPage */, @@ -787,6 +826,7 @@ 367244022BEDEC4A007A5A7B /* AuthRouter.swift */, 367244032BEDEC4A007A5A7B /* ChallengeRouter.swift */, 367244042BEDEC4A007A5A7B /* MyPageRouter.swift */, + 0B6A835B2C085EFD0095060C /* PointRouter.swift */, ); path = Router; sourceTree = ""; @@ -1208,16 +1248,20 @@ 0B3C296D2BA01C2000435B30 /* ChallengeView.swift in Sources */, 367243B22BE9ABCC007A5A7B /* ChallengeViewModel.swift in Sources */, 0BDDA0142C005A25001BD43E /* KeyChainStorage.swift in Sources */, + 0B6A83692C08644F0095060C /* UsePointResponseDTO.swift in Sources */, 3601C8362BC6E8FB005790F7 /* HomeViewModel.swift in Sources */, + 0B6A83672C08643B0095060C /* PointListResponseDTO.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 */, + 0B6A835C2C085EFD0095060C /* PointRouter.swift in Sources */, 367244132BF086A7007A5A7B /* AuthInterceptor.swift in Sources */, 367243F62BEDEB32007A5A7B /* DeleteAppRequestDTO.swift in Sources */, 368CAADF2BB9975C00FA83B3 /* NavigationBarView.swift in Sources */, + 0B6A835F2C0861B20095060C /* PointRequestDTO.swift in Sources */, 0B3C296B2BA01BD200435B30 /* TabBarView.swift in Sources */, 367243F42BEDEB32007A5A7B /* AddAppResponseDTO.swift in Sources */, 367244052BEDEC4A007A5A7B /* AuthRouter.swift in Sources */, @@ -1226,6 +1270,7 @@ 0B5140542BE3A2D600C78B9F /* LoginView.swift in Sources */, 0BC0E5B32BB04BC600FB0330 /* GoalPeriodView.swift in Sources */, 0B86937D2BE727E5000D7CE1 /* LoginViewModel.swift in Sources */, + 0B6A836B2C0864640095060C /* UserPointResponseDTO.swift in Sources */, 0B86937F2BE87A5F000D7CE1 /* LoginButton.swift in Sources */, 367243E22BEDEAF8007A5A7B /* SocialLoginRequestDTO.swift in Sources */, 367244012BEDEBD8007A5A7B /* GetUserDataResponseDTO.swift in Sources */, @@ -1238,11 +1283,13 @@ 0BC0E5BD2BB0571E00FB0330 /* NextButtonView.swift in Sources */, 367244ED2BF3E778007A5A7B /* NotificationManager.swift in Sources */, 367244152BF0956B007A5A7B /* PointView.swift in Sources */, + 0B6A83632C0864010095060C /* UsagePointResponseDTO.swift in Sources */, 0BC0E5A92BB03EE400FB0330 /* OnboardingModel.swift in Sources */, 0B8693772BE5CB46000D7CE1 /* SwipeView.swift in Sources */, 0BBF28822BF2F82500101F40 /* UnlockCompleteAlertView.swift in Sources */, 0B86937B2BE727DA000D7CE1 /* SocialLoginModel.swift in Sources */, 0BD2D6782B9F39EF00733843 /* Font.swift in Sources */, + 0B6A83652C08641D0095060C /* EarnPointResponseDTO.swift in Sources */, 367244172BF095AF007A5A7B /* PointViewModel.swift in Sources */, 0B205B352BFCC16A00B0FB83 /* UserManager.swift in Sources */, 0B7646BB2BB13F6100C56D7A /* SurveyButton.swift in Sources */, @@ -1264,6 +1311,7 @@ 367243FB2BEDEB32007A5A7B /* CreateChallengeRequestDTO.swift in Sources */, 0BBF28862BF2F84700101F40 /* WithdrawAlertView.swift in Sources */, 0BBF28802BF2F81A00101F40 /* UsePointsAlertView.swift in Sources */, + 0B6A836E2C08C0520095060C /* HMHToastView.swift in Sources */, 369D7EE52C04AE2000295791 /* ScreenTimeViewModel.swift in Sources */, 367243F82BEDEB32007A5A7B /* GetChallengeResponseDTO.swift in Sources */, 0B9834DC2BC8234700A1457A /* SplashView.swift in Sources */, diff --git a/HMH_iOS/HMH_iOS/Assets.xcassets/toast.colorset/Contents.json b/HMH_iOS/HMH_iOS/Assets.xcassets/toast.colorset/Contents.json new file mode 100644 index 0000000..03e9e5b --- /dev/null +++ b/HMH_iOS/HMH_iOS/Assets.xcassets/toast.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.750", + "blue" : "0x48", + "green" : "0x39", + "red" : "0x36" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HMH_iOS/HMH_iOS/Global/Struct/CustomAlertModifier.swift b/HMH_iOS/HMH_iOS/Global/Struct/CustomAlertModifier.swift index 7d4b5d6..15fa86f 100644 --- a/HMH_iOS/HMH_iOS/Global/Struct/CustomAlertModifier.swift +++ b/HMH_iOS/HMH_iOS/Global/Struct/CustomAlertModifier.swift @@ -5,10 +5,9 @@ // Created by Seonwoo Kim on 5/13/24. // - import SwiftUI -enum CustoAlertButtonType { +enum CustomAlertButtonType { case Confirm case Cancel } @@ -83,28 +82,28 @@ enum CustomAlertType { struct CustomAlertModifier: ViewModifier { @Binding var isPresent: Bool - - let alert: CustomAlertView + let alert: () -> CustomAlertView func body(content: Content) -> some View { content - .fullScreenCover(isPresented: $isPresent) { - alert - } - .transaction { transaction in - transaction.disablesAnimations = true - } + .overlay( + ZStack { + if isPresent { + alert() + } + } + ) } } struct CustomAlertButtonView: View { - typealias Action = () -> () + typealias Action = () -> Void @Binding var isPresented: Bool var action: Action - var buttonType : CustoAlertButtonType - var alertType : CustomAlertType + var buttonType: CustomAlertButtonType + var alertType: CustomAlertType private var buttonBackgroundColor: Color { switch (buttonType, alertType) { @@ -117,7 +116,7 @@ struct CustomAlertButtonView: View { } } - init(buttonType: CustoAlertButtonType, + init(buttonType: CustomAlertButtonType, alertType: CustomAlertType, isPresented: Binding, action: @escaping Action) { @@ -185,18 +184,14 @@ struct CustomAlertView: View { } } - - extension View { - func customAlert(isPresented:Binding, customAlert: @escaping () -> CustomAlertView) -> some View { - return modifier(CustomAlertModifier(isPresent: isPresented, alert: customAlert())) + func customAlert(isPresented: Binding, customAlert: @escaping () -> CustomAlertView) -> some View { + self.modifier(CustomAlertModifier(isPresent: isPresented, alert: customAlert)) } } struct ClearBackground: UIViewRepresentable { - func makeUIView(context: Context) -> UIView { - let view = ClearBackgroundView() DispatchQueue.main.async { view.superview?.superview?.backgroundColor = .clear diff --git a/HMH_iOS/HMH_iOS/Global/Struct/CustomNavigationBarModifier.swift b/HMH_iOS/HMH_iOS/Global/Struct/CustomNavigationBarModifier.swift index 7093f9c..b23c77f 100644 --- a/HMH_iOS/HMH_iOS/Global/Struct/CustomNavigationBarModifier.swift +++ b/HMH_iOS/HMH_iOS/Global/Struct/CustomNavigationBarModifier.swift @@ -8,8 +8,8 @@ import SwiftUI extension View { - func customNavigationBar(title: String, showBackButton: Bool, showPointButton: Bool, isPointView: Bool = false) -> some View { - self.modifier(CustomNavigationBarModifier(title: title, + func customNavigationBar(title: String, showBackButton: Bool, showPointButton: Bool, isPointView: Bool = false, point: Int) -> some View { + self.modifier(CustomNavigationBarModifier(title: title, point: point, showBackButton: showBackButton, showPointButton: showPointButton, isPointView: isPointView)) @@ -18,6 +18,7 @@ extension View { struct CustomNavigationBarModifier: ViewModifier { let title: String + var point: Int var showBackButton: Bool var showPointButton: Bool var isPointView: Bool @@ -28,7 +29,7 @@ struct CustomNavigationBarModifier: ViewModifier { NavigationBarView(showBackButton: showBackButton, showPointButton: showPointButton, isPointView: isPointView, - title: title) + title: title, point: point) content .toolbar(.hidden) } diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Point/EarnPointResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Point/EarnPointResponseDTO.swift new file mode 100644 index 0000000..1a2a0f9 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Point/EarnPointResponseDTO.swift @@ -0,0 +1,12 @@ +// +// EarnPointResponseDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 5/30/24. +// + +import Foundation + +struct EarnPointResponseDTO: Codable { + let point: Int +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Point/PointListResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Point/PointListResponseDTO.swift new file mode 100644 index 0000000..e2495c1 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Point/PointListResponseDTO.swift @@ -0,0 +1,19 @@ +// +// PointListResponseDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 5/30/24. +// + +import Foundation + +struct PointListResponseDTO: Codable { + let point: Int + let period: Int + let challengePointStatuses: [PointList] +} + +struct PointList: Codable { + let challengeDate: String + let status: String +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Point/PointRequestDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Point/PointRequestDTO.swift new file mode 100644 index 0000000..23bbbf8 --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Point/PointRequestDTO.swift @@ -0,0 +1,12 @@ +// +// EarnPointRequestDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 5/30/24. +// + +import Foundation + +struct PointRequestDTO: Codable { + let challengeDate: String +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Point/UsagePointResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Point/UsagePointResponseDTO.swift new file mode 100644 index 0000000..c6549cc --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Point/UsagePointResponseDTO.swift @@ -0,0 +1,12 @@ +// +// UsagePointDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 5/30/24. +// + +import Foundation + +struct UsagePointResponseDTO: Codable { + let point: Int +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Point/UsePointResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Point/UsePointResponseDTO.swift new file mode 100644 index 0000000..501d17d --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Point/UsePointResponseDTO.swift @@ -0,0 +1,12 @@ +// +// UsePointResponseDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 5/30/24. +// + +import Foundation + +struct UsePointResponseDTO: Codable { + let challengeDate: String +} diff --git a/HMH_iOS/HMH_iOS/Network/DTO/Point/UserPointResponseDTO.swift b/HMH_iOS/HMH_iOS/Network/DTO/Point/UserPointResponseDTO.swift new file mode 100644 index 0000000..3071fdc --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/DTO/Point/UserPointResponseDTO.swift @@ -0,0 +1,13 @@ +// +// UserPointResponseDTO.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 5/30/24. +// + +import Foundation + +struct UserPointResponseDTO: Codable { + let point: Int +} + diff --git a/HMH_iOS/HMH_iOS/Network/Foundation/APIConstants.swift b/HMH_iOS/HMH_iOS/Network/Foundation/APIConstants.swift index a330af4..362c289 100644 --- a/HMH_iOS/HMH_iOS/Network/Foundation/APIConstants.swift +++ b/HMH_iOS/HMH_iOS/Network/Foundation/APIConstants.swift @@ -36,6 +36,8 @@ extension APIConstants{ static let hasTokenHeader = [contentType: applicationJSON, OS: iOS, auth : accessToken] + static let hasAccessTokenHeader = [contentType: applicationJSON, + auth : accessToken] static let hasRefreshTokenHeader = [contentType: applicationJSON, auth : refreshToken] static let signUpHeader = [contentType: applicationJSON, diff --git a/HMH_iOS/HMH_iOS/Network/Router/PointRouter.swift b/HMH_iOS/HMH_iOS/Network/Router/PointRouter.swift new file mode 100644 index 0000000..d2b936d --- /dev/null +++ b/HMH_iOS/HMH_iOS/Network/Router/PointRouter.swift @@ -0,0 +1,80 @@ +// +// PointRouter.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 5/30/24. +// + +import Foundation + +import Moya + +enum PointRouter { + case getUsagePoint + case patchEarnPoint(data: PointRequestDTO) + case getPointList + case patchPointUse(data: PointRequestDTO) + case getCurrentPoint(data: PointRequestDTO) +} + +extension PointRouter: BaseTargetType { + var headers: [String : String]? { + switch self { + case .getUsagePoint: + return APIConstants.hasAccessTokenHeader + case .patchEarnPoint : + return APIConstants.hasTokenHeader + case .getPointList: + return APIConstants.hasAccessTokenHeader + case .patchPointUse: + return APIConstants.hasAccessTokenHeader + case .getCurrentPoint: + return APIConstants.hasAccessTokenHeader + } + } + + var path: String { + switch self { + case .getUsagePoint: + return "point" + case .patchEarnPoint : + return "point/earn" + case .getPointList: + return "point/list" + case .patchPointUse: + return "point/use" + case .getCurrentPoint: + return "user/point" + } + } + + var method: Moya.Method { + switch self { + case .getUsagePoint: + return .get + case .patchEarnPoint : + return .patch + case .getPointList: + return .get + case .patchPointUse: + return .patch + case .getCurrentPoint: + return .get + } + } + + var task: Moya.Task { + switch self { + case .getUsagePoint: + return .requestPlain + case .patchEarnPoint(let data) : + return .requestJSONEncodable(data) + case .patchPointUse(let data): + return .requestJSONEncodable(data) + case .getPointList: + return .requestPlain + case .getCurrentPoint(let data): + return .requestJSONEncodable(data) + } + } +} diff --git a/HMH_iOS/HMH_iOS/Network/Service/Providers.swift b/HMH_iOS/HMH_iOS/Network/Service/Providers.swift index eea990c..5e9037f 100644 --- a/HMH_iOS/HMH_iOS/Network/Service/Providers.swift +++ b/HMH_iOS/HMH_iOS/Network/Service/Providers.swift @@ -12,6 +12,7 @@ struct Providers { static let challengeProvider = NetworkProvider(withAuth: true) static let myPageProvider = NetworkProvider(withAuth: true) static let AuthProvider = NetworkProvider(withAuth: false) + static let pointProvider = NetworkProvider(withAuth: false) } extension MoyaProvider { diff --git a/HMH_iOS/HMH_iOS/Presentation/Challenge/ViewModels/PointViewModel.swift b/HMH_iOS/HMH_iOS/Presentation/Challenge/ViewModels/PointViewModel.swift index 9f2be6e..a9a17bc 100644 --- a/HMH_iOS/HMH_iOS/Presentation/Challenge/ViewModels/PointViewModel.swift +++ b/HMH_iOS/HMH_iOS/Presentation/Challenge/ViewModels/PointViewModel.swift @@ -8,5 +8,57 @@ import Foundation final class PointViewModel: ObservableObject { - @Published var challengeDay = 14 + @Published var challengeDay = 1 + @Published var currentPoint = 0 + @Published var pointList: [PointList] = [] + @Published var isPresented = false + + func getUsagePoint() { + Providers.pointProvider.request(target: .getUsagePoint, + instance: BaseResponse.self) { result in + guard let data = result.data else { return } + } + } + // 앱 잠금해제시에 사용될 포인트를 조회하는 api입니다. + + func patchEarnPoint(day: Int) { + let date = pointList[day].challengeDate + let request = PointRequestDTO(challengeDate: date) + Providers.pointProvider.request(target: .patchEarnPoint(data: request), + instance: BaseResponse.self) { result in + guard let data = result.data else { return } + self.isPresented = true + } + } + // 하루하루 챌린지를 성공하고, 포인트를 받는 버튼을 눌렀을 때, 포인트를 받는 API + + func getPointList() { + Providers.pointProvider.request(target: .getPointList, + instance: BaseResponse.self) { result in + guard let data = result.data else { return } + self.challengeDay = data.period + self.currentPoint = data.point + self.pointList = data.challengePointStatuses + } + } + // 챌린지 보상 수령 여부를 리스트로 조회하는 api입니다. + + func patchPointUse(day: Int) { + let date = pointList[day].challengeDate + let request = PointRequestDTO(challengeDate: date) + Providers.pointProvider.request(target: .patchPointUse(data: request), + instance: BaseResponse.self) { result in + guard let data = result.data else { return } + } + } + // 포인트를 사용해 이용시간 잠금을 해제할 때 사용하는 api + + func getCurrentPoint(date: String) { + let request = PointRequestDTO(challengeDate: date) + Providers.pointProvider.request(target: .getCurrentPoint(data: request), + instance: BaseResponse.self) { result in + guard let data = result.data else { return } + } + } + // 현재 유저 포인트 불러오기 } diff --git a/HMH_iOS/HMH_iOS/Presentation/Challenge/Views/ChallengeView.swift b/HMH_iOS/HMH_iOS/Presentation/Challenge/Views/ChallengeView.swift index 09b7acb..2aa9b91 100644 --- a/HMH_iOS/HMH_iOS/Presentation/Challenge/Views/ChallengeView.swift +++ b/HMH_iOS/HMH_iOS/Presentation/Challenge/Views/ChallengeView.swift @@ -54,7 +54,7 @@ extension ChallengeView { } .customNavigationBar(title: StringLiteral.NavigationBar.challenge, showBackButton: false, - showPointButton: true) + showPointButton: true, point: 0) .background(.blackground) .onAppear { viewModel.getChallengeInfo() diff --git a/HMH_iOS/HMH_iOS/Presentation/Challenge/Views/PointView.swift b/HMH_iOS/HMH_iOS/Presentation/Challenge/Views/PointView.swift index 41f7ab5..027bc2c 100644 --- a/HMH_iOS/HMH_iOS/Presentation/Challenge/Views/PointView.swift +++ b/HMH_iOS/HMH_iOS/Presentation/Challenge/Views/PointView.swift @@ -8,16 +8,12 @@ import SwiftUI struct PointView: View { - @State var viewModel = PointViewModel() - - public init(viewModel: PointViewModel) { - self.viewModel = viewModel - } + @StateObject var viewModel = PointViewModel() public var body: some View { main .onAppear { - + viewModel.getPointList() } } } @@ -29,35 +25,29 @@ extension PointView { .padding(.vertical, 16) .padding(.horizontal, 20) } + .showToast(toastType: .earnPoint, isPresented: $viewModel.isPresented) .customNavigationBar(title: StringLiteral.NavigationBar.point, showBackButton: true, showPointButton: true, - isPointView: true) + isPointView: true, point: viewModel.currentPoint) .background(.blackground) .navigationBarHidden(true) } private var listView: some View { - ForEach(1...viewModel.challengeDay + 1, id: \.self) { day in - HStack{ - VStack(alignment: .leading){ + ForEach(1...viewModel.challengeDay, id: \.self) { day in + HStack { + VStack(alignment: .leading) { Text("\(day)" + StringLiteral.Challenge.pointTitle) .font(.text4_semibold_16) - .foregroundStyle(.whiteText) + .foregroundColor(.whiteText) .padding(.bottom, 2) Text("\(viewModel.challengeDay)" + StringLiteral.Challenge.pointSubTitle) .font(.detail4_medium_12) - .foregroundStyle(.gray2) + .foregroundColor(.gray2) } Spacer() - Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: { - Text(StringLiteral.Challenge.pointButton) - .font(.text4_semibold_16) - .foregroundStyle(.whiteBtn) - .frame(width: 73, height: 40) - .background(.bluePurpleButton) - .clipShape(RoundedRectangle(cornerSize: CGSize(width: 3, height: 3))) - }) + EarnPointButton(day: day, viewModel: viewModel) } .frame(height: 80) } @@ -67,3 +57,22 @@ extension PointView { #Preview { PointView(viewModel: .init()) } + +struct EarnPointButton: View { + let day: Int + @ObservedObject var viewModel: PointViewModel + + var body: some View { + Button(action: { + viewModel.patchEarnPoint(day: day) + }, label: { + Text(StringLiteral.Challenge.pointButton) + .font(.text4_semibold_16) + .foregroundStyle(.whiteBtn) + .frame(width: 73, height: 40) + .background(.bluePurpleButton) + .clipShape(RoundedRectangle(cornerSize: CGSize(width: 3, height: 3))) + }) + } +} + diff --git a/HMH_iOS/HMH_iOS/Presentation/Common/Toast/HMHToastView.swift b/HMH_iOS/HMH_iOS/Presentation/Common/Toast/HMHToastView.swift new file mode 100644 index 0000000..068a8bd --- /dev/null +++ b/HMH_iOS/HMH_iOS/Presentation/Common/Toast/HMHToastView.swift @@ -0,0 +1,100 @@ +// +// HMHToastView.swift +// HMH_iOS +// +// Created by Seonwoo Kim on 5/30/24. +// + +import SwiftUI + +enum ToastType { + case pointWarn + case onboardingWarn + case earnPoint +} + +struct HMHToastView: View { + var toastType: ToastType + + @Binding var isPresented: Bool + + var body: some View { + VStack { + Spacer() + toastContentView() + .transition(.move(edge: .bottom)) + .frame(width: 328, height: 48) + .background(.toast) + .cornerRadius(43) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + withAnimation { + isPresented = false + } + } + } + } + .padding(.bottom, 30) + } + + @ViewBuilder + private func toastContentView() -> some View { + switch toastType { + case .pointWarn: + pointWarnView() + case .onboardingWarn: + onboardingWarnView() + case .earnPoint: + earnPointView() + } + } + + private func earnPointView() -> some View { + HStack { + Text("포인트를 획득했어요!") + .foregroundColor(.whiteBtn) + .font(.text6_medium_14) + } + } + + private func onboardingWarnView() -> some View { + HStack { + Text("오류입니다.") + .foregroundColor(.whiteBtn) + .font(.text6_medium_14) + } + } + + private func pointWarnView() -> some View { + HStack { + Text("포인트를 다 받은 후 챌린지를 생성하세요") + .foregroundColor(.whiteBtn) + .font(.text6_medium_14) + .padding(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)) + Spacer() + NavigationLink(destination: PointView()) { + Text("이동") + .font(.text4_semibold_16) + .foregroundColor(.bluePurpleText) + } + .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 20)) + } + } +} + +extension View { + func showToast(toastType: ToastType, isPresented: Binding) -> some View { + ZStack { + self + if isPresented.wrappedValue { + VStack { + Spacer() + HMHToastView(toastType: toastType, isPresented: isPresented) + .padding(.bottom, 30) + } + .transition(.move(edge: .bottom)) + .animation(.easeInOut, value: isPresented.wrappedValue) + } + } + } +} diff --git a/HMH_iOS/HMH_iOS/Presentation/Home/Views/HomeView.swift b/HMH_iOS/HMH_iOS/Presentation/Home/Views/HomeView.swift index 822c8dd..fcb564f 100644 --- a/HMH_iOS/HMH_iOS/Presentation/Home/Views/HomeView.swift +++ b/HMH_iOS/HMH_iOS/Presentation/Home/Views/HomeView.swift @@ -35,7 +35,7 @@ struct HomeView: View { } .customNavigationBar(title: StringLiteral.NavigationBar.home, showBackButton: false, - showPointButton: false) + showPointButton: false, point: 0) .background(.blackground) .onAppear { screenTimeViewModel.requestAuthorization() diff --git a/HMH_iOS/HMH_iOS/Presentation/NavigationBarView.swift b/HMH_iOS/HMH_iOS/Presentation/NavigationBarView.swift index de72f8e..0a0e10f 100644 --- a/HMH_iOS/HMH_iOS/Presentation/NavigationBarView.swift +++ b/HMH_iOS/HMH_iOS/Presentation/NavigationBarView.swift @@ -14,7 +14,7 @@ struct NavigationBarView: View { let showPointButton: Bool let isPointView: Bool let title: String - let point = 100 + let point: Int var body: some View { ZStack { @@ -103,5 +103,5 @@ extension NavigationBarView { } #Preview { - NavigationBarView(showBackButton: false, showPointButton: true, isPointView: false, title: "마이페이지") + NavigationBarView(showBackButton: false, showPointButton: true, isPointView: false, title: "마이페이지", point: 100) } diff --git a/HMH_iOS/HMH_iOS/Presentation/Onboarding/ViewModels/OnboardingViewModel.swift b/HMH_iOS/HMH_iOS/Presentation/Onboarding/ViewModels/OnboardingViewModel.swift index 715a26a..ee55bb1 100644 --- a/HMH_iOS/HMH_iOS/Presentation/Onboarding/ViewModels/OnboardingViewModel.swift +++ b/HMH_iOS/HMH_iOS/Presentation/Onboarding/ViewModels/OnboardingViewModel.swift @@ -22,6 +22,12 @@ class OnboardingViewModel: ObservableObject { @Published var isCompleted: Bool + @Published + var isOnboardingError : Bool = false + + @Published + var isCompletePresented: Bool = false + @Published var selectedGoalTime: String @@ -78,9 +84,7 @@ class OnboardingViewModel: ObservableObject { case 3: self.goalTime = convertToTotalMilliseconds(hour: selectedGoalTime, minute: "0") if isChallengeMode { - print("isChallengeMode") - postCreateChallengeData() - addOnboardingState() + isCompletePresented = true } else { addOnboardingState() } @@ -95,13 +99,17 @@ class OnboardingViewModel: ObservableObject { case 6: self.appGoalTime = convertToTotalMilliseconds(hour: selectedAppHour, minute: selectedAppMinute) postSignUpLoginData() - addOnboardingState() offIsCompleted() default: break } } + func alertAction() { + postCreateChallengeData() + addOnboardingState() + } + func addOnboardingState() { onboardingState += 1 } @@ -154,9 +162,9 @@ class OnboardingViewModel: ObservableObject { UserManager.shared.accessToken = data.data?.token.accessToken ?? "" UserManager.shared.refreshToken = data.data?.token.refreshToken ?? "" } else if data.message == "이미 회원가입된 유저입니다." { - UserManager.shared.appStateString = "login" + self.isOnboardingError = true } else { - self.onboardingState = 0 + self.isOnboardingError = true } } } diff --git a/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/GoalTimeView.swift b/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/GoalTimeView.swift index f330379..85ed689 100644 --- a/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/GoalTimeView.swift +++ b/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/GoalTimeView.swift @@ -9,7 +9,7 @@ import SwiftUI struct GoalTimeView: View { - var times = ["2", "3", "4", "5", "6"] + var times = ["1", "2", "3", "4", "5", "6"] @ObservedObject var viewModel: OnboardingViewModel var body: some View { diff --git a/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingContentView.swift b/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingContentView.swift index 84136da..1e67f60 100644 --- a/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingContentView.swift +++ b/HMH_iOS/HMH_iOS/Presentation/Onboarding/Views/OnboardingContentView.swift @@ -47,6 +47,32 @@ struct OnboardingContentView: View { self.presentationMode.wrappedValue.dismiss() } } + .showToast(toastType: .onboardingWarn, isPresented: $onboardingViewModel.isOnboardingError) + .customAlert( + isPresented: $onboardingViewModel.isCompletePresented, + customAlert: { + CustomAlertView( + alertType: .challengeCreationComplete, + confirmBtn: CustomAlertButtonView( + buttonType: .Confirm, + alertType: .challengeCreationComplete, + isPresented: $onboardingViewModel.isCompletePresented, + action: { + onboardingViewModel.alertAction() + } + ), + cancelBtn: CustomAlertButtonView( + buttonType: .Cancel, + alertType: .challengeCreationComplete, + isPresented: $onboardingViewModel.isCompletePresented, + action: { + onboardingViewModel.alertAction() + } + ) + ) + } + ) + } }