diff --git a/Cuckoo_swiftUI/Cuckoo/Cuckoo.xcodeproj/project.pbxproj b/Cuckoo_swiftUI/Cuckoo/Cuckoo.xcodeproj/project.pbxproj index 7391208..9702806 100644 --- a/Cuckoo_swiftUI/Cuckoo/Cuckoo.xcodeproj/project.pbxproj +++ b/Cuckoo_swiftUI/Cuckoo/Cuckoo.xcodeproj/project.pbxproj @@ -40,6 +40,7 @@ 7A7F87942AEF559E00F14B11 /* CuckooTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7F87932AEF559E00F14B11 /* CuckooTests.swift */; }; 7A7F879E2AEF559E00F14B11 /* CuckooUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7F879D2AEF559E00F14B11 /* CuckooUITests.swift */; }; 7A7F87A02AEF559E00F14B11 /* CuckooUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7F879F2AEF559E00F14B11 /* CuckooUITestsLaunchTests.swift */; }; + 7D8857832B27E78800BD8D82 /* TagViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D8857822B27E78800BD8D82 /* TagViewModel.swift */; }; 7D8DE4BD2B1EAF95004502FF /* MemoTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D8DE4BC2B1EAF95004502FF /* MemoTag.swift */; }; 7D8DE4BF2B1EB078004502FF /* AlarmPreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D8DE4BE2B1EB078004502FF /* AlarmPreset.swift */; }; 7D8DE4C12B1EB0A6004502FF /* NotificationLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D8DE4C02B1EB0A6004502FF /* NotificationLog.swift */; }; @@ -114,6 +115,7 @@ 7A7F87992AEF559E00F14B11 /* CuckooUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CuckooUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7A7F879D2AEF559E00F14B11 /* CuckooUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CuckooUITests.swift; sourceTree = ""; }; 7A7F879F2AEF559E00F14B11 /* CuckooUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CuckooUITestsLaunchTests.swift; sourceTree = ""; }; + 7D8857822B27E78800BD8D82 /* TagViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagViewModel.swift; sourceTree = ""; }; 7D8DE4BC2B1EAF95004502FF /* MemoTag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoTag.swift; sourceTree = ""; }; 7D8DE4BE2B1EB078004502FF /* AlarmPreset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmPreset.swift; sourceTree = ""; }; 7D8DE4C02B1EB0A6004502FF /* NotificationLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationLog.swift; sourceTree = ""; }; @@ -224,6 +226,7 @@ 7DF6B4D32B1B26E800B64CC0 /* MainContainerViewModel.swift */, 7D9AB3CD2B2295AE00B00C09 /* SettingTagViewModel.swift */, 00133EB12B24128E0035AB70 /* UserProfileViewModel.swift */, + 7D8857822B27E78800BD8D82 /* TagViewModel.swift */, ); path = ViewModels; sourceTree = ""; @@ -619,6 +622,7 @@ 7A0601A62B26AD6700055EBB /* LocalNotification.swift in Sources */, 7DF6B4D42B1B26E800B64CC0 /* MainContainerViewModel.swift in Sources */, 00DBF6FC2B1F1FF1001EBCE3 /* SettingAlarmPresetView.swift in Sources */, + 7D8857832B27E78800BD8D82 /* TagViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Cuckoo_swiftUI/Cuckoo/Cuckoo.xcworkspace/xcuserdata/kimkyeongmin.xcuserdatad/UserInterfaceState.xcuserstate b/Cuckoo_swiftUI/Cuckoo/Cuckoo.xcworkspace/xcuserdata/kimkyeongmin.xcuserdatad/UserInterfaceState.xcuserstate index 323bc66..0e1f89c 100644 Binary files a/Cuckoo_swiftUI/Cuckoo/Cuckoo.xcworkspace/xcuserdata/kimkyeongmin.xcuserdatad/UserInterfaceState.xcuserstate and b/Cuckoo_swiftUI/Cuckoo/Cuckoo.xcworkspace/xcuserdata/kimkyeongmin.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Cuckoo_swiftUI/Cuckoo/Cuckoo/Network/API/TagAPI.swift b/Cuckoo_swiftUI/Cuckoo/Cuckoo/Network/API/TagAPI.swift index 457ae76..53d96e2 100644 --- a/Cuckoo_swiftUI/Cuckoo/Cuckoo/Network/API/TagAPI.swift +++ b/Cuckoo_swiftUI/Cuckoo/Cuckoo/Network/API/TagAPI.swift @@ -6,6 +6,7 @@ // import Moya +import Foundation enum TagAPI { case createTag(params: CreateTagRequest) diff --git a/Cuckoo_swiftUI/Cuckoo/Cuckoo/Network/NetworkManager.swift b/Cuckoo_swiftUI/Cuckoo/Cuckoo/Network/NetworkManager.swift index 1d7ee93..1d29529 100644 --- a/Cuckoo_swiftUI/Cuckoo/Cuckoo/Network/NetworkManager.swift +++ b/Cuckoo_swiftUI/Cuckoo/Cuckoo/Network/NetworkManager.swift @@ -13,6 +13,7 @@ let loggerPlugin = NetworkLoggerPlugin(configuration: loggerConfig) class NetworkManager { static let shared = NetworkManager() let memo_provider = MoyaProvider(plugins:[loggerPlugin]) + let preset_provider = MoyaProvider(plugins:[loggerPlugin]) // 공통 네트워크 요청 로직 } diff --git a/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/AddMemoViewModel.swift b/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/AddMemoViewModel.swift index a45541f..50fbc56 100644 --- a/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/AddMemoViewModel.swift +++ b/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/AddMemoViewModel.swift @@ -6,3 +6,45 @@ // import Foundation + + +class AddMemoViewModel: ObservableObject { + @Published var memoType: String = "" + @Published var link: String = "" + @Published var memoContent: String = "" + @Published var selectedReminder: String = "" + private let memoViewModel = MemoViewModel.shared + + func addNewMemo() { + let url = URL(string: link) + let thumbURL = URL(string: "") // 썸네일 URL은 여기서는 빈 문자열로 처리했습니다. + print("작성완료") + // 메모 타입, 내용, URL 등을 사용하여 새 메모 추가 + MemoViewModel.shared.addMemo( + uuid: "86be72a7-9cae-42e1-ab57-b6d7a0df07b3", // 실제 사용자 UUID로 대체 + title: memoType, // 메모 타입 + comment: memoContent, // 메모 내용 + url: url, // 메모 URL + thumbURL: thumbURL, // 썸네일 URL + notificationCycle: 0, // 알림 주기, 예시로 0 사용 + notificationPreset: 0, // 알림 프리셋, 예시로 0 사용 + isPinned: false // 고정 여부, 예시로 false 사용 + ) + } + + + private func convertReminderToCycle(reminder: String) -> Int { + // 알림 주기 문자열을 숫자로 변환하는 로직 + switch reminder { + case "7일": + return 7 + case "14일": + return 14 + // 다른 주기에 대한 처리... + default: + return 0 // '없음' 또는 처리되지 않은 경우 + } + } +} + + diff --git a/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/MemoDetailViewModel.swift b/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/MemoDetailViewModel.swift index 85d624b..cd36462 100644 --- a/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/MemoDetailViewModel.swift +++ b/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/MemoDetailViewModel.swift @@ -6,6 +6,7 @@ // import Foundation +import Combine class MemoDetailViewModel: ObservableObject { @Published var memo: Memo @@ -17,14 +18,21 @@ class MemoDetailViewModel: ObservableObject { @Published var showDeleteAlert = false @Published var selectedReminder: String // 선택된 알람 주기를 저장 private let memoViewModel = MemoViewModel.shared + private let tagViewModel = TagViewModel.shared + private var cancellables = Set() + let reminderOptions = ["없음", "7일", "14일", "21일", "30일"] - init(memo: Memo, allTags: [Tag] = dummyTags, memoTags: [MemoTag] = dummyMemoTags) { - self.memo = memo - self.allTags = allTags - self.memoTags = memoTags + init(memo: Memo) { + self.memo = memo self.selectedReminder = "" - loadTags() + self.allTags = [] + self.tags = [] + self.memoTags = [] + self.isEditing = false + self.showActionButtons = false + self.showDeleteAlert = false + loadTagsForMemo(memoId: memo.id) } func toggleEditing() { @@ -71,6 +79,15 @@ class MemoDetailViewModel: ObservableObject { let relatedTagIds = relatedMemoTags.map { $0.tagId } tags = allTags.filter { relatedTagIds.contains($0.id) } } + private func loadTagsForMemo(memoId: Int) { + // 메모와 연관된 태그 로드 + tagViewModel.loadTagsForMemo(memoId: memoId) + // 결과를 관찰하여 tags 배열 업데이트 + tagViewModel.$tags.receive(on: RunLoop.main).sink { [weak self] loadedTags in + self?.tags = loadedTags + }.store(in: &cancellables) + } + } diff --git a/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/MemoViewModel.swift b/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/MemoViewModel.swift index 2b0c929..bdbea39 100644 --- a/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/MemoViewModel.swift +++ b/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/MemoViewModel.swift @@ -98,8 +98,9 @@ class MemoViewModel: ObservableObject { print("Error updating memo: \(error)") } } - - + } + + // func addMemo( // uuid: String!, @@ -176,17 +177,16 @@ class MemoViewModel: ObservableObject { // } - } - func deleteMemo(uuid: String, memoId: Int) { - NetworkManager.shared.memo_provider.request(.deleteMemo(type: "uuid", identifier: uuid, memo_id: memoId)) { result in - switch result { - case .success: - DispatchQueue.main.async { - self.memos.removeAll(where: { $0.id == memoId }) + func deleteMemo(uuid: String, memoId: Int) { + NetworkManager.shared.memo_provider.request(.deleteMemo(type: "uuid", identifier: uuid, memo_id: memoId)) { result in + switch result { + case .success: + DispatchQueue.main.async { + self.memos.removeAll(where: { $0.id == memoId }) + } + case .failure(let error): + print("Error deleting memo: \(error)") } - case .failure(let error): - print("Error deleting memo: \(error)") } } } -} diff --git a/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/TagViewModel.swift b/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/TagViewModel.swift new file mode 100644 index 0000000..c8943c8 --- /dev/null +++ b/Cuckoo_swiftUI/Cuckoo/Cuckoo/ViewModels/TagViewModel.swift @@ -0,0 +1,35 @@ +// +// TagViewModel.swift +// Cuckoo +// +// Created by 김경민 on 2023/12/12. +// + +import Foundation +import Moya + +class TagViewModel: ObservableObject { + static let shared = TagViewModel() + @Published var tags: [Tag] = [] + private let provider = MoyaProvider() + + func loadTagsForMemo(memoId: Int) { + provider.request(.loadTag(type: "memo", identifier: String(memoId))) { result in + switch result { + case .success(let response): + do { + // 서버로부터 받은 응답을 파싱하여 태그 배열에 저장 + let tagResponse = try JSONDecoder().decode(LoadTagResponse.self, from: response.data) + DispatchQueue.main.async { + self.tags = tagResponse.map { Tag(id: $0.id, name: $0.name, color: $0.color, memoCount: $0.memoCount) } + } + } catch { + print("Error decoding tags: \(error)") + } + case .failure(let error): + print("Error loading tags: \(error)") + } + } + } +} + diff --git a/Cuckoo_swiftUI/Cuckoo/Cuckoo/Views/AddMemoView.swift b/Cuckoo_swiftUI/Cuckoo/Cuckoo/Views/AddMemoView.swift index 6694d27..74ad71b 100644 --- a/Cuckoo_swiftUI/Cuckoo/Cuckoo/Views/AddMemoView.swift +++ b/Cuckoo_swiftUI/Cuckoo/Cuckoo/Views/AddMemoView.swift @@ -10,7 +10,7 @@ import Combine struct AddMemoView: View { - + @StateObject private var viewModel = AddMemoViewModel() @SwiftUI.Environment(\.dismiss) var dismiss var body: some View { @@ -20,16 +20,16 @@ struct AddMemoView: View { .frame(maxWidth: .infinity) VStack(alignment: .leading, spacing: 30) { - MemoTypeFormView() + MemoTypeFormView(memoType: $viewModel.memoType) .frame(maxWidth: .infinity) - MemoUrlTypeFormView() + MemoUrlTypeFormView(link: $viewModel.link) .frame(maxWidth: .infinity) - MemoContentFormView() + MemoContentFormView(memoContent: $viewModel.memoContent) .frame(maxWidth: .infinity) - MemoAlarmIntervalFormView() + MemoAlarmIntervalFormView(selectedReminder: $viewModel.selectedReminder) .frame(maxWidth: .infinity) // MemoPreView() @@ -39,7 +39,9 @@ struct AddMemoView: View { .padding(.horizontal, 30) .frame(maxWidth: .infinity) Spacer() - AddMemoFooterView() + AddMemoFooterView(addMemoAction: { + viewModel.addNewMemo() + }) .frame(height: 60) .frame(maxWidth: .infinity) } @@ -56,6 +58,7 @@ struct AddMemoView_Previews: PreviewProvider { // Components struct MemoTypeFormView: View { + @Binding var memoType: String var body: some View { VStack(alignment: .leading, spacing: 10) { CardTitleText(title: "메모 타입") @@ -71,7 +74,7 @@ struct MemoTypeFormView: View { } struct MemoUrlTypeFormView: View { - @State private var link: String = "" + @Binding var link: String var body: some View { VStack(alignment: .leading, spacing: 10) { @@ -103,12 +106,12 @@ struct MemoUrlTypeFormView: View { struct MemoContentFormView: View { - @State private var memoContent: String = "" // 사용자가 입력할 내용을 저장할 상태 변수입니다. + @Binding var memoContent: String // 사용자가 입력할 내용을 저장할 상태 변수입니다. private let maxCharacterLimit = 250 - - init() { - UITextView.appearance().backgroundColor = .clear - } +// +// init() { +// UITextView.appearance().backgroundColor = .clear +// } var body: some View { VStack(alignment: .leading, spacing: 10) { @@ -145,6 +148,7 @@ struct MemoContentFormView: View { } struct MemoAlarmIntervalFormView: View { + @Binding var selectedReminder: String @State var isEditing: Bool = true var body: some View { @@ -195,11 +199,14 @@ struct MemoPreView: View { } struct AddMemoFooterView: View { + var addMemoAction: () -> Void var body: some View { VStack { + Button(action: addMemoAction) { Text("작성 완료") - .font(.system(size: 20, weight: .bold)) - .foregroundColor(.white) + .font(.system(size: 20, weight: .bold)) + .foregroundColor(.white) + } } .frame(maxWidth: .infinity) .padding(15)