Skip to content

Commit

Permalink
[Feat] #459 - 일정 상세뷰 UI 구현
Browse files Browse the repository at this point in the history
[Feat] #459 - 일정 상세뷰 UI 구현
  • Loading branch information
yungu0010 authored Jan 18, 2025
2 parents 31073c1 + 07a6c6e commit 9252f53
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 44 deletions.
6 changes: 6 additions & 0 deletions SOPT-iOS/Projects/Core/Sources/Literals/StringLiterals.swift
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,15 @@ public struct I18N {
public static let instagram = "인스타"
public static let youtube = "유튜브"
}

public struct CalendarDetail {
public static let navigationTitle = "일정"
public static let attendance = "출석하러 가기"
}
}

public struct Soptlog {
public static let navigationTitle = "솝트로그"
public static let editProfile = "프로필 수정"
public static let enrollIntroduce = "프로필 수정에서 한 줄 소개 등록해보세요!"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// HomeCalendarDetailPresentable.swift
// HomeFeatureDemo
//
// Created by 강윤서 on 12/12/24.
// Copyright © 2024 SOPT-iOS. All rights reserved.
//

import Foundation

import BaseFeatureDependency
import Core

public protocol HomeCalendarDetailViewControllable: ViewControllable {}
public protocol HomeCalendarDetailCoordinatable {

}
public typealias HomeCalendarDetailViewModelType = ViewModelType & HomeCalendarDetailCoordinatable
public typealias HomeCalendarDetailPresentable = (vc: HomeCalendarDetailViewControllable, vm: any HomeCalendarDetailViewModelType)
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ import Core
public protocol HomeFeatureBuildable {
func makeHomeForMember() -> HomeForMemberPresentable
func makeHomeForVisitor() -> HomeForVisitorPresentable
func makeHomeCalendarDetail() -> HomeCalendarDetailPresentable
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Core

public protocol HomeForMemberViewControllable: ViewControllable { }
public protocol HomeForMemberCoordinatable {
var onDashBoardCellTapped: (() -> Void)? { get set }

}
public typealias HomeForMemberViewModelType = ViewModelType & HomeForMemberCoordinatable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// HomeCalendarDetailCVC.swift
// HomeFeatureDemo
//
// Created by 강윤서 on 12/12/24.
// Copyright © 2024 SOPT-iOS. All rights reserved.
//

import UIKit

import Then
import DSKit

final class HomeCalendarDetailCVC: UICollectionViewCell {

// MARK: UI Components

private let circleView = UIView().then {
$0.backgroundColor = DSKitAsset.Colors.gray500.color
$0.layer.cornerRadius = 7.5
}

private let stickView = UIView().then {
$0.backgroundColor = DSKitAsset.Colors.gray500.color
}

private let dateLabel = UILabel().then {
$0.font = DSKitFontFamily.Suit.medium.font(size: 14)
$0.textColor = DSKitAsset.Colors.gray300.color
}

private let homeCategoryTagView = HomeSquareTagView()

private let calendarTitleLabel = UILabel().then {
$0.font = DSKitFontFamily.Suit.bold.font(size: 18)
$0.textColor = DSKitAsset.Colors.gray10.color
}

// MARK: - Initialization

override init(frame: CGRect) {
super.init(frame: frame)

setUI()
setLayout()
}

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

// MARK: UI & Layout

extension HomeCalendarDetailCVC {
private func setUI() {
contentView.backgroundColor = .clear
}

private func setLayout() {
contentView.addSubviews(circleView, stickView, dateLabel, homeCategoryTagView, calendarTitleLabel)

circleView.snp.makeConstraints { make in
make.width.height.equalTo(13)
make.top.equalToSuperview().inset(15)
make.leading.equalToSuperview().inset(1.5)
}

stickView.snp.makeConstraints { make in
make.top.equalTo(circleView.snp.bottom)
make.centerX.equalTo(circleView)
make.width.equalTo(1)
make.bottom.equalToSuperview().offset(90)
}

dateLabel.snp.makeConstraints { make in
make.leading.equalTo(circleView.snp.trailing).offset(9.5)
make.centerY.equalTo(circleView)
}

homeCategoryTagView.snp.makeConstraints { make in
make.top.equalTo(dateLabel.snp.bottom).offset(17)
make.leading.equalTo(dateLabel)
}

calendarTitleLabel.snp.makeConstraints { make in
make.centerY.equalTo(homeCategoryTagView)
make.leading.equalTo(homeCategoryTagView.snp.trailing).offset(10)
}
}
}

extension HomeCalendarDetailCVC {
func configureCell(_ model: CalendarDetail) {
dateLabel.text = model.date
calendarTitleLabel.text = model.title
homeCategoryTagView.setData(title: model.type.text,
titleColor: model.type.textColor,
backgroundColor: model.type.backgroundColor)
circleView.backgroundColor = model.isRecentSchedule ? DSKitAsset.Colors.white.color : DSKitAsset.Colors.gray500.color
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
//
// HomeCalendarDetailVC.swift
// HomeFeatureDemo
//
// Created by 강윤서 on 12/12/24.
// Copyright © 2024 SOPT-iOS. All rights reserved.
//

import UIKit
import DSKit
import Core

final class HomeCalendarDetailVC: UIViewController, HomeCalendarDetailViewControllable {

// MARK: Properties

public let viewModel: HomeCalendarDetailViewModel

// MARK: UI Components

private lazy var naviBar = OPNavigationBar(self,
type: .oneLeftButton,
backgroundColor: DSKitAsset.Colors.semanticBackground.color)
.addMiddleLabel(title: I18N.Home.CalendarDetail.navigationTitle, font: DSKitFontFamily.Suit.medium.font(size: 16))


private lazy var collectionView = UICollectionView(
frame: .zero,
collectionViewLayout: UICollectionViewFlowLayout()
).then {
$0.isScrollEnabled = true
$0.showsHorizontalScrollIndicator = false
$0.showsVerticalScrollIndicator = false
$0.contentInset = UIEdgeInsets(top: 16, left: 0, bottom: 138, right: 0)
$0.backgroundColor = .clear
}

private let attendanceButton = AppCustomButton(title: I18N.Home.CalendarDetail.attendance)
.changeCornerRadius(radius: 12)
.setConfigForState(enabledFont: DSKitFontFamily.Suit.semiBold.font(size: 18))

private let gradientView = UIView().then {
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [DSKitAsset.Colors.black.color.withAlphaComponent(0.0).cgColor, DSKitAsset.Colors.black.color.cgColor]
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
$0.layer.addSublayer(gradientLayer)
$0.isUserInteractionEnabled = false
}

// MARK: - Initialization

init(viewModel: HomeCalendarDetailViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}

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

// MARK: - Life Cycle

override func viewDidLoad() {
super.viewDidLoad()

setUI()
setLayout()
setDelegate()
registerCells()
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

if let gradientLayer = gradientView.layer.sublayers?.first as? CAGradientLayer {
gradientLayer.frame = gradientView.bounds
}

scrollToRecentSchedule()
}
}

// MARK: - UI & Layout

extension HomeCalendarDetailVC {
private func setUI() {
view.backgroundColor = DSKitAsset.Colors.semanticBackground.color
self.navigationController?.isNavigationBarHidden = true
}

private func setLayout() {
view.addSubviews(naviBar, collectionView, gradientView, attendanceButton)

naviBar.snp.makeConstraints { make in
make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide)
}

collectionView.snp.makeConstraints { make in
make.top.equalTo(naviBar.snp.bottom)
make.leading.trailing.equalToSuperview().inset(20)
make.bottom.equalToSuperview()
}

gradientView.snp.makeConstraints { make in
make.leading.trailing.bottom.equalToSuperview()
make.height.equalTo(209.adjustedH)
}

attendanceButton.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview().inset(20)
make.bottom.equalToSuperview().inset(34)
make.height.equalTo(56)
}
}
}

// MARK: - Methods

extension HomeCalendarDetailVC {
private func setDelegate() {
collectionView.dataSource = self
collectionView.delegate = self
}

private func registerCells() {
collectionView.register(HomeCalendarDetailCVC.self, forCellWithReuseIdentifier: HomeCalendarDetailCVC.className)
}

private func scrollToRecentSchedule() {
if let index = self.viewModel.calendarDetailList.firstIndex(where: {$0.isRecentSchedule}) {
self.collectionView.scrollToItem(at: IndexPath(item: index, section: 0),
at: .top,
animated: true)
}
}
}

extension HomeCalendarDetailVC: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModel.calendarDetailList.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: HomeCalendarDetailCVC.className, for: indexPath) as? HomeCalendarDetailCVC else { return UICollectionViewCell() }

cell.configureCell(viewModel.calendarDetailList[indexPath.row])

return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let length = self.collectionView.frame.size.width
return CGSize(width: length, height: 96.adjustedH)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// HomeCalendarDetailViewModel.swift
// HomeFeatureDemo
//
// Created by 강윤서 on 12/12/24.
// Copyright © 2024 SOPT-iOS. All rights reserved.
//

import Foundation

import Core
import HomeFeatureInterface

struct CalendarDetail {
let date: String
let title: String
let isRecentSchedule: Bool
let type: DashBoardCalenderCategoryTagType
}


public class HomeCalendarDetailViewModel: HomeCalendarDetailViewModelType {

// TODO: - 서버 연결 필요

let calendarDetailList: [CalendarDetail] = [
CalendarDetail(date: "9월 28일 토요일", title: "OT", isRecentSchedule: false, type: .event),
CalendarDetail(date: "9월 28일 토요일", title: "1차 세미나", isRecentSchedule: false, type: .seminar),
CalendarDetail(date: "9월 28일 토요일", title: "2차 세미나", isRecentSchedule: false, type: .seminar),
CalendarDetail(date: "9월 28일 토요일", title: "3차 세미나", isRecentSchedule: true, type: .seminar),
CalendarDetail(date: "9월 28일 토요일", title: "4차 세미나", isRecentSchedule: false, type: .seminar),
CalendarDetail(date: "9월 28일 토요일", title: "5차 세미나", isRecentSchedule: false, type: .seminar),
CalendarDetail(date: "9월 28일 토요일", title: "6차 세미나", isRecentSchedule: false, type: .seminar),
CalendarDetail(date: "9월 28일 토요일", title: "7차 세미나", isRecentSchedule: false, type: .seminar),
CalendarDetail(date: "9월 28일 토요일", title: "8차 세미나", isRecentSchedule: false, type: .seminar)
]

// MARK: - Inputs

public struct Input { }

// MARK: - Outputs

public struct Output { }

// MARK: - initialization

public init() { }
}

extension HomeCalendarDetailViewModel {
public func transform(from input: Input, cancelBag: CancelBag) -> Output {
let output = Output()
return output
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ enum DashBoardCalenderCategoryTagType: String {
case .event:
return DSKitAsset.Colors.success.color
case .seminar:
return DSKitAsset.Colors.success.color
return DSKitAsset.Colors.secondary.color
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,10 @@ extension HomeBuilder: HomeFeatureBuildable {
let homeForVisitorVC = HomeForVisitorVC(viewModel: viewModel)
return (homeForVisitorVC, viewModel)
}

public func makeHomeCalendarDetail() -> HomeCalendarDetailPresentable {
let viewModel = HomeCalendarDetailViewModel()
let homeCalendarDetailVC = HomeCalendarDetailVC(viewModel: viewModel)
return (homeCalendarDetailVC, viewModel)
}
}
Loading

0 comments on commit 9252f53

Please sign in to comment.