From 4e29b3cc7a000a9b9cf39744253b0703fcfc582b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=80=E1=85=B5=E1=84=92?= =?UTF-8?q?=E1=85=A7=E1=86=AB?= Date: Wed, 30 Jul 2025 03:41:59 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix/#170:=20StoreListCell=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=95=84=EC=9B=83=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Map/StoreListView/StoreListCell.swift | 185 ++++++++++-------- .../Map/StoreListView/StoreListView.swift | 99 ++++++---- .../StoreListViewController.swift | 3 - 3 files changed, 156 insertions(+), 131 deletions(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListCell.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListCell.swift index bdfb71b8..3399dc8f 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListCell.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListCell.swift @@ -1,6 +1,7 @@ import UIKit import DesignSystem +import Infrastructure import ReactorKit import RxSwift @@ -9,63 +10,70 @@ import SnapKit final class StoreListCell: UICollectionViewCell { static let identifier = "StoreListCell" + // MARK: - Properties + var disposeBag = DisposeBag() + + private enum Constant { + static let imageHeight: CGFloat = 140 + static let bookmarkSize: CGFloat = 24 + static let bookmarkInset: CGFloat = 8 + static let categoryTopOffset: CGFloat = 12 + static let categoryHeight: CGFloat = 15 + static let titleTopOffset: CGFloat = 4 + static let addressHeight: CGFloat = 17 + static let dateHeight: CGFloat = 15 + static let cornerRadius: CGFloat = 12 + } + // MARK: - Components - private let thumbnailImageView: UIImageView = { - let iv = UIImageView() - iv.contentMode = .scaleAspectFill - iv.clipsToBounds = true - iv.layer.cornerRadius = 12 - iv.backgroundColor = .g100 - return iv - }() - - let bookmarkButton: UIButton = { - let button = UIButton() - button.setImage(UIImage(named: "icon_bookmark"), for: .normal) - button.backgroundColor = .clear - button.layer.cornerRadius = 12 - return button - }() - - private let categoryTagLabel: PPLabel = { - let label = PPLabel(style: .bold, fontSize: 11, text: "") - label.textColor = .blu500 - label.text = "#카테고리" - return label - }() - - private let titleLabel: PPLabel = { - let label = PPLabel(style: .bold, fontSize: 14, text: "") - label.textColor = .g900 - label.numberOfLines = 2 - return label - }() - - private let locationLabel: PPLabel = { - let label = PPLabel(style: .medium, fontSize: 11, text: "") - label.textColor = .g400 - label.numberOfLines = 2 - return label - }() - - private let dateLabel: PPLabel = { - let label = PPLabel(style: .regular, fontSize: 12, text: "") - label.textColor = .g400 - label.numberOfLines = 2 - return label - }() + private let thumbnailImageView = UIImageView().then { + $0.contentMode = .scaleAspectFill + $0.clipsToBounds = true + $0.layer.cornerRadius = Constant.cornerRadius + $0.backgroundColor = .g100 + } - var disposeBag = DisposeBag() + let bookmarkButton = UIButton().then { + $0.setImage(UIImage(named: "icon_bookmark"), for: .normal) + $0.backgroundColor = .clear + } + + private let categoryTagLabel = PPLabel(style: .bold, fontSize: 11).then { + $0.textColor = .blu500 + $0.setLineHeightText(text: "category", font: .korFont(style: .bold, size: 11)) + } + + private let titleLabel = PPLabel(style: .bold, fontSize: 14).then { + $0.numberOfLines = 2 + $0.lineBreakMode = .byTruncatingTail + $0.textColor = .g900 + $0.setLineHeightText(text: "title", font: .korFont(style: .bold, size: 14)) + } + + private let locationLabel = PPLabel(style: .medium, fontSize: 11).then { + $0.numberOfLines = 1 + $0.lineBreakMode = .byTruncatingTail + $0.textColor = .g400 + $0.setLineHeightText(text: "location", font: .korFont(style: .medium, size: 11)) + } + + private let dateLabel = PPLabel(style: .medium, fontSize: 11).then { + $0.lineBreakMode = .byTruncatingTail + $0.textColor = .g400 + $0.setLineHeightText(text: "date", font: .korFont(style: .medium, size: 11)) + } // MARK: - Init override init(frame: CGRect) { super.init(frame: frame) - setUpConstraints() - configureUI() + + self.addViews() + self.setupConstraints() + self.configureUI() } required init?(coder: NSCoder) { - fatalError() + fatalError("\(#file), \(#function) Error") } override func prepareForReuse() { @@ -76,52 +84,56 @@ final class StoreListCell: UICollectionViewCell { // MARK: - SetUp private extension StoreListCell { - func configureUI() { - // backgroundColor = .white + func addViews() { + [thumbnailImageView, categoryTagLabel, titleLabel, locationLabel, dateLabel, bookmarkButton].forEach { + self.contentView.addSubview($0) + } } - func setUpConstraints() { - contentView.addSubview(thumbnailImageView) + func setupConstraints() { thumbnailImageView.snp.makeConstraints { make in - make.top.leading.equalToSuperview() - make.width.equalTo((UIScreen.main.bounds.width - 48) / 2) - make.height.equalTo(thumbnailImageView.snp.width) + make.width.equalTo(contentView.bounds.width) + make.height.equalTo(Constant.imageHeight) + make.top.equalToSuperview() + make.centerX.equalToSuperview() } - contentView.addSubview(bookmarkButton) bookmarkButton.snp.makeConstraints { make in - make.top.trailing.equalToSuperview().inset(8) - make.size.equalTo(24) + make.size.equalTo(Constant.bookmarkSize) + make.top.trailing.equalToSuperview().inset(Constant.bookmarkInset) + } + + categoryTagLabel.snp.makeConstraints { make in + make.leading.equalToSuperview() + make.top.equalTo(thumbnailImageView.snp.bottom).offset(Constant.categoryTopOffset) + make.height.equalTo(Constant.categoryHeight) + } + + titleLabel.snp.makeConstraints { make in + make.top.equalTo(categoryTagLabel.snp.bottom).offset(Constant.titleTopOffset) + make.leading.trailing.equalToSuperview() + } + + dateLabel.snp.makeConstraints { make in + make.leading.equalToSuperview() + make.height.equalTo(Constant.dateHeight).priority(.high) + make.bottom.equalToSuperview() } - contentView.addSubview(categoryTagLabel) - contentView.addSubview(titleLabel) - contentView.addSubview(locationLabel) - contentView.addSubview(dateLabel) - - // 각 라벨의 위치 설정 - categoryTagLabel.snp.makeConstraints { make in - make.top.equalTo(thumbnailImageView.snp.bottom).offset(10) - make.leading.trailing.equalToSuperview() - make.height.equalTo(16) - } - - titleLabel.snp.makeConstraints { make in - make.top.equalTo(categoryTagLabel.snp.bottom).offset(6) - make.leading.trailing.equalToSuperview() - } - - locationLabel.snp.makeConstraints { make in - make.top.equalTo(titleLabel.snp.bottom).offset(12) - make.leading.trailing.equalToSuperview() - } - - dateLabel.snp.makeConstraints { make in - make.top.equalTo(locationLabel.snp.bottom).offset(6) - make.leading.trailing.equalToSuperview() - make.bottom.lessThanOrEqualToSuperview() - } - } + locationLabel.snp.makeConstraints { make in + make.leading.trailing.equalToSuperview() + make.bottom.equalTo(dateLabel.snp.top) + make.height.equalTo(Constant.addressHeight).priority(.high) + } + } + + func configureUI() { + self.contentView.layer.cornerRadius = 4 + self.contentView.clipsToBounds = true + + thumbnailImageView.layer.cornerRadius = 4 + thumbnailImageView.clipsToBounds = true + } } // MARK: - Inputable @@ -145,5 +157,4 @@ extension StoreListCell: Inputable { let bookmarkImage = input.isBookmarked ? "icon_bookmark_fill" : "icon_bookmark" bookmarkButton.setImage(UIImage(named: bookmarkImage), for: .normal) } - } diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListView.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListView.swift index 79f01619..a90d63ec 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListView.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListView.swift @@ -2,9 +2,26 @@ import SnapKit import UIKit final class StoreListView: UIView { + + // MARK: - Properties + private enum Constant { + static let grabberWidth: CGFloat = 36 + static let grabberHeight: CGFloat = 5 + static let grabberTopOffset: CGFloat = 14 + static let grabberCornerRadius: CGFloat = 2.5 + static let collectionViewTopOffset: CGFloat = 8 + static let cornerRadius: CGFloat = 16 + static let itemHeight: CGFloat = 250 + static let minimumLineSpacing: CGFloat = 20 + static let minimumInteritemSpacing: CGFloat = 16 + static let sectionInsetTop: CGFloat = 16 + static let sectionInsetHorizontal: CGFloat = 16 + static let sectionInsetBottom: CGFloat = 16 + } + // MARK: - Components lazy var collectionView: UICollectionView = { - let layout = createLayout() + let layout = self.createLayout() let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.backgroundColor = .white cv.register(StoreListCell.self, forCellWithReuseIdentifier: StoreListCell.identifier) @@ -14,22 +31,18 @@ final class StoreListView: UIView { let grabberHandle: UIView = { let view = UIView() view.backgroundColor = .g200 - view.layer.cornerRadius = 2.5 + view.layer.cornerRadius = Constant.grabberCornerRadius view.isUserInteractionEnabled = true return view }() - private let paddingView: UIView = { - let view = UIView() - view.backgroundColor = .clear // 간격만 추가하므로 투명 - return view - }() - // MARK: - Init override init(frame: CGRect) { super.init(frame: frame) - configureLayer() // 최상단 레이어 설정 - setUpConstraints() + + self.configureLayer() + self.addViews() + self.setupConstraints() } required init?(coder: NSCoder) { @@ -39,47 +52,51 @@ final class StoreListView: UIView { // MARK: - Setup private extension StoreListView { + func addViews() { + [collectionView, grabberHandle].forEach { + self.addSubview($0) + } + } + + func setupConstraints() { + grabberHandle.snp.makeConstraints { make in + make.top.equalToSuperview().offset(Constant.grabberTopOffset).priority(.high) + make.centerX.equalToSuperview() + make.width.equalTo(Constant.grabberWidth) + make.height.equalTo(Constant.grabberHeight) + } + + collectionView.snp.makeConstraints { make in + make.top.equalTo(grabberHandle.snp.bottom).offset(Constant.collectionViewTopOffset).priority(.medium) + make.leading.trailing.equalToSuperview() + make.bottom.equalToSuperview() + } + } + func createLayout() -> UICollectionViewFlowLayout { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .vertical - layout.minimumLineSpacing = 20 - layout.minimumInteritemSpacing = 16 + layout.minimumLineSpacing = Constant.minimumLineSpacing + layout.minimumInteritemSpacing = Constant.minimumInteritemSpacing - let totalWidth = UIScreen.main.bounds.width - 32 + let totalWidth = UIScreen.main.bounds.width - (Constant.sectionInsetHorizontal * 2) let itemWidth = (totalWidth - layout.minimumInteritemSpacing) / 2 - layout.itemSize = CGSize(width: floor(itemWidth), height: itemWidth + 100) - layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) + layout.itemSize = CGSize(width: floor(itemWidth), height: Constant.itemHeight) + layout.sectionInset = UIEdgeInsets( + top: Constant.sectionInsetTop, + left: Constant.sectionInsetHorizontal, + bottom: Constant.sectionInsetBottom, + right: Constant.sectionInsetHorizontal + ) return layout } - func setUpConstraints() { - backgroundColor = .white - addSubview(collectionView) - addSubview(grabberHandle) - grabberHandle.snp.makeConstraints { make in - make.top.equalToSuperview().offset(14).priority(.high) - make.centerX.equalToSuperview() - make.width.equalTo(36) - make.height.equalTo(5) - } -// paddingView.snp.makeConstraints { make in -// make.top.equalTo(grabberHandle.snp.bottom) -// make.leading.trailing.equalToSuperview() -// -// } - - collectionView.snp.makeConstraints { make in - make.top.equalTo(grabberHandle.snp.bottom).offset(8).priority(.medium) - make.leading.trailing.equalToSuperview() - make.bottom.equalToSuperview() // bottom 제약 다시 추가 - } - } - func configureLayer() { - layer.cornerRadius = 16 - layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] // 상단 좌우 코너만 적용 - layer.masksToBounds = true + self.backgroundColor = .white + self.layer.cornerRadius = Constant.cornerRadius + self.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + self.layer.masksToBounds = true } } diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListViewController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListViewController.swift index 92dba9d9..42a3cf8f 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListViewController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListViewController.swift @@ -93,7 +93,6 @@ final class StoreListViewController: UIViewController, View { .bind(to: mainView.collectionView.rx.items(dataSource: dataSource)) .disposed(by: disposeBag) - // 찜한 팝업 토스트 처리 체인 reactor.state .map { $0.shouldShowBookmarkToast } .distinctUntilChanged() @@ -104,7 +103,6 @@ final class StoreListViewController: UIViewController, View { if isBookmarking { toastView.moveButton.rx.tap .subscribe(onNext: { [weak self] in - // 이동 처리 (예: 찜한 팝업 리스트 페이지로 이동) }) .disposed(by: self.disposeBag) } @@ -112,7 +110,6 @@ final class StoreListViewController: UIViewController, View { } .disposed(by: disposeBag) - // 3) 아이템 선택 mainView.collectionView.rx.itemSelected .withUnretained(self) .subscribe(onNext: { owner, indexPath in From b4f94cbb2c0aa1a38eff83ce80764d0744db3055 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 29 Jul 2025 18:45:44 +0000 Subject: [PATCH 2/3] style/#170: Apply SwiftLint autocorrect --- .../Presentation/Scene/Map/StoreListView/StoreListView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListView.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListView.swift index a90d63ec..f87d08bd 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListView.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListView.swift @@ -11,7 +11,7 @@ final class StoreListView: UIView { static let grabberCornerRadius: CGFloat = 2.5 static let collectionViewTopOffset: CGFloat = 8 static let cornerRadius: CGFloat = 16 - static let itemHeight: CGFloat = 250 + static let itemHeight: CGFloat = 250 static let minimumLineSpacing: CGFloat = 20 static let minimumInteritemSpacing: CGFloat = 16 static let sectionInsetTop: CGFloat = 16 From eee1dc643b1263e48c3c71f4da565db559127b86 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 5 Aug 2025 04:22:22 +0000 Subject: [PATCH 3/3] style/#170: Apply SwiftLint autocorrect --- .../Presentation/Scene/Map/StoreListView/StoreListCell.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListCell.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListCell.swift index 263a9ccd..c59c7506 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListCell.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Map/StoreListView/StoreListCell.swift @@ -158,4 +158,4 @@ extension StoreListCell: Inputable { let bookmarkImage = input.isBookmarked ? "icon_bookmark_fill" : "icon_bookmark" self.bookmarkButton.setImage(UIImage(named: bookmarkImage), for: .normal) } -} \ No newline at end of file +}