Manos Chorianopoulos

MyRewards dynamic profile info

...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
7 <key>Pods-SwiftWarplyFramework.xcscheme_^#shared#^_</key> 7 <key>Pods-SwiftWarplyFramework.xcscheme_^#shared#^_</key>
8 <dict> 8 <dict>
9 <key>orderHint</key> 9 <key>orderHint</key>
10 - <integer>0</integer> 10 + <integer>1</integer>
11 </dict> 11 </dict>
12 </dict> 12 </dict>
13 </dict> 13 </dict>
......
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
40 1E4C4CFB2DE6014500279AAD /* CopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C4CFA2DE6014500279AAD /* CopyableLabel.swift */; }; 40 1E4C4CFB2DE6014500279AAD /* CopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C4CFA2DE6014500279AAD /* CopyableLabel.swift */; };
41 1E64E1832DE48E0600543217 /* MyRewardsOfferCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E64E1822DE48E0600543217 /* MyRewardsOfferCollectionViewCell.xib */; }; 41 1E64E1832DE48E0600543217 /* MyRewardsOfferCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E64E1822DE48E0600543217 /* MyRewardsOfferCollectionViewCell.xib */; };
42 1E64E1842DE48E0600543217 /* MyRewardsOfferCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E64E1812DE48E0600543217 /* MyRewardsOfferCollectionViewCell.swift */; }; 42 1E64E1842DE48E0600543217 /* MyRewardsOfferCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E64E1812DE48E0600543217 /* MyRewardsOfferCollectionViewCell.swift */; };
43 + 1E66E4972E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E66E4962E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.xib */; };
44 + 1E66E4982E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E66E4952E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.swift */; };
43 1E917CD62DDF64B2002221D8 /* MyRewardsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E917CD52DDF64B2002221D8 /* MyRewardsViewController.xib */; }; 45 1E917CD62DDF64B2002221D8 /* MyRewardsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E917CD52DDF64B2002221D8 /* MyRewardsViewController.xib */; };
44 1E917CD72DDF64B2002221D8 /* MyRewardsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E917CD42DDF64B2002221D8 /* MyRewardsViewController.swift */; }; 46 1E917CD72DDF64B2002221D8 /* MyRewardsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E917CD42DDF64B2002221D8 /* MyRewardsViewController.swift */; };
45 1E917CDB2DDF68C7002221D8 /* CouponViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E917CDA2DDF68C7002221D8 /* CouponViewController.xib */; }; 47 1E917CDB2DDF68C7002221D8 /* CouponViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1E917CDA2DDF68C7002221D8 /* CouponViewController.xib */; };
...@@ -116,6 +118,8 @@ ...@@ -116,6 +118,8 @@
116 1E4C4CFA2DE6014500279AAD /* CopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLabel.swift; sourceTree = "<group>"; }; 118 1E4C4CFA2DE6014500279AAD /* CopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLabel.swift; sourceTree = "<group>"; };
117 1E64E1812DE48E0600543217 /* MyRewardsOfferCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyRewardsOfferCollectionViewCell.swift; sourceTree = "<group>"; }; 119 1E64E1812DE48E0600543217 /* MyRewardsOfferCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyRewardsOfferCollectionViewCell.swift; sourceTree = "<group>"; };
118 1E64E1822DE48E0600543217 /* MyRewardsOfferCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyRewardsOfferCollectionViewCell.xib; sourceTree = "<group>"; }; 120 1E64E1822DE48E0600543217 /* MyRewardsOfferCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyRewardsOfferCollectionViewCell.xib; sourceTree = "<group>"; };
121 + 1E66E4952E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyRewardsProfileInfoTableViewCell.swift; sourceTree = "<group>"; };
122 + 1E66E4962E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyRewardsProfileInfoTableViewCell.xib; sourceTree = "<group>"; };
119 1E917CD42DDF64B2002221D8 /* MyRewardsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyRewardsViewController.swift; sourceTree = "<group>"; }; 123 1E917CD42DDF64B2002221D8 /* MyRewardsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyRewardsViewController.swift; sourceTree = "<group>"; };
120 1E917CD52DDF64B2002221D8 /* MyRewardsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyRewardsViewController.xib; sourceTree = "<group>"; }; 124 1E917CD52DDF64B2002221D8 /* MyRewardsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyRewardsViewController.xib; sourceTree = "<group>"; };
121 1E917CD92DDF68C7002221D8 /* CouponViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CouponViewController.swift; sourceTree = "<group>"; }; 125 1E917CD92DDF68C7002221D8 /* CouponViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CouponViewController.swift; sourceTree = "<group>"; };
...@@ -276,6 +280,15 @@ ...@@ -276,6 +280,15 @@
276 path = MyRewardsOfferCollectionViewCell; 280 path = MyRewardsOfferCollectionViewCell;
277 sourceTree = "<group>"; 281 sourceTree = "<group>";
278 }; 282 };
283 + 1E66E4942E30F8C600BCEF9D /* MyRewardsProfileInfoTableViewCell */ = {
284 + isa = PBXGroup;
285 + children = (
286 + 1E66E4952E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.swift */,
287 + 1E66E4962E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.xib */,
288 + );
289 + path = MyRewardsProfileInfoTableViewCell;
290 + sourceTree = "<group>";
291 + };
279 1E917CD32DDF6472002221D8 /* MyRewardsViewController */ = { 292 1E917CD32DDF6472002221D8 /* MyRewardsViewController */ = {
280 isa = PBXGroup; 293 isa = PBXGroup;
281 children = ( 294 children = (
...@@ -326,6 +339,7 @@ ...@@ -326,6 +339,7 @@
326 1ED41E492DE0C21800836ABA /* MyRewardsBannerOfferCollectionViewCell */, 339 1ED41E492DE0C21800836ABA /* MyRewardsBannerOfferCollectionViewCell */,
327 1EB4F4282DE0A09500D934C0 /* MyRewardsOffersScrollTableViewCell */, 340 1EB4F4282DE0A09500D934C0 /* MyRewardsOffersScrollTableViewCell */,
328 1EB4F4222DE09A4300D934C0 /* MyRewardsBannerOffersScrollTableViewCell */, 341 1EB4F4222DE09A4300D934C0 /* MyRewardsBannerOffersScrollTableViewCell */,
342 + 1E66E4942E30F8C600BCEF9D /* MyRewardsProfileInfoTableViewCell */,
329 ); 343 );
330 path = cells; 344 path = cells;
331 sourceTree = "<group>"; 345 sourceTree = "<group>";
...@@ -588,6 +602,7 @@ ...@@ -588,6 +602,7 @@
588 1EA8E5C12DDF427A00CD3418 /* PingLCG-Light.otf in Resources */, 602 1EA8E5C12DDF427A00CD3418 /* PingLCG-Light.otf in Resources */,
589 1EA8E5C22DDF427A00CD3418 /* PingLCG-Regular.otf in Resources */, 603 1EA8E5C22DDF427A00CD3418 /* PingLCG-Regular.otf in Resources */,
590 1EB4F42B2DE0A0AF00D934C0 /* MyRewardsOffersScrollTableViewCell.xib in Resources */, 604 1EB4F42B2DE0A0AF00D934C0 /* MyRewardsOffersScrollTableViewCell.xib in Resources */,
605 + 1E66E4972E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.xib in Resources */,
591 1EDBAF102DE8443B00911E79 /* ProfileHeaderTableViewCell.xib in Resources */, 606 1EDBAF102DE8443B00911E79 /* ProfileHeaderTableViewCell.xib in Resources */,
592 1E917CDB2DDF68C7002221D8 /* CouponViewController.xib in Resources */, 607 1E917CDB2DDF68C7002221D8 /* CouponViewController.xib in Resources */,
593 1E917CE02DDF6909002221D8 /* ProfileViewController.xib in Resources */, 608 1E917CE02DDF6909002221D8 /* ProfileViewController.xib in Resources */,
...@@ -668,6 +683,7 @@ ...@@ -668,6 +683,7 @@
668 E6A77853282933340045BBA8 /* SwiftWarplyFramework.docc in Sources */, 683 E6A77853282933340045BBA8 /* SwiftWarplyFramework.docc in Sources */,
669 1EDBAF092DE843FB00911E79 /* ProfileCouponFiltersTableViewCell.swift in Sources */, 684 1EDBAF092DE843FB00911E79 /* ProfileCouponFiltersTableViewCell.swift in Sources */,
670 E6A778DF282933E60045BBA8 /* WarplyReactMethods.m in Sources */, 685 E6A778DF282933E60045BBA8 /* WarplyReactMethods.m in Sources */,
686 + 1E66E4982E30F9F200BCEF9D /* MyRewardsProfileInfoTableViewCell.swift in Sources */,
671 1E917CD72DDF64B2002221D8 /* MyRewardsViewController.swift in Sources */, 687 1E917CD72DDF64B2002221D8 /* MyRewardsViewController.swift in Sources */,
672 1E917CDC2DDF68C7002221D8 /* CouponViewController.swift in Sources */, 688 1E917CDC2DDF68C7002221D8 /* CouponViewController.swift in Sources */,
673 1E4C4CFB2DE6014500279AAD /* CopyableLabel.swift in Sources */, 689 1E4C4CFB2DE6014500279AAD /* CopyableLabel.swift in Sources */,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
7 <key>SwiftWarplyFramework.xcscheme_^#shared#^_</key> 7 <key>SwiftWarplyFramework.xcscheme_^#shared#^_</key>
8 <dict> 8 <dict>
9 <key>orderHint</key> 9 <key>orderHint</key>
10 - <integer>1</integer> 10 + <integer>0</integer>
11 </dict> 11 </dict>
12 </dict> 12 </dict>
13 </dict> 13 </dict>
......
...@@ -9,7 +9,7 @@ import UIKit ...@@ -9,7 +9,7 @@ import UIKit
9 9
10 protocol MyRewardsBannerOffersScrollTableViewCellDelegate: AnyObject { 10 protocol MyRewardsBannerOffersScrollTableViewCellDelegate: AnyObject {
11 func didSelectBannerOffer(_ index: Int) 11 func didSelectBannerOffer(_ index: Int)
12 - func didTapProfileButton() 12 +// func didTapProfileButton()
13 } 13 }
14 14
15 @objc(MyRewardsBannerOffersScrollTableViewCell) 15 @objc(MyRewardsBannerOffersScrollTableViewCell)
...@@ -103,7 +103,7 @@ public class MyRewardsBannerOffersScrollTableViewCell: UITableViewCell { ...@@ -103,7 +103,7 @@ public class MyRewardsBannerOffersScrollTableViewCell: UITableViewCell {
103 103
104 @objc private func profileButtonTapped() { 104 @objc private func profileButtonTapped() {
105 // TODO: UNCOMMENT 105 // TODO: UNCOMMENT
106 - delegate?.didTapProfileButton() 106 +// delegate?.didTapProfileButton()
107 } 107 }
108 } 108 }
109 109
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
17 <autoresizingMask key="autoresizingMask"/> 17 <autoresizingMask key="autoresizingMask"/>
18 <subviews> 18 <subviews>
19 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="VzF-dQ-3Wa" userLabel="Parent View"> 19 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="VzF-dQ-3Wa" userLabel="Parent View">
20 - <rect key="frame" x="0.0" y="0.0" width="413" height="465"/> 20 + <rect key="frame" x="0.0" y="0.0" width="413" height="349"/>
21 <subviews> 21 <subviews>
22 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JTs-J5-DO2" userLabel="Top View"> 22 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JTs-J5-DO2" userLabel="Top View">
23 <rect key="frame" x="24" y="36" width="365" height="35"/> 23 <rect key="frame" x="24" y="36" width="365" height="35"/>
...@@ -106,7 +106,7 @@ ...@@ -106,7 +106,7 @@
106 </constraints> 106 </constraints>
107 </view> 107 </view>
108 <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="I7z-Fz-SNP"> 108 <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="I7z-Fz-SNP">
109 - <rect key="frame" x="0.0" y="91" width="413" height="348"/> 109 + <rect key="frame" x="0.0" y="-25" width="413" height="348"/>
110 <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 110 <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
111 <constraints> 111 <constraints>
112 <constraint firstAttribute="height" constant="348" id="aEf-Xl-A2C"/> 112 <constraint firstAttribute="height" constant="348" id="aEf-Xl-A2C"/>
...@@ -124,7 +124,7 @@ ...@@ -124,7 +124,7 @@
124 </connections> 124 </connections>
125 </collectionView> 125 </collectionView>
126 <pageControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="3" translatesAutoresizingMaskIntoConstraints="NO" id="lOm-CZ-dVG"> 126 <pageControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="3" translatesAutoresizingMaskIntoConstraints="NO" id="lOm-CZ-dVG">
127 - <rect key="frame" x="170" y="439" width="73" height="26"/> 127 + <rect key="frame" x="170" y="323" width="73" height="26"/>
128 </pageControl> 128 </pageControl>
129 </subviews> 129 </subviews>
130 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 130 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
...@@ -136,9 +136,14 @@ ...@@ -136,9 +136,14 @@
136 <constraint firstAttribute="trailing" secondItem="JTs-J5-DO2" secondAttribute="trailing" constant="24" id="Rdi-FK-2Ft"/> 136 <constraint firstAttribute="trailing" secondItem="JTs-J5-DO2" secondAttribute="trailing" constant="24" id="Rdi-FK-2Ft"/>
137 <constraint firstAttribute="trailing" secondItem="I7z-Fz-SNP" secondAttribute="trailing" id="avB-Gc-ttI"/> 137 <constraint firstAttribute="trailing" secondItem="I7z-Fz-SNP" secondAttribute="trailing" id="avB-Gc-ttI"/>
138 <constraint firstItem="I7z-Fz-SNP" firstAttribute="leading" secondItem="VzF-dQ-3Wa" secondAttribute="leading" id="pTY-7d-s1S"/> 138 <constraint firstItem="I7z-Fz-SNP" firstAttribute="leading" secondItem="VzF-dQ-3Wa" secondAttribute="leading" id="pTY-7d-s1S"/>
139 - <constraint firstItem="I7z-Fz-SNP" firstAttribute="top" secondItem="JTs-J5-DO2" secondAttribute="bottom" constant="20" id="vJF-jy-p83"/> 139 + <constraint firstItem="I7z-Fz-SNP" firstAttribute="top" secondItem="VzF-dQ-3Wa" secondAttribute="top" constant="20" id="vJF-jy-p83"/>
140 <constraint firstItem="lOm-CZ-dVG" firstAttribute="centerX" secondItem="VzF-dQ-3Wa" secondAttribute="centerX" id="xpw-tV-NcW"/> 140 <constraint firstItem="lOm-CZ-dVG" firstAttribute="centerX" secondItem="VzF-dQ-3Wa" secondAttribute="centerX" id="xpw-tV-NcW"/>
141 </constraints> 141 </constraints>
142 + <variation key="default">
143 + <mask key="subviews">
144 + <exclude reference="JTs-J5-DO2"/>
145 + </mask>
146 + </variation>
142 </view> 147 </view>
143 </subviews> 148 </subviews>
144 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> 149 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
......
1 +//
2 +// MyRewardsProfileInfoTableViewCell.swift
3 +// SwiftWarplyFramework
4 +//
5 +// Created by Manos Chorianopoulos on 23/7/25.
6 +//
7 +
8 +import UIKit
9 +
10 +protocol MyRewardsProfileInfoTableViewCellDelegate: AnyObject {
11 + func didTapProfileButton()
12 +}
13 +
14 +@objc(MyRewardsProfileInfoTableViewCell)
15 +public class MyRewardsProfileInfoTableViewCell: UITableViewCell {
16 + @IBOutlet weak var tagView1: UIView!
17 + @IBOutlet weak var tagLabel1: UILabel!
18 + @IBOutlet weak var tagView2: UIView!
19 + @IBOutlet weak var tagLabel2: UILabel!
20 + @IBOutlet weak var profileImage: UIImageView!
21 + @IBOutlet weak var profileButton: UIButton!
22 +
23 + weak var delegate: MyRewardsProfileInfoTableViewCellDelegate?
24 +
25 + // MARK: - Properties
26 + private var profileModel: ProfileModel?
27 +
28 + public override func awakeFromNib() {
29 + super.awakeFromNib()
30 + // Initialization code
31 +
32 + profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
33 +
34 + profileButton.addTarget(self, action: #selector(profileButtonTapped), for: .touchUpInside)
35 +
36 + tagView1.backgroundColor = UIColor(rgb: 0x09914E)
37 + tagView1.layer.cornerRadius = 4.0
38 + tagLabel1.font = UIFont(name: "PingLCG-Regular", size: 17)
39 + tagLabel1.textColor = UIColor(rgb: 0xFFFFFF)
40 +
41 + tagView2.backgroundColor = UIColor(rgb: 0xFC9F25)
42 + tagView2.layer.cornerRadius = 4.0
43 + tagLabel2.font = UIFont(name: "PingLCG-Regular", size: 17)
44 + tagLabel2.textColor = UIColor(rgb: 0xFFFFFF)
45 +
46 + }
47 +
48 + public override func setSelected(_ selected: Bool, animated: Bool) {
49 + super.setSelected(selected, animated: animated)
50 +
51 + // Configure the view for the selected state
52 + }
53 +
54 + @objc private func profileButtonTapped() {
55 + delegate?.didTapProfileButton()
56 + }
57 +
58 + // MARK: - Configuration Methods
59 +
60 + public func configureCell(data: SectionModel?) {
61 + guard let data = data,
62 + let itemType = data.itemType,
63 + itemType == .profile else {
64 + configureDefaultState()
65 + return
66 + }
67 +
68 + // Check if we have real profile data
69 + if let metadata = data.metadata,
70 + let profile = metadata["profile"] as? ProfileModel {
71 + // Configure with real profile data
72 + configureCell(profile: profile)
73 + } else {
74 + // Configure with default state (no profile data)
75 + configureDefaultState()
76 + }
77 + }
78 +
79 + public func configureCell(profile: ProfileModel) {
80 + self.profileModel = profile
81 +
82 + // TODO: Configure tag labels with profile data
83 + // We need to determine what data should populate tagView1 and tagView2
84 + // Possible options from ProfileModel:
85 + // - _user_points (loyalty points)
86 + // - _badge (user badge/tier)
87 + // - _verified (verification status)
88 + // - Custom business logic based on profile data
89 +
90 + // For now, keep tags visible with current static styling
91 + tagView1.isHidden = false
92 + tagView2.isHidden = false
93 +
94 + // Load profile image if available
95 + if !profile._image_url.isEmpty {
96 + loadProfileImage(from: profile._image_url)
97 + } else {
98 + profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
99 + }
100 + }
101 +
102 + private func configureDefaultState() {
103 + // Default state: no profile data available
104 + self.profileModel = nil
105 +
106 + // Keep tags visible even in default state
107 + tagView1.isHidden = false
108 + tagView2.isHidden = false
109 +
110 + profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
111 + }
112 +
113 + private func loadProfileImage(from urlString: String) {
114 + // For now, use default image - can be enhanced later with URL loading
115 + profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
116 + }
117 +}
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<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">
3 + <device id="retina6_12" orientation="portrait" appearance="light"/>
4 + <dependencies>
5 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/>
6 + <capability name="Safe area layout guides" minToolsVersion="9.0"/>
7 + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
8 + </dependencies>
9 + <objects>
10 + <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
11 + <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
12 + <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="MyRewardsProfileInfoTableViewCell" rowHeight="141" id="KGk-i7-Jjw" customClass="MyRewardsProfileInfoTableViewCell">
13 + <rect key="frame" x="0.0" y="0.0" width="318" height="141"/>
14 + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
15 + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
16 + <rect key="frame" x="0.0" y="0.0" width="318" height="141"/>
17 + <autoresizingMask key="autoresizingMask"/>
18 + <subviews>
19 + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GrG-Na-dBF" userLabel="Parent View">
20 + <rect key="frame" x="0.0" y="0.0" width="318" height="130.33333333333334"/>
21 + <subviews>
22 + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Uzq-sj-DeG" userLabel="Top View">
23 + <rect key="frame" x="24" y="35.999999999999993" width="270" height="94.333333333333314"/>
24 + <subviews>
25 + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iZR-9I-qrq">
26 + <rect key="frame" x="0.0" y="34.333333333333329" width="58" height="26"/>
27 + <subviews>
28 + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Green" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HbR-qg-oZj">
29 + <rect key="frame" x="6" y="3" width="46" height="20"/>
30 + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
31 + <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
32 + <nil key="textColor"/>
33 + <nil key="highlightedColor"/>
34 + </label>
35 + </subviews>
36 + <color key="backgroundColor" red="0.035294117649999998" green="0.56862745100000001" blue="0.30588235289999999" alpha="1" colorSpace="calibratedRGB"/>
37 + <constraints>
38 + <constraint firstAttribute="trailing" secondItem="HbR-qg-oZj" secondAttribute="trailing" constant="6" id="D5p-jO-24v"/>
39 + <constraint firstItem="HbR-qg-oZj" firstAttribute="leading" secondItem="iZR-9I-qrq" secondAttribute="leading" constant="6" id="LFh-ia-T2B"/>
40 + <constraint firstItem="HbR-qg-oZj" firstAttribute="top" secondItem="iZR-9I-qrq" secondAttribute="top" constant="3" id="RhN-3V-CNu"/>
41 + <constraint firstAttribute="bottom" secondItem="HbR-qg-oZj" secondAttribute="bottom" constant="3" id="aPc-Uy-H9c"/>
42 + </constraints>
43 + </view>
44 + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uq8-95-vyl">
45 + <rect key="frame" x="66" y="34.333333333333329" width="61.666666666666657" height="26"/>
46 + <subviews>
47 + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Family" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UDU-LU-kJf">
48 + <rect key="frame" x="6" y="3" width="49.666666666666664" height="20"/>
49 + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
50 + <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
51 + <nil key="textColor"/>
52 + <nil key="highlightedColor"/>
53 + </label>
54 + </subviews>
55 + <color key="backgroundColor" red="0.98823529409999999" green="0.62352941179999999" blue="0.1450980392" alpha="1" colorSpace="calibratedRGB"/>
56 + <constraints>
57 + <constraint firstAttribute="trailing" secondItem="UDU-LU-kJf" secondAttribute="trailing" constant="6" id="Ann-r9-abe"/>
58 + <constraint firstItem="UDU-LU-kJf" firstAttribute="top" secondItem="uq8-95-vyl" secondAttribute="top" constant="3" id="cUu-IO-JNt"/>
59 + <constraint firstAttribute="bottom" secondItem="UDU-LU-kJf" secondAttribute="bottom" constant="3" id="dIU-Z8-BrZ"/>
60 + <constraint firstItem="UDU-LU-kJf" firstAttribute="leading" secondItem="uq8-95-vyl" secondAttribute="leading" constant="6" id="vb0-4P-dZE"/>
61 + </constraints>
62 + </view>
63 + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="D1N-l1-zYb">
64 + <rect key="frame" x="227" y="0.0" width="43" height="94.333333333333329"/>
65 + <subviews>
66 + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ksj-lM-RAp">
67 + <rect key="frame" x="0.0" y="0.0" width="43" height="43"/>
68 + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
69 + <constraints>
70 + <constraint firstAttribute="width" constant="43" id="MsB-3N-rp3"/>
71 + <constraint firstAttribute="height" constant="43" id="UVr-zI-nCH"/>
72 + </constraints>
73 + </imageView>
74 + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PEZ-e6-PaN" userLabel="ProfileButton">
75 + <rect key="frame" x="0.0" y="0.0" width="43" height="94.333333333333329"/>
76 + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
77 + <state key="normal" title="Button"/>
78 + <buttonConfiguration key="configuration" style="plain" title="Button">
79 + <color key="baseForegroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
80 + </buttonConfiguration>
81 + </button>
82 + </subviews>
83 + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
84 + <constraints>
85 + <constraint firstAttribute="trailing" secondItem="PEZ-e6-PaN" secondAttribute="trailing" id="0Bs-BN-BYr"/>
86 + <constraint firstItem="ksj-lM-RAp" firstAttribute="top" secondItem="D1N-l1-zYb" secondAttribute="top" id="72b-ae-wwu"/>
87 + <constraint firstItem="PEZ-e6-PaN" firstAttribute="leading" secondItem="D1N-l1-zYb" secondAttribute="leading" id="JDf-Bc-agp"/>
88 + <constraint firstAttribute="bottom" secondItem="ksj-lM-RAp" secondAttribute="bottom" id="JVS-lc-V1a"/>
89 + <constraint firstAttribute="bottom" secondItem="PEZ-e6-PaN" secondAttribute="bottom" id="UsX-dl-5BF"/>
90 + <constraint firstAttribute="trailing" secondItem="ksj-lM-RAp" secondAttribute="trailing" id="VMk-Qb-GcZ"/>
91 + <constraint firstItem="ksj-lM-RAp" firstAttribute="leading" secondItem="D1N-l1-zYb" secondAttribute="leading" id="noX-0V-w67"/>
92 + <constraint firstItem="PEZ-e6-PaN" firstAttribute="top" secondItem="D1N-l1-zYb" secondAttribute="top" id="zU6-UR-WGM"/>
93 + </constraints>
94 + </view>
95 + </subviews>
96 + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
97 + <constraints>
98 + <constraint firstItem="D1N-l1-zYb" firstAttribute="top" secondItem="Uzq-sj-DeG" secondAttribute="top" id="2Pg-pB-HXM"/>
99 + <constraint firstAttribute="trailing" secondItem="D1N-l1-zYb" secondAttribute="trailing" id="TIg-op-IhZ"/>
100 + <constraint firstItem="iZR-9I-qrq" firstAttribute="centerY" secondItem="Uzq-sj-DeG" secondAttribute="centerY" id="Xj6-Va-Vu6"/>
101 + <constraint firstItem="uq8-95-vyl" firstAttribute="leading" secondItem="iZR-9I-qrq" secondAttribute="trailing" constant="8" id="cFB-Jw-8CI"/>
102 + <constraint firstItem="uq8-95-vyl" firstAttribute="centerY" secondItem="Uzq-sj-DeG" secondAttribute="centerY" id="lpD-GB-qJb"/>
103 + <constraint firstItem="iZR-9I-qrq" firstAttribute="leading" secondItem="Uzq-sj-DeG" secondAttribute="leading" id="nqO-fC-fCW"/>
104 + <constraint firstItem="D1N-l1-zYb" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="uq8-95-vyl" secondAttribute="trailing" constant="8" id="yWz-PS-7AW"/>
105 + <constraint firstAttribute="bottom" secondItem="D1N-l1-zYb" secondAttribute="bottom" id="zP0-l8-HZz"/>
106 + </constraints>
107 + </view>
108 + </subviews>
109 + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
110 + <constraints>
111 + <constraint firstAttribute="trailing" secondItem="Uzq-sj-DeG" secondAttribute="trailing" constant="24" id="6Cb-JD-fEd"/>
112 + <constraint firstItem="Uzq-sj-DeG" firstAttribute="top" secondItem="GrG-Na-dBF" secondAttribute="top" constant="36" id="a4m-JH-bDa"/>
113 + <constraint firstItem="Uzq-sj-DeG" firstAttribute="leading" secondItem="GrG-Na-dBF" secondAttribute="leading" constant="24" id="bJt-81-pTc"/>
114 + <constraint firstAttribute="bottom" secondItem="Uzq-sj-DeG" secondAttribute="bottom" id="cjl-n6-BBf"/>
115 + </constraints>
116 + </view>
117 + </subviews>
118 + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
119 + <constraints>
120 + <constraint firstItem="GrG-Na-dBF" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="6vh-eL-qMw"/>
121 + <constraint firstAttribute="trailing" secondItem="GrG-Na-dBF" secondAttribute="trailing" id="Mhv-wX-J42"/>
122 + <constraint firstAttribute="bottom" secondItem="GrG-Na-dBF" secondAttribute="bottom" id="WfG-lv-Uw7"/>
123 + <constraint firstItem="GrG-Na-dBF" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="iSV-2N-pbv"/>
124 + </constraints>
125 + </tableViewCellContentView>
126 + <viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
127 + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
128 + <connections>
129 + <outlet property="profileButton" destination="PEZ-e6-PaN" id="FBL-8U-9OZ"/>
130 + <outlet property="profileImage" destination="ksj-lM-RAp" id="lwv-9G-Mmy"/>
131 + <outlet property="tagLabel1" destination="HbR-qg-oZj" id="Ggl-NO-w2a"/>
132 + <outlet property="tagLabel2" destination="UDU-LU-kJf" id="Tc6-yb-xi1"/>
133 + <outlet property="tagView1" destination="iZR-9I-qrq" id="EtM-Q0-Ru9"/>
134 + <outlet property="tagView2" destination="uq8-95-vyl" id="mP6-vQ-GY6"/>
135 + </connections>
136 + <point key="canvasLocation" x="41.221374045801525" y="29.929577464788736"/>
137 + </tableViewCell>
138 + </objects>
139 +</document>
...@@ -11,6 +11,7 @@ import Foundation ...@@ -11,6 +11,7 @@ import Foundation
11 // MARK: - Section Types 11 // MARK: - Section Types
12 12
13 enum SectionType { 13 enum SectionType {
14 + case myRewardsProfileInfo // MyRewardsProfileInfoTableViewCell
14 case myRewardsBannerOffers // MyRewardsBannerOffersScrollTableViewCell 15 case myRewardsBannerOffers // MyRewardsBannerOffersScrollTableViewCell
15 case myRewardsHorizontalCouponsets // MyRewardsOffersScrollTableViewCell 16 case myRewardsHorizontalCouponsets // MyRewardsOffersScrollTableViewCell
16 case profileHeader // ProfileHeaderTableViewCell (no items) 17 case profileHeader // ProfileHeaderTableViewCell (no items)
...@@ -21,6 +22,7 @@ enum SectionType { ...@@ -21,6 +22,7 @@ enum SectionType {
21 } 22 }
22 23
23 enum ItemType { 24 enum ItemType {
25 + case profile // ProfileModel
24 case campaigns // [CampaignItemModel] 26 case campaigns // [CampaignItemModel]
25 case couponSets // [CouponSetItemModel] 27 case couponSets // [CouponSetItemModel]
26 case coupons // [CouponItemModel] 28 case coupons // [CouponItemModel]
......
...@@ -40,6 +40,10 @@ import UIKit ...@@ -40,6 +40,10 @@ import UIKit
40 // Campaign data for banners 40 // Campaign data for banners
41 var bannerCampaigns: [CampaignItemModel] = [] 41 var bannerCampaigns: [CampaignItemModel] = []
42 42
43 + // Profile data
44 + var profileModel: ProfileModel?
45 + var profileSection: SectionModel?
46 +
43 public override func viewDidLoad() { 47 public override func viewDidLoad() {
44 super.viewDidLoad() 48 super.viewDidLoad()
45 49
...@@ -56,13 +60,18 @@ import UIKit ...@@ -56,13 +60,18 @@ import UIKit
56 tableView.estimatedRowHeight = 200 60 tableView.estimatedRowHeight = 200
57 tableView.rowHeight = UITableView.automaticDimension 61 tableView.rowHeight = UITableView.automaticDimension
58 62
59 - // Start with empty sections - will be populated dynamically by API calls 63 + // Always create profile section first (with default state)
60 - loadCampaigns() 64 + createDefaultProfileSection()
65 +
66 + // Load data
67 + loadProfile() // Try to populate profile with real data
68 + loadCampaigns() // Load campaigns
61 } 69 }
62 70
63 // NEW: Safe XIB registration method 71 // NEW: Safe XIB registration method
64 private func registerTableViewCells() { 72 private func registerTableViewCells() {
65 let cellConfigs = [ 73 let cellConfigs = [
74 + ("MyRewardsProfileInfoTableViewCell", "MyRewardsProfileInfoTableViewCell"),
66 ("MyRewardsBannerOffersScrollTableViewCell", "MyRewardsBannerOffersScrollTableViewCell"), 75 ("MyRewardsBannerOffersScrollTableViewCell", "MyRewardsBannerOffersScrollTableViewCell"),
67 ("MyRewardsOffersScrollTableViewCell", "MyRewardsOffersScrollTableViewCell") 76 ("MyRewardsOffersScrollTableViewCell", "MyRewardsOffersScrollTableViewCell")
68 ] 77 ]
...@@ -127,6 +136,66 @@ import UIKit ...@@ -127,6 +136,66 @@ import UIKit
127 } 136 }
128 } 137 }
129 138
139 + // MARK: - Profile Loading
140 + public func loadProfile() {
141 + // Always attempt to load profile, regardless of authentication status
142 + // If not authenticated, the API call will fail gracefully and we keep the default state
143 +
144 + WarplySDK.shared.getProfile { [weak self] profile in
145 + guard let self = self else { return }
146 +
147 + if let profile = profile {
148 + // Success: Update with real profile data
149 + self.profileModel = profile
150 + self.updateProfileSectionWithData(profile)
151 + print("✅ [MyRewardsViewController] Profile loaded successfully")
152 + } else {
153 + // No profile data: Keep default state
154 + print("ℹ️ [MyRewardsViewController] No profile data received - keeping default state")
155 + }
156 +
157 + } failureCallback: { [weak self] errorCode in
158 + print("⚠️ [MyRewardsViewController] Profile loading failed with error: \(errorCode) - keeping default state")
159 + // Don't remove section - just keep the default state
160 + // The profile section remains visible with default profile pic
161 + }
162 + }
163 +
164 + private func createDefaultProfileSection() {
165 + // Create profile section with default/empty state
166 + let defaultProfileSection = SectionModel(
167 + sectionType: .myRewardsProfileInfo,
168 + title: nil,
169 + count: 1,
170 + metadata: ["profile": nil] // nil profile = default state
171 + )
172 +
173 + // Always insert at index 0 (top of the list)
174 + sections.insert(defaultProfileSection, at: 0)
175 + profileSection = defaultProfileSection
176 + }
177 +
178 + private func updateProfileSectionWithData(_ profile: ProfileModel) {
179 + // Create updated profile section with real data
180 + let updatedProfileSection = SectionModel(
181 + sectionType: .myRewardsProfileInfo,
182 + title: nil,
183 + count: 1,
184 + metadata: ["profile": profile]
185 + )
186 +
187 + // Find and update the profile section
188 + if let profileIndex = sections.firstIndex(where: { $0.sectionType == .myRewardsProfileInfo }) {
189 + sections[profileIndex] = updatedProfileSection
190 + profileSection = updatedProfileSection
191 +
192 + // Reload only the profile section
193 + DispatchQueue.main.async {
194 + self.tableView.reloadSections(IndexSet(integer: profileIndex), with: .none)
195 + }
196 + }
197 + }
198 +
130 private func openCampaignViewController(with index: Int) { 199 private func openCampaignViewController(with index: Int) {
131 // Validate index bounds 200 // Validate index bounds
132 guard index < bannerCampaigns.count else { 201 guard index < bannerCampaigns.count else {
...@@ -203,6 +272,12 @@ extension MyRewardsViewController: UITableViewDelegate, UITableViewDataSource{ ...@@ -203,6 +272,12 @@ extension MyRewardsViewController: UITableViewDelegate, UITableViewDataSource{
203 let sectionModel = sections[indexPath.section] 272 let sectionModel = sections[indexPath.section]
204 273
205 switch sectionModel.sectionType { 274 switch sectionModel.sectionType {
275 + case .myRewardsProfileInfo:
276 + let cell = tableView.dequeueReusableCell(withIdentifier: "MyRewardsProfileInfoTableViewCell", for: indexPath) as! MyRewardsProfileInfoTableViewCell
277 + cell.delegate = self
278 + cell.configureCell(data: sectionModel)
279 + return cell
280 +
206 case .myRewardsBannerOffers: 281 case .myRewardsBannerOffers:
207 let cell = tableView.dequeueReusableCell(withIdentifier: "MyRewardsBannerOffersScrollTableViewCell", for: indexPath) as! MyRewardsBannerOffersScrollTableViewCell 282 let cell = tableView.dequeueReusableCell(withIdentifier: "MyRewardsBannerOffersScrollTableViewCell", for: indexPath) as! MyRewardsBannerOffersScrollTableViewCell
208 cell.delegate = self 283 cell.delegate = self
...@@ -232,16 +307,24 @@ extension MyRewardsViewController: UITableViewDelegate, UITableViewDataSource{ ...@@ -232,16 +307,24 @@ extension MyRewardsViewController: UITableViewDelegate, UITableViewDataSource{
232 } 307 }
233 308
234 // Add delegate conformance 309 // Add delegate conformance
310 +extension MyRewardsViewController: MyRewardsProfileInfoTableViewCellDelegate {
311 + func didTapProfileButton() {
312 + // Navigate to ProfileViewController
313 + openProfileViewController()
314 + }
315 +}
316 +
317 +// Add delegate conformance
235 extension MyRewardsViewController: MyRewardsBannerOffersScrollTableViewCellDelegate { 318 extension MyRewardsViewController: MyRewardsBannerOffersScrollTableViewCellDelegate {
236 func didSelectBannerOffer(_ index: Int) { 319 func didSelectBannerOffer(_ index: Int) {
237 // Navigate to CampaignViewController 320 // Navigate to CampaignViewController
238 openCampaignViewController(with: index) 321 openCampaignViewController(with: index)
239 } 322 }
240 323
241 - func didTapProfileButton() { 324 +// func didTapProfileButton() {
242 - // Navigate to ProfileViewController 325 +// // Navigate to ProfileViewController
243 - openProfileViewController() 326 +// openProfileViewController()
244 - } 327 +// }
245 } 328 }
246 329
247 // Add delegate conformance 330 // Add delegate conformance
......