Manos Chorianopoulos

CategoryOffersViewController part1

......@@ -57,7 +57,11 @@ let package = Package(
.process("cells/MyRewardsOfferCollectionViewCell/MyRewardsOfferCollectionViewCell.xib"),
.process("cells/MyRewardsBannerOffersScrollTableViewCell/MyRewardsBannerOffersScrollTableViewCell.xib"),
.process("screens/MyCouponsViewController/MyCouponsViewController.xib"),
.process("cells/MyCouponsHeaderTableViewCell/MyCouponsHeaderTableViewCell.xib")
.process("cells/MyCouponsHeaderTableViewCell/MyCouponsHeaderTableViewCell.xib"),
.process("cells/CategoryOfferCollectionViewCell/CategoryOfferCollectionViewCell.xib"),
.process("cells/CategoryOffersHeaderTableViewCell/CategoryOffersHeaderTableViewCell.xib"),
.process("cells/CategoryOffersGridTableViewCell/CategoryOffersGridTableViewCell.xib"),
.process("screens/CategoryOffersViewController/CategoryOffersViewController.xib")
]
),
]
......
......@@ -77,6 +77,14 @@
626AF6DE2F699081008BCA08 /* MapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 626AF6DC2F699081008BCA08 /* MapViewController.swift */; };
626AF6DF2F699081008BCA08 /* MapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 626AF6DD2F699081008BCA08 /* MapViewController.xib */; };
626DC8012F6ACA3B00CFC8C2 /* CarouselItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 626DC8002F6ACA3B00CFC8C2 /* CarouselItemModel.swift */; };
627B9C752F6C3EB000A2456F /* CategoryOffersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 627B9C732F6C3EB000A2456F /* CategoryOffersViewController.swift */; };
627B9C762F6C3EB000A2456F /* CategoryOffersViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 627B9C742F6C3EB000A2456F /* CategoryOffersViewController.xib */; };
627B9C7A2F6C438500A2456F /* CategoryOfferCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 627B9C782F6C438500A2456F /* CategoryOfferCollectionViewCell.swift */; };
627B9C7B2F6C438500A2456F /* CategoryOfferCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 627B9C792F6C438500A2456F /* CategoryOfferCollectionViewCell.xib */; };
627B9C7F2F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 627B9C7D2F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.swift */; };
627B9C802F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 627B9C7E2F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.xib */; };
627B9C842F6C492F00A2456F /* CategoryOffersGridTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 627B9C822F6C492F00A2456F /* CategoryOffersGridTableViewCell.swift */; };
627B9C852F6C492F00A2456F /* CategoryOffersGridTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 627B9C832F6C492F00A2456F /* CategoryOffersGridTableViewCell.xib */; };
62A0A6D32F67FEDC00508534 /* MyCouponsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A0A6D12F67FEDC00508534 /* MyCouponsViewController.swift */; };
62A0A6D42F67FEDC00508534 /* MyCouponsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 62A0A6D22F67FEDC00508534 /* MyCouponsViewController.xib */; };
62A0A6D82F680C6A00508534 /* MyCouponsHeaderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A0A6D62F680C6A00508534 /* MyCouponsHeaderTableViewCell.swift */; };
......@@ -162,6 +170,14 @@
626AF6DC2F699081008BCA08 /* MapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewController.swift; sourceTree = "<group>"; };
626AF6DD2F699081008BCA08 /* MapViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MapViewController.xib; sourceTree = "<group>"; };
626DC8002F6ACA3B00CFC8C2 /* CarouselItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItemModel.swift; sourceTree = "<group>"; };
627B9C732F6C3EB000A2456F /* CategoryOffersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryOffersViewController.swift; sourceTree = "<group>"; };
627B9C742F6C3EB000A2456F /* CategoryOffersViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CategoryOffersViewController.xib; sourceTree = "<group>"; };
627B9C782F6C438500A2456F /* CategoryOfferCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryOfferCollectionViewCell.swift; sourceTree = "<group>"; };
627B9C792F6C438500A2456F /* CategoryOfferCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CategoryOfferCollectionViewCell.xib; sourceTree = "<group>"; };
627B9C7D2F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryOffersHeaderTableViewCell.swift; sourceTree = "<group>"; };
627B9C7E2F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CategoryOffersHeaderTableViewCell.xib; sourceTree = "<group>"; };
627B9C822F6C492F00A2456F /* CategoryOffersGridTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryOffersGridTableViewCell.swift; sourceTree = "<group>"; };
627B9C832F6C492F00A2456F /* CategoryOffersGridTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CategoryOffersGridTableViewCell.xib; sourceTree = "<group>"; };
62A0A6D12F67FEDC00508534 /* MyCouponsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyCouponsViewController.swift; sourceTree = "<group>"; };
62A0A6D22F67FEDC00508534 /* MyCouponsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyCouponsViewController.xib; sourceTree = "<group>"; };
62A0A6D62F680C6A00508534 /* MyCouponsHeaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyCouponsHeaderTableViewCell.swift; sourceTree = "<group>"; };
......@@ -340,6 +356,7 @@
1EA8E5B42DDF315600CD3418 /* screens */ = {
isa = PBXGroup;
children = (
627B9C722F6C3E9800A2456F /* CategoryOffersViewController */,
626AF6D92F698F96008BCA08 /* MapViewController */,
622DA0AB2F51CA9100308AB8 /* CouponsetViewController */,
1EBE45642E02DDF90055A0D4 /* CampaignViewController */,
......@@ -354,6 +371,9 @@
1EA8E5BC2DDF34FB00CD3418 /* cells */ = {
isa = PBXGroup;
children = (
627B9C812F6C491900A2456F /* CategoryOffersGridTableViewCell */,
627B9C7C2F6C48CE00A2456F /* CategoryOffersHeaderTableViewCell */,
627B9C772F6C434F00A2456F /* CategoryOfferCollectionViewCell */,
62A0A6D52F680C1E00508534 /* MyCouponsHeaderTableViewCell */,
1EDBAF122DE844C500911E79 /* ProfileFilterCollectionViewCell */,
1EDBAF012DE8439000911E79 /* ProfileCouponTableViewCell */,
......@@ -469,6 +489,42 @@
path = MapViewController;
sourceTree = "<group>";
};
627B9C722F6C3E9800A2456F /* CategoryOffersViewController */ = {
isa = PBXGroup;
children = (
627B9C732F6C3EB000A2456F /* CategoryOffersViewController.swift */,
627B9C742F6C3EB000A2456F /* CategoryOffersViewController.xib */,
);
path = CategoryOffersViewController;
sourceTree = "<group>";
};
627B9C772F6C434F00A2456F /* CategoryOfferCollectionViewCell */ = {
isa = PBXGroup;
children = (
627B9C782F6C438500A2456F /* CategoryOfferCollectionViewCell.swift */,
627B9C792F6C438500A2456F /* CategoryOfferCollectionViewCell.xib */,
);
path = CategoryOfferCollectionViewCell;
sourceTree = "<group>";
};
627B9C7C2F6C48CE00A2456F /* CategoryOffersHeaderTableViewCell */ = {
isa = PBXGroup;
children = (
627B9C7D2F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.swift */,
627B9C7E2F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.xib */,
);
path = CategoryOffersHeaderTableViewCell;
sourceTree = "<group>";
};
627B9C812F6C491900A2456F /* CategoryOffersGridTableViewCell */ = {
isa = PBXGroup;
children = (
627B9C822F6C492F00A2456F /* CategoryOffersGridTableViewCell.swift */,
627B9C832F6C492F00A2456F /* CategoryOffersGridTableViewCell.xib */,
);
path = CategoryOffersGridTableViewCell;
sourceTree = "<group>";
};
62A0A6D02F67FE8100508534 /* MyCouponsViewController */ = {
isa = PBXGroup;
children = (
......@@ -655,9 +711,12 @@
1EDBAF082DE843FB00911E79 /* ProfileCouponFiltersTableViewCell.xib in Resources */,
1EBE45682E02DE9A0055A0D4 /* CampaignViewController.xib in Resources */,
1EDBAF042DE843CA00911E79 /* ProfileCouponTableViewCell.xib in Resources */,
627B9C762F6C3EB000A2456F /* CategoryOffersViewController.xib in Resources */,
1EDBAF0C2DE8441000911E79 /* ProfileQuestionnaireTableViewCell.xib in Resources */,
E6A77A38282BC3530045BBA8 /* Media.xcassets in Resources */,
627B9C852F6C492F00A2456F /* CategoryOffersGridTableViewCell.xib in Resources */,
1E116F682DE845B1009AE791 /* ProfileFilterCollectionViewCell.xib in Resources */,
627B9C7B2F6C438500A2456F /* CategoryOfferCollectionViewCell.xib in Resources */,
1EB4F4252DE09AAC00D934C0 /* MyRewardsBannerOffersScrollTableViewCell.xib in Resources */,
62A0A6D92F680C6A00508534 /* MyCouponsHeaderTableViewCell.xib in Resources */,
1EA8E5C02DDF427A00CD3418 /* PingLCG-Bold.otf in Resources */,
......@@ -672,6 +731,7 @@
1EDBAF102DE8443B00911E79 /* ProfileHeaderTableViewCell.xib in Resources */,
1E917CDB2DDF68C7002221D8 /* CouponViewController.xib in Resources */,
1E917CE02DDF6909002221D8 /* ProfileViewController.xib in Resources */,
627B9C802F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -723,6 +783,7 @@
1E089DFC2DF87C39007459F1 /* Merchant.swift in Sources */,
1E0E724B2E0C3B6C00BC926F /* TokenRefreshManager.swift in Sources */,
1E089DFD2DF87C39007459F1 /* Campaign.swift in Sources */,
627B9C842F6C492F00A2456F /* CategoryOffersGridTableViewCell.swift in Sources */,
1E089E062DF87CED007459F1 /* Endpoints.swift in Sources */,
1E089E072DF87CED007459F1 /* NetworkService.swift in Sources */,
1EBE45672E02DE9A0055A0D4 /* CampaignViewController.swift in Sources */,
......@@ -742,6 +803,7 @@
E6A77955282933E70045BBA8 /* ViewControllerExtensions.swift in Sources */,
A07936762885E9CC00064122 /* UIColorExtensions.swift in Sources */,
1EB4F42C2DE0A0AF00D934C0 /* MyRewardsOffersScrollTableViewCell.swift in Sources */,
627B9C752F6C3EB000A2456F /* CategoryOffersViewController.swift in Sources */,
62A0A6D32F67FEDC00508534 /* MyCouponsViewController.swift in Sources */,
1E089E022DF87CCF007459F1 /* WarplySDK.swift in Sources */,
1E0E723B2E0C3AE400BC926F /* DatabaseConfiguration.swift in Sources */,
......@@ -760,6 +822,8 @@
626AF6DE2F699081008BCA08 /* MapViewController.swift in Sources */,
1EDBAF112DE8443B00911E79 /* ProfileHeaderTableViewCell.swift in Sources */,
1EDBAF052DE843CA00911E79 /* ProfileCouponTableViewCell.swift in Sources */,
627B9C7A2F6C438500A2456F /* CategoryOfferCollectionViewCell.swift in Sources */,
627B9C7F2F6C48E800A2456F /* CategoryOffersHeaderTableViewCell.swift in Sources */,
626AF6DB2F698FF1008BCA08 /* MerchantAnnotation.swift in Sources */,
1EB4F4262DE09AAC00D934C0 /* MyRewardsBannerOffersScrollTableViewCell.swift in Sources */,
);
......
//
// CategoryOfferCollectionViewCell.swift
// SwiftWarplyFramework
//
// Created by Manos Chorianopoulos on 19/3/26.
//
import UIKit
@objc(CategoryOfferCollectionViewCell)
public class CategoryOfferCollectionViewCell: UICollectionViewCell {
public override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
<?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">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12042"/>
<capability name="Safe area layout guides" minToolsVersion="9.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"/>
<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"/>
</view>
<viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
</collectionViewCell>
</objects>
</document>
//
// CategoryOffersGridTableViewCell.swift
// SwiftWarplyFramework
//
// Created by Manos Chorianopoulos on 19/3/26.
//
import UIKit
@objc(CategoryOffersGridTableViewCell)
public class CategoryOffersGridTableViewCell: UITableViewCell {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!
var data: SectionModel?
weak var parentViewController: UIViewController?
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
XIBLoader.registerCollectionViewCell(
collectionView,
cellClass: UICollectionViewCell.self,
nibName: "CategoryOfferCollectionViewCell",
identifier: "CategoryOfferCollectionViewCell"
)
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.minimumInteritemSpacing = 16
layout.minimumLineSpacing = 16
layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
}
}
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
}
}
extension CategoryOffersGridTableViewCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
public func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.data?.itemCount ?? 0
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryOfferCollectionViewCell", for: indexPath) as! CategoryOfferCollectionViewCell
guard let data = self.data,
let items = data.items,
indexPath.row < items.count else {
return cell
}
switch data.itemType {
case .couponSets:
if let couponSet = items[indexPath.row] as? CouponSetItemModel {
cell.configureCell(data: couponSet)
}
default:
if let offer = items[indexPath.row] as? OfferModel {
cell.configureCell(data: offer)
}
}
return cell
}
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let data = self.data,
let items = data.items,
indexPath.row < items.count else {
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 {
vc.couponset = couponSet
self.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)
}
}
}
}
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
// Adjust height as needed based on design (aspect ratio or fixed)
let itemHeight = itemWidth * 1.3 // Approximation from screenshot
return CGSize(width: itemWidth, height: itemHeight)
}
}
<?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="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"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="KGk-i7-Jjw" customClass="CategoryOffersGridTableViewCell" customModule="SwiftWarplyFramework" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="200"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="320" height="200"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="6q1-8v-H6d">
<rect key="frame" x="0.0" y="0.0" width="320" height="200"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="200" id="E2S-dE-z3n"/>
</constraints>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="g5b-eS-1Jq">
<size key="itemSize" width="128" height="128"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
</collectionView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="6q1-8v-H6d" secondAttribute="bottom" id="D01-9c-29T"/>
<constraint firstAttribute="trailing" secondItem="6q1-8v-H6d" secondAttribute="trailing" id="D3B-e1-2jZ"/>
<constraint firstItem="6q1-8v-H6d" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="O63-T2-B2y"/>
<constraint firstItem="6q1-8v-H6d" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="YjY-W1-T3M"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="collectionView" destination="6q1-8v-H6d" id="N8a-1a-1yO"/>
<outlet property="collectionViewHeightConstraint" destination="E2S-dE-z3n" id="A8b-Zc-3rZ"/>
</connections>
<point key="canvasLocation" x="141" y="20"/>
</tableViewCell>
</objects>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
//
// CategoryOffersHeaderTableViewCell.swift
// SwiftWarplyFramework
//
// Created by Manos Chorianopoulos on 19/3/26.
//
import UIKit
@objc(CategoryOffersHeaderTableViewCell)
public class CategoryOffersHeaderTableViewCell: UITableViewCell {
@IBOutlet weak var headerLabel: UILabel!
@IBOutlet weak var filtersView: UIView!
@IBOutlet weak var filtersLabel: UILabel!
@IBOutlet weak var filtersImage: UIImageView!
@IBOutlet weak var mapView: UIView!
@IBOutlet weak var mapImage: UIImageView!
public override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.headerLabel.text = ""
self.headerLabel.font = UIFont(name: "PingLCG-Bold", size: 24)
self.headerLabel.textColor = UIColor(rgb: 0x0D1B29)
self.headerLabel.frame.size.width = self.headerLabel.intrinsicContentSize.width
self.headerLabel.frame.size.height = self.headerLabel.intrinsicContentSize.height
self.filtersView.backgroundColor = UIColor(rgb: 0xF1F2F4)
self.filtersView.layer.cornerRadius = 16 // Assuming height is 32 or similar based on standard chip design
self.filtersView.layer.masksToBounds = true
self.filtersLabel.text = "Αναζήτηση"
self.filtersLabel.font = UIFont(name: "PingLCG-Regular", size: 16)
self.filtersLabel.textColor = UIColor(rgb: 0x000F1E)
self.filtersLabel.frame.size.width = self.filtersLabel.intrinsicContentSize.width
self.filtersLabel.frame.size.height = self.filtersLabel.intrinsicContentSize.height
self.filtersImage.image = UIImage(named: "filter", in: MyEmptyClass.resourceBundle(), compatibleWith: nil)
if mapView != nil {
self.mapView.backgroundColor = UIColor(rgb: 0xF1F2F4)
self.mapView.layer.cornerRadius = 22 // Assuming height is 44
self.mapView.layer.masksToBounds = true
}
if mapImage != nil {
self.mapImage.image = UIImage(named: "ic_map", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
}
}
public override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
<?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="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"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" rowHeight="100" id="KGk-i7-Jjw" customClass="CategoryOffersHeaderTableViewCell" customModule="SwiftWarplyFramework" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="100"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="375" height="100"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZCw-Ll-zwM" userLabel="HeaderView">
<rect key="frame" x="0.0" y="0.0" width="375" height="100"/>
<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="cBC-6g-plR" userLabel="HeaderLabel">
<rect key="frame" x="18" y="10" width="339" height="29"/>
<fontDescription key="fontDescription" type="system" pointSize="24"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uCx-Us-JUI" userLabel="FiltersView">
<rect key="frame" x="18" y="49" width="125" height="32"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Αναζήτηση" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sDK-OF-lXa" userLabel="FiltersLabel">
<rect key="frame" x="12" y="5.6666666666666643" width="79" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3Xf-bL-CdH" userLabel="Filters Image View">
<rect key="frame" x="97" y="8" width="16" height="16"/>
<constraints>
<constraint firstAttribute="width" constant="16" id="YhY-z1-ejZ"/>
<constraint firstAttribute="height" constant="16" id="kYH-vQ-nxs"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="sDK-OF-lXa" firstAttribute="leading" secondItem="uCx-Us-JUI" secondAttribute="leading" constant="12" id="1bJ-2D-9G2"/>
<constraint firstItem="3Xf-bL-CdH" firstAttribute="centerY" secondItem="uCx-Us-JUI" secondAttribute="centerY" id="5aO-bF-8t8"/>
<constraint firstAttribute="height" constant="32" id="Pqa-c3-bwe"/>
<constraint firstAttribute="trailing" secondItem="3Xf-bL-CdH" secondAttribute="trailing" constant="12" id="a7L-Ll-tLr"/>
<constraint firstItem="sDK-OF-lXa" firstAttribute="centerY" secondItem="uCx-Us-JUI" secondAttribute="centerY" id="maL-1h-ry9"/>
<constraint firstItem="3Xf-bL-CdH" firstAttribute="leading" secondItem="sDK-OF-lXa" secondAttribute="trailing" constant="6" id="tLf-zt-nxJ"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="map-bg-view" userLabel="MapView">
<rect key="frame" x="313" y="43" width="44" height="44"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="map-icon-img" userLabel="Map Image View">
<rect key="frame" x="12" y="12" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="20" id="M1X-bS-b6A"/>
<constraint firstAttribute="height" constant="20" id="M1X-bS-b6B"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="map-icon-img" firstAttribute="centerX" secondItem="map-bg-view" secondAttribute="centerX" id="M1X-bS-b6C"/>
<constraint firstItem="map-icon-img" firstAttribute="centerY" secondItem="map-bg-view" secondAttribute="centerY" id="M1X-bS-b6D"/>
<constraint firstAttribute="width" constant="44" id="M1X-bS-b6E"/>
<constraint firstAttribute="height" constant="44" id="M1X-bS-b6F"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="uCx-Us-JUI" firstAttribute="leading" secondItem="ZCw-Ll-zwM" secondAttribute="leading" constant="18" id="6Ex-bt-5yV"/>
<constraint firstAttribute="trailing" secondItem="cBC-6g-plR" secondAttribute="trailing" constant="18" id="Cqb-tb-tvv"/>
<constraint firstItem="uCx-Us-JUI" firstAttribute="top" secondItem="cBC-6g-plR" secondAttribute="bottom" constant="10" id="GXj-Xe-Vsr"/>
<constraint firstAttribute="bottom" secondItem="uCx-Us-JUI" secondAttribute="bottom" constant="19" id="gNr-Kw-YvL"/>
<constraint firstItem="cBC-6g-plR" firstAttribute="top" secondItem="ZCw-Ll-zwM" secondAttribute="top" constant="10" id="nwy-UX-mnC"/>
<constraint firstItem="cBC-6g-plR" firstAttribute="leading" secondItem="ZCw-Ll-zwM" secondAttribute="leading" constant="18" id="wiM-Yd-Hmd"/>
<constraint firstAttribute="trailing" secondItem="map-bg-view" secondAttribute="trailing" constant="18" id="M1X-bS-b6G"/>
<constraint firstItem="map-bg-view" firstAttribute="centerY" secondItem="uCx-Us-JUI" secondAttribute="centerY" id="M1X-bS-b6H"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="ZCw-Ll-zwM" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="cRF-Vh-enF"/>
<constraint firstAttribute="bottom" secondItem="ZCw-Ll-zwM" secondAttribute="bottom" id="gEL-mg-txR"/>
<constraint firstItem="ZCw-Ll-zwM" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="rsN-TO-MVS"/>
<constraint firstAttribute="trailing" secondItem="ZCw-Ll-zwM" secondAttribute="trailing" id="slO-cF-esX"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="filtersImage" destination="3Xf-bL-CdH" id="3Xf-bL-CdI"/>
<outlet property="filtersLabel" destination="sDK-OF-lXa" id="sDK-OF-lXb"/>
<outlet property="filtersView" destination="uCx-Us-JUI" id="uCx-Us-JUJ"/>
<outlet property="headerLabel" destination="cBC-6g-plR" id="cBC-6g-plS"/>
<outlet property="mapImage" destination="map-icon-img" id="map-icon-img-1"/>
<outlet property="mapView" destination="map-bg-view" id="map-bg-view-1"/>
</connections>
<point key="canvasLocation" x="141.22137404580153" y="154.22535211267606"/>
</tableViewCell>
</objects>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
//
// CategoryOffersViewController.swift
// SwiftWarplyFramework
//
// Created by Manos Chorianopoulos on 19/3/26.
//
import UIKit
@objc public class CategoryOffersViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
public var sectionData: SectionModel?
public override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(false, animated: false)
setBackButton()
setupTableView()
}
private func setupTableView() {
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
tableView.backgroundColor = .white
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
}
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
}
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryOffersGridTableViewCell", for: indexPath) as! CategoryOffersGridTableViewCell
cell.configureCell(with: sectionData, parentViewController: self)
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
}
}
}
<?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="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" customClass="CategoryOffersViewController" customModule="SwiftWarplyFramework" customModuleProvider="target">
<connections>
<outlet property="tableView" destination="xJ1-8b-ZQa" id="zFv-3o-xR8"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="xJ1-8b-ZQa">
<rect key="frame" x="0.0" y="59" width="393" height="759"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</tableView>
</subviews>
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="xJ1-8b-ZQa" secondAttribute="bottom" id="D5R-hF-Lz4"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="xJ1-8b-ZQa" secondAttribute="trailing" id="LhI-M4-0eB"/>
<constraint firstItem="xJ1-8b-ZQa" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" id="O6f-Kk-Ufe"/>
<constraint firstItem="xJ1-8b-ZQa" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="aT8-Zg-Kk4"/>
</constraints>
<point key="canvasLocation" x="65" y="154"/>
</view>
</objects>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>