From de180fa43758d54c55b6bd159caae3a0bdbf7bea Mon Sep 17 00:00:00 2001
From: Ayush Rodrigues
Date: Sun, 18 Jan 2026 23:37:27 +0000
Subject: [PATCH] lots of fixes
---
.cursor/debug.log | 203 +++++++++++++
.../internal/customers/CusSearchService.ts | 21 +-
shared/utils/productDisplayUtils.ts | 268 +++++++++++-------
.../compareProductUtils/compareItemUtils.ts | 16 +-
.../components/general/table/table-header.tsx | 4 +-
.../InlinePlanEditor.tsx | 17 +-
vite/src/components/v2/selects/Select.tsx | 4 +-
.../v2/sheet-overlay/SheetOverlay.tsx | 105 +++++++
.../v2/sheets/SharedSheetComponents.tsx | 23 +-
vite/src/components/v2/sheets/Sheet.tsx | 23 +-
vite/src/hooks/stores/useSheetStore.ts | 6 +-
.../filter-dropdown/CustomersFilterButton.tsx | 2 +-
.../filter-dropdown/FilterStatusSubMenu.tsx | 16 +-
.../filter-dropdown/ProductsSubMenu.tsx | 228 ++++++++-------
.../components/filter-dropdown/SavedViews.tsx | 38 ++-
.../filter-dropdown/SavedViewsDropdown.tsx | 5 +-
.../analytics/hooks/useAnalyticsData.tsx | 4 +-
.../hooks/useCustomersQueryStates.tsx | 12 +-
.../sheets/SubscriptionDetailSheet.tsx | 1 +
.../customer-list/CustomerListColumns.tsx | 3 +
.../CustomerListFilterButton.tsx | 10 +-
.../customer-list/CustomerListSearchBar.tsx | 6 +-
.../table/customer-list/CustomerListTable.tsx | 10 +-
.../CustomerProductsColumns.tsx | 1 +
.../CustomerProductsStatus.tsx | 30 +-
vite/src/views/main-sidebar/MainSidebar.tsx | 2 +-
.../src/views/onboarding4/OnboardingGuide.tsx | 4 +-
.../components/UpdateFeatureSheet.tsx | 8 +
.../components/UpdateCreditSystemSheet.tsx | 8 +
.../products/plan/components/PlanEditor.tsx | 95 +------
.../plan/components/SaveChangesBar.tsx | 6 +-
.../EditPlanFeatureSheet.tsx | 56 +++-
.../products/plan/utils/getDefaultItem.ts | 17 +-
.../product-list/ProductListColumns.tsx | 2 +-
.../product-list/ProductListTable.tsx | 12 +-
35 files changed, 828 insertions(+), 438 deletions(-)
create mode 100644 .cursor/debug.log
create mode 100644 vite/src/components/v2/sheet-overlay/SheetOverlay.tsx
diff --git a/.cursor/debug.log b/.cursor/debug.log
new file mode 100644
index 000000000..348613480
--- /dev/null
+++ b/.cursor/debug.log
@@ -0,0 +1,203 @@
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":true,"isVersionChanged":true,"isProductUpdated":true,"productId":"free_plan","productVersion":1,"willUpdate":true},"timestamp":1768767206353,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:setBaseProduct","message":"updating baseProduct","data":{"frontendProductItemsCount":1,"frontendProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}]},"timestamp":1768767206353,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":1,"lastProductId":"free_plan","lastProductVersion":1,"willUpdate":false},"timestamp":1768767206354,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":1,"lastProductId":"free_plan","lastProductVersion":1,"willUpdate":false},"timestamp":1768767206365,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}]},"timestamp":1768767206361,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}]},"timestamp":1768767206361,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":true,"productId":"free_plan","productVersion":1,"lastProductId":"free_plan","lastProductVersion":1,"willUpdate":true},"timestamp":1768767207732,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:setBaseProduct","message":"updating baseProduct","data":{"frontendProductItemsCount":1,"frontendProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}]},"timestamp":1768767207732,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}]},"timestamp":1768767207732,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}]},"timestamp":1768767207733,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767208701,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"},{"feature_id":"analytics","interval":null,"included_usage":null,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}]},"timestamp":1768767208701,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767208701,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767208701,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"},{"feature_id":"analytics","interval":null,"included_usage":null,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38IUPp9xbsN9aTLxJWylhmhpSMd"}]},"timestamp":1768767208701,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767208702,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":1,"lastProductId":"free_plan","lastProductVersion":1,"willUpdate":false},"timestamp":1768767208711,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:start","message":"save clicked - before save","data":{"productId":"free_plan","itemsCount":2,"items":[{"feature_id":"messages","interval":null,"included_usage":10},{"feature_id":"analytics","interval":null,"included_usage":null}]},"timestamp":1768767210156,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767217153,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":true,"isProductUpdated":true,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":1,"willUpdate":true},"timestamp":1768767220542,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:setBaseProduct","message":"updating baseProduct","data":{"frontendProductItemsCount":2,"frontendProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","entitlement_id":"ent_38RfHfo63jeH40j8nB7K1BAHLeT"}]},"timestamp":1768767220542,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","entitlement_id":"ent_38RfHfo63jeH40j8nB7K1BAHLeT"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","entitlement_id":"ent_38RfHfo63jeH40j8nB7K1BAHLeT"}]},"timestamp":1768767220548,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","entitlement_id":"ent_38RfHfo63jeH40j8nB7K1BAHLeT"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","entitlement_id":"ent_38RfHfo63jeH40j8nB7K1BAHLeT"}]},"timestamp":1768767220548,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767220550,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","entitlement_id":"ent_38RfHfo63jeH40j8nB7K1BAHLeT"}]},"timestamp":1768767226001,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","entitlement_id":"ent_38RfHfo63jeH40j8nB7K1BAHLeT"}]},"timestamp":1768767226002,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767226003,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:start","message":"save clicked - before save","data":{"productId":"free_plan","itemsCount":1,"items":[{"feature_id":"messages","interval":null,"included_usage":10}]},"timestamp":1768767226796,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"SaveChangesBar.tsx:onSuccess","message":"save onSuccess - about to refetch","data":{},"timestamp":1768767232230,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":true,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":true},"timestamp":1768767233610,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:setBaseProduct","message":"updating baseProduct","data":{"frontendProductItemsCount":1,"frontendProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767233610,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767233611,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767233611,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"SaveChangesBar.tsx:onSuccess:afterRefetch","message":"refetch completed","data":{},"timestamp":1768767235270,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:end","message":"save completed","data":{"result":true},"timestamp":1768767235270,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767236608,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767236608,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767236608,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767236608,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767236608,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767236609,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767236614,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:start","message":"save clicked - before save","data":{"productId":"free_plan","itemsCount":2,"items":[{"feature_id":"messages","interval":null,"included_usage":10},{"feature_id":"analytics","interval":null,"included_usage":null}]},"timestamp":1768767237868,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"SaveChangesBar.tsx:onSuccess","message":"save onSuccess - about to refetch","data":{},"timestamp":1768767242801,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":true,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":true},"timestamp":1768767244180,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:setBaseProduct","message":"updating baseProduct","data":{"frontendProductItemsCount":2,"frontendProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767244181,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767244181,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"analytics","failedChecks":[{"check":"reset_usage_when_enabled","message":"Reset usage when enabled different: true !== false"}],"item1ResetUsage":true,"item2ResetUsage":false,"item1Interval":null,"item1IncludedUsage":null},"timestamp":1768767244181,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"analytics","failedChecks":[{"check":"reset_usage_when_enabled","message":"Reset usage when enabled different: true !== false"}],"item1ResetUsage":true,"item2ResetUsage":false,"item1Interval":null,"item1IncludedUsage":null},"timestamp":1768767244181,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareProductUtils.ts:productsAreSame:itemsDifferent","message":"items not same after comparison","data":{"item1":"{\"feature_id\":\"analytics\",\"feature_type\":\"static\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":true,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"analytics\",\"entity_feature_id\":null,\"entitlement_id\":\"ent_38RfKZrFZYfWslXTJOSbeoBjzkV\",\"feature_type\":\"static\",\"reset_usage_when_enabled\":false,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","featureId":"analytics"},"timestamp":1768767244181,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:itemsDifferent","message":"items not same after comparison","data":{"item1":"{\"feature_id\":\"analytics\",\"feature_type\":\"static\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":true,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"analytics\",\"entity_feature_id\":null,\"entitlement_id\":\"ent_38RfKZrFZYfWslXTJOSbeoBjzkV\",\"feature_type\":\"static\",\"reset_usage_when_enabled\":false,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","featureId":"analytics"},"timestamp":1768767244182,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"analytics","failedChecks":[{"check":"reset_usage_when_enabled","message":"Reset usage when enabled different: true !== false"}],"item1ResetUsage":true,"item2ResetUsage":false,"item1Interval":null,"item1IncludedUsage":null},"timestamp":1768767244182,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareProductUtils.ts:productsAreSame:itemsDifferent","message":"items not same after comparison","data":{"item1":"{\"feature_id\":\"analytics\",\"feature_type\":\"static\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":true,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"analytics\",\"entity_feature_id\":null,\"entitlement_id\":\"ent_38RfKZrFZYfWslXTJOSbeoBjzkV\",\"feature_type\":\"static\",\"reset_usage_when_enabled\":false,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","featureId":"analytics"},"timestamp":1768767244182,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767244182,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"analytics","failedChecks":[{"check":"reset_usage_when_enabled","message":"Reset usage when enabled different: true !== false"}],"item1ResetUsage":true,"item2ResetUsage":false,"item1Interval":null,"item1IncludedUsage":null},"timestamp":1768767244182,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareProductUtils.ts:productsAreSame:itemsDifferent","message":"items not same after comparison","data":{"item1":"{\"feature_id\":\"analytics\",\"feature_type\":\"static\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":true,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"analytics\",\"entity_feature_id\":null,\"entitlement_id\":\"ent_38RfKZrFZYfWslXTJOSbeoBjzkV\",\"feature_type\":\"static\",\"reset_usage_when_enabled\":false,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","featureId":"analytics"},"timestamp":1768767244182,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"SaveChangesBar.tsx:onSuccess:afterRefetch","message":"refetch completed","data":{},"timestamp":1768767245839,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:end","message":"save completed","data":{"result":true},"timestamp":1768767245839,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"analytics","failedChecks":[{"check":"reset_usage_when_enabled","message":"Reset usage when enabled different: true !== false"}],"item1ResetUsage":true,"item2ResetUsage":false,"item1Interval":null,"item1IncludedUsage":null},"timestamp":1768767394297,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"analytics","failedChecks":[{"check":"reset_usage_when_enabled","message":"Reset usage when enabled different: true !== false"}],"item1ResetUsage":true,"item2ResetUsage":false,"item1Interval":null,"item1IncludedUsage":null},"timestamp":1768767394298,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareProductUtils.ts:productsAreSame:itemsDifferent","message":"items not same after comparison","data":{"item1":"{\"feature_id\":\"analytics\",\"feature_type\":\"static\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":true,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"analytics\",\"entity_feature_id\":null,\"entitlement_id\":\"ent_38RfKZrFZYfWslXTJOSbeoBjzkV\",\"feature_type\":\"static\",\"reset_usage_when_enabled\":false,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","featureId":"analytics"},"timestamp":1768767394297,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:itemsDifferent","message":"items not same after comparison","data":{"item1":"{\"feature_id\":\"analytics\",\"feature_type\":\"static\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":true,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"analytics\",\"entity_feature_id\":null,\"entitlement_id\":\"ent_38RfKZrFZYfWslXTJOSbeoBjzkV\",\"feature_type\":\"static\",\"reset_usage_when_enabled\":false,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","featureId":"analytics"},"timestamp":1768767394298,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767394297,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767394298,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"analytics","failedChecks":[{"check":"reset_usage_when_enabled","message":"Reset usage when enabled different: true !== false"}],"item1ResetUsage":true,"item2ResetUsage":false,"item1Interval":null,"item1IncludedUsage":null},"timestamp":1768767394298,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareProductUtils.ts:productsAreSame:itemsDifferent","message":"items not same after comparison","data":{"item1":"{\"feature_id\":\"analytics\",\"feature_type\":\"static\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":true,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"analytics\",\"entity_feature_id\":null,\"entitlement_id\":\"ent_38RfKZrFZYfWslXTJOSbeoBjzkV\",\"feature_type\":\"static\",\"reset_usage_when_enabled\":false,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","featureId":"analytics"},"timestamp":1768767394298,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"analytics","failedChecks":[{"check":"reset_usage_when_enabled","message":"Reset usage when enabled different: true !== false"}],"item1ResetUsage":true,"item2ResetUsage":false,"item1Interval":null,"item1IncludedUsage":null},"timestamp":1768767394297,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareProductUtils.ts:productsAreSame:itemsDifferent","message":"items not same after comparison","data":{"item1":"{\"feature_id\":\"analytics\",\"feature_type\":\"static\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":true,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"analytics\",\"entity_feature_id\":null,\"entitlement_id\":\"ent_38RfKZrFZYfWslXTJOSbeoBjzkV\",\"feature_type\":\"static\",\"reset_usage_when_enabled\":false,\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","featureId":"analytics"},"timestamp":1768767394297,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":true,"isVersionChanged":true,"isProductUpdated":true,"productId":"free_plan","productVersion":2,"willUpdate":true},"timestamp":1768767394313,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:setBaseProduct","message":"updating baseProduct","data":{"frontendProductItemsCount":2,"frontendProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767394314,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767394318,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767394332,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767394332,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767394337,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767501092,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfKZrFZYfWslXTJOSbeoBjzkV"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767501092,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767501096,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:start","message":"save clicked - before save","data":{"productId":"free_plan","itemsCount":1,"items":[{"feature_id":"messages","interval":null,"included_usage":10}]},"timestamp":1768767501888,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"SaveChangesBar.tsx:onSuccess","message":"save onSuccess - about to refetch","data":{},"timestamp":1768767508153,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":true,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":true},"timestamp":1768767509550,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:setBaseProduct","message":"updating baseProduct","data":{"frontendProductItemsCount":1,"frontendProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767509550,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767509550,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767509551,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"SaveChangesBar.tsx:onSuccess:afterRefetch","message":"refetch completed","data":{},"timestamp":1768767511210,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:end","message":"save completed","data":{"result":true},"timestamp":1768767511210,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767525751,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767525751,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767525751,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767525751,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"analytics","item1Interval":null,"item1IncludedUsage":null,"items2Count":1,"items2FeatureIds":["messages"]},"timestamp":1768767525751,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null}],"baseProductItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767525751,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767525757,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:start","message":"save clicked - before save","data":{"productId":"free_plan","itemsCount":2,"items":[{"feature_id":"messages","interval":null,"included_usage":10},{"feature_id":"analytics","interval":null,"included_usage":null}]},"timestamp":1768767526804,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"SaveChangesBar.tsx:onSuccess","message":"save onSuccess - about to refetch","data":{},"timestamp":1768767531740,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":true,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":true},"timestamp":1768767533130,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:setBaseProduct","message":"updating baseProduct","data":{"frontendProductItemsCount":2,"frontendProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfuuS2oOJiQBLwQrlKxo8TOM4"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767533131,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfuuS2oOJiQBLwQrlKxo8TOM4"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767533131,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"},{"feature_id":"analytics","interval":null,"included_usage":null}],"baseProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfuuS2oOJiQBLwQrlKxo8TOM4"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767533131,"sessionId":"debug-session","hypothesisId":"H1-H3"}
+{"location":"SaveChangesBar.tsx:onSuccess:afterRefetch","message":"refetch completed","data":{},"timestamp":1768767534789,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:end","message":"save completed","data":{"result":true},"timestamp":1768767534789,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767554592,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":true,"isVersionChanged":true,"isProductUpdated":true,"productId":"free_plan","productVersion":2,"willUpdate":true},"timestamp":1768767559098,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:setBaseProduct","message":"updating baseProduct","data":{"frontendProductItemsCount":2,"frontendProductItems":[{"feature_id":"analytics","entitlement_id":"ent_38RfuuS2oOJiQBLwQrlKxo8TOM4"},{"feature_id":"messages","interval":null,"included_usage":10,"reset_usage_when_enabled":true,"entitlement_id":"ent_38RfHdX9I9BqCWnytV2ylYvGgnu"}]},"timestamp":1768767559098,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767559099,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"useProductSync.ts:useEffect","message":"sync effect triggered","data":{"isNewProduct":false,"isVersionChanged":false,"isProductUpdated":false,"productId":"free_plan","productVersion":2,"lastProductId":"free_plan","lastProductVersion":2,"willUpdate":false},"timestamp":1768767559112,"sessionId":"debug-session","hypothesisId":"H4"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":null,"item1IncludedUsage":null,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767564109,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":null,"item1IncludedUsage":null,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767564109,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":null,"item1IncludedUsage":null,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767564109,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":null,"item1IncludedUsage":null,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767564109,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":null,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767568548,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":null,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767568548,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":null,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767568548,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":null,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767568548,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":2,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767569476,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":2,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767569476,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":2,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767569476,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":2,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767569476,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767569717,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767569717,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767569717,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767569717,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:start","message":"save clicked - before save","data":{"productId":"free_plan","itemsCount":3,"items":[{"feature_id":"analytics"},{"feature_id":"messages","interval":null,"included_usage":10},{"feature_id":"seats","interval":"month","included_usage":25}]},"timestamp":1768767573201,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767573208,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767573209,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767573209,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767573209,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"SaveChangesBar.tsx:handleSaveClicked:end","message":"save completed","data":{"result":false},"timestamp":1768767574954,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767575485,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767575485,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767575485,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"compareProductUtils.ts:productsAreSame:noSimilarItem","message":"no similar item found for item1","data":{"item1FeatureId":"seats","item1Interval":"month","item1IncludedUsage":25,"items2Count":2,"items2FeatureIds":["analytics","messages"]},"timestamp":1768767575485,"sessionId":"debug-session","hypothesisId":"H2-H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768767861061,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768767861062,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768492990,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768492990,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768494722,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768494722,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768494856,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768494857,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768503769,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768503770,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768509714,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768509714,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":0}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768510972,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":0}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768510973,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":0}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768512258,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":0}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768512259,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768513093,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768513093,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768513323,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768513323,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"compareItemUtils.ts:featurePriceItemsAreSame","message":"feature price items comparison failed","data":{"featureId":"seats","failedEntChecks":[{"check":"included_usage","message":"Included usage different: null != 0"}],"failedPriceChecks":[],"item1":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":null,\"interval\":\"month\",\"price\":4,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false,\"usage_model\":\"pay_per_use\",\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":0,\"interval\":\"month\",\"interval_count\":1,\"price\":4,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false,\"usage_model\":\"pay_per_use\",\"created_at\":1768768517976,\"entitlement_id\":\"ent_38Rhv08gZdC1AOrMvs20Gt4exbK\",\"price_id\":\"pr_38RhuzPJAjXGGc5JaF7JBQnKclZ\",\"price_config\":{\"type\":\"usage\",\"interval\":\"month\",\"bill_when\":\"end_of_period\",\"feature_id\":\"seats\",\"usage_tiers\":[{\"to\":\"inf\",\"amount\":4}],\"billing_units\":1,\"interval_count\":1,\"should_prorate\":true,\"stripe_price_id\":\"price_1Sr2gtG2wlWesuVT9hSb0qPO\",\"stripe_product_id\":\"prod_Tog21hujMdhsAJ\",\"internal_feature_id\":\"fe_38IUUvu4BoVK96JwbDZfJHwcRyD\",\"stripe_placeholder_price_id\":\"price_1Sr2guG2wlWesuVTfbCs2bkT\"},\"config\":{\"on_decrease\":\"prorate_immediately\",\"on_increase\":\"prorate_immediately\"},\"usage_limit\":null}"},"timestamp":1768768522738,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768522738,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"compareItemUtils.ts:featurePriceItemsAreSame","message":"feature price items comparison failed","data":{"featureId":"seats","failedEntChecks":[{"check":"included_usage","message":"Included usage different: null != 0"}],"failedPriceChecks":[],"item1":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":null,\"interval\":\"month\",\"price\":4,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false,\"usage_model\":\"pay_per_use\",\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":0,\"interval\":\"month\",\"interval_count\":1,\"price\":4,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false,\"usage_model\":\"pay_per_use\",\"created_at\":1768768517976,\"entitlement_id\":\"ent_38Rhv08gZdC1AOrMvs20Gt4exbK\",\"price_id\":\"pr_38RhuzPJAjXGGc5JaF7JBQnKclZ\",\"price_config\":{\"type\":\"usage\",\"interval\":\"month\",\"bill_when\":\"end_of_period\",\"feature_id\":\"seats\",\"usage_tiers\":[{\"to\":\"inf\",\"amount\":4}],\"billing_units\":1,\"interval_count\":1,\"should_prorate\":true,\"stripe_price_id\":\"price_1Sr2gtG2wlWesuVT9hSb0qPO\",\"stripe_product_id\":\"prod_Tog21hujMdhsAJ\",\"internal_feature_id\":\"fe_38IUUvu4BoVK96JwbDZfJHwcRyD\",\"stripe_placeholder_price_id\":\"price_1Sr2guG2wlWesuVTfbCs2bkT\"},\"config\":{\"on_decrease\":\"prorate_immediately\",\"on_increase\":\"prorate_immediately\"},\"usage_limit\":null}"},"timestamp":1768768522739,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareItemUtils.ts:featurePriceItemsAreSame","message":"feature price items comparison failed","data":{"featureId":"seats","failedEntChecks":[{"check":"included_usage","message":"Included usage different: null != 0"}],"failedPriceChecks":[],"item1":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":null,\"interval\":\"month\",\"price\":4,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false,\"usage_model\":\"pay_per_use\",\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":0,\"interval\":\"month\",\"interval_count\":1,\"price\":4,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false,\"usage_model\":\"pay_per_use\",\"created_at\":1768768517976,\"entitlement_id\":\"ent_38Rhv08gZdC1AOrMvs20Gt4exbK\",\"price_id\":\"pr_38RhuzPJAjXGGc5JaF7JBQnKclZ\",\"price_config\":{\"type\":\"usage\",\"interval\":\"month\",\"bill_when\":\"end_of_period\",\"feature_id\":\"seats\",\"usage_tiers\":[{\"to\":\"inf\",\"amount\":4}],\"billing_units\":1,\"interval_count\":1,\"should_prorate\":true,\"stripe_price_id\":\"price_1Sr2gtG2wlWesuVT9hSb0qPO\",\"stripe_product_id\":\"prod_Tog21hujMdhsAJ\",\"internal_feature_id\":\"fe_38IUUvu4BoVK96JwbDZfJHwcRyD\",\"stripe_placeholder_price_id\":\"price_1Sr2guG2wlWesuVTfbCs2bkT\"},\"config\":{\"on_decrease\":\"prorate_immediately\",\"on_increase\":\"prorate_immediately\"},\"usage_limit\":null}"},"timestamp":1768768522738,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"compareItemUtils.ts:featurePriceItemsAreSame","message":"feature price items comparison failed","data":{"featureId":"seats","failedEntChecks":[{"check":"included_usage","message":"Included usage different: null != 0"}],"failedPriceChecks":[],"item1":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":null,\"interval\":\"month\",\"price\":4,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false,\"usage_model\":\"pay_per_use\",\"config\":{\"on_increase\":\"prorate_immediately\",\"on_decrease\":\"prorate_immediately\"}}","item2":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":0,\"interval\":\"month\",\"interval_count\":1,\"price\":4,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false,\"usage_model\":\"pay_per_use\",\"created_at\":1768768517976,\"entitlement_id\":\"ent_38Rhv08gZdC1AOrMvs20Gt4exbK\",\"price_id\":\"pr_38RhuzPJAjXGGc5JaF7JBQnKclZ\",\"price_config\":{\"type\":\"usage\",\"interval\":\"month\",\"bill_when\":\"end_of_period\",\"feature_id\":\"seats\",\"usage_tiers\":[{\"to\":\"inf\",\"amount\":4}],\"billing_units\":1,\"interval_count\":1,\"should_prorate\":true,\"stripe_price_id\":\"price_1Sr2gtG2wlWesuVT9hSb0qPO\",\"stripe_product_id\":\"prod_Tog21hujMdhsAJ\",\"internal_feature_id\":\"fe_38IUUvu4BoVK96JwbDZfJHwcRyD\",\"stripe_placeholder_price_id\":\"price_1Sr2guG2wlWesuVTfbCs2bkT\"},\"config\":{\"on_decrease\":\"prorate_immediately\",\"on_increase\":\"prorate_immediately\"},\"usage_limit\":null}"},"timestamp":1768768522739,"sessionId":"debug-session","hypothesisId":"H3"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768522739,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768616773,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768616773,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768617686,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768617687,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768619603,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768619604,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768627805,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768627805,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768634551,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768634551,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":0}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768635559,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":0}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768635559,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768636851,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768636851,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768637168,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768637169,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768647252,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":[{"to":"inf","amount":4}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768647253,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768650150,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768650151,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768653414,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768653414,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":0}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768654738,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":0}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768654738,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":5}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768656050,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":5}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768656050,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":5}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768656372,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":5}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":"month","included_usage":0,"reset_usage_when_enabled":false,"price":null,"tiers":[{"amount":4,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768656373,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":5}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768657946,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":5}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768657947,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":5}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":0,"reset_usage_when_enabled":true,"price":null,"tiers":[{"amount":5,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768668632,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":null,"reset_usage_when_enabled":true,"price":null,"tiers":[{"to":"inf","amount":5}],"usage_model":"pay_per_use"}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":0,"reset_usage_when_enabled":true,"price":null,"tiers":[{"amount":5,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768668633,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":0,"reset_usage_when_enabled":true,"price":null,"tiers":[{"amount":5,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768670093,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":1,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":0,"reset_usage_when_enabled":true,"price":null,"tiers":[{"amount":5,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768670094,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":0,"reset_usage_when_enabled":true,"price":null,"tiers":[{"amount":5,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768675489,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"runs","feature_type":"single_use","interval":"month","included_usage":0,"reset_usage_when_enabled":true,"price":null,"tiers":[{"amount":5,"to":"inf"}],"usage_model":"pay_per_use"}]},"timestamp":1768768675489,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768677586,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":null,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768677586,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":5,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768678144,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":true,"itemsSame":false,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":1,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":5,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true}]},"timestamp":1768768678144,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"seats","failedChecks":[{"check":"included_usage","message":"Included usage different: 5 != null"}],"item1":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":5,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false}","item2":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false}"},"timestamp":1768768678144,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"seats","failedChecks":[{"check":"included_usage","message":"Included usage different: 5 != null"}],"item1":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":5,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false}","item2":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false}"},"timestamp":1768768678145,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"seats","failedChecks":[{"check":"included_usage","message":"Included usage different: 5 != null"}],"item1":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":5,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false}","item2":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false}"},"timestamp":1768768678145,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"compareItemUtils.ts:featureItemsAreSame","message":"feature items comparison failed","data":{"featureId":"seats","failedChecks":[{"check":"included_usage","message":"Included usage different: 5 != null"}],"item1":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":5,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false}","item2":"{\"feature_id\":\"seats\",\"feature_type\":\"continuous_use\",\"included_usage\":null,\"interval\":null,\"price\":null,\"tiers\":null,\"billing_units\":1,\"entity_feature_id\":null,\"reset_usage_when_enabled\":false}"},"timestamp":1768768678145,"sessionId":"debug-session","hypothesisId":"H2"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":5,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":5,"reset_usage_when_enabled":false}]},"timestamp":1768768686901,"sessionId":"debug-session","hypothesisId":"H1"}
+{"location":"useProductStore.ts:useHasChanges","message":"hasChanges computed","data":{"hasChanges":false,"itemsSame":true,"detailsSame":true,"freeTrialsSame":true,"productItemsCount":2,"baseProductItemsCount":2,"productItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":5,"reset_usage_when_enabled":false,"price":null,"tiers":null}],"baseProductItems":[{"feature_id":"messages","feature_type":"single_use","interval":null,"included_usage":10,"reset_usage_when_enabled":true},{"feature_id":"seats","feature_type":"continuous_use","interval":null,"included_usage":5,"reset_usage_when_enabled":false}]},"timestamp":1768768686901,"sessionId":"debug-session","hypothesisId":"H1"}
diff --git a/server/src/internal/customers/CusSearchService.ts b/server/src/internal/customers/CusSearchService.ts
index ae97f6228..972531e57 100644
--- a/server/src/internal/customers/CusSearchService.ts
+++ b/server/src/internal/customers/CusSearchService.ts
@@ -10,12 +10,14 @@ import {
and,
desc,
eq,
- gt, ilike, isNotNull,
+ gt,
+ ilike,
+ isNotNull,
isNull,
lt,
notExists,
or,
- sql
+ sql,
} from "drizzle-orm";
import { alias } from "drizzle-orm/pg-core";
import type { DrizzleCli } from "@/db/initDrizzle.js";
@@ -155,6 +157,16 @@ export class CusSearchService {
? or(
...statuses.map((status) => {
switch (status) {
+ case "active":
+ return and(
+ eq(customerProducts.status, CusProductStatus.Active),
+ isNull(customerProducts.canceled_at),
+ );
+ case "past_due":
+ return and(
+ eq(customerProducts.status, CusProductStatus.PastDue),
+ isNull(customerProducts.canceled_at),
+ );
case "canceled":
return and(
isNotNull(customerProducts.canceled_at),
@@ -164,6 +176,7 @@ export class CusSearchService {
return and(
gt(customerProducts.trial_ends_at, Date.now()),
isNotNull(customerProducts.free_trial_id),
+ isNull(customerProducts.canceled_at),
activeProdFilter,
);
case CusProductStatus.Expired:
@@ -513,7 +526,8 @@ export class CusSearchService {
});
}
- if (filters?.version && filters?.version.length > 0) {
+ // Call searchByProduct if we have version filters OR status filters
+ if ((filters?.version && filters?.version.length > 0) || (filters?.status && filters?.status.length > 0)) {
return await CusSearchService.searchByProduct({
db,
orgId,
@@ -642,7 +656,6 @@ export class CusSearchService {
return { data: finalResults, count: totalCount };
}
}
-
// // Legacy support for product_id field (if still used)
// let productIds: string[] = [];
// if (filters.product_id) {
diff --git a/shared/utils/productDisplayUtils.ts b/shared/utils/productDisplayUtils.ts
index 6ecfbbaec..637bb8b59 100644
--- a/shared/utils/productDisplayUtils.ts
+++ b/shared/utils/productDisplayUtils.ts
@@ -1,4 +1,7 @@
-import { FeatureType } from "../models/featureModels/featureEnums.js";
+import {
+ FeatureType,
+ FeatureUsageType,
+} from "../models/featureModels/featureEnums.js";
import type { Feature } from "../models/featureModels/featureModels.js";
import { Infinite } from "../models/productModels/productEnums.js";
import type { ProductItem } from "../models/productV2Models/productItemModels/productItemModels.js";
@@ -12,40 +15,84 @@ import {
} from "./productV2Utils/productItemUtils/getItemType.js";
import { notNullish, nullish } from "./utils.js";
+// ============================================================================
+// Types
+// ============================================================================
+
+interface DisplayResult {
+ primary_text: string;
+ secondary_text?: string;
+}
+
+interface FormatTiersParams {
+ item: ProductItem;
+ currency?: string | null;
+ amountFormatOptions?: Intl.NumberFormatOptions;
+}
+
+// ============================================================================
+// Helpers
+// ============================================================================
+
+const getIntervalDisplay = (item: ProductItem): string | undefined => {
+ if (!item.interval) return undefined;
+
+ return formatInterval({
+ interval: item.interval,
+ intervalCount: item.interval_count ?? undefined,
+ });
+};
+
+const getIncludedUsageText = (item: ProductItem, feature: Feature): string => {
+ const featureName = getFeatureName({
+ feature,
+ units: item.included_usage,
+ });
+
+ if (item.included_usage === Infinite) {
+ return `Unlimited ${featureName}`;
+ }
+
+ if (nullish(item.included_usage) || item.included_usage === 0) {
+ return `0 ${featureName}`;
+ }
+
+ return `${numberWithCommas(item.included_usage)} ${featureName}`;
+};
+
+const isSingleUseFeature = (feature: Feature): boolean => {
+ return feature.config?.usage_type === FeatureUsageType.Single;
+};
+
+// ============================================================================
+// Tier Formatting
+// ============================================================================
+
export const formatTiers = ({
item,
currency,
amountFormatOptions,
-}: {
- item: ProductItem;
- currency?: string | null;
- amountFormatOptions?: Intl.NumberFormatOptions;
-}) => {
+}: FormatTiersParams): string | undefined => {
const tiers = item.tiers;
- if (tiers) {
- if (tiers.length === 1) {
- return formatAmount({
- currency,
- amount: tiers[0].amount,
- amountFormatOptions,
- });
- }
+ if (!tiers) return undefined;
- const firstPrice = tiers[0].amount;
- const lastPrice = tiers[tiers.length - 1].amount;
+ const format = (amount: number) =>
+ formatAmount({ currency, amount, amountFormatOptions });
- return `${formatAmount({
- currency,
- amount: firstPrice,
- amountFormatOptions,
- })} - ${formatAmount({
- currency,
- amount: lastPrice,
- amountFormatOptions,
- })}`;
+ if (tiers.length === 1) {
+ return format(tiers[0].amount);
}
+
+ const firstPrice = tiers[0].amount;
+ const lastPrice = tiers[tiers.length - 1].amount;
+
+ return `${format(firstPrice)} - ${format(lastPrice)}`;
};
+// ============================================================================
+// Feature Item Display (no pricing, just entitlement)
+// ============================================================================
+
export const getFeatureItemDisplay = ({
item,
feature,
@@ -54,57 +101,30 @@ export const getFeatureItemDisplay = ({
item: ProductItem;
feature?: Feature;
fullDisplay?: boolean;
-}) => {
- if (!feature) throw new Error(`Feature ${item.feature_id} not found`);
+}): DisplayResult => {
+ if (!feature) {
+ // Return fallback display when feature is not found (e.g., during feature ID rename)
+ return { primary_text: item.feature_id || "Loading..." };
+ }
+ // Boolean features just show the name
if (feature.type === FeatureType.Boolean) {
return { primary_text: feature.name };
}
- const featureName = getFeatureName({
- feature,
- units: item.included_usage,
- });
+ const primaryText = getIncludedUsageText(item, feature);
- const includedUsageTxt =
- item.included_usage === Infinite
- ? "Unlimited "
- : nullish(item.included_usage) || item.included_usage === 0
- ? "0 "
- : `${numberWithCommas(item.included_usage)} `;
-
- // If interval is null for a feature item, it's a one-time/lifetime feature
- const intervalStr = item.interval
- ? formatInterval({
- interval: item.interval,
- intervalCount: item.interval_count ?? undefined,
- })
- : "one-off";
-
- return {
- primary_text: `${includedUsageTxt}${featureName}`,
- secondary_text: fullDisplay ? intervalStr : undefined,
- };
-};
-
-export const getPriceItemDisplay = ({
- item,
- currency,
-}: {
- item: ProductItem;
- currency?: string | null;
-}) => {
- const primaryText = formatAmount({
- currency,
- amount: item.price as number,
- });
-
- const intervalStr = formatInterval({
- interval: item.interval ?? undefined,
- intervalCount: item.interval_count ?? undefined,
- });
-
- const secondaryText = intervalStr || undefined;
+ // Determine secondary text (interval display)
+ let secondaryText: string | undefined;
+ if (fullDisplay) {
+ const intervalDisplay = getIntervalDisplay(item);
+ if (intervalDisplay) {
+ secondaryText = intervalDisplay;
+ } else if (isSingleUseFeature(feature)) {
+ // Only show "one-off" for single-use features, not continuous use
+ secondaryText = "one-off";
+ }
+ }
return {
primary_text: primaryText,
@@ -112,12 +132,39 @@ export const getPriceItemDisplay = ({
};
};
+// ============================================================================
+// Price Item Display (flat price, no feature)
+// ============================================================================
+
+export const getPriceItemDisplay = ({
+ item,
+ currency,
+}: {
+ item: ProductItem;
+ currency?: string | null;
+}): DisplayResult => {
+ const primaryText = formatAmount({
+ currency,
+ amount: item.price as number,
+ });
+
+ const secondaryText = getIntervalDisplay(item);
+
+ return {
+ primary_text: primaryText,
+ secondary_text: secondaryText,
+ };
+};
+
+// ============================================================================
+// Feature + Price Item Display (usage-based pricing)
+// ============================================================================
+
export const getFeaturePriceItemDisplay = ({
feature,
item,
currency,
isMainPrice = false,
- // minifyIncluded = false,
amountFormatOptions,
fullDisplay = false,
}: {
@@ -125,73 +172,77 @@ export const getFeaturePriceItemDisplay = ({
item: ProductItem;
currency?: string | null;
isMainPrice?: boolean;
- // minifyIncluded?: boolean;
amountFormatOptions?: Intl.NumberFormatOptions;
fullDisplay?: boolean;
-}) => {
+}): DisplayResult => {
if (!feature) {
throw new Error(`Feature ${item.feature_id} not found`);
}
- // 1. Get included usage
+ // Build included usage string (e.g., "100 credits")
+ const includedUsage = item.included_usage as number | null;
+ const hasIncludedUsage = notNullish(includedUsage) && includedUsage > 0;
+
const includedFeatureName = getFeatureName({
feature,
units: item.included_usage,
});
+ const includedUsageStr = hasIncludedUsage
+ ? `${numberWithCommas(includedUsage)} ${includedFeatureName}`
+ : "";
- const includedUsage = item.included_usage as number | null;
- let includedUsageStr = "";
- if (notNullish(includedUsage) && includedUsage > 0) {
- includedUsageStr = `${numberWithCommas(includedUsage)} ${includedFeatureName}`;
- }
-
+ // Build price string (e.g., "$0.01")
const priceStr = formatTiers({ item, currency, amountFormatOptions }) ?? "";
- // For "per X" display, use singular when billing_units is 1 or not specified
+ // Build billing unit string (e.g., "credit" or "100 credits")
const billingUnits = item.billing_units ?? 1;
const billingFeatureName = getFeatureName({
feature,
units: billingUnits,
});
+ const perUnitStr =
+ billingUnits > 1
+ ? `${numberWithCommas(billingUnits)} ${billingFeatureName}`
+ : billingFeatureName;
- let priceStr2 = "";
- if (billingUnits > 1) {
- priceStr2 = `${numberWithCommas(billingUnits)} ${billingFeatureName}`;
- } else {
- priceStr2 = `${billingFeatureName}`;
+ // Build interval string
+ const showInterval = isMainPrice || fullDisplay;
+ let intervalStr = "";
+ if (showInterval) {
+ const intervalDisplay = getIntervalDisplay(item);
+ if (intervalDisplay) {
+ intervalStr = intervalDisplay;
+ } else if (isSingleUseFeature(feature)) {
+ intervalStr = "one-off";
+ }
}
- // If interval is null for a priced feature, it's a one-time purchase
- const intervalStr =
- isMainPrice || fullDisplay
- ? item.interval
- ? formatInterval({
- interval: item.interval,
- intervalCount: item.interval_count ?? undefined,
- })
- : "one-off"
- : "";
-
- if (includedUsageStr) {
+ // Format output based on what we have
+ if (hasIncludedUsage) {
return {
primary_text: includedUsageStr,
- secondary_text: `then ${priceStr} per ${priceStr2} ${intervalStr}`,
+ secondary_text:
+ `then ${priceStr} per ${perUnitStr} ${intervalStr}`.trim(),
};
}
- if (isMainPrice || fullDisplay) {
+ if (showInterval) {
return {
primary_text: priceStr,
- secondary_text: `per ${priceStr2} ${intervalStr}`,
+ secondary_text: `per ${perUnitStr} ${intervalStr}`.trim(),
};
}
return {
- primary_text: `${priceStr} per ${priceStr2} ${intervalStr}`,
+ primary_text: `${priceStr} per ${perUnitStr}`.trim(),
secondary_text: undefined,
};
};
+// ============================================================================
+// Main Entry Point
+// ============================================================================
+
export const getProductItemDisplay = ({
item,
features,
@@ -204,26 +255,25 @@ export const getProductItemDisplay = ({
currency?: string | null;
fullDisplay?: boolean;
amountFormatOptions?: Intl.NumberFormatOptions;
-}) => {
+}): DisplayResult => {
+ const findFeature = () => features.find((f) => f.id === item.feature_id);
+
if (isFeatureItem(item)) {
return getFeatureItemDisplay({
item,
- feature: features.find((f) => f.id === item.feature_id),
+ feature: findFeature(),
fullDisplay,
});
}
if (isPriceItem(item)) {
- return getPriceItemDisplay({
- item,
- currency,
- });
+ return getPriceItemDisplay({ item, currency });
}
if (isFeaturePriceItem(item)) {
return getFeaturePriceItemDisplay({
item,
- feature: features.find((f) => f.id === item.feature_id),
+ feature: findFeature(),
currency,
fullDisplay,
amountFormatOptions,
diff --git a/shared/utils/productV2Utils/compareProductUtils/compareItemUtils.ts b/shared/utils/productV2Utils/compareProductUtils/compareItemUtils.ts
index f2401e365..ed0fb3277 100644
--- a/shared/utils/productV2Utils/compareProductUtils/compareItemUtils.ts
+++ b/shared/utils/productV2Utils/compareProductUtils/compareItemUtils.ts
@@ -103,6 +103,12 @@ const tiersAreSame = (
);
};
+// Helper to normalize included_usage for comparison (null and 0 are equivalent)
+const normalizeIncludedUsage = (value: number | "inf" | null | undefined) => {
+ if (value === null || value === undefined) return 0;
+ return value;
+};
+
export const featureItemsAreSame = ({
item1,
item2,
@@ -118,7 +124,10 @@ export const featureItemsAreSame = ({
message: `Feature ID different: ${item1.feature_id} != ${item2.feature_id}`,
},
included_usage: {
- condition: item1.included_usage == item2.included_usage,
+ // Normalize null/undefined to 0 for comparison since they're semantically equivalent
+ condition:
+ normalizeIncludedUsage(item1.included_usage) ==
+ normalizeIncludedUsage(item2.included_usage),
message: `Included usage different: ${item1.included_usage} != ${item2.included_usage}`,
},
interval: {
@@ -232,7 +241,10 @@ export const featurePriceItemsAreSame = ({
// console.log("Item 2 config:", item2.config);
const entsSame = {
included_usage: {
- condition: item1.included_usage == item2.included_usage,
+ // Normalize null/undefined to 0 for comparison since they're semantically equivalent
+ condition:
+ normalizeIncludedUsage(item1.included_usage) ==
+ normalizeIncludedUsage(item2.included_usage),
message: `Included usage different: ${item1.included_usage} != ${item2.included_usage}`,
},
usage_limit: {
diff --git a/vite/src/components/general/table/table-header.tsx b/vite/src/components/general/table/table-header.tsx
index 306869073..74400b5f5 100644
--- a/vite/src/components/general/table/table-header.tsx
+++ b/vite/src/components/general/table/table-header.tsx
@@ -14,7 +14,7 @@ function SortIcon({ sortDirection }: { sortDirection: string | false }) {
return (
);
@@ -23,7 +23,7 @@ function SortIcon({ sortDirection }: { sortDirection: string | false }) {
return (
);
diff --git a/vite/src/components/v2/inline-custom-plan-editor/InlinePlanEditor.tsx b/vite/src/components/v2/inline-custom-plan-editor/InlinePlanEditor.tsx
index fe29d9819..ce4337767 100644
--- a/vite/src/components/v2/inline-custom-plan-editor/InlinePlanEditor.tsx
+++ b/vite/src/components/v2/inline-custom-plan-editor/InlinePlanEditor.tsx
@@ -3,6 +3,7 @@ import { AnimatePresence, motion } from "motion/react";
import { createPortal } from "react-dom";
import { Button } from "@/components/v2/buttons/Button";
import { ShortcutButton } from "@/components/v2/buttons/ShortcutButton";
+import { SheetOverlay } from "@/components/v2/sheet-overlay/SheetOverlay";
import { cn } from "@/lib/utils";
import { CustomerPlanInfoBox } from "@/views/customers2/customer-plan/CustomerPlanInfoBox";
import { EditPlanHeader } from "@/views/products/plan/components/EditPlanHeader";
@@ -53,7 +54,7 @@ function InlinePlanEditorContent({
onCancel: () => void;
}) {
const { product } = useProduct();
- const { sheetType, closeSheet } = useSheet();
+ const { sheetType } = useSheet();
const hasPlanChanges = useHasPlanChanges();
return (
@@ -63,6 +64,7 @@ function InlinePlanEditorContent({
exit={{ opacity: 0, scale: 0.97, y: 8 }}
transition={{ duration: 0.2, ease: [0.16, 1, 0.3, 1] }}
className="absolute inset-0 z-100 bg-background flex flex-col"
+ data-inline-editor-open
>
-
- {sheetType && (
- closeSheet()}
- />
- )}
-
+
diff --git a/vite/src/components/v2/selects/Select.tsx b/vite/src/components/v2/selects/Select.tsx
index 66d90a10e..a957b878e 100644
--- a/vite/src/components/v2/selects/Select.tsx
+++ b/vite/src/components/v2/selects/Select.tsx
@@ -104,8 +104,8 @@ function SelectContent({
;
+ item: ProductItem | null;
+ sheetType: string | null;
+ hasItemChanges: boolean;
+}): boolean {
+ // Don't close if item has unsaved changes
+ if (hasItemChanges) {
+ return false;
+ }
+
+ // Get the active element before blur happens
+ const activeElement = document.activeElement;
+
+ if (
+ activeElement &&
+ activeElement !== document.body &&
+ activeElement instanceof HTMLElement
+ ) {
+ // Only apply blur behavior to inputs, textareas, and selects
+ const isInputElement =
+ activeElement.tagName === "INPUT" ||
+ activeElement.tagName === "TEXTAREA" ||
+ activeElement.tagName === "SELECT";
+
+ if (!isInputElement) {
+ // Not an input, proceed with normal close behavior
+ return !!sheetType;
+ }
+
+ // Check if the active element is within the sheet (not in the main content area)
+ const clickTarget = e.target as HTMLElement;
+ const isActiveInSheet = !clickTarget.contains(activeElement);
+
+ if (isActiveInSheet) {
+ activeElement.blur();
+ e.preventDefault(); // Prevent default to stop the click from propagating
+ return false;
+ }
+ }
+
+ // If the click is outside the sheet and no input is focused, close the sheet
+ return !!sheetType;
+}
+
+/**
+ * Shared overlay component for plan editors.
+ * Portals to [data-main-content] by default, or renders inline if `inline` prop is true.
+ */
+export function SheetOverlay({ inline = false }: { inline?: boolean }) {
+ const { sheetType, closeSheet } = useSheet();
+ const item = useCurrentItem();
+ const hasItemChanges = useHasItemChanges();
+
+ const handleMouseDown = (e: React.MouseEvent) => {
+ if (shouldCloseSheetOnMouseDown({ e, item, sheetType, hasItemChanges })) {
+ closeSheet();
+ }
+ };
+
+ const overlay = (
+
+ {sheetType && (
+
+ )}
+
+ );
+
+ if (inline) {
+ return overlay;
+ }
+
+ const mainContent = document.querySelector("[data-main-content]");
+ if (!mainContent) {
+ console.error("[SheetOverlay] Could not find portal target");
+ return null;
+ }
+
+ return createPortal(overlay, mainContent);
+}
diff --git a/vite/src/components/v2/sheets/SharedSheetComponents.tsx b/vite/src/components/v2/sheets/SharedSheetComponents.tsx
index 72e2b61fd..e5e460367 100644
--- a/vite/src/components/v2/sheets/SharedSheetComponents.tsx
+++ b/vite/src/components/v2/sheets/SharedSheetComponents.tsx
@@ -14,6 +14,7 @@ interface SheetHeaderProps {
isOnboarding?: boolean;
breadcrumbs?: { name: string; sheet?: string }[];
itemId?: string | null;
+ action?: React.ReactNode;
}
export function SheetHeader({
@@ -25,6 +26,7 @@ export function SheetHeader({
className,
isOnboarding = false,
itemId,
+ action,
}: SheetHeaderProps) {
return (
@@ -37,16 +39,19 @@ export function SheetHeader({
) : (
{title}
)}
-
- {description}
-
+
+
+ {description}
+
+ {action}
+
{children}
- {!noSeparator &&
}
+ {!noSeparator &&
}
);
}
diff --git a/vite/src/components/v2/sheets/Sheet.tsx b/vite/src/components/v2/sheets/Sheet.tsx
index c92088c0d..6453c32f7 100644
--- a/vite/src/components/v2/sheets/Sheet.tsx
+++ b/vite/src/components/v2/sheets/Sheet.tsx
@@ -1,13 +1,10 @@
"use client";
-import { AppEnv } from "@autumn/shared";
import * as SheetPrimitive from "@radix-ui/react-dialog";
import { XIcon } from "lucide-react";
import type * as React from "react";
-import { usePortalContainer } from "@/contexts/PortalContainerContext";
import { cn } from "@/lib/utils";
-import { useEnv } from "@/utils/envUtils";
function Sheet({ ...props }: React.ComponentProps) {
return ;
@@ -28,11 +25,11 @@ function SheetClose({
function SheetPortal({
...props
}: React.ComponentProps) {
- const containerRef = usePortalContainer();
+ const mainContent = document.querySelector("[data-main-content]");
return (
);
@@ -46,7 +43,7 @@ function SheetOverlay({
diff --git a/vite/src/views/customers/components/filter-dropdown/FilterStatusSubMenu.tsx b/vite/src/views/customers/components/filter-dropdown/FilterStatusSubMenu.tsx
index 47db5d267..b180b4325 100644
--- a/vite/src/views/customers/components/filter-dropdown/FilterStatusSubMenu.tsx
+++ b/vite/src/views/customers/components/filter-dropdown/FilterStatusSubMenu.tsx
@@ -1,17 +1,23 @@
+import { Checkbox } from "@/components/v2/checkboxes/Checkbox";
import {
+ DropdownMenuItem,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
- DropdownMenuItem,
} from "@/components/v2/dropdowns/DropdownMenu";
-import { Checkbox } from "@/components/v2/checkboxes/Checkbox";
import { keyToTitle } from "@/utils/formatUtils/formatTextUtils";
import { useCustomersQueryStates } from "../../hooks/useCustomersQueryStates";
export const FilterStatusSubMenu = () => {
- const { queryStates, setQueryStates } = useCustomersQueryStates();
+ const { queryStates, setFilters } = useCustomersQueryStates();
- const statuses: string[] = ["canceled", "free_trial", "expired"];
+ const statuses: string[] = [
+ "active",
+ "past_due",
+ "canceled",
+ "free_trial",
+ "expired",
+ ];
const selectedStatuses = queryStates.status || [];
const hasSelections = selectedStatuses.length > 0;
@@ -23,7 +29,7 @@ export const FilterStatusSubMenu = () => {
? selected.filter((s: string) => s !== status)
: [...selected, status];
- setQueryStates({ ...queryStates, status: updated });
+ setFilters({ status: updated });
};
return (
diff --git a/vite/src/views/customers/components/filter-dropdown/ProductsSubMenu.tsx b/vite/src/views/customers/components/filter-dropdown/ProductsSubMenu.tsx
index fd835c4a8..26a43c2b8 100644
--- a/vite/src/views/customers/components/filter-dropdown/ProductsSubMenu.tsx
+++ b/vite/src/views/customers/components/filter-dropdown/ProductsSubMenu.tsx
@@ -1,19 +1,19 @@
+import { Checkbox } from "@/components/v2/checkboxes/Checkbox";
import {
+ DropdownMenuItem,
+ DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
- DropdownMenuSeparator,
- DropdownMenuItem,
} from "@/components/v2/dropdowns/DropdownMenu";
-import { Checkbox } from "@/components/v2/checkboxes/Checkbox";
-import { cn } from "@/lib/utils";
-import { useCustomersQueryStates } from "../../hooks/useCustomersQueryStates";
import { useProductsQuery } from "@/hooks/queries/useProductsQuery";
+import { cn } from "@/lib/utils";
import { getVersionCounts } from "@/utils/productUtils";
+import { useCustomersQueryStates } from "../../hooks/useCustomersQueryStates";
export const ProductsSubMenu = () => {
const { products } = useProductsQuery();
- const { queryStates, setQueryStates } = useCustomersQueryStates();
+ const { queryStates, setFilters } = useCustomersQueryStates();
const versionCounts = getVersionCounts(products);
const selectedVersions = queryStates.version;
@@ -63,14 +63,9 @@ export const ProductsSubMenu = () => {
allProductVersions.length > 0 &&
allProductVersions.every((pv) => selectedVersions.includes(pv.key));
if (allSelected) {
- setQueryStates({
- ...queryStates,
- version: [],
- none: false,
- });
+ setFilters({ version: [], none: false });
} else {
- setQueryStates({
- ...queryStates,
+ setFilters({
version: allProductVersions.map((pv) => pv.key),
none: false,
});
@@ -88,7 +83,7 @@ export const ProductsSubMenu = () => {
selectedVersions.includes(key),
);
- let newSelectedVersions;
+ let newSelectedVersions: string[] = [];
let newNone = queryStates.none;
if (allProductVersionsSelected) {
// Deselect all versions of this product
@@ -104,18 +99,14 @@ export const ProductsSubMenu = () => {
newNone = false;
}
- setQueryStates({
- ...queryStates,
- version: newSelectedVersions,
- none: newNone,
- });
+ setFilters({ version: newSelectedVersions, none: newNone });
};
const toggleVersion = (productId: string, version: string) => {
const versionKey = `${productId}:${version}`;
const isSelected = selectedVersions.includes(versionKey);
- let newSelectedVersions;
+ let newSelectedVersions: string[] = [];
let newNone = queryStates.none;
if (isSelected) {
newSelectedVersions = selectedVersions.filter(
@@ -126,28 +117,20 @@ export const ProductsSubMenu = () => {
newNone = false;
}
- setQueryStates({
- ...queryStates,
- version: newSelectedVersions,
- none: newNone,
- });
+ setFilters({ version: newSelectedVersions, none: newNone });
};
const handleSelectNone = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
- setQueryStates({
- ...queryStates,
- version: [],
- none: !queryStates.none,
- });
+ setFilters({ version: [], none: !queryStates.none });
};
return (
- Products
+ Plans
{hasSelections && (
{selectedProductsCount}
@@ -163,17 +146,21 @@ export const ProductsSubMenu = () => {
<>
- {uniqueProducts?.map((product: any) => {
- const versionCount = versionCounts?.[product.id] || 1;
- const productVersionKeys = Array.from(
- { length: versionCount },
- (_, i) => `${product.id}:${i + 1}`,
- );
- const allProductVersionsSelected = productVersionKeys.every((key) =>
- selectedVersions.includes(key),
- );
- const someProductVersionsSelected = productVersionKeys.some((key) =>
- selectedVersions.includes(key),
- );
+ {uniqueProducts?.map((product: any) => {
+ const versionCount = versionCounts?.[product.id] || 1;
+ const productVersionKeys = Array.from(
+ { length: versionCount },
+ (_, i) => `${product.id}:${i + 1}`,
+ );
+ const allProductVersionsSelected = productVersionKeys.every(
+ (key) => selectedVersions.includes(key),
+ );
+ const someProductVersionsSelected = productVersionKeys.some(
+ (key) => selectedVersions.includes(key),
+ );
- return (
-
- {versionCount === 1 ? (
- // Single version - show just one button for the product
-
{
- e.preventDefault();
- toggleVersion(product.id, "1");
- }}
- onSelect={(e) => e.preventDefault()}
- className="flex items-center gap-2 cursor-pointer font-medium"
- >
-
- {product.name}
-
- ) : (
- // Multiple versions - show product name with hover submenu for versions
-
- {
- e.preventDefault();
- toggleProduct(product);
- }}
- >
- {
- if (
- ref &&
- someProductVersionsSelected &&
- !allProductVersionsSelected
- ) {
- ref.indeterminate = true;
- }
- }}
- />
- {product.name}
-
-
+ return (
+
+ {versionCount === 1 ? (
+ // Single version - show just one button for the product
{
e.preventDefault();
- toggleProduct(product);
+ toggleVersion(product.id, "1");
}}
onSelect={(e) => e.preventDefault()}
className="flex items-center gap-2 cursor-pointer font-medium"
>
-
- All Versions
+
+ {product.name}
-
- {Array.from(
- { length: versionCount },
- (_, i) => i + 1,
- ).map((version) => {
- const versionKey = `${product.id}:${version}`;
- const isVersionSelected =
- selectedVersions.includes(versionKey);
-
- return (
+ ) : (
+ // Multiple versions - show product name with hover submenu for versions
+
+ {
+ e.preventDefault();
+ toggleProduct(product);
+ }}
+ >
+ {
+ if (
+ ref &&
+ someProductVersionsSelected &&
+ !allProductVersionsSelected
+ ) {
+ ref.indeterminate = true;
+ }
+ }}
+ />
+ {product.name}
+
+
{
e.preventDefault();
- toggleVersion(product.id, version.toString());
+ toggleProduct(product);
}}
onSelect={(e) => e.preventDefault()}
- className="flex items-center gap-2 cursor-pointer text-sm"
+ className="flex items-center gap-2 cursor-pointer font-medium"
>
- v{version}
+
+ All Versions
- );
- })}
-
-
- )}
-
- );
- })}
-
- >
- )}
+
+ {Array.from(
+ { length: versionCount },
+ (_, i) => i + 1,
+ ).map((version) => {
+ const versionKey = `${product.id}:${version}`;
+ const isVersionSelected =
+ selectedVersions.includes(versionKey);
+
+ return (
+
{
+ e.preventDefault();
+ toggleVersion(product.id, version.toString());
+ }}
+ onSelect={(e) => e.preventDefault()}
+ className="flex items-center gap-2 cursor-pointer text-sm"
+ >
+
+ v{version}
+
+ );
+ })}
+
+
+ )}
+
+ );
+ })}
+
+ >
+ )}
);
diff --git a/vite/src/views/customers/components/filter-dropdown/SavedViews.tsx b/vite/src/views/customers/components/filter-dropdown/SavedViews.tsx
index db5744939..21766b5b1 100644
--- a/vite/src/views/customers/components/filter-dropdown/SavedViews.tsx
+++ b/vite/src/views/customers/components/filter-dropdown/SavedViews.tsx
@@ -1,3 +1,7 @@
+import { TrashIcon } from "@phosphor-icons/react";
+import { useState } from "react";
+import { toast } from "sonner";
+import { Button } from "@/components/ui/button";
import {
DropdownMenuGroup,
DropdownMenuItem,
@@ -9,13 +13,8 @@ import {
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
-import { Button } from "@/components/ui/button";
-
-import { toast } from "sonner";
-import { getBackendErr } from "@/utils/genUtils";
import { useAxiosInstance } from "@/services/useAxiosInstance";
-import { Delete } from "lucide-react";
-import { useState } from "react";
+import { getBackendErr } from "@/utils/genUtils";
import { useCustomersQueryStates } from "../../hooks/useCustomersQueryStates";
interface SavedView {
@@ -34,7 +33,7 @@ export const SavedViews = ({
mutateViews: any;
setDropdownOpen: (open: boolean) => void;
}) => {
- const { setQueryStates } = useCustomersQueryStates();
+ const { setFilters } = useCustomersQueryStates();
const axiosInstance = useAxiosInstance();
const [deletingViewId, setDeletingViewId] = useState(null);
@@ -44,24 +43,17 @@ export const SavedViews = ({
const decodedParams = atob(view.filters);
const params = new URLSearchParams(decodedParams);
- // Apply all parameters using setQueryStates (this will reset pagination automatically)
+ // Apply all parameters using setFilters (this will reset pagination automatically)
const statusParam = params.get("status") || "";
const versionParam = params.get("version") || "";
const noneParam = params.get("none");
- const queryParams = {
- page: 1,
+ setFilters({
q: params.get("q") || "",
status: statusParam ? statusParam.split(",").filter(Boolean) : [],
version: versionParam ? versionParam.split(",").filter(Boolean) : [],
none: noneParam === "true",
- lastItemId: "",
- };
-
- setQueryStates(queryParams);
-
- // Explicitly trigger a data refetch to ensure the view is applied immediately
- // await mutate();
+ });
toast.success(`Applied filters from ${view.name} view`);
} catch (error) {
@@ -95,7 +87,7 @@ export const SavedViews = ({
{views.map((view: SavedView) => (
{
await applyView(view);
setDropdownOpen(false);
@@ -110,18 +102,22 @@ export const SavedViews = ({
e.preventDefault()}
onCloseAutoFocus={(e) => e.preventDefault()}
>
diff --git a/vite/src/views/customers/components/filter-dropdown/SavedViewsDropdown.tsx b/vite/src/views/customers/components/filter-dropdown/SavedViewsDropdown.tsx
index 482baabac..9e3595826 100644
--- a/vite/src/views/customers/components/filter-dropdown/SavedViewsDropdown.tsx
+++ b/vite/src/views/customers/components/filter-dropdown/SavedViewsDropdown.tsx
@@ -1,3 +1,5 @@
+import { BookmarkIcon, Trash2 } from "lucide-react";
+import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
@@ -10,8 +12,6 @@ import {
} from "@/components/ui/dropdown-menu";
import { useAxiosInstance } from "@/services/useAxiosInstance";
import { getBackendErr } from "@/utils/genUtils";
-import { BookmarkIcon, Trash2 } from "lucide-react";
-import { toast } from "sonner";
import { useCustomersQueryStates } from "../../hooks/useCustomersQueryStates";
import { useSavedViewsQuery } from "../../hooks/useSavedViewsQuery";
@@ -119,6 +119,7 @@ export const SavedViewsDropdown = () => {
>
{view.name}
- {!hasRows && hasSearchQuery ? (
+ {!hasRows && hasActiveFiltersOrSearch ? (
}
diff --git a/vite/src/views/customers2/components/table/customer-products/CustomerProductsColumns.tsx b/vite/src/views/customers2/components/table/customer-products/CustomerProductsColumns.tsx
index 983a5962d..6074e950a 100644
--- a/vite/src/views/customers2/components/table/customer-products/CustomerProductsColumns.tsx
+++ b/vite/src/views/customers2/components/table/customer-products/CustomerProductsColumns.tsx
@@ -50,6 +50,7 @@ export const CustomerProductsColumns = [
status={row.original.status}
starts_at={row.original.starts_at ?? undefined}
canceled={row.original.canceled}
+ canceled_at={row.original.canceled_at ?? undefined}
trialing={isCustomerProductTrialing(row.original) || false}
trial_ends_at={row.original.trial_ends_at ?? undefined}
/>
diff --git a/vite/src/views/customers2/components/table/customer-products/CustomerProductsStatus.tsx b/vite/src/views/customers2/components/table/customer-products/CustomerProductsStatus.tsx
index 2a9dbfe02..c159dd9e0 100644
--- a/vite/src/views/customers2/components/table/customer-products/CustomerProductsStatus.tsx
+++ b/vite/src/views/customers2/components/table/customer-products/CustomerProductsStatus.tsx
@@ -14,15 +14,29 @@ const StatusItem = ({
children,
text,
trial_ends_at,
+ canceled_at,
tooltip,
className,
}: {
children: React.ReactNode;
text: string;
trial_ends_at?: number;
+ canceled_at?: number;
tooltip?: boolean;
className?: string;
}) => {
+ const getSubtext = () => {
+ if (trial_ends_at) {
+ return `${formatDistanceToNow(trial_ends_at)} left`;
+ }
+ if (canceled_at) {
+ return `${formatDistanceToNow(canceled_at)} ago`;
+ }
+ return null;
+ };
+
+ const subtext = getSubtext();
+
return (
{tooltip ? (
@@ -31,10 +45,8 @@ const StatusItem = ({
{children}
{text}
- {trial_ends_at && (
-
- ({formatDistanceToNow(trial_ends_at)} left)
-
+ {subtext && (
+ ({subtext})
)}
@@ -45,12 +57,10 @@ const StatusItem = ({
{children}
{text}
- {trial_ends_at && (
+ {subtext && (
<>
-
- {formatDistanceToNow(trial_ends_at)} left
-
+ {subtext}
>
)}
>
@@ -63,6 +73,7 @@ export const CustomerProductsStatus = ({
tooltip,
status,
canceled,
+ canceled_at,
trialing,
trial_ends_at,
starts_at,
@@ -70,6 +81,7 @@ export const CustomerProductsStatus = ({
status?: CusProductStatus;
tooltip?: boolean;
canceled?: boolean;
+ canceled_at?: number;
trialing?: boolean;
trial_ends_at?: number;
starts_at?: number;
@@ -105,7 +117,7 @@ export const CustomerProductsStatus = ({
// If product is canceled, show that status
if (canceled) {
return (
-
+
{
icon: ,
},
{
- title: "Features",
+ title: "Plan Features",
value: "features",
icon: ,
},
diff --git a/vite/src/views/onboarding4/OnboardingGuide.tsx b/vite/src/views/onboarding4/OnboardingGuide.tsx
index c7377c462..5ab58311f 100644
--- a/vite/src/views/onboarding4/OnboardingGuide.tsx
+++ b/vite/src/views/onboarding4/OnboardingGuide.tsx
@@ -105,9 +105,9 @@ function StepCard({
animate={{ flex: isActive ? 4 : 1 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className={cn(
- "relative rounded-xl border bg-card cursor-pointer h-29 overflow-hidden",
+ "relative border dark:border-none rounded-xl bg-card cursor-pointer h-29 overflow-hidden",
isActive
- ? "border-primary/30"
+ ? ""
: "hover:border-primary/20 hover:bg-interactive-secondary-hover",
isComplete && !isActive && "opacity-50",
)}
diff --git a/vite/src/views/products/features/components/UpdateFeatureSheet.tsx b/vite/src/views/products/features/components/UpdateFeatureSheet.tsx
index 0baa1f65c..fc95bad06 100644
--- a/vite/src/views/products/features/components/UpdateFeatureSheet.tsx
+++ b/vite/src/views/products/features/components/UpdateFeatureSheet.tsx
@@ -22,12 +22,14 @@ interface UpdateFeatureSheetProps {
open: boolean;
setOpen: (open: boolean) => void;
selectedFeature: Feature | null;
+ onSuccess?: (oldId: string, newId: string) => void;
}
function UpdateFeatureSheet({
open,
setOpen,
selectedFeature,
+ onSuccess,
}: UpdateFeatureSheetProps) {
const [loading, setLoading] = useState(false);
@@ -63,6 +65,12 @@ function UpdateFeatureSheet({
await refetch();
toast.success("Feature updated successfully");
+
+ // Call onSuccess with old and new IDs, if it's updated from the plan editor to update the plan items.
+ if (onSuccess) {
+ onSuccess(selectedFeature.id, feature.id);
+ }
+
setOpen(false);
} catch (error: unknown) {
console.log(error);
diff --git a/vite/src/views/products/features/credit-systems/components/UpdateCreditSystemSheet.tsx b/vite/src/views/products/features/credit-systems/components/UpdateCreditSystemSheet.tsx
index 847f208db..5fbc54192 100644
--- a/vite/src/views/products/features/credit-systems/components/UpdateCreditSystemSheet.tsx
+++ b/vite/src/views/products/features/credit-systems/components/UpdateCreditSystemSheet.tsx
@@ -21,12 +21,14 @@ interface UpdateCreditSystemSheetProps {
open: boolean;
setOpen: (open: boolean) => void;
selectedCreditSystem: Feature | null;
+ onSuccess?: (oldId: string, newId: string) => void;
}
function UpdateCreditSystemSheet({
open,
setOpen,
selectedCreditSystem,
+ onSuccess,
}: UpdateCreditSystemSheetProps) {
const [loading, setLoading] = useState(false);
const [creditSystem, setCreditSystem] = useState({
@@ -92,6 +94,12 @@ function UpdateCreditSystemSheet({
await refetch();
toast.success("Credit system updated successfully");
+
+ // Call onSuccess with old and new IDs
+ if (onSuccess) {
+ onSuccess(selectedCreditSystem.id, creditSystem.id || selectedCreditSystem.id);
+ }
+
setOpen(false);
} catch (error: unknown) {
console.log(error);
diff --git a/vite/src/views/products/plan/components/PlanEditor.tsx b/vite/src/views/products/plan/components/PlanEditor.tsx
index 1601fe5ba..2fd6ddce4 100644
--- a/vite/src/views/products/plan/components/PlanEditor.tsx
+++ b/vite/src/views/products/plan/components/PlanEditor.tsx
@@ -1,10 +1,6 @@
-import { AnimatePresence, motion } from "motion/react";
-import { createPortal } from "react-dom";
-import {
- useCurrentItem,
- useHasItemChanges,
- useIsCusPlanEditor,
-} from "@/hooks/stores/useProductStore";
+import { motion } from "motion/react";
+import { SheetOverlay } from "@/components/v2/sheet-overlay/SheetOverlay";
+import { useIsCusPlanEditor } from "@/hooks/stores/useProductStore";
import { useSheetStore } from "@/hooks/stores/useSheetStore";
import { CustomerPlanEditorBar } from "@/views/customers2/customer-plan/CustomerPlanEditorBar";
import { CustomerPlanInfoBox } from "@/views/customers2/customer-plan/CustomerPlanInfoBox";
@@ -14,66 +10,8 @@ import { EditPlanHeader } from "./EditPlanHeader";
import PlanCard from "./plan-card/PlanCard";
import { SaveChangesBar } from "./SaveChangesBar";
-function shouldCloseSheetOnMouseDown({
- e,
- item,
- sheetType,
- hasItemChanges,
-}: {
- e: React.MouseEvent;
- item: ReturnType;
- sheetType: string | null;
- hasItemChanges: boolean;
-}): boolean {
- // Don't close if item has unsaved changes
- if (hasItemChanges) {
- return false;
- }
-
- // Don't close if item is invalid
- // if (item && !checkItemIsValid(item, false)) {
- // return false;
- // }
-
- // Get the active element before blur happens
- const activeElement = document.activeElement;
-
- if (
- activeElement &&
- activeElement !== document.body &&
- activeElement instanceof HTMLElement
- ) {
- // Only apply blur behavior to inputs, textareas, and selects
- const isInputElement =
- activeElement.tagName === "INPUT" ||
- activeElement.tagName === "TEXTAREA" ||
- activeElement.tagName === "SELECT";
-
- if (!isInputElement) {
- // Not an input, proceed with normal close behavior
- return !!sheetType;
- }
-
- // Check if the active element is within the sheet (not in the main content area)
- const clickTarget = e.target as HTMLElement;
- const isActiveInSheet = !clickTarget.contains(activeElement);
-
- if (isActiveInSheet) {
- activeElement.blur();
- e.preventDefault(); // Prevent default to stop the click from propagating
- return false;
- }
- }
-
- // If the click is outside the sheet and no input is focused, close the sheet
- return !!sheetType;
-}
-
export const PlanEditor = () => {
- const closeSheet = useSheetStore((s) => s.closeSheet);
const sheetType = useSheetStore((s) => s.type);
- const item = useCurrentItem();
- const hasItemChanges = useHasItemChanges();
return (
@@ -100,32 +38,7 @@ export const PlanEditor = () => {
)}
- {createPortal(
-
- {sheetType && (
- {
- if (
- shouldCloseSheetOnMouseDown({
- e,
- item,
- sheetType,
- hasItemChanges,
- })
- ) {
- closeSheet();
- }
- }}
- />
- )}
- ,
- document.body,
- )}
+
diff --git a/vite/src/views/products/plan/components/SaveChangesBar.tsx b/vite/src/views/products/plan/components/SaveChangesBar.tsx
index 2ee2c04b7..b74aaf63e 100644
--- a/vite/src/views/products/plan/components/SaveChangesBar.tsx
+++ b/vite/src/views/products/plan/components/SaveChangesBar.tsx
@@ -128,9 +128,9 @@ export const SaveChangesBar = ({
You have unsaved changes
-
+
{
+ if (oldId !== newId && product.items) {
+ // Wait for features to be refetched to avoid race condition
+ await refetch();
+ // Update the feature_id in the product item
+ const updatedItems = product.items.map((i) =>
+ i.feature_id === oldId ? { ...i, feature_id: newId } : i,
+ );
+ setProduct({ ...product, items: updatedItems });
+
+ // Also update initialItem so it doesn't show as having changes
+ if (item?.feature_id === oldId) {
+ setInitialItem({ ...item, feature_id: newId });
+ }
+ }
+ };
const emptyPriceItem =
item?.usage_model &&
@@ -56,6 +81,16 @@ export function EditPlanFeatureSheet({
{feature?.name}
}
+ action={
+ }
+ onClick={() => setEditFeatureOpen(true)}
+ >
+ Edit Feature
+
+ }
/>
)}
@@ -98,6 +133,23 @@ export function EditPlanFeatureSheet({
{/* Footer stays at bottom */}
{showFooter && }
+
+ {/* Edit Feature Sheet */}
+ {feature?.type === FeatureType.CreditSystem ? (
+
+ ) : (
+
+ )}
);
}
diff --git a/vite/src/views/products/plan/utils/getDefaultItem.ts b/vite/src/views/products/plan/utils/getDefaultItem.ts
index 6c881a88e..1b9b46706 100644
--- a/vite/src/views/products/plan/utils/getDefaultItem.ts
+++ b/vite/src/views/products/plan/utils/getDefaultItem.ts
@@ -16,22 +16,27 @@ export const getDefaultItem = ({
feature,
});
+ // For static (boolean) features, reset_usage_when_enabled is not applicable
+ // since they don't track usage. Setting it causes mismatch with backend
+ // which doesn't store this field for boolean features.
+ const isStaticFeature = itemFeatureType === ProductItemFeatureType.Static;
+ const isContinuousUse =
+ itemFeatureType === ProductItemFeatureType.ContinuousUse;
+
// Create a new item with the selected feature
const newItem = {
feature_id: feature.id,
feature_type: itemFeatureType,
included_usage: null,
interval:
- itemFeatureType === ProductItemFeatureType.ContinuousUse ||
- itemFeatureType === ProductItemFeatureType.Static
- ? null
- : ProductItemInterval.Month,
+ isContinuousUse || isStaticFeature ? null : ProductItemInterval.Month,
price: null,
tiers: null,
billing_units: 1,
entity_feature_id: null,
- reset_usage_when_enabled:
- itemFeatureType !== ProductItemFeatureType.ContinuousUse,
+ // Only set reset_usage_when_enabled for usage-tracked features
+ // Boolean/static features don't track usage, so this field is not applicable
+ reset_usage_when_enabled: isStaticFeature ? undefined : !isContinuousUse,
};
return newItem;
diff --git a/vite/src/views/products/products/components/product-list/ProductListColumns.tsx b/vite/src/views/products/products/components/product-list/ProductListColumns.tsx
index beb1731a0..c44f84721 100644
--- a/vite/src/views/products/products/components/product-list/ProductListColumns.tsx
+++ b/vite/src/views/products/products/components/product-list/ProductListColumns.tsx
@@ -17,7 +17,7 @@ export const createProductListColumns = ({
size: 300,
header: "Name",
accessorKey: "name",
- enableSorting: false,
+ enableSorting: true,
cell: ({ row }: { row: Row }) => {
return (
diff --git a/vite/src/views/products/products/components/product-list/ProductListTable.tsx b/vite/src/views/products/products/components/product-list/ProductListTable.tsx
index 61468a8f7..ede408760 100644
--- a/vite/src/views/products/products/components/product-list/ProductListTable.tsx
+++ b/vite/src/views/products/products/components/product-list/ProductListTable.tsx
@@ -1,6 +1,7 @@
import { isOneOffProductV2, type ProductV2 } from "@autumn/shared";
import { CubeIcon } from "@phosphor-icons/react";
-import { useMemo } from "react";
+import type { SortingState } from "@tanstack/react-table";
+import { useMemo, useState } from "react";
import { Table } from "@/components/general/table";
import { SectionTag } from "@/components/v2/badges/SectionTag";
import { EmptyState } from "@/components/v2/empty-states/EmptyState";
@@ -20,6 +21,9 @@ export function ProductListTable() {
const { products, counts, isCountsLoading } = useProductsQuery();
const { queryStates } = useProductsQueryState();
+ // Shared sorting state for all tables
+ const [sorting, setSorting] = useState([]);
+
const { recurringBasePlans, recurringAddOnPlans, oneTimePlans } =
useMemo(() => {
const filtered = products?.filter((product) =>
@@ -100,6 +104,8 @@ export function ProductListTable() {
globalFilterFn: "includesString",
enableGlobalFilter: true,
enableSorting: true,
+ state: { sorting },
+ onSortingChange: setSorting,
},
});
@@ -110,6 +116,8 @@ export function ProductListTable() {
globalFilterFn: "includesString",
enableGlobalFilter: true,
enableSorting: true,
+ state: { sorting },
+ onSortingChange: setSorting,
},
});
@@ -120,6 +128,8 @@ export function ProductListTable() {
globalFilterFn: "includesString",
enableGlobalFilter: true,
enableSorting: true,
+ state: { sorting },
+ onSortingChange: setSorting,
},
});