diff --git a/project/Projects/App/Sources/RootCoordinator/Main/Center /CenterMainCoordinator.swift b/project/Projects/App/Sources/RootCoordinator/Main/Center /CenterMainCoordinator.swift
index 08b34bbc..6afb2cd9 100644
--- a/project/Projects/App/Sources/RootCoordinator/Main/Center /CenterMainCoordinator.swift
+++ b/project/Projects/App/Sources/RootCoordinator/Main/Center /CenterMainCoordinator.swift
@@ -42,7 +42,7 @@ class CenterMainCoordinator: CenterMainCoordinatable {
)
}
- let tabController = IdleTabBar()
+ let tabController = IdleTabBarProto()
tabController.setViewControllers(info: tabInfo)
tabController.selectedIndex = 0
diff --git a/project/Projects/App/Sources/RootCoordinator/Main/Worker/WorkerMainCoordinator.swift b/project/Projects/App/Sources/RootCoordinator/Main/Worker/WorkerMainCoordinator.swift
index 1bdea884..8f1578fb 100644
--- a/project/Projects/App/Sources/RootCoordinator/Main/Worker/WorkerMainCoordinator.swift
+++ b/project/Projects/App/Sources/RootCoordinator/Main/Worker/WorkerMainCoordinator.swift
@@ -31,76 +31,61 @@ class WorkerMainCoordinator: ParentCoordinator {
func start() {
- let tabInfo = WorkerMainScreen.allCases.map { tab in
+ let pageInfo = IdleWorkerMainPage.allCases.map { page in
- TabBarInfo(
- viewController: createNavForTab(tab: tab),
- tabBarItem: .init(
- name: tab.name
- )
+ let navigationController = createNavForTab(page: page)
+
+ return IdleTabBar.PageTabItemInfo(
+ page: page,
+ navigationController: navigationController
)
}
- let tabController = IdleTabBar()
- tabController.setViewControllers(info: tabInfo)
- tabController.selectedIndex = 0
+ let tabController = IdleTabBar(
+ initialPage: IdleWorkerMainPage.home,
+ info: pageInfo
+ )
+
navigationController.pushViewController(tabController, animated: false)
}
// #1. Tab별 네비게이션 컨트롤러 생성
- func createNavForTab(tab: WorkerMainScreen) -> UINavigationController {
+ func createNavForTab(page: IdleWorkerMainPage) -> UINavigationController {
let tabNavController = UINavigationController()
tabNavController.setNavigationBarHidden(false, animated: false)
startTabCoordinator(
- tab: tab,
+ page: page,
navigationController: tabNavController
)
return tabNavController
}
// #2. 생성한 컨트롤러를 각 탭별 Coordinator에 전달
- func startTabCoordinator(tab: WorkerMainScreen, navigationController: UINavigationController) {
+ func startTabCoordinator(page: IdleWorkerMainPage, navigationController: UINavigationController) {
var coordinator: ChildCoordinator!
- switch tab {
- case .recruitmentBoard:
+ switch page {
+ case .home:
coordinator = RecruitmentBoardCoordinator(
navigationController: navigationController
)
- case .applyManagement:
+ case .preferredPost:
coordinator = ApplyManagementCoordinator(
navigationController: navigationController
)
case .setting:
- coordinator = SettingCoordinator(
+ coordinator = RecruitmentBoardCoordinator(
navigationController: navigationController
)
}
+
addChildCoordinator(coordinator)
// 코디네이터들을 실행
coordinator.start()
}
}
-
-// MARK: Worker 탭의 구성요소들
-enum WorkerMainScreen: Int, CaseIterable {
- case recruitmentBoard = 0
- case applyManagement = 1
- case setting = 2
-
- var name: String {
- switch self {
- case .recruitmentBoard:
- "채용"
- case .applyManagement:
- "공고관리"
- case .setting:
- "설정"
- }
- }
-}
diff --git a/project/Projects/App/Sources/RootCoordinator/RootCoordinator+Extension.swift b/project/Projects/App/Sources/RootCoordinator/RootCoordinator+Extension.swift
index a5b5dcc7..3e032225 100644
--- a/project/Projects/App/Sources/RootCoordinator/RootCoordinator+Extension.swift
+++ b/project/Projects/App/Sources/RootCoordinator/RootCoordinator+Extension.swift
@@ -13,14 +13,18 @@ extension RootCoordinator {
/// 로그인및 회원가입을 실행합니다.
func auth() {
- let authCoordinator = AuthCoordinator(
+ let coordinator = AuthCoordinator(
dependency: .init(
navigationController: navigationController,
injector: injector
)
)
- authCoordinator.start()
+ coordinator.parent = self
+
+ addChildCoordinator(coordinator)
+
+ coordinator.start()
}
/// 요양보호사 메인화면을 실행합니다.
diff --git a/project/Projects/App/Sources/RootCoordinator/RootCoordinator.swift b/project/Projects/App/Sources/RootCoordinator/RootCoordinator.swift
index e0e9da8e..b9fbe6b2 100644
--- a/project/Projects/App/Sources/RootCoordinator/RootCoordinator.swift
+++ b/project/Projects/App/Sources/RootCoordinator/RootCoordinator.swift
@@ -28,7 +28,7 @@ class RootCoordinator: ParentCoordinator {
func start() {
navigationController.setNavigationBarHidden(true, animated: false)
- centerMain()
+ workerMain()
}
func popViewController() {
diff --git a/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_home.imageset/Contents.json b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_home.imageset/Contents.json
new file mode 100644
index 00000000..4b897f29
--- /dev/null
+++ b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_home.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "filename" : "worker_home.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+}
diff --git a/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_home.imageset/worker_home.svg b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_home.imageset/worker_home.svg
new file mode 100644
index 00000000..63da851f
--- /dev/null
+++ b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_home.imageset/worker_home.svg
@@ -0,0 +1,3 @@
+
diff --git a/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_post.imageset/Contents.json b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_post.imageset/Contents.json
new file mode 100644
index 00000000..ff1988bd
--- /dev/null
+++ b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_post.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "filename" : "worker_post.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+}
diff --git a/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_post.imageset/worker_post.svg b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_post.imageset/worker_post.svg
new file mode 100644
index 00000000..074fa3ef
--- /dev/null
+++ b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_post.imageset/worker_post.svg
@@ -0,0 +1,6 @@
+
diff --git a/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_setting.imageset/Contents.json b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_setting.imageset/Contents.json
new file mode 100644
index 00000000..f2dbb21c
--- /dev/null
+++ b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_setting.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "filename" : "worker_setting.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+}
diff --git a/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_setting.imageset/worker_setting.svg b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_setting.imageset/worker_setting.svg
new file mode 100644
index 00000000..51efca5e
--- /dev/null
+++ b/project/Projects/Presentation/DSKit/Resources/Icons.xcassets/worker_setting.imageset/worker_setting.svg
@@ -0,0 +1,3 @@
+
diff --git a/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBar.swift b/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBarProto.swift
similarity index 95%
rename from project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBar.swift
rename to project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBarProto.swift
index 33bcba96..99c407c2 100644
--- a/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBar.swift
+++ b/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBarProto.swift
@@ -1,5 +1,5 @@
//
-// IdleTabBar.swift
+// IdleTabBarProto.swift
// PresentationCore
//
// Created by choijunios on 7/25/24.
@@ -10,14 +10,14 @@ import RxSwift
import RxCocoa
import PresentationCore
-public class IdleTabBar: UIViewController {
+public class IdleTabBarProto: UIViewController {
// Coordinator
public weak var coordinator: ParentCoordinator?
// 탭바구성
public private(set) var viewControllers: [UIViewController] = []
- private var tabBarItems: [IdleTabBarItem] = []
+ private var tabBarItems: [IdleTabBarItemProto] = []
// View
var tabBarItemStack: UIView!
@@ -151,7 +151,7 @@ public protocol IdleTabBarItemViewable: UIView {
}
-public struct IdleTabBarItem {
+public struct IdleTabBarItemProto {
let name: String
public init(name: String) {
@@ -161,9 +161,9 @@ public struct IdleTabBarItem {
public struct TabBarInfo {
let viewController: UIViewController
- let tabBarItem: IdleTabBarItem
+ let tabBarItem: IdleTabBarItemProto
- public init(viewController: UIViewController, tabBarItem: IdleTabBarItem) {
+ public init(viewController: UIViewController, tabBarItem: IdleTabBarItemProto) {
self.viewController = viewController
self.tabBarItem = tabBarItem
}
diff --git a/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/TabBarContainer/IdleTabBarItem.swift b/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/TabBarContainer/IdleTabBarItem.swift
new file mode 100644
index 00000000..8ebb488a
--- /dev/null
+++ b/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/TabBarContainer/IdleTabBarItem.swift
@@ -0,0 +1,95 @@
+//
+// itemView.swift
+// DSKit
+//
+// Created by choijunios on 8/15/24.
+//
+
+import UIKit
+import RxSwift
+import RxCocoa
+
+/// 메인 화면의 탭바 아이템으로 사용됩니다.
+public class IdleTabBarItem: TappableUIView {
+
+ // Init
+ public let index: Int
+
+ // State components
+ public enum State {
+ case idle
+ case accent
+ }
+
+ // idle
+ let idleIconColor: UIColor = DSColor.gray300.color
+
+
+ // accent
+ let accentIconColor: UIColor = DSColor.gray700.color
+
+ // View
+ let label: IdleLabel = {
+ let label = IdleLabel(typography: .caption)
+ label.attrTextColor = DSColor.gray700.color
+ return label
+ }()
+ let imageView: UIImageView = {
+ let view = UIImageView()
+ view.contentMode = .scaleAspectFit
+ return view
+ }()
+
+ public init(index: Int, labelText: String, image: UIImage) {
+ self.index = index
+ self.label.textString = labelText
+ self.imageView.image = image
+
+ super.init()
+
+ setAppearance()
+ setLayout()
+ }
+ public required init?(coder: NSCoder) { nil }
+
+ private func setAppearance() {
+ imageView.tintColor = idleIconColor
+ }
+
+ private func setLayout() {
+ let mainStack = VStack([imageView, label], spacing: 4, alignment: .center)
+
+ self.addSubview(mainStack)
+ mainStack.translatesAutoresizingMaskIntoConstraints = false
+
+ NSLayoutConstraint.activate([
+ imageView.widthAnchor.constraint(equalToConstant: 32),
+ imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
+
+ mainStack.topAnchor.constraint(equalTo: self.topAnchor),
+ mainStack.leftAnchor.constraint(equalTo: self.leftAnchor),
+ mainStack.rightAnchor.constraint(equalTo: self.rightAnchor),
+ mainStack.bottomAnchor.constraint(equalTo: self.bottomAnchor),
+ ])
+ }
+
+ /// 탭바 아이템의 상태를 변경합니다.
+ public func setState(_ state: State, duration: CGFloat = 0.2) {
+ UIView.animate(withDuration: duration) { [weak self] in
+ if state == .accent {
+ self?.setToAccent()
+ } else {
+ self?.setToIdle()
+ }
+ }
+ }
+
+ private func setToIdle() {
+ imageView.tintColor = idleIconColor
+ }
+
+ private func setToAccent() {
+ imageView.tintColor = accentIconColor
+ }
+}
+
diff --git a/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/TabBarContainer/TabBarContainer.swift b/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/TabBarContainer/TabBarContainer.swift
new file mode 100644
index 00000000..ed550753
--- /dev/null
+++ b/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/TabBarContainer/TabBarContainer.swift
@@ -0,0 +1,65 @@
+//
+// TabBarContainer.swift
+// DSKit
+//
+// Created by choijunios on 8/15/24.
+//
+
+import UIKit
+import RxSwift
+import RxCocoa
+
+public class IdleTabBarContainer: UIView {
+
+ let items: [UIView]
+
+ public init(items: [UIView]) {
+ self.items = items
+ super.init(frame: .zero)
+
+ setAppearance()
+ setLayout()
+ }
+ required init?(coder: NSCoder) { nil }
+
+ func setAppearance() {
+ self.backgroundColor = DSColor.gray0.color
+ }
+
+ func setLayout() {
+ self.layoutMargins = .init(
+ top: 8,
+ left: 71.5,
+ bottom: 8,
+ right: 71.5
+ )
+
+ let mainStack = HStack(
+ items,
+ alignment: .fill,
+ distribution: .equalCentering
+ )
+
+ let border = Spacer(height: 1)
+ border.backgroundColor = DSColor.gray100.color
+
+ [
+ border,
+ mainStack
+ ].forEach {
+ self.addSubview($0)
+ $0.translatesAutoresizingMaskIntoConstraints = false
+ }
+
+ NSLayoutConstraint.activate([
+ mainStack.topAnchor.constraint(equalTo: self.layoutMarginsGuide.topAnchor),
+ mainStack.leftAnchor.constraint(equalTo: self.layoutMarginsGuide.leftAnchor),
+ mainStack.rightAnchor.constraint(equalTo: self.layoutMarginsGuide.rightAnchor),
+ mainStack.bottomAnchor.constraint(equalTo: self.layoutMarginsGuide.bottomAnchor),
+
+ border.topAnchor.constraint(equalTo: self.topAnchor),
+ border.leftAnchor.constraint(equalTo: self.leftAnchor),
+ border.rightAnchor.constraint(equalTo: self.rightAnchor),
+ ])
+ }
+}
diff --git a/project/Projects/Presentation/DSKit/Sources/Component/Base/DSKitShortcuts.swift b/project/Projects/Presentation/DSKit/Sources/Component/Base/DSKitShortcuts.swift
new file mode 100644
index 00000000..e2696ddc
--- /dev/null
+++ b/project/Projects/Presentation/DSKit/Sources/Component/Base/DSKitShortcuts.swift
@@ -0,0 +1,11 @@
+//
+// DSKitShortcuts.swift
+// DSKit
+//
+// Created by choijunios on 8/15/24.
+//
+
+import Foundation
+
+public typealias DSColor = DSKitAsset.Colors
+public typealias DSIcon = DSKitAsset.Icons
diff --git a/project/Projects/Presentation/Feature/Root/Sources/Screen/TabBar/IdleTabBar.swift b/project/Projects/Presentation/Feature/Root/Sources/Screen/TabBar/IdleTabBar.swift
new file mode 100644
index 00000000..c5b07afe
--- /dev/null
+++ b/project/Projects/Presentation/Feature/Root/Sources/Screen/TabBar/IdleTabBar.swift
@@ -0,0 +1,160 @@
+//
+// IdleTabBar.swift
+// DSKit
+//
+// Created by choijunios on 8/15/24.
+//
+
+import UIKit
+import RxSwift
+import RxCocoa
+import DSKit
+
+public protocol IdleMainPageItemable: Hashable & CaseIterable {
+ var tabItemIcon: UIImage { get }
+ var tabItemText: String { get }
+ var pageOrderNumber: Int { get }
+}
+
+public class IdleTabBar: UIViewController {
+
+ // 탭바구성
+ public private(set) var controllers: [Item: UIViewController] = [:]
+ public private(set) var items: [Item: IdleTabBarItem] = [:]
+
+ // View
+ private(set) var displayingVC: UIViewController?
+
+ // Observable
+ public private(set) var displayingPage: Item?
+
+ // 탭바 컨테이너
+ private var tabBarItemContainer: IdleTabBarContainer!
+
+ // Observable
+ private let disposeBag = DisposeBag()
+
+ public init(
+ initialPage: Item,
+ info: [PageTabItemInfo]
+ ) {
+
+ super.init(nibName: nil, bundle: nil)
+
+ setPageControllers(info)
+ setPageTabItem()
+
+ setAppearance()
+ setLayout()
+ setObservable()
+
+ // 초기세팅
+ items[initialPage]?.setState(.accent)
+ setPage(page: initialPage)
+ }
+
+ public required init?(coder: NSCoder) { fatalError() }
+
+ private func setAppearance() {
+ view.backgroundColor = DSColor.gray0.color
+ }
+
+ private func setLayout() {
+ view.addSubview(tabBarItemContainer)
+ tabBarItemContainer.translatesAutoresizingMaskIntoConstraints = false
+
+ NSLayoutConstraint.activate([
+ tabBarItemContainer.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
+ tabBarItemContainer.leftAnchor.constraint(equalTo: view.leftAnchor),
+ tabBarItemContainer.rightAnchor.constraint(equalTo: view.rightAnchor),
+ ])
+ }
+
+ private func setObservable() {
+
+ let selectionPublishers = items.map { (page: Item, itemView: IdleTabBarItem) in
+ itemView.rx.tap.map { _ in page }
+ }
+
+ Observable
+ .merge(selectionPublishers)
+ .subscribe(onNext: { [weak self] selectedPage in
+ guard let self else { return }
+
+ // 선택된 화면 표출
+ setPage(page: selectedPage)
+
+ // Item들 외향 변경
+ items.forEach { (page: Item, itemView: IdleTabBarItem) in
+
+ itemView.setState(selectedPage == page ? .accent : .idle)
+ }
+ })
+ .disposed(by: disposeBag)
+
+ }
+}
+
+public extension IdleTabBar {
+
+ struct PageTabItemInfo {
+ let page: Item
+ let navigationController: UINavigationController
+
+ public init(page: Item, navigationController: UINavigationController) {
+ self.page = page
+ self.navigationController = navigationController
+ }
+ }
+
+ /// #1. 현재 컨트롤러에 페이지 컨트롤러들을 세팅합니다.
+ private func setPageControllers(_ using: [PageTabItemInfo]) {
+ using.forEach { info in
+ let controller = info.navigationController
+ addChild(controller)
+ controller.didMove(toParent: self)
+ controllers[info.page] = controller
+ }
+ }
+
+ /// #2. 페이지별 탭바 아이템뷰를 설정합니다.
+ private func setPageTabItem() {
+
+ let pages = controllers.keys.sorted { $0.pageOrderNumber < $1.pageOrderNumber }
+
+ let itemViews = pages.map { page in
+ let item = IdleTabBarItem(
+ index: page.pageOrderNumber,
+ labelText: page.tabItemText,
+ image: page.tabItemIcon
+ )
+ items[page] = item
+ return item
+ }
+
+ tabBarItemContainer = IdleTabBarContainer(
+ items: itemViews
+ )
+ }
+
+ /// 해당 함수는 뷰모델에 의해서만 호출됩니다. 특정 페이지를 display합니다.
+ private func setPage(page: Item) {
+
+ displayingVC?.view.removeFromSuperview()
+
+ let willDisplayVC = controllers[page]!
+ let willDisplayView = willDisplayVC.view!
+
+ view.addSubview(willDisplayView)
+ willDisplayView.translatesAutoresizingMaskIntoConstraints = false
+
+ NSLayoutConstraint.activate([
+ willDisplayView.topAnchor.constraint(equalTo: view.topAnchor),
+ willDisplayView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
+ willDisplayView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
+ willDisplayView.bottomAnchor.constraint(equalTo: tabBarItemContainer.topAnchor)
+ ])
+
+ displayingVC = willDisplayVC
+ }
+}
diff --git a/project/Projects/Presentation/Feature/Root/Sources/Screen/TabBar/IdleWorkerMainPage.swift b/project/Projects/Presentation/Feature/Root/Sources/Screen/TabBar/IdleWorkerMainPage.swift
new file mode 100644
index 00000000..b8d64506
--- /dev/null
+++ b/project/Projects/Presentation/Feature/Root/Sources/Screen/TabBar/IdleWorkerMainPage.swift
@@ -0,0 +1,63 @@
+//
+// IdleWorkerMainPage.swift
+// DSKit
+//
+// Created by choijunios on 8/15/24.
+//
+
+import UIKit
+import DSKit
+
+public enum IdleWorkerMainPage: IdleMainPageItemable {
+
+ public enum State {
+ case idle
+ case accent
+ }
+
+ case home
+ case preferredPost
+ case setting
+
+ public init?(index: Int) {
+ switch index {
+ case 0: self = .home
+ case 1: self = .preferredPost
+ case 2: self = .setting
+ default: return nil
+ }
+ }
+
+ public var pageOrderNumber: Int {
+ switch self {
+ case .home:
+ return 0
+ case .preferredPost:
+ return 1
+ case .setting:
+ return 2
+ }
+ }
+
+ public var tabItemIcon: UIImage {
+ switch self {
+ case .home:
+ return DSIcon.workerHome.image
+ case .preferredPost:
+ return DSIcon.workerPost.image
+ case .setting:
+ return DSIcon.workerSetting.image
+ }
+ }
+
+ public var tabItemText: String {
+ switch self {
+ case .home:
+ "홈"
+ case .preferredPost:
+ "공고"
+ case .setting:
+ "설정"
+ }
+ }
+}