Manos Chorianopoulos

MyRewardsVC fixes

......@@ -121,23 +121,15 @@ extension MyRewardsBannerOffersScrollTableViewCell: UICollectionViewDataSource,
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyRewardsBannerOfferCollectionViewCell", for: indexPath) as! MyRewardsBannerOfferCollectionViewCell
// Handle different item types
// Handle only CampaignItemModel - banner cells are campaign-specific
guard let data = self.data,
let itemType = data.itemType,
let items = data.items,
indexPath.row < items.count else {
indexPath.row < items.count,
let campaign = items[indexPath.row] as? CampaignItemModel else {
return cell
}
switch itemType {
case .campaigns:
if let campaign = items[indexPath.row] as? CampaignItemModel {
cell.configureCell(data: campaign)
}
default:
// Handle other types if needed in the future
break
}
cell.configureCell(data: campaign)
return cell
}
......
......@@ -65,49 +65,6 @@ public class MyRewardsOfferCollectionViewCell: UICollectionViewCell {
logoImage.image = UIImage(named: data.merchantLogo, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
}
// MARK: - New configureCell methods for different data types
func configureCell(data: CampaignItemModel) {
// Use campaign's banner image if available
let imageName = data._banner_img_mobile ?? ""
if !imageName.isEmpty {
bannerImage.image = UIImage(named: imageName, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
} else {
bannerImage.image = nil
}
// Default to not favorite for campaigns
favoriteImage.image = UIImage(named: "favorite_empty", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
// Use campaign category or type for discount display
discountLabel.text = data._category ?? data._campaign_type ?? ""
discountLabel.font = UIFont(name: "PingLCG-Bold", size: 17)
discountLabel.textColor = UIColor(rgb: 0xF2F2F2)
// Default color for campaigns
discountView.backgroundColor = UIColor(rgb: 0xEE417D)
titleLabel.text = data._title ?? ""
titleLabel.font = UIFont(name: "PingLCG-Bold", size: 17)
titleLabel.textColor = UIColor(rgb: 0x000F1E)
subtitleLabel.text = data._subtitle ?? ""
subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 14)
subtitleLabel.textColor = UIColor(rgb: 0x00111B)
// Use campaign expiration date
expirationLabel.text = data._valid_until ?? ""
expirationLabel.font = UIFont(name: "PingLCG-Regular", size: 13)
expirationLabel.textColor = UIColor(rgb: 0x00111B)
// Use campaign logo
let logoName = data._logo_url ?? ""
if !logoName.isEmpty {
logoImage.image = UIImage(named: logoName, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
} else {
logoImage.image = nil
}
}
func configureCell(data: CouponSetItemModel) {
// Use coupon set preview image
......@@ -166,60 +123,4 @@ public class MyRewardsOfferCollectionViewCell: UICollectionViewCell {
}
}
func configureCell(data: CouponItemModel) {
// Use coupon image
let imageName = data.image ?? ""
if !imageName.isEmpty {
bannerImage.image = UIImage(named: imageName, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
} else {
bannerImage.image = nil
}
// Default to not favorite for coupons
favoriteImage.image = UIImage(named: "favorite_empty", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
// Use coupon discount
discountLabel.text = data.discount ?? ""
discountLabel.font = UIFont(name: "PingLCG-Bold", size: 17)
discountLabel.textColor = UIColor(rgb: 0xF2F2F2)
// Color based on coupon status
let statusColor: UInt = {
switch data.status {
case 1:
return 0x28A745 // Active - green
case 0:
return 0x6C757D // Used - gray
default:
return 0x007AFF // Default - blue
}
}()
discountView.backgroundColor = UIColor(rgb: statusColor)
titleLabel.text = data.name ?? ""
titleLabel.font = UIFont(name: "PingLCG-Bold", size: 17)
titleLabel.textColor = UIColor(rgb: 0x000F1E)
subtitleLabel.text = data.short_description ?? ""
subtitleLabel.font = UIFont(name: "PingLCG-Regular", size: 14)
subtitleLabel.textColor = UIColor(rgb: 0x00111B)
expirationLabel.text = data.expiration ?? ""
expirationLabel.font = UIFont(name: "PingLCG-Regular", size: 13)
expirationLabel.textColor = UIColor(rgb: 0x00111B)
// Use coupon set data image if available
if let couponSetData = data.couponset_data,
let imgArray = couponSetData.img,
!imgArray.isEmpty {
let logoName = imgArray[0]
if !logoName.isEmpty {
logoImage.image = UIImage(named: logoName, in: Bundle.frameworkResourceBundle, compatibleWith: nil)
} else {
logoImage.image = nil
}
} else {
logoImage.image = nil
}
}
}
......
......@@ -151,7 +151,7 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyRewardsOfferCollectionViewCell", for: indexPath) as! MyRewardsOfferCollectionViewCell
// Handle different item types with type checking
// Handle only CouponSetItemModel and OfferModel - no campaigns
guard let data = self.data,
let items = data.items,
indexPath.row < items.count else {
......@@ -159,27 +159,22 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl
}
switch data.itemType {
case .campaigns:
if let campaign = items[indexPath.row] as? CampaignItemModel {
cell.configureCell(data: campaign)
}
case .couponSets:
if let couponSet = items[indexPath.row] as? CouponSetItemModel {
cell.configureCell(data: couponSet)
}
case .coupons:
if let coupon = items[indexPath.row] as? CouponItemModel {
cell.configureCell(data: coupon)
}
default:
break
// Handle OfferModel for ProfileViewController compatibility
if let offer = items[indexPath.row] as? OfferModel {
cell.configureCell(data: offer)
}
}
return cell;
}
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// Handle different item types with type checking
// Handle only CouponSetItemModel and OfferModel - no campaigns
guard let data = self.data,
let items = data.items,
indexPath.row < items.count else {
......@@ -187,60 +182,28 @@ extension MyRewardsOffersScrollTableViewCell: UICollectionViewDataSource, UIColl
}
switch data.itemType {
case .campaigns:
if let campaign = items[indexPath.row] as? CampaignItemModel {
// For now, we'll need to convert CampaignItemModel to OfferModel for delegate compatibility
// This maintains backward compatibility while using the new data structure
let offer = OfferModel(
category: campaign._category ?? "",
title: campaign._title ?? "",
description: campaign._subtitle ?? "",
discount: "",
discountType: "",
bannerImage: campaign._banner_img_mobile ?? "",
merchantLogo: campaign._logo_url ?? "",
expirationDate: "",
color: 0x000000,
isFavorite: false
)
delegate?.didSelectOffer(offer)
}
case .couponSets:
if let couponSet = items[indexPath.row] as? CouponSetItemModel {
// Convert CouponSetItemModel to OfferModel for delegate compatibility
let offer = OfferModel(
category: "",
title: couponSet._name ?? "",
description: couponSet._short_description ?? "",
discount: "",
discountType: "",
bannerImage: "",
merchantLogo: couponSet._img_preview ?? "",
expirationDate: "",
title: couponSet.name ?? "",
description: couponSet.short_description ?? "",
discount: couponSet.discount ?? "",
discountType: couponSet.discount_type ?? "",
bannerImage: couponSet.img_preview ?? "",
merchantLogo: couponSet.img?.first ?? "",
expirationDate: couponSet.expiration ?? "",
color: 0x000000,
isFavorite: false
)
delegate?.didSelectOffer(offer)
}
case .coupons:
if let coupon = items[indexPath.row] as? CouponItemModel {
// Convert CouponItemModel to OfferModel for delegate compatibility
let offer = OfferModel(
category: "",
title: coupon._name ?? "",
description: coupon._short_description ?? "",
discount: "",
discountType: "",
bannerImage: "",
merchantLogo: coupon._img_preview ?? "",
expirationDate: "",
color: 0x000000,
isFavorite: false
)
default:
// Handle OfferModel directly for ProfileViewController compatibility
if let offer = items[indexPath.row] as? OfferModel {
delegate?.didSelectOffer(offer)
}
default:
break
}
}
......
......@@ -24,274 +24,15 @@ import UIKit
super.init(coder: coder)
}
// MARK: - Dummy Data
// match - survey - tesla - energy saver
let allOffers: [OfferModel] = [
// Banner Offers
OfferModel(
category: "Διαγωνισμός",
title: "Διαγωνισμός Κού-πονς!",
description: "13 Απίθανα ΔΩΡΑ σε περιμένουν!",
discount: "",
discountType: "contest",
bannerImage: "contest_banner_2",
merchantLogo: "contest_logo",
expirationDate: "30/06/2025",
color: 0x8A2BE2,
isFavorite: false
),
OfferModel(
category: "Διαγωνισμός",
title: "Διαγωνισμός Κού-πονς!",
description: "13 Απίθανα ΔΩΡΑ σε περιμένουν!",
discount: "",
discountType: "contest",
bannerImage: "contest_banner_3",
merchantLogo: "contest_logo",
expirationDate: "30/06/2025",
color: 0x8A2BE2,
isFavorite: false
),
OfferModel(
category: "Διαγωνισμός",
title: "Διαγωνισμός Κού-πονς!",
description: "13 Απίθανα ΔΩΡΑ σε περιμένουν!",
discount: "",
discountType: "contest",
bannerImage: "contest_banner_4",
merchantLogo: "contest_logo",
expirationDate: "30/06/2025",
color: 0x8A2BE2,
isFavorite: false
),
OfferModel(
category: "Διαγωνισμός",
title: "Διαγωνισμός Κού-πονς!",
description: "13 Απίθανα ΔΩΡΑ σε περιμένουν!",
discount: "",
discountType: "contest",
bannerImage: "contest_banner_1",
merchantLogo: "contest_logo",
expirationDate: "30/06/2025",
color: 0x8A2BE2,
isFavorite: false
),
// Top offers
OfferModel(
category: "Top offers",
title: "Μόνο 17.95",
description: "2 πίτσες & Coca-COLA 1,5lt",
discount: "17.95€",
discountType: "price",
bannerImage: "dominos_banner",
merchantLogo: "dominos_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: true
),
OfferModel(
category: "Top offers",
title: "20% έκπτωση",
description: "για όλες τις online αγορές σας",
discount: "20%",
discountType: "percentage",
bannerImage: "dominos_banner",
merchantLogo: "dominos_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: false
),
// Αγαπημένα
// OfferModel(
// category: "Αγαπημένα",
// title: "15% έκπτωση",
// description: "στην ενοικίαση αυτοκινήτου",
// discount: "15%",
// discountType: "percentage",
// bannerImage: "car_rental_banner",
// merchantLogo: "avis_logo",
// expirationDate: "έως 30-09",
// color: 0xEE417D,
// isFavorite: true
// ),
// OfferModel(
// category: "Αγαπημένα",
// title: "20€ έως και",
// description: "έκπτωση στα πακέτα",
// discount: "20€",
// discountType: "amount",
// bannerImage: "hotel_banner",
// merchantLogo: "booking_logo",
// expirationDate: "έως 30-09",
// color: 0xEE417D,
// isFavorite: true
// ),
// Βιωσιμότητα
OfferModel(
category: "Βιωσιμότητα",
title: "15% έκπτωση",
description: "σε όλα τα προϊόντα",
discount: "15%",
discountType: "percentage",
bannerImage: "musa_banner",
merchantLogo: "musa_logo",
expirationDate: "έως 30-09",
color: 0x09914E,
isFavorite: false
),
OfferModel(
category: "Βιωσιμότητα",
title: "20% έκπτωση",
description: "στην παραγγελία",
discount: "20%",
discountType: "percentage",
bannerImage: "musa_banner",
merchantLogo: "musa_logo",
expirationDate: "έως 30-09",
color: 0x09914E,
isFavorite: true
),
// Family
OfferModel(
category: "Family",
title: "10% έκπτωση",
description: "στην κατασκήνωση στο The Ranch",
discount: "10%",
discountType: "percentage",
bannerImage: "ranch_banner",
merchantLogo: "ranch_logo",
expirationDate: "έως 30-09",
color: 0xFC9F25,
isFavorite: false
),
OfferModel(
category: "Family",
title: "1+1 εισιτήριο",
description: "δώρο στην είσοδο του παιδότοπου",
discount: "1+1",
discountType: "buyOneGetOne",
bannerImage: "ranch_banner",
merchantLogo: "ranch_logo",
expirationDate: "έως 30-09",
color: 0xFC9F25,
isFavorite: false
),
// Φαγητό και καφές
OfferModel(
category: "Φαγητό και καφές",
title: "2€ έκπτωση",
description: "στην αγορά σου",
discount: "2€",
discountType: "amount",
bannerImage: "coffeeisland_banner",
merchantLogo: "coffeeisland_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: false
),
OfferModel(
category: "Φαγητό και καφές",
title: "10% έκπτωση",
description: "σε γλυκά & πεϊνιρλιδες",
discount: "10%",
discountType: "percentage",
bannerImage: "coffeeisland_banner",
merchantLogo: "coffeeisland_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: false
),
// Απόδραση
OfferModel(
category: "Απόδραση",
title: "10% έκπτωση",
description: "στην διαμονή/διασκέδαση σου",
discount: "10%",
discountType: "percentage",
bannerImage: "ninemia_banner",
merchantLogo: "ninemia_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: true
),
OfferModel(
category: "Απόδραση",
title: "10% έκπτωση",
description: "σε όλες τις υπηρεσίες",
discount: "10%",
discountType: "percentage",
bannerImage: "ninemia_banner",
merchantLogo: "ninemia_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: false
),
// Παιδί
OfferModel(
category: "Παιδί",
title: "10% έκπτωση",
description: "για αγορές από τα φυσικά καταστήματα",
discount: "10%",
discountType: "percentage",
bannerImage: "moustakas_banner",
merchantLogo: "moustakas_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: false
),
OfferModel(
category: "Παιδί",
title: "1+1 Δώρο",
description: "στην είσοδο του παιδότοπου",
discount: "1+1",
discountType: "buyOneGetOne",
bannerImage: "moustakas_banner",
merchantLogo: "moustakas_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: false
),
// Αγορές
OfferModel(
category: "Αγορές",
title: "15€ έκπτωση",
description: "για αγορές",
discount: "15€",
discountType: "amount",
bannerImage: "migato_banner",
merchantLogo: "migato_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: false
),
OfferModel(
category: "Αγορές",
title: "Έως 30% έκπτωση",
description: "στις αγορές σου",
discount: "30%",
discountType: "percentage",
bannerImage: "migato_banner",
merchantLogo: "migato_logo",
expirationDate: "έως 30-09",
color: 0xEE417D,
isFavorite: false
)
]
// match - survey - tesla - energy saver
let contestUrls: [String] = [
"https://warply.s3.amazonaws.com/dei/campaigns/match_dev/index.html",
"https://warply.s3.amazonaws.com/dei/campaigns/questionnaire_dev/index.html",
"https://warply.s3.amazonaws.com/dei/campaigns/tesla_dev/index.html",
"https://warply.s3.amazonaws.com/dei/campaigns/EnergySaverContest_dev/index.html"
]
// COMMENTED OUT: Static contest URLs no longer used
// let contestUrls: [String] = [
// "https://warply.s3.amazonaws.com/dei/campaigns/match_dev/index.html",
// "https://warply.s3.amazonaws.com/dei/campaigns/questionnaire_dev/index.html",
// "https://warply.s3.amazonaws.com/dei/campaigns/tesla_dev/index.html",
// "https://warply.s3.amazonaws.com/dei/campaigns/EnergySaverContest_dev/index.html"
// ]
// Dynamic sections array - populated by API calls
var sections: [SectionModel] = []
......@@ -352,83 +93,6 @@ import UIKit
}
// MARK: Function
func initializeSections() {
// Banner Offers (for the promotional banner at the top)
let bannerOffers = allOffers.filter { $0.category == "Διαγωνισμός" }
bannerOffersSection = SectionModel(
title: "Διαγωνισμός",
count: bannerOffers.count,
offers: bannerOffers
)
// Top Offers
let topOffers = allOffers.filter { $0.category == "Top offers" }
topOffersSection = SectionModel(
title: "Top offers",
count: topOffers.count,
offers: topOffers
)
// Favorite Offers
let favoriteOffers = allOffers.filter { $0.isFavorite }
favoriteOffersSection = SectionModel(
title: "Αγαπημένα",
count: favoriteOffers.count,
offers: favoriteOffers
)
// Sustainable Offers
let sustainableOffers = allOffers.filter { $0.category == "Βιωσιμότητα" }
sustainableOffersSection = SectionModel(
title: "Βιωσιμότητα",
count: sustainableOffers.count,
offers: sustainableOffers
)
// Family Offers
let familyOffers = allOffers.filter { $0.category == "Family" }
familyOffersSection = SectionModel(
title: "Family",
count: familyOffers.count,
offers: familyOffers
)
// Food Offers
let foodOffers = allOffers.filter { $0.category == "Φαγητό και καφές" }
foodOffersSection = SectionModel(
title: "Φαγητό και καφές",
count: foodOffers.count,
offers: foodOffers
)
// Escape Offers
let escapeOffers = allOffers.filter { $0.category == "Απόδραση" }
escapeOffersSection = SectionModel(
title: "Απόδραση",
count: escapeOffers.count,
offers: escapeOffers
)
// Child Offers
let childOffers = allOffers.filter { $0.category == "Παιδί" }
childOffersSection = SectionModel(
title: "Παιδί",
count: childOffers.count,
offers: childOffers
)
// Shopping Offers
let shoppingOffers = allOffers.filter { $0.category == "Αγορές" }
shoppingOffersSection = SectionModel(
title: "Αγορές",
count: shoppingOffers.count,
offers: shoppingOffers
)
self.tableView.reloadData()
}
// MARK: - Campaign Loading
private func loadCampaigns() {
// Load campaigns from WarplySDK
......@@ -463,18 +127,24 @@ import UIKit
}
private func openCampaignViewController(with index: Int) {
let vc = SwiftWarplyFramework.CampaignViewController(nibName: "CampaignViewController", bundle: Bundle.frameworkBundle)
// Validate index bounds
guard index < bannerCampaigns.count else {
print("Invalid campaign index: \(index)")
return
}
// Use real campaign URL if available, otherwise fallback to static URLs
if index < bannerCampaigns.count {
// Use campaign URL from real campaign data
let campaign = bannerCampaigns[index]
vc.campaignUrl = campaign._campaign_url ?? campaign.index_url ?? contestUrls[min(index, contestUrls.count - 1)]
} else {
// Fallback to static contest URLs
vc.campaignUrl = contestUrls[min(index, contestUrls.count - 1)]
let campaign = bannerCampaigns[index]
let campaignUrl = campaign._campaign_url ?? campaign.index_url
// Check if URL is not empty before proceeding
guard let url = campaignUrl, !url.isEmpty else {
print("Campaign URL is empty, cannot open CampaignViewController for campaign: \(campaign._title ?? "Unknown")")
return
}
// Proceed with navigation only if we have a valid URL
let vc = SwiftWarplyFramework.CampaignViewController(nibName: "CampaignViewController", bundle: Bundle.frameworkBundle)
vc.campaignUrl = url
vc.showHeader = false
self.navigationController?.pushViewController(vc, animated: true)
}
......
......@@ -247,16 +247,16 @@ import UIKit
let forYouOffers = allOffers.filter { $0.category == "Προτάσεις για εσένα" }
forYouOffersSection = SectionModel(
title: "Προτάσεις για εσένα",
count: forYouOffers.count,
offers: forYouOffers
items: forYouOffers,
itemType: .offers
)
// Favorite Offers
// Active Offers
let activeOffers = allOffers.filter { $0.active ?? false }
activeOffersSection = SectionModel(
title: "Ενεργά",
count: activeOffers.count,
offers: activeOffers
items: activeOffers,
itemType: .offers
)
filteredOffersSection = activeOffersSection
......@@ -265,16 +265,16 @@ import UIKit
let favoriteOffers = allOffers.filter { $0.isFavorite }
favoriteOffersSection = SectionModel(
title: "Αγαπημένα",
count: favoriteOffers.count,
offers: favoriteOffers
items: favoriteOffers,
itemType: .offers
)
// Favorite Offers
// Redeemed Offers
let redeemedOffers = allOffers.filter { $0.redeemed ?? false }
redeemedOffersSection = SectionModel(
title: "Εξαργυρωμένα",
count: redeemedOffers.count,
offers: redeemedOffers
items: redeemedOffers,
itemType: .offers
)
self.tableView.reloadData()
......@@ -314,7 +314,7 @@ extension ProfileViewController: UITableViewDelegate, UITableViewDataSource {
if (section <= 3) {
return 1
} else {
return filteredOffersSection?.offers.count ?? 0
return filteredOffersSection?.itemCount ?? 0
}
}
......@@ -383,7 +383,9 @@ extension ProfileViewController: UITableViewDelegate, UITableViewDataSource {
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileCouponTableViewCell", for: indexPath) as! ProfileCouponTableViewCell
if let offer = self.filteredOffersSection?.offers[indexPath.row] {
if let items = self.filteredOffersSection?.items,
indexPath.row < items.count,
let offer = items[indexPath.row] as? OfferModel {
cell.configureCell(data: offer)
}
return cell
......@@ -395,7 +397,9 @@ extension ProfileViewController: UITableViewDelegate, UITableViewDataSource {
if (indexPath.section <= 3) {
// Do nothing
} else {
if let offer = self.filteredOffersSection?.offers[indexPath.row] {
if let items = self.filteredOffersSection?.items,
indexPath.row < items.count,
let offer = items[indexPath.row] as? OfferModel {
openCouponViewController(with: offer)
}
}
......