-
Notifications
You must be signed in to change notification settings - Fork 1
Design/#33 내여행탭 #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The head ref may contain hidden characters: "design/#33-\uB0B4\uC5EC\uD589\uD0ED"
Design/#33 내여행탭 #36
Changes from all commits
57a4e79
e915b24
32a8a91
32b9db0
c4a8b5c
2250ca2
0ff2d8d
38435c3
9f8545f
32ab446
2c8fdf4
954ee2a
30bf109
06ed7c6
8a27b75
aab8670
29ae329
fe9cc18
b489aa6
b5e3ac6
882edea
0e66c9a
889ad9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // | ||
| // Date+.swift | ||
| // Core | ||
| // | ||
| // Created by 최안용 on 2/22/26. | ||
| // Copyright © 2026 NDGL-iOS. All rights reserved. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| public extension Date { | ||
| func toKoreanMMdd() -> String { | ||
| let formatter = DateFormatter() | ||
| formatter.locale = Locale(identifier: "ko_KR") | ||
| formatter.dateFormat = "M월 d일" | ||
| return formatter.string(from: self) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // | ||
| // UserDefaultWrapper.swift | ||
| // Core | ||
| // | ||
| // Created by 최안용 on 2/23/26. | ||
| // Copyright © 2026 NDGL-iOS. All rights reserved. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| @propertyWrapper public struct UserDefaultWrapper<T> { | ||
| public var wrappedValue: T? { | ||
| get { | ||
| return UserDefaults.standard.object(forKey: self.key.rawValue) as? T | ||
| } | ||
|
|
||
| set { | ||
| if newValue == nil { | ||
| UserDefaults.standard.removeObject(forKey: self.key.rawValue) | ||
| } else { | ||
| UserDefaults.standard.setValue(newValue, forKey: self.key.rawValue) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private let key: UserDefaultKeys | ||
|
|
||
| public init(key: UserDefaultKeys) { | ||
| self.key = key | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| // | ||
| // UserManager.swift | ||
| // Core | ||
| // | ||
| // Created by 최안용 on 2/23/26. | ||
| // Copyright © 2026 NDGL-iOS. All rights reserved. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| public enum UserDefaultKeys: String { | ||
| case uuid = "uuid" | ||
| case nickname = "nickname" | ||
| case isFirstOpen = "isFirstOpen" | ||
| } | ||
|
|
||
| public final class UserManager { | ||
| @UserDefaultWrapper(key: .uuid) public var uuid: String? | ||
| @UserDefaultWrapper(key: .nickname) public var nickname: String? | ||
| @UserDefaultWrapper(key: .isFirstOpen) private var isFirstOpen: Bool? | ||
|
|
||
| public static let shared = UserManager() | ||
|
|
||
| private init() {} | ||
|
|
||
| public func isFirstOpenApp() -> Bool { | ||
| guard let isFirstOpen else { | ||
| self.isFirstOpen = true | ||
| return true | ||
| } | ||
| return !isFirstOpen | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -10,5 +10,7 @@ import Foundation | |||
|
|
||||
| public protocol UserTravelRepositoryInterface { | ||||
| func createUserTravel(request: CreateTravelRequest) async throws -> CreateTravelResponse | ||||
| // func fetchContentCard(id: Int) async throws -> | ||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 불완전한 주석 처리된 코드 제거 필요 반환 타입이 없는 미완성 선언입니다. 완성할 계획이 없다면 삭제하세요. 🗑️ 제거 제안-// func fetchContentCard(id: Int) async throws ->📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||
| func fetchUpcoming() async throws -> MyTripSummary | ||||
| func fetchUpcomingList(page: Int?, size: Int?) async throws -> [UpcomingInfo] | ||||
| } | ||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| // | ||
| // UpcomingInfo.swift | ||
| // Domain | ||
| // | ||
| // Created by 최안용 on 2/22/26. | ||
| // Copyright © 2026 NDGL-iOS. All rights reserved. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| public struct UpcomingInfo { | ||
| public let id: Int | ||
| public let title: String | ||
| public let country: String | ||
| public let city: String | ||
| public let startDate: Date | ||
| public let endDate: Date | ||
| public let nights: Int | ||
| public let days: Int | ||
| public let templateId: Int | ||
| public let thumbnail: String? | ||
| public let profileImage: String? | ||
|
|
||
| public init( | ||
| id: Int, | ||
| title: String, | ||
| country: String, | ||
| city: String, | ||
| startDate: Date, | ||
| endDate: Date, | ||
| nights: Int, | ||
| days: Int, | ||
| templateId: Int, | ||
| thumbnail: String?, | ||
| profileImage: String? | ||
| ) { | ||
| self.id = id | ||
| self.title = title | ||
| self.country = country | ||
| self.city = city | ||
| self.startDate = startDate | ||
| self.endDate = endDate | ||
| self.nights = nights | ||
| self.days = days | ||
| self.templateId = templateId | ||
| self.thumbnail = thumbnail | ||
| self.profileImage = profileImage | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| // | ||
| // MyTravelUsecase.swift | ||
| // Domain | ||
| // | ||
| // Created by 최안용 on 2/22/26. | ||
| // Copyright © 2026 NDGL-iOS. All rights reserved. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| public protocol MyTravelUsecaseProtocol { | ||
| func fetchMyTripInfo() async throws -> MyTripSummary | ||
| func fetchUpcomingList(page: Int?, size: Int?) async throws -> [UpcomingInfo] | ||
| func fetchRecommendTripList(page: Int?, size: Int?) async throws -> [TripInfo] | ||
| } | ||
|
|
||
| public extension MyTravelUsecaseProtocol { | ||
| func fetchUpcomingList( | ||
| page: Int? = nil, | ||
| size: Int? = nil | ||
| ) async throws -> [UpcomingInfo] { | ||
| try await fetchUpcomingList(page: page, size: size) | ||
| } | ||
|
|
||
| func fetchRecommendTripList( | ||
| page: Int? = nil, | ||
| size: Int? = nil | ||
| ) async throws -> [TripInfo] { | ||
| try await fetchRecommendTripList(page: page, size: size) | ||
| } | ||
| } | ||
|
|
||
| public final class MyTravelUsecase { | ||
| private let travelTemplateRepository: TravelTemplateRepositoryInterface | ||
| private let userTravelRepository: UserTravelRepositoryInterface | ||
|
|
||
| public init( | ||
| travelTemplateRepository: TravelTemplateRepositoryInterface, | ||
| userTravelRepository: UserTravelRepositoryInterface | ||
| ) { | ||
| self.travelTemplateRepository = travelTemplateRepository | ||
| self.userTravelRepository = userTravelRepository | ||
| } | ||
| } | ||
|
|
||
| extension MyTravelUsecase: MyTravelUsecaseProtocol { | ||
| public func fetchMyTripInfo() async throws -> MyTripSummary { | ||
| try await userTravelRepository.fetchUpcoming() | ||
| } | ||
|
|
||
| public func fetchUpcomingList(page: Int?, size: Int?) async throws -> [UpcomingInfo] { | ||
| try await userTravelRepository.fetchUpcomingList(page: page, size: size) | ||
| } | ||
|
|
||
| public func fetchRecommendTripList(page: Int?, size: Int?) async throws -> [TripInfo] { | ||
| try await travelTemplateRepository.fetchRecommendTripList(page: page, size: size) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 135
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 1299
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 133
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 625
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 1427
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 583
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 2441
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 1060
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 57
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 14607
🏁 Script executed:
Repository: YAPP-Github/27th-App-Team-1-iOS
Length of output: 4249
String.toDate()메서드의 성능 최적화 고려DateFormatter는 초기화 비용이 크므로 매 호출마다 새로 생성하는 것은 성능상 비효율적입니다. 다만,DateFormatter는 스레드 안전하지 않으므로 static으로 캐싱할 경우UserTravelTransform처럼 비동기 작업 중 호출되는 시나리오에서는 동기화 문제가 발생할 수 있습니다.메인 스레드에서만 호출된다면 캐싱을 적용하고, 백그라운드 스레드에서도 호출될 가능성이 있다면 현재 방식을 유지하거나 스레드 로컬 저장소(thread-local storage) 또는 직렬 큐로 보호하는 것을 검토해 주세요.
🤖 Prompt for AI Agents