Manos Chorianopoulos

new getCouponFilters request and MyRewardsViewController sections handling

...@@ -438,6 +438,7 @@ private final class SDKState { ...@@ -438,6 +438,7 @@ private final class SDKState {
438 var carouselList: [CampaignItemModel] = [] 438 var carouselList: [CampaignItemModel] = []
439 var marketPassDetails: MarketPassDetailsModel? 439 var marketPassDetails: MarketPassDetailsModel?
440 var supermarketCampaign: CampaignItemModel? 440 var supermarketCampaign: CampaignItemModel?
441 + var couponFilters: CouponFiltersDataModel?
441 442
442 private init() {} 443 private init() {}
443 } 444 }
...@@ -2545,6 +2546,77 @@ public final class WarplySDK { ...@@ -2545,6 +2546,77 @@ public final class WarplySDK {
2545 } 2546 }
2546 } 2547 }
2547 2548
2549 + /// Get coupon filters via new endpoint
2550 + /// - Parameters:
2551 + /// - language: Optional language code (defaults to applicationLocale)
2552 + /// - completion: Returns the raw response dictionary on success
2553 + /// - failureCallback: Returns error code on failure
2554 + public func getCouponFilters(
2555 + language: String? = nil,
2556 + completion: @escaping (CouponFiltersDataModel?) -> Void,
2557 + failureCallback: @escaping (Int) -> Void
2558 + ) {
2559 + let finalLanguage = language ?? self.applicationLocale
2560 +
2561 + Task {
2562 + do {
2563 + let endpoint = Endpoint.getCouponFilters(language: finalLanguage)
2564 + let response = try await networkService.requestRaw(endpoint)
2565 +
2566 + await MainActor.run {
2567 + print("📥 getCouponFilters response: \(response)")
2568 +
2569 + let dynatraceEvent = LoyaltySDKDynatraceEventModel()
2570 + dynatraceEvent._eventName = "custom_success_couponfilters_loyalty"
2571 + dynatraceEvent._parameters = nil
2572 + self.postFrameworkEvent("dynatrace", sender: dynatraceEvent)
2573 +
2574 + if let resultData = response["result"] as? [String: Any] {
2575 + let filterModel = CouponFiltersDataModel(dictionary: resultData)
2576 + self.setCouponFilters(filterModel)
2577 + completion(filterModel)
2578 + } else {
2579 + completion(nil)
2580 + }
2581 + }
2582 + } catch {
2583 + await MainActor.run {
2584 + let dynatraceEvent = LoyaltySDKDynatraceEventModel()
2585 + dynatraceEvent._eventName = "custom_error_couponfilters_loyalty"
2586 + dynatraceEvent._parameters = nil
2587 + self.postFrameworkEvent("dynatrace", sender: dynatraceEvent)
2588 +
2589 + if let networkError = error as? NetworkError {
2590 + failureCallback(networkError.code)
2591 + } else {
2592 + failureCallback(-1)
2593 + }
2594 + }
2595 + }
2596 + }
2597 + }
2598 +
2599 + /// Get coupon filters (async/await variant)
2600 + /// - Parameters:
2601 + /// - language: Language code for localized content (optional, defaults to applicationLocale)
2602 + /// - Returns: Parsed filters model
2603 + /// - Throws: WarplyError if the request fails
2604 + public func getCouponFilters(
2605 + language: String? = nil
2606 + ) async throws -> CouponFiltersDataModel {
2607 + return try await withCheckedThrowingContinuation { continuation in
2608 + getCouponFilters(language: language, completion: { response in
2609 + if let response = response {
2610 + continuation.resume(returning: response)
2611 + } else {
2612 + continuation.resume(throwing: WarplyError.networkError)
2613 + }
2614 + }, failureCallback: { errorCode in
2615 + continuation.resume(throwing: WarplyError.unknownError(errorCode))
2616 + })
2617 + }
2618 + }
2619 +
2548 /// Get available coupons (async/await variant) 2620 /// Get available coupons (async/await variant)
2549 /// - Returns: Dictionary of coupon availability data 2621 /// - Returns: Dictionary of coupon availability data
2550 /// - Throws: WarplyError if the request fails 2622 /// - Throws: WarplyError if the request fails
...@@ -4344,6 +4416,16 @@ public final class WarplySDK { ...@@ -4344,6 +4416,16 @@ public final class WarplySDK {
4344 return state.couponSets 4416 return state.couponSets
4345 } 4417 }
4346 4418
4419 + /// Set coupon filters data
4420 + public func setCouponFilters(_ filters: CouponFiltersDataModel) {
4421 + state.couponFilters = filters
4422 + }
4423 +
4424 + /// Get coupon filters data
4425 + public func getCouponFilters() -> CouponFiltersDataModel? {
4426 + return state.couponFilters
4427 + }
4428 +
4347 /// Set seasonal list 4429 /// Set seasonal list
4348 public func setSeasonalList(_ seasonalCoupons: [LoyaltyGiftsForYouPackage]) { 4430 public func setSeasonalList(_ seasonalCoupons: [LoyaltyGiftsForYouPackage]) {
4349 state.seasonalList = seasonalCoupons 4431 state.seasonalList = seasonalCoupons
......
...@@ -68,6 +68,7 @@ public enum Endpoint { ...@@ -68,6 +68,7 @@ public enum Endpoint {
68 case getCoupons(language: String, couponsetType: String) 68 case getCoupons(language: String, couponsetType: String)
69 case getCouponSets(language: String, active: Bool, visible: Bool, uuids: [String]?) 69 case getCouponSets(language: String, active: Bool, visible: Bool, uuids: [String]?)
70 case getCouponSetsNew(language: String, active: Bool, visible: Bool, region: String?, offerCategory: String?) 70 case getCouponSetsNew(language: String, active: Bool, visible: Bool, region: String?, offerCategory: String?)
71 + case getCouponFilters(language: String)
71 case getAvailableCoupons 72 case getAvailableCoupons
72 73
73 // Market & Merchants 74 // Market & Merchants
...@@ -143,7 +144,7 @@ public enum Endpoint { ...@@ -143,7 +144,7 @@ public enum Endpoint {
143 return "/api/mobile/v2/{appUUID}/context/" 144 return "/api/mobile/v2/{appUUID}/context/"
144 145
145 // Authenticated Context endpoints - /oauth/{appUUID}/context 146 // Authenticated Context endpoints - /oauth/{appUUID}/context
146 - case .getCampaignsPersonalized, .getCoupons, .getMarketPassDetails, .getProfile, .addCard, .getCards, .deleteCard, .getTransactionHistory, .getPointsHistory, .validateCoupon, .redeemCoupon, .retrieveCoupon, .getCarouselContent, .getCouponSetsNew: 147 + case .getCampaignsPersonalized, .getCoupons, .getMarketPassDetails, .getProfile, .addCard, .getCards, .deleteCard, .getTransactionHistory, .getPointsHistory, .validateCoupon, .redeemCoupon, .retrieveCoupon, .getCarouselContent, .getCouponSetsNew, .getCouponFilters:
147 return "/oauth/{appUUID}/context" 148 return "/oauth/{appUUID}/context"
148 149
149 // Session endpoints - /api/session/{sessionUuid} 150 // Session endpoints - /api/session/{sessionUuid}
...@@ -171,7 +172,7 @@ public enum Endpoint { ...@@ -171,7 +172,7 @@ public enum Endpoint {
171 public var method: HTTPMethod { 172 public var method: HTTPMethod {
172 switch self { 173 switch self {
173 case .register, .changePassword, .resetPassword, .requestOtp, .verifyTicket, .refreshToken, .logout, .getCampaigns, .getCampaignsPersonalized, 174 case .register, .changePassword, .resetPassword, .requestOtp, .verifyTicket, .refreshToken, .logout, .getCampaigns, .getCampaignsPersonalized,
174 - .getCoupons, .getCouponSets, .getCouponSetsNew, .getAvailableCoupons, 175 + .getCoupons, .getCouponSets, .getCouponSetsNew, .getCouponFilters, .getAvailableCoupons,
175 .getMarketPassDetails, .getProfile, .addCard, .getCards, .deleteCard, .getTransactionHistory, .getPointsHistory, .validateCoupon, .redeemCoupon, .retrieveCoupon, .getMerchants, .getMerchantCategories, .getStores, .getArticles, .sendEvent, .sendDeviceInfo, .getCosmoteUser, .deiLogin, .getCarouselContent: 176 .getMarketPassDetails, .getProfile, .addCard, .getCards, .deleteCard, .getTransactionHistory, .getPointsHistory, .validateCoupon, .redeemCoupon, .retrieveCoupon, .getMerchants, .getMerchantCategories, .getStores, .getArticles, .sendEvent, .sendDeviceInfo, .getCosmoteUser, .deiLogin, .getCarouselContent:
176 return .POST 177 return .POST
177 case .getSingleCampaign, .getNetworkStatus: 178 case .getSingleCampaign, .getNetworkStatus:
...@@ -314,6 +315,14 @@ public enum Endpoint { ...@@ -314,6 +315,14 @@ public enum Endpoint {
314 "coupon": couponParams 315 "coupon": couponParams
315 ] 316 ]
316 317
318 + case .getCouponFilters(let language):
319 + return [
320 + "coupon": [
321 + "action": "get_filters",
322 + "language": language
323 + ]
324 + ]
325 +
317 case .getAvailableCoupons: 326 case .getAvailableCoupons:
318 return [ 327 return [
319 "coupon": [ 328 "coupon": [
...@@ -523,7 +532,7 @@ public enum Endpoint { ...@@ -523,7 +532,7 @@ public enum Endpoint {
523 return .standardContext 532 return .standardContext
524 533
525 // Authenticated Context - /oauth/{appUUID}/context 534 // Authenticated Context - /oauth/{appUUID}/context
526 - case .getCampaignsPersonalized, .getCoupons, .getMarketPassDetails, .getProfile, .addCard, .getCards, .deleteCard, .getTransactionHistory, .getPointsHistory, .validateCoupon, .redeemCoupon, .retrieveCoupon, .getCarouselContent, .getCouponSetsNew: 535 + case .getCampaignsPersonalized, .getCoupons, .getMarketPassDetails, .getProfile, .addCard, .getCards, .deleteCard, .getTransactionHistory, .getPointsHistory, .validateCoupon, .redeemCoupon, .retrieveCoupon, .getCarouselContent, .getCouponSetsNew, .getCouponFilters:
527 return .authenticatedContext 536 return .authenticatedContext
528 537
529 // Authentication - /oauth/{appUUID}/login, /oauth/{appUUID}/token 538 // Authentication - /oauth/{appUUID}/login, /oauth/{appUUID}/token
...@@ -565,7 +574,7 @@ public enum Endpoint { ...@@ -565,7 +574,7 @@ public enum Endpoint {
565 return .standard 574 return .standard
566 575
567 // Bearer Token Authentication (loyalty headers + Authorization: Bearer) 576 // Bearer Token Authentication (loyalty headers + Authorization: Bearer)
568 - case .changePassword, .getCampaignsPersonalized, .getCoupons, .getMarketPassDetails, .getProfile, .addCard, .getCards, .deleteCard, .getTransactionHistory, .getPointsHistory, .validateCoupon, .redeemCoupon, .retrieveCoupon, .getCarouselContent, .getCouponSetsNew: 577 + case .changePassword, .getCampaignsPersonalized, .getCoupons, .getMarketPassDetails, .getProfile, .addCard, .getCards, .deleteCard, .getTransactionHistory, .getPointsHistory, .validateCoupon, .redeemCoupon, .retrieveCoupon, .getCarouselContent, .getCouponSetsNew, .getCouponFilters:
569 return .bearerToken 578 return .bearerToken
570 579
571 // Basic Authentication (loyalty headers + Authorization: Basic) 580 // Basic Authentication (loyalty headers + Authorization: Basic)
......
...@@ -659,6 +659,72 @@ public class RedeemedSMHistoryModel { ...@@ -659,6 +659,72 @@ public class RedeemedSMHistoryModel {
659 } 659 }
660 } 660 }
661 661
662 +// MARK: - Coupon Filters Models
663 +
664 +public class CouponFiltersDataModel {
665 + private var offer_categories: [CouponOfferCategoryModel]?
666 + private var regions: [String]?
667 +
668 + public init(dictionary: [String: Any]) {
669 + if let regionsArray = dictionary["regions"] as? [Any] {
670 + self.regions = regionsArray.compactMap { $0 as? String }
671 + } else {
672 + self.regions = []
673 + }
674 +
675 + if let categoriesArray = dictionary["offer_categories"] as? [[String: Any]] {
676 + var tempCategories: [CouponOfferCategoryModel] = []
677 + for catDict in categoriesArray {
678 + tempCategories.append(CouponOfferCategoryModel(dictionary: catDict))
679 + }
680 + self.offer_categories = tempCategories
681 + } else {
682 + self.offer_categories = []
683 + }
684 + }
685 +
686 + public var _offer_categories: [CouponOfferCategoryModel]? { get { return self.offer_categories } }
687 + public var _regions: [String]? { get { return self.regions } }
688 +}
689 +
690 +public class CouponOfferCategoryModel {
691 + private var uuid: String?
692 + private var admin_name: String?
693 + private var name: String?
694 + private var image: String?
695 + private var parent: String?
696 + private var children: [CouponOfferCategoryModel]?
697 +
698 + public init(dictionary: [String: Any]) {
699 + self.uuid = dictionary["uuid"] as? String
700 + self.admin_name = dictionary["admin_name"] as? String
701 + self.name = dictionary["name"] as? String
702 +
703 + if let imgString = dictionary["image"] as? String {
704 + self.image = imgString.trimmingCharacters(in: .whitespacesAndNewlines)
705 + }
706 +
707 + self.parent = dictionary["parent"] as? String
708 +
709 + if let childrenArray = dictionary["children"] as? [[String: Any]] {
710 + var tempChildren: [CouponOfferCategoryModel] = []
711 + for childDict in childrenArray {
712 + tempChildren.append(CouponOfferCategoryModel(dictionary: childDict))
713 + }
714 + self.children = tempChildren
715 + } else {
716 + self.children = []
717 + }
718 + }
719 +
720 + public var _uuid: String { get { return self.uuid ?? "" } }
721 + public var _admin_name: String { get { return self.admin_name ?? "" } }
722 + public var _name: String { get { return self.name ?? "" } }
723 + public var _image: String { get { return self.image ?? "" } }
724 + public var _parent: String { get { return self.parent ?? "" } }
725 + public var _children: [CouponOfferCategoryModel]? { get { return self.children } }
726 +}
727 +
662 // MARK: - String Extension for HTML 728 // MARK: - String Extension for HTML
663 729
664 // extension String { 730 // extension String {
......