# Karma Subito & Marketing Admin Panel - Release Notes

This document captures the latest updates, bug fixes, and feature additions to the project.

---


### Core API & Auth [0.0.7] - Mar 26, 2026
- **Fix**: Resolved `TypeError: dispatcher.getOwner is not a function` in React 19 by enforcing `NODE_ENV=production` in build and start scripts.
- **Fix**: Corrected 502 Proxy Error on `request-password-reset` API on the server.
- **Feat**: Added full "Reset & Set Up Password" workflow.
- **Fix**: Updated logo URL and rendering logic in the password reset email template.
- **Fix**: Improved environment variable loading and validation.

### AI Chatbot
- **Fix**: Updated AI Chatbot port to `3001` for consistency.
- **Fix**: Improved cross-origin (CORS) configuration for the Chatbot.

### Admin Console
- **Fix**: Enhanced Notification "Recipients" search functionality.
- **Fix**: Resolved port conflict issues and refined drawer components.

### Marketing CMS & Others
- **Feat**: Integrated email configuration for CMS.
- **Fix**: Updated meta tags, favicons, and basic branding assets.
- **Fix**: Improved build stability and dependency resolution in the monorepo.


### Admin Console
- **Fix**: Resolved table row selection issue.



### [0.0.9] - Mar 31, 2026

### Marketing CMS
- **Fix**: Return 404 for unpublished pages when accessed via the page API.
- **Feat**: Added support for redirect types (internal & external) with dynamic field handling.
- **Feat**: Included new form configuration in API responses.
- **Fix**: Updated EDM handling to properly support raw HTML by removing unnecessary wrapping elements.
- **Feat**: Implemented Audit Logs to track changes and user-specific activity.
- **Feat**: Added RBAC (Role-Based Access Control) on CMS resources.

### Admin Console
- **Fix**: Resolved date parsing issue in History section where date selection was not working.


- **Fix**: Disable delete promo points if length is <= 1
- **Fix**: Remove name field capitalization
- **Fix**: Add name and description as mandatory fields

## [Unreleased] - Latest Updates

### [0.0.14] - April 17, 2026
- **Fix**: Return result for false active flag.

### Admin Console
- **Fix**: Notification Recipients drawer — tab switches under the delivery summary (Sent / Invalid / Non-Processable) now show the correct list of emails. Pagination preserves the active tab filter and rapid tab switches no longer race to display stale results.

### [0.0.36] - June 13, 2026

### Admin Console
- **Fix**: Corrected label casing for "Karma Subito Promo Code".
- **Feat**: Added access redirection in the dashboard loader so users without permission are routed away.
- **Feat**: Added a Seen / Unseen recipient filter to the campaign report, alongside the existing delivery-status filter. Filter selection resets pagination and is preserved across page changes, search, and status-tab switches.
- **Fix**: Hid non-report UI (Back button, campaign ID, demographics chart, action buttons, filters) from the printed campaign report via `no-print`.
- **Feat**: Promo Code details — added Phone Number, DOB, and Nationality columns to the Registered / Logged-in user tables, and renamed "Commence Date" to "Date of Acquisition" (table + Excel export).
- **Feat**: Promo Code details — extended user filters with a Nationality dropdown and a Date-of-Birth range; quick search now also matches phone number and nationality.
- **Feat**: Promo Code details — Country, Nationality, and Account Type filters are now multi-select (pick several values; rows match any selected).
- **Fix**: Promo Code details — wide user table now has synced top + bottom horizontal scrollbars (visible on macOS) and a sticky header, so columns are reachable without scrolling to the last row.
- **Chore**: Extracted the dual-scrollbar table wrapper into a reusable `HScrollTable` component (`@/lib/components/HScrollTable`) for use across the admin console.
- **Fix**: Applied the `HScrollTable` scrollbars + sticky header to the wide tables in the promo-code sections — the Promo Codes list table (also shown inside Campaign details) and the Campaign list table.

### Core API
- **Feat**: `GET /v1/admin-console/notifications/campaigns/:id/recipients` now accepts a `seen_status` query param (`seen` / `unseen`) and filters recipients by their enriched seen status from the Updot DB.
- **Feat**: Promo Code signups listing now returns `nationality`, `date_of_birth`, and `phone` (member mobile), and its search matches nationality and phone in addition to name / email / membership number.

