Manos Chorianopoulos

MyRewardsVC fixes

...@@ -121,23 +121,15 @@ extension MyRewardsBannerOffersScrollTableViewCell: UICollectionViewDataSource, ...@@ -121,23 +121,15 @@ extension MyRewardsBannerOffersScrollTableViewCell: UICollectionViewDataSource,
121 public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 121 public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
122 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyRewardsBannerOfferCollectionViewCell", for: indexPath) as! MyRewardsBannerOfferCollectionViewCell 122 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyRewardsBannerOfferCollectionViewCell", for: indexPath) as! MyRewardsBannerOfferCollectionViewCell
123 123
124 - // Handle different item types 124 + // Handle only CampaignItemModel - banner cells are campaign-specific
125 guard let data = self.data, 125 guard let data = self.data,
126 - let itemType = data.itemType,
127 let items = data.items, 126 let items = data.items,
128 - indexPath.row < items.count else { 127 + indexPath.row < items.count,
128 + let campaign = items[indexPath.row] as? CampaignItemModel else {
129 return cell 129 return cell
130 } 130 }
131 131
132 - switch itemType {
133 - case .campaigns:
134 - if let campaign = items[indexPath.row] as? CampaignItemModel {
135 cell.configureCell(data: campaign) 132 cell.configureCell(data: campaign)
136 - }
137 - default:
138 - // Handle other types if needed in the future
139 - break
140 - }
141 133
142 return cell 134 return cell
143 } 135 }
......
...@@ -65,49 +65,6 @@ public class MyRewardsOfferCollectionViewCell: UICollectionViewCell { ...@@ -65,49 +65,6 @@ public class MyRewardsOfferCollectionViewCell: UICollectionViewCell {
65 logoImage.image = UIImage(named: data.merchantLogo, in: Bundle.frameworkResourceBundle, compatibleWith: nil) 65 logoImage.image = UIImage(named: data.merchantLogo, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
66 } 66 }
67 67
68 - // MARK: - New configureCell methods for different data types
69 -
70 - func configureCell(data: CampaignItemModel) {
71 - // Use campaign's banner image if available
72 - let imageName = data._banner_img_mobile ?? ""
73 - if !imageName.isEmpty {
74 - bannerImage.image = UIImage(named: imageName, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
75 - } else {
76 - bannerImage.image = nil
77 - }
78 -
79 - // Default to not favorite for campaigns
80 - favoriteImage.image = UIImage(named: "favorite_empty", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
81 -
82 - // Use campaign category or type for discount display
83 - discountLabel.text = data._category ?? data._campaign_type ?? ""
84 - discountLabel.font = UIFont(name: "PingLCG-Bold", size: 17)
85 - discountLabel.textColor = UIColor(rgb: 0xF2F2F2)
86 -
87 - // Default color for campaigns
88 - discountView.backgroundColor = UIColor(rgb: 0xEE417D)
89 -
90 - titleLabel.text = data._title ?? ""
91 - titleLabel.font = UIFont(name: "PingLCG-Bold", size: 17)
92 - titleLabel.textColor = UIColor(rgb: 0x000F1E)
93 -
94 - subtitleLabel.text = data._subtitle ?? ""
95 - subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 14)
96 - subtitleLabel.textColor = UIColor(rgb: 0x00111B)
97 -
98 - // Use campaign expiration date
99 - expirationLabel.text = data._valid_until ?? ""
100 - expirationLabel.font = UIFont(name: "PingLCG-Regular", size: 13)
101 - expirationLabel.textColor = UIColor(rgb: 0x00111B)
102 -
103 - // Use campaign logo
104 - let logoName = data._logo_url ?? ""
105 - if !logoName.isEmpty {
106 - logoImage.image = UIImage(named: logoName, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
107 - } else {
108 - logoImage.image = nil
109 - }
110 - }
111 68
112 func configureCell(data: CouponSetItemModel) { 69 func configureCell(data: CouponSetItemModel) {
113 // Use coupon set preview image 70 // Use coupon set preview image
...@@ -166,60 +123,4 @@ public class MyRewardsOfferCollectionViewCell: UICollectionViewCell { ...@@ -166,60 +123,4 @@ public class MyRewardsOfferCollectionViewCell: UICollectionViewCell {
166 } 123 }
167 } 124 }
168 125
169 - func configureCell(data: CouponItemModel) {
170 - // Use coupon image
171 - let imageName = data.image ?? ""
172 - if !imageName.isEmpty {
173 - bannerImage.image = UIImage(named: imageName, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
174 - } else {
175 - bannerImage.image = nil
176 - }
177 -
178 - // Default to not favorite for coupons
179 - favoriteImage.image = UIImage(named: "favorite_empty", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
180 -
181 - // Use coupon discount
182 - discountLabel.text = data.discount ?? ""
183 - discountLabel.font = UIFont(name: "PingLCG-Bold", size: 17)
184 - discountLabel.textColor = UIColor(rgb: 0xF2F2F2)
185 -
186 - // Color based on coupon status
187 - let statusColor: UInt = {
188 - switch data.status {
189 - case 1:
190 - return 0x28A745 // Active - green
191 - case 0:
192 - return 0x6C757D // Used - gray
193 - default:
194 - return 0x007AFF // Default - blue
195 - }
196 - }()
197 - discountView.backgroundColor = UIColor(rgb: statusColor)
198 -
199 - titleLabel.text = data.name ?? ""
200 - titleLabel.font = UIFont(name: "PingLCG-Bold", size: 17)
201 - titleLabel.textColor = UIColor(rgb: 0x000F1E)
202 -
203 - subtitleLabel.text = data.short_description ?? ""
204 - subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 14)
205 - subtitleLabel.textColor = UIColor(rgb: 0x00111B)
206 -
207 - expirationLabel.text = data.expiration ?? ""
208 - expirationLabel.font = UIFont(name: "PingLCG-Regular", size: 13)
209 - expirationLabel.textColor = UIColor(rgb: 0x00111B)
210 -
211 - // Use coupon set data image if available
212 - if let couponSetData = data.couponset_data,
213 - let imgArray = couponSetData.img,
214 - !imgArray.isEmpty {
215 - let logoName = imgArray[0]
216 - if !logoName.isEmpty {
217 - logoImage.image = UIImage(named: logoName, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
218 - } else {
219 - logoImage.image = nil
220 - }
221 - } else {
222 - logoImage.image = nil
223 - }
224 - }
225 } 126 }
......
...@@ -151,7 +151,7 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl ...@@ -151,7 +151,7 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl
151 public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 151 public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
152 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyRewardsOfferCollectionViewCell", for: indexPath) as! MyRewardsOfferCollectionViewCell 152 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyRewardsOfferCollectionViewCell", for: indexPath) as! MyRewardsOfferCollectionViewCell
153 153
154 - // Handle different item types with type checking 154 + // Handle only CouponSetItemModel and OfferModel - no campaigns
155 guard let data = self.data, 155 guard let data = self.data,
156 let items = data.items, 156 let items = data.items,
157 indexPath.row < items.count else { 157 indexPath.row < items.count else {
...@@ -159,27 +159,22 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl ...@@ -159,27 +159,22 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl
159 } 159 }
160 160
161 switch data.itemType { 161 switch data.itemType {
162 - case .campaigns:
163 - if let campaign = items[indexPath.row] as? CampaignItemModel {
164 - cell.configureCell(data: campaign)
165 - }
166 case .couponSets: 162 case .couponSets:
167 if let couponSet = items[indexPath.row] as? CouponSetItemModel { 163 if let couponSet = items[indexPath.row] as? CouponSetItemModel {
168 cell.configureCell(data: couponSet) 164 cell.configureCell(data: couponSet)
169 } 165 }
170 - case .coupons:
171 - if let coupon = items[indexPath.row] as? CouponItemModel {
172 - cell.configureCell(data: coupon)
173 - }
174 default: 166 default:
175 - break 167 + // Handle OfferModel for ProfileViewController compatibility
168 + if let offer = items[indexPath.row] as? OfferModel {
169 + cell.configureCell(data: offer)
170 + }
176 } 171 }
177 172
178 return cell; 173 return cell;
179 } 174 }
180 175
181 public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 176 public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
182 - // Handle different item types with type checking 177 + // Handle only CouponSetItemModel and OfferModel - no campaigns
183 guard let data = self.data, 178 guard let data = self.data,
184 let items = data.items, 179 let items = data.items,
185 indexPath.row < items.count else { 180 indexPath.row < items.count else {
...@@ -187,60 +182,28 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl ...@@ -187,60 +182,28 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl
187 } 182 }
188 183
189 switch data.itemType { 184 switch data.itemType {
190 - case .campaigns:
191 - if let campaign = items[indexPath.row] as? CampaignItemModel {
192 - // For now, we'll need to convert CampaignItemModel to OfferModel for delegate compatibility
193 - // This maintains backward compatibility while using the new data structure
194 - let offer = OfferModel(
195 - category: campaign._category ?? "",
196 - title: campaign._title ?? "",
197 - description: campaign._subtitle ?? "",
198 - discount: "",
199 - discountType: "",
200 - bannerImage: campaign._banner_img_mobile ?? "",
201 - merchantLogo: campaign._logo_url ?? "",
202 - expirationDate: "",
203 - color: 0x000000,
204 - isFavorite: false
205 - )
206 - delegate?.didSelectOffer(offer)
207 - }
208 case .couponSets: 185 case .couponSets:
209 if let couponSet = items[indexPath.row] as? CouponSetItemModel { 186 if let couponSet = items[indexPath.row] as? CouponSetItemModel {
210 // Convert CouponSetItemModel to OfferModel for delegate compatibility 187 // Convert CouponSetItemModel to OfferModel for delegate compatibility
211 let offer = OfferModel( 188 let offer = OfferModel(
212 category: "", 189 category: "",
213 - title: couponSet._name ?? "", 190 + title: couponSet.name ?? "",
214 - description: couponSet._short_description ?? "", 191 + description: couponSet.short_description ?? "",
215 - discount: "", 192 + discount: couponSet.discount ?? "",
216 - discountType: "", 193 + discountType: couponSet.discount_type ?? "",
217 - bannerImage: "", 194 + bannerImage: couponSet.img_preview ?? "",
218 - merchantLogo: couponSet._img_preview ?? "", 195 + merchantLogo: couponSet.img?.first ?? "",
219 - expirationDate: "", 196 + expirationDate: couponSet.expiration ?? "",
220 color: 0x000000, 197 color: 0x000000,
221 isFavorite: false 198 isFavorite: false
222 ) 199 )
223 delegate?.didSelectOffer(offer) 200 delegate?.didSelectOffer(offer)
224 } 201 }
225 - case .coupons: 202 + default:
226 - if let coupon = items[indexPath.row] as? CouponItemModel { 203 + // Handle OfferModel directly for ProfileViewController compatibility
227 - // Convert CouponItemModel to OfferModel for delegate compatibility 204 + if let offer = items[indexPath.row] as? OfferModel {
228 - let offer = OfferModel(
229 - category: "",
230 - title: coupon._name ?? "",
231 - description: coupon._short_description ?? "",
232 - discount: "",
233 - discountType: "",
234 - bannerImage: "",
235 - merchantLogo: coupon._img_preview ?? "",
236 - expirationDate: "",
237 - color: 0x000000,
238 - isFavorite: false
239 - )
240 delegate?.didSelectOffer(offer) 205 delegate?.didSelectOffer(offer)
241 } 206 }
242 - default:
243 - break
244 } 207 }
245 } 208 }
246 209
......
...@@ -24,274 +24,15 @@ import UIKit ...@@ -24,274 +24,15 @@ import UIKit
24 super.init(coder: coder) 24 super.init(coder: coder)
25 } 25 }
26 26
27 - // MARK: - Dummy Data
28 - // match - survey - tesla - energy saver
29 - let allOffers: [OfferModel] = [
30 - // Banner Offers
31 - OfferModel(
32 - category: "Διαγωνισμός",
33 - title: "Διαγωνισμός Κού-πονς!",
34 - description: "13 Απίθανα ΔΩΡΑ σε περιμένουν!",
35 - discount: "",
36 - discountType: "contest",
37 - bannerImage: "contest_banner_2",
38 - merchantLogo: "contest_logo",
39 - expirationDate: "30/06/2025",
40 - color: 0x8A2BE2,
41 - isFavorite: false
42 - ),
43 - OfferModel(
44 - category: "Διαγωνισμός",
45 - title: "Διαγωνισμός Κού-πονς!",
46 - description: "13 Απίθανα ΔΩΡΑ σε περιμένουν!",
47 - discount: "",
48 - discountType: "contest",
49 - bannerImage: "contest_banner_3",
50 - merchantLogo: "contest_logo",
51 - expirationDate: "30/06/2025",
52 - color: 0x8A2BE2,
53 - isFavorite: false
54 - ),
55 - OfferModel(
56 - category: "Διαγωνισμός",
57 - title: "Διαγωνισμός Κού-πονς!",
58 - description: "13 Απίθανα ΔΩΡΑ σε περιμένουν!",
59 - discount: "",
60 - discountType: "contest",
61 - bannerImage: "contest_banner_4",
62 - merchantLogo: "contest_logo",
63 - expirationDate: "30/06/2025",
64 - color: 0x8A2BE2,
65 - isFavorite: false
66 - ),
67 - OfferModel(
68 - category: "Διαγωνισμός",
69 - title: "Διαγωνισμός Κού-πονς!",
70 - description: "13 Απίθανα ΔΩΡΑ σε περιμένουν!",
71 - discount: "",
72 - discountType: "contest",
73 - bannerImage: "contest_banner_1",
74 - merchantLogo: "contest_logo",
75 - expirationDate: "30/06/2025",
76 - color: 0x8A2BE2,
77 - isFavorite: false
78 - ),
79 - // Top offers
80 - OfferModel(
81 - category: "Top offers",
82 - title: "Μόνο 17.95",
83 - description: "2 πίτσες & Coca-COLA 1,5lt",
84 - discount: "17.95€",
85 - discountType: "price",
86 - bannerImage: "dominos_banner",
87 - merchantLogo: "dominos_logo",
88 - expirationDate: "έως 30-09",
89 - color: 0xEE417D,
90 - isFavorite: true
91 - ),
92 - OfferModel(
93 - category: "Top offers",
94 - title: "20% έκπτωση",
95 - description: "για όλες τις online αγορές σας",
96 - discount: "20%",
97 - discountType: "percentage",
98 - bannerImage: "dominos_banner",
99 - merchantLogo: "dominos_logo",
100 - expirationDate: "έως 30-09",
101 - color: 0xEE417D,
102 - isFavorite: false
103 - ),
104 -
105 - // Αγαπημένα
106 - // OfferModel(
107 - // category: "Αγαπημένα",
108 - // title: "15% έκπτωση",
109 - // description: "στην ενοικίαση αυτοκινήτου",
110 - // discount: "15%",
111 - // discountType: "percentage",
112 - // bannerImage: "car_rental_banner",
113 - // merchantLogo: "avis_logo",
114 - // expirationDate: "έως 30-09",
115 - // color: 0xEE417D,
116 - // isFavorite: true
117 - // ),
118 - // OfferModel(
119 - // category: "Αγαπημένα",
120 - // title: "20€ έως και",
121 - // description: "έκπτωση στα πακέτα",
122 - // discount: "20€",
123 - // discountType: "amount",
124 - // bannerImage: "hotel_banner",
125 - // merchantLogo: "booking_logo",
126 - // expirationDate: "έως 30-09",
127 - // color: 0xEE417D,
128 - // isFavorite: true
129 - // ),
130 -
131 - // Βιωσιμότητα
132 - OfferModel(
133 - category: "Βιωσιμότητα",
134 - title: "15% έκπτωση",
135 - description: "σε όλα τα προϊόντα",
136 - discount: "15%",
137 - discountType: "percentage",
138 - bannerImage: "musa_banner",
139 - merchantLogo: "musa_logo",
140 - expirationDate: "έως 30-09",
141 - color: 0x09914E,
142 - isFavorite: false
143 - ),
144 - OfferModel(
145 - category: "Βιωσιμότητα",
146 - title: "20% έκπτωση",
147 - description: "στην παραγγελία",
148 - discount: "20%",
149 - discountType: "percentage",
150 - bannerImage: "musa_banner",
151 - merchantLogo: "musa_logo",
152 - expirationDate: "έως 30-09",
153 - color: 0x09914E,
154 - isFavorite: true
155 - ),
156 -
157 - // Family
158 - OfferModel(
159 - category: "Family",
160 - title: "10% έκπτωση",
161 - description: "στην κατασκήνωση στο The Ranch",
162 - discount: "10%",
163 - discountType: "percentage",
164 - bannerImage: "ranch_banner",
165 - merchantLogo: "ranch_logo",
166 - expirationDate: "έως 30-09",
167 - color: 0xFC9F25,
168 - isFavorite: false
169 - ),
170 - OfferModel(
171 - category: "Family",
172 - title: "1+1 εισιτήριο",
173 - description: "δώρο στην είσοδο του παιδότοπου",
174 - discount: "1+1",
175 - discountType: "buyOneGetOne",
176 - bannerImage: "ranch_banner",
177 - merchantLogo: "ranch_logo",
178 - expirationDate: "έως 30-09",
179 - color: 0xFC9F25,
180 - isFavorite: false
181 - ),
182 -
183 - // Φαγητό και καφές
184 - OfferModel(
185 - category: "Φαγητό και καφές",
186 - title: "2€ έκπτωση",
187 - description: "στην αγορά σου",
188 - discount: "2€",
189 - discountType: "amount",
190 - bannerImage: "coffeeisland_banner",
191 - merchantLogo: "coffeeisland_logo",
192 - expirationDate: "έως 30-09",
193 - color: 0xEE417D,
194 - isFavorite: false
195 - ),
196 - OfferModel(
197 - category: "Φαγητό και καφές",
198 - title: "10% έκπτωση",
199 - description: "σε γλυκά & πεϊνιρλιδες",
200 - discount: "10%",
201 - discountType: "percentage",
202 - bannerImage: "coffeeisland_banner",
203 - merchantLogo: "coffeeisland_logo",
204 - expirationDate: "έως 30-09",
205 - color: 0xEE417D,
206 - isFavorite: false
207 - ),
208 -
209 - // Απόδραση
210 - OfferModel(
211 - category: "Απόδραση",
212 - title: "10% έκπτωση",
213 - description: "στην διαμονή/διασκέδαση σου",
214 - discount: "10%",
215 - discountType: "percentage",
216 - bannerImage: "ninemia_banner",
217 - merchantLogo: "ninemia_logo",
218 - expirationDate: "έως 30-09",
219 - color: 0xEE417D,
220 - isFavorite: true
221 - ),
222 - OfferModel(
223 - category: "Απόδραση",
224 - title: "10% έκπτωση",
225 - description: "σε όλες τις υπηρεσίες",
226 - discount: "10%",
227 - discountType: "percentage",
228 - bannerImage: "ninemia_banner",
229 - merchantLogo: "ninemia_logo",
230 - expirationDate: "έως 30-09",
231 - color: 0xEE417D,
232 - isFavorite: false
233 - ),
234 -
235 - // Παιδί
236 - OfferModel(
237 - category: "Παιδί",
238 - title: "10% έκπτωση",
239 - description: "για αγορές από τα φυσικά καταστήματα",
240 - discount: "10%",
241 - discountType: "percentage",
242 - bannerImage: "moustakas_banner",
243 - merchantLogo: "moustakas_logo",
244 - expirationDate: "έως 30-09",
245 - color: 0xEE417D,
246 - isFavorite: false
247 - ),
248 - OfferModel(
249 - category: "Παιδί",
250 - title: "1+1 Δώρο",
251 - description: "στην είσοδο του παιδότοπου",
252 - discount: "1+1",
253 - discountType: "buyOneGetOne",
254 - bannerImage: "moustakas_banner",
255 - merchantLogo: "moustakas_logo",
256 - expirationDate: "έως 30-09",
257 - color: 0xEE417D,
258 - isFavorite: false
259 - ),
260 -
261 - // Αγορές
262 - OfferModel(
263 - category: "Αγορές",
264 - title: "15€ έκπτωση",
265 - description: "για αγορές",
266 - discount: "15€",
267 - discountType: "amount",
268 - bannerImage: "migato_banner",
269 - merchantLogo: "migato_logo",
270 - expirationDate: "έως 30-09",
271 - color: 0xEE417D,
272 - isFavorite: false
273 - ),
274 - OfferModel(
275 - category: "Αγορές",
276 - title: "Έως 30% έκπτωση",
277 - description: "στις αγορές σου",
278 - discount: "30%",
279 - discountType: "percentage",
280 - bannerImage: "migato_banner",
281 - merchantLogo: "migato_logo",
282 - expirationDate: "έως 30-09",
283 - color: 0xEE417D,
284 - isFavorite: false
285 - )
286 - ]
287 27
288 // match - survey - tesla - energy saver 28 // match - survey - tesla - energy saver
289 - let contestUrls: [String] = [ 29 + // COMMENTED OUT: Static contest URLs no longer used
290 - "https://warply.s3.amazonaws.com/dei/campaigns/match_dev/index.html", 30 + // let contestUrls: [String] = [
291 - "https://warply.s3.amazonaws.com/dei/campaigns/questionnaire_dev/index.html", 31 + // "https://warply.s3.amazonaws.com/dei/campaigns/match_dev/index.html",
292 - "https://warply.s3.amazonaws.com/dei/campaigns/tesla_dev/index.html", 32 + // "https://warply.s3.amazonaws.com/dei/campaigns/questionnaire_dev/index.html",
293 - "https://warply.s3.amazonaws.com/dei/campaigns/EnergySaverContest_dev/index.html" 33 + // "https://warply.s3.amazonaws.com/dei/campaigns/tesla_dev/index.html",
294 - ] 34 + // "https://warply.s3.amazonaws.com/dei/campaigns/EnergySaverContest_dev/index.html"
35 + // ]
295 36
296 // Dynamic sections array - populated by API calls 37 // Dynamic sections array - populated by API calls
297 var sections: [SectionModel] = [] 38 var sections: [SectionModel] = []
...@@ -352,83 +93,6 @@ import UIKit ...@@ -352,83 +93,6 @@ import UIKit
352 } 93 }
353 94
354 95
355 - // MARK: Function
356 - func initializeSections() {
357 - // Banner Offers (for the promotional banner at the top)
358 - let bannerOffers = allOffers.filter { $0.category == "Διαγωνισμός" }
359 - bannerOffersSection = SectionModel(
360 - title: "Διαγωνισμός",
361 - count: bannerOffers.count,
362 - offers: bannerOffers
363 - )
364 -
365 - // Top Offers
366 - let topOffers = allOffers.filter { $0.category == "Top offers" }
367 - topOffersSection = SectionModel(
368 - title: "Top offers",
369 - count: topOffers.count,
370 - offers: topOffers
371 - )
372 -
373 - // Favorite Offers
374 - let favoriteOffers = allOffers.filter { $0.isFavorite }
375 - favoriteOffersSection = SectionModel(
376 - title: "Αγαπημένα",
377 - count: favoriteOffers.count,
378 - offers: favoriteOffers
379 - )
380 -
381 - // Sustainable Offers
382 - let sustainableOffers = allOffers.filter { $0.category == "Βιωσιμότητα" }
383 - sustainableOffersSection = SectionModel(
384 - title: "Βιωσιμότητα",
385 - count: sustainableOffers.count,
386 - offers: sustainableOffers
387 - )
388 -
389 - // Family Offers
390 - let familyOffers = allOffers.filter { $0.category == "Family" }
391 - familyOffersSection = SectionModel(
392 - title: "Family",
393 - count: familyOffers.count,
394 - offers: familyOffers
395 - )
396 -
397 - // Food Offers
398 - let foodOffers = allOffers.filter { $0.category == "Φαγητό και καφές" }
399 - foodOffersSection = SectionModel(
400 - title: "Φαγητό και καφές",
401 - count: foodOffers.count,
402 - offers: foodOffers
403 - )
404 -
405 - // Escape Offers
406 - let escapeOffers = allOffers.filter { $0.category == "Απόδραση" }
407 - escapeOffersSection = SectionModel(
408 - title: "Απόδραση",
409 - count: escapeOffers.count,
410 - offers: escapeOffers
411 - )
412 -
413 - // Child Offers
414 - let childOffers = allOffers.filter { $0.category == "Παιδί" }
415 - childOffersSection = SectionModel(
416 - title: "Παιδί",
417 - count: childOffers.count,
418 - offers: childOffers
419 - )
420 -
421 - // Shopping Offers
422 - let shoppingOffers = allOffers.filter { $0.category == "Αγορές" }
423 - shoppingOffersSection = SectionModel(
424 - title: "Αγορές",
425 - count: shoppingOffers.count,
426 - offers: shoppingOffers
427 - )
428 -
429 - self.tableView.reloadData()
430 - }
431 -
432 // MARK: - Campaign Loading 96 // MARK: - Campaign Loading
433 private func loadCampaigns() { 97 private func loadCampaigns() {
434 // Load campaigns from WarplySDK 98 // Load campaigns from WarplySDK
...@@ -463,18 +127,24 @@ import UIKit ...@@ -463,18 +127,24 @@ import UIKit
463 } 127 }
464 128
465 private func openCampaignViewController(with index: Int) { 129 private func openCampaignViewController(with index: Int) {
466 - let vc = SwiftWarplyFramework.CampaignViewController(nibName: "CampaignViewController", bundle: Bundle.frameworkBundle) 130 + // Validate index bounds
131 + guard index < bannerCampaigns.count else {
132 + print("Invalid campaign index: \(index)")
133 + return
134 + }
467 135
468 - // Use real campaign URL if available, otherwise fallback to static URLs
469 - if index < bannerCampaigns.count {
470 - // Use campaign URL from real campaign data
471 let campaign = bannerCampaigns[index] 136 let campaign = bannerCampaigns[index]
472 - vc.campaignUrl = campaign._campaign_url ?? campaign.index_url ?? contestUrls[min(index, contestUrls.count - 1)] 137 + let campaignUrl = campaign._campaign_url ?? campaign.index_url
473 - } else { 138 +
474 - // Fallback to static contest URLs 139 + // Check if URL is not empty before proceeding
475 - vc.campaignUrl = contestUrls[min(index, contestUrls.count - 1)] 140 + guard let url = campaignUrl, !url.isEmpty else {
141 + print("Campaign URL is empty, cannot open CampaignViewController for campaign: \(campaign._title ?? "Unknown")")
142 + return
476 } 143 }
477 144
145 + // Proceed with navigation only if we have a valid URL
146 + let vc = SwiftWarplyFramework.CampaignViewController(nibName: "CampaignViewController", bundle: Bundle.frameworkBundle)
147 + vc.campaignUrl = url
478 vc.showHeader = false 148 vc.showHeader = false
479 self.navigationController?.pushViewController(vc, animated: true) 149 self.navigationController?.pushViewController(vc, animated: true)
480 } 150 }
......
...@@ -247,16 +247,16 @@ import UIKit ...@@ -247,16 +247,16 @@ import UIKit
247 let forYouOffers = allOffers.filter { $0.category == "Προτάσεις για εσένα" } 247 let forYouOffers = allOffers.filter { $0.category == "Προτάσεις για εσένα" }
248 forYouOffersSection = SectionModel( 248 forYouOffersSection = SectionModel(
249 title: "Προτάσεις για εσένα", 249 title: "Προτάσεις για εσένα",
250 - count: forYouOffers.count, 250 + items: forYouOffers,
251 - offers: forYouOffers 251 + itemType: .offers
252 ) 252 )
253 253
254 - // Favorite Offers 254 + // Active Offers
255 let activeOffers = allOffers.filter { $0.active ?? false } 255 let activeOffers = allOffers.filter { $0.active ?? false }
256 activeOffersSection = SectionModel( 256 activeOffersSection = SectionModel(
257 title: "Ενεργά", 257 title: "Ενεργά",
258 - count: activeOffers.count, 258 + items: activeOffers,
259 - offers: activeOffers 259 + itemType: .offers
260 ) 260 )
261 261
262 filteredOffersSection = activeOffersSection 262 filteredOffersSection = activeOffersSection
...@@ -265,16 +265,16 @@ import UIKit ...@@ -265,16 +265,16 @@ import UIKit
265 let favoriteOffers = allOffers.filter { $0.isFavorite } 265 let favoriteOffers = allOffers.filter { $0.isFavorite }
266 favoriteOffersSection = SectionModel( 266 favoriteOffersSection = SectionModel(
267 title: "Αγαπημένα", 267 title: "Αγαπημένα",
268 - count: favoriteOffers.count, 268 + items: favoriteOffers,
269 - offers: favoriteOffers 269 + itemType: .offers
270 ) 270 )
271 271
272 - // Favorite Offers 272 + // Redeemed Offers
273 let redeemedOffers = allOffers.filter { $0.redeemed ?? false } 273 let redeemedOffers = allOffers.filter { $0.redeemed ?? false }
274 redeemedOffersSection = SectionModel( 274 redeemedOffersSection = SectionModel(
275 title: "Εξαργυρωμένα", 275 title: "Εξαργυρωμένα",
276 - count: redeemedOffers.count, 276 + items: redeemedOffers,
277 - offers: redeemedOffers 277 + itemType: .offers
278 ) 278 )
279 279
280 self.tableView.reloadData() 280 self.tableView.reloadData()
...@@ -314,7 +314,7 @@ extension ProfileViewController: UITableViewDelegate, UITableViewDataSource { ...@@ -314,7 +314,7 @@ extension ProfileViewController: UITableViewDelegate, UITableViewDataSource {
314 if (section <= 3) { 314 if (section <= 3) {
315 return 1 315 return 1
316 } else { 316 } else {
317 - return filteredOffersSection?.offers.count ?? 0 317 + return filteredOffersSection?.itemCount ?? 0
318 } 318 }
319 } 319 }
320 320
...@@ -383,7 +383,9 @@ extension ProfileViewController: UITableViewDelegate, UITableViewDataSource { ...@@ -383,7 +383,9 @@ extension ProfileViewController: UITableViewDelegate, UITableViewDataSource {
383 383
384 } else { 384 } else {
385 let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileCouponTableViewCell", for: indexPath) as! ProfileCouponTableViewCell 385 let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileCouponTableViewCell", for: indexPath) as! ProfileCouponTableViewCell
386 - if let offer = self.filteredOffersSection?.offers[indexPath.row] { 386 + if let items = self.filteredOffersSection?.items,
387 + indexPath.row < items.count,
388 + let offer = items[indexPath.row] as? OfferModel {
387 cell.configureCell(data: offer) 389 cell.configureCell(data: offer)
388 } 390 }
389 return cell 391 return cell
...@@ -395,7 +397,9 @@ extension ProfileViewController: UITableViewDelegate, UITableViewDataSource { ...@@ -395,7 +397,9 @@ extension ProfileViewController: UITableViewDelegate, UITableViewDataSource {
395 if (indexPath.section <= 3) { 397 if (indexPath.section <= 3) {
396 // Do nothing 398 // Do nothing
397 } else { 399 } else {
398 - if let offer = self.filteredOffersSection?.offers[indexPath.row] { 400 + if let items = self.filteredOffersSection?.items,
401 + indexPath.row < items.count,
402 + let offer = items[indexPath.row] as? OfferModel {
399 openCouponViewController(with: offer) 403 openCouponViewController(with: offer)
400 } 404 }
401 } 405 }
......