diff --git a/SOPT-iOS/Projects/Core/Sources/Literals/StringLiterals.swift b/SOPT-iOS/Projects/Core/Sources/Literals/StringLiterals.swift index c94b4159..5b4b4ac0 100644 --- a/SOPT-iOS/Projects/Core/Sources/Literals/StringLiterals.swift +++ b/SOPT-iOS/Projects/Core/Sources/Literals/StringLiterals.swift @@ -246,10 +246,14 @@ public struct I18N { } public struct MainProduct { + public static let headerTitleForVisitor = "SOPT를 더 알고 싶다면, 둘러보세요" public static let playground = "Playground" public static let groupAndStudy = "모임/스터디" public static let member = "멤버" public static let project = "프로젝트" + public static let homePage = "홈페이지" + public static let activityReview = "활동후기" + public static let instagram = "인스타그램" } public struct AppService { diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/Cells/Announcements/AnnouncementCardCVC.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/Announcements/AnnouncementCardCVC.swift similarity index 100% rename from SOPT-iOS/Projects/Features/HomeFeature/Sources/Cells/Announcements/AnnouncementCardCVC.swift rename to SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/Announcements/AnnouncementCardCVC.swift diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/Cells/Announcements/AnnouncementPageContolFooterView.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/Announcements/AnnouncementPageContolFooterView.swift similarity index 100% rename from SOPT-iOS/Projects/Features/HomeFeature/Sources/Cells/Announcements/AnnouncementPageContolFooterView.swift rename to SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/Announcements/AnnouncementPageContolFooterView.swift diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/AppService/AppServiceCardCVC.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/AppService/AppServiceCardCVC.swift index 55d4530d..445d24ba 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/AppService/AppServiceCardCVC.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/AppService/AppServiceCardCVC.swift @@ -80,6 +80,10 @@ extension AppServiceCardCVC { func configureCell(imageURL: String, name: String, badgeText: String) { self.logoImageView.setImage(with: imageURL) self.titleLabel.text = name - self.notificationBadgeView.setData(with: badgeText) + if badgeText.isEmpty { + self.notificationBadgeView.isHidden = true + } else { + self.notificationBadgeView.setData(with: badgeText) + } } } diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/DashBoard/DashBoardCalendarCardCVC.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/Calendar/CalendarCardCVC.swift similarity index 96% rename from SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/DashBoard/DashBoardCalendarCardCVC.swift rename to SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/Calendar/CalendarCardCVC.swift index 994f1726..c89cd770 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/DashBoard/DashBoardCalendarCardCVC.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/Calendar/CalendarCardCVC.swift @@ -11,7 +11,7 @@ import UIKit import Core import DSKit -final class DashBoardCalendarCardCVC: UICollectionViewCell { +final class CalendarCardCVC: UICollectionViewCell { // MARK: - UI Components @@ -83,7 +83,7 @@ final class DashBoardCalendarCardCVC: UICollectionViewCell { // MARK: - UI & Layout -extension DashBoardCalendarCardCVC { +extension CalendarCardCVC { private func setUI() { self.backgroundColor = DSKitAsset.Colors.gray800.color self.layer.cornerRadius = 8 @@ -122,7 +122,7 @@ extension DashBoardCalendarCardCVC { // MARK: - Methods -extension DashBoardCalendarCardCVC { +extension CalendarCardCVC { func configureCell(date: String, tagType: DashBoardCalenderCategoryTagType, title: String, userType: UserType) { self.dateLabel.text = date self.scheduleTitleLabel.text = title diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/DashBoard/DashBoardHeaderView.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/DashBoard/DashBoardCardCVC.swift similarity index 83% rename from SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/DashBoard/DashBoardHeaderView.swift rename to SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/DashBoard/DashBoardCardCVC.swift index 9d2ab2c3..f2f9fe20 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/DashBoard/DashBoardHeaderView.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/DashBoard/DashBoardCardCVC.swift @@ -1,5 +1,5 @@ // -// DashBoardHeaderView.swift +// DashBoardCardCVC.swift // HomeFeature // // Created by Jae Hyun Lee on 11/22/24. @@ -11,7 +11,7 @@ import UIKit import Core import DSKit -final class DashBoardHeaderView: UICollectionReusableView { +final class DashBoardCardCVC: UICollectionViewCell { // MARK: - UI Components @@ -44,7 +44,7 @@ final class DashBoardHeaderView: UICollectionReusableView { // MARK: - UI & Layout -extension DashBoardHeaderView { +extension DashBoardCardCVC { private func setUI() { self.backgroundColor = DSKitAsset.Colors.gray800.color self.layer.cornerRadius = 8 @@ -53,7 +53,8 @@ extension DashBoardHeaderView { private func setLayout() { self.addSubviews( userInfoLabel, - userHistoryView + userHistoryView, + rightArrowWithCircleImageView ) userInfoLabel.snp.makeConstraints { make in @@ -67,10 +68,6 @@ extension DashBoardHeaderView { make.width.equalTo(250) make.height.equalTo(23) } - } - - private func setRightArrowWithCircleImageViewLayout() { - self.addSubview(rightArrowWithCircleImageView) rightArrowWithCircleImageView.snp.makeConstraints { make in make.centerY.equalToSuperview() @@ -82,16 +79,18 @@ extension DashBoardHeaderView { // MARK: - Methods -extension DashBoardHeaderView { - func setData(userType: UserType) { +extension DashBoardCardCVC { + func configureCell(userType: UserType) { switch userType { case .visitor: self.userInfoLabel.text = I18N.Home.DashBoard.UserHistory.encourage + self.rightArrowWithCircleImageView.isHidden = true case .active, .inactive: self.userInfoLabel.text = "김솝트 님은\nSOPT와 N개월 째" - setRightArrowWithCircleImageViewLayout() + self.rightArrowWithCircleImageView.isHidden = false } + self.userInfoLabel.setLineSpacing(lineSpacing: 5) userHistoryView.setData(userType: userType, recentHistory: 35, allHistory: [35, 34, 33, 32, 31, 30, 29]) } } diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/Cells/SocialLinks/SocialLinkCardCVC.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/SocialLinks/SocialLinkCardCVC.swift similarity index 100% rename from SOPT-iOS/Projects/Features/HomeFeature/Sources/Cells/SocialLinks/SocialLinkCardCVC.swift rename to SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Cells/SocialLinks/SocialLinkCardCVC.swift diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForMemberCompositionalLayout.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForMemberCompositionalLayout.swift index 5603255d..fb3f3e5c 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForMemberCompositionalLayout.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForMemberCompositionalLayout.swift @@ -31,6 +31,8 @@ extension HomeForMemberVC { switch sectionKind { case .dashBoard: return self.createDashBoardSection() + case .calendar: + return self.createCalendarSection() case .mainProduct: return self.createMainProductSection() case .appService: @@ -45,20 +47,33 @@ extension HomeForMemberVC { return self.createCoffeeChatSection() case .socialLinks: return self.createSocialLinksSection() - default: - return self.createEmptySection() } } } private func createDashBoardSection() -> NSCollectionLayoutSection { - /// header: 유저 정보 및 활동 히스토리 - let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), - heightDimension: .absolute(123)) - let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, - elementKind: UICollectionView.elementKindSectionHeader, - alignment: .top) + /// item: 유저 정보 및 활동 히스토리 카드 + let dashBoardItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .absolute(123)) + let dashBoardItem = NSCollectionLayoutItem(layoutSize: dashBoardItemSize) + /// group: 유저 정보 및 활동 히스토리 카드 + let dashBoardGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .estimated(123)) + let dashBoardGroup = NSCollectionLayoutGroup.vertical(layoutSize: dashBoardGroupSize, + subitems: [dashBoardItem]) + + /// section 지정 + let section = NSCollectionLayoutSection(group: dashBoardGroup) + section.contentInsets = NSDirectionalEdgeInsets(top: 12, + leading: Metric.collectionViewDefaultSideInset, + bottom: 0, + trailing: Metric.collectionViewDefaultSideInset) + + return section + } + + private func createCalendarSection() -> NSCollectionLayoutSection { /// item: 캘린더 카드 let calendarItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(56)) @@ -72,7 +87,6 @@ extension HomeForMemberVC { /// section 지정 let section = NSCollectionLayoutSection(group: calendarGroup) - section.boundarySupplementaryItems = [header] section.contentInsets = NSDirectionalEdgeInsets(top: 12, leading: Metric.collectionViewDefaultSideInset, bottom: 0, diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForMemberSectionLayoutKind.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForMemberSectionLayoutKind.swift index 01c98d81..0b07fd68 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForMemberSectionLayoutKind.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForMemberSectionLayoutKind.swift @@ -12,6 +12,7 @@ import Core enum HomeForMemberSectionLayoutKind: Int, CaseIterable { case dashBoard + case calendar case mainProduct case appService case insight diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForVisitorCompositionalLayout.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForVisitorCompositionalLayout.swift new file mode 100644 index 00000000..49355069 --- /dev/null +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForVisitorCompositionalLayout.swift @@ -0,0 +1,135 @@ +// +// HomeForVisitorCompositionalLayout.swift +// HomeFeature +// +// Created by Jae Hyun Lee on 12/9/24. +// Copyright © 2024 SOPT-iOS. All rights reserved. +// + +import UIKit + +import Core + +extension HomeForVisitorVC { + private enum Metric { + static let collectionViewDefaultSideInset: Double = 20 + static let defaultItemSpacing: Double = 16 + static let defaultGroupSpacing: Double = 12 + static let defaultLineSpacing: Double = 56 + static let defaultSectionSpacing: Double = 36 + + static let productItemSpacing: Double = 15 + static let appServiceItemSpacing: Double = 16 + } + + func createLayout() -> UICollectionViewCompositionalLayout { + return UICollectionViewCompositionalLayout { sectionIndex, env in + guard let sectionKind = HomeForVisitorSectionLayoutKind(rawValue: sectionIndex) else { return self.createEmptySection() } + + switch sectionKind { + case .dashBoard: + return self.createDashBoardSection() + case .mainProduct: + return self.createMainProductSection() + case .appService: + return self.createAppServiceSection() + } + } + } + + private func createDashBoardSection() -> NSCollectionLayoutSection { + /// item: 대시보드 카드 + let dashBoardItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .absolute(123)) + let dashBoardItem = NSCollectionLayoutItem(layoutSize: dashBoardItemSize) + + /// group: 대시보드 카드 + let dashBoardGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .estimated(123)) + let dashBoardGroup = NSCollectionLayoutGroup.vertical(layoutSize: dashBoardGroupSize, + subitems: [dashBoardItem]) + + /// section 지정 + let section = NSCollectionLayoutSection(group: dashBoardGroup) + section.contentInsets = NSDirectionalEdgeInsets(top: 0, + leading: Metric.collectionViewDefaultSideInset, + bottom: Metric.defaultSectionSpacing, + trailing: Metric.collectionViewDefaultSideInset) + + return section + } + + private func createMainProductSection() -> NSCollectionLayoutSection { + /// header: default + let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .absolute(30)) + let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, + elementKind: UICollectionView.elementKindSectionHeader, + alignment: .top) + + /// item: 프로덕트 카드 + let productItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25), + heightDimension: .absolute(92)) + let productItem = NSCollectionLayoutItem(layoutSize: productItemSize) + + /// group: 프로덕트 카드 + let productGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .estimated(92)) + let productGroup = NSCollectionLayoutGroup.horizontal(layoutSize: productGroupSize, + subitems: [productItem]) + productGroup.interItemSpacing = .fixed(Metric.productItemSpacing) + + /// section 지정 + let section = NSCollectionLayoutSection(group: productGroup) + section.boundarySupplementaryItems = [header] + section.contentInsets = NSDirectionalEdgeInsets(top: Metric.defaultItemSpacing, + leading: Metric.collectionViewDefaultSideInset, + bottom: 40, + trailing: Metric.collectionViewDefaultSideInset) + + return section + } + + private func createAppServiceSection() -> NSCollectionLayoutSection { + /// header: default + let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .absolute(30)) + let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, + elementKind: UICollectionView.elementKindSectionHeader, + alignment: .top) + + /// item: 앱 서비스 카드 + let appServiceItemSize = NSCollectionLayoutSize(widthDimension: .absolute(80), + heightDimension: .absolute(106)) + let appServiceItem = NSCollectionLayoutItem(layoutSize: appServiceItemSize) + + /// group: 앱 서비스 카드 + let appServiceGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .estimated(106)) + let appServiceGroup = NSCollectionLayoutGroup.horizontal(layoutSize: appServiceGroupSize, + subitems: [appServiceItem]) + appServiceGroup.interItemSpacing = .fixed(Metric.appServiceItemSpacing) + + /// section 지정 + let section = NSCollectionLayoutSection(group: appServiceGroup) + section.boundarySupplementaryItems = [header] + section.contentInsets = NSDirectionalEdgeInsets(top: Metric.defaultItemSpacing, + leading: Metric.collectionViewDefaultSideInset, + bottom: Metric.defaultLineSpacing, + trailing: Metric.collectionViewDefaultSideInset) + return section + } + + private func createEmptySection() -> NSCollectionLayoutSection { + let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(1), + heightDimension: .absolute(1)) + let item = NSCollectionLayoutItem(layoutSize: itemSize) + + let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(1), + heightDimension: .absolute(1)) + let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, + subitems: [item]) + + return NSCollectionLayoutSection(group: group) + } +} diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForVisitorSectionLayoutKind.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForVisitorSectionLayoutKind.swift new file mode 100644 index 00000000..c86e8658 --- /dev/null +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/CollectionView/HomeForVisitorSectionLayoutKind.swift @@ -0,0 +1,28 @@ +// +// HomeForVisitorSectionLayoutKind.swift +// HomeFeature +// +// Created by Jae Hyun Lee on 12/9/24. +// Copyright © 2024 SOPT-iOS. All rights reserved. +// + +import Foundation + +import Core + +enum HomeForVisitorSectionLayoutKind: Int, CaseIterable { + case dashBoard + case mainProduct + case appService + + var title: String { + switch self { + case .mainProduct: + return I18N.Home.MainProduct.headerTitleForVisitor + case .appService: + return I18N.Home.AppService.headerTitle + default: + return "" + } + } +} diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Coordinator/HomeBuilder.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Coordinator/HomeBuilder.swift index 48286587..44f535dc 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Coordinator/HomeBuilder.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Coordinator/HomeBuilder.swift @@ -22,8 +22,8 @@ extension HomeBuilder: HomeFeatureBuildable { } public func makeHomeForVisitor() -> HomeForVisitorPresentable { - let homeForVisitorVC = HomeForVisitorVC() let viewModel = HomeForVisitorViewModel() + let homeForVisitorVC = HomeForVisitorVC(viewModel: viewModel) return (homeForVisitorVC, viewModel) } } diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/VC/HomeForMemberVC.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/VC/HomeForMemberVC.swift index df9a114d..5227924f 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/VC/HomeForMemberVC.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/VC/HomeForMemberVC.swift @@ -72,7 +72,7 @@ extension HomeForMemberVC { ) naviBar.snp.makeConstraints { make in - make.leading.top.trailing.equalTo(view.safeAreaLayoutGuide) + make.leading.top.trailing.equalTo(view.safeAreaLayoutGuide) } collectionView.snp.makeConstraints { make in @@ -92,16 +92,15 @@ extension HomeForMemberVC { private func registerCells() { /// Header - self.collectionView.register(DashBoardHeaderView.self, - forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, - withReuseIdentifier: DashBoardHeaderView.className) self.collectionView.register(HomeDefaultHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HomeDefaultHeaderView.className) /// Cell - self.collectionView.register(DashBoardCalendarCardCVC.self, - forCellWithReuseIdentifier: DashBoardCalendarCardCVC.className) + self.collectionView.register(DashBoardCardCVC.self, + forCellWithReuseIdentifier: DashBoardCardCVC.className) + self.collectionView.register(CalendarCardCVC.self, + forCellWithReuseIdentifier: CalendarCardCVC.className) self.collectionView.register(MainProductCardCVC.self, forCellWithReuseIdentifier: MainProductCardCVC.className) self.collectionView.register(AppServiceCardCVC.self, @@ -142,23 +141,12 @@ extension HomeForMemberVC: UICollectionViewDataSource { /// Header View if kind == UICollectionView.elementKindSectionHeader { - switch sectionKind { - /// dashBoard일 경우에만 defaultHeader 대신 UserHistory가 나타나는 커스텀 헤더를 사용합니다. - case .dashBoard: - guard let headerView = collectionView - .dequeueReusableSupplementaryView(ofKind: kind, - withReuseIdentifier: DashBoardHeaderView.className, - for: indexPath) as? DashBoardHeaderView else { return UICollectionReusableView() } - headerView.setData(userType: .active) - return headerView - default: - guard let headerView = collectionView - .dequeueReusableSupplementaryView(ofKind: kind, - withReuseIdentifier: HomeDefaultHeaderView.className, - for: indexPath) as? HomeDefaultHeaderView else { return UICollectionReusableView() } - headerView.setData(sectionKind: sectionKind) - return headerView - } + guard let headerView = collectionView + .dequeueReusableSupplementaryView(ofKind: kind, + withReuseIdentifier: HomeDefaultHeaderView.className, + for: indexPath) as? HomeDefaultHeaderView else { return UICollectionReusableView() } + headerView.setDataForMember(sectionKind: sectionKind) + return headerView } /// Footer View else if kind == UICollectionView.elementKindSectionFooter { switch sectionKind { @@ -182,6 +170,7 @@ extension HomeForMemberVC: UICollectionViewDataSource { switch sectionKind { case .dashBoard: return 1 + case .calendar: return 1 case .mainProduct: return viewModel.productInfoList.count case .appService: return viewModel.appServiceInfoList.count case .insight: return viewModel.insightInfoList.count @@ -189,7 +178,6 @@ extension HomeForMemberVC: UICollectionViewDataSource { case .coffeeChat: return viewModel.coffeeChatHostInfoList.count case .announcement: return viewModel.announcementInfoList.count case .socialLinks: return SocialLinkCardType.allCases.count - default: return 0 } } @@ -198,14 +186,24 @@ extension HomeForMemberVC: UICollectionViewDataSource { switch sectionKind { case .dashBoard: + /// 대시보드 카드 셀 + guard let dashBoardCardCell = collectionView + .dequeueReusableCell(withReuseIdentifier: DashBoardCardCVC.className, + for: indexPath) as? DashBoardCardCVC else { return UICollectionViewCell() } + dashBoardCardCell.configureCell(userType: .active) + + return dashBoardCardCell + + case .calendar: /// 캘린더 카드 셀 guard let calendarCardCell = collectionView - .dequeueReusableCell(withReuseIdentifier: DashBoardCalendarCardCVC.className, - for: indexPath) as? DashBoardCalendarCardCVC else { return UICollectionViewCell() } + .dequeueReusableCell(withReuseIdentifier: CalendarCardCVC.className, + for: indexPath) as? CalendarCardCVC else { return UICollectionViewCell() } calendarCardCell.configureCell(date: "10.22", - tagType: .event, - title: "1차 행사", - userType: .active) + tagType: .event, + title: "1차 행사", + userType: .active) + return calendarCardCell case .mainProduct: @@ -215,9 +213,9 @@ extension HomeForMemberVC: UICollectionViewDataSource { guard let productCardCell = collectionView .dequeueReusableCell(withReuseIdentifier: MainProductCardCVC.className, for: indexPath) as? MainProductCardCVC else { return UICollectionViewCell() } - productCardCell.configureCell(title: product.name, image: product.image) + return productCardCell case .appService: @@ -230,6 +228,7 @@ extension HomeForMemberVC: UICollectionViewDataSource { appServiceCardCell.configureCell(imageURL: appService.imageURL, name: appService.name, badgeText: appService.badgeText) + return appServiceCardCell case .insight: @@ -283,7 +282,6 @@ extension HomeForMemberVC: UICollectionViewDataSource { socialLinkCardCell.configureCell(type: socialLinkType) return socialLinkCardCell - default: return UICollectionViewCell() } } } diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/VC/HomeForVisitorVC.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/VC/HomeForVisitorVC.swift index 4dbba128..d1cd4ed2 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/VC/HomeForVisitorVC.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/VC/HomeForVisitorVC.swift @@ -15,17 +15,45 @@ import DSKit import BaseFeatureDependency final class HomeForVisitorVC: UIViewController, HomeForVisitorViewControllable { + + // MARK: - Properties + + public let viewModel: HomeForVisitorViewModel // MARK: - UI Components private lazy var naviBar = HomeNavigationBar().hideNoticeButton() + private lazy var collectionView = UICollectionView( + frame: .zero, + collectionViewLayout: self.createLayout() + ).then { + $0.isScrollEnabled = true + $0.showsHorizontalScrollIndicator = false + $0.showsVerticalScrollIndicator = false + $0.contentInset = .zero + $0.backgroundColor = .clear + } + + // MARK: - Initialization + + public init(viewModel: HomeForVisitorViewModel) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() setUI() setLayout() + setDelegate() + registerCells() } } @@ -38,16 +66,115 @@ extension HomeForVisitorVC { } private func setLayout() { - view.addSubviews(naviBar) + view.addSubviews( + naviBar, + collectionView + ) naviBar.snp.makeConstraints { make in make.leading.top.trailing.equalTo(view.safeAreaLayoutGuide) } + + collectionView.snp.makeConstraints { make in + make.top.equalTo(naviBar.snp.bottom).offset(16) + make.leading.trailing.bottom.equalTo(view.safeAreaLayoutGuide) + } } } // MARK: - Methods extension HomeForVisitorVC { + private func setDelegate() { + self.collectionView.delegate = self + self.collectionView.dataSource = self + } + private func registerCells() { + /// Header + self.collectionView.register(HomeDefaultHeaderView.self, + forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, + withReuseIdentifier: HomeDefaultHeaderView.className) + + /// Cell + self.collectionView.register(DashBoardCardCVC.self, + forCellWithReuseIdentifier: DashBoardCardCVC.className) + self.collectionView.register(MainProductCardCVC.self, + forCellWithReuseIdentifier: MainProductCardCVC.className) + self.collectionView.register(AppServiceCardCVC.self, + forCellWithReuseIdentifier: AppServiceCardCVC.className) + } +} + +// MARK: - UICollectionViewDelegate + +extension HomeForVisitorVC: UICollectionViewDelegate { + +} + +// MARK: - UICollectionViewDataSource + +extension HomeForVisitorVC: UICollectionViewDataSource { + func numberOfSections(in collectionView: UICollectionView) -> Int { + return HomeForVisitorSectionLayoutKind.allCases.count + } + + func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { + guard let sectionKind = HomeForVisitorSectionLayoutKind(rawValue: indexPath.section) else { return UICollectionReusableView() } + guard let headerView = collectionView + .dequeueReusableSupplementaryView(ofKind: kind, + withReuseIdentifier: HomeDefaultHeaderView.className, + for: indexPath) as? HomeDefaultHeaderView else { return UICollectionReusableView() } + headerView.setDataForVisitor(sectionKind: sectionKind) + return headerView + } + + public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + guard let sectionKind = HomeForVisitorSectionLayoutKind(rawValue: section) else { return 0 } + + switch sectionKind { + case .dashBoard: return 1 + case .mainProduct: return viewModel.productInfoList.count + case .appService: return viewModel.appServiceInfoList.count + } + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let sectionKind = HomeForVisitorSectionLayoutKind(rawValue: indexPath.section) else { return UICollectionViewCell() } + switch sectionKind { + case .dashBoard: + /// 대시보드 카드 셀 + guard let dashBoardCardCell = collectionView + .dequeueReusableCell(withReuseIdentifier: DashBoardCardCVC.className, + for: indexPath) as? DashBoardCardCVC else { return UICollectionViewCell() } + dashBoardCardCell.configureCell(userType: .visitor) + + return dashBoardCardCell + + case .mainProduct: + /// 프로덕트 카드 셀 + let productIndex = indexPath.item + guard let product = viewModel.productInfoList[safe: productIndex] else { return UICollectionViewCell() } + guard let productCardCell = collectionView + .dequeueReusableCell(withReuseIdentifier: MainProductCardCVC.className, + for: indexPath) as? MainProductCardCVC else { return UICollectionViewCell() } + productCardCell.configureCell(title: product.name, + image: product.image) + + return productCardCell + + case .appService: + /// 앱 서비스 카드 셀 + let appServiceIndex = indexPath.item + guard let appService = viewModel.appServiceInfoList[safe: appServiceIndex] else { return UICollectionViewCell() } + guard let appServiceCardCell = collectionView + .dequeueReusableCell(withReuseIdentifier: AppServiceCardCVC.className, + for: indexPath) as? AppServiceCardCVC else { return UICollectionViewCell() } + appServiceCardCell.configureCell(imageURL: appService.imageURL, + name: appService.name, + badgeText: appService.badgeText) + + return appServiceCardCell + } + } } diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/ViewModel/HomeForVisitorViewModel.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/ViewModel/HomeForVisitorViewModel.swift index 8bc612aa..ddee8c91 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/ViewModel/HomeForVisitorViewModel.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/ViewModel/HomeForVisitorViewModel.swift @@ -11,12 +11,29 @@ import Combine import Core import Domain +import DSKit import HomeFeatureInterface import BaseFeatureDependency public class HomeForVisitorViewModel: HomeForVisitorViewModelType { + // MARK: - Properties + + let productInfoList: [ProductInfo] = [ + ProductInfo(name: I18N.Home.MainProduct.homePage, image: DSKitAsset.Assets.imgHomepage.image), + ProductInfo(name: I18N.Home.MainProduct.activityReview, image: DSKitAsset.Assets.imgGroupLogo.image), + ProductInfo(name: I18N.Home.MainProduct.project, image: DSKitAsset.Assets.imgMemberLogo.image), + ProductInfo(name: I18N.Home.MainProduct.instagram, image: DSKitAsset.Assets.imgInstagram.image) + ] + + // TODO: 서버 연결 필요 + let appServiceInfoList: [AppServiceInfo] = [ + AppServiceInfo(name: "콕찌르기", imageURL: "https://images.mypetlife.co.kr/content/uploads/2018/12/09154907/cotton-tulear-2422612_1280.jpg", badgeText: ""), + AppServiceInfo(name: "솝마디", imageURL: "https://images.mypetlife.co.kr/content/uploads/2018/12/09154907/cotton-tulear-2422612_1280.jpg", badgeText: ""), + AppServiceInfo(name: "솝탬프", imageURL: "https://images.mypetlife.co.kr/content/uploads/2018/12/09154907/cotton-tulear-2422612_1280.jpg", badgeText: "") + ] + // MARK: - Inputs public struct Input { } diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Views/HomeDefaultHeaderView.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Views/HomeDefaultHeaderView.swift index 2cb27927..016b5fb8 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Views/HomeDefaultHeaderView.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/Views/HomeDefaultHeaderView.swift @@ -77,10 +77,14 @@ extension HomeDefaultHeaderView { // MARK: - Methods extension HomeDefaultHeaderView { - func setData(sectionKind: HomeForMemberSectionLayoutKind) { + func setDataForMember(sectionKind: HomeForMemberSectionLayoutKind) { self.titleLabel.text = sectionKind.title self.viewAllButton.isHidden = (sectionKind == .appService) ? true : false self.coffechatLogoImageView.isHidden = (sectionKind == .coffeeChat) ? false : true } + + func setDataForVisitor(sectionKind: HomeForVisitorSectionLayoutKind) { + self.titleLabel.text = sectionKind.title + self.viewAllButton.isHidden = true + } } - diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_homepage.imageset/Contents.json b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_homepage.imageset/Contents.json new file mode 100644 index 00000000..5c0a4a21 --- /dev/null +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_homepage.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "icn_homepage.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_homepage.imageset/icn_homepage.svg b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_homepage.imageset/icn_homepage.svg new file mode 100644 index 00000000..5a5de6ae --- /dev/null +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_homepage.imageset/icn_homepage.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_instagram.imageset/Contents.json b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_instagram.imageset/Contents.json new file mode 100644 index 00000000..8bea1346 --- /dev/null +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_instagram.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Frame 1171275665.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_instagram.imageset/Frame 1171275665.svg b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_instagram.imageset/Frame 1171275665.svg new file mode 100644 index 00000000..864f430c --- /dev/null +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_instagram.imageset/Frame 1171275665.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + +