diff --git a/Backend/febird-api/src/exercise/exercise.controller.ts b/Backend/febird-api/src/exercise/exercise.controller.ts index f0e3f889..46a06f4f 100644 --- a/Backend/febird-api/src/exercise/exercise.controller.ts +++ b/Backend/febird-api/src/exercise/exercise.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Param } from '@nestjs/common'; +99999999import { Controller, Get, Param } from '@nestjs/common'; import { ExerciseService } from './exercise.service'; @Controller('exercise') diff --git a/Backend/febird-api/src/exercise/exercise.entity.ts b/Backend/febird-api/src/exercise/exercise.entity.ts index 5b267ca7..81cf8376 100644 --- a/Backend/febird-api/src/exercise/exercise.entity.ts +++ b/Backend/febird-api/src/exercise/exercise.entity.ts @@ -20,4 +20,4 @@ export class Exercise { @OneToMany(() => Routine, (routine) => routine.exercise) routines: Routine[]; -} \ No newline at end of file +} diff --git a/ColorChipsData.zip b/ColorChipsData.zip new file mode 100644 index 00000000..ba5b67b5 Binary files /dev/null and b/ColorChipsData.zip differ diff --git a/Frontend-iOS/FebirdApp/FebirdApp.xcodeproj/project.pbxproj b/Frontend-iOS/FebirdApp/FebirdApp.xcodeproj/project.pbxproj index c0c05fe8..812b3279 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp.xcodeproj/project.pbxproj +++ b/Frontend-iOS/FebirdApp/FebirdApp.xcodeproj/project.pbxproj @@ -59,7 +59,6 @@ 8F0F48062C63723F004E3B86 /* RoutineViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0F48052C63723F004E3B86 /* RoutineViewModel.swift */; }; 8F0F48082C637261004E3B86 /* LevelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0F48072C637261004E3B86 /* LevelViewModel.swift */; }; 8F0F480A2C6372EA004E3B86 /* ExerciseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0F48092C6372EA004E3B86 /* ExerciseViewModel.swift */; }; - 8F0F48132C637905004E3B86 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 8F0F48122C637905004E3B86 /* Alamofire */; }; 8F0F48152C63795A004E3B86 /* HistoryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0F48142C63795A004E3B86 /* HistoryViewModel.swift */; }; 8F0F48172C637985004E3B86 /* MemberViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0F48162C637985004E3B86 /* MemberViewModel.swift */; }; 8F8A77E72C5E7AF9008E61D7 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F8A77E62C5E7AF9008E61D7 /* SettingsViewModel.swift */; }; @@ -67,6 +66,7 @@ 8F8A77EC2C5F554F008E61D7 /* UserProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F8A77EB2C5F554F008E61D7 /* UserProfile.swift */; }; 8F8A77EE2C5F56BD008E61D7 /* ProfileSettingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F8A77ED2C5F56BD008E61D7 /* ProfileSettingViewModel.swift */; }; 8F8A77F02C5F734B008E61D7 /* SettingHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F8A77EF2C5F734B008E61D7 /* SettingHeaderView.swift */; }; + 8F910D7E2CB7926600FCDB6A /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 8F910D7D2CB7926600FCDB6A /* Alamofire */; }; 8F92DF7A2C4B93730071F336 /* ExerciseGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F92DF792C4B93730071F336 /* ExerciseGuideView.swift */; }; 8F92DF7C2C4B9A390071F336 /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F92DF7B2C4B9A390071F336 /* CustomNavigationBar.swift */; }; 8F92DF7E2C4BA9750071F336 /* ExerciseGuideListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F92DF7D2C4BA9750071F336 /* ExerciseGuideListView.swift */; }; @@ -341,7 +341,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8F0F48132C637905004E3B86 /* Alamofire in Frameworks */, + 8F910D7E2CB7926600FCDB6A /* Alamofire in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -918,7 +918,7 @@ ); name = FebirdApp; packageProductDependencies = ( - 8F0F48122C637905004E3B86 /* Alamofire */, + 8F910D7D2CB7926600FCDB6A /* Alamofire */, ); productName = FebirdApp; productReference = 3EF6F0492C36937E00EEF18F /* FebirdApp.app */; @@ -994,7 +994,7 @@ mainGroup = 3EF6F0402C36937D00EEF18F; packageReferences = ( 8F0F48102C6375A9004E3B86 /* XCRemoteSwiftPackageReference "SwiftLintPlugins" */, - 8F0F48112C637905004E3B86 /* XCRemoteSwiftPackageReference "Alamofire" */, + 8F910D7C2CB7926600FCDB6A /* XCRemoteSwiftPackageReference "Alamofire" */, ); productRefGroup = 3EF6F04A2C36937E00EEF18F /* Products */; projectDirPath = ""; @@ -1561,7 +1561,7 @@ minimumVersion = 0.56.1; }; }; - 8F0F48112C637905004E3B86 /* XCRemoteSwiftPackageReference "Alamofire" */ = { + 8F910D7C2CB7926600FCDB6A /* XCRemoteSwiftPackageReference "Alamofire" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Alamofire/Alamofire.git"; requirement = { @@ -1572,9 +1572,9 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 8F0F48122C637905004E3B86 /* Alamofire */ = { + 8F910D7D2CB7926600FCDB6A /* Alamofire */ = { isa = XCSwiftPackageProductDependency; - package = 8F0F48112C637905004E3B86 /* XCRemoteSwiftPackageReference "Alamofire" */; + package = 8F910D7C2CB7926600FCDB6A /* XCRemoteSwiftPackageReference "Alamofire" */; productName = Alamofire; }; /* End XCSwiftPackageProductDependency section */ diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseDetector.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseDetector.swift index 3bfccef6..175403bf 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseDetector.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseDetector.swift @@ -9,24 +9,30 @@ import SwiftUI import Vision import AVFoundation +/** + - Vision: 머신 비전 프레임워크로, 이미지 분석 및 비디오 처리에 사용할 수 있습니다. 이 코드는 사람의 신체 포즈를 인식하는 데 사용됩니다. + - AVFoundation: 비디오와 오디오 캡처 및 처리를 위한 프레임워크입니다. 카메라 세션을 설정하고 비디오 데이터를 캡처합니다. + - Combine: @Published 속성을 사용하여 데이터의 변화를 관찰하고, UI와의 바인딩을 쉽게 관리합니다. + */ + class ExerciseDetector: NSObject, ObservableObject { - @Published var currentExercise: ExerciseType = .overheadClap - @Published var count: Int = 0 - @Published var cameraPermissionStatus: AVAuthorizationStatus = .notDetermined - @Published var isDetecting: Bool = false - @Published var currentJoints: [VNHumanBodyPoseObservation.JointName] = [] - @Published var lastObservation: VNHumanBodyPoseObservation? + @Published var currentExercise: ExerciseType = .overheadClap // 현재 운동 종류 + @Published var count: Int = 0 // 운동 동작 카운트 + @Published var cameraPermissionStatus: AVAuthorizationStatus = .notDetermined // 카메라 권한 상태 + @Published var isDetecting: Bool = false // 현재 동작 인식 여부 + @Published var currentJoints: [VNHumanBodyPoseObservation.JointName] = [] // 현재 인식된 관절 목록 + @Published var lastObservation: VNHumanBodyPoseObservation? // 마지막 관절 관측 결과 - var captureSession: AVCaptureSession? - var videoDataOutput: AVCaptureVideoDataOutput? - var previewLayer: AVCaptureVideoPreviewLayer? + var captureSession: AVCaptureSession? // 비디오 캡처 세션 + var videoDataOutput: AVCaptureVideoDataOutput? // 비디오 데이터 출력 + var previewLayer: AVCaptureVideoPreviewLayer? // 비디오 미리보기 레이어 - private var lastPlayedSound: SystemSoundID? + private var lastPlayedSound: SystemSoundID? // 마지막으로 재생된 소리의 ID var exerciseStateString: String { switch currentExercise { case .overheadClap: - return clappingState.rawValue + return clappingState.rawValue // 현재 운동 상태 문자열 반환 case .downwardPunch: return downwardPunchState.rawValue case .sumoSquat: @@ -34,10 +40,11 @@ class ExerciseDetector: NSObject, ObservableObject { } } - var clappingState: ClappingState = .start - var downwardPunchState: DownwardPunchState = .standing - var sumoSquatState: SumoSquatState = .standing + var clappingState: ClappingState = .start // 박수 운동 상태 + var downwardPunchState: DownwardPunchState = .standing // 아래로 주먹치기 운동 상태 + var sumoSquatState: SumoSquatState = .standing // 스모 스쿼트 운동 상태 + /// 운동 상태를 초기화하는 메서드 func resetExerciseState() { switch currentExercise { case .overheadClap: @@ -49,29 +56,32 @@ class ExerciseDetector: NSObject, ObservableObject { } } + /// 동작 인식을 시작하거나 중지하는 메서드 func toggleDetection() { - isDetecting.toggle() + isDetecting.toggle() // 인식 상태 전환 if isDetecting { - startDetecting() + startDetecting() // 인식 시작 } else { - stopDetecting() + stopDetecting() // 인식 중지 } } + /// 동작 인식을 시작하는 메서드 func startDetecting() { - isDetecting = true + isDetecting = true // 인식 상태 설정 if captureSession == nil { - setupCaptureSession() + setupCaptureSession() // 캡처 세션 설정 } DispatchQueue.global(qos: .userInitiated).async { [weak self] in - self?.captureSession?.startRunning() + self?.captureSession?.startRunning() // 비디오 캡처 세션 시작 } } + /// 동작 인식을 중지하는 메서드 func stopDetecting() { - isDetecting = false + isDetecting = false // 인식 상태 해제 DispatchQueue.global(qos: .userInitiated).async { [weak self] in - self?.captureSession?.stopRunning() + self?.captureSession?.stopRunning() // 비디오 캡처 세션 중지 } } } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseGuideViewModel.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseGuideViewModel.swift index 37b99635..cab7ae7b 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseGuideViewModel.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseGuideViewModel.swift @@ -15,10 +15,11 @@ class ExerciseGuideViewModel: ObservableObject { "팔을 천천히 내리면서 시작 자세로 돌아옵니다." ] + /// 비디오를 로드하여 재생합니다. func loadVideo() { guard let url = URL(string: "https://strfeo.blob.core.windows.net/exercise-video/466512^Overhead_Clap^Shoulders.mp4") else { return } let player = AVPlayer(url: url) self.player = player - player.play() + player.play() // 비디오 재생 } } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseTimerViewModel.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseTimerViewModel.swift index c8ded677..4bb8c75a 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseTimerViewModel.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Exercise/ViewModels/ExerciseTimerViewModel.swift @@ -16,45 +16,50 @@ class ExerciseTimerViewModel: ObservableObject { private var timer: Timer? init(initialSeconds: Int = 10) { - self.timerSeconds = initialSeconds + self.timerSeconds = initialSeconds // 초기 타이머 설정 } + /// 시간을 감소시킵니다. func decreaseTime() { if timerSeconds > 5 { - timerSeconds -= 5 + timerSeconds -= 5 // 최소 5초로 유지 } } + /// 시간을 증가시킵니다. func increaseTime() { - timerSeconds += 5 + timerSeconds += 5 // 5초 증가 } + /// 시간을 문자열 형태로 변환합니다. func timeString() -> String { let minutes = timerSeconds / 60 let remainingSeconds = timerSeconds % 60 - return String(format: "%02d:%02d", minutes, remainingSeconds) + return String(format: "%02d:%02d", minutes, remainingSeconds) // "MM:SS" 형식 } + /// 타이머를 시작합니다. func startTimer(completion: @escaping () -> Void) { - isTimerRunning = true + isTimerRunning = true // 타이머 실행 중 설정 timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in guard let self = self else { return } if self.timerSeconds > 0 { - self.timerSeconds -= 1 + self.timerSeconds -= 1 // 1초마다 감소 } else { - self.stopTimer() - completion() + self.stopTimer() // 타이머 중지 + completion() // 완료 핸들러 호출 } } } + /// 타이머를 중지합니다. func stopTimer() { - timer?.invalidate() + timer?.invalidate() // 타이머 무효화 timer = nil - isTimerRunning = false + isTimerRunning = false // 타이머 실행 중 설정 해제 } deinit { - stopTimer() + stopTimer() // 메모리 해제 시 타이머 중지 } } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Chat/ChatViewModel.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Chat/ChatViewModel.swift index ca45a510..82d8e18f 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Chat/ChatViewModel.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Chat/ChatViewModel.swift @@ -34,11 +34,11 @@ class ChatViewModel: ObservableObject { ["role": "user", "content": content] ] ] - + let request = AF.request(url, method: .post, parameters: body, encoding: JSONEncoding.default, headers: headers) - + let response = await request.serializingDecodable(ChatResponse.self).response - + switch response.result { case .success(let chatResponse): if let message = chatResponse.choices.first?.message { diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Inbody/AzureInbodyViewModel.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Inbody/AzureInbodyViewModel.swift index e2b98869..e2cd9d44 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Inbody/AzureInbodyViewModel.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Inbody/AzureInbodyViewModel.swift @@ -90,6 +90,7 @@ class AzureInbodyViewModel: ObservableObject { DispatchQueue.main.async { self?.isLoading = false self?.error = .dataParsingError + print("data parsing error") } } case .failure(let error): diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Member/MemberViewModel.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Member/MemberViewModel.swift index 8320aad9..725261d7 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Member/MemberViewModel.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/Member/MemberViewModel.swift @@ -29,11 +29,11 @@ class MemberViewModel: ObservableObject { "Content-Type": "application/json", "appleID": appleID ] - + let request = AF.request(url, method: .post, headers: headers) - + let response = await request.serializingDecodable(LoginResponse.self).response - + switch response.result { case .success(let loginResponse): print("JWT 토큰: \(loginResponse.token)") diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/NetworkManager.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/NetworkManager.swift index 54a64a40..f7fd26b5 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/NetworkManager.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/NetworkService/NetworkManager.swift @@ -25,15 +25,20 @@ enum NetworkError: Error, LocalizedError { } } -enum HTTPMethod: String { - case get = "GET" - case post = "POST" - case patch = "PATCH" - case delete = "DELETE" -} +//enum HTTPMethod: String { +// case get = "GET" +// case post = "POST" +// case patch = "PATCH" +// case delete = "DELETE" +//} class NetworkManager { - static func fetch(_ endpoint: String, method: HTTPMethod = .get, body: T? = nil, multipartData: [String: Data]? = nil) async throws -> T { + static func fetch( + _ endpoint: String, + method: HTTPMethod = .get, + body: T? = nil, + multipartData: [String: Data]? = nil + ) async throws -> T { let requestURL = URL(string: Config.baseURL + endpoint)! return try await withCheckedThrowingContinuation { continuation in diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/EyeBodyView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/EyeBodyView.swift index 2cebfd16..72ba66c3 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/EyeBodyView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/EyeBodyView.swift @@ -11,6 +11,7 @@ struct EyeBodyView: View { @EnvironmentObject var onboardingNavigationPathFinder: NavigationPathFinder @EnvironmentObject var profileNavigationPathFinder: NavigationPathFinder @StateObject private var viewModel = EyeBodyPhotoViewModel() + @EnvironmentObject var tabViewModel: TabViewModel @Environment(\.modelContext) private var modelContext var isOnboarding: Bool = true @@ -107,6 +108,12 @@ struct EyeBodyView: View { .padding(.top, 30) } .navigationBarBackButtonHidden() + .onAppear { + tabViewModel.isHidden = true + } + .onDisappear { + tabViewModel.isHidden = false + } } func getPlaceholder(for index: Int) -> String { diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyAddView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyAddView.swift index bed1c85e..f8a34480 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyAddView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyAddView.swift @@ -8,10 +8,17 @@ import SwiftUI struct InbodyAddView: View { - @EnvironmentObject var navigationPathFinder: NavigationPathFinder + @EnvironmentObject var onboardingNavigationPathFinder: NavigationPathFinder + @EnvironmentObject var profileNavigationPathFinder: NavigationPathFinder @EnvironmentObject var viewModel: AzureInbodyViewModel +<<<<<<< HEAD + @EnvironmentObject var tabViewModel: TabViewModel +======= + @EnvironmentObject var onboardingNavigationPathFinder: NavigationPathFinder + @EnvironmentObject var profileNavigationPathFinder: NavigationPathFinder @State private var showOnboardingGaugeView = true +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) @State private var showSkipButton = true @State private var showActionSheet = false @State private var showImagePicker = false @@ -19,18 +26,43 @@ struct InbodyAddView: View { @State private var isImageSelected = false @State private var image: UIImage? = UIImage(named: "InbodyDefault") @State private var showCamera = false - + var body: some View { VStack { - if showOnboardingGaugeView { +<<<<<<< HEAD + if onboardingNavigationPathFinder.isFirstEnteredApp { +======= + if !navigationPathFinder.isFirstEnteredApp { +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) OnboardingGaugeView(progress: 3) + .padding(.top, 40) } - + else { + HStack { + Button { + profileNavigationPathFinder.popPath() + tabViewModel.isHidden = false + } label: { + Image("Chevron-left") + } + + Spacer() + + Text("인바디 사진 추가") + .font(.customFont(size: 22, weight: .bold)) + .foregroundStyle(.gray100) + + Spacer() + } + .padding(.horizontal, 20) + } + VStack { Text("인바디 사진은 아래와 같이 등록해주세요!") .font(.customFont(size: 20, weight: .bold)) + .foregroundStyle(.gray100) .padding(.bottom, 36) - + ZStack { Image(uiImage: image ?? UIImage(named: "InbodyDefault")!) .resizable() @@ -38,18 +70,18 @@ struct InbodyAddView: View { .frame(width: 300, height: 400) .padding() .clipShape(RoundedRectangle(cornerRadius: 10)) - + if !isImageSelected { RoundedRectangle(cornerRadius: 10) .fill(.black.opacity(0.7)) .frame(width: 345, height: 434) - + VStack { Text("민감 정보는 서버에 저장되지 않아요!") .foregroundStyle(Color(white: 1.0)) .font(.customFont(size: 18, weight: .bold)) .padding(.bottom, 26) - + Text("건강 정보는 개인 기기에만 저장되며\n 그래프로 기록을 보여드리기 위함이니 안심하세요 😔") .foregroundStyle(Color(white: 1.0)) .font(.customFont(size: 14, weight: .medium)) @@ -58,26 +90,51 @@ struct InbodyAddView: View { } } Spacer() - + if !isImageSelected { - CustomButtonView(title: "등록하기") { - showActionSheet = true + if onboardingNavigationPathFinder.isFirstEnteredApp { // 온보딩일 때만 건너뛰깇 + CustomButtonView(title: "등록하기") { + showActionSheet = true + }.padding(.top, 10) + + CustomButtonView(title: "건너뛰기") { + onboardingNavigationPathFinder.addPath(option: .inbodyInputView) + } + .padding(.bottom, 20) } +<<<<<<< HEAD + else { + CustomButtonView(title: "등록하기") { + showActionSheet = true + } +======= .padding(.top, 40) CustomButtonView(title: "건너뛰기") { - navigationPathFinder.addPath(option: .inbodyInputView) + onboardingNavigationPathFinder.addPath(option: .inbodyInputView) +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) } - } else { + } + else { CustomButtonView(title: "다시찍기") { showActionSheet = true } .padding(.top, 40) - + CustomButtonView(title: "분석하기") { - viewModel.analyzeImage(image!) + viewModel.analyzeImage(image!) // 분석하는 로직 if viewModel.isLoading && viewModel.error == nil { - navigationPathFinder.addPath(option: .onboardingLoadingView) +<<<<<<< HEAD + if onboardingNavigationPathFinder.isFirstEnteredApp { + onboardingNavigationPathFinder.addPath(option: .onboardingLoadingView) + } + else if !profileNavigationPathFinder.isFirstEnteredApp { + profileNavigationPathFinder.addPath(option: .onboardingLoadingView) + } + +======= + onboardingNavigationPathFinder.addPath(option: .onboardingLoadingView) +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) } } } @@ -103,12 +160,20 @@ struct InbodyAddView: View { isImageSelected = true } }) +<<<<<<< HEAD + } + .background(Color.white.ignoresSafeArea()) + .preferredColorScheme(.light) + .navigationBarBackButtonHidden() + .onAppear { + if !onboardingNavigationPathFinder.isFirstEnteredApp { + tabViewModel.isHidden = true + } + } +======= + .background(Color.gray10.ignoresSafeArea()) .navigationBarBackButtonHidden() } - +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) } } - -#Preview { - InbodyAddView() -} diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyFixView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyFixView.swift index d59a8eb1..39fb8a1a 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyFixView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyFixView.swift @@ -8,43 +8,127 @@ import SwiftUI struct InbodyFixView: View { - @EnvironmentObject var navigationPathFinder: NavigationPathFinder + @EnvironmentObject var onboardingNavigationPathFinder: NavigationPathFinder + @EnvironmentObject var profileNavigationPathFinder: NavigationPathFinder @EnvironmentObject var viewModel: AzureInbodyViewModel - + @EnvironmentObject var inbodyViewModel: InbodyViewModel + @EnvironmentObject var tabViewModel: TabViewModel + @State private var weight: String = "" @State private var height: String = "" @State private var bmi: String = "" @State private var bodyfat: String = "" @State private var bmr: String = "" @State private var showActionSheet = false - + var body: some View { ScrollView { - OnboardingGaugeView(progress: 4) +<<<<<<< HEAD + if onboardingNavigationPathFinder.isFirstEnteredApp { + OnboardingGaugeView(progress: 4) + } + else { + HStack { + Button { + profileNavigationPathFinder.popPath() + } label: { + Image("Chevron-left") + } + + Spacer() + + Text("인바디 수정") + .font(.customFont(size: 22, weight: .bold)) + .foregroundStyle(.gray100) + + Spacer() + } + .padding(.horizontal, 20) + } + +======= + if !navigationPathFinder.isFirstEnteredApp { + OnboardingGaugeView(progress: 4) + } +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) Text("정보가 다르게 인식됐나요? \n여기에서 수정할 수 있어요 😉") .font(.customFont(size: 20, weight: .bold)) .foregroundStyle(Color(red: 0.07, green: 0.07, blue: 0.08)) .padding(.bottom, 46) - + VStack(spacing: 20) { - OnboardingTextField(question: "체중 *", placeholder: viewModel.weight?.content ?? "45.3", unit: "kg", inputValue: weight, keyboardType: .numberPad, autoFocus: false, text: $weight) - OnboardingTextField(question: "키 *", placeholder: "160.3", unit: "cm", inputValue: height, keyboardType: .numberPad, autoFocus: false, text: $height) - OnboardingTextField(question: "BMI", placeholder: viewModel.bmi?.content ?? "17.6", unit: "%", inputValue: bmi, keyboardType: .numberPad, autoFocus: false, text: $bmi) - OnboardingTextField(question: "체지방량", placeholder: viewModel.bodyFat?.content ?? "9.6", unit: "%", inputValue: bodyfat, keyboardType: .numberPad, autoFocus: false, text: $bodyfat) - OnboardingTextField(question: "기초대사량", placeholder: viewModel.bmr?.content ?? "kcal", unit: "kg", inputValue: bmr, keyboardType: .numberPad, autoFocus: false, text: $bmr) - }.padding(.horizontal, 20) - + OnboardingTextField(question: "체중 *", placeholder: viewModel.weight?.content.extractNumbers() ?? "45.3", unit: "kg", inputValue: weight, keyboardType: .numberPad, autoFocus: false, text: $weight) + OnboardingTextField(question: "키 *", placeholder: "160", unit: "cm", inputValue: height, keyboardType: .numberPad, autoFocus: false, text: $height) + OnboardingTextField(question: "BMI", placeholder: viewModel.bmi?.content.extractNumbers() ?? "17.6", unit: "%", inputValue: bmi, keyboardType: .numberPad, autoFocus: false, text: $bmi) + OnboardingTextField(question: "체지방량", placeholder: viewModel.bodyFat?.content.extractNumbers() ?? "9.6", unit: "%", inputValue: bodyfat, keyboardType: .numberPad, autoFocus: false, text: $bodyfat) + OnboardingTextField(question: "기초대사량", placeholder: viewModel.bmr?.content.extractNumbers() ?? "kcal", unit: "kg", inputValue: bmr, keyboardType: .numberPad, autoFocus: false, text: $bmr) + } + .padding(.horizontal, 20) + .foregroundStyle(.gray100) + CustomButtonView(title: "다시찍기") { showActionSheet = true } .padding(.top, 40) - + CustomButtonView(title: "저장하기") { - // TODO: 백엔드에 회원 정보 저장 - navigationPathFinder.addPath(option: .eyeBodyView) + saveInbodyData() + if onboardingNavigationPathFinder.isFirstEnteredApp { + onboardingNavigationPathFinder.addPath(option: .eyeBodyView) + } + else { + profileNavigationPathFinder.popToRoot() + tabViewModel.isHidden = false + } } } + .background(Color.gray10.ignoresSafeArea()) .navigationBarBackButtonHidden() +<<<<<<< HEAD + .preferredColorScheme(.light) +======= + .padding(.vertical, 60) +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) + } + + private func saveInbodyData() { + + guard let weightValue = Float(weight), + let heightValue = Float(height) else { + return + } + + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd" + let inbodyDateString = dateFormatter.string(from: Date()) + + let createInbodyDto = CreateInbodyDto( + height: heightValue, + weight: weightValue, + inbodyDate: inbodyDateString, + bmr: Float(bmr), + bodyfat: Double(bodyfat), + bmi: Double(bmi), + memberID: 27) + + Task { + do { + // TODO: isFirstEnteredApp가 false일 때 수정값 백엔드 연결 추가 + let response = try await NetworkManager.createInbody(createInbodyDto: createInbodyDto) + await MainActor.run { + inbodyViewModel.createdInbody = response + } + } catch { + print("Error creating inbody: \(error)") + } + } + } +} +// MARK: 문자열 숫자 추출 +extension String { + func extractNumbers() -> String { + let numberSet = CharacterSet.decimalDigits + return self.unicodeScalars.filter { numberSet.contains($0) }.map { String($0) }.joined() } } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyInputView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyInputView.swift index 7552d640..f7e4bcdf 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyInputView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/InbodyInputView.swift @@ -8,9 +8,11 @@ import SwiftUI struct InbodyInputView: View { - @EnvironmentObject var navigationPathFinder: NavigationPathFinder + @EnvironmentObject var onboardingNavigationPathFinder: NavigationPathFinder + @EnvironmentObject var profileNavigationPathFinder: NavigationPathFinder @EnvironmentObject var inbodyViewModel: InbodyViewModel - + @EnvironmentObject var tabViewModel: TabViewModel + @State private var weight: String = "" @State private var height: String = "" @State private var bmi: String = "" @@ -18,18 +20,48 @@ struct InbodyInputView: View { @State private var bmr: String = "" @State private var showAlert = false @State private var alertMessage = "" - + var body: some View { VStack { - OnboardingGaugeView(progress: 5) +<<<<<<< HEAD + if onboardingNavigationPathFinder.isFirstEnteredApp { + OnboardingGaugeView(progress: 5) + .padding(.top, 50) + } + else { + HStack { + Button { + profileNavigationPathFinder.popPath() + tabViewModel.isHidden = false + } label: { + Image("Chevron-left") + } +======= + if !navigationPathFinder.isFirstEnteredApp { + OnboardingGaugeView(progress: 5) + } +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) + + Spacer() + Text("인바디 직접 추가") + .font(.customFont(size: 22, weight: .bold)) + .foregroundStyle(.gray100) + + Spacer() + } + .padding(.horizontal, 20) + .padding(.top, 50) + } + VStack { ScrollView { Text("체중과 키를 기록하면 변화를 그래프로 보여드릴게요 😉") .font(.customFont(size: 20, weight: .bold)) .foregroundStyle(Color(red: 0.07, green: 0.07, blue: 0.08)) .padding(.bottom, 46) - + .padding(.horizontal, 20) + VStack(spacing: 20) { OnboardingTextField(question: "체중 *", placeholder: "70", unit: "kg", inputValue: nil, keyboardType: .numberPad, autoFocus: false, text: $weight) OnboardingTextField(question: "키 *", placeholder: "170", unit: "cm", inputValue: nil, keyboardType: .numberPad, autoFocus: false, text: $height) @@ -38,36 +70,62 @@ struct InbodyInputView: View { OnboardingTextField(question: "기초대사량", placeholder: "1500", unit: "kcal", inputValue: nil, keyboardType: .numberPad, autoFocus: false, text: $bmr) } .padding(.horizontal, 30) + .foregroundStyle(.gray100) } - - CustomButtonView(title: "저장하기") { - saveInbodyData() - } - - CustomButtonView(title: "건너뛰기") { - navigationPathFinder.addPath(option: .onboardingEndView) + + if onboardingNavigationPathFinder.isFirstEnteredApp { + CustomButtonView(title: "저장하기") { + saveInbodyData() + onboardingNavigationPathFinder.addPath(option: .onboardingEndView) + } + + CustomButtonView(title: "건너뛰기") { + onboardingNavigationPathFinder.addPath(option: .onboardingEndView) + }.padding(.bottom, 20) + } else { + CustomButtonView(title: "저장하기") { + saveInbodyData() + profileNavigationPathFinder.popToRoot() + tabViewModel.isHidden = false + } + .padding(.bottom, 20) } } } .navigationBarBackButtonHidden() + .background( + Rectangle() + .foregroundStyle(.white) + ) + .ignoresSafeArea() .gesture( TapGesture() .onEnded { _ in UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } ) +<<<<<<< HEAD + .onAppear { + if !onboardingNavigationPathFinder.isFirstEnteredApp { + tabViewModel.isHidden = true + } + } +======= + .background(Color.gray10.ignoresSafeArea()) + .padding(.vertical, 60) +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) } - + private func saveInbodyData() { guard let weightValue = Float(weight), let heightValue = Float(height) else { return } - + let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let inbodyDateString = dateFormatter.string(from: Date()) - + let createInbodyDto = CreateInbodyDto( height: heightValue, weight: weightValue, @@ -76,7 +134,7 @@ struct InbodyInputView: View { bodyfat: Double(bodyfat), bmi: Double(bmi), memberID: 27) - + Task { do { let response = try await NetworkManager.createInbody(createInbodyDto: createInbodyDto) diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingEndView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingEndView.swift index 46b2d9c6..474ab409 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingEndView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingEndView.swift @@ -27,7 +27,7 @@ struct OnboardingEndView: View { Spacer() Button(action: { - navigationPathFinder.isFirstEnteredApp = false + navigationPathFinder.setIsFirstenteredApp(false) navigationPathFinder.popToRoot() }, label: { Text("메인으로 이동하기") @@ -41,6 +41,7 @@ struct OnboardingEndView: View { }) .padding(.horizontal, 24) .navigationBarBackButtonHidden() + .padding(.vertical, 60) } } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingLoadingView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingLoadingView.swift index 2bf4bef9..6b8de964 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingLoadingView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingLoadingView.swift @@ -8,26 +8,44 @@ import SwiftUI struct OnboardingLoadingView: View { - @EnvironmentObject var navigationPathFinder: NavigationPathFinder + @EnvironmentObject var onboardingNavigationPathFinder: NavigationPathFinder + @EnvironmentObject var profileNavigationPathFinder: NavigationPathFinder @EnvironmentObject var viewModel: AzureInbodyViewModel var body: some View { +<<<<<<< HEAD + ZStack { + Color.white.ignoresSafeArea() + VStack { + if onboardingNavigationPathFinder.isFirstEnteredApp { + OnboardingGaugeView(progress: 6) + } + Text("🧐") + .font(.customFont(size: 200, weight: .bold)) +======= VStack { - OnboardingGaugeView(progress: 6) - - Text("🧐") - .font(.customFont(size: 200, weight: .bold)) + if !navigationPathFinder.isFirstEnteredApp { + OnboardingGaugeView(progress: 6) + } +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) - Text("분석중...") - .font(.customFont(size: 20, weight: .bold)) + Text("분석중...") + .font(.customFont(size: 20, weight: .bold)) + } } .onReceive(viewModel.$isLoading) { isLoading in if !isLoading { print("-------------로딩 완료----------------") - navigationPathFinder.addPath(option: .inbodyFixView) + if onboardingNavigationPathFinder.isFirstEnteredApp { + onboardingNavigationPathFinder.addPath(option: .inbodyFixView) + } + else if !profileNavigationPathFinder.isFirstEnteredApp { + profileNavigationPathFinder.addPath(option: .inbodyFixView) + } } } .navigationBarBackButtonHidden() + .padding(.vertical, 60) } } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingSelectUserInfoView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingSelectUserInfoView.swift index 415a9da4..18da9fcd 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingSelectUserInfoView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingSelectUserInfoView.swift @@ -8,17 +8,19 @@ import SwiftUI struct OnboardingSelectUserInfoView: View { - @EnvironmentObject var navigationPathFinder: NavigationPathFinder + @EnvironmentObject var onboardingNavigationPathFinder: NavigationPathFinder @EnvironmentObject var memberViewModel : MemberViewModel @EnvironmentObject var profilleSettingViewModel : ProfileSettingViewModel @State private var name = "" - @State private var age = "" + @State private var age = "26" @State private var selectedGender: UserProfile.Gender = .female var body: some View { VStack { - OnboardingGaugeView(progress: 3) + if !navigationPathFinder.isFirstEnteredApp { + OnboardingGaugeView(progress: 3) + } ScrollView { VStack(spacing: 28) { HStack { @@ -28,7 +30,7 @@ struct OnboardingSelectUserInfoView: View { Spacer() } - OnboardingProfileSelectionView(selectedImageIndex: 1) + OnboardingProfileSelectionView(selectedImageIndex: 5) HStack { Text("어떻게 불러드릴까요?") @@ -86,7 +88,15 @@ struct OnboardingSelectUserInfoView: View { CustomButtonView(title: "입력하기") { // TODO: API POST 로직 추가 - navigationPathFinder.addPath(option: .inbodyAddView) +<<<<<<< HEAD + onboardingNavigationPathFinder.addPath(option: .inbodyAddView) +======= + if name.isEmpty { + Alert(title: Text("이름을 입력해주세요!")) + } else { + navigationPathFinder.addPath(option: .inbodyAddView) + } +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) } .navigationBarBackButtonHidden() } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingWelcomView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingWelcomView.swift index d30e587b..e5a01b14 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingWelcomView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Onboarding/Views/OnboardingWelcomView.swift @@ -13,7 +13,6 @@ struct OnboardingWelcomView: View { var body: some View { VStack { OnboardingGaugeView(progress: 1) - // .padding(.bottom, 44) VStack(alignment: .center, content: { Text("반가워요 핑! \n 저는 운동 교관 피오에요 핑! \n 오늘부터 운동 습관을 잡아줄게요 핑!") diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/ViewModels/InbodyViewModel.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/ViewModels/InbodyViewModel.swift index 3a6b1429..a9a23673 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/ViewModels/InbodyViewModel.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/ViewModels/InbodyViewModel.swift @@ -15,7 +15,7 @@ class InbodyViewModel: ObservableObject { @Published var createdInbody: InbodyResponse? @Published var errorMessage: String? - func analyzeTrend(for inbodys: [InbodyModel], getValue: (InbodyModel) -> T?) -> String { + func analyzeTrend(for inbodys: [Inbody], getValue: (Inbody) -> T?) -> String { let filteredInbodys = inbodys.filter { getValue($0) != nil }.sorted { $0.inbodyDate < $1.inbodyDate } guard filteredInbodys.count >= 2 else { diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/Components/InbodyChartView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/Components/InbodyChartView.swift index 955b820f..753b0c89 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/Components/InbodyChartView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/Components/InbodyChartView.swift @@ -9,20 +9,20 @@ import SwiftUI import Charts struct InbodyChartView: View { - let inbodys: [InbodyModel] + let inbodys: [Inbody] let title: String let xAxisTitle: String let yAxisTitle: String let color: Color - let getValue: (InbodyModel) -> T? + let getValue: (Inbody) -> T? @StateObject private var inbodyViewModel = InbodyViewModel() - private var sortedInbodys: [InbodyModel] { + private var sortedInbodys: [Inbody] { return inbodys.sorted { $0.inbodyDate < $1.inbodyDate} } - private var filteredInbodys: [InbodyModel] { + private var filteredInbodys: [Inbody] { return sortedInbodys.filter { getValue($0) != nil } } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/InbodyInputSelectView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/InbodyInputSelectView.swift index c3a1d399..8abeba7b 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/InbodyInputSelectView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/InbodyInputSelectView.swift @@ -8,19 +8,36 @@ import SwiftUI struct InbodyInputSelectView: View { - @Binding var isPresented: Bool + @EnvironmentObject var navigationPathFinder: NavigationPathFinder + @EnvironmentObject var tabViewModel: TabViewModel var body: some View { - VStack { HStack { + Button { + navigationPathFinder.popPath() + tabViewModel.isHidden = false + } label: { + Image("Chevron-left") + } + + Spacer() + + Text("인바디 수정") + .font(.customFont(size: 22, weight: .bold)) + .foregroundStyle(.gray100) + Spacer() + } + .padding(.horizontal, 20) + + Spacer() + + HStack { Text("인바디를 등록하세요") .font(.customFont(size: 20, weight: .bold)) .foregroundStyle(.gray100) - Spacer() } - .padding(.top, 32) .padding(.bottom, 56) ZStack { @@ -39,17 +56,32 @@ struct InbodyInputSelectView: View { Spacer() CustomButtonView(title: "사진찍기") { - - }.padding(.bottom, 10) + navigationPathFinder.addPath(option: .inbodyAddView) + } + .padding(.vertical, 10) CustomButtonView(title: "수기입력") { - + navigationPathFinder.addPath(option: .inbodyInputView) } } - .background(.white) +<<<<<<< HEAD + .background(.white) + .navigationBarBackButtonHidden() +======= + .padding(.vertical, 50) + .background( + Rectangle() + .foregroundStyle(.white) + ) + .ignoresSafeArea() +>>>>>>> 6d4c919 (🐛 :: 뭔가 고친 것 같은데 기억 나지 않음 ...) + .onAppear { + tabViewModel.isHidden = true + } } } #Preview { - InbodyInputSelectView(isPresented: .constant(true)) + InbodyInputSelectView() + .environmentObject(TabViewModel()) } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/InbodyMainView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/InbodyMainView.swift index 2392e57d..b9291682 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/InbodyMainView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/InbodyMainView.swift @@ -10,30 +10,26 @@ import SwiftUI struct InbodyMainView: View { @EnvironmentObject var navigationPathFinder: NavigationPathFinder @EnvironmentObject var inbodyViewModel: InbodyViewModel - @State private var isShowModal = false - let inbodys: [InbodyModel] var body: some View { VStack { ScrollView { - InbodyChartView(inbodys: inbodys, title: "체중", xAxisTitle: "날짜", yAxisTitle: "체중", color: .red) { $0.weight } - InbodyChartView(inbodys: inbodys, title: "기초 대사량", xAxisTitle: "날짜", yAxisTitle: "기초 대사량", color: .orange) { $0.bmr } - InbodyChartView(inbodys: inbodys, title: "체지방량", xAxisTitle: "날짜", yAxisTitle: "체지방량", color: .green) { $0.bodyfat } - InbodyChartView(inbodys: inbodys, title: "BMI", xAxisTitle: "날짜", yAxisTitle: "BMI", color: .blue) { $0.bmi } + InbodyChartView(inbodys: inbodyViewModel.inbodies, title: "체중", xAxisTitle: "날짜", yAxisTitle: "체중", color: .red) { $0.weight } + InbodyChartView(inbodys: inbodyViewModel.inbodies, title: "기초 대사량", xAxisTitle: "날짜", yAxisTitle: "기초 대사량", color: .orange) { $0.bmr } + InbodyChartView(inbodys: inbodyViewModel.inbodies, title: "체지방량", xAxisTitle: "날짜", yAxisTitle: "체지방량", color: .green) { $0.bodyfat } + InbodyChartView(inbodys: inbodyViewModel.inbodies, title: "BMI", xAxisTitle: "날짜", yAxisTitle: "BMI", color: .blue) { $0.bmi } } CustomButtonView(title: "인바디 추가하기", style: .black) { - isShowModal = true + navigationPathFinder.addPath(option: .inbodyInputSelectView) } - .sheet(isPresented: $isShowModal, content: { - InbodyInputSelectView(isPresented: $isShowModal) - }) } .ignoresSafeArea() .preferredColorScheme(.light) + .onAppear { + Task { + await inbodyViewModel.findAllInbodies(memberId: 27) + } + } } } - -#Preview { - InbodyMainView(inbodys: inbodyDummyData) -} diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/ProfileMainView.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/ProfileMainView.swift index 41e5b1e1..9bc9d633 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/ProfileMainView.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Profile/Views/ProfileMainView.swift @@ -25,7 +25,7 @@ struct ProfileMainView: View { case .album: AlbumMainView() case .inbody: - InbodyMainView(inbodys: inbodyDummyData) + InbodyMainView() case .eyeBody: EyeBodyMainView() } diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Utils/NavigationComponents/NavigationPathFinder.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Utils/NavigationComponents/NavigationPathFinder.swift index f53a3d91..0fb050a9 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Utils/NavigationComponents/NavigationPathFinder.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Utils/NavigationComponents/NavigationPathFinder.swift @@ -9,7 +9,7 @@ import SwiftUI class NavigationPathFinder: ObservableObject { @Published var path: [Option] = [] - @Published var isFirstEnteredApp: Bool + @Published var isFirstEnteredApp: Bool = true init() { isFirstEnteredApp = UserDefaults.standard.bool(forKey: "IsFirstEnteredApp") diff --git a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Utils/NavigationComponents/ViewOptions.swift b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Utils/NavigationComponents/ViewOptions.swift index 5ff37866..a9d577f3 100644 --- a/Frontend-iOS/FebirdApp/FebirdApp/Sources/Utils/NavigationComponents/ViewOptions.swift +++ b/Frontend-iOS/FebirdApp/FebirdApp/Sources/Utils/NavigationComponents/ViewOptions.swift @@ -64,6 +64,10 @@ enum ProfileViewOptions: Hashable, ViewOptions { case profileSettingView case eyeBodyView(isOnboarding: Bool) case inbodyInputView + case inbodyInputSelectView + case inbodyAddView + case onboardingLoadingView + case inbodyFixView @ViewBuilder func view() -> some View { switch self { @@ -78,6 +82,14 @@ enum ProfileViewOptions: Hashable, ViewOptions { EyeBodyView(isOnboarding: isOnboarding) case .inbodyInputView: InbodyInputView() + case .inbodyInputSelectView: + InbodyInputSelectView() + case .inbodyAddView: + InbodyAddView() + case .onboardingLoadingView: + OnboardingLoadingView() + case .inbodyFixView: + InbodyFixView() } } }