### [0.0.37] - June 13, 2026

### Admin Console
- **Feat**: New **Reports** section (under Promo Codes) — a report builder that fetches a combined member list across one or more selected promo codes, with column selection, drag-to-reorder, search, a Logged-in filter, pagination, and Excel export. The promo-code picker loads lazily and results are fetched only once codes are selected.
- **Chore**: Added a reusable `TablePaginationFooter` component — a rows-per-page selector (10 / 25 / 50 / 100) plus a page navigator — so list pagination looks and behaves the same across the campaign / promo-code / report tables. Promo Code detail user lists now use it.
- **Feat**: Raised the default page size to **100** across the promo-code and campaign routes (Promo Codes list, Campaigns list, campaign/promo logs panels, member detail, Member Referrals, and the attach-codes modal).
- **Chore**: Added a `useSessionStorageState` hook so list filters/state survive navigating away and back (and same-tab refresh).
- **Fix**: Slimmed the `HScrollTable` horizontal scrollbar (thinner bar, transparent track) so it no longer looks oversized.
- **Feat**: Reports section — added the full filter set from the Promo Code detail page (Status, Country / Nationality / Account Type multi-select, Date-of-Acquisition and Date-of-Birth ranges, Sort), and switched the preview to the shared `HScrollTable` (synced scrollbars + sticky header) with loading skeletons.
- **Fix**: Reports — reorganised the "Arrange columns" list into a compact, wrapping, scroll-capped layout so it stays short when many columns are selected.
- **Fix**: Chart colors are now fully generated (golden-angle HSL) instead of a fixed 24-color palette — distinct colors for hundreds/thousands of promo codes with no duplicates and nothing to maintain. Pie and bar charts in Campaign analytics share one scale, so a promo code keeps the same color across both.
- **Fix**: Back navigation from a promo-code detail page now returns to the originating section. Opening a code from **Member Referrals** previously went back to the Promo Codes list; a `from` origin param now sends you back where you came from (Campaigns / Promo Codes list / Member Referrals), preserved through the member drill-down.

### Core API
- **Feat**: New `POST /v1/admin-console/promo-code-campaigns/reports/users` — returns a combined, paginated member list across one or more promo codes (POST so a long code list fits in the body). Each row carries its own `signup_promo_code`, and rows are ordered by the selected-code order, then alphabetically by name. The single-code users query is now a thin wrapper over this multi-code query.
- **Fix**: Promo Code create/update now strips `null`/`undefined` fields before forwarding to the Updot Core API, fixing a `"expected string, received null"` rejection when saving rewards without an optional name / currency / expiry.

### [0.0.38] - June 17, 2026

### Admin Console
- **Feat**: New **Reports** section (under Promo Codes) — a builder for three report types (**Members**, **Promo Codes**, **Campaigns**), each with column pick + drag-to-reorder, search, an inline live-applied filter panel, paginated preview, and Excel export.
- **Feat**: **Signup-activity filters** across every report and the Promo Codes list, Campaigns list, and Member Referrals pages — a **"Signups in"** time window (Today / Last 7 days / Last 30 days / This month / Custom / All time) plus a **Country (signups from)** filter, applied **dataset-wide** (server-side, not just the current page). An active window implies "has signups", so zero-count rows drop out.
- **Change**: All filter pop-ups/modals replaced by a reusable, **collapsible `FilterPanel`** (inline, live-applied, single Reset) across Reports, Promo Codes list, Campaigns list, and Member Referrals; each panel **remembers its open/closed state** (`sessionStorage`). Reports default to **newest-first**.
- **Feat**: **Export guardrails** — a **1,000-row cap** (over-limit exports are cancelled with a warning) and a **per-request timeout** that fails slow fetches fast.
- **Chore**: Raised default page size to **100** on the promo-code / campaign routes; extracted reusable building blocks (`FilterPanel`, `HScrollTable` with synced scrollbars + sticky header, `TablePaginationFooter`, `useSessionStorageState`, report primitives, generated chart colors); Campaigns list distribution chart shows a loading skeleton on first fetch.

