Skip to content
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

[CAT-208] 온보딩 - 고양이 이름짓기 뷰 UI 및 로직 #32

Merged
merged 6 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified DependencyGraph/mohanyang_dev_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified DependencyGraph/mohanyang_prod_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public enum Domain: String, Modulable {
case AuthService
case PushService
case UserService
case CatService
}
14 changes: 0 additions & 14 deletions Projects/Core/UserDefaultsClient/Interface/Keys.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// CatServiceInterface.swift
// CatService
//
// Created by 김지현 on 8/17/24.
//

import Foundation

import APIClientInterface

import Dependencies
import DependenciesMacros


@DependencyClient
public struct CatService {
public var fetchCatLists: @Sendable (
_ apiClient: APIClient
) async throws -> CatList

public var changeCatName: @Sendable (
_ apiClient: APIClient,
_ name: String
) async throws -> Void
}

extension CatService: TestDependencyKey {
public static let previewValue = Self()
public static let testValue = Self()
}
46 changes: 46 additions & 0 deletions Projects/Domain/CatService/Interface/API/CatAPIRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// CatAPIRequest.swift
// CatServiceInterface
//
// Created by 김지현 on 8/17/24.
// Copyright © 2024 PomoNyang. All rights reserved.
//

import Foundation
import APIClientInterface

public enum CatAPIrequest {
case fetchCatList, changeCatName(String)
}

extension CatAPIrequest: APIBaseRequest {
public var baseURL: String {
return API.apiBaseURL
}

public var path: String {
switch self {
case .fetchCatList, .changeCatName:
return "/api/v1/cats"
}
}

public var method: HTTPMethod {
switch self {
case .fetchCatList:
return .get
case.changeCatName:
return .put
}
}

public var parameters: RequestParams {
switch self {
case .fetchCatList:
return .requestPlain
case .changeCatName(let name):
let dto = CatDTO.Request.ChangeCatNameRequestDTO(name: name)
return .body(dto)
}
}
}
30 changes: 30 additions & 0 deletions Projects/Domain/CatService/Interface/DTO/CatDTO.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// CatDTO.swift
// CatServiceInterface
//
// Created by 김지현 on 8/17/24.
// Copyright © 2024 PomoNyang. All rights reserved.
//

import Foundation

public typealias CatList = [CatDTO.Response.GetCatListResponseDTO]

public enum CatDTO {
public enum Request { }
public enum Response { }
}

public extension CatDTO.Request {
struct ChangeCatNameRequestDTO: Encodable {
public var name: String
}
}

public extension CatDTO.Response {
struct GetCatListResponseDTO: Equatable, Decodable {
public var no: Int
public var name: String
public var type: String
}
}
20 changes: 20 additions & 0 deletions Projects/Domain/CatService/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import ProjectDescription
import ProjectDescriptionHelpers

@_spi(Domain)
@_spi(Core)
import DependencyPlugin

let project: Project = .makeTMABasedProject(
module: Domain.CatService,
scripts: [],
targets: [
.sources,
.interface
],
dependencies: [
.interface: [
.dependency(rootModule: Core.self)
]
]
)
36 changes: 36 additions & 0 deletions Projects/Domain/CatService/Sources/API/CatAPIClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// CatService.swift
// CatService
//
// Created by 김지현 on 8/17/24.
//

import Foundation

import APIClientInterface
import CatServiceInterface

import Dependencies

