Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feature/(#138)-add…
Browse files Browse the repository at this point in the history
…_bug_report
  • Loading branch information
juyeong525 committed Feb 26, 2024
2 parents d2cce6d + 849bd59 commit cc40b72
Show file tree
Hide file tree
Showing 21 changed files with 512 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public struct TotalPassStudentResponseDTO: Codable {

public extension TotalPassStudentResponseDTO {
func toDomain() -> TotalPassStudentEntity {
TotalPassStudentEntity(
let totalStudentCount = totalStudentCount > 0 ? totalStudentCount: 1
return TotalPassStudentEntity(
totalStudentCount: totalStudentCount,
passedCount: passedCount,
approvedCount: approvedCount
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public struct FetchRecruitmentListUseCase {
private let recruitmentsRepository: RecruitmentsRepository

public func execute(
page: Int, jobCode: String?, techCode: [String]?, name: String?
page: Int, jobCode: String? = nil, techCode: [String]? = nil, name: String? = nil
) -> Single<[RecruitmentEntity]> {
recruitmentsRepository.fetchRecruitmentList(page: page, jobCode: jobCode, techCode: techCode, name: name)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "fluent_speaker-2-48-regular.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"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.
4 changes: 4 additions & 0 deletions Projects/Modules/DesignSystem/Sources/Image/JobisIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public enum JobisIcon {
case currentPageControl
case defaultPageControl
case pieChart
case sound
case trash
case emptyBookmark

Expand Down Expand Up @@ -100,6 +101,9 @@ public enum JobisIcon {
case .pieChart:
return dsIcons.pieChart.image

case .sound:
return dsIcons.sound.image

case .trash:
return dsIcons.trash.image

Expand Down
251 changes: 251 additions & 0 deletions Projects/Presentation/Sources/Base/BaseBottomSheetViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
import UIKit
import Then
import SnapKit
import RxGesture
import RxSwift
import RxCocoa
import DesignSystem

public enum BottomSheetViewState {
case normal
case custom(height: CGFloat)
}

public class BaseBottomSheetViewController<ViewModel: BaseViewModel>: UIViewController,
ViewControllable,
LifeCyclePublishable,
HasDisposeBag,
AddViewable,
SetLayoutable,
Bindable,
ViewControllerConfigurable,
NavigationConfigurable {
public let viewModel: ViewModel
public var disposeBag = DisposeBag()
public var viewDidLoadPublisher = PublishRelay<Void>()
public var viewWillAppearPublisher = PublishRelay<Void>()
public var viewDidAppearPublisher = PublishRelay<Void>()
public var viewWillDisappearPublisher = PublishRelay<Void>()
public var viewDidDisappearPublisher = PublishRelay<Void>()
private lazy var dimmedView = UIView().then {
$0.backgroundColor = .black.withAlphaComponent(0.5)
$0.alpha = 0
$0.isUserInteractionEnabled = true
}
private let bottomSheetView = UIView().then {
$0.backgroundColor = .clear
}
private let dragIndicatorView = UIView().then {
$0.backgroundColor = .white
$0.layer.cornerRadius = 2
}
public let contentView = UIView().then {
$0.backgroundColor = .GrayScale.gray30
$0.layer.cornerRadius = 16
$0.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
$0.clipsToBounds = true
}
private let state: BottomSheetViewState
private let bottomSheetPanMinTopInset: CGFloat = 50
private let dragHeight = 28.0
private var defaultHeight: CGFloat = 500
private lazy var maxTopInset = (
view.safeAreaInsets.bottom + view.safeAreaLayoutGuide.layoutFrame.height
)
private lazy var bottomSheetViewTopInset: CGFloat = maxTopInset
private lazy var bottomSheetPanStartingTopInset: CGFloat = bottomSheetPanMinTopInset

public init(_ viewModel: ViewModel, state: BottomSheetViewState = .normal) {
self.viewModel = viewModel
self.state = state
super .init(nibName: nil, bundle: nil)
self.modalPresentationStyle = .overFullScreen
}

required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

public override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.addView()
self.setLayout()
}

public override func viewDidLoad() {
super.viewDidLoad()
self.bind()
self.configureNavigation()
self.configureViewController()
}

public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.viewWillAppearPublisher.accept(())
}

public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.viewDidAppearPublisher.accept(())
self.showBottomSheet(atState: state)
}

public override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.viewWillDisappearPublisher.accept(())
}

public override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.viewDidDisappearPublisher.accept(())
}

public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
self.view.endEditing(true)
}

public func addView() {
[
dimmedView,
bottomSheetView
].forEach(view.addSubview(_:))
[
dragIndicatorView,
contentView
].forEach(bottomSheetView.addSubview(_:))
}

public func setLayout() {
dimmedView.snp.makeConstraints {
$0.edges.equalToSuperview()
}
bottomSheetView.snp.updateConstraints {
$0.leading.trailing.bottom.equalToSuperview()
$0.top.equalTo(view.safeAreaLayoutGuide).inset(bottomSheetViewTopInset)
}
dragIndicatorView.snp.makeConstraints {
$0.width.lessThanOrEqualTo(64)
$0.height.lessThanOrEqualTo(4)
$0.centerX.equalToSuperview()
$0.top.lessThanOrEqualToSuperview().inset(12)
}
contentView.snp.makeConstraints {
$0.top.equalTo(dragIndicatorView.snp.bottom).offset(12)
$0.leading.trailing.bottom.equalToSuperview()
}
}

public func bind() {}

public func configureViewController() {
dimmedView.rx.tapGesture()
.when(.recognized)
.bind { [weak self] _ in
self?.dismissBottomSheet()
}
.disposed(by: disposeBag)

bottomSheetView.rx.panGesture()
.skip(1)
.bind(with: self, onNext: { owner, gesture in
let translation = gesture.translation(in: owner.view)
let defaultPadding = owner.maxTopInset - owner.defaultHeight

switch gesture.state {
case .began:
owner.bottomSheetPanStartingTopInset = owner.bottomSheetViewTopInset

case .changed:
if translation.y > 0 {
owner.bottomSheetViewTopInset = owner
.bottomSheetPanStartingTopInset + translation.y
}
owner.bottomSheetView.snp.updateConstraints {
$0.top.equalTo(owner.view.safeAreaLayoutGuide)
.inset(owner.bottomSheetViewTopInset)
}

case .ended:
let nearestValue = owner.nearest(
to: owner.bottomSheetViewTopInset,
inValues: [defaultPadding, owner.maxTopInset]
)

if nearestValue == defaultPadding {
owner.showBottomSheet(atState: owner.state)
} else {
owner.dismissBottomSheet()
}

default:
return
}
})
.disposed(by: disposeBag)
}

public func configureNavigation() {}
}

extension BaseBottomSheetViewController {
private func showBottomSheet(atState: BottomSheetViewState) {
switch atState {
case .normal:
bottomSheetViewTopInset = maxTopInset - defaultHeight - dragHeight
case let .custom(customHegiht):
defaultHeight = customHegiht
let topInset = maxTopInset - customHegiht - dragHeight
if topInset > 0 {
bottomSheetViewTopInset = topInset
} else {
bottomSheetViewTopInset = bottomSheetPanMinTopInset
defaultHeight = maxTopInset - bottomSheetPanMinTopInset
}
}

bottomSheetView.snp.remakeConstraints {
$0.leading.trailing.bottom.equalToSuperview()
$0.top.equalTo(view.safeAreaLayoutGuide).inset(bottomSheetViewTopInset)
}

UIView.animate(
withDuration: 0.2,
delay: 0,
options: .curveEaseInOut
) { self.dimmedView.alpha = 1 }

UIView.animate(
withDuration: 0.5,
delay: 0,
usingSpringWithDamping: 0.76,
initialSpringVelocity: 0.0
) { self.view.layoutIfNeeded() }
}

public func dismissBottomSheet() {
bottomSheetViewTopInset = maxTopInset
bottomSheetView.snp.remakeConstraints {
$0.leading.trailing.bottom.equalToSuperview()
$0.top.equalTo(view.safeAreaLayoutGuide).inset(bottomSheetViewTopInset)
}

UIView.animate(
withDuration: 0.2,
delay: 0,
options: .curveEaseInOut
) {
self.dimmedView.alpha = 0
self.view.layoutIfNeeded()
} completion: { _ in
self.dismiss(animated: false)
}
}

// 가까이 있는 숫자 반환해주는 함수
private func nearest(to number: CGFloat, inValues values: [CGFloat]) -> CGFloat {
guard let nearestVal = values.min(by: { abs(number - $0) < abs(number - $1) })
else { return number }
return nearestVal
}
}
5 changes: 0 additions & 5 deletions Projects/Presentation/Sources/Base/BaseTabBarController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ public class BaseTabBarController: UITabBarController,
private let stroke = UIView().then {
$0.backgroundColor = .GrayScale.gray30
}
private let impactFeedbackGenerator = UIImpactFeedbackGenerator(style: .light)

public override func viewDidLoad() {
super.viewDidLoad()
Expand All @@ -33,10 +32,6 @@ public class BaseTabBarController: UITabBarController,
$0.height.equalTo(1)
}
}

public override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
self.impactFeedbackGenerator.impactOccurred()
}
}

extension BaseTabBarController: UITabBarControllerDelegate {
Expand Down
8 changes: 6 additions & 2 deletions Projects/Presentation/Sources/DI/PresentationAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ public final class PresentationAssembly: Assembly {
container.register(RecruitmentViewController.self) { resolver in
RecruitmentViewController(resolver.resolve(RecruitmentViewModel.self)!)
}
container.register(RecruitmentViewModel.self) { _ in
RecruitmentViewModel()

container.register(RecruitmentViewModel.self) { resolver in
RecruitmentViewModel(
fetchRecruitmentListUseCase: resolver.resolve(FetchRecruitmentListUseCase.self)!,
bookmarkUseCase: resolver.resolve(BookmarkUseCase.self)!
)
}

container.register(BookmarkViewController.self) { resolver in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import UIKit
import DesignSystem

final class SectionTableViewCell: UITableViewCell {
typealias SectionType = (String, UIImage)
final class SectionTableViewCell: BaseTableViewCell<SectionType> {
static let identifier = "SectionTableViewCell"
private let sectionImageView = UIImageView()
private let titleLabel = UILabel()

override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
self.titleLabel.textColor = self.isHighlighted ? .GrayScale.gray90.withAlphaComponent(0.1) : .GrayScale.gray90
self.titleLabel.textColor = self.isHighlighted ? .GrayScale.gray50 : .GrayScale.gray90
}

override func layoutSubviews() {
override func addView() {
[
sectionImageView,
titleLabel
].forEach { self.addSubview($0) }
}

override func setLayout() {
sectionImageView.snp.makeConstraints {
$0.top.bottom.equalToSuperview().inset(12)
$0.width.equalTo(28)
Expand All @@ -28,9 +31,9 @@ final class SectionTableViewCell: UITableViewCell {
}
}

func setCell(image: UIImage, title: String) {
self.sectionImageView.image = image
self.titleLabel.setJobisText(title, font: .body, color: .GrayScale.gray90)
override func adapt(model: SectionType) {
self.sectionImageView.image = model.1
self.titleLabel.setJobisText(model.0, font: .body, color: .GrayScale.gray90)
self.selectionStyle = .none
}
}
Loading

0 comments on commit cc40b72

Please sign in to comment.