### Core API
- **Feat**: `POST /reports/users` accepts signup-window `from`/`to` + `country[]` (server-side); new `POST /reports/signup-aggregate` (per-code/per-country counts) and `POST /reports/campaign-signups` (per-campaign totals + country list).
### Admin Console
- **Feat**: Report entry points are now gated behind the `campaign-reports` permission — the **Reports** tab in the Promo Codes sub-nav and the report link on notification campaign rows are hidden from users without report access.
- **Change**: Moved the **Export Promo Codes** button on the **Member Referrals** page into the page header next to the title, matching the placement used across the other promo-code pages.
- **Fix**: Promo Code details — the edit form now re-syncs with the latest saved data, so the **Active** toggle (and other fields) no longer drift out of sync with the saved value.
- **Fix**: Promo Code details — failed update validation now shows a notification instead of the Save silently doing nothing (e.g. a required field empty in a collapsed section).
- **Feat**: Added synced top + bottom scrollbars + sticky header (`HScrollTable`) to the Campaign detail attach-promo-codes table.
- **Fix**: Reports — the result count now follows the active status / nationality / account-type / DOB filters (was stuck on the server total), and the "Preview" section is renamed **Members**.

### [0.0.39] - June 18, 2026

### Admin Console
- **Feat**: **Karma Subito Promo Code** page now has the same **Analytics** section as Member Referrals — a "Signups per Promo Code" pie and a "Country × Promo Code" stacked bar, aggregated across all promo codes and window-aware (re-fetches on date-range change, cached for instant tab revisits).
- **Feat**: Added a total-count badge next to the title on **Karma Subito Promo Code** and **Campaigns** (e.g. `2989 promo codes` / `N campaigns`), matching Member Referrals.
- **Chore**: Extracted a reusable **`ListTableCard`** + **`ListTableFooter`** (`@/lib/components/ListTableCard`) and applied them to the **Karma Subito Promo Code** and **Campaigns** tables, so all three promo-code list tables share one card layout — a `Name (count)` header with search + sort, the table, and a footer with the rows-per-page selector, `Showing X–Y of Z`, and pagination.
- **Fix**: Reports (**Members**) — the result count is now the **true filtered total across all pages**. The Status, Nationality, Account Type, and Date-of-Birth filters are applied **server-side** (previously only the loaded page was filtered, so the count under-reported). Nationality / Account Type filter options accumulate across loads so the lists don't collapse once a filter is applied.

### Core API
- **Feat**: New `GET /v1/admin-console/promo-code-campaigns/promo-codes/analytics` — aggregated signup analytics across all regular (non-member-referral) promo codes, returning the same shape as the member-referrals analytics so the analytics card is reusable.
- **Feat**: `POST /reports/users` now accepts `status` (`active` / `inactive`), `nationality[]`, `accountType[]`, and `dobFrom` / `dobTo`, applied server-side so `pagination.total` reflects them.

### [0.0.40] - June 22, 2026

