Showing
8 changed files
with
229 additions
and
100 deletions
No preview for this file type
| ... | @@ -9,10 +9,118 @@ import UIKit | ... | @@ -9,10 +9,118 @@ import UIKit |
| 9 | 9 | ||
| 10 | @objc(CategoryOfferCollectionViewCell) | 10 | @objc(CategoryOfferCollectionViewCell) |
| 11 | public class CategoryOfferCollectionViewCell: UICollectionViewCell { | 11 | public class CategoryOfferCollectionViewCell: UICollectionViewCell { |
| 12 | + @IBOutlet weak var parentView: UIView! | ||
| 13 | + @IBOutlet weak var bannerImage: UIImageView! | ||
| 14 | + @IBOutlet weak var logoImage: UIImageView! | ||
| 15 | + @IBOutlet weak var discountView: UIView! | ||
| 16 | + @IBOutlet weak var discountLabel: UILabel! | ||
| 17 | + @IBOutlet weak var merchantNameLabel: UILabel! | ||
| 18 | + @IBOutlet weak var titleLabel: UILabel! | ||
| 19 | + @IBOutlet weak var subtitleLabel: UILabel! | ||
| 20 | + @IBOutlet weak var expirationLabel: UILabel! | ||
| 21 | + | ||
| 22 | + var postImageURL: String? { | ||
| 23 | + didSet { | ||
| 24 | + if let url = postImageURL { | ||
| 25 | + self.bannerImage.image = UIImage() | ||
| 26 | + UIImage.loadImageUsingCacheWithUrlString(url) { image in | ||
| 27 | + if url == self.postImageURL { | ||
| 28 | + self.bannerImage.image = image | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + } else { | ||
| 32 | + self.bannerImage.image = nil | ||
| 33 | + } | ||
| 34 | + } | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + var logoImageURL: String? { | ||
| 38 | + didSet { | ||
| 39 | + if let url = logoImageURL { | ||
| 40 | + self.logoImage.image = UIImage() | ||
| 41 | + UIImage.loadImageUsingCacheWithUrlString(url) { image in | ||
| 42 | + if url == self.logoImageURL { | ||
| 43 | + self.logoImage.image = image | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | + } else { | ||
| 47 | + self.logoImage.image = nil | ||
| 48 | + } | ||
| 49 | + } | ||
| 50 | + } | ||
| 12 | 51 | ||
| 13 | public override func awakeFromNib() { | 52 | public override func awakeFromNib() { |
| 14 | super.awakeFromNib() | 53 | super.awakeFromNib() |
| 15 | - // Initialization code | 54 | + |
| 55 | + parentView.layer.borderWidth = 1.0 | ||
| 56 | + parentView.layer.borderColor = UIColor(rgb: 0xD2D6D9).cgColor | ||
| 57 | + parentView.layer.cornerRadius = 12.0 | ||
| 58 | + parentView.clipsToBounds = true | ||
| 59 | + | ||
| 60 | + logoImage.layer.cornerRadius = 8.0 | ||
| 61 | + logoImage.clipsToBounds = true | ||
| 62 | + logoImage.backgroundColor = UIColor(rgb: 0xEEEEEE) | ||
| 63 | + | ||
| 64 | + discountView.layer.cornerRadius = 17.0 | ||
| 65 | + discountView.clipsToBounds = true | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + func configureCell(data: OfferModel) { | ||
| 69 | + bannerImage.image = UIImage(named: data.bannerImage, in: Bundle.frameworkResourceBundle, compatibleWith: nil) | ||
| 70 | + | ||
| 71 | + discountLabel.text = data.discount | ||
| 72 | + discountLabel.font = UIFont(name: "PingLCG-Bold", size: 14) | ||
| 73 | + discountLabel.textColor = UIColor(rgb: 0xFFFFFF) | ||
| 74 | + discountView.backgroundColor = UIColor(rgb: 0xCBCBCB) | ||
| 75 | + | ||
| 76 | + merchantNameLabel.text = data.title | ||
| 77 | + merchantNameLabel.font = UIFont(name: "PingLCG-Regular", size: 12) | ||
| 78 | + merchantNameLabel.textColor = UIColor(rgb: 0x000F1E) | ||
| 79 | + | ||
| 80 | + titleLabel.text = data.title | ||
| 81 | + titleLabel.font = UIFont(name: "PingLCG-Bold", size: 15) | ||
| 82 | + titleLabel.textColor = UIColor(rgb: 0x000F1E) | ||
| 83 | + | ||
| 84 | + subtitleLabel.text = data.description | ||
| 85 | + subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 13) | ||
| 86 | + subtitleLabel.textColor = UIColor(rgb: 0x00111B) | ||
| 87 | + | ||
| 88 | + expirationLabel.text = data.expirationDate | ||
| 89 | + expirationLabel.font = UIFont(name: "PingLCG-Regular", size: 12) | ||
| 90 | + expirationLabel.textColor = UIColor(rgb: 0x9BA1A6) | ||
| 91 | + | ||
| 92 | + logoImage.image = UIImage(named: data.merchantLogo, in: Bundle.frameworkResourceBundle, compatibleWith: nil) | ||
| 16 | } | 93 | } |
| 17 | 94 | ||
| 95 | + func configureCell(data: CouponSetItemModel) { | ||
| 96 | + self.postImageURL = data._app_img_preview | ||
| 97 | + | ||
| 98 | + discountLabel.text = data._discount | ||
| 99 | + discountLabel.font = UIFont(name: "PingLCG-Bold", size: 14) | ||
| 100 | + discountLabel.textColor = UIColor(rgb: 0xFFFFFF) | ||
| 101 | + discountView.backgroundColor = UIColor(rgb: 0xCBCBCB) | ||
| 102 | + | ||
| 103 | + if let merchant = data._merchant { | ||
| 104 | + merchantNameLabel.text = merchant._admin_name | ||
| 105 | + self.logoImageURL = merchant._img_preview | ||
| 106 | + } else { | ||
| 107 | + merchantNameLabel.text = "" | ||
| 108 | + self.logoImageURL = nil | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + merchantNameLabel.font = UIFont(name: "PingLCG-Regular", size: 12) | ||
| 112 | + merchantNameLabel.textColor = UIColor(rgb: 0x000F1E) | ||
| 113 | + | ||
| 114 | + titleLabel.text = data._name | ||
| 115 | + titleLabel.font = UIFont(name: "PingLCG-Bold", size: 15) | ||
| 116 | + titleLabel.textColor = UIColor(rgb: 0x000F1E) | ||
| 117 | + | ||
| 118 | + subtitleLabel.text = data._short_description | ||
| 119 | + subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 13) | ||
| 120 | + subtitleLabel.textColor = UIColor(rgb: 0x00111B) | ||
| 121 | + | ||
| 122 | + expirationLabel.text = "until " + data.formattedEndDate(format: "dd-MM") | ||
| 123 | + expirationLabel.font = UIFont(name: "PingLCG-Regular", size: 12) | ||
| 124 | + expirationLabel.textColor = UIColor(rgb: 0x9BA1A6) | ||
| 125 | + } | ||
| 18 | } | 126 | } | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -12,52 +12,64 @@ public class CategoryOffersGridTableViewCell: UITableViewCell { | ... | @@ -12,52 +12,64 @@ public class CategoryOffersGridTableViewCell: UITableViewCell { |
| 12 | 12 | ||
| 13 | @IBOutlet weak var collectionView: UICollectionView! | 13 | @IBOutlet weak var collectionView: UICollectionView! |
| 14 | @IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint! | 14 | @IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint! |
| 15 | - | 15 | + |
| 16 | var data: SectionModel? | 16 | var data: SectionModel? |
| 17 | weak var parentViewController: UIViewController? | 17 | weak var parentViewController: UIViewController? |
| 18 | 18 | ||
| 19 | public override func awakeFromNib() { | 19 | public override func awakeFromNib() { |
| 20 | super.awakeFromNib() | 20 | super.awakeFromNib() |
| 21 | - // Initialization code | ||
| 22 | - | ||
| 23 | - setupCollectionView() | ||
| 24 | - } | ||
| 25 | 21 | ||
| 26 | - public override func setSelected(_ selected: Bool, animated: Bool) { | ||
| 27 | - super.setSelected(selected, animated: animated) | ||
| 28 | - // Configure the view for the selected state | ||
| 29 | - } | ||
| 30 | - | ||
| 31 | - private func setupCollectionView() { | ||
| 32 | collectionView.delegate = self | 22 | collectionView.delegate = self |
| 33 | collectionView.dataSource = self | 23 | collectionView.dataSource = self |
| 34 | collectionView.backgroundColor = .clear | 24 | collectionView.backgroundColor = .clear |
| 35 | - collectionView.isScrollEnabled = false // Scroll is handled by the outer TableView | 25 | + collectionView.isScrollEnabled = false |
| 36 | - | 26 | + |
| 37 | XIBLoader.registerCollectionViewCell( | 27 | XIBLoader.registerCollectionViewCell( |
| 38 | collectionView, | 28 | collectionView, |
| 39 | cellClass: UICollectionViewCell.self, | 29 | cellClass: UICollectionViewCell.self, |
| 40 | nibName: "CategoryOfferCollectionViewCell", | 30 | nibName: "CategoryOfferCollectionViewCell", |
| 41 | identifier: "CategoryOfferCollectionViewCell" | 31 | identifier: "CategoryOfferCollectionViewCell" |
| 42 | ) | 32 | ) |
| 43 | - | 33 | + |
| 44 | if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { | 34 | if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { |
| 45 | - layout.minimumInteritemSpacing = 16 | 35 | + layout.minimumInteritemSpacing = 12 |
| 46 | layout.minimumLineSpacing = 16 | 36 | layout.minimumLineSpacing = 16 |
| 47 | layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) | 37 | layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) |
| 48 | } | 38 | } |
| 49 | } | 39 | } |
| 50 | - | 40 | + |
| 41 | + public override func setSelected(_ selected: Bool, animated: Bool) { | ||
| 42 | + super.setSelected(selected, animated: animated) | ||
| 43 | + } | ||
| 44 | + | ||
| 51 | func configureCell(with sectionData: SectionModel?, parentViewController: UIViewController?) { | 45 | func configureCell(with sectionData: SectionModel?, parentViewController: UIViewController?) { |
| 52 | self.data = sectionData | 46 | self.data = sectionData |
| 53 | self.parentViewController = parentViewController | 47 | self.parentViewController = parentViewController |
| 54 | - | 48 | + |
| 55 | collectionView.reloadData() | 49 | collectionView.reloadData() |
| 56 | - | 50 | + |
| 57 | - // Use layoutIfNeeded to calculate content size and set the height constraint | 51 | + // Calculate and set the collection view height so the table view cell expands correctly |
| 58 | - collectionView.layoutIfNeeded() | 52 | + DispatchQueue.main.async { |
| 59 | - let height = collectionView.collectionViewLayout.collectionViewContentSize.height | 53 | + self.collectionView.layoutIfNeeded() |
| 60 | - collectionViewHeightConstraint.constant = height | 54 | + let height = self.collectionView.collectionViewLayout.collectionViewContentSize.height |
| 55 | + self.collectionViewHeightConstraint.constant = max(height, 1) | ||
| 56 | + // Notify the parent table view to recalculate its layout | ||
| 57 | + if let tableView = self.parentViewController?.view.subviews.first(where: { $0 is UITableView }) as? UITableView { | ||
| 58 | + tableView.beginUpdates() | ||
| 59 | + tableView.endUpdates() | ||
| 60 | + } | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + // Compute item size for 2-column grid | ||
| 65 | + private func itemSize() -> CGSize { | ||
| 66 | + let totalWidth = collectionView.bounds.width > 0 ? collectionView.bounds.width : UIScreen.main.bounds.width | ||
| 67 | + let inset: CGFloat = 16 | ||
| 68 | + let spacing: CGFloat = 12 | ||
| 69 | + let availableWidth = totalWidth - (inset * 2) - spacing | ||
| 70 | + let itemWidth = floor(availableWidth / 2) | ||
| 71 | + let itemHeight = itemWidth * 1.65 // ratio matching the design card proportions | ||
| 72 | + return CGSize(width: itemWidth, height: itemHeight) | ||
| 61 | } | 73 | } |
| 62 | } | 74 | } |
| 63 | 75 | ||
| ... | @@ -73,13 +85,13 @@ extension CategoryOffersGridTableViewCell: UICollectionViewDataSource, UICollect | ... | @@ -73,13 +85,13 @@ extension CategoryOffersGridTableViewCell: UICollectionViewDataSource, UICollect |
| 73 | 85 | ||
| 74 | public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { | 86 | public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { |
| 75 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryOfferCollectionViewCell", for: indexPath) as! CategoryOfferCollectionViewCell | 87 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryOfferCollectionViewCell", for: indexPath) as! CategoryOfferCollectionViewCell |
| 76 | - | 88 | + |
| 77 | guard let data = self.data, | 89 | guard let data = self.data, |
| 78 | let items = data.items, | 90 | let items = data.items, |
| 79 | indexPath.row < items.count else { | 91 | indexPath.row < items.count else { |
| 80 | return cell | 92 | return cell |
| 81 | } | 93 | } |
| 82 | - | 94 | + |
| 83 | switch data.itemType { | 95 | switch data.itemType { |
| 84 | case .couponSets: | 96 | case .couponSets: |
| 85 | if let couponSet = items[indexPath.row] as? CouponSetItemModel { | 97 | if let couponSet = items[indexPath.row] as? CouponSetItemModel { |
| ... | @@ -90,49 +102,46 @@ extension CategoryOffersGridTableViewCell: UICollectionViewDataSource, UICollect | ... | @@ -90,49 +102,46 @@ extension CategoryOffersGridTableViewCell: UICollectionViewDataSource, UICollect |
| 90 | cell.configureCell(data: offer) | 102 | cell.configureCell(data: offer) |
| 91 | } | 103 | } |
| 92 | } | 104 | } |
| 93 | - | 105 | + |
| 94 | return cell | 106 | return cell |
| 95 | } | 107 | } |
| 96 | - | 108 | + |
| 97 | public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { | 109 | public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { |
| 98 | guard let data = self.data, | 110 | guard let data = self.data, |
| 99 | let items = data.items, | 111 | let items = data.items, |
| 100 | indexPath.row < items.count else { | 112 | indexPath.row < items.count else { |
| 101 | return | 113 | return |
| 102 | } | 114 | } |
| 103 | - | 115 | + |
| 104 | - // Handle navigation based on item type | ||
| 105 | switch data.itemType { | 116 | switch data.itemType { |
| 106 | case .couponSets: | 117 | case .couponSets: |
| 107 | if let couponSet = items[indexPath.row] as? CouponSetItemModel { | 118 | if let couponSet = items[indexPath.row] as? CouponSetItemModel { |
| 108 | - let storyboard = UIStoryboard(name: "Main", bundle: Bundle.frameworkResourceBundle) | 119 | + let vc = CouponsetViewController(nibName: "CouponsetViewController", bundle: Bundle.frameworkResourceBundle) |
| 109 | - if let vc = storyboard.instantiateViewController(withIdentifier: "CouponsetViewController") as? CouponsetViewController { | 120 | + vc.couponset = couponSet |
| 110 | - vc.couponset = couponSet | 121 | + parentViewController?.navigationController?.pushViewController(vc, animated: true) |
| 111 | - self.parentViewController?.navigationController?.pushViewController(vc, animated: true) | ||
| 112 | - } | ||
| 113 | } | 122 | } |
| 114 | default: | 123 | default: |
| 115 | if let offer = items[indexPath.row] as? OfferModel { | 124 | if let offer = items[indexPath.row] as? OfferModel { |
| 116 | - // Determine if it's a campaign or other offer and navigate appropriately | 125 | + let vc = CouponViewController(nibName: "CouponViewController", bundle: Bundle.frameworkResourceBundle) |
| 117 | - // (Using existing patterns from MyRewardsViewController) | 126 | + vc.offer = offer |
| 118 | - let storyboard = UIStoryboard(name: "Main", bundle: Bundle.frameworkResourceBundle) | 127 | + parentViewController?.navigationController?.pushViewController(vc, animated: true) |
| 119 | - if let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as? CampaignViewController { | ||
| 120 | - vc.campaignUrl = offer.campaignUrl // Assuming OfferModel has this | ||
| 121 | - self.parentViewController?.navigationController?.pushViewController(vc, animated: true) | ||
| 122 | - } | ||
| 123 | } | 128 | } |
| 124 | } | 129 | } |
| 125 | } | 130 | } |
| 126 | 131 | ||
| 127 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { | 132 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { |
| 128 | - // Calculate width for 2 columns with spacing | 133 | + return itemSize() |
| 129 | - let padding: CGFloat = 16 * 3 // left + middle + right padding | 134 | + } |
| 130 | - let availableWidth = collectionView.frame.width - padding | 135 | + |
| 131 | - let itemWidth = availableWidth / 2 | 136 | + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { |
| 132 | - | 137 | + return 16 |
| 133 | - // Adjust height as needed based on design (aspect ratio or fixed) | 138 | + } |
| 134 | - let itemHeight = itemWidth * 1.3 // Approximation from screenshot | 139 | + |
| 135 | - | 140 | + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { |
| 136 | - return CGSize(width: itemWidth, height: itemHeight) | 141 | + return 12 |
| 142 | + } | ||
| 143 | + | ||
| 144 | + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { | ||
| 145 | + return UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) | ||
| 137 | } | 146 | } |
| 138 | } | 147 | } | ... | ... |
| ... | @@ -10,6 +10,7 @@ import UIKit | ... | @@ -10,6 +10,7 @@ import UIKit |
| 10 | protocol MyRewardsOffersScrollTableViewCellDelegate: AnyObject { | 10 | protocol MyRewardsOffersScrollTableViewCellDelegate: AnyObject { |
| 11 | func didSelectOffer(_ offer: OfferModel) | 11 | func didSelectOffer(_ offer: OfferModel) |
| 12 | func didSelectCouponSet(_ couponSet: CouponSetItemModel) | 12 | func didSelectCouponSet(_ couponSet: CouponSetItemModel) |
| 13 | + func didSelectAllOffers(_ section: SectionModel) | ||
| 13 | } | 14 | } |
| 14 | 15 | ||
| 15 | @objc(MyRewardsOffersScrollTableViewCell) | 16 | @objc(MyRewardsOffersScrollTableViewCell) |
| ... | @@ -29,19 +30,19 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell { | ... | @@ -29,19 +30,19 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell { |
| 29 | super.awakeFromNib() | 30 | super.awakeFromNib() |
| 30 | // Initialization code | 31 | // Initialization code |
| 31 | 32 | ||
| 32 | - // allButtonView.layer.borderWidth = 1.0 | ||
| 33 | - // allButtonView.layer.borderColor = UIColor(rgb: 0x000F1E).cgColor | ||
| 34 | - // allButtonView.layer.cornerRadius = 4.0 | ||
| 35 | - | ||
| 36 | allButtonArrowImage.image = UIImage(named: "arrow_right_blue", in: Bundle.frameworkResourceBundle, compatibleWith: nil) | 33 | allButtonArrowImage.image = UIImage(named: "arrow_right_blue", in: Bundle.frameworkResourceBundle, compatibleWith: nil) |
| 37 | 34 | ||
| 38 | - // allButtonLabel.text = "Όλα" | ||
| 39 | allButtonLabel.text = "All" | 35 | allButtonLabel.text = "All" |
| 40 | allButtonLabel.font = UIFont(name: "PingLCG-Regular", size: 15) | 36 | allButtonLabel.font = UIFont(name: "PingLCG-Regular", size: 15) |
| 41 | allButtonLabel.textColor = UIColor(rgb: 0x004E6E) | 37 | allButtonLabel.textColor = UIColor(rgb: 0x004E6E) |
| 42 | allButtonLabel.frame.size.width = allButtonLabel.intrinsicContentSize.width | 38 | allButtonLabel.frame.size.width = allButtonLabel.intrinsicContentSize.width |
| 43 | allButtonLabel.frame.size.height = allButtonLabel.intrinsicContentSize.height | 39 | allButtonLabel.frame.size.height = allButtonLabel.intrinsicContentSize.height |
| 44 | 40 | ||
| 41 | + // Add tap gesture to allButtonView | ||
| 42 | + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(allButtonTapped)) | ||
| 43 | + allButtonView.isUserInteractionEnabled = true | ||
| 44 | + allButtonView.addGestureRecognizer(tapGesture) | ||
| 45 | + | ||
| 45 | // UPDATED: Safe XIB registration for collection view cells | 46 | // UPDATED: Safe XIB registration for collection view cells |
| 46 | registerCollectionViewCells() | 47 | registerCollectionViewCells() |
| 47 | 48 | ||
| ... | @@ -56,6 +57,11 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell { | ... | @@ -56,6 +57,11 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell { |
| 56 | collectionView.dataSource = self | 57 | collectionView.dataSource = self |
| 57 | } | 58 | } |
| 58 | 59 | ||
| 60 | + @objc private func allButtonTapped() { | ||
| 61 | + guard let data = data else { return } | ||
| 62 | + delegate?.didSelectAllOffers(data) | ||
| 63 | + } | ||
| 64 | + | ||
| 59 | // NEW: Safe collection view cell registration | 65 | // NEW: Safe collection view cell registration |
| 60 | private func registerCollectionViewCells() { | 66 | private func registerCollectionViewCells() { |
| 61 | XIBLoader.registerCollectionViewCell( | 67 | XIBLoader.registerCollectionViewCell( |
| ... | @@ -109,20 +115,11 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell { | ... | @@ -109,20 +115,11 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell { |
| 109 | collectionViewBottom.constant = 0 | 115 | collectionViewBottom.constant = 0 |
| 110 | } | 116 | } |
| 111 | 117 | ||
| 112 | - // Update collection view height based on section | 118 | + collectionViewHeightConstraint.constant = 232 // Default height |
| 113 | - // if data?.title == "Αγαπημένα" { | ||
| 114 | - // collectionViewHeightConstraint.constant = 350 // Match cell height | ||
| 115 | - // } else { | ||
| 116 | - collectionViewHeightConstraint.constant = 232 // Default height | ||
| 117 | - // } | ||
| 118 | 119 | ||
| 119 | // Configure layout based on section type | 120 | // Configure layout based on section type |
| 120 | if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { | 121 | if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { |
| 121 | - // if data?.title == "Αγαπημένα" { | 122 | + layout.minimumLineSpacing = 7 |
| 122 | - // layout.minimumLineSpacing = 24 | ||
| 123 | - // } else { | ||
| 124 | - layout.minimumLineSpacing = 7 | ||
| 125 | - // } | ||
| 126 | } | 123 | } |
| 127 | 124 | ||
| 128 | let catBoldText = (data?.title ?? "") + " " | 125 | let catBoldText = (data?.title ?? "") + " " |
| ... | @@ -138,13 +135,11 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell { | ... | @@ -138,13 +135,11 @@ public class MyRewardsOffersScrollTableViewCell: UITableViewCell { |
| 138 | categoryLabel.attributedText = catAttributedString | 135 | categoryLabel.attributedText = catAttributedString |
| 139 | 136 | ||
| 140 | self.collectionView.reloadData(); | 137 | self.collectionView.reloadData(); |
| 141 | - | ||
| 142 | } | 138 | } |
| 143 | } | 139 | } |
| 144 | 140 | ||
| 145 | extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { | 141 | extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { |
| 146 | 142 | ||
| 147 | - | ||
| 148 | public func numberOfSections(in collectionView: UICollectionView) -> Int { | 143 | public func numberOfSections(in collectionView: UICollectionView) -> Int { |
| 149 | return 1 | 144 | return 1 |
| 150 | } | 145 | } |
| ... | @@ -189,11 +184,9 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl | ... | @@ -189,11 +184,9 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl |
| 189 | switch data.itemType { | 184 | switch data.itemType { |
| 190 | case .couponSets: | 185 | case .couponSets: |
| 191 | if let couponSet = items[indexPath.row] as? CouponSetItemModel { | 186 | if let couponSet = items[indexPath.row] as? CouponSetItemModel { |
| 192 | - // Pass CouponSetItemModel directly to new delegate method | ||
| 193 | delegate?.didSelectCouponSet(couponSet) | 187 | delegate?.didSelectCouponSet(couponSet) |
| 194 | } | 188 | } |
| 195 | default: | 189 | default: |
| 196 | - // Handle OfferModel directly for ProfileViewController compatibility | ||
| 197 | if let offer = items[indexPath.row] as? OfferModel { | 190 | if let offer = items[indexPath.row] as? OfferModel { |
| 198 | delegate?.didSelectOffer(offer) | 191 | delegate?.didSelectOffer(offer) |
| 199 | } | 192 | } |
| ... | @@ -202,20 +195,12 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl | ... | @@ -202,20 +195,12 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl |
| 202 | 195 | ||
| 203 | // MARK: - UICollectionViewDelegateFlowLayout | 196 | // MARK: - UICollectionViewDelegateFlowLayout |
| 204 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { | 197 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { |
| 205 | - // if self.data?.title == "Αγαπημένα" { | 198 | + return CGSize(width: 257, height: 232) |
| 206 | - // return CGSize(width: 275, height: 350) | ||
| 207 | - // } else { | ||
| 208 | - return CGSize(width: 257, height: 232) | ||
| 209 | - // } | ||
| 210 | } | 199 | } |
| 211 | 200 | ||
| 212 | // Distance Between Item Cells | 201 | // Distance Between Item Cells |
| 213 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { | 202 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { |
| 214 | - // if self.data?.title == "Αγαπημένα" { | 203 | + return 7 |
| 215 | - // return 24 | ||
| 216 | - // } else { | ||
| 217 | - return 7 | ||
| 218 | - // } | ||
| 219 | } | 204 | } |
| 220 | 205 | ||
| 221 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { | 206 | public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { | ... | ... |
| ... | @@ -8,60 +8,71 @@ | ... | @@ -8,60 +8,71 @@ |
| 8 | import UIKit | 8 | import UIKit |
| 9 | 9 | ||
| 10 | @objc public class CategoryOffersViewController: UIViewController { | 10 | @objc public class CategoryOffersViewController: UIViewController { |
| 11 | - | 11 | + |
| 12 | @IBOutlet weak var tableView: UITableView! | 12 | @IBOutlet weak var tableView: UITableView! |
| 13 | - | 13 | + |
| 14 | public var sectionData: SectionModel? | 14 | public var sectionData: SectionModel? |
| 15 | - | 15 | + |
| 16 | public override func viewDidLoad() { | 16 | public override func viewDidLoad() { |
| 17 | super.viewDidLoad() | 17 | super.viewDidLoad() |
| 18 | - | 18 | + |
| 19 | self.navigationController?.setNavigationBarHidden(false, animated: false) | 19 | self.navigationController?.setNavigationBarHidden(false, animated: false) |
| 20 | setBackButton() | 20 | setBackButton() |
| 21 | - | 21 | + |
| 22 | setupTableView() | 22 | setupTableView() |
| 23 | } | 23 | } |
| 24 | - | 24 | + |
| 25 | private func setupTableView() { | 25 | private func setupTableView() { |
| 26 | tableView.delegate = self | 26 | tableView.delegate = self |
| 27 | tableView.dataSource = self | 27 | tableView.dataSource = self |
| 28 | - | ||
| 29 | tableView.separatorStyle = .none | 28 | tableView.separatorStyle = .none |
| 30 | tableView.backgroundColor = .white | 29 | tableView.backgroundColor = .white |
| 31 | - | 30 | + tableView.estimatedRowHeight = 100 |
| 32 | - tableView.register(UINib(nibName: "CategoryOffersHeaderTableViewCell", bundle: Bundle.frameworkResourceBundle), forCellReuseIdentifier: "CategoryOffersHeaderTableViewCell") | 31 | + tableView.rowHeight = UITableView.automaticDimension |
| 33 | - tableView.register(UINib(nibName: "CategoryOffersGridTableViewCell", bundle: Bundle.frameworkResourceBundle), forCellReuseIdentifier: "CategoryOffersGridTableViewCell") | 32 | + |
| 33 | + tableView.register( | ||
| 34 | + UINib(nibName: "CategoryOffersHeaderTableViewCell", bundle: Bundle.frameworkResourceBundle), | ||
| 35 | + forCellReuseIdentifier: "CategoryOffersHeaderTableViewCell" | ||
| 36 | + ) | ||
| 37 | + tableView.register( | ||
| 38 | + UINib(nibName: "CategoryOffersGridTableViewCell", bundle: Bundle.frameworkResourceBundle), | ||
| 39 | + forCellReuseIdentifier: "CategoryOffersGridTableViewCell" | ||
| 40 | + ) | ||
| 34 | } | 41 | } |
| 35 | } | 42 | } |
| 36 | 43 | ||
| 37 | extension CategoryOffersViewController: UITableViewDelegate, UITableViewDataSource { | 44 | extension CategoryOffersViewController: UITableViewDelegate, UITableViewDataSource { |
| 45 | + | ||
| 38 | public func numberOfSections(in tableView: UITableView) -> Int { | 46 | public func numberOfSections(in tableView: UITableView) -> Int { |
| 39 | return 1 | 47 | return 1 |
| 40 | } | 48 | } |
| 41 | - | 49 | + |
| 42 | public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | 50 | public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
| 43 | - return 2 // Header + Grid | 51 | + return 2 // Row 0: Header, Row 1: Grid |
| 44 | } | 52 | } |
| 45 | - | 53 | + |
| 46 | public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | 54 | public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
| 47 | if indexPath.row == 0 { | 55 | if indexPath.row == 0 { |
| 48 | let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryOffersHeaderTableViewCell", for: indexPath) as! CategoryOffersHeaderTableViewCell | 56 | let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryOffersHeaderTableViewCell", for: indexPath) as! CategoryOffersHeaderTableViewCell |
| 49 | - if let title = sectionData?.title { | 57 | + cell.headerLabel.text = sectionData?.title ?? "" |
| 50 | - cell.headerLabel.text = title | 58 | + cell.selectionStyle = .none |
| 51 | - } | ||
| 52 | return cell | 59 | return cell |
| 53 | } else { | 60 | } else { |
| 54 | let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryOffersGridTableViewCell", for: indexPath) as! CategoryOffersGridTableViewCell | 61 | let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryOffersGridTableViewCell", for: indexPath) as! CategoryOffersGridTableViewCell |
| 55 | cell.configureCell(with: sectionData, parentViewController: self) | 62 | cell.configureCell(with: sectionData, parentViewController: self) |
| 63 | + cell.selectionStyle = .none | ||
| 56 | return cell | 64 | return cell |
| 57 | } | 65 | } |
| 58 | } | 66 | } |
| 59 | - | 67 | + |
| 60 | public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { | 68 | public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { |
| 69 | + return UITableView.automaticDimension | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + public func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { | ||
| 61 | if indexPath.row == 0 { | 73 | if indexPath.row == 0 { |
| 62 | - return UITableView.automaticDimension | 74 | + return 100 |
| 63 | - } else { | ||
| 64 | - return UITableView.automaticDimension // Or a calculated height depending on content | ||
| 65 | } | 75 | } |
| 76 | + return 600 | ||
| 66 | } | 77 | } |
| 67 | } | 78 | } | ... | ... |
| ... | @@ -802,4 +802,15 @@ extension MyRewardsViewController: MyRewardsOffersScrollTableViewCellDelegate { | ... | @@ -802,4 +802,15 @@ extension MyRewardsViewController: MyRewardsOffersScrollTableViewCellDelegate { |
| 802 | func didSelectCouponSet(_ couponSet: CouponSetItemModel) { | 802 | func didSelectCouponSet(_ couponSet: CouponSetItemModel) { |
| 803 | openCouponsetViewController(with: couponSet) | 803 | openCouponsetViewController(with: couponSet) |
| 804 | } | 804 | } |
| 805 | + | ||
| 806 | + func didSelectAllOffers(_ section: SectionModel) { | ||
| 807 | + let vc = CategoryOffersViewController(nibName: "CategoryOffersViewController", bundle: Bundle.frameworkResourceBundle) | ||
| 808 | + vc.sectionData = section | ||
| 809 | + if let navigationController = self.navigationController { | ||
| 810 | + navigationController.pushViewController(vc, animated: true) | ||
| 811 | + } else { | ||
| 812 | + vc.modalPresentationStyle = .fullScreen | ||
| 813 | + self.present(vc, animated: true, completion: nil) | ||
| 814 | + } | ||
| 815 | + } | ||
| 805 | } | 816 | } | ... | ... |
| ... | @@ -545,6 +545,11 @@ extension ProfileViewController: MyRewardsOffersScrollTableViewCellDelegate { | ... | @@ -545,6 +545,11 @@ extension ProfileViewController: MyRewardsOffersScrollTableViewCellDelegate { |
| 545 | // ProfileViewController doesn't handle coupon sets, so just log | 545 | // ProfileViewController doesn't handle coupon sets, so just log |
| 546 | print("CouponSet selected in ProfileViewController: \(couponSet._name)") | 546 | print("CouponSet selected in ProfileViewController: \(couponSet._name)") |
| 547 | } | 547 | } |
| 548 | + | ||
| 549 | + func didSelectAllOffers(_ section: SectionModel) { | ||
| 550 | + // ProfileViewController doesn't navigate to category offers | ||
| 551 | + print("⚠️ [ProfileVC] didSelectAllOffers — not handled") | ||
| 552 | + } | ||
| 548 | } | 553 | } |
| 549 | 554 | ||
| 550 | // Add delegate conformance | 555 | // Add delegate conformance | ... | ... |
-
Please register or login to post a comment