Skip to content

Commit

Permalink
Merge pull request #281 from rlarjsdn3/feat/#279-생일-표시-구현
Browse files Browse the repository at this point in the history
feat: 달력에 생일자 표시 구현, 초대 링크 생성 IndicatorView 추가
  • Loading branch information
rlarjsdn3 authored Jan 16, 2024
2 parents 5fcd910 + c504a9c commit 1e09f61
Show file tree
Hide file tree
Showing 28 changed files with 254 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ extension SectionOfMonthlyCalendar {
static let date6: Date = calendar.date(from: components6)!

static let months: [Date] = [
"2023-12".toDate(), "2024-01".toDate()
"2023-12".toDate(with: "yyyy-MM"), "2024-01".toDate(with: "yyyy-MM")
]
static let dates: [[Date]] = [
[date1, date2, date3],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import Data
import Domain

public final class ImageCalendarCellDIContainer {
public typealias UseCase = CalendarUseCaseProtocol
public typealias Repository = CalendarRepositoryProtocol
public typealias Reactor = ImageCalendarCellReactor

public let type: ImageCalendarCellReactor.CalendarType
public let isSelected: Bool
public let dayResponse: CalendarResponse
public let selection: Bool

private var globalState: GlobalStateProviderProtocol {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
Expand All @@ -27,19 +29,28 @@ public final class ImageCalendarCellDIContainer {

public init(
_ type: ImageCalendarCellReactor.CalendarType,
dayResponse: CalendarResponse,
isSelected selection: Bool
isSelected: Bool = false,
dayResponse: CalendarResponse
) {
self.type = type
self.isSelected = isSelected
self.dayResponse = dayResponse
self.selection = selection
}

public func makeUseCase() -> UseCase {
return CalendarUseCase(calendarRepository: makeRepository())
}

public func makeRepository() -> Repository {
return CalendarRepository()
}

public func makeReactor() -> Reactor {
return ImageCalendarCellReactor(
type,
isSelected: isSelected,
dayResponse: dayResponse,
isSelected: selection,
calendarUseCase: makeUseCase(),
provider: globalState
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public final class CalendarPageCellReactor: Reactor {

// MARK: - Intializer
init(_ yearMonth: String, usecase: CalendarUseCaseProtocol, provider: GlobalStateProviderProtocol) {
self.initialState = State(date: yearMonth.toDate())
self.initialState = State(date: yearMonth.toDate(with: "yyyy-MM"))

self.calendarUseCase = usecase
self.provider = provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ final public class ImageCalendarCellReactor: Reactor {
}

// MARK: - Action
public enum Action { }
public enum Action {
case checkDayOfBirth
}

// MARK: - Mutate
public enum Mutation {
case selectDate
case deselectDate
case injectDateOfBirth(Bool)
}

// MARK: - State
Expand All @@ -34,12 +37,14 @@ final public class ImageCalendarCellReactor: Reactor {
var representativePostId: String
var representativeThumbnailUrl: String
var allFamilyMemebersUploaded: Bool
var isDayOfBirth: Bool
var isSelected: Bool
}

// MARK: - Properties
public var initialState: State

private let calendarUseCase: CalendarUseCaseProtocol
private let provider: GlobalStateProviderProtocol

public var type: CalendarType
Expand All @@ -48,20 +53,23 @@ final public class ImageCalendarCellReactor: Reactor {
// MARK: - Intializer
init(
_ type: CalendarType,
isSelected: Bool,
dayResponse: CalendarResponse,
isSelected selection: Bool,
calendarUseCase: CalendarUseCaseProtocol,
provider: GlobalStateProviderProtocol
) {
self.initialState = State(
date: dayResponse.date,
representativePostId: dayResponse.representativePostId,
representativeThumbnailUrl: dayResponse.representativeThumbnailUrl,
allFamilyMemebersUploaded: dayResponse.allFamilyMemebersUploaded,
isSelected: selection
isDayOfBirth: false,
isSelected: isSelected
)
self.type = type
self.date = dayResponse.date

self.calendarUseCase = calendarUseCase
self.provider = provider
}

Expand All @@ -77,8 +85,11 @@ final public class ImageCalendarCellReactor: Reactor {
// 이전에 선택된 날짜와 같지 않다면 (셀이 재사용되더라도 ToastView가 다시 뜨게 하지 않기 위함)
if !lastSelectedDate.isEqual(with: date) {
let uploaded = $0.0.currentState.allFamilyMemebersUploaded
// 전체 가족 업로드 유무에 따른 토스트 뷰 출력 이벤트 방출함.
$0.0.provider.toastGlobalState.showAllFamilyUploadedToastMessageView(uploaded, selection: date)
// 전체 가족 업로드 유무에 따른 토스트 뷰 출력 이벤트 방출함
$0.0.provider.toastGlobalState.showAllFamilyUploadedToastMessageView(
uploaded,
selection: date
)
}

return Observable<Mutation>.just(.selectDate)
Expand All @@ -93,6 +104,15 @@ final public class ImageCalendarCellReactor: Reactor {

return Observable<Mutation>.merge(mutation, eventMutation)
}

// MARK: - Mutate
public func mutate(action: Action) -> Observable<Mutation> {
switch action {
case .checkDayOfBirth:
let isDateOfBirth: Bool = calendarUseCase.executeCheckDateOfBirth(date)
return Observable<Mutation>.just(.injectDateOfBirth(isDateOfBirth))
}
}

// MARK: - Reduce {
public func reduce(state: State, mutation: Mutation) -> State {
Expand All @@ -103,6 +123,9 @@ final public class ImageCalendarCellReactor: Reactor {

case .deselectDate:
newState.isSelected = false

case let .injectDateOfBirth(isDateOfBirth):
newState.isDayOfBirth = isDateOfBirth
}

return newState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,16 +217,14 @@ extension CalendarPageCell: FSCalendarDataSource {
)
cell.reactor = ImageCalendarCellDIContainer(
.month,
dayResponse: emptyResponse,
isSelected: false
dayResponse: emptyResponse
).makeReactor()
return cell
}

cell.reactor = ImageCalendarCellDIContainer(
.month,
dayResponse: dayResponse,
isSelected: false
dayResponse: dayResponse
).makeReactor()
return cell
// 셀의 날짜가 현재 월(月)과 동일하지 않다면
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import Then
final public class ImageCalendarCell: FSCalendarCell, ReactorKit.View {
// MARK: - Views
private let dayLabel: BibbiLabel = BibbiLabel(.body1Regular, alignment: .center)
private let thumbnailBackgroundView: UIView = UIView()
private let containerView: UIView = UIView()
private let thumbnailView: UIImageView = UIImageView()
private let todayStrokeView: UIView = UIView()
private let badgeView: UIImageView = UIImageView()
private let allFamilyUploadedBadge: UIImageView = UIImageView()
private let dayOfBirthBadge: UIImageView = UIImageView()

// MARK: - Properties
public var disposeBag: RxSwift.DisposeBag = DisposeBag()
Expand All @@ -47,16 +48,16 @@ final public class ImageCalendarCell: FSCalendarCell, ReactorKit.View {
thumbnailView.image = nil
thumbnailView.layer.borderWidth = .zero
thumbnailView.layer.borderColor = UIColor.bibbiWhite.cgColor
badgeView.isHidden = true
todayStrokeView.isHidden = true
allFamilyUploadedBadge.isHidden = true
}

// MARK: - Helpers
private func setupUI() {
contentView.insertSubview(thumbnailView, at: 0)
contentView.insertSubview(thumbnailBackgroundView, at: 0)
contentView.insertSubview(containerView, at: 0)
contentView.addSubviews(
dayLabel, badgeView, todayStrokeView
dayLabel, todayStrokeView, allFamilyUploadedBadge, dayOfBirthBadge
)
}

Expand All @@ -65,7 +66,7 @@ final public class ImageCalendarCell: FSCalendarCell, ReactorKit.View {
$0.center.equalTo(contentView.snp.center)
}

thumbnailBackgroundView.snp.makeConstraints {
containerView.snp.makeConstraints {
$0.center.equalTo(contentView.snp.center)
$0.width.height.equalTo(contentView.snp.width).inset(CalendarCell.AutoLayout.thumbnailInsetValue)
}
Expand All @@ -80,10 +81,16 @@ final public class ImageCalendarCell: FSCalendarCell, ReactorKit.View {
$0.width.height.equalTo(contentView.snp.width).inset(CalendarCell.AutoLayout.thumbnailInsetValue)
}

badgeView.snp.makeConstraints {
$0.top.equalTo(contentView.snp.top).offset(CalendarCell.AutoLayout.badgeOffsetValue)
$0.trailing.equalTo(contentView.snp.trailing).offset(-CalendarCell.AutoLayout.badgeOffsetValue)
$0.width.height.equalTo(15.0)
allFamilyUploadedBadge.snp.makeConstraints {
$0.top.equalToSuperview().offset(2)
$0.trailing.equalToSuperview().offset(-2)
$0.size.equalTo(15)
}

dayOfBirthBadge.snp.makeConstraints {
$0.top.equalToSuperview().offset(2)
$0.leading.equalToSuperview().offset(2)
$0.size.equalTo(15)
}
}

Expand All @@ -92,10 +99,10 @@ final public class ImageCalendarCell: FSCalendarCell, ReactorKit.View {
$0.isHidden = true
}

thumbnailBackgroundView.do {
containerView.do {
$0.clipsToBounds = true
$0.layer.cornerRadius = 13.0
$0.backgroundColor = DesignSystemAsset.gray900.color
$0.backgroundColor = .gray900
}

thumbnailView.do {
Expand All @@ -114,10 +121,16 @@ final public class ImageCalendarCell: FSCalendarCell, ReactorKit.View {
$0.layer.borderColor = DesignSystemAsset.mainGreen.color.cgColor
}

badgeView.do {
allFamilyUploadedBadge.do {
$0.image = DesignSystemAsset.greenSmileEmoji.image
$0.isHidden = true
$0.backgroundColor = UIColor.clear
$0.backgroundColor = .clear
}

dayOfBirthBadge.do {
$0.image = DesignSystemAsset.birthday.image
$0.isHidden = true
$0.backgroundColor = .clear
}
}

Expand All @@ -126,7 +139,12 @@ final public class ImageCalendarCell: FSCalendarCell, ReactorKit.View {
bindOutput(reactor: reactor)
}

private func bindInput(reactor: ImageCalendarCellReactor) { }
private func bindInput(reactor: ImageCalendarCellReactor) {
Observable<Void>.just(())
.map { Reactor.Action.checkDayOfBirth }
.bind(to: reactor.action)
.disposed(by: disposeBag)
}

private func bindOutput(reactor: ImageCalendarCellReactor) {
reactor.state.map { "\($0.date.day)" }
Expand All @@ -147,7 +165,12 @@ final public class ImageCalendarCell: FSCalendarCell, ReactorKit.View {

reactor.state.map { !$0.allFamilyMemebersUploaded }
.distinctUntilChanged()
.bind(to: badgeView.rx.isHidden)
.bind(to: allFamilyUploadedBadge.rx.isHidden)
.disposed(by: disposeBag)

reactor.state.map { !$0.isDayOfBirth }
.distinctUntilChanged()
.bind(to: dayOfBirthBadge.rx.isHidden)
.disposed(by: disposeBag)

reactor.state.map { $0.representativeThumbnailUrl }
Expand All @@ -174,12 +197,12 @@ final public class ImageCalendarCell: FSCalendarCell, ReactorKit.View {
$0.0.todayStrokeView.isHidden = true

$0.0.thumbnailView.alpha = 1.0
$0.0.thumbnailBackgroundView.alpha = 1.0
$0.0.containerView.alpha = 1.0
$0.0.thumbnailView.layer.borderWidth = 2.0
$0.0.thumbnailView.layer.borderColor = UIColor.bibbiWhite.cgColor
} else {
$0.0.thumbnailView.alpha = 0.3
$0.0.thumbnailBackgroundView.alpha = 0.3
$0.0.containerView.alpha = 0.3
$0.0.thumbnailView.layer.borderWidth = 0.0

if reactor.currentState.date.isToday {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,16 +357,15 @@ extension CalendarPostViewController: FSCalendarDataSource {
)
cell.reactor = ImageCalendarCellDIContainer(
.week,
dayResponse: emptyResponse,
isSelected: false
dayResponse: emptyResponse
).makeReactor()
return cell
}

cell.reactor = ImageCalendarCellDIContainer(
.week,
dayResponse: dayResponse,
isSelected: currentState.selectedDate.isEqual(with: date)
isSelected: currentState.selectedDate.isEqual(with: date),
dayResponse: dayResponse
).makeReactor()
return cell
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,32 @@ import Core
import Data
import Domain

public final class FamilyManagementDIContainer: BaseDIContainer {
public typealias ViewController = FamilyManagementViewController
public typealias UseCase = FamilyViewUseCaseProtocol
public typealias Repository = FamilyRepositoryProtocol
public typealias Reactor = FamilyManagementViewReactor

public final class FamilyManagementDIContainer {
// MARK: - Properties
private var globalState: GlobalStateProviderProtocol {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return GlobalStateProvider()
}
return appDelegate.globalStateProvider
}

public func makeViewController() -> ViewController {
// MARK: - Make
public func makeViewController() -> FamilyManagementViewController {
return FamilyManagementViewController(reactor: makeReactor())
}

public func makeUsecase() -> UseCase {
return FamilyViewUseCase(familyRepository: makeRepository())
public func makeFamilyUseCase() -> FamilyViewUseCaseProtocol {
return FamilyViewUseCase(familyRepository: makeFamilyRepository())
}

public func makeRepository() -> FamilyRepositoryProtocol {
public func makeFamilyRepository() -> FamilyRepositoryProtocol {
return FamilyRepository()
}

public func makeReactor() -> FamilyManagementViewReactor {
return FamilyManagementViewReactor(familyUseCase: makeUsecase(), provider: globalState)
return FamilyManagementViewReactor(
familyUseCase: makeFamilyUseCase(),
provider: globalState
)
}
}
Loading

0 comments on commit 1e09f61

Please sign in to comment.