Skip to content
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
2 changes: 2 additions & 0 deletions SampoomManagement.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
Expand Down Expand Up @@ -271,6 +272,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_COMPILATION_MODE = wholemodule;
VALIDATE_PRODUCT = YES;
};
Expand Down
32 changes: 29 additions & 3 deletions SampoomManagement/App/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ enum Tabs {
case dashboard, outbound, cart, orders, parts
}

enum SettingNavigation: Hashable {
case settings
}

struct ContentView: View {
// MARK: - Properties
let dependencies: AppDependencies
Expand All @@ -19,6 +23,7 @@ struct ContentView: View {
@State private var selectedTab: Tabs = .dashboard
@State private var ordersNavigationPath = NavigationPath()
@State private var partsNavigationPath = NavigationPath()
@State private var dashboardNavigationPath = NavigationPath()

// MARK: - Initialization
init(dependencies: AppDependencies) {
Expand All @@ -37,7 +42,8 @@ struct ContentView: View {
TabView(selection: $selectedTab) {
// Dashboard 탭 (DashboardView directly)
Tab(value: .dashboard) {
NavigationStack {
NavigationStack(path: $dashboardNavigationPath) {
let user = try? dependencies.authPreferences.getStoredUser()
DashboardView(
viewModel: dashboardViewModel,
onLogoutClick: {
Expand All @@ -52,9 +58,29 @@ struct ContentView: View {
onNavigateOrderList: {
selectedTab = .orders
},
userName: ((try? dependencies.authPreferences.getStoredUser())?.name) ?? "",
branch: ((try? dependencies.authPreferences.getStoredUser())?.branch) ?? ""
onSettingClick: {
dashboardNavigationPath.append(SettingNavigation.settings)
},
userName: user?.name ?? "",
branch: user?.branch ?? "",
userRole: user?.role ?? .user
)
.navigationDestination(for: SettingNavigation.self) { destination in
switch destination {
case .settings:
SettingView(
viewModel: dependencies.makeSettingViewModel(),
onNavigateBack: {
if !dashboardNavigationPath.isEmpty {
dashboardNavigationPath.removeLast()
}
},
onLogoutClick: {
dependencies.authViewModel.handleSignedOutState()
}
Comment thread
Sangyoon98 marked this conversation as resolved.
)
}
}
}
} label: {
Label {
Expand Down
17 changes: 14 additions & 3 deletions SampoomManagement/Core/DI/AppDependencies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class AppDependencies {
let getOrderUseCase: GetOrderUseCase
let createOrderUseCase: CreateOrderUseCase
let getOrderDetailUseCase: GetOrderDetailUseCase
let completeOrderUseCase: CompleteOrderUseCase
let receiveOrderUseCase: ReceiveOrderUseCase
let cancelOrderUseCase: CancelOrderUseCase

Expand Down Expand Up @@ -103,15 +104,15 @@ class AppDependencies {

// Part
partAPI = PartAPI(networkManager: networkManager)
partRepository = PartRepositoryImpl(api: partAPI)
partRepository = PartRepositoryImpl(api: partAPI, preferences: authPreferences)
getCategoryUseCase = GetCategoryUseCase(repository: partRepository)
getGroupUseCase = GetGroupUseCase(repository: partRepository)
getPartUseCase = GetPartUseCase(repository: partRepository)
searchPartsUseCase = SearchPartsUseCase(repository: partRepository)

// Outbound
outboundAPI = OutboundAPI(networkManager: networkManager)
outboundRepository = OutboundRepositoryImpl(api: outboundAPI)
outboundRepository = OutboundRepositoryImpl(api: outboundAPI, preferences: authPreferences)
getOutboundUseCase = GetOutboundUseCase(repository: outboundRepository)
addOutboundUseCase = AddOutboundUseCase(repository: outboundRepository)
deleteOutboundUseCase = DeleteOutboundUseCase(repository: outboundRepository)
Expand All @@ -121,7 +122,7 @@ class AppDependencies {

// Cart
cartAPI = CartAPI(networkManager: networkManager)
cartRepository = CartRepositoryImpl(api: cartAPI)
cartRepository = CartRepositoryImpl(api: cartAPI, preferences: authPreferences)
getCartUseCase = GetCartUseCase(repository: cartRepository)
addCartUseCase = AddCartUseCase(repository: cartRepository)
deleteCartUseCase = DeleteCartUseCase(repository: cartRepository)
Expand All @@ -134,6 +135,7 @@ class AppDependencies {
getOrderUseCase = GetOrderUseCase(repository: orderRepository)
createOrderUseCase = CreateOrderUseCase(repository: orderRepository)
getOrderDetailUseCase = GetOrderDetailUseCase(repository: orderRepository)
completeOrderUseCase = CompleteOrderUseCase(repository: orderRepository)
receiveOrderUseCase = ReceiveOrderUseCase(repository: orderRepository)
cancelOrderUseCase = CancelOrderUseCase(repository: orderRepository)
}
Expand Down Expand Up @@ -206,10 +208,19 @@ class AppDependencies {
return OrderDetailViewModel(
getOrderDetailUseCase: getOrderDetailUseCase,
cancelOrderUseCase: cancelOrderUseCase,
completeOrderUseCase: completeOrderUseCase,
receiveOrderUseCase: receiveOrderUseCase,
globalMessageHandler: globalMessageHandler,
orderId: orderId
)
}

func makeSettingViewModel() -> SettingViewModel {
return SettingViewModel(
authPreferences: authPreferences,
signOutUseCase: signOutUseCase,
globalMessageHandler: globalMessageHandler
)
}
}

6 changes: 5 additions & 1 deletion SampoomManagement/Core/Network/TokenRefreshService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ class TokenRefreshService {
let updatedUser = User(
id: existingUser.id,
name: existingUser.name,
email: existingUser.email,
role: existingUser.role,
accessToken: dto.accessToken,
refreshToken: dto.refreshToken,
expiresIn: dto.expiresIn,
position: existingUser.position,
workspace: existingUser.workspace,
branch: existingUser.branch
branch: existingUser.branch,
agencyId: existingUser.agencyId,
startedAt: existingUser.startedAt,
endedAt: existingUser.endedAt
)

try authPreferences.saveUser(updatedUser)
Expand Down
38 changes: 29 additions & 9 deletions SampoomManagement/Core/Resources/StringResources.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct StringResources {
static let intro = "오늘도 효율적인 재고 관리를 시작해보세요."
static let employee = "직원 관리"
static let partsOnHand = "보유 부품"
static let partsInProgress = "진행중 주문"
static let partsInProgress = "진행중 부품"
static let shortageOfParts = "부족 부품"
static let orderAmount = "주문 금액"
static let recentOrdersTitle = "최근 주문"
Expand Down Expand Up @@ -77,6 +77,7 @@ struct StringResources {
// MARK: - Common
struct Common {
static let ok = "확인"
static let confirm = "확인"
static let cancel = "취소"
static let save = "저장"
static let delete = "삭제"
Expand All @@ -85,6 +86,10 @@ struct StringResources {
static let error = "오류"
static let retry = "다시 시도"
static let loadMore = "더 보기"
static let close = "닫기"
static let detail = "상세 보기"
static let EA = "EA"
static let slash = "-"
}

// MARK: - Search
Expand Down Expand Up @@ -169,11 +174,24 @@ struct StringResources {
static let detailToastOrderReceive = "입고 처리되었습니다"

// Order Status
static let statusPending = "승인대기"
static let statusPending = "대기중"
static let statusConfirmed = "주문확인"
static let statusShipping = "배송중"
static let statusDelayed = "배송지연"
static let statusProducing = "생산중"
static let statusArrived = "배송완료"
static let statusCompleted = "입고완료"
static let statusCanceled = "주문취소"
}

// MARK: - Setting
struct Setting {
static let title = "설정"
static let editProfile = "프로필 수정"
static let logout = "로그아웃"
static let dialogLogout = "로그아웃 하시겠습니까?"
}

// MARK: - Auth
struct Auth {
// Login
Expand Down Expand Up @@ -203,14 +221,16 @@ struct StringResources {

// Validation Messages
static func fieldRequired(_ field: String) -> String {
return "\(field)을(를) 입력해주세요."
return "\(field)을(를) 입력해주세요"
}
static let emailRequired = "이메일을 입력해주세요."
static let emailInvalid = "올바른 이메일 형식이 아닙니다."
static let passwordRequired = "비밀번호를 입력해주세요."
static let passwordTooShort = "비밀번호는 8자 이상이어야 합니다."
static let emailRequired = "이메일을 입력해주세요"
static let emailInvalid = "올바른 이메일 형식이 아닙니다"
static let passwordRequired = "비밀번호를 입력해주세요"
static let passwordTooShort = "비밀번호는 최소 8자 이상이어야 합니다"
static let passwordMaxLength = "비밀번호는 최대 30자까지 가능합니다"
static let passwordComplexity = "영문, 숫자, 특수문자를 각각 1개 이상 포함해야 합니다"
static let passwordInvalid = "비밀번호는 영문과 숫자를 포함해야 합니다."
static let passwordCheckRequired = "비밀번호 확인을 입력해주세요."
static let passwordCheckMismatch = "비밀번호가 일치하지 않습니다."
static let passwordCheckRequired = "비밀번호 확인을 입력해주세요"
static let passwordCheckMismatch = "비밀번호가 일치하지 않습니다"
}
}
2 changes: 1 addition & 1 deletion SampoomManagement/Core/UI/Components/OrderItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct OrderItem: View {
Text(order.createdAt ?? "-")
.font(.gmarketCaption)
.foregroundColor(.textSecondary)
StatusChip(status: order.status.rawValue)
StatusChip(status: order.status)
}
}
.padding(16)
Expand Down
37 changes: 24 additions & 13 deletions SampoomManagement/Core/UI/Components/StatusChip.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation

/// 주문 상태를 표시하는 칩 컴포넌트
struct StatusChip: View {
let status: String // 임시로 String 사용
let status: OrderStatus

var body: some View {
let (text, color) = statusDisplayInfo
Expand All @@ -25,24 +25,35 @@ struct StatusChip: View {
}

private var statusDisplayInfo: (text: String, color: Color) {
switch status.lowercased() {
case "pending":
return ("승인대기", Color(.waitYellow))
case "completed":
return ("입고완료", Color(.successGreen))
case "canceled":
return ("주문취소", Color(.failRed))
default:
return ("승인대기", Color(.waitYellow))
switch status {
case .pending:
return (StringResources.Order.statusPending, Color(.waitYellow))
case .confirmed:
return (StringResources.Order.statusConfirmed, Color(.waitYellow))
case .shipping:
return (StringResources.Order.statusShipping, Color(.waitYellow))
case .delayed:
return (StringResources.Order.statusDelayed, Color(.waitYellow))
case .producing:
return (StringResources.Order.statusProducing, Color(.waitYellow))
case .arrived:
return (StringResources.Order.statusArrived, Color(.waitYellow))
case .completed:
return (StringResources.Order.statusCompleted, Color(.successGreen))
case .canceled:
return (StringResources.Order.statusCanceled, Color(.failRed))
}
}
}

#Preview {
VStack(spacing: 16) {
StatusChip(status: "pending")
StatusChip(status: "completed")
StatusChip(status: "canceled")
StatusChip(status: .pending)
StatusChip(status: .confirmed)
StatusChip(status: .shipping)
StatusChip(status: .arrived)
StatusChip(status: .completed)
StatusChip(status: .canceled)
}
.padding()
}
Loading