@@ -292,8 +292,11 @@ The SwiftWarplyFramework provides ready-to-use view controllers that you can int
| View Controller | Purpose | Description |
|----------------|---------|-------------|
| `MyRewardsViewController` | Main rewards screen | Displays campaigns, offers, and banners |
| `MyRewardsViewController` | Main rewards screen | Displays carousel banners, filter bar, and horizontally-scrollable category offer rows |
| `ProfileViewController` | User profile & coupons | Shows user profile and coupon management |
| `MyCouponsViewController` | User's coupon list | Full-screen list of the user's active, redeemed, and expired coupons with filter tabs |
| `MapViewController` | Merchant store map | Interactive MKMapView showing merchant store locations; accepts an optional `CouponSetItemModel` coupon and `isMarket` flag |
| `CategoryOffersViewController` | Category offers grid | 2-column grid of all offers in a specific category; opened from the "All" button on a category row; accepts a `SectionModel` |
| `CouponsetViewController` | Coupon set details | Displays detailed coupon set information with expandable description, terms, store locator, and website link |
...
...
@@ -328,6 +331,28 @@ class MainViewController: UIViewController {
@@ -1790,6 +1899,31 @@ Start with the Quick Start guide and gradually adopt the advanced features as ne
## 📋 **Changelog**
### **Version 2.5.1** - *March 20, 2026*
#### **🆕 New Features**
-**`MyCouponsViewController` Added**: New full-screen view controller displaying the user's complete coupon list with filter tabs (Active, Redeemed, Expired). Loads coupon data from the API on launch and supports dynamic filter selection.
-**`MapViewController` Added**: New map view controller using `MKMapView` to display merchant store locations. Accepts an optional `coupon: CouponItemModel?` to pre-filter stores for a specific merchant, and an `isMarket: Bool?` flag to differentiate supermarket vs. regular merchant context.
-**`CategoryOffersViewController` Added**: New view controller displaying a 2-column grid of all offers within a specific category. Opened automatically from the "All" button on any category row in `MyRewardsViewController`. Accepts a `sectionData: SectionModel` property containing the full offer list.
-**`MyRewardsViewController` Updated**:
- Banner section now uses `CarouselItemModel` (from `getCarouselContent()`) instead of legacy `CampaignItemModel`.
- Added `MyRewardsFiltersTableViewCell` row beneath the banner section on every screen load, showing a search/filter button and a map button (actions are stubbed — `TODO`).
- Tapping the "All" button on any category row now pushes `CategoryOffersViewController` with the full `SectionModel` for that category.
-**New API: `getCarouselContent()`** — Fetches the ordered list of carousel banner items (`[CarouselItemModel]`) for the banner section. Each item carries a `_url` field that drives tap-navigation routing.
-**New API: `getCouponFilters()`** — Fetches the available coupon filter categories (`CouponFiltersDataModel`) used by both `MyCouponsViewController` and `ProfileViewController`.
-**New API: `getStores()`** — Fetches the physical store locations (`[MerchantModel]`) for a given merchant UUID, used to populate `MapViewController` pin annotations.
-**New Model: `CarouselItemModel`** — Represents a banner carousel item with fields: `_uuid`, `_name`, `_entity`, `_app_img`, `_app_url`, `_url`, `_web_img`, `_web_img_responsive`.
#### **🔧 Improvements**
-`MyRewardsOfferCollectionViewCell`: `discountLabel` now auto-scales its font down to 50% (`minimumScaleFactor = 0.5`) instead of truncating when the discount text is long.
-`MyRewardsFiltersTableViewCell`: Map button now correctly covers the full 44×44 tap area of `mapView`.
| `CarouselItemModel` | CarouselItemModel.swift | `_uuid`, `_name`, `_entity`, `_app_img`, `_app_url`, `_url`, `_web_img`, `_web_img_responsive` | Banner carousel items for MyRewardsViewController; `_url` drives tap navigation routing (NEW 2.5.1) |
| `CouponFiltersDataModel` | CouponFilterModel.swift | Filter category data | Top-level model returned by `getCouponFilters()`; contains filter lists (NEW 2.5.1) |
| `CouponFilterModel` | CouponFilterModel.swift | `id`, `title`, `count` | Individual filter chip (e.g. "Active", "Redeemed"); used by `MyCouponsViewController` and `ProfileViewController` (NEW 2.5.1) |
@@ -676,8 +688,11 @@ All screens use **XIB-based** layouts (not SwiftUI) with `Bundle.frameworkBundle
| Screen | Storyboard ID | Purpose |
|--------|--------------|---------|
| `MyRewardsViewController` | — (XIB) | Main rewards dashboard with campaigns, offers, banners |
| `MyRewardsViewController` | — (XIB) | Main rewards dashboard: carousel banners (`CarouselItemModel`), filter bar row, horizontal category offer rows. Fetches `getCarouselContent()`, `getCouponSetsNew()`, `getCouponFilters()` on load. |
| `ProfileViewController` | — (XIB) | User profile with coupons, filters, questionnaires |
| `MyCouponsViewController` | — (XIB) | Full coupon list for the current user with filter tabs. Fetches coupons on load. Public init via `MyCouponsViewController()`. (NEW 2.5.1) |
| `MapViewController` | — (XIB) | `MKMapView`-based merchant store map. `public var coupon: CouponItemModel?` (optional, filters to merchant's stores). `public var isMarket: Bool?` (supermarket vs regular). Calls `getStores(merchantUuid:)` internally. (NEW 2.5.1) |
| `CategoryOffersViewController` | — (XIB) | 2-column grid of all offers in a category. `public var sectionData: SectionModel?`. Pushed from `MyRewardsOffersScrollTableViewCell` "All" button via `didSelectAllOffers` delegate. Navigation bar shown with back button via `setBackButton()`. (NEW 2.5.1) |
-`MyRewardsBannerOfferCollectionViewCell` — Banner carousel item in collection view (configures from `CarouselItemModel`)
-`MyRewardsOfferCollectionViewCell` — Standard offer card in horizontal-scroll collection view (configures from `CouponSetItemModel`); `discountLabel` auto-scales font to `minimumScaleFactor = 0.5`
-`MyRewardsOffersScrollTableViewCell` — Horizontal scrolling offer cards per category; delegate: `MyRewardsOffersScrollTableViewCellDelegate` (`didSelectCouponSet`, `didSelectAllOffers`). `allButton: UIButton` triggers `didSelectAllOffers` via `addTarget`
-`MyRewardsProfileInfoTableViewCell` — Profile info header
-`MyRewardsFiltersTableViewCell` — Filter bar row with `filtersButton` (search/filter) and `mapButton` (map); both are transparent overlay buttons covering their parent views; actions are `TODO` stubs (NEW 2.5.1)
-`MyCouponsHeaderTableViewCell` — Section header cell for `MyCouponsViewController` (NEW 2.5.1)
-`CategoryOfferCollectionViewCell` — Card cell for `CategoryOffersViewController` 2-column grid; configures from `CouponSetItemModel` only; top half = gray banner + centered logo + discount circle; bottom half = merchant name + bold title + subtitle + expiry (NEW 2.5.1)
-`CategoryOffersGridTableViewCell` — `UITableViewCell` containing a non-scrolling `UICollectionView` (2-column grid); dynamically computes its own height via `collectionViewHeightConstraint`; `didSelectItemAt` pushes `CouponsetViewController` (NEW 2.5.1)
-`CategoryOffersHeaderTableViewCell` — Header cell for `CategoryOffersViewController` showing category title, search/filter button (`filtersView`/`filtersButton`), and map button (`mapView`/`mapButton`) (NEW 2.5.1)
-`ProfileCouponTableViewCell` — Coupon row in profile
-`ProfileCouponFiltersTableViewCell` — Filter chips for coupons
-`getStores(language:merchantUuid:completion:failureCallback:)` / async variant — returns `[MerchantModel]` for a specific merchant UUID; used by `MapViewController` (NEW 2.5.1)
-`getCarouselContent(completion:failureCallback:)` / async variant — returns `[CarouselItemModel]` for the banner carousel in `MyRewardsViewController` (NEW 2.5.1)