### Admin Console
- **Change**: **Consistent list layout across the promo-code section** — every list/table (Campaigns, Karma Subito Promo Codes, Member Referrals, Campaign detail, Promo Code detail) now shows the same arrangement: a title row, then a controls row with **search on the left** and **sort on the right**, with all other filters living only in the Filters panel.
- **Change**: **"Sort by" moved out of the Filters panel into the table controls** on every page (Campaigns list, Karma Subito Promo Codes, Member Referrals, Campaign detail, Promo Code detail, and Reports → Members). It no longer counts toward the active-filter badge or gets cleared by the Filters "Reset".
- **Fix**: **Removed duplicated search fields** — the Filters panel no longer carries a code/name search that mirrored the in-table quick search (Campaign detail and Member Referrals); search now lives only in the table.
- **Change**: **Filter panels now default to collapsed** everywhere (shared `FilterPanel`), so pages open with the filters tucked away; each panel still remembers its open/closed state per tab.
- **Change**: Moved the **Export Promo Codes** button on the **Campaign detail** page out of the Promo Codes table card into the page header (top-right), matching the other promo-code pages.
- **Change**: Long always-on info banners are now compact **info-icon tooltips on the title** on Karma Subito Promo Code ("Core DB ID vs VP ID"), Member Referrals ("codes attached implicitly"), and **Reports → Members report** ("build a flexible user report"). Unified into a reusable **`InfoHint`** component — a blue `(i)` icon with a light-blue tooltip — so all three look consistent and professional.
- **Feat**: Promo Code details — added a **Phone number** filter to the user filters, and clearer search placeholders ("Search by name, email, membership # or phone…").
- **Change**: Reports → Members report — moved the **Search users** box out of the setup panel into the **Members results header** (search left, sort right), matching every other list/table; the placeholder also advertises phone search.
- **Change**: **Export over-limit message** is clearer across all exports — when an export exceeds the **1,000-row cap** it's cancelled with a popup telling the user to change the filters so the export has 1,000 rows or fewer.
- **Fix**: **1,000-row cap is now enforced up front on every export** — Member Referrals and Campaign-detail exports previously fetched details for all codes before the cap kicked in (so a 3,000-code export appeared to proceed). They now validate the row count first and block immediately with the over-limit popup, matching the Promo Codes list, Campaigns list, Promo Code detail, and Reports exports.
- **Fix**: Deleting a promo code on the Karma Subito list no longer triggers a full page refresh (which reset the filters) — the row is removed in place, preserving search, sort, and filter state.
- **Fix**: Opening a promo code from **Member Referrals** now keeps the **Member Referrals** tab highlighted in the sub-nav (the active tab follows the `from` origin instead of the raw path).
- **Feat**: Promo code **reward `ttl`** (time-to-live in seconds) is now supported end-to-end — added to the reward form (per-reward "TTL (seconds)" input), the client payload types, the create/update builders, and the `apps/core` reward schema so it is forwarded to Updot Core instead of being dropped.
- **Change**: Promo code **update now sends only the fields that changed** (diffed against the loaded record). Scalars are compared individually; `rewards` / `access_list` / `signupPromoCodes` are sent as a whole only when any item within them changed. An unchanged save still shows "No changes to save".
- **Change**: Promo code create/edit form — **all accordion sections (Basic info, Rewards, Access list, Signup promo codes) are expanded by default** in the modal. On submit, any section containing a validation error is flagged **red with an alert icon** on its header, so missing required fields are visible even when a section is collapsed.

- **Fix**: Promo code **status now loads reliably in the Member Referrals and Campaign-detail tables**. These tables fetch each visible row's status on demand. They were firing one request per row at once (up to the 100-row page size), which flooded the proxy so many calls failed; combined with the way the page re-renders when analytics revalidate, rows could be left permanently without a status (showing a wrong "Inactive"). The fetches now run in **small batches (6 at a time)**, **commit progressively** (statuses stream in top-down instead of all-at-once), keep a **persistent per-row claim** so a re-render doesn't refire the whole page, and a row whose fetch **fails releases its claim and retries** on a later pass. While a row's status is still loading it shows a neutral "—" rather than a misleading "Inactive".
- **Change**: **Filters now persist across navigation** (per browser tab, via `sessionStorage`) on every promo-code section — drilling into a member and coming back, or moving between list and detail, no longer resets them. Persisted filters added on **Promo Code detail** (status, country, nationality, account type, phone, date-of-acquisition / DOB ranges, sort, signup window), **Campaigns list** (status, sort, created-date range, min/max codes, updated-by), **Member Referrals** (search, min/max signups, only-with-signups, sort), **Reports → Members** (status, nationality, account type, DOB range, sort), and **Karma Subito Promo Codes** (sort) — on top of the signup-window/country filters that already persisted.

### Core API
- **Feat**: `apps/core` promo-code reward schema accepts `ttl` (optional number) so it passes through to the Updot Core promo-code create/update endpoints.
- **Fix**: Updated layout justification in **CampaignsClientPage** and **CampaignAnalyticsCard** so page content, controls, and analytics sections align consistently across the Campaigns experience.

### [0.0.41] - June 23, 2026

