Skip to content

Commit 6256dc3

Browse files
author
Roy
authored
Merge pull request #13 from TimeSpotApp/feature/explore
🔍 코드 리뷰: 중요 인증 및 UI 개선사항
1 parent 000c453 commit 6256dc3

59 files changed

Lines changed: 3328 additions & 412 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Projects/App/Sources/Di/DiRegister.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,14 @@ public final class AppDIManager {
4040
.register { AppleLoginRepositoryImpl() as AppleAuthRequestInterface }
4141
.register { AppleOAuthRepositoryImpl() as AppleOAuthInterface }
4242
.register { AppleOAuthProvider() as AppleOAuthProviderInterface }
43-
// MARK: - 회원가입
43+
// MARK: - 회원가입
4444
.register { SignUpRepositoryImpl() as SignUpInterface }
45-
// MARK: - 프로필
45+
// MARK: - 프로필
4646
.register(ProfileInterface.self) { ProfileRepositoryImpl() }
47+
// MARK: - 히스토리
48+
.register(HistoryInterface.self) { HistoryRepositoryImpl() }
49+
// MARK: - 역
50+
.register(StationInterface.self) { StationRepositoryImpl() }
4751

4852

4953

Projects/App/Sources/Reducer/AppReducer.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ extension AppReducer {
202202
case .auth(.navigation(.presentMain)):
203203
return .send(.view(.presentRoot))
204204

205+
case .home(.router(.routeAction(id: _, action: .home(.delegate(.presentAuth))))):
206+
return .send(.view(.presentAuth))
207+
205208
case .home(.router(.routeAction(id: _, action: .profile(.navigation(.presentAuth))))):
206209
return .send(.view(.presentAuth))
207210

Projects/Data/API/Sources/API/Domain/TimeSpotDomain.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ public enum TimeSpotDomain {
1313
case auth
1414
case place
1515
case profile
16+
case history
17+
case station
1618
}
1719

1820
extension TimeSpotDomain: DomainType {
@@ -28,6 +30,10 @@ extension TimeSpotDomain: DomainType {
2830
return "api/v1/place"
2931
case .profile:
3032
return "api/v1/users"
33+
case .history:
34+
return "api/v1/histories"
35+
case .station:
36+
return "api/v1/stations"
3137
}
3238
}
3339
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// HistoryAPI.swift
3+
// API
4+
//
5+
// Created by Wonji Suh on 3/26/26.
6+
//
7+
import Foundation
8+
9+
public enum HistoryAPI: String, CaseIterable {
10+
case myHistory
11+
12+
public var description: String {
13+
switch self {
14+
case .myHistory:
15+
return ""
16+
}
17+
}
18+
}
19+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// StationAPI.swift
3+
// API
4+
//
5+
// Created by Wonji Suh on 3/26/26.
6+
//
7+
8+
import Foundation
9+
10+
public enum StationAPI {
11+
case allStation
12+
case addFavoriteStation
13+
case deleteFavoriteStation(deleteStationId: Int)
14+
15+
public var description: String {
16+
switch self {
17+
case .allStation:
18+
return ""
19+
case .addFavoriteStation:
20+
return "/favorites"
21+
case .deleteFavoriteStation(let deleteStationId):
22+
return "/favorites/\(deleteStationId)"
23+
}
24+
}
25+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
//
2+
// HistoryDTOModel.swift
3+
// Model
4+
//
5+
// Created by Wonji Suh on 3/26/26.
6+
//
7+
8+
import Foundation
9+
10+
public typealias HistoryDTOModel = BaseResponseDTO<HistoryPageResponseDTO>
11+
12+
public struct HistoryPageResponseDTO: Decodable, Equatable {
13+
public let content: [HistoryItemResponseDTO]
14+
public let totalElements: Int
15+
public let totalPages: Int
16+
public let size: Int
17+
public let number: Int
18+
public let first: Bool
19+
public let last: Bool
20+
21+
enum CodingKeys: String, CodingKey {
22+
case content
23+
case totalElements
24+
case totalPages
25+
case size
26+
case number
27+
case first
28+
case last
29+
case hasNext
30+
}
31+
32+
public init(
33+
content: [HistoryItemResponseDTO],
34+
totalElements: Int,
35+
totalPages: Int,
36+
size: Int,
37+
number: Int,
38+
first: Bool,
39+
last: Bool
40+
) {
41+
self.content = content
42+
self.totalElements = totalElements
43+
self.totalPages = totalPages
44+
self.size = size
45+
self.number = number
46+
self.first = first
47+
self.last = last
48+
}
49+
50+
public init(from decoder: Decoder) throws {
51+
let container = try decoder.container(keyedBy: CodingKeys.self)
52+
let content = try container.decode([HistoryItemResponseDTO].self, forKey: .content)
53+
let totalElements = try container.decode(Int.self, forKey: .totalElements)
54+
let totalPages = try container.decode(Int.self, forKey: .totalPages)
55+
let size = try container.decode(Int.self, forKey: .size)
56+
let number = try container.decode(Int.self, forKey: .number)
57+
58+
let hasNext = try container.decodeIfPresent(Bool.self, forKey: .hasNext) ?? false
59+
let first = try container.decodeIfPresent(Bool.self, forKey: .first) ?? (number == 0)
60+
let last = try container.decodeIfPresent(Bool.self, forKey: .last) ?? !hasNext
61+
62+
self.init(
63+
content: content,
64+
totalElements: totalElements,
65+
totalPages: totalPages,
66+
size: size,
67+
number: number,
68+
first: first,
69+
last: last
70+
)
71+
}
72+
}
73+
74+
public struct HistoryItemResponseDTO: Decodable, Equatable {
75+
public let visitingHistoryID: Int
76+
public let stationID: Int
77+
public let stationName: String
78+
public let placeID: Int
79+
public let placeName: String
80+
public let placeCategory: String
81+
public let startTime: String
82+
public let endTime: String?
83+
public let trainDepartureTime: String
84+
public let totalDurationMinutes: Int
85+
public let isInProgress: Bool
86+
public let isSuccess: Bool
87+
public let createdAt: String
88+
89+
enum CodingKeys: String, CodingKey {
90+
case visitingHistoryID = "visitingHistoryId"
91+
case stationID = "stationId"
92+
case stationName
93+
case placeID = "placeId"
94+
case placeName
95+
case placeCategory
96+
case startTime
97+
case endTime
98+
case trainDepartureTime
99+
case totalDurationMinutes
100+
case isInProgress
101+
case isSuccess
102+
case createdAt
103+
}
104+
105+
public init(
106+
visitingHistoryID: Int,
107+
stationID: Int,
108+
stationName: String,
109+
placeID: Int,
110+
placeName: String,
111+
placeCategory: String,
112+
startTime: String,
113+
endTime: String?,
114+
trainDepartureTime: String,
115+
totalDurationMinutes: Int,
116+
isInProgress: Bool,
117+
isSuccess: Bool,
118+
createdAt: String
119+
) {
120+
self.visitingHistoryID = visitingHistoryID
121+
self.stationID = stationID
122+
self.stationName = stationName
123+
self.placeID = placeID
124+
self.placeName = placeName
125+
self.placeCategory = placeCategory
126+
self.startTime = startTime
127+
self.endTime = endTime
128+
self.trainDepartureTime = trainDepartureTime
129+
self.totalDurationMinutes = totalDurationMinutes
130+
self.isInProgress = isInProgress
131+
self.isSuccess = isSuccess
132+
self.createdAt = createdAt
133+
}
134+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// HistoryDTOModel+.swift
3+
// Model
4+
//
5+
// Created by Wonji Suh on 3/26/26.
6+
//
7+
8+
import Entity
9+
10+
public extension HistoryPageResponseDTO {
11+
func toDomain() -> HistoryEntity {
12+
HistoryEntity(
13+
items: content.map { $0.toDomain() },
14+
totalElements: totalElements,
15+
totalPages: totalPages,
16+
size: size,
17+
page: number + 1,
18+
isFirstPage: first,
19+
isLastPage: last
20+
)
21+
}
22+
}
23+
24+
public extension HistoryItemResponseDTO {
25+
func toDomain() -> HistoryItemEntity {
26+
HistoryItemEntity(
27+
id: visitingHistoryID,
28+
stationID: stationID,
29+
stationName: stationName,
30+
placeID: placeID,
31+
placeName: placeName,
32+
placeCategory: placeCategory,
33+
startTime: startTime,
34+
endTime: endTime,
35+
trainDepartureTime: trainDepartureTime,
36+
totalDurationMinutes: totalDurationMinutes,
37+
isInProgress: isInProgress,
38+
isSuccess: isSuccess,
39+
createdAt: createdAt
40+
)
41+
}
42+
}

Projects/Data/Model/Sources/Profile/DTO/ProfileDTO.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ public typealias ProfileDTOModel = BaseResponseDTO<ProfileResponseDTO>
1313
public struct ProfileResponseDTO: Decodable, Equatable {
1414
let userID, email, nickname, mapAPI: String
1515
let role, providerType, createdAt: String
16+
let totalVisitCount, totalJourneyMinutes: Int
1617

1718
enum CodingKeys: String, CodingKey {
1819
case userID = "userId"
1920
case email, nickname
2021
case mapAPI = "mapApi"
2122
case role, providerType, createdAt
23+
case totalVisitCount, totalJourneyMinutes
2224
}
2325

2426
public init(
@@ -28,7 +30,9 @@ public struct ProfileResponseDTO: Decodable, Equatable {
2830
mapAPI: String,
2931
role: String,
3032
providerType: String,
31-
createdAt: String
33+
createdAt: String,
34+
totalJourneyMinutes: Int,
35+
totalVisitCount: Int
3236
) {
3337
self.userID = userID
3438
self.email = email
@@ -37,5 +41,7 @@ public struct ProfileResponseDTO: Decodable, Equatable {
3741
self.role = role
3842
self.providerType = providerType
3943
self.createdAt = createdAt
44+
self.totalVisitCount = totalVisitCount
45+
self.totalJourneyMinutes = totalJourneyMinutes
4046
}
4147
}

Projects/Data/Model/Sources/Profile/Mapper/ProfileDTOModel+.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ public extension ProfileResponseDTO {
3434
email: self.email,
3535
nickname: self.nickname,
3636
mapType: mapType,
37-
provider: provider
37+
provider: provider,
38+
totalVisitCount: totalVisitCount,
39+
totalJourneyMinutes: totalJourneyMinutes
3840
)
3941
}
4042
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// FavoriteStationMutationDTOModel.swift
3+
// Model
4+
//
5+
// Created by Wonji Suh on 3/26/26.
6+
//
7+
8+
import Foundation
9+
10+
public struct FavoriteStationMutationDTOModel: Decodable, Equatable {
11+
public let code: Int
12+
public let message: String
13+
public let data: EmptyResponseDTO?
14+
15+
public init(
16+
code: Int,
17+
message: String,
18+
data: EmptyResponseDTO? = nil
19+
) {
20+
self.code = code
21+
self.message = message
22+
self.data = data
23+
}
24+
25+
enum CodingKeys: String, CodingKey {
26+
case code
27+
case message
28+
case data
29+
}
30+
31+
public init(from decoder: Decoder) throws {
32+
let container = try decoder.container(keyedBy: CodingKeys.self)
33+
self.code = try container.decode(Int.self, forKey: .code)
34+
self.message = try container.decode(String.self, forKey: .message)
35+
self.data = try container.decodeIfPresent(EmptyResponseDTO.self, forKey: .data)
36+
}
37+
}

0 commit comments

Comments
 (0)