Manos Chorianopoulos

MyCouponsViewController part3

......@@ -10,44 +10,58 @@ import UIKit
@objc(ProfileCouponTableViewCell)
public class ProfileCouponTableViewCell: UITableViewCell {
@IBOutlet weak var parentView: UIView!
@IBOutlet weak var bannerImage: UIImageView!
@IBOutlet weak var favoriteImage: UIImageView!
@IBOutlet weak var discountView: UIView!
@IBOutlet weak var discountLabel: UILabel!
// @IBOutlet weak var bannerImage: UIImageView!
// @IBOutlet weak var favoriteImage: UIImageView!
// @IBOutlet weak var discountView: UIView!
// @IBOutlet weak var discountLabel: UILabel!
@IBOutlet weak var logoImageView: UIView!
@IBOutlet weak var logoImage: UIImageView!
@IBOutlet weak var expirationView: UIView!
@IBOutlet weak var expirationImage: UIImageView!
@IBOutlet weak var expirationLabel: UILabel!
@IBOutlet weak var merchantNameLabel: UILabel!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subtitleLabel: UILabel!
@IBOutlet weak var expirationLabel: UILabel!
@IBOutlet weak var logoImage: UIImageView!
@IBOutlet weak var arrowView: UIView!
@IBOutlet weak var arrowImage: UIImageView!
public override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
parentView.layer.borderWidth = 1.0
parentView.layer.borderColor = UIColor(rgb: 0xCCCCCC).cgColor
parentView.layer.cornerRadius = 8.0
parentView.backgroundColor = UIColor(rgb: 0xDDEFFB)
parentView.layer.borderWidth = 2.0
parentView.layer.borderColor = UIColor(rgb: 0xA5DAF8).cgColor
parentView.layer.cornerRadius = 12.0
parentView.clipsToBounds = true
arrowView.backgroundColor = UIColor(rgb: 0xFFFFFF)
arrowView.layer.cornerRadius = arrowView.bounds.height / 2
discountView.layer.cornerRadius = 42.0
arrowImage.image = UIImage(named: "ic_forward", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
expirationImage.image = UIImage(named: "clock", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
// discountView.layer.cornerRadius = 42.0
}
// MARK: - Image Loading Helpers
private var bannerImageURL: String? {
didSet {
if let url = bannerImageURL, !url.isEmpty {
self.bannerImage.image = UIImage()
UIImage.loadImageUsingCacheWithUrlString(url) { [weak self] image in
if url == self?.bannerImageURL {
self?.bannerImage.image = image
}
}
} else {
self.bannerImage.image = nil
}
}
}
// private var bannerImageURL: String? {
// didSet {
// if let url = bannerImageURL, !url.isEmpty {
// self.bannerImage.image = UIImage()
// UIImage.loadImageUsingCacheWithUrlString(url) { [weak self] image in
// if url == self?.bannerImageURL {
// self?.bannerImage.image = image
// }
// }
// } else {
// self.bannerImage.image = nil
// }
// }
// }
private var logoImageURL: String? {
didSet {
......@@ -67,22 +81,22 @@ public class ProfileCouponTableViewCell: UITableViewCell {
// MARK: - Configure with OfferModel (legacy, kept for backward compatibility)
func configureCell(data: OfferModel) {
bannerImage.image = UIImage(named: data.bannerImage, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
favoriteImage.image = UIImage(named: data.isFavorite ? "favorite_filled" : "favorite_empty", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
// bannerImage.image = UIImage(named: data.bannerImage, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
// favoriteImage.image = UIImage(named: data.isFavorite ? "favorite_filled" : "favorite_empty", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
let discountSymbol =
data.discountType == "percentage" ? "%"
: data.discountType == "price" ? "€"
: data.discountType == "buyOneGetOne" ? "1+1"
: data.discountType == "free" ? "Δωρεάν"
: ""
// let discountSymbol =
// data.discountType == "percentage" ? "%"
// : data.discountType == "price" ? "€"
// : data.discountType == "buyOneGetOne" ? "1+1"
// : data.discountType == "free" ? "Δωρεάν"
// : ""
// discountLabel.text = "\(data.discount)\(discountSymbol)"
discountLabel.text = data.discount
discountLabel.font = UIFont(name: "PingLCG-Bold", size: 25)
discountLabel.textColor = UIColor(rgb: 0xF2F2F2)
// // discountLabel.text = "\(data.discount)\(discountSymbol)"
// discountLabel.text = data.discount
// discountLabel.font = UIFont(name: "PingLCG-Bold", size: 25)
// discountLabel.textColor = UIColor(rgb: 0xF2F2F2)
discountView.backgroundColor = UIColor(rgb: data.color)
// discountView.backgroundColor = UIColor(rgb: data.color)
titleLabel.text = data.title
titleLabel.font = UIFont(name: "PingLCG-Bold", size: 22)
......@@ -103,56 +117,84 @@ public class ProfileCouponTableViewCell: UITableViewCell {
func configureCell(data: CouponItemModel) {
// Banner image — load from couponset_data img_preview (remote URL)
if let imgPreview = data.couponset_data?._img_preview, !imgPreview.isEmpty {
self.bannerImageURL = imgPreview
} else {
bannerImage.image = nil
}
// if let imgPreview = data.couponset_data?._img_preview, !imgPreview.isEmpty {
// self.bannerImageURL = imgPreview
// } else {
// bannerImage.image = nil
// }
// Favorite — default to not favorite for now
favoriteImage.image = UIImage(named: "favorite_empty", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
// Discount label — use coupon discount or couponset discount
let discountText = data.discount ?? data.couponset_data?._discount ?? ""
discountLabel.text = discountText
discountLabel.font = UIFont(name: "PingLCG-Bold", size: 25)
discountLabel.textColor = UIColor(rgb: 0xF2F2F2)
// Discount view color based on discount type
let discountType = data.couponset_data?._discount_type ?? ""
let discountColor: UInt = {
switch discountType {
case "percentage":
return 0xFF6B35
case "value":
return 0x28A745
case "plus_one":
return 0x007AFF
default:
return 0xEE417D
}
}()
discountView.backgroundColor = UIColor(rgb: discountColor)
// favoriteImage.image = UIImage(named: "favorite_empty", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
// // Discount label — use coupon discount or couponset discount
// let discountText = data.discount ?? data.couponset_data?._discount ?? ""
// discountLabel.text = discountText
// discountLabel.font = UIFont(name: "PingLCG-Bold", size: 25)
// discountLabel.textColor = UIColor(rgb: 0xF2F2F2)
// // Discount view color based on discount type
// let discountType = data.couponset_data?._discount_type ?? ""
// let discountColor: UInt = {
// switch discountType {
// case "percentage":
// return 0xFF6B35
// case "value":
// return 0x28A745
// case "plus_one":
// return 0x007AFF
// default:
// return 0xEE417D
// }
// }()
// discountView.backgroundColor = UIColor(rgb: discountColor)
merchantNameLabel.font = UIFont(name: "PingLCG-Bold", size: 14)
merchantNameLabel.textColor = UIColor(rgb: 0x5C6369)
merchantNameLabel.text = data.merchant_details?._name
// Title — from couponset_data name
titleLabel.text = data.couponset_data?._name ?? ""
titleLabel.font = UIFont(name: "PingLCG-Bold", size: 22)
titleLabel.textColor = UIColor(rgb: 0x000F1E)
titleLabel.textColor = UIColor(rgb: 0x1D2023)
// Subtitle — from couponset_data short_description
subtitleLabel.text = data.couponset_data?._short_description ?? ""
subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 16)
subtitleLabel.textColor = UIColor(rgb: 0x00111B)
subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 13)
subtitleLabel.textColor = UIColor(rgb: 0x5C6369)
// Expiration — already formatted as "dd/MM/yyyy" by CouponItemModel
if let expiration = data.expiration, !expiration.isEmpty {
expirationLabel.text = "έως " + expiration
expirationView.layer.cornerRadius = 6.0
expirationView.layer.borderWidth = 1.0
let isExpiringSoon: Bool
if let expirationDate = data.expirationDate {
let today = Calendar.current.startOfDay(for: Date())
let expDay = Calendar.current.startOfDay(for: expirationDate)
let daysLeft = Calendar.current.dateComponents([.day], from: today, to: expDay).day ?? Int.max
if daysLeft <= 3 {
isExpiringSoon = true
expirationLabel.text = "\(daysLeft) days left"
} else {
isExpiringSoon = false
expirationLabel.text = "Valid until " + data.formattedExpiration(format: "MMMM d, yyyy")
}
} else {
isExpiringSoon = false
expirationLabel.text = ""
}
expirationLabel.font = UIFont(name: "PingLCG-Regular", size: 13)
expirationLabel.textColor = UIColor(rgb: 0x00111B)
if isExpiringSoon {
expirationView.backgroundColor = UIColor(rgb: 0xFFF5DA)
expirationView.layer.borderColor = UIColor(rgb: 0xFFEABA).cgColor
} else {
expirationView.backgroundColor = UIColor(rgb: 0xF1F2F4)
expirationView.layer.borderColor = UIColor(rgb: 0xD2D6D9).cgColor
}
expirationLabel.font = UIFont(name: "PingLCG-Bold", size: 13)
expirationLabel.textColor = UIColor(rgb: 0x002430)
logoImageView.backgroundColor = UIColor(rgb: 0xFFFFFF)
logoImageView.layer.cornerRadius = 10.0
// Logo — load from merchant_details img_preview (remote URL)
if let merchantImgPreview = data.merchant_details?._img_preview, !merchantImgPreview.isEmpty {
self.logoImageURL = merchantImgPreview
......
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<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="23084"/>
<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"/>
......@@ -18,153 +18,157 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="x0X-za-HZ9" userLabel="Parent View">
<rect key="frame" x="22" y="0.0" width="276" height="292"/>
<rect key="frame" x="18" y="0.0" width="284" height="175"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8Ht-7Z-jiW" userLabel="Top View">
<rect key="frame" x="0.0" y="0.0" width="276" height="171"/>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fZ6-8K-DXr" userLabel="Bottom View">
<rect key="frame" x="0.0" y="0.0" width="284" height="175"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="09g-Nj-HG4">
<rect key="frame" x="0.0" y="0.0" width="276" height="171"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</imageView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4xy-g8-Ukx" userLabel="Fav View">
<rect key="frame" x="16" y="13" width="46" height="46"/>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Fcn-J9-gqq" userLabel="LogoImageView">
<rect key="frame" x="10" y="10" width="67" height="67"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="T91-Ra-dmT">
<rect key="frame" x="0.0" y="0.0" width="46" height="46"/>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="hM2-8T-4vX">
<rect key="frame" x="10" y="10" width="47" height="47"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</imageView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="46" id="Cc2-q8-pqb"/>
<constraint firstAttribute="trailing" secondItem="T91-Ra-dmT" secondAttribute="trailing" id="FHe-DH-ghP"/>
<constraint firstItem="T91-Ra-dmT" firstAttribute="top" secondItem="4xy-g8-Ukx" secondAttribute="top" id="HMT-10-TaU"/>
<constraint firstAttribute="bottom" secondItem="T91-Ra-dmT" secondAttribute="bottom" id="K7M-Vf-uo8"/>
<constraint firstItem="T91-Ra-dmT" firstAttribute="leading" secondItem="4xy-g8-Ukx" secondAttribute="leading" id="diD-2x-xIG"/>
<constraint firstAttribute="height" constant="46" id="gtM-XV-LnS"/>
<constraint firstAttribute="width" constant="67" id="9pk-g2-gcB"/>
<constraint firstAttribute="bottom" secondItem="hM2-8T-4vX" secondAttribute="bottom" constant="10" id="AQa-wS-Zt5"/>
<constraint firstAttribute="height" constant="67" id="FfF-lB-tUl"/>
<constraint firstItem="hM2-8T-4vX" firstAttribute="top" secondItem="Fcn-J9-gqq" secondAttribute="top" constant="10" id="gus-oR-l57"/>
<constraint firstItem="hM2-8T-4vX" firstAttribute="leading" secondItem="Fcn-J9-gqq" secondAttribute="leading" constant="10" id="pn8-ti-KXs"/>
<constraint firstAttribute="trailing" secondItem="hM2-8T-4vX" secondAttribute="trailing" constant="10" id="qbD-TE-zfq"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dnZ-fa-M3o" userLabel="Discount View">
<rect key="frame" x="179" y="14" width="84" height="84"/>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9ju-6P-k6F" userLabel="Expiration View">
<rect key="frame" x="197.66666666666666" y="10" width="76.333333333333343" height="34.333333333333336"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XeI-PB-wG7">
<rect key="frame" x="5" y="31.666666666666664" width="74" height="21"/>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="wkd-wh-r1w" userLabel="Expiration Image">
<rect key="frame" x="10" y="10.333333333333332" width="14" height="14"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="14" id="6zU-V6-H7S"/>
<constraint firstAttribute="width" constant="14" id="vf0-mS-97Q"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZgP-Qt-8og" userLabel="Expiration Label">
<rect key="frame" x="28.000000000000004" y="6.9999999999999982" width="41.333333333333343" height="20.333333333333329"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="84" id="8gp-O1-LgD"/>
<constraint firstAttribute="width" constant="84" id="Mve-Yl-rsU"/>
<constraint firstItem="XeI-PB-wG7" firstAttribute="centerY" secondItem="dnZ-fa-M3o" secondAttribute="centerY" id="Rlp-4Z-urE"/>
<constraint firstAttribute="trailing" secondItem="XeI-PB-wG7" secondAttribute="trailing" constant="5" id="dyI-UO-uvn"/>
<constraint firstItem="XeI-PB-wG7" firstAttribute="leading" secondItem="dnZ-fa-M3o" secondAttribute="leading" constant="5" id="eon-8Y-X7c"/>
<constraint firstAttribute="trailing" secondItem="ZgP-Qt-8og" secondAttribute="trailing" constant="7" id="AwZ-gG-3PO"/>
<constraint firstItem="wkd-wh-r1w" firstAttribute="centerY" secondItem="9ju-6P-k6F" secondAttribute="centerY" id="CnU-ts-AtX"/>
<constraint firstItem="ZgP-Qt-8og" firstAttribute="leading" secondItem="wkd-wh-r1w" secondAttribute="trailing" constant="4" id="PXB-bc-eTM"/>
<constraint firstAttribute="bottom" secondItem="ZgP-Qt-8og" secondAttribute="bottom" constant="7" id="Wab-ed-1oR"/>
<constraint firstItem="wkd-wh-r1w" firstAttribute="leading" secondItem="9ju-6P-k6F" secondAttribute="leading" constant="10" id="e2L-4Z-2xN"/>
<constraint firstItem="ZgP-Qt-8og" firstAttribute="top" secondItem="9ju-6P-k6F" secondAttribute="top" constant="7" id="gYV-rG-X6r"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="09g-Nj-HG4" firstAttribute="leading" secondItem="8Ht-7Z-jiW" secondAttribute="leading" id="1AO-0a-ZpN"/>
<constraint firstItem="dnZ-fa-M3o" firstAttribute="top" secondItem="8Ht-7Z-jiW" secondAttribute="top" constant="14" id="AC6-zX-rmc"/>
<constraint firstItem="09g-Nj-HG4" firstAttribute="top" secondItem="8Ht-7Z-jiW" secondAttribute="top" id="DYc-4B-bTE"/>
<constraint firstAttribute="bottom" secondItem="09g-Nj-HG4" secondAttribute="bottom" id="Rsg-ZQ-0bM"/>
<constraint firstItem="4xy-g8-Ukx" firstAttribute="leading" secondItem="8Ht-7Z-jiW" secondAttribute="leading" constant="16" id="U8A-vw-Pca"/>
<constraint firstItem="4xy-g8-Ukx" firstAttribute="top" secondItem="8Ht-7Z-jiW" secondAttribute="top" constant="13" id="ZGF-7X-iSN"/>
<constraint firstAttribute="trailing" secondItem="09g-Nj-HG4" secondAttribute="trailing" id="qwK-yM-rD6"/>
<constraint firstAttribute="trailing" secondItem="dnZ-fa-M3o" secondAttribute="trailing" constant="13" id="zAy-FM-iqd"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fZ6-8K-DXr" userLabel="Bottom View">
<rect key="frame" x="0.0" y="171" width="276" height="121"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YtM-Db-ygP">
<rect key="frame" x="16" y="17" width="130" height="93"/>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YtM-Db-ygP" userLabel="InfoView">
<rect key="frame" x="17" y="93" width="260" height="65"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="63p-dI-yTa">
<rect key="frame" x="0.0" y="0.0" width="130" height="21"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Label" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mO2-Xp-IVu" userLabel="Merchant Name Label">
<rect key="frame" x="0.0" y="0.0" width="260" height="20.333333333333332"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="z30-VZ-8h3">
<rect key="frame" x="0.0" y="23" width="130" height="20.333333333333329"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="63p-dI-yTa">
<rect key="frame" x="0.0" y="22.333333333333343" width="211" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PZ3-qH-3XH">
<rect key="frame" x="0.0" y="72" width="130" height="21"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="z30-VZ-8h3">
<rect key="frame" x="0.0" y="45.333333333333329" width="211" height="20.333333333333329"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cko-1v-wDx" userLabel="ArrowView">
<rect key="frame" x="221" y="26" width="39" height="39"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ZRF-CC-IKd">
<rect key="frame" x="11" y="13" width="17" height="13"/>
<constraints>
<constraint firstAttribute="height" constant="13" id="ZR7-aH-0zM"/>
<constraint firstAttribute="width" constant="17" id="lGj-BM-N9w"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="39" id="Zh7-U5-7dh"/>
<constraint firstAttribute="width" constant="39" id="eIh-Ke-CJw"/>
<constraint firstItem="ZRF-CC-IKd" firstAttribute="centerY" secondItem="cko-1v-wDx" secondAttribute="centerY" id="jyW-Ir-XED"/>
<constraint firstItem="ZRF-CC-IKd" firstAttribute="centerX" secondItem="cko-1v-wDx" secondAttribute="centerX" id="sdA-PR-KMw"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="63p-dI-yTa" firstAttribute="top" secondItem="mO2-Xp-IVu" secondAttribute="bottom" constant="2" id="1rR-YP-pAJ"/>
<constraint firstItem="mO2-Xp-IVu" firstAttribute="top" secondItem="YtM-Db-ygP" secondAttribute="top" id="28l-ae-BOD"/>
<constraint firstAttribute="bottom" secondItem="z30-VZ-8h3" secondAttribute="bottom" id="6k0-Nw-BSn"/>
<constraint firstItem="z30-VZ-8h3" firstAttribute="leading" secondItem="YtM-Db-ygP" secondAttribute="leading" id="DHf-fQ-lXA"/>
<constraint firstAttribute="trailing" secondItem="z30-VZ-8h3" secondAttribute="trailing" id="DnI-99-e8v"/>
<constraint firstAttribute="trailing" secondItem="PZ3-qH-3XH" secondAttribute="trailing" id="JA5-Am-dmE"/>
<constraint firstItem="63p-dI-yTa" firstAttribute="top" secondItem="YtM-Db-ygP" secondAttribute="top" id="Kfa-m3-rWW"/>
<constraint firstAttribute="trailing" secondItem="63p-dI-yTa" secondAttribute="trailing" id="bxa-5c-OE6"/>
<constraint firstAttribute="trailing" secondItem="mO2-Xp-IVu" secondAttribute="trailing" id="QeV-2c-rkN"/>
<constraint firstItem="cko-1v-wDx" firstAttribute="leading" secondItem="z30-VZ-8h3" secondAttribute="trailing" constant="10" id="ZCX-vU-yAg"/>
<constraint firstAttribute="trailing" secondItem="cko-1v-wDx" secondAttribute="trailing" id="bMz-0j-PnH"/>
<constraint firstItem="63p-dI-yTa" firstAttribute="leading" secondItem="YtM-Db-ygP" secondAttribute="leading" id="gk1-Zr-MIl"/>
<constraint firstItem="PZ3-qH-3XH" firstAttribute="leading" secondItem="YtM-Db-ygP" secondAttribute="leading" id="hE4-2m-iZk"/>
<constraint firstItem="z30-VZ-8h3" firstAttribute="top" secondItem="63p-dI-yTa" secondAttribute="bottom" constant="2" id="hfr-Gi-omT"/>
<constraint firstAttribute="bottom" secondItem="PZ3-qH-3XH" secondAttribute="bottom" id="xMs-dh-ybb"/>
<constraint firstItem="mO2-Xp-IVu" firstAttribute="leading" secondItem="YtM-Db-ygP" secondAttribute="leading" id="hkf-Ek-pmr"/>
<constraint firstItem="cko-1v-wDx" firstAttribute="leading" secondItem="63p-dI-yTa" secondAttribute="trailing" constant="10" id="m2R-vr-DCQ"/>
<constraint firstAttribute="bottom" secondItem="cko-1v-wDx" secondAttribute="bottom" id="pND-ei-iWF"/>
</constraints>
</view>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="hM2-8T-4vX">
<rect key="frame" x="164" y="17" width="84" height="84"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="84" id="6to-Dv-ukR"/>
<constraint firstAttribute="height" constant="84" id="QjU-rO-Uqx"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="YtM-Db-ygP" secondAttribute="bottom" constant="11" id="6ul-bC-Jpj"/>
<constraint firstItem="YtM-Db-ygP" firstAttribute="leading" secondItem="fZ6-8K-DXr" secondAttribute="leading" constant="16" id="C7J-bI-8ap"/>
<constraint firstItem="hM2-8T-4vX" firstAttribute="top" secondItem="fZ6-8K-DXr" secondAttribute="top" constant="17" id="HBF-J2-ed0"/>
<constraint firstItem="hM2-8T-4vX" firstAttribute="leading" secondItem="YtM-Db-ygP" secondAttribute="trailing" constant="18" id="WML-nR-cLh"/>
<constraint firstItem="YtM-Db-ygP" firstAttribute="top" secondItem="fZ6-8K-DXr" secondAttribute="top" constant="17" id="f0H-m3-OAP"/>
<constraint firstAttribute="trailing" secondItem="hM2-8T-4vX" secondAttribute="trailing" constant="28" id="jKa-nW-g41"/>
<constraint firstAttribute="height" constant="121" id="ptz-uq-5rq"/>
<constraint firstAttribute="bottom" secondItem="YtM-Db-ygP" secondAttribute="bottom" constant="17" id="6ul-bC-Jpj"/>
<constraint firstItem="YtM-Db-ygP" firstAttribute="top" secondItem="Fcn-J9-gqq" secondAttribute="bottom" constant="16" id="8dr-sO-7qI"/>
<constraint firstItem="YtM-Db-ygP" firstAttribute="leading" secondItem="fZ6-8K-DXr" secondAttribute="leading" constant="17" id="C7J-bI-8ap"/>
<constraint firstItem="Fcn-J9-gqq" firstAttribute="top" secondItem="fZ6-8K-DXr" secondAttribute="top" constant="10" id="KVH-GO-BRe"/>
<constraint firstItem="Fcn-J9-gqq" firstAttribute="leading" secondItem="fZ6-8K-DXr" secondAttribute="leading" constant="10" id="Oph-8j-Guf"/>
<constraint firstAttribute="trailing" secondItem="9ju-6P-k6F" secondAttribute="trailing" constant="10" id="aON-Fo-H1J"/>
<constraint firstAttribute="trailing" secondItem="YtM-Db-ygP" secondAttribute="trailing" constant="7" id="ghj-41-twp"/>
<constraint firstItem="9ju-6P-k6F" firstAttribute="top" secondItem="fZ6-8K-DXr" secondAttribute="top" constant="10" id="uXH-9L-517"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="fZ6-8K-DXr" firstAttribute="leading" secondItem="x0X-za-HZ9" secondAttribute="leading" id="DKa-9V-lma"/>
<constraint firstAttribute="trailing" secondItem="8Ht-7Z-jiW" secondAttribute="trailing" id="LK1-Cz-JUh"/>
<constraint firstItem="8Ht-7Z-jiW" firstAttribute="top" secondItem="x0X-za-HZ9" secondAttribute="top" id="P9v-fu-Mhs"/>
<constraint firstAttribute="height" constant="292" id="lA6-op-vsG"/>
<constraint firstItem="fZ6-8K-DXr" firstAttribute="top" secondItem="x0X-za-HZ9" secondAttribute="top" id="cdY-T8-x47"/>
<constraint firstAttribute="height" constant="175" id="lA6-op-vsG"/>
<constraint firstAttribute="trailing" secondItem="fZ6-8K-DXr" secondAttribute="trailing" id="lAU-n1-MKy"/>
<constraint firstItem="8Ht-7Z-jiW" firstAttribute="leading" secondItem="x0X-za-HZ9" secondAttribute="leading" id="sK9-Tw-Yqn"/>
<constraint firstAttribute="bottom" secondItem="fZ6-8K-DXr" secondAttribute="bottom" id="u4z-JD-qby"/>
<constraint firstItem="fZ6-8K-DXr" firstAttribute="top" secondItem="8Ht-7Z-jiW" secondAttribute="bottom" id="v5X-nL-hKm"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="x0X-za-HZ9" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="22" id="SzO-Fk-ZCB"/>
<constraint firstItem="x0X-za-HZ9" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="18" id="SzO-Fk-ZCB"/>
<constraint firstItem="x0X-za-HZ9" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="uQN-BA-o6w"/>
<constraint firstAttribute="trailing" secondItem="x0X-za-HZ9" secondAttribute="trailing" constant="22" id="vi4-dI-lx3"/>
<constraint firstAttribute="bottom" secondItem="x0X-za-HZ9" secondAttribute="bottom" constant="19" id="zsL-aX-JRL"/>
<constraint firstAttribute="trailing" secondItem="x0X-za-HZ9" secondAttribute="trailing" constant="18" id="vi4-dI-lx3"/>
<constraint firstAttribute="bottom" secondItem="x0X-za-HZ9" secondAttribute="bottom" constant="16" id="zsL-aX-JRL"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<connections>
<outlet property="bannerImage" destination="09g-Nj-HG4" id="1Ux-ZI-rVQ"/>
<outlet property="discountLabel" destination="XeI-PB-wG7" id="Kyy-aE-GgR"/>
<outlet property="discountView" destination="dnZ-fa-M3o" id="fht-MW-ToM"/>
<outlet property="expirationLabel" destination="PZ3-qH-3XH" id="vIb-60-EVp"/>
<outlet property="favoriteImage" destination="T91-Ra-dmT" id="leZ-Tz-zo8"/>
<outlet property="arrowImage" destination="ZRF-CC-IKd" id="9Wh-O0-Lzr"/>
<outlet property="arrowView" destination="cko-1v-wDx" id="mMW-Dp-q6K"/>
<outlet property="expirationImage" destination="wkd-wh-r1w" id="5ng-6x-HtH"/>
<outlet property="expirationLabel" destination="ZgP-Qt-8og" id="bNv-Rl-m7b"/>
<outlet property="expirationView" destination="9ju-6P-k6F" id="YiF-Z5-Q6s"/>
<outlet property="logoImage" destination="hM2-8T-4vX" id="Zqv-yp-lrD"/>
<outlet property="logoImageView" destination="Fcn-J9-gqq" id="mAE-fP-e6I"/>
<outlet property="merchantNameLabel" destination="mO2-Xp-IVu" id="Don-n2-JqF"/>
<outlet property="parentView" destination="x0X-za-HZ9" id="OE0-tT-IPd"/>
<outlet property="subtitleLabel" destination="z30-VZ-8h3" id="s40-MP-4Jn"/>
<outlet property="titleLabel" destination="63p-dI-yTa" id="YOe-I2-Cly"/>
......
......@@ -96,7 +96,7 @@ public class CouponSetItemModel {
/// Try multiple date formats and return the first successful parse
/// - Parameter dateString: The date string to parse
/// - Returns: Parsed Date or nil if no format matched
private static func parseDate(_ dateString: String) -> Date? {
static func parseDate(_ dateString: String) -> Date? {
let formatter = DateFormatter()
for format in supportedDateFormats {
formatter.dateFormat = format
......@@ -411,7 +411,8 @@ public class CouponItemModel {
public let couponset_uuid: String?
public let name: String?
public let image: String?
public let expiration: String?
public let expiration: String? // raw string from API e.g. "2026-06-30 11:59:00"
public let expiration_formatted: String? // pre-formatted "dd/MM/yyyy" for display
public let created: String?
public let description: String?
public let discount: String?
......@@ -495,15 +496,16 @@ public class CouponItemModel {
}
// <==
let expirationString = dictionary["expiration"] as? String? ?? ""
let expirationString = dictionary["expiration"] as? String ?? ""
self.expiration = expirationString
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
if let date = dateFormatter.date(from: expirationString ?? "") {
if let date = dateFormatter.date(from: expirationString) {
dateFormatter.dateFormat = "dd/MM/yyyy"
let resultString = dateFormatter.string(from: date)
self.expiration = resultString
self.expiration_formatted = dateFormatter.string(from: date)
} else {
self.expiration = ""
self.expiration_formatted = ""
}
// Extract created date: try changes_dates.created first (universal coupons), then top-level created
......@@ -558,6 +560,26 @@ public class CouponItemModel {
public func setCouponSetData(_ couponSet: CouponSetItemModel) {
self.couponset_data = couponSet
}
/// Returns the expiration as a Date object for date comparisons (e.g. days-left calculation)
public var expirationDate: Date? {
guard let raw = self.expiration, !raw.isEmpty else { return nil }
return CouponSetItemModel.parseDate(raw)
}
/// Format expiration date with a custom output format.
/// Uses the same multi-format parser as CouponSetItemModel.
/// - Parameter format: DateFormatter format string (e.g. "MMMM d, yyyy", "dd/MM/yyyy")
/// - Returns: Formatted date string, or empty string if expiration is absent or unparseable
public func formattedExpiration(format: String) -> String {
guard let raw = self.expiration, !raw.isEmpty else { return "" }
if let date = CouponSetItemModel.parseDate(raw) {
let formatter = DateFormatter()
formatter.dateFormat = format
return formatter.string(from: date)
}
return ""
}
}
public class RedeemedSMHistoryModel {
......
......@@ -383,7 +383,7 @@ extension MyCouponsViewController: UITableViewDelegate, UITableViewDataSource {
}
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if (indexPath.section <= 3) {
if (indexPath.section <= 1) {
// Do nothing
} else {
if let items = self.filteredOffersSection?.items,
......