Manos Chorianopoulos

CategoryOffers part2

......@@ -9,10 +9,118 @@ import UIKit
@objc(CategoryOfferCollectionViewCell)
public class CategoryOfferCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var parentView: UIView!
@IBOutlet weak var bannerImage: UIImageView!
@IBOutlet weak var logoImage: UIImageView!
@IBOutlet weak var discountView: UIView!
@IBOutlet weak var discountLabel: UILabel!
@IBOutlet weak var merchantNameLabel: UILabel!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subtitleLabel: UILabel!
@IBOutlet weak var expirationLabel: UILabel!
var postImageURL: String? {
didSet {
if let url = postImageURL {
self.bannerImage.image = UIImage()
UIImage.loadImageUsingCacheWithUrlString(url) { image in
if url == self.postImageURL {
self.bannerImage.image = image
}
}
} else {
self.bannerImage.image = nil
}
}
}
var logoImageURL: String? {
didSet {
if let url = logoImageURL {
self.logoImage.image = UIImage()
UIImage.loadImageUsingCacheWithUrlString(url) { image in
if url == self.logoImageURL {
self.logoImage.image = image
}
}
} else {
self.logoImage.image = nil
}
}
}
public override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
parentView.layer.borderWidth = 1.0
parentView.layer.borderColor = UIColor(rgb: 0xD2D6D9).cgColor
parentView.layer.cornerRadius = 12.0
parentView.clipsToBounds = true
logoImage.layer.cornerRadius = 8.0
logoImage.clipsToBounds = true
logoImage.backgroundColor = UIColor(rgb: 0xEEEEEE)
discountView.layer.cornerRadius = 17.0
discountView.clipsToBounds = true
}
func configureCell(data: OfferModel) {
bannerImage.image = UIImage(named: data.bannerImage, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
discountLabel.text = data.discount
discountLabel.font = UIFont(name: "PingLCG-Bold", size: 14)
discountLabel.textColor = UIColor(rgb: 0xFFFFFF)
discountView.backgroundColor = UIColor(rgb: 0xCBCBCB)
merchantNameLabel.text = data.title
merchantNameLabel.font = UIFont(name: "PingLCG-Regular", size: 12)
merchantNameLabel.textColor = UIColor(rgb: 0x000F1E)
titleLabel.text = data.title
titleLabel.font = UIFont(name: "PingLCG-Bold", size: 15)
titleLabel.textColor = UIColor(rgb: 0x000F1E)
subtitleLabel.text = data.description
subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 13)
subtitleLabel.textColor = UIColor(rgb: 0x00111B)
expirationLabel.text = data.expirationDate
expirationLabel.font = UIFont(name: "PingLCG-Regular", size: 12)
expirationLabel.textColor = UIColor(rgb: 0x9BA1A6)
logoImage.image = UIImage(named: data.merchantLogo, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
}
func configureCell(data: CouponSetItemModel) {
self.postImageURL = data._app_img_preview
discountLabel.text = data._discount
discountLabel.font = UIFont(name: "PingLCG-Bold", size: 14)
discountLabel.textColor = UIColor(rgb: 0xFFFFFF)
discountView.backgroundColor = UIColor(rgb: 0xCBCBCB)
if let merchant = data._merchant {
merchantNameLabel.text = merchant._admin_name
self.logoImageURL = merchant._img_preview
} else {
merchantNameLabel.text = ""
self.logoImageURL = nil
}
merchantNameLabel.font = UIFont(name: "PingLCG-Regular", size: 12)
merchantNameLabel.textColor = UIColor(rgb: 0x000F1E)
titleLabel.text = data._name
titleLabel.font = UIFont(name: "PingLCG-Bold", size: 15)
titleLabel.textColor = UIColor(rgb: 0x000F1E)
subtitleLabel.text = data._short_description
subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 13)
subtitleLabel.textColor = UIColor(rgb: 0x00111B)
expirationLabel.text = "until " + data.formattedEndDate(format: "dd-MM")
expirationLabel.font = UIFont(name: "PingLCG-Regular", size: 12)
expirationLabel.textColor = UIColor(rgb: 0x9BA1A6)
}
}
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13142" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="24506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12042"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24504"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="CategoryOfferCollectionViewCell" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="CategoryOfferCollectionViewCell" customModule="SwiftWarplyFramework" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="170" height="280"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<rect key="frame" x="0.0" y="0.0" width="170" height="280"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<!-- parentView: card container with border + rounded corners -->
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="A1B-CD-EFG" userLabel="parentView">
<rect key="frame" x="0.0" y="0.0" width="170" height="280"/>
<subviews>
<!-- Top View: gray background, banner image, logo, discount -->
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TOP-vw-001" userLabel="TopView">
<rect key="frame" x="0.0" y="0.0" width="170" height="140"/>
<subviews>
<!-- Banner image fills the top view -->
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="BNR-img-001">
<rect key="frame" x="0.0" y="0.0" width="170" height="140"/>
</imageView>
<!-- Logo image: centered in top view -->
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="LGO-img-001">
<rect key="frame" x="51" y="42" width="48" height="48"/>
<constraints>
<constraint firstAttribute="width" constant="48" id="LGO-w-001"/>
<constraint firstAttribute="height" constant="48" id="LGO-h-001"/>
</constraints>
</imageView>
<!-- Discount circle: top-right -->
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="DSC-vw-001" userLabel="discountView">
<rect key="frame" x="130" y="8" width="34" height="34"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="%" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="YES" minimumFontScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="DSC-lbl-001">
<rect key="frame" x="2" y="2" width="30" height="30"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.796" green="0.796" blue="0.796" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="34" id="DSC-w-001"/>
<constraint firstAttribute="height" constant="34" id="DSC-h-001"/>
<constraint firstItem="DSC-lbl-001" firstAttribute="top" secondItem="DSC-vw-001" secondAttribute="top" constant="2" id="DSC-t-001"/>
<constraint firstItem="DSC-lbl-001" firstAttribute="leading" secondItem="DSC-vw-001" secondAttribute="leading" constant="2" id="DSC-l-001"/>
<constraint firstAttribute="trailing" secondItem="DSC-lbl-001" secondAttribute="trailing" constant="2" id="DSC-tr-001"/>
<constraint firstAttribute="bottom" secondItem="DSC-lbl-001" secondAttribute="bottom" constant="2" id="DSC-b-001"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="0.937" green="0.941" blue="0.945" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<!-- Banner fills top view -->
<constraint firstItem="BNR-img-001" firstAttribute="top" secondItem="TOP-vw-001" secondAttribute="top" id="BNR-t-001"/>
<constraint firstItem="BNR-img-001" firstAttribute="leading" secondItem="TOP-vw-001" secondAttribute="leading" id="BNR-l-001"/>
<constraint firstAttribute="trailing" secondItem="BNR-img-001" secondAttribute="trailing" id="BNR-tr-001"/>
<constraint firstAttribute="bottom" secondItem="BNR-img-001" secondAttribute="bottom" id="BNR-b-001"/>
<!-- Logo centered -->
<constraint firstItem="LGO-img-001" firstAttribute="centerX" secondItem="TOP-vw-001" secondAttribute="centerX" id="LGO-cx-001"/>
<constraint firstItem="LGO-img-001" firstAttribute="centerY" secondItem="TOP-vw-001" secondAttribute="centerY" id="LGO-cy-001"/>
<!-- Discount top-right, 8pt from edges -->
<constraint firstAttribute="trailing" secondItem="DSC-vw-001" secondAttribute="trailing" constant="8" id="DSC-tr2-001"/>
<constraint firstItem="DSC-vw-001" firstAttribute="top" secondItem="TOP-vw-001" secondAttribute="top" constant="8" id="DSC-top-001"/>
<!-- Top view height -->
<constraint firstAttribute="height" constant="140" id="TOP-h-001"/>
</constraints>
</view>
<!-- Bottom View: white, text labels -->
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BTM-vw-001" userLabel="BottomView">
<rect key="frame" x="0.0" y="140" width="170" height="140"/>
<subviews>
<!-- Merchant name label -->
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Merchant" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MRC-lbl-001">
<rect key="frame" x="10" y="10" width="150" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<!-- Title label (bold) -->
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TTL-lbl-001">
<rect key="frame" x="10" y="30" width="150" height="40"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<!-- Subtitle label -->
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Subtitle" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SUB-lbl-001">
<rect key="frame" x="10" y="74" width="150" height="34"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<!-- Expiration label -->
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="until 30-09" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EXP-lbl-001">
<rect key="frame" x="10" y="112" width="150" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<!-- Merchant label -->
<constraint firstItem="MRC-lbl-001" firstAttribute="top" secondItem="BTM-vw-001" secondAttribute="top" constant="10" id="MRC-t-001"/>
<constraint firstItem="MRC-lbl-001" firstAttribute="leading" secondItem="BTM-vw-001" secondAttribute="leading" constant="10" id="MRC-l-001"/>
<constraint firstAttribute="trailing" secondItem="MRC-lbl-001" secondAttribute="trailing" constant="10" id="MRC-tr-001"/>
<!-- Title below merchant, 4pt gap -->
<constraint firstItem="TTL-lbl-001" firstAttribute="top" secondItem="MRC-lbl-001" secondAttribute="bottom" constant="4" id="TTL-t-001"/>
<constraint firstItem="TTL-lbl-001" firstAttribute="leading" secondItem="BTM-vw-001" secondAttribute="leading" constant="10" id="TTL-l-001"/>
<constraint firstAttribute="trailing" secondItem="TTL-lbl-001" secondAttribute="trailing" constant="10" id="TTL-tr-001"/>
<!-- Subtitle below title, 4pt gap -->
<constraint firstItem="SUB-lbl-001" firstAttribute="top" secondItem="TTL-lbl-001" secondAttribute="bottom" constant="4" id="SUB-t-001"/>
<constraint firstItem="SUB-lbl-001" firstAttribute="leading" secondItem="BTM-vw-001" secondAttribute="leading" constant="10" id="SUB-l-001"/>
<constraint firstAttribute="trailing" secondItem="SUB-lbl-001" secondAttribute="trailing" constant="10" id="SUB-tr-001"/>
<!-- Expiration pinned to bottom -->
<constraint firstAttribute="bottom" secondItem="EXP-lbl-001" secondAttribute="bottom" constant="10" id="EXP-b-001"/>
<constraint firstItem="EXP-lbl-001" firstAttribute="leading" secondItem="BTM-vw-001" secondAttribute="leading" constant="10" id="EXP-l-001"/>
<constraint firstAttribute="trailing" secondItem="EXP-lbl-001" secondAttribute="trailing" constant="10" id="EXP-tr-001"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<!-- Top view pinned to top -->
<constraint firstItem="TOP-vw-001" firstAttribute="top" secondItem="A1B-CD-EFG" secondAttribute="top" id="TOP-t-p-001"/>
<constraint firstItem="TOP-vw-001" firstAttribute="leading" secondItem="A1B-CD-EFG" secondAttribute="leading" id="TOP-l-p-001"/>
<constraint firstAttribute="trailing" secondItem="TOP-vw-001" secondAttribute="trailing" id="TOP-tr-p-001"/>
<!-- Bottom view below top view -->
<constraint firstItem="BTM-vw-001" firstAttribute="top" secondItem="TOP-vw-001" secondAttribute="bottom" id="BTM-t-p-001"/>
<constraint firstItem="BTM-vw-001" firstAttribute="leading" secondItem="A1B-CD-EFG" secondAttribute="leading" id="BTM-l-p-001"/>
<constraint firstAttribute="trailing" secondItem="BTM-vw-001" secondAttribute="trailing" id="BTM-tr-p-001"/>
<constraint firstAttribute="bottom" secondItem="BTM-vw-001" secondAttribute="bottom" id="BTM-b-p-001"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="A1B-CD-EFG" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="PV-t-001"/>
<constraint firstItem="A1B-CD-EFG" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="PV-l-001"/>
<constraint firstAttribute="trailing" secondItem="A1B-CD-EFG" secondAttribute="trailing" id="PV-tr-001"/>
<constraint firstAttribute="bottom" secondItem="A1B-CD-EFG" secondAttribute="bottom" id="PV-b-001"/>
</constraints>
</view>
<viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
<connections>
<outlet property="bannerImage" destination="BNR-img-001" id="BNR-out-001"/>
<outlet property="discountLabel" destination="DSC-lbl-001" id="DSC-out-001"/>
<outlet property="discountView" destination="DSC-vw-001" id="DSC-out-002"/>
<outlet property="expirationLabel" destination="EXP-lbl-001" id="EXP-out-001"/>
<outlet property="logoImage" destination="LGO-img-001" id="LGO-out-001"/>
<outlet property="merchantNameLabel" destination="MRC-lbl-001" id="MRC-out-001"/>
<outlet property="parentView" destination="A1B-CD-EFG" id="PV-out-001"/>
<outlet property="subtitleLabel" destination="SUB-lbl-001" id="SUB-out-001"/>
<outlet property="titleLabel" destination="TTL-lbl-001" id="TTL-out-001"/>
</connections>
<size key="customSize" width="170" height="280"/>
<point key="canvasLocation" x="50" y="50"/>
</collectionViewCell>
</objects>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
......
......@@ -18,21 +18,11 @@ public class CategoryOffersGridTableViewCell: UITableViewCell {
public override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
setupCollectionView()
}
public override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
private func setupCollectionView() {
collectionView.delegate = self
collectionView.dataSource = self
collectionView.backgroundColor = .clear
collectionView.isScrollEnabled = false // Scroll is handled by the outer TableView
collectionView.isScrollEnabled = false
XIBLoader.registerCollectionViewCell(
collectionView,
......@@ -42,22 +32,44 @@ public class CategoryOffersGridTableViewCell: UITableViewCell {
)
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.minimumInteritemSpacing = 16
layout.minimumInteritemSpacing = 12
layout.minimumLineSpacing = 16
layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
}
}
public override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func configureCell(with sectionData: SectionModel?, parentViewController: UIViewController?) {
self.data = sectionData
self.parentViewController = parentViewController
collectionView.reloadData()
// Use layoutIfNeeded to calculate content size and set the height constraint
collectionView.layoutIfNeeded()
let height = collectionView.collectionViewLayout.collectionViewContentSize.height
collectionViewHeightConstraint.constant = height
// Calculate and set the collection view height so the table view cell expands correctly
DispatchQueue.main.async {
self.collectionView.layoutIfNeeded()
let height = self.collectionView.collectionViewLayout.collectionViewContentSize.height
self.collectionViewHeightConstraint.constant = max(height, 1)
// Notify the parent table view to recalculate its layout
if let tableView = self.parentViewController?.view.subviews.first(where: { $0 is UITableView }) as? UITableView {
tableView.beginUpdates()
tableView.endUpdates()
}
}
}
// Compute item size for 2-column grid
private func itemSize() -> CGSize {
let totalWidth = collectionView.bounds.width > 0 ? collectionView.bounds.width : UIScreen.main.bounds.width
let inset: CGFloat = 16
let spacing: CGFloat = 12
let availableWidth = totalWidth - (inset * 2) - spacing
let itemWidth = floor(availableWidth / 2)
let itemHeight = itemWidth * 1.65 // ratio matching the design card proportions
return CGSize(width: itemWidth, height: itemHeight)
}
}
......@@ -101,38 +113,35 @@ extension CategoryOffersGridTableViewCell: UICollectionViewDataSource, UICollect
return
}
// Handle navigation based on item type
switch data.itemType {
case .couponSets:
if let couponSet = items[indexPath.row] as? CouponSetItemModel {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.frameworkResourceBundle)
if let vc = storyboard.instantiateViewController(withIdentifier: "CouponsetViewController") as? CouponsetViewController {
let vc = CouponsetViewController(nibName: "CouponsetViewController", bundle: Bundle.frameworkResourceBundle)
vc.couponset = couponSet
self.parentViewController?.navigationController?.pushViewController(vc, animated: true)
}
parentViewController?.navigationController?.pushViewController(vc, animated: true)
}
default:
if let offer = items[indexPath.row] as? OfferModel {
// Determine if it's a campaign or other offer and navigate appropriately
// (Using existing patterns from MyRewardsViewController)
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.frameworkResourceBundle)
if let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as? CampaignViewController {
vc.campaignUrl = offer.campaignUrl // Assuming OfferModel has this
self.parentViewController?.navigationController?.pushViewController(vc, animated: true)
}
let vc = CouponViewController(nibName: "CouponViewController", bundle: Bundle.frameworkResourceBundle)
vc.offer = offer
parentViewController?.navigationController?.pushViewController(vc, animated: true)
}
}
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Calculate width for 2 columns with spacing
let padding: CGFloat = 16 * 3 // left + middle + right padding
let availableWidth = collectionView.frame.width - padding
let itemWidth = availableWidth / 2
return itemSize()
}
// Adjust height as needed based on design (aspect ratio or fixed)
let itemHeight = itemWidth * 1.3 // Approximation from screenshot
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 16
}
return CGSize(width: itemWidth, height: itemHeight)
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 12
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
}
}
......
......@@ -10,6 +10,7 @@ import UIKit
protocol MyRewardsOffersScrollTableViewCellDelegate: AnyObject {
func didSelectOffer(_ offer: OfferModel)
func didSelectCouponSet(_ couponSet: CouponSetItemModel)
func didSelectAllOffers(_ section: SectionModel)
}
@objc(MyRewardsOffersScrollTableViewCell)
......@@ -29,19 +30,19 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell {
super.awakeFromNib()
// Initialization code
// allButtonView.layer.borderWidth = 1.0
// allButtonView.layer.borderColor = UIColor(rgb: 0x000F1E).cgColor
// allButtonView.layer.cornerRadius = 4.0
allButtonArrowImage.image = UIImage(named: "arrow_right_blue", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
// allButtonLabel.text = "Όλα"
allButtonLabel.text = "All"
allButtonLabel.font = UIFont(name: "PingLCG-Regular", size: 15)
allButtonLabel.textColor = UIColor(rgb: 0x004E6E)
allButtonLabel.frame.size.width = allButtonLabel.intrinsicContentSize.width
allButtonLabel.frame.size.height = allButtonLabel.intrinsicContentSize.height
// Add tap gesture to allButtonView
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(allButtonTapped))
allButtonView.isUserInteractionEnabled = true
allButtonView.addGestureRecognizer(tapGesture)
// UPDATED: Safe XIB registration for collection view cells
registerCollectionViewCells()
......@@ -56,6 +57,11 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell {
collectionView.dataSource = self
}
@objc private func allButtonTapped() {
guard let data = data else { return }
delegate?.didSelectAllOffers(data)
}
// NEW: Safe collection view cell registration
private func registerCollectionViewCells() {
XIBLoader.registerCollectionViewCell(
......@@ -109,20 +115,11 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell {
collectionViewBottom.constant = 0
}
// Update collection view height based on section
// if data?.title == "Αγαπημένα" {
// collectionViewHeightConstraint.constant = 350 // Match cell height
// } else {
collectionViewHeightConstraint.constant = 232 // Default height
// }
// Configure layout based on section type
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
// if data?.title == "Αγαπημένα" {
// layout.minimumLineSpacing = 24
// } else {
layout.minimumLineSpacing = 7
// }
}
let catBoldText = (data?.title ?? "") + " "
......@@ -138,13 +135,11 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell {
categoryLabel.attributedText = catAttributedString
self.collectionView.reloadData();
}
}
extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
public func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
......@@ -189,11 +184,9 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl
switch data.itemType {
case .couponSets:
if let couponSet = items[indexPath.row] as? CouponSetItemModel {
// Pass CouponSetItemModel directly to new delegate method
delegate?.didSelectCouponSet(couponSet)
}
default:
// Handle OfferModel directly for ProfileViewController compatibility
if let offer = items[indexPath.row] as? OfferModel {
delegate?.didSelectOffer(offer)
}
......@@ -202,20 +195,12 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl
// MARK: - UICollectionViewDelegateFlowLayout
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// if self.data?.title == "Αγαπημένα" {
// return CGSize(width: 275, height: 350)
// } else {
return CGSize(width: 257, height: 232)
// }
}
// Distance Between Item Cells
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
// if self.data?.title == "Αγαπημένα" {
// return 24
// } else {
return 7
// }
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
......
......@@ -25,43 +25,54 @@ import UIKit
private func setupTableView() {
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
tableView.backgroundColor = .white
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableView.automaticDimension
tableView.register(UINib(nibName: "CategoryOffersHeaderTableViewCell", bundle: Bundle.frameworkResourceBundle), forCellReuseIdentifier: "CategoryOffersHeaderTableViewCell")
tableView.register(UINib(nibName: "CategoryOffersGridTableViewCell", bundle: Bundle.frameworkResourceBundle), forCellReuseIdentifier: "CategoryOffersGridTableViewCell")
tableView.register(
UINib(nibName: "CategoryOffersHeaderTableViewCell", bundle: Bundle.frameworkResourceBundle),
forCellReuseIdentifier: "CategoryOffersHeaderTableViewCell"
)
tableView.register(
UINib(nibName: "CategoryOffersGridTableViewCell", bundle: Bundle.frameworkResourceBundle),
forCellReuseIdentifier: "CategoryOffersGridTableViewCell"
)
}
}
extension CategoryOffersViewController: UITableViewDelegate, UITableViewDataSource {
public func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2 // Header + Grid
return 2 // Row 0: Header, Row 1: Grid
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryOffersHeaderTableViewCell", for: indexPath) as! CategoryOffersHeaderTableViewCell
if let title = sectionData?.title {
cell.headerLabel.text = title
}
cell.headerLabel.text = sectionData?.title ?? ""
cell.selectionStyle = .none
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryOffersGridTableViewCell", for: indexPath) as! CategoryOffersGridTableViewCell
cell.configureCell(with: sectionData, parentViewController: self)
cell.selectionStyle = .none
return cell
}
}
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
return UITableView.automaticDimension
} else {
return UITableView.automaticDimension // Or a calculated height depending on content
}
public func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
return 100
}
return 600
}
}
......
......@@ -802,4 +802,15 @@ extension MyRewardsViewController: MyRewardsOffersScrollTableViewCellDelegate {
func didSelectCouponSet(_ couponSet: CouponSetItemModel) {
openCouponsetViewController(with: couponSet)
}
func didSelectAllOffers(_ section: SectionModel) {
let vc = CategoryOffersViewController(nibName: "CategoryOffersViewController", bundle: Bundle.frameworkResourceBundle)
vc.sectionData = section
if let navigationController = self.navigationController {
navigationController.pushViewController(vc, animated: true)
} else {
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true, completion: nil)
}
}
}
......
......@@ -545,6 +545,11 @@ extension ProfileViewController: MyRewardsOffersScrollTableViewCellDelegate {
// ProfileViewController doesn't handle coupon sets, so just log
print("CouponSet selected in ProfileViewController: \(couponSet._name)")
}
func didSelectAllOffers(_ section: SectionModel) {
// ProfileViewController doesn't navigate to category offers
print("⚠️ [ProfileVC] didSelectAllOffers — not handled")
}
}
// Add delegate conformance
......