diff --git a/Dietto/Dietto.xcodeproj/project.pbxproj b/Dietto/Dietto.xcodeproj/project.pbxproj index 22c2148..2fb9184 100644 --- a/Dietto/Dietto.xcodeproj/project.pbxproj +++ b/Dietto/Dietto.xcodeproj/project.pbxproj @@ -274,12 +274,14 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Dietto/Info.plist; + INFOPLIST_KEY_NSMotionUsageDescription = "걸음 데이터에 접근하기 위한 권한이 필요합니다."; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = ""; INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleLightContent; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UIUserInterfaceStyle = Light; IPHONEOS_DEPLOYMENT_TARGET = 18.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -305,12 +307,14 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Dietto/Info.plist; + INFOPLIST_KEY_NSMotionUsageDescription = "걸음 데이터에 접근하기 위한 권한이 필요합니다."; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = ""; INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleLightContent; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UIUserInterfaceStyle = Light; IPHONEOS_DEPLOYMENT_TARGET = 18.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/Dietto/Dietto/Apps/DiettoApp.swift b/Dietto/Dietto/Apps/DiettoApp.swift index e27c9cb..4382b9e 100644 --- a/Dietto/Dietto/Apps/DiettoApp.swift +++ b/Dietto/Dietto/Apps/DiettoApp.swift @@ -10,11 +10,11 @@ import SwiftData @main struct DiettoApp: App { - @AppStorage("isFirstLaunch") var isFirstLaunch: Bool = true + @AppStorage("isFirstLaunch") var isFirstLaunch: Bool = false var body: some Scene { WindowGroup { if isFirstLaunch { - IntroView() + TutorialView() } else { MainTabView() diff --git a/Dietto/Dietto/Data/DTO/InterestsDTO.swift b/Dietto/Dietto/Data/DTO/InterestsDTO.swift new file mode 100644 index 0000000..7dc72c2 --- /dev/null +++ b/Dietto/Dietto/Data/DTO/InterestsDTO.swift @@ -0,0 +1,18 @@ +// +// InterestsDTO.swift +// Dietto +// +// Created by 안정흠 on 5/28/25. +// + +import Foundation +import SwiftData + +@Model +final class InterestsDTO { + var title: String + + init(title: String) { + self.title = title + } +} diff --git a/Dietto/Dietto/Data/UserDTO.swift b/Dietto/Dietto/Data/DTO/UserDTO.swift similarity index 100% rename from Dietto/Dietto/Data/UserDTO.swift rename to Dietto/Dietto/Data/DTO/UserDTO.swift diff --git a/Dietto/Dietto/Data/WeightDTO.swift b/Dietto/Dietto/Data/DTO/WeightDTO.swift similarity index 100% rename from Dietto/Dietto/Data/WeightDTO.swift rename to Dietto/Dietto/Data/DTO/WeightDTO.swift diff --git a/Dietto/Dietto/Data/Repository/NetworkRepository.swift b/Dietto/Dietto/Data/Repository/NetworkRepository.swift index 749ac00..336037c 100644 --- a/Dietto/Dietto/Data/Repository/NetworkRepository.swift +++ b/Dietto/Dietto/Data/Repository/NetworkRepository.swift @@ -26,7 +26,7 @@ final class NetworkRepositoryImpl: NetworkRepository { func fetch(promptType: PromptType, rawValues: [Any], outputType: T.Type) async throws -> T where T: Decodable { let values: [String] = rawValues.compactMap { if let ing = $0 as? IngredientEntity { return ing.ingredient } - if let art = $0 as? ArticleEntity { return art.title } + if let art = $0 as? InterestEntity { return art.title } return nil } let prompt = promptManager.makePrompt(for: promptType, with: values) diff --git a/Dietto/Dietto/Data/PedometerRepository.swift b/Dietto/Dietto/Data/Repository/PedometerRepository.swift similarity index 100% rename from Dietto/Dietto/Data/PedometerRepository.swift rename to Dietto/Dietto/Data/Repository/PedometerRepository.swift diff --git a/Dietto/Dietto/Data/StorageRepository.swift b/Dietto/Dietto/Data/Repository/StorageRepository.swift similarity index 100% rename from Dietto/Dietto/Data/StorageRepository.swift rename to Dietto/Dietto/Data/Repository/StorageRepository.swift diff --git a/Dietto/Dietto/Domain/Entities/ArticleEntity.swift b/Dietto/Dietto/Domain/Entities/ArticleEntity.swift index 7e94e01..0105dd5 100644 --- a/Dietto/Dietto/Domain/Entities/ArticleEntity.swift +++ b/Dietto/Dietto/Domain/Entities/ArticleEntity.swift @@ -10,5 +10,7 @@ import Foundation //MARK: - 아티클은 저장합니다. struct ArticleEntity: Identifiable, Hashable, Decodable{ var id = UUID() - let title: String + let url : URL + let title : String + let description : String } diff --git a/Dietto/Dietto/Domain/Entities/InterestEntity.swift b/Dietto/Dietto/Domain/Entities/InterestEntity.swift new file mode 100644 index 0000000..b384f86 --- /dev/null +++ b/Dietto/Dietto/Domain/Entities/InterestEntity.swift @@ -0,0 +1,12 @@ +// +// InterestEntity.swift +// Dietto +// +// Created by 안세훈 on 5/26/25. +// + +import Foundation + +struct InterestEntity: Hashable { + let title : String +} diff --git a/Dietto/Dietto/Domain/Usecases/AlanUsecase.swift b/Dietto/Dietto/Domain/Usecases/AlanUsecase.swift index da85291..e237769 100644 --- a/Dietto/Dietto/Domain/Usecases/AlanUsecase.swift +++ b/Dietto/Dietto/Domain/Usecases/AlanUsecase.swift @@ -11,7 +11,7 @@ import Foundation protocol AlanUsecase { func fetchRecommend(ingredients: [IngredientEntity]) async throws -> [RecommendEntity] - func fetchArticle(topics : [ArticleEntity]) async throws -> [ArticleEntity] + func fetchArticle(topics : [InterestEntity]) async throws -> [ArticleEntity] } //MARK: - UsecaseImpl @@ -30,7 +30,8 @@ final class AlanUsecaseImpl : AlanUsecase { return wrapper.recommendation } - func fetchArticle(topics: [ArticleEntity]) async throws -> [ArticleEntity] { + //아티클 + func fetchArticle(topics: [InterestEntity]) async throws -> [ArticleEntity] { let wrapper = try await repository.fetch(promptType: .article, rawValues: topics, outputType: ArticleDTO.self) return wrapper.articles diff --git a/Dietto/Dietto/Domain/Usecases/InterestsUsecase.swift b/Dietto/Dietto/Domain/Usecases/InterestsUsecase.swift new file mode 100644 index 0000000..95d5986 --- /dev/null +++ b/Dietto/Dietto/Domain/Usecases/InterestsUsecase.swift @@ -0,0 +1,49 @@ +// +// InterestsUsecaseImpl.swift +// Dietto +// +// Created by 안정흠 on 5/27/25. +// + +import Foundation + +protocol InterestsUsecase { + func insertInterests(_ interests: InterestEntity) + func deleteInterests(_ interests: InterestEntity) + func fetchInterests() -> [InterestEntity] +} + +final class InterestsUsecaseImpl: InterestsUsecase where Repository.T == InterestsDTO { + private let repository: Repository + + init(repository: Repository) { + self.repository = repository + } + + func insertInterests(_ interests: InterestEntity) { + repository.insertData(data: InterestsDTO(title: interests.title)) + } + + func deleteInterests(_ interests: InterestEntity) { + do { + let title = interests.title + let predicate = #Predicate { $0.title == title } + try repository.deleteData(where: predicate) + } + catch { + print("\(#function) : \(error.localizedDescription)") + } + + } + + func fetchInterests() -> [InterestEntity] { + do { + let result = try repository.fetchData(where: nil, sort: []) + return result.map{InterestEntity(title: $0.title)} + } + catch { + print("\(#function) : \(error.localizedDescription)") + return [] + } + } +} diff --git a/Dietto/Dietto/Domain/PedometerUsecase.swift b/Dietto/Dietto/Domain/Usecases/PedometerUsecase.swift similarity index 100% rename from Dietto/Dietto/Domain/PedometerUsecase.swift rename to Dietto/Dietto/Domain/Usecases/PedometerUsecase.swift diff --git a/Dietto/Dietto/Domain/UserStorageUsecase.swift b/Dietto/Dietto/Domain/Usecases/UserStorageUsecase.swift similarity index 100% rename from Dietto/Dietto/Domain/UserStorageUsecase.swift rename to Dietto/Dietto/Domain/Usecases/UserStorageUsecase.swift diff --git a/Dietto/Dietto/Domain/WeightHistoryUsecase.swift b/Dietto/Dietto/Domain/Usecases/WeightHistoryUsecase.swift similarity index 100% rename from Dietto/Dietto/Domain/WeightHistoryUsecase.swift rename to Dietto/Dietto/Domain/Usecases/WeightHistoryUsecase.swift diff --git a/Dietto/Dietto/Info.plist b/Dietto/Dietto/Info.plist index 5b1a2fc..9cd55ed 100644 --- a/Dietto/Dietto/Info.plist +++ b/Dietto/Dietto/Info.plist @@ -2,8 +2,6 @@ - NSMotionUsageDescription - 걸음 데이터에 접근하기 위한 권한이 필요합니다. UIAppFonts NerkoOne-regular.otf diff --git a/Dietto/Dietto/Presentation/Article/View/ArticleView.swift b/Dietto/Dietto/Presentation/Article/View/ArticleView.swift new file mode 100644 index 0000000..85d25ed --- /dev/null +++ b/Dietto/Dietto/Presentation/Article/View/ArticleView.swift @@ -0,0 +1,113 @@ +// +// ArticleView.swift +// Dietto +// +// Created by 안세훈 on 5/26/25. +// + +import SwiftUI + +struct ArticleView: View { + let articles = [ + "https://www.youtube.com/watch?v=3p8EBPVZ2Iw", + "https://www.news1.kr/articles/?5301234", + "https://www.youtube.com/watch?v=FdYIvEc7e-0", + "https://www.youtube.com/watch?v=2tM1LFFxeKg" + ] + @StateObject var viewModel = ArticleViewModel() + var body: some View { + NavigationView { + VStack(alignment: .leading){ + HStack { + //MARK: - 로고 + Text("Dietto") + .font(.NerkoOne40) + .foregroundStyle(.text) + Spacer() + + NavigationLink(destination: InterestsView(viewModel: viewModel)) { + Text("관심사 수정") + .font(.pretendardMedium16) + .foregroundColor(.white) + .padding(.vertical, 4) + .padding(.horizontal, 12) + .background(Color.appMain) + .clipShape(Capsule()) + } + } + .padding([.leading, .trailing], 16) + Text("내 관심사") + .font(.pretendardBold20) + .padding(.leading, 16) + Interests( + topic: "", + titles: viewModel.selectedInterests.map{$0.title}, + onClicked: {_ in }, + isSelected: {_ in true} + ).padding(.leading, 16) + + List(articles, id: \.self) { item in + LinkRow(previewURL: URL(string: item)!) + } + .listStyle(.plain) + + } + } + .toolbarVisibility(.hidden, for: .navigationBar) + } +} + +#Preview { + NavigationView { + ArticleView() + } + +} + + + +// +// +// +/* + [ + { + "title": "계룡시, 등굣길 금연 캠페인 성황리에 마무리", + "link": "https://www.news1.kr/articles/?5301234" + }, + { + "title": "영도구보건소, 금연구역 인증 걷기 챌린지 운영", + "link": "https://www.news2.kr/articles/?5301235" + }, + { + "title": "광주시의회, 세계 금연의 날 맞아 금연 결의 대회 개최", + "link": "https://www.news3.kr/articles/?5301236" + }, + { + "title": "팔굽혀펴기로 치매 예방하기?...근육량 증가하면 당뇨·치매 위험 낮아져 [Health Recipe]", + "link": "https://www.healthnews.kr/articles/?5301237" + }, + { + "title": "노년층 복병 ‘골근감소증’ “장내 미생물 먹었더니”…뼈밀도·근육량 증가↑", + "link": "https://www.healthnews.kr/articles/?5301238" + }, + { + "title": "체중 재증가하는 여성은 근육량보다 지방량 증가가 원인", + "link": "https://www.healthnews.kr/articles/?5301239" + }, + { + "title": "금연 무기력함 극복하는 꿀팁 3가지를 소개합니다! : 네이버 블로그", + "link": "https://blog.naver.com/PostView.nhn?blogId=example1&logNo=222123456789" + }, + { + "title": "근육량 증가, 근성장을 극대화해줄 꿀팁! - 네이버 블로그", + "link": "https://blog.naver.com/PostView.nhn?blogId=example2&logNo=222123456790" + }, + { + "title": "지속 가능한 근육량 증가 운동 프로그램 : 네이버 블로그", + "link": "https://blog.naver.com/PostView.nhn?blogId=example3&logNo=222123456791" + } + ] + + + */ diff --git a/Dietto/Dietto/Presentation/Article/View/InterestView.swift b/Dietto/Dietto/Presentation/Article/View/InterestView.swift new file mode 100644 index 0000000..eb3150d --- /dev/null +++ b/Dietto/Dietto/Presentation/Article/View/InterestView.swift @@ -0,0 +1,67 @@ +// +// InterestsView.swift +// Dietto +// +// Created by InTak Han on 5/14/25. +// + +import SwiftUI + +struct InterestsView: View { + + @ObservedObject var viewModel : ArticleViewModel + @Environment(\.dismiss) private var dismiss + + var body: some View { + VStack { + VStack(alignment: .leading) { + Text("건강에 관련된\n") + + Text("관심사").foregroundColor(.appMain) + + Text("를 알려주세요 !") + } + .font(.pretendardBold24) + .padding(.top, 20) + .padding(.horizontal, 20) + .frame(maxWidth: .infinity, alignment: .leading) + +// ScrollView { +// VStack(alignment: .leading, spacing: 30) { + ForEach(viewModel.interestData, id: \.topic) { block in + Interests( + topic: block.topic, + titles: block.titles, + onClicked: { title in + viewModel.toggleInterest(title) + }, + isSelected: { title in + viewModel.selectedInterests.contains(where: { $0.title == title }) + } + ) + } + .padding() + Spacer() + Button { + print("Submit!") + dismiss() + } label: { + Text("저장") + .frame(maxWidth: .infinity) + .padding() + .background(Color.appMain) + .foregroundColor(.white) + .cornerRadius(13) + .font(.pretendardMedium16) + } + .padding() + } + .navigationTitle("관심사 수정") + .toolbarTitleDisplayMode(.inline) + .background(Color.backGround) + } +} + +#Preview { + NavigationView { + InterestsView(viewModel: ArticleViewModel()) + } +} diff --git a/Dietto/Dietto/Presentation/Onboarding/View/Interests.swift b/Dietto/Dietto/Presentation/Article/View/Interests.swift similarity index 100% rename from Dietto/Dietto/Presentation/Onboarding/View/Interests.swift rename to Dietto/Dietto/Presentation/Article/View/Interests.swift diff --git a/Dietto/Dietto/Presentation/Article/View/LinkRow.swift b/Dietto/Dietto/Presentation/Article/View/LinkRow.swift new file mode 100644 index 0000000..64ac59a --- /dev/null +++ b/Dietto/Dietto/Presentation/Article/View/LinkRow.swift @@ -0,0 +1,42 @@ +// +// LinkRow.swift +// Dietto +// +// Created by 안정흠 on 5/27/25. +// + + +import SwiftUI +import LinkPresentation + +struct LinkRow : UIViewRepresentable { + + var previewURL:URL + + func makeUIView(context: Context) -> LPLinkView { + let view = LPLinkView(url: previewURL) + + let provider = LPMetadataProvider() + provider.startFetchingMetadata(for: previewURL) { (metadata, error) in + if let md = metadata { + DispatchQueue.main.async { + view.metadata = md + view.sizeToFit() + } + } + else if error != nil + { + let md = LPLinkMetadata() + md.title = "Custom title" + view.metadata = md + view.sizeToFit() + } + } + + return view + } + + func updateUIView(_ view: LPLinkView, context: Context) { + // New instance for each update + } +} \ No newline at end of file diff --git a/Dietto/Dietto/Presentation/Article/ViewModel/ArticleViewModel.swift b/Dietto/Dietto/Presentation/Article/ViewModel/ArticleViewModel.swift new file mode 100644 index 0000000..7e7388a --- /dev/null +++ b/Dietto/Dietto/Presentation/Article/ViewModel/ArticleViewModel.swift @@ -0,0 +1,60 @@ +// +// ArticleViewModel.swift +// Dietto +// +// Created by 안세훈 on 5/26/25. +// + +import SwiftUI + +final class ArticleViewModel: ObservableObject { + @Published private(set) var selectedInterests: [InterestEntity] = [] + + private let alanUsecase: AlanUsecase + private let storageUsecase: InterestsUsecase + let interestData: [(topic: String, titles: [String])] = [ + ("운동", ["근육량 증가", "규칙적인 운동", "체지방률 감소"]), + ("식습관 개선", ["음식 섭취 패턴 안정화", "안정된 영양소 섭취", "수분 섭취", "외식 줄이기", "저염식"]), + ("건강 관리", ["금연 / 금주", "혈당 안정화", "음식 일기", "피부 개선"]), + ("수면 및 스트레스", ["수면 개선", "스트레스"]) + ] + + init( + alanUsecase: AlanUsecase = AlanUsecaseImpl(repository: NetworkRepositoryImpl()), + storageUsecase: InterestsUsecase = InterestsUsecaseImpl(repository: StorageRepositoryImpl()) + ) { + self.alanUsecase = alanUsecase + self.storageUsecase = storageUsecase + selectedInterests = storageUsecase.fetchInterests() + } + + // MARK: - 아티클 로드 + func loadArticles() async throws -> [ArticleEntity] { +// alanUsecase.fetchArticle(topics: <#T##[ArticleEntity]#>) + [] + } + + // MARK: - 관심사 추가 / 삭제 + func addInterest(_ title: String) { + let entity = InterestEntity(title: title) + guard !selectedInterests.contains(where: { $0.title == title }) else { return } + selectedInterests.append(entity) + } + + func removeInterest(_ title: String) { + if let index = selectedInterests.firstIndex(where: { $0.title == title }) { + selectedInterests.remove(at: index) + } + } + + func toggleInterest(_ title: String) { + if selectedInterests.contains(where: { $0.title == title }) { + removeInterest(title) + storageUsecase.deleteInterests(InterestEntity(title: title)) + } else { + addInterest(title) + storageUsecase.insertInterests(InterestEntity(title: title)) + } + print(selectedInterests) + } +} diff --git a/Dietto/Dietto/Presentation/Community/View/CommunityView.swift b/Dietto/Dietto/Presentation/Community/View/CommunityView.swift deleted file mode 100644 index cf3d72a..0000000 --- a/Dietto/Dietto/Presentation/Community/View/CommunityView.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// CommunityView.swift -// Dietto -// -// Created by 안세훈 on 5/13/25. -// - -import SwiftUI - -struct CommunityView: View { - var body: some View { - Text("친구 뷰 ") - } -} - -#Preview { - CommunityView() -} diff --git a/Dietto/Dietto/Presentation/Dietary/View/DietaryView.swift b/Dietto/Dietto/Presentation/Dietary/View/DietaryView.swift index fc64a22..c87588a 100644 --- a/Dietto/Dietto/Presentation/Dietary/View/DietaryView.swift +++ b/Dietto/Dietto/Presentation/Dietary/View/DietaryView.swift @@ -163,11 +163,9 @@ struct DietaryView: View { print("식단 추천 받기 버튼이 클릭댐") if !dietartViewModel.presentIngredients.isEmpty { isLoading = true - Task { #warning("쓰레드 확인해보기.") - await dietartViewModel.fetchRecommendations(ingredients: dietartViewModel.presentIngredients) - isLoading = false - PushToRecommandView = true - } + dietartViewModel.fetchRecommendations(ingredients: dietartViewModel.presentIngredients) + isLoading = false + PushToRecommandView = true }else{ print("비어있음 현재 식재료가 ") } diff --git a/Dietto/Dietto/Presentation/Dietary/ViewModel/DietaryViewModel.swift b/Dietto/Dietto/Presentation/Dietary/ViewModel/DietaryViewModel.swift index 7bd3a7c..5040f5f 100644 --- a/Dietto/Dietto/Presentation/Dietary/ViewModel/DietaryViewModel.swift +++ b/Dietto/Dietto/Presentation/Dietary/ViewModel/DietaryViewModel.swift @@ -75,14 +75,16 @@ class DietaryViewModel: ObservableObject { } //MARK: - 현재 재료를 통해 식단 추천 받기. - //mainactor <- thread -#warning("쓰레드 확인해보기.") - func fetchRecommendations(ingredients: [IngredientEntity]) async { - do { - let result = try await usecase.fetchRecommend(ingredients: ingredients) - self.recommendList = result - } catch { - print(#file,#function,#line, error.localizedDescription) + func fetchRecommendations(ingredients: [IngredientEntity]) { + Task { + do { + let result = try await usecase.fetchRecommend(ingredients: ingredients) + await MainActor.run { + self.recommendList = result + } + } catch { + print(#file,#function,#line, error.localizedDescription) + } } } diff --git a/Dietto/Dietto/Presentation/MainTabView.swift b/Dietto/Dietto/Presentation/MainTabView.swift index f806647..ad25293 100644 --- a/Dietto/Dietto/Presentation/MainTabView.swift +++ b/Dietto/Dietto/Presentation/MainTabView.swift @@ -17,7 +17,7 @@ struct MainTabView: View { DietaryView() } Tab("아티클", systemImage: "newspaper") { - EmptyView() + ArticleView() } Tab("프로필", systemImage: "person.circle.fill") { ProfileView() diff --git a/Dietto/Dietto/Presentation/Onboarding/View/InterestView.swift b/Dietto/Dietto/Presentation/Onboarding/View/InterestView.swift deleted file mode 100644 index c6057af..0000000 --- a/Dietto/Dietto/Presentation/Onboarding/View/InterestView.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// InterestsView.swift -// Dietto -// -// Created by InTak Han on 5/14/25. -// - -import SwiftUI - -struct InterestsView: View { - - @ObservedObject var viewModel : OnboardingViewModel - - @Binding var selection: Int //binding - - var body: some View { - VStack(spacing: 40) { - VStack(alignment: .leading) { - Text("\(viewModel.nickname)님의") - + Text(" 관심사").foregroundColor(.appMain) - + Text("를 알려주세요 !") - } - .font(.pretendardBold24) - .padding(.top, 20) - .padding(.horizontal, 20) - .frame(maxWidth: .infinity, alignment: .leading) - - ScrollView { - VStack(alignment: .leading, spacing: 30) { - ForEach(viewModel.interestData, id: \.topic) { block in - Interests( - topic: block.topic, - titles: block.titles, - onClicked: { title in - viewModel.toggleInterest(title) - }, - isSelected: { title in - viewModel.selectedArticles.contains(where: { $0.title == title }) - } - ) - } - } - .padding(.horizontal, 20) - .padding(.bottom, 20) - } - } - .background(Color(.backGround).ignoresSafeArea()) - } -} diff --git a/Dietto/Dietto/Presentation/Onboarding/View/TutorialView.swift b/Dietto/Dietto/Presentation/Onboarding/View/TutorialView.swift index a7a70f9..0a3aaa4 100644 --- a/Dietto/Dietto/Presentation/Onboarding/View/TutorialView.swift +++ b/Dietto/Dietto/Presentation/Onboarding/View/TutorialView.swift @@ -20,8 +20,8 @@ struct TutorialView: View { //목표 설정 뷰 GoalView(selection: $selection, viewModel: viewModel) .tag(0) - InterestsView(viewModel: viewModel, selection: $selection) - .tag(1) +// InterestsView(viewModel: viewModel, selection: $selection) +// .tag(1) } .tabViewStyle(.page(indexDisplayMode: .never)) .animation(.linear, value: selection) diff --git a/Dietto/Dietto/Presentation/Onboarding/ViewModel/OnboardingViewModel.swift b/Dietto/Dietto/Presentation/Onboarding/ViewModel/OnboardingViewModel.swift index afee5c4..d2f2d2b 100644 --- a/Dietto/Dietto/Presentation/Onboarding/ViewModel/OnboardingViewModel.swift +++ b/Dietto/Dietto/Presentation/Onboarding/ViewModel/OnboardingViewModel.swift @@ -14,14 +14,9 @@ final class OnboardingViewModel: ObservableObject { let weights: [Int] = Array(20...100).reversed() let distances: [Int] = Array(1...10).reversed() - let interestData: [(topic: String, titles: [String])] = [ - ("운동", ["근육량 증가", "규칙적인 운동", "체지방률 감소"]), - ("식습관 개선", ["음식 섭취 패턴 안정화", "안정된 영양소 섭취", "수분 섭취", "외식 줄이기", "저염식"]), - ("건강 관리", ["금연 / 금주", "혈당 안정화", "음식 일기", "피부 개선"]), - ("수면 및 스트레스", ["수면 개선", "스트레스"]) - ] - @Published private(set) var selectedArticles: [ArticleEntity] = [] + + @Published var weight : Int = 0 @Published var distance : Int = 0 @@ -33,26 +28,5 @@ final class OnboardingViewModel: ObservableObject { self.distance = distance } - // MARK: - 관심사 추가 / 삭제 - - func addInterest(_ title: String) { - let entity = ArticleEntity(title: title) - guard !selectedArticles.contains(where: { $0.title == title }) else { return } - selectedArticles.append(entity) - } - func removeInterest(_ title: String) { - if let index = selectedArticles.firstIndex(where: { $0.title == title }) { - selectedArticles.remove(at: index) - } - } - - func toggleInterest(_ title: String) { - if selectedArticles.contains(where: { $0.title == title }) { - removeInterest(title) - } else { - addInterest(title) - } - print(selectedArticles) - } } diff --git a/Dietto/Dietto/Presentation/Profile/View/ProfileEditView.swift b/Dietto/Dietto/Presentation/Profile/View/ProfileEditView.swift index a69af82..d027eeb 100644 --- a/Dietto/Dietto/Presentation/Profile/View/ProfileEditView.swift +++ b/Dietto/Dietto/Presentation/Profile/View/ProfileEditView.swift @@ -9,6 +9,7 @@ import SwiftUI import Foundation //MARK: - 뷰 class ProfileEditViewModel: ObservableObject { + @Published var name: String = "" @Published var birthString: String = "" @Published var gender: String = "" diff --git a/Dietto/Dietto/Presentation/SocialLogin/View/LoginView.swift b/Dietto/Dietto/Presentation/SocialLogin/View/LoginView.swift deleted file mode 100644 index 8f4beab..0000000 --- a/Dietto/Dietto/Presentation/SocialLogin/View/LoginView.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// LoginView.swift -// Dietto -// -// Created by 안세훈 on 5/13/25. -// - -import SwiftUI - -struct LoginView: View { - var body: some View { - Text("LoginView") - } -} - -#Preview { - LoginView() -} diff --git a/Dietto/Dietto/Presentation/Workout/View/WorkoutView.swift b/Dietto/Dietto/Presentation/Workout/View/WorkoutView.swift deleted file mode 100644 index 5b280f3..0000000 --- a/Dietto/Dietto/Presentation/Workout/View/WorkoutView.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// WorkoutView.swift -// Dietto -// -// Created by 안세훈 on 5/13/25. -// - -import SwiftUI - -struct WorkoutView: View { - var body: some View { - Text("운동 뷰") - } -} - -#Preview { - WorkoutView() -}