extension CatService: DependencyKey {
public static let liveValue: CatService = .live()
private static func live() -> Self {
return CatService(
fetchCatLists: { apiClient in
let request = CatAPIrequest.fetchCatList
return try await apiClient.apiRequest(
request: request,
as: CatList.self
)
},

changeCatName: { apiClient, name in
let request = CatAPIrequest.changeCatName(name)
_ = try await apiClient.apiRequest(
request: request,
as: EmptyResponse.self
)
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ import DependenciesMacros

@DependencyClient
public struct UserService {
public var fetchCatLists: @Sendable (
_ apiClient: APIClient
) async throws -> CatList
public var selectCat: @Sendable (
_ no: Int,
_ apiClient: APIClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
import APIClientInterface

public enum UserAPIrequest {
case fetchCatList, selectCat(Int)
case selectCat(Int)
}

extension UserAPIrequest: APIBaseRequest {
Expand All @@ -20,26 +20,20 @@ extension UserAPIrequest: APIBaseRequest {

public var path: String {
switch self {
case .fetchCatList:
return "/api/v1/cats"
case .selectCat:
return "/api/v1/users/cats"
}
}

public var method: HTTPMethod {
switch self {
case .fetchCatList:
return .get
case .selectCat:
return .put
}
}

public var parameters: RequestParams {
switch self {
case .fetchCatList:
return .requestPlain
case .selectCat(let no):
let dto = UserDTO.Request.SelectCatRequestDTO(catNo: no)
return .body(dto)
Expand Down
8 changes: 0 additions & 8 deletions Projects/Domain/UserService/Interface/DTO/UserDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

import Foundation

public typealias CatList = [UserDTO.Response.GetCatListResponseDTO]

public enum UserDTO {
public enum Request { }
public enum Response { }
Expand All @@ -22,11 +20,5 @@ public extension UserDTO.Request {
}

public extension UserDTO.Response {
struct GetCatListResponseDTO: Equatable, Decodable {
public var no: Int
public var name: String
public var type: String
}

struct SelectCatResponseDTO: Decodable { }
}
7 changes: 0 additions & 7 deletions Projects/Domain/UserService/Sources/API/UserAPIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ extension UserService: DependencyKey {
public static let liveValue: UserService = .live()
private static func live() -> Self {
return UserService(
fetchCatLists: { apiClient in
let request = UserAPIrequest.fetchCatList
return try await apiClient.apiRequest(
request: request,
as: CatList.self
)
},
selectCat: { no, apiClient in
let request = UserAPIrequest.selectCat(no)
_ = try await apiClient.apiRequest(
Expand Down
7 changes: 6 additions & 1 deletion Projects/Feature/Feature/Sources/AppCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ public struct AppCore {

case .home:
return .none


case .onboarding(.selectCat(.presented(.namingCat(.presented(.moveToHome))))):
state.onboarding = nil
state.home = HomeCore.State()
return .none

case .onboarding:
return .none
}
Expand Down
1 change: 1 addition & 0 deletions Projects/Feature/Feature/Sources/AppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public struct AppView: View {
Color.red
}
}
.transition(.opacity)
.onAppear {
store.send(.onAppear)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// NamingCatCore.swift
// OnboardingFeature
//
// Created by 김지현 on 8/17/24.
// Copyright © 2024 PomoNyang. All rights reserved.
//

import UserDefaultsClientInterface
import APIClientInterface
import CatServiceInterface

import ComposableArchitecture

@Reducer
public struct NamingCatCore {
@ObservableState
public struct State: Equatable {
public init(selectedCat: AnyCat) {
self.selectedCat = selectedCat
}

var selectedCat: AnyCat
var text: String = ""
var inputFieldError: NamingCatError?
var tooltip: DownDirectionTooltip? = .init()
}

public enum Action: BindableAction {
case onAppear
case tapStartButton
case moveToHome
case binding(BindingAction<State>)
}

@Dependency(UserDefaultsClient.self) var userDefaultsClient
@Dependency(APIClient.self) var apiClient
@Dependency(CatService.self) var catService

public init() {}

public var body: some ReducerOf<Self> {
BindingReducer()
Reduce(self.core)
}

private func core(state: inout State, action: Action) -> EffectOf<Self> {
let isOnboardedKey = "mohanyang_userdefaults_isOnboarded"

switch action {
case .onAppear:
return .none

case .tapStartButton:
return .run { [text = state.text] send in
_ = try await catService.changeCatName(
apiClient: apiClient,
name: text
)
await userDefaultsClient.setBool(true, key: isOnboardedKey)
await send(.moveToHome)
}

case .moveToHome:
return .none

case .binding(\.text):
state.inputFieldError = setError(state.text)
return .none

case .binding:
return .none
}
}

private func setError(_ text: String) -> NamingCatError? {
var error: NamingCatError? = nil

if text == " " {
error = .startsWithWhiteSpace
} else if text.count > 10 {
error = .exceedsMaxLength
} else if text.containsWhitespaceOrSpecialCharacters() {
error = .hasSpecialCharacter
} else {
error = nil
}

return error
}
}
Loading
Loading