### Admin Console
- **Feat**: Reports → Members — **member rows are now clickable** and open the member detail **within the Reports section**. New nested routes (`/admin/reports/members/:code/:membershipNumber` and its `:contactId` contact sub-page) keep the sidebar/breadcrumb on Reports and send the Back button to the report, instead of jumping into the Karma Subito Promo Code / Member Referral pages.
- **Change**: **Search now persists across navigation** (per browser tab, `sessionStorage`) on every promo-code page with a search box — Promo Code detail (Registered + Logged-in tables), Karma Subito Promo Codes list, and Campaigns list — matching the filters/sort that already persisted. Restoring a non-empty search re-runs the query on mount so the list matches the box.
- **Change**: **Active tab now persists** on the Promo Code detail (Details / Registered / Logged-in) and Campaign detail (Details / Promo codes) pages — returning to a page restores the tab you left rather than defaulting back to Details.
- **Change**: **All saved state is now individual per page** — tab, search, filters, and sort are scoped per promo code on Promo Code detail and per campaign on Campaign detail (keyed by id), so opening a different code/campaign starts clean instead of inheriting the previous one's tab/search/filters.
- **Feat**: **Campaign detail filters now persist** (previously reset on every navigation) — promo-code search, sort, signup window, only-with-signups, min/max signups, and analytics country, all per campaign. Analytics refetches on mount when a non-default signup window is restored so the chart matches the control.
- **Chore**: Parameterized the shared promo-code member/contact view components with optional `backHref` / `contactHrefBase` overrides so the new Reports member route reuses them while keeping navigation inside the Reports section.

### [0.0.42] - June 23, 2026

### Admin Console
- **Feat**: EDM editor — new **"Test the Template"** tab (last tab) giving QA a one-click validation flow. Tick checks (Mailchimp, SendGrid, File name, URL/Path, Google Analytics, Mail provider, Social media) and run them client-side against the template's HTML — no backend, nothing sent. Each result shows **Pass / Warning / Fail** with structured detail: the merge-tag variable list (`*|…|*`), footer/redirect/social **links with "Open in new tab" previews** (and merge-tag links shown as tags), and **image thumbnails** with extension flags. Rules are grounded in the real Karma EDM templates (footer items, `*|UPDATE_PROFILE|*` / `*|UNSUB|*`, jpg/png-only assets, expected Facebook/Instagram/TikTok/YouTube links, https/localhost path checks).
- **Fix**: **Count labels now follow the active search/filters** across the promo-code section. The title badges and card counts on **Member Referrals**, **Karma Subito Promo Codes**, and **Campaigns** previously showed the unfiltered total while the rows were filtered — they now show the filtered count that matches the rows on screen.
- **Change**: **Campaigns list** — any active filter (status / created-date / min-max codes / updated-by, not just the signup-window/country filters) now switches the list to the **dataset-wide view**, so the rows, count, pagination, and analytics span **all** campaigns instead of just the current server page.
- **Change**: **Karma Subito Promo Codes** — converted to the dataset-wide model whenever a type filter (Only Promo Codes / Referral) or a signup filter is active, so the **count matches the rows shown** and the **analytics charts follow the filtered codes**. The upstream list API returns a `total` that ignores the type filter (and is read-only from this repo), so the count is now computed client-side from the fetched set.

### [0.0.43] - June 24, 2026

### Admin Console
- **Fix**: Promo Code detail — **"Registered" and "Logged in" count labels** (tab titles + section headings) now show the true API total instead of the current page size, which was always capped at 100 due to server-side pagination.
- **Feat**: EDM editor — **"Test the Template"** pipeline upgraded with new checks and improved design:
  - **File name check** — now async; performs a **live load test** per image (5 s timeout, parallel) to detect broken assets, and flags filenames containing spaces or `%20` (naming convention: use underscores or hyphens). Each image row in the results shows **broken** (red) / **spaces** (orange) badges and an **"Open"** button to inspect the asset in a new tab.
  - **HTML check** (new, was TODO) — validates `<!DOCTYPE html>` presence, flags email-unsafe elements (`<script>`, `<form>`, `<iframe>`, `<object>`, `<embed>`), and checks open/close balance for ~20 common block tags (`div`, `table`, `tr`, `td`, `a`, `span`, `p`, etc.). Void elements (`br`, `img`, `hr`, `input`, etc.) are correctly excluded from the balance check.
  - **SendGrid check** — extended with three new variable-syntax checks: mismatched double-open/single-close (`{{var}`), mismatched single-open/double-close (`{var}}`), and single-brace variables that look like Handlebars names (`{var}` instead of `{{var}}`). CSS rules are excluded from the single-brace check. All SendGrid findings now use **Warning** only (removed Fail state — severity depends on the template).
  - **Mail provider check** — removed the `CSS float:` rule (to be re-evaluated and re-added after testing).
  - **Pipeline UI** — removed the "None" button (simplified selection flow); added **tooltips on every check chip** showing its description on hover; "Run pipeline" renamed to **"Run checks"** / **"Re-run"** with a refresh icon; pending stages are visually dimmed; a `Divider` separates the config area from the run controls.
  - **Access control** — "Test the Template" tab is now gated behind **email-template read access**; the "Run checks" button requires **write access** (read-only users see the panel but the button is disabled with a tooltip explaining why).

