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

[WEAV-121] 홈 - 프로필 탭 구현 #39

Merged
merged 4 commits into from
Nov 5, 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
4 changes: 2 additions & 2 deletions Projects/App/Sources/Navigation/NavigationStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ extension PathType {
SplashAnimatedView()

// features
case .home:
HomeMainView()
case .home(let userInfo):
HomeMainView(userInfo: userInfo)

case .signUp(let subView):
switch subView {
Expand Down
6 changes: 4 additions & 2 deletions Projects/App/Sources/Splash/SplashAnimatedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ struct SplashAnimatedView: View {
/// 로그아웃 -> 애니메이션 계속진행
if isAuthorized {
try? await Task.sleep(for: .seconds(1))
pushToHomeView()
await pushToHomeView()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

await 키워드 사용에 대한 에러 처리 개선 필요

try?를 사용하여 에러를 무시하는 대신, 적절한 에러 처리를 구현하는 것이 좋습니다. 스플래시 화면에서의 네비게이션 실패는 사용자 경험에 중요한 영향을 미칠 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

- await pushToHomeView()
+ do {
+     await pushToHomeView()
+ } catch {
+     Logger.error("홈 화면 이동 실패: \(error)")
+     // 적절한 폴백 처리 또는 사용자에게 알림
+ }

Committable suggestion skipped: line range outside the PR's diff.

break
}
}
Expand Down Expand Up @@ -177,7 +177,9 @@ struct SplashAnimatedView: View {

@MainActor
private func pushToHomeView() {
AppCoordinator.shared.changeRootView(.authDebug)
if let userInfo = AppCoordinator.shared.userInfo {
AppCoordinator.shared.changeRootView(.home(userInfo))
}
Comment on lines +180 to +182
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

userInfo가 nil일 경우의 처리 로직 필요

현재 구현은 userInfo가 nil일 경우 아무런 동작도 하지 않습니다. 이는 잠재적인 데드락이나 사용자 경험 저하를 초래할 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

@MainActor
private func pushToHomeView() {
    if let userInfo = AppCoordinator.shared.userInfo {
        AppCoordinator.shared.changeRootView(.home(userInfo))
+   } else {
+       Logger.error("유저 정보 없음")
+       AppCoordinator.shared.changeRootView(.signUp(.authPhoneInput))
    }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if let userInfo = AppCoordinator.shared.userInfo {
AppCoordinator.shared.changeRootView(.home(userInfo))
}
if let userInfo = AppCoordinator.shared.userInfo {
AppCoordinator.shared.changeRootView(.home(userInfo))
} else {
Logger.error("유저 정보 없음")
AppCoordinator.shared.changeRootView(.signUp(.authPhoneInput))
}

}

private func updateIconStates(for step: SplashAnimationStep) {
Expand Down
10 changes: 9 additions & 1 deletion Projects/Core/CommonKit/Sources/Path/PathTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,21 @@ import Foundation
import Model

public enum PathType: Hashable {
public static func == (lhs: PathType, rhs: PathType) -> Bool {
return lhs.hashValue == rhs.hashValue
}

public func hash(into hasher: inout Hasher) {
hasher.combine(self.name)
}
Comment on lines +13 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

연관값을 무시하는 Hashable 구현이 필요합니다

현재 구현에는 몇 가지 문제점이 있습니다:

  1. hashValue를 직접 비교하는 것은 권장되지 않습니다
  2. 이전 PR #28에서 확인된 것처럼, 연관값과 관계없이 동일한 케이스는 동일하게 취급되어야 합니다

다음과 같이 수정하는 것을 제안합니다:

public static func == (lhs: PathType, rhs: PathType) -> Bool {
-    return lhs.hashValue == rhs.hashValue
+    switch (lhs, rhs) {
+    case (.designPreview, .designPreview),
+         (.authDebug, .authDebug),
+         (.intro, .intro),
+         (.home, .home),
+         (.signUp(let lType), .signUp(let rType)):
+        return lType == rType
+    default:
+        return false
+    }
}

public func hash(into hasher: inout Hasher) {
-    hasher.combine(self.name)
+    switch self {
+    case .designPreview: hasher.combine(0)
+    case .authDebug: hasher.combine(1)
+    case .intro: hasher.combine(2)
+    case .home: hasher.combine(3)
+    case .signUp(let type): 
+        hasher.combine(4)
+        hasher.combine(type)
+    }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static func == (lhs: PathType, rhs: PathType) -> Bool {
return lhs.hashValue == rhs.hashValue
}
public func hash(into hasher: inout Hasher) {
hasher.combine(self.name)
}
public static func == (lhs: PathType, rhs: PathType) -> Bool {
switch (lhs, rhs) {
case (.designPreview, .designPreview),
(.authDebug, .authDebug),
(.intro, .intro),
(.home, .home),
(.signUp(let lType), .signUp(let rType)):
return lType == rType
default:
return false
}
}
public func hash(into hasher: inout Hasher) {
switch self {
case .designPreview: hasher.combine(0)
case .authDebug: hasher.combine(1)
case .intro: hasher.combine(2)
case .home: hasher.combine(3)
case .signUp(let type):
hasher.combine(4)
hasher.combine(type)
}
}


// App
case designPreview
case authDebug
case intro

// Features
case home
case home(UserInfo?)
case signUp(SignUpSubViewType)

#if STAGING || DEBUG
Expand Down
15 changes: 15 additions & 0 deletions Projects/Core/CoreKit/Sources/Int+Ext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Int+Ext.swift
// CoreKit
//
// Created by 김지수 on 11/3/24.
// Copyright © 2024 com.weave. All rights reserved.
//

import Foundation

extension Int {
public func toString() -> String {
return String(self)
}
}
jisu15-kim marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "building_fill.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "building_fill@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "building_fill@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "business_fill.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "business_fill@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "business_fill@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "location_fill.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "location_fill@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "location_fill@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 @@ -8,43 +8,43 @@

import SwiftUI

public enum JobOccupation: CaseIterable {
public enum JobOccupation: String, CaseIterable {
/// 경영관리
case business
case business = "BUSINESS_ADMIN"
/// 영업 마케팅
case marketing
case marketing = "SALES_MARKETING"
/// 연구개발
case research
case research = "RESEARCH_DEVELOPMENT"
/// IT 정보통신
case IT
case IT = "IT_INFORMATION"
/// 금융 회계
case financial
case financial = "FINANCE_ACCOUNTING"
/// 생산 제조
case manufacture
case manufacture = "MANUFACTURING_PRODUCTION"
/// 교육 학술
case education
case education = "EDUCATION_ACADEMIA"
/// 법률 행정
case law
case law = "LAW_ADMINISTRATION"
/// 경찰 소방 군인
case policeFirefighterMilitary
case policeFirefighterMilitary = "MILITARY_SECURITY"
/// 의료 보건
case medical
case medical = "HEALTHCARE_MEDICAL"
/// 미디어 언론
case mediaPress
case mediaPress = "MEDIA_ENTERTAINMENT"
/// 예술 문화
case artCulture
case artCulture = "ARTS_DESIGN"
/// 스포츠
case sports
case sports = "SPORTS"
/// 건설 토목
case construction
case construction = "CONSTRUCTION_ENGINEERING"
/// 운송 물류
case transport
case transport = "TRANSPORTATION_LOGISTICS"
/// 농림 어업
case farming
case farming = "AGRICULTURE_FARMING"
/// 서비스
case service
case service = "SERVICE_INDUSTRY"
/// 기타
case etc
case etc = "OTHER"
}

extension JobOccupation {
Expand Down Expand Up @@ -97,25 +97,6 @@ extension JobOccupation {

extension JobOccupation {
public var requestValue: String {
switch self {
case .business: return "BUSINESS_ADMIN"
case .marketing: return "SALES_MARKETING"
case .research: return "RESEARCH_DEVELOPMENT"
case .IT: return "IT_INFORMATION"
case .financial: return "FINANCE_ACCOUNTING"
case .manufacture: return "MANUFACTURING_PRODUCTION"
case .education: return "EDUCATION_ACADEMIA"
case .law: return "LAW_ADMINISTRATION"
case .policeFirefighterMilitary: return "MILITARY_SECURITY"
case .medical: return "HEALTHCARE_MEDICAL"
case .mediaPress: return "MEDIA_ENTERTAINMENT"
case .artCulture: return "ARTS_DESIGN"
case .sports: return "SPORTS"
case .construction: return "CONSTRUCTION_ENGINEERING"
case .transport: return "TRANSPORTATION_LOGISTICS"
case .farming: return "AGRICULTURE_FARMING"
case .service: return "SERVICE_INDUSTRY"
case .etc: return "OTHER"
}
return self.rawValue
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,37 @@ extension TagListCollectionView: UICollectionViewDataSource, UICollectionViewDel
height: 40
)
}

//MARK: - Constants
private static let rowHeight: CGFloat = 40 + 8
private static let horizontalSpacing: CGFloat = 8
private static let horizontalInsets: CGFloat = 0
private static let verticalInsets: CGFloat = 20

//MARK: - 동적 높이 계산
public static func calculateHeight(tags: [TagModel], deviceWidth: CGFloat) -> CGFloat {
var currentLineWidth: CGFloat = 0
var totalHeight: CGFloat = verticalInsets
var currentLineCount: Int = 1

for tag in tags {
let label = UILabel()
label.font = UIFont.pretendard(._500, size: 14)
label.text = tag.name
label.sizeToFit()

let cellWidth = label.frame.size.width + 24

if currentLineWidth + cellWidth + horizontalSpacing <= deviceWidth - horizontalInsets {
currentLineWidth += cellWidth + horizontalSpacing
} else {
currentLineCount += 1
currentLineWidth = cellWidth + horizontalSpacing
}
}

totalHeight += CGFloat(currentLineCount) * rowHeight - 8

return totalHeight
}
}
23 changes: 20 additions & 3 deletions Projects/Features/Home/Sources/HomeMain/HomeMainIntent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,24 @@
import Foundation
import CommonKit
import CoreKit
import Model
import NetworkKit

//MARK: - Intent
class HomeMainIntent {
private weak var model: HomeMainModelActionable?
private let input: DataModel
private let authService: AuthServiceProtocol

// MARK: Life cycle
init(
model: HomeMainModelActionable,
input: DataModel
input: DataModel,
service: AuthServiceProtocol = AuthService.shared
) {
self.input = input
self.model = model
self.authService = service
}
}

Expand All @@ -37,7 +42,9 @@ extension HomeMainIntent {
func task() async
}

struct DataModel {}
struct DataModel {
let userInfo: UserInfo?
}
}

//MARK: - Intentable
Expand All @@ -46,7 +53,17 @@ extension HomeMainIntent: HomeMainIntent.Intentable {
func onTapTab(_ tab: HomeMainTab) {
model?.setSelectedTab(tab: tab)
}
func onAppear() {}
func onAppear() {
Task {
if let userInfo = input.userInfo {
model?.setUserInfo(userInfo: userInfo)
} else {
let userInfo = try await authService.requestMyUserInfo()
AppCoordinator.shared.userInfo = userInfo
model?.setUserInfo(userInfo: userInfo)
}
}
}
Comment on lines +56 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

사용자 정보 로딩 로직 개선 제안

현재 구현은 작동하지만, 몇 가지 개선이 필요해 보입니다:

  1. 에러 처리가 누락되어 있습니다
  2. 로딩 상태 처리가 없습니다

다음과 같은 개선을 제안드립니다:

 func onAppear() {
     Task {
+        model?.setLoading(true)
         if let userInfo = input.userInfo {
             model?.setUserInfo(userInfo: userInfo)
         } else {
+            do {
                 let userInfo = try await authService.requestMyUserInfo()
                 AppCoordinator.shared.userInfo = userInfo
                 model?.setUserInfo(userInfo: userInfo)
+            } catch {
+                model?.setError(error)
+            }
         }
+        model?.setLoading(false)
     }
 }

Committable suggestion skipped: line range outside the PR's diff.


func task() async {}

Expand Down
9 changes: 8 additions & 1 deletion Projects/Features/Home/Sources/HomeMain/HomeMainModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
import Foundation
import CommonKit
import CoreKit
import Model

final class HomeMainModel: ObservableObject {

//MARK: Stateful
protocol Stateful {
// content
var userInfo: UserInfo? { get }
var selectedTab: HomeMainTab { get set }
var isValidated: Bool { get }

Expand All @@ -28,7 +30,8 @@ final class HomeMainModel: ObservableObject {

//MARK: State Properties
// content
@Published var selectedTab: HomeMainTab = .home
@Published var userInfo: UserInfo?
@Published var selectedTab: HomeMainTab = .profile
@Published var isValidated: Bool = false

// default
Expand All @@ -44,6 +47,7 @@ extension HomeMainModel: HomeMainModel.Stateful {}
//MARK: - Actionable
protocol HomeMainModelActionable: AnyObject {
// content
func setUserInfo(userInfo: UserInfo)
func setSelectedTab(tab: HomeMainTab)
func setValidation(value: Bool)

Expand All @@ -58,6 +62,9 @@ protocol HomeMainModelActionable: AnyObject {

extension HomeMainModel: HomeMainModelActionable {
// content
func setUserInfo(userInfo: UserInfo) {
self.userInfo = userInfo
}
func setSelectedTab(tab: HomeMainTab) {
self.selectedTab = tab
}
Expand Down
Loading
Loading