---

### [0.0.44] - July 3, 2026

### Core API
- **Fix**: Promo-code member lists — **members no longer appear twice** in the Registered / Logged-in tables (and referral reports). The Updot `member_profiles` table can hold more than one row per member; the queries now join only the **latest profile row**, so a duplicated profile no longer fans a member out into multiple identical rows (e.g. same membership # listed twice while the count said one less).
- **Fix**: Same latest-profile join applied to the **signup analytics aggregates**, so a member with duplicate profiles can't be double-counted across country buckets in "Signups by Country".
- **Fix**: **Updot admin session auto-refresh** in `PromoCodesService`. The cached Updot Core session is rotated whenever anything else signs in with the same admin account; previously a stale session made every promo-code call fail (upstream 400) until the server was restarted. Auth-shaped failures now invalidate the cached session, re-login, and retry once (GETs on 400/401/403, mutations on 401/403) — same pattern already used by the Updot proxy and campaign service.

### Admin Console
- **Fix**: Karma Subito Promo Codes — the **"N promo codes" count badge now shows a skeleton** while loading instead of appearing suddenly once counts arrive (no layout shift), matching the Member Referrals page.

### [0.0.49] - July 8, 2026

### Core API
- **Fix**: Promo-code report — a member **no longer appears twice** in the user list and export. The report joined `member_profiles` without deduping, so a member with more than one profile row was printed once per profile (e.g. dashboard count said 1611/1646 while the export had 1612/1647 rows). The report now joins only the member's latest profile via a single `DISTINCT ON (member_id)` scan, so each member yields exactly one row and the export matches the dashboard count.
- **Fix**: Added a unique `members.id` tiebreaker to the report's paginated user list so rows can't repeat or skip across page boundaries when members tie on signup date + first name.
- **Fix**: Same unique-tiebreaker applied to the **promo-code campaigns list** query, which paginated with only a `created_at` sort — campaigns sharing a timestamp could otherwise repeat/skip across pages.

### [0.0.51] - July 9, 2026

### Admin Console
- **Feat**: Added a **Select all** option to the Country (signups from) multi-select — shared across `Promo Codes`, `Campaigns`, and `Member Referrals`.
- **Fix**: Default page size bumped to 25 (from 10) for `Promo Codes`, `Member Referrals`, and `Reports → Member Report`
- **Fix**: Promo Codes list was loading with page size 10 despite the default being 25
- **Fix**: Header count badges (**Campaigns, Promo Codes, Member Referrals, Reports → Members**) shows the true grand total
Fix: Repositioned the loading 


### [0.0.52] - July 9, 2026

### Admin Console
- **Feat**: Add a shared "Select all" option to the Country (signups from) multi-select, reused across Promo Codes, `Campaigns`, and `Member Referrals`
- **Feat**: Add a Country × Campaign breakdown bar chart to the **Campaigns analytics card**, backed by a new by Country Campaign in `Campaign`
- **Fix**: Updated karma subito Promo-code history break-down



---

### [0.0.52] - July 9, 2026

### Admin Console
- **Change**: EDM editor "Test the Template" — **removed the Mail provider check**. Its client-compatibility warnings (`<style>` block, `position:`, flex/grid, etc.) were noisy and low-signal, so the check was dropped from the drawer.
- **Fix**: EDM **HTML check** no longer reports **false "unclosed tag"** warnings. Close-tag matching now tolerates whitespace and newlines — `</tr >`, `< /tr>`, and tags split across lines (`<` on one line, `/tr>` on the next) — which render fine but were previously counted as unclosed.
- **Feat**: EDM **HTML check now pinpoints the exact line**. Instead of `<tr> (48 open, 47 close)`, it walks each tag with a stack and reports `<tr> not closed (line 512)` (and `</tr> has no opening tag (line N)` for stray closes), so the offending tag is quick to locate and fix.
- **Change**: EDM **Social media check** — clearer description and summary wording (detects social links by domain, flags missing expected platforms and links with no icon image, allows extra platforms).

---

### [0.0.53] - July 14, 2026

### Admin Console
- **Feat**: Reports — Country / Nationality / Account type filters only show values with real matching data, with **Select all** support.
- **Feat**: Karma Subito Promo Codes — added an **Inactive** filter alongside **Active**.
- **Fix**: Country charts (Campaigns + Promo Codes / Member Referrals) — country filter now actually scopes the chart data instead of just gating which codes appear; UI polish (bigger legend, header badges, total-signups badge moved into the chart).
- **Fix**: Member Referrals — corrected the misleading "total promo codes" badge to reflect actual referral codes.
- **Fix**: Global loader — progress bar no longer restarts/flickers on chained redirects (e.g. login).

### Core API
- **Feat**: New report filter-options endpoint powering the Reports Country / Nationality / Account type filters.
- **Fix**: Campaign signups endpoint — country filter now applied to the country-breakdown aggregation, not just the totals.

---

### [0.0.56] - July 14, 2026

### Admin Console
- **feat**: add verification EDM template ID to promo code forms and schemas

### Core 
- **feat**: add verification EDM template ID to promo code schemas

---

### [0.0.58] - July 20, 2026

### Admin Console
- **feat**: Updated campaign sign-up calculation to return more accurate totals.
- **feat**: Improved Country MultiSelect UI for large selections.

---

### [0.0.61] - July 24, 2026

### Admin Console
- **feat**: Added live ViewPoint points fetch button and "Actual Points" column in promo code user tables.

### Core 
- **feat**: Added `GET /v1/admin/promo-code-campaigns/members/:membershipNumber/points` endpoint to fetch live member points entitlements from ViewPoint.

---

### [0.0.62] - July 24, 2026

### Admin Console
- **feat**: Added unified 3D Pie Charts for Internal vs External Booking Distribution analytics across all campaign and promo code dashboard pages.
- **feat**: Redesigned analytics section into a side-by-side 2-column layout with vertical and horizontal dividing lines and bold section headings.
- **feat**: Restricted Internal and External Booking count columns strictly to the Logged in user tab table.

### Core
- **feat**: Aggregated internal and external booking counts across full promo code datasets for campaign analytics.

---

### [0.0.65] - July 27, 2026

### Admin Console
- **feat**: Added `countryRecordIDs` multi-select field (displaying country names with full search support) and `viewpointChargeCenterID` select dropdown (displaying Charge Center Name and Currency) to the Create/Edit Promo Code form.

### Core
- **feat**: Updated `PromoSignupCodeSchema` to validate and forward `countryRecordIDs` and `viewpointChargeCenterID` fields in promo code request payloads.

---

### [0.0.66] - July 28, 2026

### Admin Console
- **feat**: Replaced static country data with database-driven country options across Campaigns, Karma Subito Promo Codes, Member Referrals, Reports, and Promo Code Form, ensuring searchable and consistent country lists throughout the application.
- **fix**: Resolved stale Date of Birth (DOB) filters on the Reports page by resetting the filter on each visit, clearing legacy persisted values from session storage, and safely handling existing date values during migration.

### Core
- **feat**: Added a new countries endpoint for Promo Code Campaigns that retrieves country names and codes directly from the `countries` table, providing a single backend source for all Admin Console country filters and selectors.

---

### [0.0.68] - July 30, 2026

### Admin Console
- **feat**: Updated Promo Code Campaign analytics UI, table columns, and chart to classify and display **Curated Event Bookings (Curated)** alongside **Internal Bookings** across Campaigns, Promo Codes, and User Analytics views.

### Core
- **feat**: Refactored the Promo Code Signups repository to classify `CURATED_EVENT` booking entities as **Curated Bookings** and dynamic filter handling.

---

### [0.0.70] - August 3, 2026

### Admin Console
- **fix**: Adjusted custom date range filter to set local start-of-day (`00:00:00.000`) and end-of-day (`23:59:59.999`) times, preventing query results from overflowing into the next calendar day due to UTC timezone offsets in Reports.

---

> [!NOTE]
> All automated deployments are triggered via PR merges using the `#dev-release:` tag in the PR title. 
