@fluid-app/portal-sdk 0.1.511 → 0.1.512
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ContactsScreen-9uwS06kQ.mjs → ContactsScreen-DVGoPMxo.mjs} +2 -0
- package/dist/{FluidProvider-BiCeYuLV.mjs → FluidProvider-BwYSWXvD.mjs} +35 -35
- package/dist/{FluidProvider-BiCeYuLV.mjs.map → FluidProvider-BwYSWXvD.mjs.map} +1 -1
- package/dist/{FluidProvider--nibp8IV.cjs → FluidProvider-jiBsFzwX.cjs} +35 -35
- package/dist/{FluidProvider--nibp8IV.cjs.map → FluidProvider-jiBsFzwX.cjs.map} +1 -1
- package/dist/{MessagingScreen-BORvUGna.cjs → MessagingScreen-BoPOajsJ.cjs} +2 -2
- package/dist/{MessagingScreen-SUZcjJhr.cjs → MessagingScreen-CbS-I_AD.cjs} +2 -2
- package/dist/{MessagingScreen-SUZcjJhr.cjs.map → MessagingScreen-CbS-I_AD.cjs.map} +1 -1
- package/dist/{MessagingScreen-BqkBe42a.mjs → MessagingScreen-DXEazJ1u.mjs} +5 -2
- package/dist/{MessagingScreen-DQRVATl3.mjs → MessagingScreen-DmFW-md3.mjs} +2 -2
- package/dist/{MessagingScreen-DQRVATl3.mjs.map → MessagingScreen-DmFW-md3.mjs.map} +1 -1
- package/dist/{MySiteScreen-CmuWTTHD.mjs → MySiteScreen-BxF5RFtm.mjs} +1 -0
- package/dist/{OrdersScreen-CyGANI31.cjs → OrdersScreen-CC66apSh.cjs} +2 -2
- package/dist/{OrdersScreen-KuFZ1yvM.mjs → OrdersScreen-DPmWvnMk.mjs} +5 -2
- package/dist/{OrdersScreen-z5tc-nBP.mjs → OrdersScreen-DtMYxhYh.mjs} +2 -2
- package/dist/{OrdersScreen-z5tc-nBP.mjs.map → OrdersScreen-DtMYxhYh.mjs.map} +1 -1
- package/dist/{OrdersScreen-CaZvXkul.cjs → OrdersScreen-sy6AG47r.cjs} +2 -2
- package/dist/{OrdersScreen-CaZvXkul.cjs.map → OrdersScreen-sy6AG47r.cjs.map} +1 -1
- package/dist/{ProfileScreen-CQAMGoLW.mjs → ProfileScreen-CTYwLHGQ.mjs} +6 -3
- package/dist/{ProfileScreen-wqtz71Jn.mjs → ProfileScreen-GdwPz5rK.mjs} +2 -2
- package/dist/{ProfileScreen-wqtz71Jn.mjs.map → ProfileScreen-GdwPz5rK.mjs.map} +1 -1
- package/dist/{ProfileScreen-BOjKptWG.cjs → ProfileScreen-ZVIawSmq.cjs} +2 -2
- package/dist/{ProfileScreen-BOjKptWG.cjs.map → ProfileScreen-ZVIawSmq.cjs.map} +1 -1
- package/dist/{ProfileScreen-BT3Mt1y1.cjs → ProfileScreen-yIYYpQ2N.cjs} +3 -3
- package/dist/{ShareablesScreen-0cse1_-D.mjs → ShareablesScreen-JMjElYlz.mjs} +3 -0
- package/dist/{ShopScreen-DSSoDy5O.mjs → ShopScreen-80D3hiO0.mjs} +2 -0
- package/dist/{SubscriptionsScreen-DfoCjsPl.mjs → SubscriptionsScreen-BgMCPJx0.mjs} +3 -3
- package/dist/{SubscriptionsScreen-DfoCjsPl.mjs.map → SubscriptionsScreen-BgMCPJx0.mjs.map} +1 -1
- package/dist/{SubscriptionsScreen-DiF_pJWA.cjs → SubscriptionsScreen-CZz0wQ9G.cjs} +3 -3
- package/dist/{SubscriptionsScreen-DiF_pJWA.cjs.map → SubscriptionsScreen-CZz0wQ9G.cjs.map} +1 -1
- package/dist/{SubscriptionsScreen-DNPANUMS.cjs → SubscriptionsScreen-j0BROH4n.cjs} +3 -3
- package/dist/{SubscriptionsScreen-Bq6eMkoN.mjs → SubscriptionsScreen-uWXwxZHg.mjs} +6 -3
- package/dist/{ar-a5XheqF4.cjs → ar-BRTqPIQm.cjs} +2 -1
- package/dist/ar-BRTqPIQm.cjs.map +1 -0
- package/dist/{ar-DzFfeuH6.mjs → ar-Bdmxegli.mjs} +2 -1
- package/dist/ar-Bdmxegli.mjs.map +1 -0
- package/dist/{bg-E4rjQ5VN.cjs → bg-QPLVQePh.cjs} +2 -1
- package/dist/bg-QPLVQePh.cjs.map +1 -0
- package/dist/{bg-CcHDDtuc.mjs → bg-Qa4MSxXf.mjs} +2 -1
- package/dist/bg-Qa4MSxXf.mjs.map +1 -0
- package/dist/{bn-BzPHQVQQ.cjs → bn-DHoCNlnT.cjs} +2 -1
- package/dist/bn-DHoCNlnT.cjs.map +1 -0
- package/dist/{bn-BaTYefLg.mjs → bn-u0Y6Pv02.mjs} +2 -1
- package/dist/bn-u0Y6Pv02.mjs.map +1 -0
- package/dist/{cs-BDNOATcV.cjs → cs-DPyeI1gt.cjs} +2 -1
- package/dist/cs-DPyeI1gt.cjs.map +1 -0
- package/dist/{cs-CKzroIj9.mjs → cs-Dp9PPgM6.mjs} +2 -1
- package/dist/cs-Dp9PPgM6.mjs.map +1 -0
- package/dist/{da-Cg-epQHP.cjs → da-BKrHgpc1.cjs} +2 -1
- package/dist/da-BKrHgpc1.cjs.map +1 -0
- package/dist/{da-D6jqtE6K.mjs → da-VuA-GrRb.mjs} +2 -1
- package/dist/da-VuA-GrRb.mjs.map +1 -0
- package/dist/{de-LTtnZcP6.mjs → de-9vk6k0nJ.mjs} +2 -1
- package/dist/de-9vk6k0nJ.mjs.map +1 -0
- package/dist/{de-DExsPlF0.cjs → de-BOG93PI8.cjs} +2 -1
- package/dist/de-BOG93PI8.cjs.map +1 -0
- package/dist/{el-PhsTmMc4.cjs → el-CYZv1P0r.cjs} +2 -1
- package/dist/el-CYZv1P0r.cjs.map +1 -0
- package/dist/{el-CLOA4Iht.mjs → el-DXPx1g2c.mjs} +2 -1
- package/dist/el-DXPx1g2c.mjs.map +1 -0
- package/dist/{es-CuD_WTjc.mjs → es-BB85bwJ_.mjs} +2 -1
- package/dist/es-BB85bwJ_.mjs.map +1 -0
- package/dist/{es-BO79JXnd.cjs → es-G6bSRkdk.cjs} +2 -1
- package/dist/es-G6bSRkdk.cjs.map +1 -0
- package/dist/{fi-B4gfHXKw.cjs → fi-BUV6jW3T.cjs} +2 -1
- package/dist/fi-BUV6jW3T.cjs.map +1 -0
- package/dist/{fi-D10qDpB_.mjs → fi-D-TtktPt.mjs} +2 -1
- package/dist/fi-D-TtktPt.mjs.map +1 -0
- package/dist/{fr-BLII0ePc.mjs → fr--BgxXkpf.mjs} +2 -1
- package/dist/fr--BgxXkpf.mjs.map +1 -0
- package/dist/{fr-CMBprdKc.cjs → fr-dhVoJgWK.cjs} +2 -1
- package/dist/fr-dhVoJgWK.cjs.map +1 -0
- package/dist/{he-CMDK884V.mjs → he-CDTvXkZd.mjs} +2 -1
- package/dist/he-CDTvXkZd.mjs.map +1 -0
- package/dist/{he-Cm3TmloM.cjs → he-Do9yqDxB.cjs} +2 -1
- package/dist/he-Do9yqDxB.cjs.map +1 -0
- package/dist/{hi-Cm_DH4G0.cjs → hi-AiRJhk6a.cjs} +2 -1
- package/dist/hi-AiRJhk6a.cjs.map +1 -0
- package/dist/{hi-CUx-Aq1K.mjs → hi-CjRrL1Q7.mjs} +2 -1
- package/dist/hi-CjRrL1Q7.mjs.map +1 -0
- package/dist/{hr-DBY2Lt8Y.mjs → hr-B0nd9e9C.mjs} +2 -1
- package/dist/hr-B0nd9e9C.mjs.map +1 -0
- package/dist/{hr-Bfcyy_rR.cjs → hr-DqJVAx7M.cjs} +2 -1
- package/dist/hr-DqJVAx7M.cjs.map +1 -0
- package/dist/{hu-BTYlpv8x.cjs → hu-DVgZpQ2J.cjs} +2 -1
- package/dist/hu-DVgZpQ2J.cjs.map +1 -0
- package/dist/{hu-CFdlLxix.mjs → hu-yj7Fc4o9.mjs} +2 -1
- package/dist/hu-yj7Fc4o9.mjs.map +1 -0
- package/dist/{id-DpB12DnB.cjs → id-DM2xUNOq.cjs} +2 -1
- package/dist/id-DM2xUNOq.cjs.map +1 -0
- package/dist/{id-CLnXnsUI.mjs → id-DOqWgn6h.mjs} +2 -1
- package/dist/id-DOqWgn6h.mjs.map +1 -0
- package/dist/index.cjs +14 -14
- package/dist/index.mjs +22 -22
- package/dist/{it-Nmq4disb.cjs → it-BAS4gSTn.cjs} +2 -1
- package/dist/it-BAS4gSTn.cjs.map +1 -0
- package/dist/{it-Dnm3Ubcb.mjs → it-C98SovBr.mjs} +2 -1
- package/dist/it-C98SovBr.mjs.map +1 -0
- package/dist/{ja-D__pQNSM.cjs → ja-BWYAe0zp.cjs} +2 -1
- package/dist/ja-BWYAe0zp.cjs.map +1 -0
- package/dist/{ja-ZDGpYIT9.mjs → ja-C716ev_g.mjs} +2 -1
- package/dist/ja-C716ev_g.mjs.map +1 -0
- package/dist/{ko-BAKmWypV.mjs → ko-C4vWj-M9.mjs} +2 -1
- package/dist/ko-C4vWj-M9.mjs.map +1 -0
- package/dist/{ko-BGQ9Vnh-.cjs → ko-CgTaued5.cjs} +2 -1
- package/dist/ko-CgTaued5.cjs.map +1 -0
- package/dist/{ms-6IGsCaks.mjs → ms-BY0Pxptn.mjs} +2 -1
- package/dist/ms-BY0Pxptn.mjs.map +1 -0
- package/dist/{ms-Bq2pHRM-.cjs → ms-JIbuoytI.cjs} +2 -1
- package/dist/ms-JIbuoytI.cjs.map +1 -0
- package/dist/{nl-l-MVSomn.mjs → nl-C9HE9V_v.mjs} +2 -1
- package/dist/nl-C9HE9V_v.mjs.map +1 -0
- package/dist/{nl-DHrQ875w.cjs → nl-haNh87L1.cjs} +2 -1
- package/dist/nl-haNh87L1.cjs.map +1 -0
- package/dist/{no-KpFMm1AJ.mjs → no-Blcb2-Cz.mjs} +2 -1
- package/dist/no-Blcb2-Cz.mjs.map +1 -0
- package/dist/{no-R3-EB5Co.cjs → no-CzSXTPnT.cjs} +2 -1
- package/dist/no-CzSXTPnT.cjs.map +1 -0
- package/dist/{pl-Bca2Pq5-.mjs → pl-CCpUmitV.mjs} +2 -1
- package/dist/pl-CCpUmitV.mjs.map +1 -0
- package/dist/{pl-Cd_YrfPg.cjs → pl-CUPFZTSC.cjs} +2 -1
- package/dist/pl-CUPFZTSC.cjs.map +1 -0
- package/dist/{pt-CIkRdYeG.mjs → pt-CIxZRWyv.mjs} +2 -1
- package/dist/pt-CIxZRWyv.mjs.map +1 -0
- package/dist/{pt-DIiHu6Mp.cjs → pt-D3RNC97N.cjs} +2 -1
- package/dist/pt-D3RNC97N.cjs.map +1 -0
- package/dist/{ro-CiE-AxDf.mjs → ro-8P4MgS9f.mjs} +2 -1
- package/dist/ro-8P4MgS9f.mjs.map +1 -0
- package/dist/{ro-odHdLgL4.cjs → ro-D8z0fvE2.cjs} +2 -1
- package/dist/ro-D8z0fvE2.cjs.map +1 -0
- package/dist/{ru-D2OwVHj5.cjs → ru-CtmifJv4.cjs} +2 -1
- package/dist/ru-CtmifJv4.cjs.map +1 -0
- package/dist/{ru-BYdpmEiK.mjs → ru-lM0vNqkN.mjs} +2 -1
- package/dist/ru-lM0vNqkN.mjs.map +1 -0
- package/dist/{sk-DQiXACwE.mjs → sk-CgEjIW_S.mjs} +2 -1
- package/dist/sk-CgEjIW_S.mjs.map +1 -0
- package/dist/{sk-BaDSrJ8u.cjs → sk-DZxahVB3.cjs} +2 -1
- package/dist/sk-DZxahVB3.cjs.map +1 -0
- package/dist/{sv-Btkf1rNQ.mjs → sv-BWt6_WTg.mjs} +2 -1
- package/dist/sv-BWt6_WTg.mjs.map +1 -0
- package/dist/{sv-B6EUMOBb.cjs → sv-GC8OT1vt.cjs} +2 -1
- package/dist/sv-GC8OT1vt.cjs.map +1 -0
- package/dist/{th-Dhyq5YKF.mjs → th-CmUZlvpQ.mjs} +2 -1
- package/dist/th-CmUZlvpQ.mjs.map +1 -0
- package/dist/{th-D8g2gDha.cjs → th-DblYfjWT.cjs} +2 -1
- package/dist/th-DblYfjWT.cjs.map +1 -0
- package/dist/{tl-sxgiHAif.mjs → tl-C_hEnuMY.mjs} +2 -1
- package/dist/tl-C_hEnuMY.mjs.map +1 -0
- package/dist/{tl-tEocbrz2.cjs → tl-DLw-m_KB.cjs} +2 -1
- package/dist/tl-DLw-m_KB.cjs.map +1 -0
- package/dist/{tr-BtM6b91I.mjs → tr-Dfc8ydzD.mjs} +2 -1
- package/dist/tr-Dfc8ydzD.mjs.map +1 -0
- package/dist/{tr-BAyeQkex.cjs → tr-gaXTEiH1.cjs} +2 -1
- package/dist/tr-gaXTEiH1.cjs.map +1 -0
- package/dist/{uk-kvcTBcGh.cjs → uk-BA-lGtnm.cjs} +2 -1
- package/dist/uk-BA-lGtnm.cjs.map +1 -0
- package/dist/{uk-Cv_fKgTe.mjs → uk-wvHSaNjV.mjs} +2 -1
- package/dist/uk-wvHSaNjV.mjs.map +1 -0
- package/dist/{use-portal-card-add-3ds-flow-7umBe1LL.mjs → use-portal-card-add-3ds-flow-BqZulT6m.mjs} +2 -2
- package/dist/{use-portal-card-add-3ds-flow-7umBe1LL.mjs.map → use-portal-card-add-3ds-flow-BqZulT6m.mjs.map} +1 -1
- package/dist/{use-portal-card-add-3ds-flow-DXDPr80N.cjs → use-portal-card-add-3ds-flow-DCVXl0ky.cjs} +2 -2
- package/dist/{use-portal-card-add-3ds-flow-DXDPr80N.cjs.map → use-portal-card-add-3ds-flow-DCVXl0ky.cjs.map} +1 -1
- package/dist/utils/build-remote-widget-plugin-manifests.mjs +3 -0
- package/dist/utils/build-remote-widget-plugin-manifests.mjs.map +1 -1
- package/dist/utils/build-widget-registry.mjs +3 -0
- package/dist/{vi-D1M0pUmI.cjs → vi-5pYkRRAI.cjs} +2 -1
- package/dist/vi-5pYkRRAI.cjs.map +1 -0
- package/dist/{vi-B877Wvfs.mjs → vi-CI1vgr9K.mjs} +2 -1
- package/dist/vi-CI1vgr9K.mjs.map +1 -0
- package/dist/{zh_CN-BbzxVpys.cjs → zh_CN-CRA7Eajb.cjs} +2 -1
- package/dist/zh_CN-CRA7Eajb.cjs.map +1 -0
- package/dist/{zh_CN-DSesb0bt.mjs → zh_CN-DHfCPhjH.mjs} +2 -1
- package/dist/zh_CN-DHfCPhjH.mjs.map +1 -0
- package/dist/{zh_TW-BDxZdNH7.cjs → zh_TW-CAJScAfB.cjs} +2 -1
- package/dist/zh_TW-CAJScAfB.cjs.map +1 -0
- package/dist/{zh_TW-Bxz64eoL.mjs → zh_TW-eo1sgYEl.mjs} +2 -1
- package/dist/zh_TW-eo1sgYEl.mjs.map +1 -0
- package/package.json +16 -16
- package/dist/ar-DzFfeuH6.mjs.map +0 -1
- package/dist/ar-a5XheqF4.cjs.map +0 -1
- package/dist/bg-CcHDDtuc.mjs.map +0 -1
- package/dist/bg-E4rjQ5VN.cjs.map +0 -1
- package/dist/bn-BaTYefLg.mjs.map +0 -1
- package/dist/bn-BzPHQVQQ.cjs.map +0 -1
- package/dist/cs-BDNOATcV.cjs.map +0 -1
- package/dist/cs-CKzroIj9.mjs.map +0 -1
- package/dist/da-Cg-epQHP.cjs.map +0 -1
- package/dist/da-D6jqtE6K.mjs.map +0 -1
- package/dist/de-DExsPlF0.cjs.map +0 -1
- package/dist/de-LTtnZcP6.mjs.map +0 -1
- package/dist/el-CLOA4Iht.mjs.map +0 -1
- package/dist/el-PhsTmMc4.cjs.map +0 -1
- package/dist/es-BO79JXnd.cjs.map +0 -1
- package/dist/es-CuD_WTjc.mjs.map +0 -1
- package/dist/fi-B4gfHXKw.cjs.map +0 -1
- package/dist/fi-D10qDpB_.mjs.map +0 -1
- package/dist/fr-BLII0ePc.mjs.map +0 -1
- package/dist/fr-CMBprdKc.cjs.map +0 -1
- package/dist/he-CMDK884V.mjs.map +0 -1
- package/dist/he-Cm3TmloM.cjs.map +0 -1
- package/dist/hi-CUx-Aq1K.mjs.map +0 -1
- package/dist/hi-Cm_DH4G0.cjs.map +0 -1
- package/dist/hr-Bfcyy_rR.cjs.map +0 -1
- package/dist/hr-DBY2Lt8Y.mjs.map +0 -1
- package/dist/hu-BTYlpv8x.cjs.map +0 -1
- package/dist/hu-CFdlLxix.mjs.map +0 -1
- package/dist/id-CLnXnsUI.mjs.map +0 -1
- package/dist/id-DpB12DnB.cjs.map +0 -1
- package/dist/it-Dnm3Ubcb.mjs.map +0 -1
- package/dist/it-Nmq4disb.cjs.map +0 -1
- package/dist/ja-D__pQNSM.cjs.map +0 -1
- package/dist/ja-ZDGpYIT9.mjs.map +0 -1
- package/dist/ko-BAKmWypV.mjs.map +0 -1
- package/dist/ko-BGQ9Vnh-.cjs.map +0 -1
- package/dist/ms-6IGsCaks.mjs.map +0 -1
- package/dist/ms-Bq2pHRM-.cjs.map +0 -1
- package/dist/nl-DHrQ875w.cjs.map +0 -1
- package/dist/nl-l-MVSomn.mjs.map +0 -1
- package/dist/no-KpFMm1AJ.mjs.map +0 -1
- package/dist/no-R3-EB5Co.cjs.map +0 -1
- package/dist/pl-Bca2Pq5-.mjs.map +0 -1
- package/dist/pl-Cd_YrfPg.cjs.map +0 -1
- package/dist/pt-CIkRdYeG.mjs.map +0 -1
- package/dist/pt-DIiHu6Mp.cjs.map +0 -1
- package/dist/ro-CiE-AxDf.mjs.map +0 -1
- package/dist/ro-odHdLgL4.cjs.map +0 -1
- package/dist/ru-BYdpmEiK.mjs.map +0 -1
- package/dist/ru-D2OwVHj5.cjs.map +0 -1
- package/dist/sk-BaDSrJ8u.cjs.map +0 -1
- package/dist/sk-DQiXACwE.mjs.map +0 -1
- package/dist/sv-B6EUMOBb.cjs.map +0 -1
- package/dist/sv-Btkf1rNQ.mjs.map +0 -1
- package/dist/th-D8g2gDha.cjs.map +0 -1
- package/dist/th-Dhyq5YKF.mjs.map +0 -1
- package/dist/tl-sxgiHAif.mjs.map +0 -1
- package/dist/tl-tEocbrz2.cjs.map +0 -1
- package/dist/tr-BAyeQkex.cjs.map +0 -1
- package/dist/tr-BtM6b91I.mjs.map +0 -1
- package/dist/uk-Cv_fKgTe.mjs.map +0 -1
- package/dist/uk-kvcTBcGh.cjs.map +0 -1
- package/dist/vi-B877Wvfs.mjs.map +0 -1
- package/dist/vi-D1M0pUmI.cjs.map +0 -1
- package/dist/zh_CN-BbzxVpys.cjs.map +0 -1
- package/dist/zh_CN-DSesb0bt.mjs.map +0 -1
- package/dist/zh_TW-BDxZdNH7.cjs.map +0 -1
- package/dist/zh_TW-Bxz64eoL.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionsScreen-DfoCjsPl.mjs","names":["getInternalDefaultOptions","getDefaultOptions","defaultLocale","portalTenant.subscriptionsList","portalTenant.subscriptionsShow","portalTenant.subscriptionsPause","portalTenant.subscriptionsResume","portalTenant.subscriptionsSkip","portalTenant.subscriptionsCancel","portalTenant.subscriptionsReactivate","portalTenant.subscriptionsRetry","portalTenant.subscriptionsFailedCycleWaiverPreview","portalTenant.subscriptionsFailedCycleWaiverCreate","portalTenant.subscriptionsUpdate","portalTenant.subscriptionsUpdate","portalTenant.subscriptionBundlesList","portalTenant.subscriptionBundlesCreate","UNIT_KEYS","formatLongDate","UNIT_KEYS","formatLongDate","formatLongDate","mapToFluidPayAddress","cn","Calendar","cn","Calendar","cn","SubscriptionDetailScreen","cn","mapToFluidPayAddress","cn","mapToFluidPayAddress","SubscriptionDetailScreenContent"],"sources":["../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/getDefaultOptions.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/getISODay.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/transpose.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/Setter.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/EraParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/constants.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/utils.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/YearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/LocalWeekYearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISOWeekYearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ExtendedYearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/QuarterParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/StandAloneQuarterParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/MonthParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/StandAloneMonthParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/setWeek.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/LocalWeekParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/setISOWeek.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISOWeekParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/DateParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/DayOfYearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/setDay.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/DayParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/LocalDayParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/StandAloneLocalDayParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/setISODay.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISODayParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/AMPMParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/AMPMMidnightParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/DayPeriodParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/Hour1to12Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/Hour0to23Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/Hour0To11Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/Hour1To24Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/MinuteParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/SecondParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/FractionOfSecondParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISOTimezoneWithZParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISOTimezoneParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/TimestampSecondsParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/TimestampMillisecondsParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse.js","../../../subscriptions/core/src/subscriptions-api-context.ts","../../../subscriptions/core/src/provider.tsx","../../../subscriptions/core/src/query-keys.ts","../../../subscriptions/core/src/bundles-api-context.ts","../../../subscriptions/core/src/bundles-provider.tsx","../../../subscriptions/core/src/hooks/use-subscriptions.ts","../../../subscriptions/core/src/hooks/use-infinite-subscriptions.ts","../../../subscriptions/core/src/hooks/use-subscription.ts","../../../subscriptions/core/src/hooks/use-pause-subscription.ts","../../../subscriptions/core/src/hooks/use-resume-subscription.ts","../../../subscriptions/core/src/hooks/use-skip-subscription.ts","../../../subscriptions/core/src/hooks/use-cancel-subscription.ts","../../../subscriptions/core/src/hooks/use-reactivate-subscription.ts","../../../subscriptions/core/src/hooks/use-retry-subscription.ts","../../../subscriptions/core/src/utils/retry-outcome.ts","../../../subscriptions/core/src/hooks/use-retry-status-polling.ts","../../../subscriptions/core/src/hooks/use-failed-cycle-waiver-preview.ts","../../../subscriptions/core/src/hooks/use-waive-failed-cycle.ts","../../../subscriptions/core/src/hooks/use-update-subscription-info.ts","../../../subscriptions/core/src/hooks/use-bundles.ts","../../../subscriptions/core/src/hooks/use-create-bundle.ts","../../../subscriptions/core/src/utils/subscription-helpers.ts","../../../subscriptions/core/src/utils/subscription-actions.ts","../../../subscriptions/core/src/utils/failed-cycle-waiver.ts","../../../subscriptions/core/src/auto-apply-points-api.ts","../../../subscriptions/core/src/auto-apply-points-api-context.ts","../src/adapters/subscriptions-api-adapter.ts","../src/adapters/auto-apply-points-api-adapter.ts","../src/subscriptions/PortalSubscriptionsApiProvider.tsx","../src/adapters/bundles-api-adapter.ts","../src/subscriptions/PortalBundlesApiProvider.tsx","../../../subscriptions/core/src/translation-api-context.ts","../src/providers/SubscriptionsTranslationBridge.tsx","../src/subscriptions/subscription-card-add-success.ts","../src/screens/subscriptions/portal-subscriptions-list-helpers.ts","../src/screens/subscriptions/PortalSubscriptionsList.tsx","../src/screens/subscriptions/bundle-drawer/payment-utils.ts","../src/screens/subscriptions/bundle-drawer/bill-date-bounds.ts","../src/screens/subscriptions/bundle-drawer/use-bundle-form.ts","../src/screens/subscriptions/bundle-drawer/DrawerStepTabs.tsx","../src/screens/subscriptions/bundle-drawer/DrawerStepSelect.tsx","../src/screens/subscriptions/bundle-drawer/DrawerStepDate.tsx","../src/screens/subscriptions/bundle-drawer/DrawerStepAddress.tsx","../src/screens/subscriptions/bundle-drawer/DrawerStepPayment.tsx","../src/screens/subscriptions/bundle-drawer/BundleSubscriptionsDrawer.tsx","../src/screens/SubscriptionsListScreen.tsx","../../../subscriptions/ui/src/components/cancel-subscription-dialog.tsx","../../../subscriptions/ui/src/lib/format.ts","../../../subscriptions/ui/src/components/pause-subscription-dialog.tsx","../../../subscriptions/ui/src/lib/parse-iso-date.ts","../../../subscriptions/ui/src/components/resume-subscription-dialog.tsx","../../../subscriptions/ui/src/components/edit-bill-date-dialog.tsx","../../../subscriptions/ui/src/lib/cn.ts","../../../subscriptions/ui/src/components/status-pill.tsx","../../../subscriptions/ui/src/components/past-due-banner.tsx","../../../subscriptions/ui/src/components/failed-cycle-waiver-dialog.tsx","../../../subscriptions/ui/src/components/bundled-with-card.tsx","../../../subscriptions/ui/src/components/subscription-detail.tsx","../../../subscriptions/ui/src/screens/SubscriptionDetailScreen.tsx","../src/subscriptions/SelectablePaymentMethodDropdown.tsx","../src/subscriptions/subscription-payment-recovery.ts","../src/subscriptions/PortalSubscriptionPaymentMethodSection.tsx","../src/subscriptions/SelectableAddressDropdown.tsx","../src/subscriptions/PortalSubscriptionShippingAddressSection.tsx","../../../subscriptions/core/src/hooks/use-update-auto-apply-points.ts","../src/subscriptions/subscription-auto-apply-points.ts","../src/subscriptions/BundleFanOutDialog.tsx","../src/subscriptions/PortalSubscriptionAutoApplyPointsSection.tsx","../src/subscriptions/PortalReactivateSubscriptionDialog.tsx","../src/screens/SubscriptionDetailScreen.tsx","../src/screens/SubscriptionsScreen.tsx"],"sourcesContent":["import { getDefaultOptions as getInternalDefaultOptions } from \"./_lib/defaultOptions.js\";\n\n/**\n * @name getDefaultOptions\n * @category Common Helpers\n * @summary Get default options.\n * @pure false\n *\n * @description\n * Returns an object that contains defaults for\n * `options.locale`, `options.weekStartsOn` and `options.firstWeekContainsDate`\n * arguments for all functions.\n *\n * You can change these with [setDefaultOptions](https://date-fns.org/docs/setDefaultOptions).\n *\n * @returns The default options\n *\n * @example\n * const result = getDefaultOptions()\n * //=> {}\n *\n * @example\n * setDefaultOptions({ weekStarsOn: 1, firstWeekContainsDate: 4 })\n * const result = getDefaultOptions()\n * //=> { weekStarsOn: 1, firstWeekContainsDate: 4 }\n */\nexport function getDefaultOptions() {\n return Object.assign({}, getInternalDefaultOptions());\n}\n\n// Fallback for modularized imports:\nexport default getDefaultOptions;\n","import { toDate } from \"./toDate.js\";\n\n/**\n * The {@link getISODay} function options.\n */\n\n/**\n * @name getISODay\n * @category Weekday Helpers\n * @summary Get the day of the ISO week of the given date.\n *\n * @description\n * Get the day of the ISO week of the given date,\n * which is 7 for Sunday, 1 for Monday etc.\n *\n * ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date\n *\n * @param date - The given date\n * @param options - An object with options\n *\n * @returns The day of ISO week\n *\n * @example\n * // Which day of the ISO week is 26 February 2012?\n * const result = getISODay(new Date(2012, 1, 26))\n * //=> 7\n */\nexport function getISODay(date, options) {\n const day = toDate(date, options?.in).getDay();\n return day === 0 ? 7 : day;\n}\n\n// Fallback for modularized imports:\nexport default getISODay;\n","import { constructFrom } from \"./constructFrom.js\";\n\n/**\n * @name transpose\n * @category Generic Helpers\n * @summary Transpose the date to the given constructor.\n *\n * @description\n * The function transposes the date to the given constructor. It helps you\n * to transpose the date in the system time zone to say `UTCDate` or any other\n * date extension.\n *\n * @typeParam InputDate - The input `Date` type derived from the passed argument.\n * @typeParam ResultDate - The result `Date` type derived from the passed constructor.\n *\n * @param date - The date to use values from\n * @param constructor - The date constructor to use\n *\n * @returns Date transposed to the given constructor\n *\n * @example\n * // Create July 10, 2022 00:00 in locale time zone\n * const date = new Date(2022, 6, 10)\n * //=> 'Sun Jul 10 2022 00:00:00 GMT+0800 (Singapore Standard Time)'\n *\n * @example\n * // Transpose the date to July 10, 2022 00:00 in UTC\n * transpose(date, UTCDate)\n * //=> 'Sun Jul 10 2022 00:00:00 GMT+0000 (Coordinated Universal Time)'\n */\nexport function transpose(date, constructor) {\n const date_ = isConstructor(constructor)\n ? new constructor(0)\n : constructFrom(constructor, 0);\n date_.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());\n date_.setHours(\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n date.getMilliseconds(),\n );\n return date_;\n}\n\nfunction isConstructor(constructor) {\n return (\n typeof constructor === \"function\" &&\n constructor.prototype?.constructor === constructor\n );\n}\n\n// Fallback for modularized imports:\nexport default transpose;\n","import { constructFrom } from \"../../constructFrom.js\";\nimport { transpose } from \"../../transpose.js\";\n\nconst TIMEZONE_UNIT_PRIORITY = 10;\n\nexport class Setter {\n subPriority = 0;\n\n validate(_utcDate, _options) {\n return true;\n }\n}\n\nexport class ValueSetter extends Setter {\n constructor(\n value,\n\n validateValue,\n\n setValue,\n\n priority,\n subPriority,\n ) {\n super();\n this.value = value;\n this.validateValue = validateValue;\n this.setValue = setValue;\n this.priority = priority;\n if (subPriority) {\n this.subPriority = subPriority;\n }\n }\n\n validate(date, options) {\n return this.validateValue(date, this.value, options);\n }\n\n set(date, flags, options) {\n return this.setValue(date, flags, this.value, options);\n }\n}\n\nexport class DateTimezoneSetter extends Setter {\n priority = TIMEZONE_UNIT_PRIORITY;\n subPriority = -1;\n\n constructor(context, reference) {\n super();\n this.context = context || ((date) => constructFrom(reference, date));\n }\n\n set(date, flags) {\n if (flags.timestampIsSet) return date;\n return constructFrom(date, transpose(date, this.context));\n }\n}\n","import { ValueSetter } from \"./Setter.js\";\n\nexport class Parser {\n run(dateString, token, match, options) {\n const result = this.parse(dateString, token, match, options);\n if (!result) {\n return null;\n }\n\n return {\n setter: new ValueSetter(\n result.value,\n this.validate,\n this.set,\n this.priority,\n this.subPriority,\n ),\n rest: result.rest,\n };\n }\n\n validate(_utcDate, _value, _options) {\n return true;\n }\n}\n","import { Parser } from \"../Parser.js\";\n\nexport class EraParser extends Parser {\n priority = 140;\n\n parse(dateString, token, match) {\n switch (token) {\n // AD, BC\n case \"G\":\n case \"GG\":\n case \"GGG\":\n return (\n match.era(dateString, { width: \"abbreviated\" }) ||\n match.era(dateString, { width: \"narrow\" })\n );\n\n // A, B\n case \"GGGGG\":\n return match.era(dateString, { width: \"narrow\" });\n // Anno Domini, Before Christ\n case \"GGGG\":\n default:\n return (\n match.era(dateString, { width: \"wide\" }) ||\n match.era(dateString, { width: \"abbreviated\" }) ||\n match.era(dateString, { width: \"narrow\" })\n );\n }\n }\n\n set(date, flags, value) {\n flags.era = value;\n date.setFullYear(value, 0, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"R\", \"u\", \"t\", \"T\"];\n}\n","export const numericPatterns = {\n month: /^(1[0-2]|0?\\d)/, // 0 to 12\n date: /^(3[0-1]|[0-2]?\\d)/, // 0 to 31\n dayOfYear: /^(36[0-6]|3[0-5]\\d|[0-2]?\\d?\\d)/, // 0 to 366\n week: /^(5[0-3]|[0-4]?\\d)/, // 0 to 53\n hour23h: /^(2[0-3]|[0-1]?\\d)/, // 0 to 23\n hour24h: /^(2[0-4]|[0-1]?\\d)/, // 0 to 24\n hour11h: /^(1[0-1]|0?\\d)/, // 0 to 11\n hour12h: /^(1[0-2]|0?\\d)/, // 0 to 12\n minute: /^[0-5]?\\d/, // 0 to 59\n second: /^[0-5]?\\d/, // 0 to 59\n\n singleDigit: /^\\d/, // 0 to 9\n twoDigits: /^\\d{1,2}/, // 0 to 99\n threeDigits: /^\\d{1,3}/, // 0 to 999\n fourDigits: /^\\d{1,4}/, // 0 to 9999\n\n anyDigitsSigned: /^-?\\d+/,\n singleDigitSigned: /^-?\\d/, // 0 to 9, -0 to -9\n twoDigitsSigned: /^-?\\d{1,2}/, // 0 to 99, -0 to -99\n threeDigitsSigned: /^-?\\d{1,3}/, // 0 to 999, -0 to -999\n fourDigitsSigned: /^-?\\d{1,4}/, // 0 to 9999, -0 to -9999\n};\n\nexport const timezonePatterns = {\n basicOptionalMinutes: /^([+-])(\\d{2})(\\d{2})?|Z/,\n basic: /^([+-])(\\d{2})(\\d{2})|Z/,\n basicOptionalSeconds: /^([+-])(\\d{2})(\\d{2})((\\d{2}))?|Z/,\n extended: /^([+-])(\\d{2}):(\\d{2})|Z/,\n extendedOptionalSeconds: /^([+-])(\\d{2}):(\\d{2})(:(\\d{2}))?|Z/,\n};\n","import {\n millisecondsInHour,\n millisecondsInMinute,\n millisecondsInSecond,\n} from \"../../constants.js\";\n\nimport { numericPatterns } from \"./constants.js\";\n\nexport function mapValue(parseFnResult, mapFn) {\n if (!parseFnResult) {\n return parseFnResult;\n }\n\n return {\n value: mapFn(parseFnResult.value),\n rest: parseFnResult.rest,\n };\n}\n\nexport function parseNumericPattern(pattern, dateString) {\n const matchResult = dateString.match(pattern);\n\n if (!matchResult) {\n return null;\n }\n\n return {\n value: parseInt(matchResult[0], 10),\n rest: dateString.slice(matchResult[0].length),\n };\n}\n\nexport function parseTimezonePattern(pattern, dateString) {\n const matchResult = dateString.match(pattern);\n\n if (!matchResult) {\n return null;\n }\n\n // Input is 'Z'\n if (matchResult[0] === \"Z\") {\n return {\n value: 0,\n rest: dateString.slice(1),\n };\n }\n\n const sign = matchResult[1] === \"+\" ? 1 : -1;\n const hours = matchResult[2] ? parseInt(matchResult[2], 10) : 0;\n const minutes = matchResult[3] ? parseInt(matchResult[3], 10) : 0;\n const seconds = matchResult[5] ? parseInt(matchResult[5], 10) : 0;\n\n return {\n value:\n sign *\n (hours * millisecondsInHour +\n minutes * millisecondsInMinute +\n seconds * millisecondsInSecond),\n rest: dateString.slice(matchResult[0].length),\n };\n}\n\nexport function parseAnyDigitsSigned(dateString) {\n return parseNumericPattern(numericPatterns.anyDigitsSigned, dateString);\n}\n\nexport function parseNDigits(n, dateString) {\n switch (n) {\n case 1:\n return parseNumericPattern(numericPatterns.singleDigit, dateString);\n case 2:\n return parseNumericPattern(numericPatterns.twoDigits, dateString);\n case 3:\n return parseNumericPattern(numericPatterns.threeDigits, dateString);\n case 4:\n return parseNumericPattern(numericPatterns.fourDigits, dateString);\n default:\n return parseNumericPattern(new RegExp(\"^\\\\d{1,\" + n + \"}\"), dateString);\n }\n}\n\nexport function parseNDigitsSigned(n, dateString) {\n switch (n) {\n case 1:\n return parseNumericPattern(numericPatterns.singleDigitSigned, dateString);\n case 2:\n return parseNumericPattern(numericPatterns.twoDigitsSigned, dateString);\n case 3:\n return parseNumericPattern(numericPatterns.threeDigitsSigned, dateString);\n case 4:\n return parseNumericPattern(numericPatterns.fourDigitsSigned, dateString);\n default:\n return parseNumericPattern(new RegExp(\"^-?\\\\d{1,\" + n + \"}\"), dateString);\n }\n}\n\nexport function dayPeriodEnumToHours(dayPeriod) {\n switch (dayPeriod) {\n case \"morning\":\n return 4;\n case \"evening\":\n return 17;\n case \"pm\":\n case \"noon\":\n case \"afternoon\":\n return 12;\n case \"am\":\n case \"midnight\":\n case \"night\":\n default:\n return 0;\n }\n}\n\nexport function normalizeTwoDigitYear(twoDigitYear, currentYear) {\n const isCommonEra = currentYear > 0;\n // Absolute number of the current year:\n // 1 -> 1 AC\n // 0 -> 1 BC\n // -1 -> 2 BC\n const absCurrentYear = isCommonEra ? currentYear : 1 - currentYear;\n\n let result;\n if (absCurrentYear <= 50) {\n result = twoDigitYear || 100;\n } else {\n const rangeEnd = absCurrentYear + 50;\n const rangeEndCentury = Math.trunc(rangeEnd / 100) * 100;\n const isPreviousCentury = twoDigitYear >= rangeEnd % 100;\n result = twoDigitYear + rangeEndCentury - (isPreviousCentury ? 100 : 0);\n }\n\n return isCommonEra ? result : 1 - result;\n}\n\nexport function isLeapYearIndex(year) {\n return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0);\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { mapValue, normalizeTwoDigitYear, parseNDigits } from \"../utils.js\";\n\n// From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns\n// | Year | y | yy | yyy | yyyy | yyyyy |\n// |----------|-------|----|-------|-------|-------|\n// | AD 1 | 1 | 01 | 001 | 0001 | 00001 |\n// | AD 12 | 12 | 12 | 012 | 0012 | 00012 |\n// | AD 123 | 123 | 23 | 123 | 0123 | 00123 |\n// | AD 1234 | 1234 | 34 | 1234 | 1234 | 01234 |\n// | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |\nexport class YearParser extends Parser {\n priority = 130;\n incompatibleTokens = [\"Y\", \"R\", \"u\", \"w\", \"I\", \"i\", \"e\", \"c\", \"t\", \"T\"];\n\n parse(dateString, token, match) {\n const valueCallback = (year) => ({\n year,\n isTwoDigitYear: token === \"yy\",\n });\n\n switch (token) {\n case \"y\":\n return mapValue(parseNDigits(4, dateString), valueCallback);\n case \"yo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"year\",\n }),\n valueCallback,\n );\n default:\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n }\n }\n\n validate(_date, value) {\n return value.isTwoDigitYear || value.year > 0;\n }\n\n set(date, flags, value) {\n const currentYear = date.getFullYear();\n\n if (value.isTwoDigitYear) {\n const normalizedTwoDigitYear = normalizeTwoDigitYear(\n value.year,\n currentYear,\n );\n date.setFullYear(normalizedTwoDigitYear, 0, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n const year =\n !(\"era\" in flags) || flags.era === 1 ? value.year : 1 - value.year;\n date.setFullYear(year, 0, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n}\n","import { getWeekYear } from \"../../../getWeekYear.js\";\n\nimport { startOfWeek } from \"../../../startOfWeek.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, normalizeTwoDigitYear, parseNDigits } from \"../utils.js\";\n\n// Local week-numbering year\nexport class LocalWeekYearParser extends Parser {\n priority = 130;\n\n parse(dateString, token, match) {\n const valueCallback = (year) => ({\n year,\n isTwoDigitYear: token === \"YY\",\n });\n\n switch (token) {\n case \"Y\":\n return mapValue(parseNDigits(4, dateString), valueCallback);\n case \"Yo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"year\",\n }),\n valueCallback,\n );\n default:\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n }\n }\n\n validate(_date, value) {\n return value.isTwoDigitYear || value.year > 0;\n }\n\n set(date, flags, value, options) {\n const currentYear = getWeekYear(date, options);\n\n if (value.isTwoDigitYear) {\n const normalizedTwoDigitYear = normalizeTwoDigitYear(\n value.year,\n currentYear,\n );\n date.setFullYear(\n normalizedTwoDigitYear,\n 0,\n options.firstWeekContainsDate,\n );\n date.setHours(0, 0, 0, 0);\n return startOfWeek(date, options);\n }\n\n const year =\n !(\"era\" in flags) || flags.era === 1 ? value.year : 1 - value.year;\n date.setFullYear(year, 0, options.firstWeekContainsDate);\n date.setHours(0, 0, 0, 0);\n return startOfWeek(date, options);\n }\n\n incompatibleTokens = [\n \"y\",\n \"R\",\n \"u\",\n \"Q\",\n \"q\",\n \"M\",\n \"L\",\n \"I\",\n \"d\",\n \"D\",\n \"i\",\n \"t\",\n \"T\",\n ];\n}\n","import { startOfISOWeek } from \"../../../startOfISOWeek.js\";\nimport { constructFrom } from \"../../../constructFrom.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigitsSigned } from \"../utils.js\";\n\n// ISO week-numbering year\nexport class ISOWeekYearParser extends Parser {\n priority = 130;\n\n parse(dateString, token) {\n if (token === \"R\") {\n return parseNDigitsSigned(4, dateString);\n }\n\n return parseNDigitsSigned(token.length, dateString);\n }\n\n set(date, _flags, value) {\n const firstWeekOfYear = constructFrom(date, 0);\n firstWeekOfYear.setFullYear(value, 0, 4);\n firstWeekOfYear.setHours(0, 0, 0, 0);\n return startOfISOWeek(firstWeekOfYear);\n }\n\n incompatibleTokens = [\n \"G\",\n \"y\",\n \"Y\",\n \"u\",\n \"Q\",\n \"q\",\n \"M\",\n \"L\",\n \"w\",\n \"d\",\n \"D\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { parseNDigitsSigned } from \"../utils.js\";\n\nexport class ExtendedYearParser extends Parser {\n priority = 130;\n\n parse(dateString, token) {\n if (token === \"u\") {\n return parseNDigitsSigned(4, dateString);\n }\n\n return parseNDigitsSigned(token.length, dateString);\n }\n\n set(date, _flags, value) {\n date.setFullYear(value, 0, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"G\", \"y\", \"Y\", \"R\", \"w\", \"I\", \"i\", \"e\", \"c\", \"t\", \"T\"];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { parseNDigits } from \"../utils.js\";\n\nexport class QuarterParser extends Parser {\n priority = 120;\n\n parse(dateString, token, match) {\n switch (token) {\n // 1, 2, 3, 4\n case \"Q\":\n case \"QQ\": // 01, 02, 03, 04\n return parseNDigits(token.length, dateString);\n // 1st, 2nd, 3rd, 4th\n case \"Qo\":\n return match.ordinalNumber(dateString, { unit: \"quarter\" });\n // Q1, Q2, Q3, Q4\n case \"QQQ\":\n return (\n match.quarter(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.quarter(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n\n // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n case \"QQQQQ\":\n return match.quarter(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n // 1st quarter, 2nd quarter, ...\n case \"QQQQ\":\n default:\n return (\n match.quarter(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.quarter(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.quarter(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 4;\n }\n\n set(date, _flags, value) {\n date.setMonth((value - 1) * 3, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"M\",\n \"L\",\n \"w\",\n \"I\",\n \"d\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { parseNDigits } from \"../utils.js\";\n\nexport class StandAloneQuarterParser extends Parser {\n priority = 120;\n\n parse(dateString, token, match) {\n switch (token) {\n // 1, 2, 3, 4\n case \"q\":\n case \"qq\": // 01, 02, 03, 04\n return parseNDigits(token.length, dateString);\n // 1st, 2nd, 3rd, 4th\n case \"qo\":\n return match.ordinalNumber(dateString, { unit: \"quarter\" });\n // Q1, Q2, Q3, Q4\n case \"qqq\":\n return (\n match.quarter(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.quarter(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n })\n );\n\n // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n case \"qqqqq\":\n return match.quarter(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n });\n // 1st quarter, 2nd quarter, ...\n case \"qqqq\":\n default:\n return (\n match.quarter(dateString, {\n width: \"wide\",\n context: \"standalone\",\n }) ||\n match.quarter(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.quarter(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 4;\n }\n\n set(date, _flags, value) {\n date.setMonth((value - 1) * 3, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"Q\",\n \"M\",\n \"L\",\n \"w\",\n \"I\",\n \"d\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class MonthParser extends Parser {\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"Q\",\n \"L\",\n \"w\",\n \"I\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n\n priority = 110;\n\n parse(dateString, token, match) {\n const valueCallback = (value) => value - 1;\n\n switch (token) {\n // 1, 2, ..., 12\n case \"M\":\n return mapValue(\n parseNumericPattern(numericPatterns.month, dateString),\n valueCallback,\n );\n // 01, 02, ..., 12\n case \"MM\":\n return mapValue(parseNDigits(2, dateString), valueCallback);\n // 1st, 2nd, ..., 12th\n case \"Mo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"month\",\n }),\n valueCallback,\n );\n // Jan, Feb, ..., Dec\n case \"MMM\":\n return (\n match.month(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.month(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // J, F, ..., D\n case \"MMMMM\":\n return match.month(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n // January, February, ..., December\n case \"MMMM\":\n default:\n return (\n match.month(dateString, { width: \"wide\", context: \"formatting\" }) ||\n match.month(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.month(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 11;\n }\n\n set(date, _flags, value) {\n date.setMonth(value, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class StandAloneMonthParser extends Parser {\n priority = 110;\n\n parse(dateString, token, match) {\n const valueCallback = (value) => value - 1;\n\n switch (token) {\n // 1, 2, ..., 12\n case \"L\":\n return mapValue(\n parseNumericPattern(numericPatterns.month, dateString),\n valueCallback,\n );\n // 01, 02, ..., 12\n case \"LL\":\n return mapValue(parseNDigits(2, dateString), valueCallback);\n // 1st, 2nd, ..., 12th\n case \"Lo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"month\",\n }),\n valueCallback,\n );\n // Jan, Feb, ..., Dec\n case \"LLL\":\n return (\n match.month(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.month(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n\n // J, F, ..., D\n case \"LLLLL\":\n return match.month(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n });\n // January, February, ..., December\n case \"LLLL\":\n default:\n return (\n match.month(dateString, { width: \"wide\", context: \"standalone\" }) ||\n match.month(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.month(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 11;\n }\n\n set(date, _flags, value) {\n date.setMonth(value, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"Q\",\n \"M\",\n \"w\",\n \"I\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { getWeek } from \"./getWeek.js\";\nimport { toDate } from \"./toDate.js\";\n\n/**\n * The {@link setWeek} function options.\n */\n\n/**\n * @name setWeek\n * @category Week Helpers\n * @summary Set the local week to the given date.\n *\n * @description\n * Set the local week to the given date, saving the weekday number.\n * The exact calculation depends on the values of\n * `options.weekStartsOn` (which is the index of the first day of the week)\n * and `options.firstWeekContainsDate` (which is the day of January, which is always in\n * the first week of the week-numbering year)\n *\n * Week numbering: https://en.wikipedia.org/wiki/Week#The_ISO_week_date_system\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The date to be changed\n * @param week - The week of the new date\n * @param options - An object with options\n *\n * @returns The new date with the local week set\n *\n * @example\n * // Set the 1st week to 2 January 2005 with default options:\n * const result = setWeek(new Date(2005, 0, 2), 1)\n * //=> Sun Dec 26 2004 00:00:00\n *\n * @example\n * // Set the 1st week to 2 January 2005,\n * // if Monday is the first day of the week,\n * // and the first week of the year always contains 4 January:\n * const result = setWeek(new Date(2005, 0, 2), 1, {\n * weekStartsOn: 1,\n * firstWeekContainsDate: 4\n * })\n * //=> Sun Jan 4 2004 00:00:00\n */\nexport function setWeek(date, week, options) {\n const date_ = toDate(date, options?.in);\n const diff = getWeek(date_, options) - week;\n date_.setDate(date_.getDate() - diff * 7);\n return toDate(date_, options?.in);\n}\n\n// Fallback for modularized imports:\nexport default setWeek;\n","import { setWeek } from \"../../../setWeek.js\";\nimport { startOfWeek } from \"../../../startOfWeek.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\n// Local week of year\nexport class LocalWeekParser extends Parser {\n priority = 100;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"w\":\n return parseNumericPattern(numericPatterns.week, dateString);\n case \"wo\":\n return match.ordinalNumber(dateString, { unit: \"week\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 53;\n }\n\n set(date, _flags, value, options) {\n return startOfWeek(setWeek(date, value, options), options);\n }\n\n incompatibleTokens = [\n \"y\",\n \"R\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"I\",\n \"d\",\n \"D\",\n \"i\",\n \"t\",\n \"T\",\n ];\n}\n","import { getISOWeek } from \"./getISOWeek.js\";\nimport { toDate } from \"./toDate.js\";\n\n/**\n * The {@link setISOWeek} function options.\n */\n\n/**\n * @name setISOWeek\n * @category ISO Week Helpers\n * @summary Set the ISO week to the given date.\n *\n * @description\n * Set the ISO week to the given date, saving the weekday number.\n *\n * ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The `Date` type of the context function.\n *\n * @param date - The date to be changed\n * @param week - The ISO week of the new date\n * @param options - An object with options\n *\n * @returns The new date with the ISO week set\n *\n * @example\n * // Set the 53rd ISO week to 7 August 2004:\n * const result = setISOWeek(new Date(2004, 7, 7), 53)\n * //=> Sat Jan 01 2005 00:00:00\n */\nexport function setISOWeek(date, week, options) {\n const _date = toDate(date, options?.in);\n const diff = getISOWeek(_date, options) - week;\n _date.setDate(_date.getDate() - diff * 7);\n return _date;\n}\n\n// Fallback for modularized imports:\nexport default setISOWeek;\n","import { setISOWeek } from \"../../../setISOWeek.js\";\nimport { startOfISOWeek } from \"../../../startOfISOWeek.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\n// ISO week of year\nexport class ISOWeekParser extends Parser {\n priority = 100;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"I\":\n return parseNumericPattern(numericPatterns.week, dateString);\n case \"Io\":\n return match.ordinalNumber(dateString, { unit: \"week\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 53;\n }\n\n set(date, _flags, value) {\n return startOfISOWeek(setISOWeek(date, value));\n }\n\n incompatibleTokens = [\n \"y\",\n \"Y\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"w\",\n \"d\",\n \"D\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport {\n isLeapYearIndex,\n parseNDigits,\n parseNumericPattern,\n} from \"../utils.js\";\n\nconst DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\nconst DAYS_IN_MONTH_LEAP_YEAR = [\n 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,\n];\n\n// Day of the month\nexport class DateParser extends Parser {\n priority = 90;\n subPriority = 1;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"d\":\n return parseNumericPattern(numericPatterns.date, dateString);\n case \"do\":\n return match.ordinalNumber(dateString, { unit: \"date\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(date, value) {\n const year = date.getFullYear();\n const isLeapYear = isLeapYearIndex(year);\n const month = date.getMonth();\n if (isLeapYear) {\n return value >= 1 && value <= DAYS_IN_MONTH_LEAP_YEAR[month];\n } else {\n return value >= 1 && value <= DAYS_IN_MONTH[month];\n }\n }\n\n set(date, _flags, value) {\n date.setDate(value);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"Q\",\n \"w\",\n \"I\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport {\n isLeapYearIndex,\n parseNDigits,\n parseNumericPattern,\n} from \"../utils.js\";\n\nexport class DayOfYearParser extends Parser {\n priority = 90;\n\n subpriority = 1;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"D\":\n case \"DD\":\n return parseNumericPattern(numericPatterns.dayOfYear, dateString);\n case \"Do\":\n return match.ordinalNumber(dateString, { unit: \"date\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(date, value) {\n const year = date.getFullYear();\n const isLeapYear = isLeapYearIndex(year);\n if (isLeapYear) {\n return value >= 1 && value <= 366;\n } else {\n return value >= 1 && value <= 365;\n }\n }\n\n set(date, _flags, value) {\n date.setMonth(0, value);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"w\",\n \"I\",\n \"d\",\n \"E\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { getDefaultOptions } from \"./_lib/defaultOptions.js\";\nimport { addDays } from \"./addDays.js\";\nimport { toDate } from \"./toDate.js\";\n\n/**\n * The {@link setDay} function options.\n */\n\n/**\n * @name setDay\n * @category Weekday Helpers\n * @summary Set the day of the week to the given date.\n *\n * @description\n * Set the day of the week to the given date.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The date to be changed\n * @param day - The day of the week of the new date\n * @param options - An object with options.\n *\n * @returns The new date with the day of the week set\n *\n * @example\n * // Set week day to Sunday, with the default weekStartsOn of Sunday:\n * const result = setDay(new Date(2014, 8, 1), 0)\n * //=> Sun Aug 31 2014 00:00:00\n *\n * @example\n * // Set week day to Sunday, with a weekStartsOn of Monday:\n * const result = setDay(new Date(2014, 8, 1), 0, { weekStartsOn: 1 })\n * //=> Sun Sep 07 2014 00:00:00\n */\nexport function setDay(date, day, options) {\n const defaultOptions = getDefaultOptions();\n const weekStartsOn =\n options?.weekStartsOn ??\n options?.locale?.options?.weekStartsOn ??\n defaultOptions.weekStartsOn ??\n defaultOptions.locale?.options?.weekStartsOn ??\n 0;\n\n const date_ = toDate(date, options?.in);\n const currentDay = date_.getDay();\n\n const remainder = day % 7;\n const dayIndex = (remainder + 7) % 7;\n\n const delta = 7 - weekStartsOn;\n const diff =\n day < 0 || day > 6\n ? day - ((currentDay + delta) % 7)\n : ((dayIndex + delta) % 7) - ((currentDay + delta) % 7);\n return addDays(date_, diff, options);\n}\n\n// Fallback for modularized imports:\nexport default setDay;\n","import { setDay } from \"../../../setDay.js\";\nimport { Parser } from \"../Parser.js\";\n\n// Day of week\nexport class DayParser extends Parser {\n priority = 90;\n\n parse(dateString, token, match) {\n switch (token) {\n // Tue\n case \"E\":\n case \"EE\":\n case \"EEE\":\n return (\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // T\n case \"EEEEE\":\n return match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n // Tu\n case \"EEEEEE\":\n return (\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // Tuesday\n case \"EEEE\":\n default:\n return (\n match.day(dateString, { width: \"wide\", context: \"formatting\" }) ||\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 6;\n }\n\n set(date, _flags, value, options) {\n date = setDay(date, value, options);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"D\", \"i\", \"e\", \"c\", \"t\", \"T\"];\n}\n","import { setDay } from \"../../../setDay.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits } from \"../utils.js\";\n\n// Local day of week\nexport class LocalDayParser extends Parser {\n priority = 90;\n parse(dateString, token, match, options) {\n const valueCallback = (value) => {\n // We want here floor instead of trunc, so we get -7 for value 0 instead of 0\n const wholeWeekDays = Math.floor((value - 1) / 7) * 7;\n return ((value + options.weekStartsOn + 6) % 7) + wholeWeekDays;\n };\n\n switch (token) {\n // 3\n case \"e\":\n case \"ee\": // 03\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n // 3rd\n case \"eo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"day\",\n }),\n valueCallback,\n );\n // Tue\n case \"eee\":\n return (\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // T\n case \"eeeee\":\n return match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n // Tu\n case \"eeeeee\":\n return (\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // Tuesday\n case \"eeee\":\n default:\n return (\n match.day(dateString, { width: \"wide\", context: \"formatting\" }) ||\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 6;\n }\n\n set(date, _flags, value, options) {\n date = setDay(date, value, options);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"y\",\n \"R\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"I\",\n \"d\",\n \"D\",\n \"E\",\n \"i\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { setDay } from \"../../../setDay.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits } from \"../utils.js\";\n\n// Stand-alone local day of week\nexport class StandAloneLocalDayParser extends Parser {\n priority = 90;\n\n parse(dateString, token, match, options) {\n const valueCallback = (value) => {\n // We want here floor instead of trunc, so we get -7 for value 0 instead of 0\n const wholeWeekDays = Math.floor((value - 1) / 7) * 7;\n return ((value + options.weekStartsOn + 6) % 7) + wholeWeekDays;\n };\n\n switch (token) {\n // 3\n case \"c\":\n case \"cc\": // 03\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n // 3rd\n case \"co\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"day\",\n }),\n valueCallback,\n );\n // Tue\n case \"ccc\":\n return (\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"standalone\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n\n // T\n case \"ccccc\":\n return match.day(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n });\n // Tu\n case \"cccccc\":\n return (\n match.day(dateString, { width: \"short\", context: \"standalone\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n\n // Tuesday\n case \"cccc\":\n default:\n return (\n match.day(dateString, { width: \"wide\", context: \"standalone\" }) ||\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"standalone\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 6;\n }\n\n set(date, _flags, value, options) {\n date = setDay(date, value, options);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"y\",\n \"R\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"I\",\n \"d\",\n \"D\",\n \"E\",\n \"i\",\n \"e\",\n \"t\",\n \"T\",\n ];\n}\n","import { addDays } from \"./addDays.js\";\nimport { getISODay } from \"./getISODay.js\";\nimport { toDate } from \"./toDate.js\";\n\n/**\n * The {@link setISODay} function options.\n */\n\n/**\n * @name setISODay\n * @category Weekday Helpers\n * @summary Set the day of the ISO week to the given date.\n *\n * @description\n * Set the day of the ISO week to the given date.\n * ISO week starts with Monday.\n * 7 is the index of Sunday, 1 is the index of Monday, etc.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The date to be changed\n * @param day - The day of the ISO week of the new date\n * @param options - An object with options\n *\n * @returns The new date with the day of the ISO week set\n *\n * @example\n * // Set Sunday to 1 September 2014:\n * const result = setISODay(new Date(2014, 8, 1), 7)\n * //=> Sun Sep 07 2014 00:00:00\n */\nexport function setISODay(date, day, options) {\n const date_ = toDate(date, options?.in);\n const currentDay = getISODay(date_, options);\n const diff = day - currentDay;\n return addDays(date_, diff, options);\n}\n\n// Fallback for modularized imports:\nexport default setISODay;\n","import { setISODay } from \"../../../setISODay.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits } from \"../utils.js\";\n\n// ISO day of week\nexport class ISODayParser extends Parser {\n priority = 90;\n\n parse(dateString, token, match) {\n const valueCallback = (value) => {\n if (value === 0) {\n return 7;\n }\n return value;\n };\n\n switch (token) {\n // 2\n case \"i\":\n case \"ii\": // 02\n return parseNDigits(token.length, dateString);\n // 2nd\n case \"io\":\n return match.ordinalNumber(dateString, { unit: \"day\" });\n // Tue\n case \"iii\":\n return mapValue(\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"short\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n }),\n valueCallback,\n );\n // T\n case \"iiiii\":\n return mapValue(\n match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n }),\n valueCallback,\n );\n // Tu\n case \"iiiiii\":\n return mapValue(\n match.day(dateString, {\n width: \"short\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n }),\n valueCallback,\n );\n // Tuesday\n case \"iiii\":\n default:\n return mapValue(\n match.day(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"short\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n }),\n valueCallback,\n );\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 7;\n }\n\n set(date, _flags, value) {\n date = setISODay(date, value);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"y\",\n \"Y\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"w\",\n \"d\",\n \"D\",\n \"E\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { dayPeriodEnumToHours } from \"../utils.js\";\n\nexport class AMPMParser extends Parser {\n priority = 80;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"a\":\n case \"aa\":\n case \"aaa\":\n return (\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n\n case \"aaaaa\":\n return match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n case \"aaaa\":\n default:\n return (\n match.dayPeriod(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n }\n }\n\n set(date, _flags, value) {\n date.setHours(dayPeriodEnumToHours(value), 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"b\", \"B\", \"H\", \"k\", \"t\", \"T\"];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { dayPeriodEnumToHours } from \"../utils.js\";\n\nexport class AMPMMidnightParser extends Parser {\n priority = 80;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"b\":\n case \"bb\":\n case \"bbb\":\n return (\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n\n case \"bbbbb\":\n return match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n case \"bbbb\":\n default:\n return (\n match.dayPeriod(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n }\n }\n\n set(date, _flags, value) {\n date.setHours(dayPeriodEnumToHours(value), 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"a\", \"B\", \"H\", \"k\", \"t\", \"T\"];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { dayPeriodEnumToHours } from \"../utils.js\";\n\n// in the morning, in the afternoon, in the evening, at night\nexport class DayPeriodParser extends Parser {\n priority = 80;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"B\":\n case \"BB\":\n case \"BBB\":\n return (\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n\n case \"BBBBB\":\n return match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n case \"BBBB\":\n default:\n return (\n match.dayPeriod(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n }\n }\n\n set(date, _flags, value) {\n date.setHours(dayPeriodEnumToHours(value), 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"a\", \"b\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class Hour1to12Parser extends Parser {\n priority = 70;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"h\":\n return parseNumericPattern(numericPatterns.hour12h, dateString);\n case \"ho\":\n return match.ordinalNumber(dateString, { unit: \"hour\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 12;\n }\n\n set(date, _flags, value) {\n const isPM = date.getHours() >= 12;\n if (isPM && value < 12) {\n date.setHours(value + 12, 0, 0, 0);\n } else if (!isPM && value === 12) {\n date.setHours(0, 0, 0, 0);\n } else {\n date.setHours(value, 0, 0, 0);\n }\n return date;\n }\n\n incompatibleTokens = [\"H\", \"K\", \"k\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class Hour0to23Parser extends Parser {\n priority = 70;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"H\":\n return parseNumericPattern(numericPatterns.hour23h, dateString);\n case \"Ho\":\n return match.ordinalNumber(dateString, { unit: \"hour\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 23;\n }\n\n set(date, _flags, value) {\n date.setHours(value, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"a\", \"b\", \"h\", \"K\", \"k\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class Hour0To11Parser extends Parser {\n priority = 70;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"K\":\n return parseNumericPattern(numericPatterns.hour11h, dateString);\n case \"Ko\":\n return match.ordinalNumber(dateString, { unit: \"hour\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 11;\n }\n\n set(date, _flags, value) {\n const isPM = date.getHours() >= 12;\n if (isPM && value < 12) {\n date.setHours(value + 12, 0, 0, 0);\n } else {\n date.setHours(value, 0, 0, 0);\n }\n return date;\n }\n\n incompatibleTokens = [\"h\", \"H\", \"k\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class Hour1To24Parser extends Parser {\n priority = 70;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"k\":\n return parseNumericPattern(numericPatterns.hour24h, dateString);\n case \"ko\":\n return match.ordinalNumber(dateString, { unit: \"hour\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 24;\n }\n\n set(date, _flags, value) {\n const hours = value <= 24 ? value % 24 : value;\n date.setHours(hours, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"a\", \"b\", \"h\", \"H\", \"K\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class MinuteParser extends Parser {\n priority = 60;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"m\":\n return parseNumericPattern(numericPatterns.minute, dateString);\n case \"mo\":\n return match.ordinalNumber(dateString, { unit: \"minute\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 59;\n }\n\n set(date, _flags, value) {\n date.setMinutes(value, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class SecondParser extends Parser {\n priority = 50;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"s\":\n return parseNumericPattern(numericPatterns.second, dateString);\n case \"so\":\n return match.ordinalNumber(dateString, { unit: \"second\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 59;\n }\n\n set(date, _flags, value) {\n date.setSeconds(value, 0);\n return date;\n }\n\n incompatibleTokens = [\"t\", \"T\"];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits } from \"../utils.js\";\n\nexport class FractionOfSecondParser extends Parser {\n priority = 30;\n\n parse(dateString, token) {\n const valueCallback = (value) =>\n Math.trunc(value * Math.pow(10, -token.length + 3));\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n }\n\n set(date, _flags, value) {\n date.setMilliseconds(value);\n return date;\n }\n\n incompatibleTokens = [\"t\", \"T\"];\n}\n","import { constructFrom } from \"../../../constructFrom.js\";\nimport { getTimezoneOffsetInMilliseconds } from \"../../../_lib/getTimezoneOffsetInMilliseconds.js\";\nimport { timezonePatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseTimezonePattern } from \"../utils.js\";\n\n// Timezone (ISO-8601. +00:00 is `'Z'`)\nexport class ISOTimezoneWithZParser extends Parser {\n priority = 10;\n\n parse(dateString, token) {\n switch (token) {\n case \"X\":\n return parseTimezonePattern(\n timezonePatterns.basicOptionalMinutes,\n dateString,\n );\n case \"XX\":\n return parseTimezonePattern(timezonePatterns.basic, dateString);\n case \"XXXX\":\n return parseTimezonePattern(\n timezonePatterns.basicOptionalSeconds,\n dateString,\n );\n case \"XXXXX\":\n return parseTimezonePattern(\n timezonePatterns.extendedOptionalSeconds,\n dateString,\n );\n case \"XXX\":\n default:\n return parseTimezonePattern(timezonePatterns.extended, dateString);\n }\n }\n\n set(date, flags, value) {\n if (flags.timestampIsSet) return date;\n return constructFrom(\n date,\n date.getTime() - getTimezoneOffsetInMilliseconds(date) - value,\n );\n }\n\n incompatibleTokens = [\"t\", \"T\", \"x\"];\n}\n","import { constructFrom } from \"../../../constructFrom.js\";\nimport { getTimezoneOffsetInMilliseconds } from \"../../../_lib/getTimezoneOffsetInMilliseconds.js\";\nimport { timezonePatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseTimezonePattern } from \"../utils.js\";\n\n// Timezone (ISO-8601)\nexport class ISOTimezoneParser extends Parser {\n priority = 10;\n\n parse(dateString, token) {\n switch (token) {\n case \"x\":\n return parseTimezonePattern(\n timezonePatterns.basicOptionalMinutes,\n dateString,\n );\n case \"xx\":\n return parseTimezonePattern(timezonePatterns.basic, dateString);\n case \"xxxx\":\n return parseTimezonePattern(\n timezonePatterns.basicOptionalSeconds,\n dateString,\n );\n case \"xxxxx\":\n return parseTimezonePattern(\n timezonePatterns.extendedOptionalSeconds,\n dateString,\n );\n case \"xxx\":\n default:\n return parseTimezonePattern(timezonePatterns.extended, dateString);\n }\n }\n\n set(date, flags, value) {\n if (flags.timestampIsSet) return date;\n return constructFrom(\n date,\n date.getTime() - getTimezoneOffsetInMilliseconds(date) - value,\n );\n }\n\n incompatibleTokens = [\"t\", \"T\", \"X\"];\n}\n","import { constructFrom } from \"../../../constructFrom.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseAnyDigitsSigned } from \"../utils.js\";\n\nexport class TimestampSecondsParser extends Parser {\n priority = 40;\n\n parse(dateString) {\n return parseAnyDigitsSigned(dateString);\n }\n\n set(date, _flags, value) {\n return [constructFrom(date, value * 1000), { timestampIsSet: true }];\n }\n\n incompatibleTokens = \"*\";\n}\n","import { constructFrom } from \"../../../constructFrom.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseAnyDigitsSigned } from \"../utils.js\";\n\nexport class TimestampMillisecondsParser extends Parser {\n priority = 20;\n\n parse(dateString) {\n return parseAnyDigitsSigned(dateString);\n }\n\n set(date, _flags, value) {\n return [constructFrom(date, value), { timestampIsSet: true }];\n }\n\n incompatibleTokens = \"*\";\n}\n","import { EraParser } from \"./parsers/EraParser.js\";\nimport { YearParser } from \"./parsers/YearParser.js\";\nimport { LocalWeekYearParser } from \"./parsers/LocalWeekYearParser.js\";\nimport { ISOWeekYearParser } from \"./parsers/ISOWeekYearParser.js\";\nimport { ExtendedYearParser } from \"./parsers/ExtendedYearParser.js\";\nimport { QuarterParser } from \"./parsers/QuarterParser.js\";\nimport { StandAloneQuarterParser } from \"./parsers/StandAloneQuarterParser.js\";\nimport { MonthParser } from \"./parsers/MonthParser.js\";\nimport { StandAloneMonthParser } from \"./parsers/StandAloneMonthParser.js\";\nimport { LocalWeekParser } from \"./parsers/LocalWeekParser.js\";\nimport { ISOWeekParser } from \"./parsers/ISOWeekParser.js\";\nimport { DateParser } from \"./parsers/DateParser.js\";\nimport { DayOfYearParser } from \"./parsers/DayOfYearParser.js\";\nimport { DayParser } from \"./parsers/DayParser.js\";\nimport { LocalDayParser } from \"./parsers/LocalDayParser.js\";\nimport { StandAloneLocalDayParser } from \"./parsers/StandAloneLocalDayParser.js\";\nimport { ISODayParser } from \"./parsers/ISODayParser.js\";\nimport { AMPMParser } from \"./parsers/AMPMParser.js\";\nimport { AMPMMidnightParser } from \"./parsers/AMPMMidnightParser.js\";\nimport { DayPeriodParser } from \"./parsers/DayPeriodParser.js\";\nimport { Hour1to12Parser } from \"./parsers/Hour1to12Parser.js\";\nimport { Hour0to23Parser } from \"./parsers/Hour0to23Parser.js\";\nimport { Hour0To11Parser } from \"./parsers/Hour0To11Parser.js\";\nimport { Hour1To24Parser } from \"./parsers/Hour1To24Parser.js\";\nimport { MinuteParser } from \"./parsers/MinuteParser.js\";\nimport { SecondParser } from \"./parsers/SecondParser.js\";\nimport { FractionOfSecondParser } from \"./parsers/FractionOfSecondParser.js\";\nimport { ISOTimezoneWithZParser } from \"./parsers/ISOTimezoneWithZParser.js\";\nimport { ISOTimezoneParser } from \"./parsers/ISOTimezoneParser.js\";\nimport { TimestampSecondsParser } from \"./parsers/TimestampSecondsParser.js\";\nimport { TimestampMillisecondsParser } from \"./parsers/TimestampMillisecondsParser.js\";\n\n/*\n * | | Unit | | Unit |\n * |-----|--------------------------------|-----|--------------------------------|\n * | a | AM, PM | A* | Milliseconds in day |\n * | b | AM, PM, noon, midnight | B | Flexible day period |\n * | c | Stand-alone local day of week | C* | Localized hour w/ day period |\n * | d | Day of month | D | Day of year |\n * | e | Local day of week | E | Day of week |\n * | f | | F* | Day of week in month |\n * | g* | Modified Julian day | G | Era |\n * | h | Hour [1-12] | H | Hour [0-23] |\n * | i! | ISO day of week | I! | ISO week of year |\n * | j* | Localized hour w/ day period | J* | Localized hour w/o day period |\n * | k | Hour [1-24] | K | Hour [0-11] |\n * | l* | (deprecated) | L | Stand-alone month |\n * | m | Minute | M | Month |\n * | n | | N | |\n * | o! | Ordinal number modifier | O* | Timezone (GMT) |\n * | p | | P | |\n * | q | Stand-alone quarter | Q | Quarter |\n * | r* | Related Gregorian year | R! | ISO week-numbering year |\n * | s | Second | S | Fraction of second |\n * | t! | Seconds timestamp | T! | Milliseconds timestamp |\n * | u | Extended year | U* | Cyclic year |\n * | v* | Timezone (generic non-locat.) | V* | Timezone (location) |\n * | w | Local week of year | W* | Week of month |\n * | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |\n * | y | Year (abs) | Y | Local week-numbering year |\n * | z* | Timezone (specific non-locat.) | Z* | Timezone (aliases) |\n *\n * Letters marked by * are not implemented but reserved by Unicode standard.\n *\n * Letters marked by ! are non-standard, but implemented by date-fns:\n * - `o` modifies the previous token to turn it into an ordinal (see `parse` docs)\n * - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,\n * i.e. 7 for Sunday, 1 for Monday, etc.\n * - `I` is ISO week of year, as opposed to `w` which is local week of year.\n * - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.\n * `R` is supposed to be used in conjunction with `I` and `i`\n * for universal ISO week-numbering date, whereas\n * `Y` is supposed to be used in conjunction with `w` and `e`\n * for week-numbering date specific to the locale.\n */\nexport const parsers = {\n G: new EraParser(),\n y: new YearParser(),\n Y: new LocalWeekYearParser(),\n R: new ISOWeekYearParser(),\n u: new ExtendedYearParser(),\n Q: new QuarterParser(),\n q: new StandAloneQuarterParser(),\n M: new MonthParser(),\n L: new StandAloneMonthParser(),\n w: new LocalWeekParser(),\n I: new ISOWeekParser(),\n d: new DateParser(),\n D: new DayOfYearParser(),\n E: new DayParser(),\n e: new LocalDayParser(),\n c: new StandAloneLocalDayParser(),\n i: new ISODayParser(),\n a: new AMPMParser(),\n b: new AMPMMidnightParser(),\n B: new DayPeriodParser(),\n h: new Hour1to12Parser(),\n H: new Hour0to23Parser(),\n K: new Hour0To11Parser(),\n k: new Hour1To24Parser(),\n m: new MinuteParser(),\n s: new SecondParser(),\n S: new FractionOfSecondParser(),\n X: new ISOTimezoneWithZParser(),\n x: new ISOTimezoneParser(),\n t: new TimestampSecondsParser(),\n T: new TimestampMillisecondsParser(),\n};\n","import { defaultLocale } from \"./_lib/defaultLocale.js\";\nimport { longFormatters } from \"./_lib/format/longFormatters.js\";\nimport {\n isProtectedDayOfYearToken,\n isProtectedWeekYearToken,\n warnOrThrowProtectedError,\n} from \"./_lib/protectedTokens.js\";\nimport { constructFrom } from \"./constructFrom.js\";\nimport { getDefaultOptions } from \"./getDefaultOptions.js\";\nimport { toDate } from \"./toDate.js\";\n\nimport { DateTimezoneSetter } from \"./parse/_lib/Setter.js\";\nimport { parsers } from \"./parse/_lib/parsers.js\";\n\n// Rexports of internal for libraries to use.\n// See: https://github.com/date-fns/date-fns/issues/3638#issuecomment-1877082874\nexport { longFormatters, parsers };\n\n/**\n * The {@link parse} function options.\n */\n\n// This RegExp consists of three parts separated by `|`:\n// - [yYQqMLwIdDecihHKkms]o matches any available ordinal number token\n// (one of the certain letters followed by `o`)\n// - (\\w)\\1* matches any sequences of the same letter\n// - '' matches two quote characters in a row\n// - '(''|[^'])+('|$) matches anything surrounded by two quote characters ('),\n// except a single quote symbol, which ends the sequence.\n// Two quote characters do not end the sequence.\n// If there is no matching single quote\n// then the sequence will continue until the end of the string.\n// - . matches any single character unmatched by previous parts of the RegExps\nconst formattingTokensRegExp =\n /[yYQqMLwIdDecihHKkms]o|(\\w)\\1*|''|'(''|[^'])+('|$)|./g;\n\n// This RegExp catches symbols escaped by quotes, and also\n// sequences of symbols P, p, and the combinations like `PPPPPPPppppp`\nconst longFormattingTokensRegExp = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;\n\nconst escapedStringRegExp = /^'([^]*?)'?$/;\nconst doubleQuoteRegExp = /''/g;\n\nconst notWhitespaceRegExp = /\\S/;\nconst unescapedLatinCharacterRegExp = /[a-zA-Z]/;\n\n/**\n * @name parse\n * @category Common Helpers\n * @summary Parse the date.\n *\n * @description\n * Return the date parsed from string using the given format string.\n *\n * > ⚠️ Please note that the `format` tokens differ from Moment.js and other libraries.\n * > See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * The characters in the format string wrapped between two single quotes characters (') are escaped.\n * Two single quotes in a row, whether inside or outside a quoted sequence, represent a 'real' single quote.\n *\n * Format of the format string is based on Unicode Technical Standard #35:\n * https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n * with a few additions (see note 5 below the table).\n *\n * Not all tokens are compatible. Combinations that don't make sense or could lead to bugs are prohibited\n * and will throw `RangeError`. For example usage of 24-hour format token with AM/PM token will throw an exception:\n *\n * ```javascript\n * parse('23 AM', 'HH a', new Date())\n * //=> RangeError: The format string mustn't contain `HH` and `a` at the same time\n * ```\n *\n * See the compatibility table: https://docs.google.com/spreadsheets/d/e/2PACX-1vQOPU3xUhplll6dyoMmVUXHKl_8CRDs6_ueLmex3SoqwhuolkuN3O05l4rqx5h1dKX8eb46Ul-CCSrq/pubhtml?gid=0&single=true\n *\n * Accepted format string patterns:\n * | Unit |Prior| Pattern | Result examples | Notes |\n * |---------------------------------|-----|---------|-----------------------------------|-------|\n * | Era | 140 | G..GGG | AD, BC | |\n * | | | GGGG | Anno Domini, Before Christ | 2 |\n * | | | GGGGG | A, B | |\n * | Calendar year | 130 | y | 44, 1, 1900, 2017, 9999 | 4 |\n * | | | yo | 44th, 1st, 1900th, 9999999th | 4,5 |\n * | | | yy | 44, 01, 00, 17 | 4 |\n * | | | yyy | 044, 001, 123, 999 | 4 |\n * | | | yyyy | 0044, 0001, 1900, 2017 | 4 |\n * | | | yyyyy | ... | 2,4 |\n * | Local week-numbering year | 130 | Y | 44, 1, 1900, 2017, 9000 | 4 |\n * | | | Yo | 44th, 1st, 1900th, 9999999th | 4,5 |\n * | | | YY | 44, 01, 00, 17 | 4,6 |\n * | | | YYY | 044, 001, 123, 999 | 4 |\n * | | | YYYY | 0044, 0001, 1900, 2017 | 4,6 |\n * | | | YYYYY | ... | 2,4 |\n * | ISO week-numbering year | 130 | R | -43, 1, 1900, 2017, 9999, -9999 | 4,5 |\n * | | | RR | -43, 01, 00, 17 | 4,5 |\n * | | | RRR | -043, 001, 123, 999, -999 | 4,5 |\n * | | | RRRR | -0043, 0001, 2017, 9999, -9999 | 4,5 |\n * | | | RRRRR | ... | 2,4,5 |\n * | Extended year | 130 | u | -43, 1, 1900, 2017, 9999, -999 | 4 |\n * | | | uu | -43, 01, 99, -99 | 4 |\n * | | | uuu | -043, 001, 123, 999, -999 | 4 |\n * | | | uuuu | -0043, 0001, 2017, 9999, -9999 | 4 |\n * | | | uuuuu | ... | 2,4 |\n * | Quarter (formatting) | 120 | Q | 1, 2, 3, 4 | |\n * | | | Qo | 1st, 2nd, 3rd, 4th | 5 |\n * | | | QQ | 01, 02, 03, 04 | |\n * | | | QQQ | Q1, Q2, Q3, Q4 | |\n * | | | QQQQ | 1st quarter, 2nd quarter, ... | 2 |\n * | | | QQQQQ | 1, 2, 3, 4 | 4 |\n * | Quarter (stand-alone) | 120 | q | 1, 2, 3, 4 | |\n * | | | qo | 1st, 2nd, 3rd, 4th | 5 |\n * | | | qq | 01, 02, 03, 04 | |\n * | | | qqq | Q1, Q2, Q3, Q4 | |\n * | | | qqqq | 1st quarter, 2nd quarter, ... | 2 |\n * | | | qqqqq | 1, 2, 3, 4 | 3 |\n * | Month (formatting) | 110 | M | 1, 2, ..., 12 | |\n * | | | Mo | 1st, 2nd, ..., 12th | 5 |\n * | | | MM | 01, 02, ..., 12 | |\n * | | | MMM | Jan, Feb, ..., Dec | |\n * | | | MMMM | January, February, ..., December | 2 |\n * | | | MMMMM | J, F, ..., D | |\n * | Month (stand-alone) | 110 | L | 1, 2, ..., 12 | |\n * | | | Lo | 1st, 2nd, ..., 12th | 5 |\n * | | | LL | 01, 02, ..., 12 | |\n * | | | LLL | Jan, Feb, ..., Dec | |\n * | | | LLLL | January, February, ..., December | 2 |\n * | | | LLLLL | J, F, ..., D | |\n * | Local week of year | 100 | w | 1, 2, ..., 53 | |\n * | | | wo | 1st, 2nd, ..., 53th | 5 |\n * | | | ww | 01, 02, ..., 53 | |\n * | ISO week of year | 100 | I | 1, 2, ..., 53 | 5 |\n * | | | Io | 1st, 2nd, ..., 53th | 5 |\n * | | | II | 01, 02, ..., 53 | 5 |\n * | Day of month | 90 | d | 1, 2, ..., 31 | |\n * | | | do | 1st, 2nd, ..., 31st | 5 |\n * | | | dd | 01, 02, ..., 31 | |\n * | Day of year | 90 | D | 1, 2, ..., 365, 366 | 7 |\n * | | | Do | 1st, 2nd, ..., 365th, 366th | 5 |\n * | | | DD | 01, 02, ..., 365, 366 | 7 |\n * | | | DDD | 001, 002, ..., 365, 366 | |\n * | | | DDDD | ... | 2 |\n * | Day of week (formatting) | 90 | E..EEE | Mon, Tue, Wed, ..., Sun | |\n * | | | EEEE | Monday, Tuesday, ..., Sunday | 2 |\n * | | | EEEEE | M, T, W, T, F, S, S | |\n * | | | EEEEEE | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | ISO day of week (formatting) | 90 | i | 1, 2, 3, ..., 7 | 5 |\n * | | | io | 1st, 2nd, ..., 7th | 5 |\n * | | | ii | 01, 02, ..., 07 | 5 |\n * | | | iii | Mon, Tue, Wed, ..., Sun | 5 |\n * | | | iiii | Monday, Tuesday, ..., Sunday | 2,5 |\n * | | | iiiii | M, T, W, T, F, S, S | 5 |\n * | | | iiiiii | Mo, Tu, We, Th, Fr, Sa, Su | 5 |\n * | Local day of week (formatting) | 90 | e | 2, 3, 4, ..., 1 | |\n * | | | eo | 2nd, 3rd, ..., 1st | 5 |\n * | | | ee | 02, 03, ..., 01 | |\n * | | | eee | Mon, Tue, Wed, ..., Sun | |\n * | | | eeee | Monday, Tuesday, ..., Sunday | 2 |\n * | | | eeeee | M, T, W, T, F, S, S | |\n * | | | eeeeee | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | Local day of week (stand-alone) | 90 | c | 2, 3, 4, ..., 1 | |\n * | | | co | 2nd, 3rd, ..., 1st | 5 |\n * | | | cc | 02, 03, ..., 01 | |\n * | | | ccc | Mon, Tue, Wed, ..., Sun | |\n * | | | cccc | Monday, Tuesday, ..., Sunday | 2 |\n * | | | ccccc | M, T, W, T, F, S, S | |\n * | | | cccccc | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | AM, PM | 80 | a..aaa | AM, PM | |\n * | | | aaaa | a.m., p.m. | 2 |\n * | | | aaaaa | a, p | |\n * | AM, PM, noon, midnight | 80 | b..bbb | AM, PM, noon, midnight | |\n * | | | bbbb | a.m., p.m., noon, midnight | 2 |\n * | | | bbbbb | a, p, n, mi | |\n * | Flexible day period | 80 | B..BBB | at night, in the morning, ... | |\n * | | | BBBB | at night, in the morning, ... | 2 |\n * | | | BBBBB | at night, in the morning, ... | |\n * | Hour [1-12] | 70 | h | 1, 2, ..., 11, 12 | |\n * | | | ho | 1st, 2nd, ..., 11th, 12th | 5 |\n * | | | hh | 01, 02, ..., 11, 12 | |\n * | Hour [0-23] | 70 | H | 0, 1, 2, ..., 23 | |\n * | | | Ho | 0th, 1st, 2nd, ..., 23rd | 5 |\n * | | | HH | 00, 01, 02, ..., 23 | |\n * | Hour [0-11] | 70 | K | 1, 2, ..., 11, 0 | |\n * | | | Ko | 1st, 2nd, ..., 11th, 0th | 5 |\n * | | | KK | 01, 02, ..., 11, 00 | |\n * | Hour [1-24] | 70 | k | 24, 1, 2, ..., 23 | |\n * | | | ko | 24th, 1st, 2nd, ..., 23rd | 5 |\n * | | | kk | 24, 01, 02, ..., 23 | |\n * | Minute | 60 | m | 0, 1, ..., 59 | |\n * | | | mo | 0th, 1st, ..., 59th | 5 |\n * | | | mm | 00, 01, ..., 59 | |\n * | Second | 50 | s | 0, 1, ..., 59 | |\n * | | | so | 0th, 1st, ..., 59th | 5 |\n * | | | ss | 00, 01, ..., 59 | |\n * | Seconds timestamp | 40 | t | 512969520 | |\n * | | | tt | ... | 2 |\n * | Fraction of second | 30 | S | 0, 1, ..., 9 | |\n * | | | SS | 00, 01, ..., 99 | |\n * | | | SSS | 000, 001, ..., 999 | |\n * | | | SSSS | ... | 2 |\n * | Milliseconds timestamp | 20 | T | 512969520900 | |\n * | | | TT | ... | 2 |\n * | Timezone (ISO-8601 w/ Z) | 10 | X | -08, +0530, Z | |\n * | | | XX | -0800, +0530, Z | |\n * | | | XXX | -08:00, +05:30, Z | |\n * | | | XXXX | -0800, +0530, Z, +123456 | 2 |\n * | | | XXXXX | -08:00, +05:30, Z, +12:34:56 | |\n * | Timezone (ISO-8601 w/o Z) | 10 | x | -08, +0530, +00 | |\n * | | | xx | -0800, +0530, +0000 | |\n * | | | xxx | -08:00, +05:30, +00:00 | 2 |\n * | | | xxxx | -0800, +0530, +0000, +123456 | |\n * | | | xxxxx | -08:00, +05:30, +00:00, +12:34:56 | |\n * | Long localized date | NA | P | 05/29/1453 | 5,8 |\n * | | | PP | May 29, 1453 | |\n * | | | PPP | May 29th, 1453 | |\n * | | | PPPP | Sunday, May 29th, 1453 | 2,5,8 |\n * | Long localized time | NA | p | 12:00 AM | 5,8 |\n * | | | pp | 12:00:00 AM | |\n * | Combination of date and time | NA | Pp | 05/29/1453, 12:00 AM | |\n * | | | PPpp | May 29, 1453, 12:00:00 AM | |\n * | | | PPPpp | May 29th, 1453 at ... | |\n * | | | PPPPpp | Sunday, May 29th, 1453 at ... | 2,5,8 |\n * Notes:\n * 1. \"Formatting\" units (e.g. formatting quarter) in the default en-US locale\n * are the same as \"stand-alone\" units, but are different in some languages.\n * \"Formatting\" units are declined according to the rules of the language\n * in the context of a date. \"Stand-alone\" units are always nominative singular.\n * In `format` function, they will produce different result:\n *\n * `format(new Date(2017, 10, 6), 'do LLLL', {locale: cs}) //=> '6. listopad'`\n *\n * `format(new Date(2017, 10, 6), 'do MMMM', {locale: cs}) //=> '6. listopadu'`\n *\n * `parse` will try to match both formatting and stand-alone units interchangeably.\n *\n * 2. Any sequence of the identical letters is a pattern, unless it is escaped by\n * the single quote characters (see below).\n * If the sequence is longer than listed in table:\n * - for numerical units (`yyyyyyyy`) `parse` will try to match a number\n * as wide as the sequence\n * - for text units (`MMMMMMMM`) `parse` will try to match the widest variation of the unit.\n * These variations are marked with \"2\" in the last column of the table.\n *\n * 3. `QQQQQ` and `qqqqq` could be not strictly numerical in some locales.\n * These tokens represent the shortest form of the quarter.\n *\n * 4. The main difference between `y` and `u` patterns are B.C. years:\n *\n * | Year | `y` | `u` |\n * |------|-----|-----|\n * | AC 1 | 1 | 1 |\n * | BC 1 | 1 | 0 |\n * | BC 2 | 2 | -1 |\n *\n * Also `yy` will try to guess the century of two digit year by proximity with `referenceDate`:\n *\n * `parse('50', 'yy', new Date(2018, 0, 1)) //=> Sat Jan 01 2050 00:00:00`\n *\n * `parse('75', 'yy', new Date(2018, 0, 1)) //=> Wed Jan 01 1975 00:00:00`\n *\n * while `uu` will just assign the year as is:\n *\n * `parse('50', 'uu', new Date(2018, 0, 1)) //=> Sat Jan 01 0050 00:00:00`\n *\n * `parse('75', 'uu', new Date(2018, 0, 1)) //=> Tue Jan 01 0075 00:00:00`\n *\n * The same difference is true for local and ISO week-numbering years (`Y` and `R`),\n * except local week-numbering years are dependent on `options.weekStartsOn`\n * and `options.firstWeekContainsDate` (compare [setISOWeekYear](https://date-fns.org/docs/setISOWeekYear)\n * and [setWeekYear](https://date-fns.org/docs/setWeekYear)).\n *\n * 5. These patterns are not in the Unicode Technical Standard #35:\n * - `i`: ISO day of week\n * - `I`: ISO week of year\n * - `R`: ISO week-numbering year\n * - `o`: ordinal number modifier\n * - `P`: long localized date\n * - `p`: long localized time\n *\n * 6. `YY` and `YYYY` tokens represent week-numbering years but they are often confused with years.\n * You should enable `options.useAdditionalWeekYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * 7. `D` and `DD` tokens represent days of the year but they are often confused with days of the month.\n * You should enable `options.useAdditionalDayOfYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * 8. `P+` tokens do not have a defined priority since they are merely aliases to other tokens based\n * on the given locale.\n *\n * using `en-US` locale: `P` => `MM/dd/yyyy`\n * using `en-US` locale: `p` => `hh:mm a`\n * using `pt-BR` locale: `P` => `dd/MM/yyyy`\n * using `pt-BR` locale: `p` => `HH:mm`\n *\n * Values will be assigned to the date in the descending order of its unit's priority.\n * Units of an equal priority overwrite each other in the order of appearance.\n *\n * If no values of higher priority are parsed (e.g. when parsing string 'January 1st' without a year),\n * the values will be taken from 3rd argument `referenceDate` which works as a context of parsing.\n *\n * `referenceDate` must be passed for correct work of the function.\n * If you're not sure which `referenceDate` to supply, create a new instance of Date:\n * `parse('02/11/2014', 'MM/dd/yyyy', new Date())`\n * In this case parsing will be done in the context of the current date.\n * If `referenceDate` is `Invalid Date` or a value not convertible to valid `Date`,\n * then `Invalid Date` will be returned.\n *\n * The result may vary by locale.\n *\n * If `formatString` matches with `dateString` but does not provides tokens, `referenceDate` will be returned.\n *\n * If parsing failed, `Invalid Date` will be returned.\n * Invalid Date is a Date, whose time value is NaN.\n * Time value of Date: http://es5.github.io/#x15.9.1.1\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param dateStr - The string to parse\n * @param formatStr - The string of tokens\n * @param referenceDate - defines values missing from the parsed dateString\n * @param options - An object with options.\n * see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * @returns The parsed date\n *\n * @throws `options.locale` must contain `match` property\n * @throws use `yyyy` instead of `YYYY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws use `yy` instead of `YY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws use `d` instead of `D` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws use `dd` instead of `DD` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws format string contains an unescaped latin alphabet character\n *\n * @example\n * // Parse 11 February 2014 from middle-endian format:\n * var result = parse('02/11/2014', 'MM/dd/yyyy', new Date())\n * //=> Tue Feb 11 2014 00:00:00\n *\n * @example\n * // Parse 28th of February in Esperanto locale in the context of 2010 year:\n * import eo from 'date-fns/locale/eo'\n * var result = parse('28-a de februaro', \"do 'de' MMMM\", new Date(2010, 0, 1), {\n * locale: eo\n * })\n * //=> Sun Feb 28 2010 00:00:00\n */\nexport function parse(dateStr, formatStr, referenceDate, options) {\n const invalidDate = () => constructFrom(options?.in || referenceDate, NaN);\n const defaultOptions = getDefaultOptions();\n const locale = options?.locale ?? defaultOptions.locale ?? defaultLocale;\n\n const firstWeekContainsDate =\n options?.firstWeekContainsDate ??\n options?.locale?.options?.firstWeekContainsDate ??\n defaultOptions.firstWeekContainsDate ??\n defaultOptions.locale?.options?.firstWeekContainsDate ??\n 1;\n\n const weekStartsOn =\n options?.weekStartsOn ??\n options?.locale?.options?.weekStartsOn ??\n defaultOptions.weekStartsOn ??\n defaultOptions.locale?.options?.weekStartsOn ??\n 0;\n\n if (!formatStr)\n return dateStr ? invalidDate() : toDate(referenceDate, options?.in);\n\n const subFnOptions = {\n firstWeekContainsDate,\n weekStartsOn,\n locale,\n };\n\n // If timezone isn't specified, it will try to use the context or\n // the reference date and fallback to the system time zone.\n const setters = [new DateTimezoneSetter(options?.in, referenceDate)];\n\n const tokens = formatStr\n .match(longFormattingTokensRegExp)\n .map((substring) => {\n const firstCharacter = substring[0];\n if (firstCharacter in longFormatters) {\n const longFormatter = longFormatters[firstCharacter];\n return longFormatter(substring, locale.formatLong);\n }\n return substring;\n })\n .join(\"\")\n .match(formattingTokensRegExp);\n\n const usedTokens = [];\n\n for (let token of tokens) {\n if (\n !options?.useAdditionalWeekYearTokens &&\n isProtectedWeekYearToken(token)\n ) {\n warnOrThrowProtectedError(token, formatStr, dateStr);\n }\n if (\n !options?.useAdditionalDayOfYearTokens &&\n isProtectedDayOfYearToken(token)\n ) {\n warnOrThrowProtectedError(token, formatStr, dateStr);\n }\n\n const firstCharacter = token[0];\n const parser = parsers[firstCharacter];\n if (parser) {\n const { incompatibleTokens } = parser;\n if (Array.isArray(incompatibleTokens)) {\n const incompatibleToken = usedTokens.find(\n (usedToken) =>\n incompatibleTokens.includes(usedToken.token) ||\n usedToken.token === firstCharacter,\n );\n if (incompatibleToken) {\n throw new RangeError(\n `The format string mustn't contain \\`${incompatibleToken.fullToken}\\` and \\`${token}\\` at the same time`,\n );\n }\n } else if (parser.incompatibleTokens === \"*\" && usedTokens.length > 0) {\n throw new RangeError(\n `The format string mustn't contain \\`${token}\\` and any other token at the same time`,\n );\n }\n\n usedTokens.push({ token: firstCharacter, fullToken: token });\n\n const parseResult = parser.run(\n dateStr,\n token,\n locale.match,\n subFnOptions,\n );\n\n if (!parseResult) {\n return invalidDate();\n }\n\n setters.push(parseResult.setter);\n\n dateStr = parseResult.rest;\n } else {\n if (firstCharacter.match(unescapedLatinCharacterRegExp)) {\n throw new RangeError(\n \"Format string contains an unescaped latin alphabet character `\" +\n firstCharacter +\n \"`\",\n );\n }\n\n // Replace two single quote characters with one single quote character\n if (token === \"''\") {\n token = \"'\";\n } else if (firstCharacter === \"'\") {\n token = cleanEscapedString(token);\n }\n\n // Cut token from string, or, if string doesn't match the token, return Invalid Date\n if (dateStr.indexOf(token) === 0) {\n dateStr = dateStr.slice(token.length);\n } else {\n return invalidDate();\n }\n }\n }\n\n // Check if the remaining input contains something other than whitespace\n if (dateStr.length > 0 && notWhitespaceRegExp.test(dateStr)) {\n return invalidDate();\n }\n\n const uniquePrioritySetters = setters\n .map((setter) => setter.priority)\n .sort((a, b) => b - a)\n .filter((priority, index, array) => array.indexOf(priority) === index)\n .map((priority) =>\n setters\n .filter((setter) => setter.priority === priority)\n .sort((a, b) => b.subPriority - a.subPriority),\n )\n .map((setterArray) => setterArray[0]);\n\n let date = toDate(referenceDate, options?.in);\n\n if (isNaN(+date)) return invalidDate();\n\n const flags = {};\n for (const setter of uniquePrioritySetters) {\n if (!setter.validate(date, subFnOptions)) {\n return invalidDate();\n }\n\n const result = setter.set(date, flags, subFnOptions);\n // Result is tuple (date, flags)\n if (Array.isArray(result)) {\n date = result[0];\n Object.assign(flags, result[1]);\n // Result is date\n } else {\n date = result;\n }\n }\n\n return date;\n}\n\nfunction cleanEscapedString(input) {\n return input.match(escapedStringRegExp)[1].replace(doubleQuoteRegExp, \"'\");\n}\n\n// Fallback for modularized imports:\nexport default parse;\n","import { createContext, use } from \"react\";\nimport type { SubscriptionsApi } from \"./subscriptions-api\";\n\nconst SubscriptionsApiContext = createContext<SubscriptionsApi | null>(null);\n\nexport const SubscriptionsApiProvider = SubscriptionsApiContext.Provider;\n\nexport function useSubscriptionsApi(): SubscriptionsApi {\n const api = use(SubscriptionsApiContext);\n if (!api) {\n throw new Error(\n \"useSubscriptionsApi must be used within a SubscriptionsCoreProvider\",\n );\n }\n return api;\n}\n","import type { JSX } from \"react\";\nimport type { SubscriptionsApi } from \"./subscriptions-api\";\nimport { SubscriptionsApiProvider } from \"./subscriptions-api-context\";\n\nexport interface SubscriptionsCoreProviderProps {\n api: SubscriptionsApi;\n children: React.ReactNode;\n}\n\nexport function SubscriptionsCoreProvider({\n api,\n children,\n}: SubscriptionsCoreProviderProps): JSX.Element {\n return (\n <SubscriptionsApiProvider value={api}>{children}</SubscriptionsApiProvider>\n );\n}\n","import type { subscriptions } from \"./types\";\n\nexport const subscriptionsKeys = {\n all: [\"subscriptions\"] as const,\n lists: [\"subscriptions\", \"list\"] as const,\n list: (params?: subscriptions.FetchSubscriptionsParams) =>\n [...subscriptionsKeys.lists, params] as const,\n infiniteLists: [\"subscriptions\", \"infinite-list\"] as const,\n infiniteList: (\n params: Omit<subscriptions.FetchSubscriptionsParams, \"cursor\" | \"page\">,\n ) => [...subscriptionsKeys.infiniteLists, params] as const,\n detail: (token: string) =>\n [...subscriptionsKeys.all, \"detail\", token] as const,\n failedCycleWaiver: (token: string) =>\n [...subscriptionsKeys.detail(token), \"failed-cycle-waiver\"] as const,\n} as const;\n\nexport const bundlesKeys = {\n all: [\"subscription_bundles\"] as const,\n list: () => [...bundlesKeys.all, \"list\"] as const,\n} as const;\n","import { createContext, use } from \"react\";\nimport type { BundlesApi } from \"./bundles-api\";\n\nconst BundlesApiContext = createContext<BundlesApi | null>(null);\n\nexport const BundlesApiProvider = BundlesApiContext.Provider;\n\nexport function useBundlesApi(): BundlesApi {\n const api = use(BundlesApiContext);\n if (!api) {\n throw new Error(\"useBundlesApi must be used within a BundlesCoreProvider\");\n }\n return api;\n}\n","import type { JSX } from \"react\";\nimport type { BundlesApi } from \"./bundles-api\";\nimport { BundlesApiProvider } from \"./bundles-api-context\";\n\nexport interface BundlesCoreProviderProps {\n api: BundlesApi;\n children: React.ReactNode;\n}\n\nexport function BundlesCoreProvider({\n api,\n children,\n}: BundlesCoreProviderProps): JSX.Element {\n return <BundlesApiProvider value={api}>{children}</BundlesApiProvider>;\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useSubscriptions(\n params: subscriptions.FetchSubscriptionsParams,\n options?: { enabled?: boolean },\n) {\n const api = useSubscriptionsApi();\n return useQuery({\n queryKey: subscriptionsKeys.list(params),\n queryFn: () => api.fetchCustomerSubscriptions(params),\n enabled: options?.enabled ?? !!params.customerId,\n });\n}\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useInfiniteSubscriptions(\n params: Omit<subscriptions.FetchSubscriptionsParams, \"cursor\" | \"page\">,\n options?: { enabled?: boolean },\n) {\n const api = useSubscriptionsApi();\n return useInfiniteQuery({\n queryKey: subscriptionsKeys.infiniteList(params),\n queryFn: ({ pageParam }) =>\n api.fetchCustomerSubscriptions({\n ...params,\n cursor: pageParam,\n limit: params.limit ?? params.perPage,\n }),\n getNextPageParam: (lastPage) =>\n lastPage.meta?.pagination?.next_cursor ?? undefined,\n initialPageParam: undefined as string | undefined,\n enabled: options?.enabled ?? !!params.customerId,\n });\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useSubscription(\n token: string,\n options?: { enabled?: boolean },\n) {\n const api = useSubscriptionsApi();\n return useQuery({\n queryKey: subscriptionsKeys.detail(token),\n queryFn: () => api.fetchSubscription(token),\n enabled: (options?.enabled ?? true) && !!token,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function usePauseSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: {\n subscriptionToken: string;\n pauseParams: subscriptions.PauseSubscriptionParams;\n }) => api.pauseSubscription(params.subscriptionToken, params.pauseParams),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useResumeSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: {\n subscriptionToken: string;\n resumeParams: subscriptions.ResumeSubscriptionParams;\n }) => api.resumeSubscription(params.subscriptionToken, params.resumeParams),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useSkipSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: {\n subscriptionToken: string;\n skipParams: subscriptions.SkipSubscriptionParams;\n }) => api.skipSubscription(params.subscriptionToken, params.skipParams),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useCancelSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: { subscriptionToken: string; customerId?: number }) =>\n api.cancelSubscription(params.subscriptionToken, params.customerId),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useReactivateSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: {\n subscriptionToken: string;\n reactivateParams: subscriptions.ReactivateSubscriptionParams;\n }) =>\n api.reactivateSubscription(\n params.subscriptionToken,\n params.reactivateParams,\n ),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: (error: unknown) => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onError?.(error);\n },\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\n// Wraps the explicit retry endpoint. The customer-facing UI calls this\n// after a successful payment-method update so the retry is opt-in\n// (vs. a side-effect of the update). See SubscriptionsApi#retrySubscription.\nexport function useRetrySubscription(options?: {\n onSuccess?: (variables: { subscriptionToken: string }) => void;\n onError?: (error: unknown, variables: { subscriptionToken: string }) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: { subscriptionToken: string }) =>\n api.retrySubscription(params.subscriptionToken),\n onSuccess: (_subscription, variables) => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(variables.subscriptionToken),\n });\n options?.onSuccess?.(variables);\n },\n onError: (error, variables) => options?.onError?.(error, variables),\n });\n}\n","// Decision logic for polling a past_due subscription after a payment retry is\n// queued. The retry charges asynchronously and returns with the sub still\n// past_due (last_failed_at reset), so the outcome is read from later polls:\n//\n// succeeded → status became \"active\" (the charge went through). Success is\n// specifically the past_due → active transition.\n// failed → still past_due AND last_failed_at advanced past the baseline\n// captured when polling started (a fresh decline, not a stale\n// read of the prior failure)\n// ended → some other terminal status (e.g. a concurrent cancel/pause):\n// stop polling, but don't claim the charge succeeded\n// pending → none of the above yet; keep polling\n//\n// Kept pure (no React) so it's unit-testable without a DOM/query harness.\nexport type RetryOutcome = \"pending\" | \"succeeded\" | \"failed\" | \"ended\";\n\nexport function resolveRetryOutcome(params: {\n status: string;\n lastFailedAt: string | null;\n baselineLastFailedAt: string | null;\n}): RetryOutcome {\n if (params.status === \"active\") return \"succeeded\";\n if (params.status !== \"past_due\") return \"ended\";\n if (\n params.lastFailedAt != null &&\n params.lastFailedAt !== params.baselineLastFailedAt\n ) {\n return \"failed\";\n }\n return \"pending\";\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\nimport { resolveRetryOutcome } from \"../utils/retry-outcome\";\n\n// A payment retry on a past_due subscription does not charge synchronously:\n// the retry endpoint resets the dunning state, enqueues an immediate billing\n// attempt, and returns with the subscription still past_due. The charge runs\n// seconds later, so the outcome can only be observed by polling the\n// subscription after the retry is queued.\n//\n// success → status flips to \"active\"\n// failure → status stays \"past_due\" and last_failed_at is set again\n// (the retry reset last_failed_at first, so a value newer than the\n// baseline captured at start() is this attempt's failure)\nconst POLL_INTERVAL_MS = 2_500;\n// The immediate billing attempt runs within seconds; stop polling well after\n// that so a stuck worker (or a backend where only the slow dunning cron runs)\n// doesn't leave the UI processing forever.\nconst POLL_TIMEOUT_MS = 30_000;\n\ntype RetryPollingAttempt = {\n subscriptionToken: string;\n phase: \"pending\" | \"failed\";\n baselineLastFailedAt: string | null;\n};\n\nexport function createRetryPollingAttempt(\n subscriptionToken: string,\n baselineLastFailedAt: string | null,\n): RetryPollingAttempt {\n return {\n subscriptionToken,\n phase: \"pending\",\n baselineLastFailedAt,\n };\n}\n\nexport function retryPollingAttemptForToken(\n attempt: RetryPollingAttempt | null,\n subscriptionToken: string,\n): RetryPollingAttempt | null {\n return attempt?.subscriptionToken === subscriptionToken ? attempt : null;\n}\n\ntype Args = {\n subscriptionToken: string;\n // Host-agnostic outcome callbacks — this package has no toast/UI layer, so\n // the consumer surfaces feedback (toasts, etc.) however it likes.\n onSucceeded?: () => void;\n onFailed?: () => void;\n onTimedOut?: () => void;\n};\n\ntype RetryStatusPolling = {\n // Begin polling for the outcome. Call after the retry has been queued.\n start: () => void;\n // The charge outcome is still being polled.\n isProcessing: boolean;\n // The most recent retry was declined.\n hasFailed: boolean;\n};\n\nexport function useRetryStatusPolling({\n subscriptionToken,\n onSucceeded,\n onFailed,\n onTimedOut,\n}: Args): RetryStatusPolling {\n const api = useSubscriptionsApi();\n const [attempt, setAttempt] = useState<RetryPollingAttempt | null>(null);\n const attemptRef = useRef<RetryPollingAttempt | null>(null);\n const currentTokenRef = useRef(subscriptionToken);\n currentTokenRef.current = subscriptionToken;\n const currentAttempt = retryPollingAttemptForToken(\n attempt,\n subscriptionToken,\n );\n\n useEffect(() => {\n if (\n attemptRef.current !== null &&\n attemptRef.current.subscriptionToken !== subscriptionToken\n ) {\n attemptRef.current = null;\n setAttempt(null);\n }\n }, [subscriptionToken]);\n\n // Latest-ref the outcome callbacks. Consumers pass inline arrows that change\n // identity every render; keeping them out of the effect deps means the\n // polling/timeout effects re-run only on real state changes (phase / polled\n // status), not on unrelated parent re-renders — so the 30s timer isn't\n // silently reset and the outcome can't double-fire.\n const callbacks = useRef({ onSucceeded, onFailed, onTimedOut });\n useEffect(() => {\n callbacks.current = { onSucceeded, onFailed, onTimedOut };\n }, [onSucceeded, onFailed, onTimedOut]);\n\n const { data: polled } = useQuery({\n queryKey: subscriptionsKeys.detail(subscriptionToken),\n queryFn: () => api.fetchSubscription(subscriptionToken),\n enabled: currentAttempt?.phase === \"pending\",\n refetchInterval:\n currentAttempt?.phase === \"pending\" ? POLL_INTERVAL_MS : false,\n refetchIntervalInBackground: true,\n });\n\n const polledStatus = polled?.subscription.status;\n const polledLastFailedAt = polled?.subscription.last_failed_at;\n const latestPolledRef = useRef({\n subscriptionToken,\n lastFailedAt: polledLastFailedAt ?? null,\n });\n latestPolledRef.current = {\n subscriptionToken,\n lastFailedAt: polledLastFailedAt ?? null,\n };\n\n useEffect(() => {\n if (currentAttempt?.phase !== \"pending\" || polledStatus === undefined) {\n return;\n }\n\n const outcome = resolveRetryOutcome({\n status: polledStatus,\n lastFailedAt: polledLastFailedAt ?? null,\n baselineLastFailedAt: currentAttempt.baselineLastFailedAt,\n });\n if (currentTokenRef.current !== currentAttempt.subscriptionToken) return;\n\n if (outcome === \"succeeded\") {\n attemptRef.current = null;\n setAttempt(null);\n callbacks.current.onSucceeded?.();\n } else if (outcome === \"failed\") {\n const failedAttempt: RetryPollingAttempt = {\n ...currentAttempt,\n phase: \"failed\",\n };\n attemptRef.current = failedAttempt;\n setAttempt(failedAttempt);\n callbacks.current.onFailed?.();\n } else if (outcome === \"ended\") {\n // A concurrent action moved the sub to another terminal state — stop\n // polling without reporting a success or failure.\n attemptRef.current = null;\n setAttempt(null);\n }\n }, [currentAttempt, polledStatus, polledLastFailedAt]);\n\n useEffect(() => {\n if (currentAttempt?.phase !== \"pending\") return;\n const attemptToken = currentAttempt.subscriptionToken;\n const timeout = setTimeout(() => {\n const activeAttempt = retryPollingAttemptForToken(\n attemptRef.current,\n currentTokenRef.current,\n );\n if (\n activeAttempt?.subscriptionToken !== attemptToken ||\n activeAttempt.phase !== \"pending\"\n ) {\n return;\n }\n\n attemptRef.current = null;\n setAttempt(null);\n callbacks.current.onTimedOut?.();\n }, POLL_TIMEOUT_MS);\n return () => clearTimeout(timeout);\n }, [currentAttempt]);\n\n return {\n start: () => {\n const currentToken = currentTokenRef.current;\n const latestPolled = latestPolledRef.current;\n const nextAttempt = createRetryPollingAttempt(\n currentToken,\n latestPolled.subscriptionToken === currentToken\n ? latestPolled.lastFailedAt\n : null,\n );\n attemptRef.current = nextAttempt;\n setAttempt(nextAttempt);\n },\n isProcessing: currentAttempt?.phase === \"pending\",\n hasFailed: currentAttempt?.phase === \"failed\",\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nfunction hasNumericStatus(error: unknown): error is { status: number } {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof error.status === \"number\"\n );\n}\n\nexport function shouldRetryFailedCycleWaiverPreview(\n failureCount: number,\n error: unknown,\n): boolean {\n if (hasNumericStatus(error) && error.status >= 400 && error.status < 500) {\n return false;\n }\n\n return failureCount < 1;\n}\n\nexport function useFailedCycleWaiverPreview(\n subscriptionToken: string,\n options: { enabled: boolean },\n) {\n const api = useSubscriptionsApi();\n\n return useQuery({\n queryKey: subscriptionsKeys.failedCycleWaiver(subscriptionToken),\n queryFn: () => api.fetchFailedCycleWaiverPreview(subscriptionToken),\n enabled: options.enabled && subscriptionToken.length > 0,\n retry: shouldRetryFailedCycleWaiverPreview,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useWaiveFailedCycle(options?: {\n onSuccess?: (variables: { subscriptionToken: string }) => void;\n onError?: (error: unknown, variables: { subscriptionToken: string }) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: { subscriptionToken: string }) =>\n api.waiveFailedCycle(params.subscriptionToken),\n onSuccess: (_subscription, variables) => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(variables.subscriptionToken),\n });\n options?.onSuccess?.(variables);\n },\n onError: (error, variables) => options?.onError?.(error, variables),\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport type UpdateSubscriptionInfoVariables = {\n subscriptionToken: string;\n body: Partial<\n Pick<\n subscriptions.UpdateSubscriptionInfoBody,\n | \"payment_method_id\"\n | \"quantity\"\n | \"address_id\"\n | \"next_bill_date\"\n | \"auto_apply_points\"\n >\n >;\n};\n\nexport function useUpdateSubscriptionInfo(options?: {\n onSuccess?: (\n variables: UpdateSubscriptionInfoVariables,\n ) => void | Promise<void>;\n onError?: (\n error: unknown,\n variables: UpdateSubscriptionInfoVariables,\n ) => void;\n // Opt out of the hook's auto-invalidation when the consumer needs\n // to chain another mutation (e.g. payment-method update → retry).\n // Without this, the auto-invalidate fires immediately on update\n // success and the chained mutation triggers a second refetch later\n // — two round-trips for one orchestrated flow. Consumers that opt\n // out are responsible for calling invalidateQueries themselves\n // after their orchestration completes.\n skipAutoInvalidate?: boolean;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: UpdateSubscriptionInfoVariables) =>\n api.updateSubscriptionInfo(params.subscriptionToken, params.body),\n onSuccess: (_subscription, variables) => {\n if (!options?.skipAutoInvalidate) {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(variables.subscriptionToken),\n });\n }\n return options?.onSuccess?.(variables);\n },\n onError: (error, variables) => options?.onError?.(error, variables),\n });\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { bundlesKeys } from \"../query-keys\";\nimport { useBundlesApi } from \"../bundles-api-context\";\n\nexport function useBundles(options?: { enabled?: boolean }) {\n const api = useBundlesApi();\n return useQuery({\n queryKey: bundlesKeys.list(),\n queryFn: () => api.fetchBundles(),\n enabled: options?.enabled ?? true,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { bundlesKeys, subscriptionsKeys } from \"../query-keys\";\nimport { useBundlesApi } from \"../bundles-api-context\";\n\nexport function useCreateBundle(options?: {\n onSuccess?: (bundle: subscriptions.Bundle) => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useBundlesApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: subscriptions.CreateBundleParams) =>\n api.createBundle(params),\n onSuccess: (bundle) => {\n queryClient.invalidateQueries({ queryKey: bundlesKeys.all });\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.(bundle);\n },\n onError: options?.onError,\n });\n}\n","interface SubscriptionPriceItem {\n allow_subscription: boolean;\n subscription_interval: number | null;\n subscription_price_in_currency: string | null;\n}\n\n/** Minimal shape needed to derive a subscription's displayed pricing. */\ninterface SubscriptionPricingInput {\n price: number;\n /**\n * Next-renewal first-class discount total (per unit). Already includes the\n * legacy renewal callback amount and the price cap, computed server-side —\n * the client cannot derive it.\n */\n renewal_discount_total?: number | null;\n subscription_discounts?:\n | { discount: { code: string }; removed_at: string | null }[]\n | null;\n}\n\ninterface ScheduledProcessingInput {\n status: string;\n nextRetryAt: string | null;\n}\n\n/** Per-unit pricing lines for a subscription detail summary. */\nexport interface SubscriptionPricingBreakdown {\n /** Recurring price shown on the subtotal line (per unit). */\n subtotalUnit: number;\n /** First-class attached renewal discount per unit; 0 if none. */\n attachedDiscountUnit: number;\n /** Active attachment's code, or null (e.g. a callback-only amount). */\n attachedDiscountCode: string | null;\n /** Net price charged next renewal (price − attached, floored at 0), per unit. */\n totalUnit: number;\n /** True when a discount line should render. */\n hasDiscount: boolean;\n}\n\n/**\n * Derive the per-unit pricing summary for a subscription detail view.\n *\n * Subtotal is `price`; the total subtracts the attached discount, matching\n * how the renewal order is billed. `original_price` is the catalog price\n * from when the subscription was created, not a discount on the next order,\n * so it stays out. Callers multiply the per-unit values by the quantity.\n */\nexport function computeSubscriptionPricing(\n subscription: SubscriptionPricingInput,\n): SubscriptionPricingBreakdown {\n const price = subscription.price;\n const attachedDiscountUnit = Math.max(\n subscription.renewal_discount_total ?? 0,\n 0,\n );\n const activeAttachment =\n subscription.subscription_discounts?.find((d) => d.removed_at == null) ??\n null;\n const attachedDiscountCode =\n attachedDiscountUnit > 0 ? (activeAttachment?.discount.code ?? null) : null;\n\n return {\n subtotalUnit: price,\n attachedDiscountUnit,\n attachedDiscountCode,\n totalUnit: Math.max(price - attachedDiscountUnit, 0),\n hasDiscount: attachedDiscountUnit > 0,\n };\n}\n\nexport function getSubscriptionPrice(\n item: SubscriptionPriceItem,\n): string | null {\n if (!item.allow_subscription) return null;\n const intervalText =\n item.subscription_interval === 1\n ? \"month\"\n : `${item.subscription_interval} mo.`;\n return `${item.subscription_price_in_currency}/${intervalText}`;\n}\n\nexport function canResumeScheduledProcessing(\n subscription: ScheduledProcessingInput,\n): boolean {\n return subscription.status === \"past_due\" && subscription.nextRetryAt == null;\n}\n\nexport function formatSubscriptionFrequency(frequency: string): string {\n if (frequency === \"day\") return \"Daily\";\n if (frequency === \"week\") return \"Weekly\";\n if (frequency === \"month\") return \"Monthly\";\n if (frequency === \"year\") return \"Yearly\";\n return frequency;\n}\n\nexport function calculateResumeDate(\n billingInterval: number,\n billingIntervalUnit: string,\n orderCount: number,\n fromDate?: string | Date | null,\n): Date {\n let startDate: Date;\n\n if (fromDate) {\n if (typeof fromDate === \"string\") {\n startDate = new Date(\n fromDate + (fromDate.includes(\"T\") ? \"\" : \"T12:00:00.000Z\"),\n );\n } else {\n startDate = new Date(\n Date.UTC(\n fromDate.getUTCFullYear(),\n fromDate.getUTCMonth(),\n fromDate.getUTCDate(),\n 12,\n 0,\n 0,\n 0,\n ),\n );\n }\n } else {\n const now = new Date();\n startDate = new Date(\n Date.UTC(\n now.getUTCFullYear(),\n now.getUTCMonth(),\n now.getUTCDate(),\n 12,\n 0,\n 0,\n 0,\n ),\n );\n }\n\n const baseDate = new Date(startDate.getTime());\n const totalIntervals = billingInterval * orderCount;\n\n switch (billingIntervalUnit.toLowerCase()) {\n case \"day\":\n baseDate.setUTCDate(baseDate.getUTCDate() + totalIntervals);\n break;\n case \"week\":\n baseDate.setUTCDate(baseDate.getUTCDate() + totalIntervals * 7);\n break;\n case \"month\": {\n const currentMonth = baseDate.getUTCMonth();\n const currentDay = baseDate.getUTCDate();\n baseDate.setUTCMonth(currentMonth + totalIntervals);\n if (baseDate.getUTCDate() !== currentDay) {\n baseDate.setUTCDate(0);\n }\n break;\n }\n case \"year\":\n baseDate.setUTCFullYear(baseDate.getUTCFullYear() + totalIntervals);\n break;\n default: {\n const defaultMonth = baseDate.getUTCMonth();\n const defaultDay = baseDate.getUTCDate();\n baseDate.setUTCMonth(defaultMonth + totalIntervals);\n if (baseDate.getUTCDate() !== defaultDay) {\n baseDate.setUTCDate(0);\n }\n }\n }\n\n return baseDate;\n}\n\nexport function isYearlyBillingCycle(\n billingInterval: number = 1,\n billingIntervalUnit: string = \"month\",\n): boolean {\n const step = Math.max(1, billingInterval);\n switch (billingIntervalUnit.toLowerCase()) {\n case \"year\":\n return true;\n case \"month\":\n return step >= 12;\n case \"week\":\n return step >= 52;\n case \"day\":\n return step >= 365;\n default:\n return false;\n }\n}\n\n/**\n * Latest date a subscription's bill date may be edited to: 2 years out for\n * yearly plans, 12 months out for everything else.\n */\nexport function getMaxEditableBillDate(\n billingInterval: number = 1,\n billingIntervalUnit: string = \"month\",\n from: Date = new Date(),\n): Date {\n const maxDate = new Date(from.getTime());\n maxDate.setHours(0, 0, 0, 0);\n const day = maxDate.getDate();\n if (isYearlyBillingCycle(billingInterval, billingIntervalUnit)) {\n maxDate.setFullYear(maxDate.getFullYear() + 2);\n } else {\n maxDate.setMonth(maxDate.getMonth() + 12);\n }\n // The native setters overflow when the target month lacks the source day\n // (Feb 29 → Mar 1); roll back to the end of the intended month.\n if (maxDate.getDate() !== day) {\n maxDate.setDate(0);\n }\n return maxDate;\n}\n\nexport interface BillingCadence {\n billingInterval?: number;\n billingIntervalUnit?: string;\n}\n\n/**\n * Latest date a whole bundle's bill date may be edited to. Every member moves\n * to one shared date, so the strictest member binds: a bundle holding one\n * monthly plan is capped at 12 months even if its other members are yearly.\n *\n * An empty list falls back to the 12-month cap, which is also what a member of\n * unknown cadence resolves to via getMaxEditableBillDate's own default.\n */\nexport function getMaxEditableBillDateForBundle(\n members: BillingCadence[],\n from: Date = new Date(),\n): Date {\n const caps = members.map((member) =>\n getMaxEditableBillDate(\n member.billingInterval,\n member.billingIntervalUnit,\n from,\n ),\n );\n const [first, ...rest] = caps;\n if (!first) return getMaxEditableBillDate(1, \"month\", from);\n\n return rest.reduce(\n (strictest, current) => (current < strictest ? current : strictest),\n first,\n );\n}\n\nexport function calculateNextBillDate(\n billingInterval: number = 1,\n billingIntervalUnit: string = \"month\",\n): string {\n const now = new Date();\n const nextBillDate = new Date(now);\n\n switch (billingIntervalUnit.toLowerCase()) {\n case \"day\":\n nextBillDate.setDate(now.getDate() + billingInterval);\n break;\n case \"week\":\n nextBillDate.setDate(now.getDate() + billingInterval * 7);\n break;\n case \"month\":\n nextBillDate.setMonth(now.getMonth() + billingInterval);\n break;\n case \"year\":\n nextBillDate.setFullYear(now.getFullYear() + billingInterval);\n break;\n default:\n nextBillDate.setMonth(now.getMonth() + billingInterval);\n }\n\n return nextBillDate.toISOString().split(\"T\")[0] || \"\";\n}\n\n/** Longest pause the dialogs have ever offered, before the cap narrows it. */\nconst MAX_SKIPPABLE_ORDERS = 99;\n\n/**\n * How many upcoming orders a pause may skip: the largest count whose resume\n * date still lands inside the bill-date cap.\n *\n * Pausing for a number of orders sets a bill date like any other edit, so the\n * API caps the date it derives from that count, 2 years out for a yearly cadence\n * and 12 months for everything else, and rejects the request naming\n * number_of_orders. Offering counts past that offers a pause the API refuses.\n *\n * Returns 0 when even a single skip overshoots, which happens on a subscription\n * whose next bill date already sits near the cap. Callers should read that as\n * \"pausing by order count is unavailable here\" and leave the indefinite pause.\n *\n * The two ends deliberately measure from different places: the resume date\n * counts forward from the current bill date, the cap counts forward from today.\n * The API stays the backstop, so the exact boundary count depends on its\n * resume-date arithmetic agreeing with calculateResumeDate.\n */\nexport function getMaxSkippableOrders(\n billingInterval: number = 1,\n billingIntervalUnit: string = \"month\",\n currentNextBillDate?: string | Date | null,\n from: Date = new Date(),\n): number {\n const cap = getMaxEditableBillDate(\n billingInterval,\n billingIntervalUnit,\n from,\n );\n let allowed = 0;\n\n for (let count = 1; count <= MAX_SKIPPABLE_ORDERS; count += 1) {\n // `from` stands in for the bill date when the subscription has none, so the\n // resume date and the cap are measured from the same day. Passing\n // currentNextBillDate straight through let calculateResumeDate fall back to\n // its own new Date() in that branch, which read the wall clock while the cap\n // read the injected date — the two drifted apart and the boundary answer\n // changed from one day to the next.\n const resume = calculateResumeDate(\n billingInterval,\n billingIntervalUnit,\n count,\n currentNextBillDate ?? from,\n );\n // calculateResumeDate anchors at noon UTC, so its UTC fields carry the\n // calendar date it means, while the cap is a local-midnight date. Rebuild\n // the resume date locally so the comparison cannot slip a day at large\n // offsets, the same reason the bill-date pickers read both ends locally.\n const resumeDate = new Date(\n resume.getUTCFullYear(),\n resume.getUTCMonth(),\n resume.getUTCDate(),\n );\n if (resumeDate > cap) break;\n allowed = count;\n }\n\n return allowed;\n}\n\nexport function formatDate(\n dateString: string,\n locale: string = \"en-US\",\n): string {\n if (!dateString) return \"\";\n\n const datePortion = dateString.split(\"T\")[0] ?? dateString;\n const parts = datePortion.split(\"-\");\n if (parts.length !== 3) return \"\";\n\n const [year, month, day] = parts.map(Number);\n if (!year || !month || !day) return \"\";\n const date = new Date(year, month - 1, day);\n\n try {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n } catch {\n // Intl throws on invalid locale values — fall back to en-US rather\n // than crashing the component.\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n }\n}\n\nexport function formatOptionalDate(\n dateString: string | null | undefined,\n locale: string = \"en-US\",\n fallback: string = \"—\",\n): string {\n if (!dateString) return fallback;\n\n const datePortion = dateString.split(\"T\")[0];\n if (!datePortion) return fallback;\n\n const parts = datePortion.split(\"-\").map(Number);\n if (parts.length !== 3) return fallback;\n const [year, month, day] = parts;\n if (year == null || month == null || day == null) return fallback;\n\n const date = new Date(year, month - 1, day);\n const isExactDate =\n date.getFullYear() === year &&\n date.getMonth() === month - 1 &&\n date.getDate() === day;\n if (!isExactDate) return fallback;\n\n try {\n return new Intl.DateTimeFormat(locale.replaceAll(\"_\", \"-\"), {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n } catch {\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n }\n}\n\n// Formats the time-of-day portion of an ISO timestamp in the given IANA\n// timezone. Returns \"\" when no timezone is supplied — the next-order display\n// intentionally omits the time line in that case (the BFF can't promise the\n// stored time-of-day is meaningful without a zone to interpret it in).\nexport function formatTime(\n dateString: string | null | undefined,\n timezone: string | null | undefined,\n locale: string = \"en-US\",\n): string {\n if (!dateString || !timezone) return \"\";\n const date = new Date(dateString);\n if (Number.isNaN(date.getTime())) return \"\";\n try {\n return new Intl.DateTimeFormat(locale, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n timeZone: timezone,\n }).format(date);\n } catch {\n // Intl throws on unknown IANA identifiers — fall back to no time rather\n // than crashing the row.\n return \"\";\n }\n}\n\nexport function getNextBillDisplay(\n nextBillDate: string | null | undefined,\n displayStatus: string,\n labels: {\n cancelled: string;\n completed: string;\n paused: string;\n notAvailable: string;\n } = {\n cancelled: \"Cancelled\",\n completed: \"Completed\",\n paused: \"Paused\",\n notAvailable: \"N/A\",\n },\n locale: string = \"en-US\",\n): string {\n if (displayStatus === \"completed\") return labels.completed;\n if (displayStatus === \"cancelled\") return labels.cancelled;\n if (nextBillDate) return formatDate(nextBillDate, locale);\n if (displayStatus === \"paused\") return labels.paused;\n return labels.notAvailable;\n}\n\nexport function calculateSubscriptionPrice(\n totalPrice: number,\n subscribeAndSave: string | null | undefined,\n quantity: number,\n): string {\n if (!subscribeAndSave) return totalPrice.toFixed(2);\n\n const unitDiscountAmount = parseFloat(subscribeAndSave);\n if (isNaN(unitDiscountAmount)) return totalPrice.toFixed(2);\n\n const subscriptionAmount = totalPrice - unitDiscountAmount * quantity;\n return subscriptionAmount.toFixed(2);\n}\n","export type SubscriptionAction =\n | \"skip_next_order\"\n | \"undo_skip\"\n | \"edit_bill_date\"\n | \"pause_subscription\"\n | \"resume_subscription\"\n | \"cancel_subscription\"\n | \"reactivate_subscription\"\n | \"retry_payment\"\n | \"change_payment_method\";\n\nexport interface SubscriptionActionPolicyInput {\n status: string;\n billingCycleLimitReached?: boolean;\n nextRetryAt?: string | null;\n nextBillDate: string | null;\n allowSkipping: boolean | null;\n maxSkips: number | null;\n skippedCount: number | null;\n hasPendingSkip: boolean;\n canUndoSkip?: boolean;\n canChangePaymentMethod: boolean;\n canWaiveFailedCycle?: boolean;\n isWaiverPreviewLoading?: boolean;\n}\n\nexport interface SubscriptionRecoveryActions {\n state: \"exhausted\" | \"scheduled\";\n primary: \"retry_payment\" | null;\n secondary: \"change_payment_method\" | null;\n tertiary: \"waive_failed_cycle\" | null;\n isCheckingWaiver: boolean;\n}\n\nexport interface SubscriptionActionPolicy {\n primary: \"resume_subscription\" | \"reactivate_subscription\" | null;\n order: SubscriptionAction[];\n menu: SubscriptionAction[];\n recovery: SubscriptionRecoveryActions | null;\n}\n\ninterface SubscriptionSkipInput {\n skipped_date: string;\n unskipped_at?: string | null;\n}\n\n/**\n * The one rule for a completed subscription: its current plan's\n * billing-cycle limit is reached. Every \"completed\" presentation and\n * gate reads this, so a new terminal condition lands here once.\n */\nexport function isSubscriptionCompleted(\n subscription: { billing_cycle_limit_reached?: boolean } | null | undefined,\n): boolean {\n return subscription?.billing_cycle_limit_reached === true;\n}\n\nexport function getSubscriptionDisplayStatus(subscription: {\n status: string;\n billing_cycle_limit_reached?: boolean;\n}): string {\n return isSubscriptionCompleted(subscription)\n ? \"completed\"\n : subscription.status;\n}\n\nexport function hasPendingSubscriptionSkip(\n skips: readonly SubscriptionSkipInput[] | null | undefined,\n today: Date = new Date(),\n): boolean {\n if (!skips?.length) return false;\n\n const todayUtc = Date.UTC(\n today.getUTCFullYear(),\n today.getUTCMonth(),\n today.getUTCDate(),\n );\n\n return skips.some((skip) => {\n if (skip.unskipped_at != null) return false;\n const skippedDate = new Date(`${skip.skipped_date.slice(0, 10)}T00:00:00Z`);\n return (\n !Number.isNaN(skippedDate.getTime()) && skippedDate.getTime() >= todayUtc\n );\n });\n}\n\nexport function getSubscriptionActionPolicy(\n subscription: SubscriptionActionPolicyInput,\n): SubscriptionActionPolicy {\n const status = getSubscriptionDisplayStatus({\n status: subscription.status,\n billing_cycle_limit_reached: subscription.billingCycleLimitReached,\n });\n\n if (status === \"active\") {\n const skipAllowanceAvailable =\n subscription.maxSkips == null ||\n (subscription.skippedCount ?? 0) < subscription.maxSkips;\n const canSkip =\n subscription.allowSkipping === true &&\n subscription.nextBillDate != null &&\n skipAllowanceAvailable;\n const order: SubscriptionAction[] = [];\n\n if (subscription.hasPendingSkip) {\n if (subscription.canUndoSkip) order.push(\"undo_skip\");\n } else if (canSkip) {\n order.push(\"skip_next_order\");\n }\n order.push(\"edit_bill_date\");\n\n return {\n primary: null,\n order,\n menu: [\"pause_subscription\", \"cancel_subscription\"],\n recovery: null,\n };\n }\n\n if (status === \"paused\") {\n return {\n primary: \"resume_subscription\",\n order: [],\n menu: [\"cancel_subscription\"],\n recovery: null,\n };\n }\n\n if (status === \"cancelled\") {\n return {\n primary: \"reactivate_subscription\",\n order: [],\n menu: [],\n recovery: null,\n };\n }\n\n if (status === \"past_due\") {\n const isExhausted = subscription.nextRetryAt == null;\n const secondary = subscription.canChangePaymentMethod\n ? \"change_payment_method\"\n : null;\n\n return {\n primary: null,\n order: [],\n menu: [\"cancel_subscription\"],\n recovery: {\n state: isExhausted ? \"exhausted\" : \"scheduled\",\n primary: isExhausted ? \"retry_payment\" : null,\n secondary,\n tertiary:\n isExhausted &&\n subscription.isWaiverPreviewLoading !== true &&\n subscription.canWaiveFailedCycle === true\n ? \"waive_failed_cycle\"\n : null,\n isCheckingWaiver:\n isExhausted && subscription.isWaiverPreviewLoading === true,\n },\n };\n }\n\n if (status === \"completed\") {\n return { primary: null, order: [], menu: [], recovery: null };\n }\n\n if ([\"pending\", \"trial\"].includes(status)) {\n return {\n primary: null,\n order: [],\n menu: [\"cancel_subscription\"],\n recovery: null,\n };\n }\n\n return { primary: null, order: [], menu: [], recovery: null };\n}\n","export type FailedCycleWaiverSummary =\n | { kind: \"combined\"; date: string }\n | { kind: \"separate\"; billDate: string; shipDate: string };\n\nconst ISO_INSTANT_PATTERN =\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?(Z|[+-]\\d{2}:\\d{2})$/;\n\nexport function getFailedCycleWaiverSummary(input: {\n nextBillDate: string;\n nextShipDate: string;\n locale: string;\n timezone: string;\n}): FailedCycleWaiverSummary | null {\n const billDate = parseIsoInstant(input.nextBillDate);\n const shipDate = parseIsoInstant(input.nextShipDate);\n if (billDate == null || shipDate == null) return null;\n\n const calendarFormatter = createCalendarDateFormatter(input.timezone);\n const displayFormatter = createDisplayDateFormatter(\n input.locale,\n input.timezone,\n );\n if (calendarFormatter == null || displayFormatter == null) return null;\n\n const billCalendarDate = getCalendarDateIdentity(calendarFormatter, billDate);\n const shipCalendarDate = getCalendarDateIdentity(calendarFormatter, shipDate);\n if (billCalendarDate == null || shipCalendarDate == null) return null;\n\n const formattedBillDate = displayFormatter.format(billDate);\n const formattedShipDate = displayFormatter.format(shipDate);\n\n if (billCalendarDate === shipCalendarDate) {\n return { kind: \"combined\", date: formattedBillDate };\n }\n\n return {\n kind: \"separate\",\n billDate: formattedBillDate,\n shipDate: formattedShipDate,\n };\n}\n\nfunction parseIsoInstant(input: string): Date | null {\n const match = ISO_INSTANT_PATTERN.exec(input);\n if (match == null) return null;\n\n const [, yearText, monthText, dayText, hourText, minuteText, secondText] =\n match;\n const offset = match[8];\n if (\n yearText == null ||\n monthText == null ||\n dayText == null ||\n hourText == null ||\n minuteText == null ||\n secondText == null ||\n offset == null\n ) {\n return null;\n }\n\n const year = Number(yearText);\n const month = Number(monthText);\n const day = Number(dayText);\n const hour = Number(hourText);\n const minute = Number(minuteText);\n const second = Number(secondText);\n\n if (\n month < 1 ||\n month > 12 ||\n day < 1 ||\n day > daysInMonth(year, month) ||\n hour > 23 ||\n minute > 59 ||\n second > 59 ||\n !isValidOffset(offset)\n ) {\n return null;\n }\n\n const instant = new Date(input);\n return Number.isNaN(instant.getTime()) ? null : instant;\n}\n\nfunction daysInMonth(year: number, month: number): number {\n if (month === 2) {\n const isLeapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);\n return isLeapYear ? 29 : 28;\n }\n\n return [4, 6, 9, 11].includes(month) ? 30 : 31;\n}\n\nfunction isValidOffset(offset: string): boolean {\n if (offset === \"Z\") return true;\n\n const offsetHour = Number(offset.slice(1, 3));\n const offsetMinute = Number(offset.slice(4, 6));\n return offsetHour <= 23 && offsetMinute <= 59;\n}\n\nfunction createCalendarDateFormatter(\n timezone: string,\n): Intl.DateTimeFormat | null {\n try {\n return new Intl.DateTimeFormat(\"en-US-u-ca-gregory-nu-latn\", {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n timeZone: timezone,\n });\n } catch {\n return null;\n }\n}\n\nfunction createDisplayDateFormatter(\n locale: string,\n timezone: string,\n): Intl.DateTimeFormat | null {\n const normalizedLocale = locale.trim().replaceAll(\"_\", \"-\");\n if (!normalizedLocale) return null;\n\n let supportedLocale: string | undefined;\n try {\n [supportedLocale] = Intl.DateTimeFormat.supportedLocalesOf(\n [normalizedLocale],\n { localeMatcher: \"lookup\" },\n );\n } catch {\n return null;\n }\n if (supportedLocale == null) return null;\n\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n timeZone: timezone,\n };\n\n try {\n return new Intl.DateTimeFormat(supportedLocale, options);\n } catch {\n return null;\n }\n}\n\nfunction getCalendarDateIdentity(\n formatter: Intl.DateTimeFormat,\n instant: Date,\n): string | null {\n const parts = formatter.formatToParts(instant);\n const year = parts.find((part) => part.type === \"year\")?.value;\n const month = parts.find((part) => part.type === \"month\")?.value;\n const day = parts.find((part) => part.type === \"day\")?.value;\n if (year == null || month == null || day == null) return null;\n\n return `${year}-${month}-${day}`;\n}\n","/** How far an auto-apply-points write reaches. */\nexport type AutoApplyPointsScope = \"subscription\" | \"bundle\";\n\n/**\n * The two token sets the server reports for one write.\n *\n * The update response's `subscription` resource deliberately does not cross\n * this port: the hook refetches detail immediately, so a partial resource here\n * would be a second source of truth for data nothing reads. Only these two\n * sets cross, because only they are unavailable any other way.\n */\nexport type AutoApplyPointsWriteResult = {\n /** Every subscription the write was resolved against. */\n resolvedSubscriptionTokens: string[];\n /** The subset whose stored value actually moved. */\n changedSubscriptionTokens: string[];\n};\n\n/**\n * Bundle membership changed under a bundle-scoped write and the server's retry\n * did not settle, so nothing was written and the customer can try again.\n *\n * Transport-free on purpose. Thrown only for HTTP 409 whose `error.code` is\n * `bundle_membership_conflict`; every other failure stays generic. A named\n * domain error rather than a discriminated result because TanStack Query's\n * error channel wants a throw, and this keeps the happy path free of\n * branching while still giving the component a stable signal to catch.\n */\nexport class BundleMembershipConflictError extends Error {\n constructor(message: string) {\n super(message);\n // Explicit, because extending a built-in loses the subclass name under\n // some transpilation targets and the name is what shows up in logs.\n this.name = \"BundleMembershipConflictError\";\n }\n}\n\n/** The portal's write for the renewal-bundle points opt-in. */\nexport interface AutoApplyPointsApi {\n /**\n * Write the opt-in at the requested scope.\n *\n * Throws BundleMembershipConflictError on a settled-out conflict; any other\n * failure throws whatever the transport produced.\n */\n updateAutoApplyPoints(input: {\n subscriptionToken: string;\n autoApplyPoints: boolean;\n scope: AutoApplyPointsScope;\n }): Promise<AutoApplyPointsWriteResult>;\n}\n","import { createContext, type Provider, use } from \"react\";\nimport type { AutoApplyPointsApi } from \"./auto-apply-points-api\";\n\nconst AutoApplyPointsApiContext = createContext<AutoApplyPointsApi | null>(\n null,\n);\n\nexport const AutoApplyPointsApiProvider: Provider<AutoApplyPointsApi | null> =\n AutoApplyPointsApiContext.Provider;\n\nexport function useAutoApplyPointsApi(): AutoApplyPointsApi {\n const api = use(AutoApplyPointsApiContext);\n if (!api) {\n throw new Error(\n \"useAutoApplyPointsApi must be used within an AutoApplyPointsApiProvider\",\n );\n }\n return api;\n}\n","import type { SubscriptionsApi } from \"@fluid-app/subscriptions-core\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport type { PortalTenantHeyApiClient } from \"@fluid-app/portal-tenant-api-client/client\";\nimport * as portalTenant from \"@fluid-app/portal-tenant-api-client/sdk\";\n\n/**\n * Maps the BFF meta envelope to the port's expected shape.\n */\nfunction mapMeta(raw: { request_id?: string | null; timestamp?: string }): {\n request_id: string;\n timestamp: string;\n} {\n return {\n request_id: raw.request_id ?? \"\",\n timestamp: raw.timestamp ?? \"\",\n };\n}\n\ntype BffSubscriptionResponse = NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionsShow>>\n>;\n\ntype BffListResponse = NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionsList>>\n>;\n\ntype BffFailedCycleWaiverPreviewResponse = NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionsFailedCycleWaiverPreview>>\n>;\n\n// `subscriptionsShow` is the only action whose response narrows `subscription`\n// to `SubscriptionDetailResource` (renewal_bundle required, since show is the\n// only action that populates it). Every other subscription action\n// (pause/resume/skip/cancel/reactivate/retry/waiver-create/update) returns the\n// looser `Subscription` shape. `mapDetailSubscription` never reads\n// renewal_bundle, so it is typed to that common denominator rather than the\n// show-specific response, letting every action's response satisfy it.\ntype BffSubscription = NonNullable<\n NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionsPause>>\n >[\"subscription\"]\n>;\n\n// Structural envelope shared by every subscription action response. Narrower\n// than each action's exact generated type (which vary in whether\n// subscription/meta are required and which carry extra fields), but every one\n// of them is assignable to it.\ntype BffSubscriptionActionResponse = {\n subscription?: BffSubscription;\n meta?: BffSubscriptionResponse[\"meta\"];\n};\n\n/**\n * Narrows the generated generic Meta schema to the shared port shape without\n * rebuilding the BFF response or dropping transport-only fields. The\n * portal-tenant BFF serves meta.request_id as null (the contract allows it),\n * so only a non-string, non-null request_id is rejected.\n */\nfunction assertSharedFailedCycleWaiverPreview(\n response: BffFailedCycleWaiverPreviewResponse,\n): asserts response is BffFailedCycleWaiverPreviewResponse &\n subscriptions.FailedCycleWaiverPreviewResponse {\n const meta = response.meta;\n if (\n meta != null &&\n ((meta.request_id != null && typeof meta.request_id !== \"string\") ||\n typeof meta.timestamp !== \"string\")\n ) {\n throw new Error(\"Failed-cycle waiver preview metadata is invalid\");\n }\n}\n\n/**\n * Safely parses a price string to a number, returning the fallback if the\n * result is NaN (e.g. non-numeric strings from a malformed BFF response).\n */\nfunction safeParsePrice(\n value: string | null | undefined,\n fallback = 0,\n): number {\n if (!value) return fallback;\n const parsed = parseFloat(value);\n return Number.isNaN(parsed) ? fallback : parsed;\n}\n\n/**\n * Maps a BFF subscription detail response to the port's SubscriptionDetail.\n *\n * The BFF returns a flat Subscription schema (plan_name, product, etc.) while\n * the port expects richly nested objects (subscription_plan, variant.product).\n * This explicitly maps every field the UI accesses so undefined-property crashes\n * are caught here at the adapter boundary rather than deep in the component tree.\n */\nexport function mapDetailSubscription(\n bff: BffSubscription,\n): subscriptions.SubscriptionDetailSubscription {\n const price = safeParsePrice(bff.total);\n\n return {\n id: bff.id ?? 0,\n subscription_token: bff.token ?? \"\",\n status: bff.status ?? \"\",\n billing_cycle_limit_reached: bff.billing_cycle_limit_reached ?? false,\n successful_billing_cycles: bff.successful_billing_cycles ?? 0,\n quantity: bff.quantity ?? 1,\n price,\n original_price: safeParsePrice(bff.original_price, price),\n next_bill_date: bff.next_billing_date ?? null,\n last_bill_date: bff.last_billing_date ?? null,\n timezone: bff.timezone ?? null,\n next_ship_date: null,\n last_ship_date: bff.last_shipping_date ?? null,\n disabled: false,\n attempts: 0,\n // The portal-tenant OpenAPI schema dropped last_failed_at/next_retry_at\n // from the Subscription response, but the BFF still returns them at runtime\n // and downstream components (past-due-banner, subscription-detail) rely on\n // them. Read through a cast until the schema is restored. Tracked in\n // CURRENT-1069.\n last_failed_at:\n ((bff as Record<string, unknown>).last_failed_at as\n | string\n | null\n | undefined) ?? null,\n next_retry_at:\n ((bff as Record<string, unknown>).next_retry_at as\n | string\n | null\n | undefined) ?? null,\n // decline_count drives the banner's \"we're trying again\" vs \"the last\n // retry didn't go through\" branch. Same cast-through-Record pattern as\n // last_failed_at/next_retry_at above until the OpenAPI schema is\n // regenerated to include it.\n decline_count:\n ((bff as Record<string, unknown>).decline_count as\n | number\n | null\n | undefined) ?? null,\n skipped_count: 0,\n max_skips: null,\n cancelled_at: null,\n created_at: bff.created_at ?? \"\",\n updated_at: bff.updated_at ?? \"\",\n notes: null,\n // Copied WITHOUT a `??` default, deliberately. This mapper is a whitelist,\n // so a field it omits reaches the UI as undefined with no type error, and a\n // default here would erase the difference between \"the company has no\n // points program\" and \"the customer turned this off\". points_enabled gates\n // whether the control renders at all, and auto_apply_points is the state it\n // renders from, so collapsing either one breaks a different thing.\n auto_apply_points: bff.auto_apply_points,\n points_enabled: bff.points_enabled,\n subscription_plan: {\n id: bff.plan?.id ?? 0,\n name: bff.plan?.name ?? bff.plan_name ?? \"\",\n billing_interval: bff.plan?.billing_interval ?? 1,\n billing_interval_unit:\n bff.plan?.billing_interval_unit ?? bff.interval ?? \"month\",\n billing_frequency_in_words: bff.plan?.billing_interval_unit\n ? `Every ${bff.plan.billing_interval ?? 1} ${bff.plan.billing_interval_unit}`\n : \"\",\n shipping_interval: 1,\n shipping_interval_unit:\n bff.plan?.billing_interval_unit ?? bff.interval ?? \"month\",\n trial_period: null,\n trial_period_unit: null,\n split_volume: false,\n allow_skipping: bff.plan?.allow_skipping ?? false,\n max_skips: bff.plan?.max_skips ?? null,\n allow_max_billing_cycles: bff.plan?.allow_max_billing_cycles ?? false,\n max_billing_cycles: bff.plan?.max_billing_cycles ?? null,\n price_adjustment_type: null,\n price_adjustment_amount: null,\n // Variant-level cap exposed via `bff.product.max_quantity` (the BFF\n // sources it from `variants.subscription_max_qty` gated on\n // `limit_subscription`). The FE port still keys it under\n // `subscription_plan` for back-compat with the existing UI consumer.\n max_quantity: bff.product?.max_quantity ?? null,\n active: true,\n company_default: null,\n created_at: \"\",\n updated_at: \"\",\n products_count: null,\n subscribers_count: null,\n },\n customer: {\n id: 0,\n account_id: null,\n first_name: null,\n last_name: null,\n full_name: bff.customer_name ?? \"\",\n email: \"\",\n verified_email: null,\n phone: null,\n orders_count: null,\n created_at: \"\",\n display_total_spent: \"0\",\n metadata: {},\n user_company_id: null,\n external_id: null,\n last_order_id: null,\n notes: null,\n active: true,\n total_spent: 0,\n customer_notes: [],\n default_address: null,\n addresses: [],\n active_subscriptions_count: 0,\n inactive_subscriptions_count: 0,\n is_rep: false,\n },\n variant: {\n id: bff.product?.id ?? 0,\n title: bff.product?.variant_name ?? \"\",\n image_url: bff.product?.image_url ?? null,\n image_path: null,\n sku: null,\n primary_image: bff.product?.image_url ?? null,\n price: bff.total ? safeParsePrice(bff.total) : null,\n price_in_currency: bff.total ?? \"0\",\n options: [],\n product: {\n id: bff.product?.id ?? 0,\n title: bff.product?.name ?? \"\",\n image_url: bff.product?.image_url ?? null,\n image_path: null,\n price: bff.total ? safeParsePrice(bff.total) : null,\n cv: null,\n tax: null,\n sku: null,\n price_in_currency: bff.total ?? \"0\",\n tax_in_currency: \"0\",\n cv_in_currency: \"0\",\n },\n },\n address_id: bff.address_id ?? null,\n address: bff.address\n ? {\n id: bff.address.id ?? null,\n name: bff.address.name ?? null,\n address1: bff.address.address1 ?? \"\",\n address2: bff.address.address2 ?? null,\n city: bff.address.city ?? \"\",\n state: bff.address.state ?? \"\",\n subdivision_code: null,\n postal_code: bff.address.postal_code ?? \"\",\n country_code: bff.address.country_code ?? null,\n default: false,\n }\n : {\n id: null,\n name: null,\n address1: \"\",\n address2: null,\n city: \"\",\n state: \"\",\n subdivision_code: null,\n postal_code: \"\",\n country_code: null,\n default: false,\n },\n payment_method: bff.payment_method\n ? {\n id: bff.payment_method.id ?? 0,\n source: bff.payment_method.source ?? \"\",\n payment_type:\n bff.payment_method.payment_type ?? bff.payment_method.source ?? \"\",\n created_at: \"\",\n updated_at: \"\",\n default: false,\n details: {\n card_network: bff.payment_method.card_network ?? undefined,\n last4: bff.payment_method.last4 ?? undefined,\n },\n }\n : {\n id: 0,\n source: \"\",\n payment_type: \"\",\n created_at: \"\",\n updated_at: \"\",\n default: false,\n details: {},\n },\n currency: {\n id: 0,\n name: bff.currency ?? null,\n code: bff.currency ?? \"USD\",\n rate: null,\n active: true,\n symbol: null,\n },\n country: { id: 0, name: \"\", iso: \"\" },\n company: { id: 0, name: \"\" },\n subscription_skips: [],\n orders: [],\n bundled_items: bff.bundled_items\n ? bff.bundled_items.map((item) => ({\n quantity: item.quantity ?? 0,\n product_id: item.product_id ?? 0,\n variant_id: item.variant_id ?? 0,\n option_titles: item.option_titles ?? [],\n product_title: item.product_title ?? \"\",\n variant_title: item.variant_title ?? \"\",\n display_to_customer: item.display_to_customer ?? true,\n }))\n : undefined,\n bundled_subscriptions: bff.bundled_subscriptions\n ? bff.bundled_subscriptions.map((sib) => ({\n subscription_token: sib.subscription_token ?? \"\",\n product_title: sib.product_title ?? \"\",\n variant_title: sib.variant_title ?? null,\n price: sib.price ?? 0,\n image_url: sib.image_url ?? null,\n }))\n : undefined,\n // The portal-tenant OpenAPI client type lags the Rails schema (same lag as\n // last_failed_at above — tracked in CURRENT-1069), so these first-class\n // subscription-discount fields are read through a cast until the generated\n // client is regenerated. The BFF returns them at runtime; the\n // subscription-detail pricing summary relies on them to render the attached\n // discount line and net total. renewal_discount_total is coerced because\n // the BFF serializes other money fields (total, original_price) as strings\n // and could normalize this one the same way later.\n subscription_discounts:\n ((bff as Record<string, unknown>).subscription_discounts as\n | subscriptions.SubscriptionDiscountAttachment[]\n | undefined) ?? [],\n renewal_discount_total:\n Number((bff as Record<string, unknown>).renewal_discount_total ?? 0) || 0,\n // Passed through as the server sent it. Both null and undefined take\n // the same fallback route (autoApplyPointsWriteRoute falsy-checks it),\n // so collapsing one into the other would discard what the server said\n // and buy nothing.\n renewal_bundle: bff.renewal_bundle,\n };\n}\n\nfunction mapSubscriptionDetail(\n response: BffSubscriptionActionResponse,\n): subscriptions.SubscriptionDetail {\n const bff = response.subscription;\n if (!bff) {\n throw new Error(\n \"BFF returned a successful response but subscription data was missing\",\n );\n }\n return {\n subscription: mapDetailSubscription(bff),\n meta: response.meta ? mapMeta(response.meta) : undefined,\n };\n}\n\n/**\n * Maps a BFF list subscription to the port's SubscriptionListItem.\n *\n * The BFF returns a flat shape with `product` and `quantity` while the port\n * expects nested `variant.product` (from the admin API). This bridges the two\n * so the UI layer sees a consistent shape regardless of which API backs it.\n */\nfunction mapListItem(\n bff: NonNullable<BffListResponse[\"subscriptions\"]>[number],\n): subscriptions.SubscriptionListItem {\n return {\n id: bff.id ?? 0,\n subscription_token: bff.token ?? \"\",\n created_at: bff.created_at ?? \"\",\n customer: {\n id: 0,\n account_id: \"\",\n active: true,\n display_total_spent: \"0\",\n email: \"\",\n first_name: \"\",\n full_name: bff.customer_name ?? \"\",\n is_rep: false,\n last_name: \"\",\n orders_count: 0,\n phone: null,\n total_spent: \"0\",\n user_company_id: null,\n },\n last_bill_date: null,\n next_bill_date: bff.next_billing_date ?? null,\n price: safeParsePrice(bff.total),\n quantity: bff.quantity ?? 1,\n status: bff.status ?? \"\",\n billing_cycle_limit_reached: bff.billing_cycle_limit_reached ?? false,\n successful_billing_cycles: bff.successful_billing_cycles ?? 0,\n subscription_plan: {\n // The flat top-level `bff.interval` is a denormalized convenience that\n // does NOT carry a numeric interval — it's a single descriptor like\n // \"monthly\". The accurate fields are on `bff.plan` (number + unit), so\n // a quarterly subscription returns interval=3 / unit=\"month\" there.\n id: bff.plan?.id ?? 0,\n active: true,\n billing_interval: bff.plan?.billing_interval ?? 1,\n billing_interval_unit: bff.plan?.billing_interval_unit ?? \"\",\n shipping_interval: bff.plan?.billing_interval ?? 1,\n shipping_interval_unit: bff.plan?.billing_interval_unit ?? \"\",\n },\n variant: {\n id: bff.product?.id ?? 0,\n title: bff.product?.variant_name ?? \"\",\n product: {\n id: bff.product?.id ?? 0,\n title: bff.product?.name ?? \"\",\n image_url: bff.product?.image_url ?? \"\",\n price_in_currency: bff.total ?? \"0\",\n },\n },\n bundled_subscriptions: (bff.bundled_subscriptions ?? []).map((b) => ({\n subscription_token: b.subscription_token ?? \"\",\n product_title: b.product_title ?? \"\",\n variant_title: b.variant_title ?? null,\n price: b.price ?? 0,\n image_url: b.image_url ?? null,\n })),\n };\n}\n\nfunction mapSubscriptionList(\n response: BffListResponse,\n): subscriptions.SubscriptionsResponse {\n const raw = response.meta ?? {};\n return {\n subscriptions: (response.subscriptions ?? []).map(mapListItem),\n meta: {\n ...mapMeta(raw),\n pagination: raw.pagination\n ? {\n cursor: raw.pagination.cursor ?? null,\n limit: raw.pagination.limit,\n next_cursor: raw.pagination.next_cursor ?? null,\n prev_cursor: raw.pagination.prev_cursor ?? null,\n }\n : undefined,\n },\n };\n}\n\n/**\n * Creates a SubscriptionsApi-compatible adapter backed by the portal-tenant BFF.\n *\n * Uses async/await with explicit field mapping. The BFF returns simplified\n * subscription types compared to the full admin API; the adapter maps the\n * response envelope and provides runtime defaults for optional fields.\n */\nexport function createPortalSubscriptionsAdapter(\n client: PortalTenantHeyApiClient,\n): SubscriptionsApi {\n return {\n fetchCustomerSubscriptions: async (\n params: subscriptions.FetchSubscriptionsParams,\n ) => {\n const rawStatus = params.status;\n const status =\n rawStatus === \"active\" || rawStatus === \"inactive\"\n ? rawStatus\n : undefined;\n const response = await portalTenant.subscriptionsList({\n client,\n query: {\n \"page[cursor]\": params.cursor,\n \"page[limit]\": params.limit ?? params.perPage,\n status,\n q: params.search ?? undefined,\n },\n });\n return mapSubscriptionList(response);\n },\n\n fetchSubscription: async (subscriptionToken: string) => {\n const response = await portalTenant.subscriptionsShow({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n pauseSubscription: async (\n subscriptionToken: string,\n params: subscriptions.PauseSubscriptionParams,\n ) => {\n const body: {\n next_bill_date?: string;\n number_of_orders?: number;\n } = {};\n if (params.nextBillDate != null)\n body.next_bill_date = params.nextBillDate;\n if (params.numberOfOrders != null)\n body.number_of_orders = params.numberOfOrders;\n const response = await portalTenant.subscriptionsPause({\n client,\n path: { token: subscriptionToken },\n body,\n });\n return mapSubscriptionDetail(response);\n },\n\n resumeSubscription: async (\n subscriptionToken: string,\n params: subscriptions.ResumeSubscriptionParams,\n ) => {\n const body = params.nextBillDate\n ? { next_bill_date: params.nextBillDate }\n : undefined;\n const response = await portalTenant.subscriptionsResume({\n client,\n path: { token: subscriptionToken },\n body,\n });\n return mapSubscriptionDetail(response);\n },\n\n skipSubscription: async (\n subscriptionToken: string,\n _params: subscriptions.SkipSubscriptionParams,\n ) => {\n const response = await portalTenant.subscriptionsSkip({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n cancelSubscription: async (\n subscriptionToken: string,\n _customerId?: number,\n ) => {\n const response = await portalTenant.subscriptionsCancel({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n reactivateSubscription: async (\n subscriptionToken: string,\n params: subscriptions.ReactivateSubscriptionParams,\n ) => {\n const response = await portalTenant.subscriptionsReactivate({\n client,\n path: { token: subscriptionToken },\n body:\n params.address_id != null\n ? { address_id: params.address_id }\n : undefined,\n });\n return mapSubscriptionDetail(response);\n },\n\n retrySubscription: async (subscriptionToken: string) => {\n const response = await portalTenant.subscriptionsRetry({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n fetchFailedCycleWaiverPreview: async (subscriptionToken: string) => {\n const response = await portalTenant.subscriptionsFailedCycleWaiverPreview(\n {\n client,\n path: { token: subscriptionToken },\n },\n );\n assertSharedFailedCycleWaiverPreview(response);\n return response;\n },\n\n waiveFailedCycle: async (subscriptionToken: string) => {\n const response = await portalTenant.subscriptionsFailedCycleWaiverCreate({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n updateSubscriptionInfo: async (\n subscriptionToken: string,\n body: Partial<\n Pick<\n subscriptions.UpdateSubscriptionInfoBody,\n | \"payment_method_id\"\n | \"quantity\"\n | \"address_id\"\n | \"next_bill_date\"\n | \"auto_apply_points\"\n >\n >,\n ) => {\n const subscription: {\n payment_method_id?: number;\n quantity?: number;\n address_id?: number;\n next_bill_date?: string;\n auto_apply_points?: boolean;\n } = {};\n if (body.payment_method_id != null) {\n subscription.payment_method_id = body.payment_method_id;\n }\n if (body.quantity != null) {\n subscription.quantity = body.quantity;\n }\n if (body.address_id != null) {\n subscription.address_id = body.address_id;\n }\n if (body.next_bill_date != null) {\n subscription.next_bill_date = body.next_bill_date;\n }\n // `!= null` rather than `!== undefined`, matching every sibling above.\n // Both let an explicit `false` through, which is what turning the setting\n // off depends on; a truthiness check is what would drop it.\n if (body.auto_apply_points != null) {\n subscription.auto_apply_points = body.auto_apply_points;\n }\n const response = await portalTenant.subscriptionsUpdate({\n client,\n path: { token: subscriptionToken },\n body: { subscription },\n });\n return mapSubscriptionDetail(response);\n },\n };\n}\n","// Import shape copied verbatim from subscriptions-api-adapter.ts, the\n// neighbour the AGENTS contract names as the pattern to follow.\nimport * as portalTenant from \"@fluid-app/portal-tenant-api-client/sdk\";\nimport type { PortalTenantHeyApiClient } from \"@fluid-app/portal-tenant-api-client/client\";\nimport { isApiError, toApiErrorBody } from \"@fluid-app/api-client-core\";\nimport {\n BundleMembershipConflictError,\n type AutoApplyPointsApi,\n type AutoApplyPointsWriteResult,\n} from \"@fluid-app/subscriptions-core\";\n\n/**\n * Whether a thrown value is the server's settled-out bundle conflict.\n *\n * isApiError alone cannot answer this: it narrows `body` to\n * `Record<string, unknown> | null`, which leaves `body.error` as `unknown`.\n * toApiErrorBody is the repo's helper for that nested-envelope narrowing.\n * Only a string `code` counts, because anything else is not this failure and\n * must not select the retry path.\n */\nfunction isBundleMembershipConflict(error: unknown): boolean {\n if (!isApiError(error) || error.status !== 409) return false;\n\n const envelope = toApiErrorBody(error.body?.error);\n return envelope?.code === \"bundle_membership_conflict\";\n}\n\n/**\n * The portal's implementation of the auto-apply-points write.\n *\n * Owns transport, request mapping, response mapping, and mapping only\n * 409-plus-bundle_membership_conflict to the typed domain error. Every other\n * failure passes through generic.\n */\nexport function createAutoApplyPointsApiAdapter(\n client: PortalTenantHeyApiClient,\n): AutoApplyPointsApi {\n return {\n async updateAutoApplyPoints({ subscriptionToken, autoApplyPoints, scope }) {\n try {\n const response = await portalTenant.subscriptionsUpdate({\n client,\n path: { token: subscriptionToken },\n body: {\n subscription: {\n auto_apply_points: autoApplyPoints,\n auto_apply_points_scope: scope,\n },\n },\n });\n\n // The response's `subscription` resource deliberately does not cross\n // the port; the hook refetches detail, so a partial resource here\n // would be a second source of truth nothing reads.\n return {\n resolvedSubscriptionTokens:\n response.resolved_subscription_tokens ?? [],\n changedSubscriptionTokens: response.changed_subscription_tokens ?? [],\n } satisfies AutoApplyPointsWriteResult;\n } catch (error) {\n if (isBundleMembershipConflict(error)) {\n throw new BundleMembershipConflictError(\n \"Bundle membership changed while the write was in flight\",\n );\n }\n throw error;\n }\n },\n };\n}\n","import { useMemo, type ReactElement, type ReactNode } from \"react\";\nimport {\n AutoApplyPointsApiProvider,\n SubscriptionsCoreProvider,\n} from \"@fluid-app/subscriptions-core\";\nimport { usePortalTenantClient } from \"../providers/PortalTenantClientProvider\";\nimport { createPortalSubscriptionsAdapter } from \"../adapters/subscriptions-api-adapter\";\nimport { createAutoApplyPointsApiAdapter } from \"../adapters/auto-apply-points-api-adapter\";\n\nexport function PortalSubscriptionsApiProvider({\n children,\n}: {\n children: ReactNode;\n}): ReactElement {\n const client = usePortalTenantClient();\n\n const api = useMemo(() => createPortalSubscriptionsAdapter(client), [client]);\n // Memoized so a re-render does not hand consumers a new port identity,\n // which would invalidate every dependent memo downstream.\n const autoApplyPointsApi = useMemo(\n () => createAutoApplyPointsApiAdapter(client),\n [client],\n );\n\n return (\n <SubscriptionsCoreProvider api={api}>\n <AutoApplyPointsApiProvider value={autoApplyPointsApi}>\n {children}\n </AutoApplyPointsApiProvider>\n </SubscriptionsCoreProvider>\n );\n}\n","import type { BundlesApi } from \"@fluid-app/subscriptions-core\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport type { PortalTenantHeyApiClient } from \"@fluid-app/portal-tenant-api-client/client\";\nimport * as portalTenant from \"@fluid-app/portal-tenant-api-client/sdk\";\nimport { mapDetailSubscription } from \"./subscriptions-api-adapter\";\n\ntype BffBundleListResponse = NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionBundlesList>>\n>;\ntype BffBundle = NonNullable<\n BffBundleListResponse[\"subscription_bundles\"]\n>[number];\n\ntype BffSubscriptionInBundle = NonNullable<BffBundle[\"subscriptions\"]>[number];\n\nfunction mapAddress(\n bff: BffBundle[\"address\"],\n): subscriptions.SubscriptionDetailAddress | null {\n if (!bff) return null;\n return {\n id: bff.id ?? 0,\n name: bff.name ?? null,\n address1: bff.address1 ?? \"\",\n address2: bff.address2 ?? null,\n city: bff.city ?? \"\",\n state: bff.state ?? \"\",\n subdivision_code: null,\n postal_code: bff.postal_code ?? \"\",\n country_code: bff.country_code ?? null,\n default: false,\n };\n}\n\nfunction mapVolumeRep(\n bff: BffBundle[\"volume_rep\"],\n): subscriptions.BundleVolumeRep | null {\n if (!bff) return null;\n return {\n id: bff.id ?? 0,\n email: bff.email ?? null,\n full_name: bff.full_name ?? null,\n image_url: bff.image_url ?? null,\n };\n}\n\nfunction mapBundle(bff: BffBundle): subscriptions.Bundle {\n return {\n next_bill_date: bff.next_bill_date ?? null,\n subscription_count: bff.subscription_count ?? 0,\n address: mapAddress(bff.address),\n volume_rep: mapVolumeRep(bff.volume_rep),\n subscriptions: (bff.subscriptions ?? []).map((s) =>\n // The bundle's subscriptions field uses the same Subscription schema as\n // the subscriptions_show endpoint, so the existing detail mapper works\n // unchanged.\n mapDetailSubscription(s as BffSubscriptionInBundle),\n ),\n };\n}\n\nexport function createPortalBundlesAdapter(\n client: PortalTenantHeyApiClient,\n): BundlesApi {\n return {\n fetchBundles: async () => {\n const response = await portalTenant.subscriptionBundlesList({ client });\n return (response.subscription_bundles ?? []).map(mapBundle);\n },\n\n createBundle: async (params: subscriptions.CreateBundleParams) => {\n const bundle: {\n subscription_tokens: string[];\n next_bill_date: string;\n address_id?: number | null;\n volume_rep_id?: number | null;\n } = {\n subscription_tokens: params.subscription_tokens,\n next_bill_date: params.next_bill_date,\n };\n if (params.address_id !== undefined)\n bundle.address_id = params.address_id;\n if (params.volume_rep_id !== undefined)\n bundle.volume_rep_id = params.volume_rep_id;\n\n const response = await portalTenant.subscriptionBundlesCreate({\n client,\n body: { bundle },\n });\n const bff = response.subscription_bundle;\n if (!bff) {\n throw new Error(\n \"BFF returned a successful response but bundle data was missing\",\n );\n }\n return mapBundle(bff);\n },\n };\n}\n","import { useMemo, type ReactElement, type ReactNode } from \"react\";\nimport { BundlesCoreProvider } from \"@fluid-app/subscriptions-core\";\nimport { usePortalTenantClient } from \"../providers/PortalTenantClientProvider\";\nimport { createPortalBundlesAdapter } from \"../adapters/bundles-api-adapter\";\n\nexport function PortalBundlesApiProvider({\n children,\n}: {\n children: ReactNode;\n}): ReactElement {\n const client = usePortalTenantClient();\n const api = useMemo(() => createPortalBundlesAdapter(client), [client]);\n return <BundlesCoreProvider api={api}>{children}</BundlesCoreProvider>;\n}\n","import type { Provider } from \"react\";\nimport { createTranslationContext } from \"@fluid-app/i18n/translation-api-context-factory\";\nimport type { TranslationApi } from \"@fluid-app/i18n/translation-api\";\nimport type { SubscriptionsDict } from \"./translation-dictionary\";\n\nconst { Provider: SubscriptionsProvider, useTranslation } =\n createTranslationContext<SubscriptionsDict>(\"Subscriptions\");\n\nexport const SubscriptionsTranslationProvider: Provider<TranslationApi<SubscriptionsDict> | null> =\n SubscriptionsProvider;\nexport const useSubscriptionsTranslation = useTranslation;\n","import { useMemo, type ReactNode } from \"react\";\nimport { useActiveLocale } from \"@fluid-app/i18n/locale-context\";\nimport { useDomainDict } from \"@fluid-app/i18n/use-domain-dict\";\nimport {\n subscriptionsDomain,\n createSubscriptionsTranslationAdapter,\n} from \"@fluid-app/subscriptions-core/translation-adapter\";\nimport { SubscriptionsTranslationProvider } from \"@fluid-app/subscriptions-core/translation-api-context\";\n\nexport function SubscriptionsTranslationBridge({\n children,\n}: {\n children: ReactNode;\n}): React.JSX.Element {\n const { locale } = useActiveLocale();\n const dict = useDomainDict(subscriptionsDomain, locale);\n const api = useMemo(\n () => createSubscriptionsTranslationAdapter(locale, dict),\n [locale, dict],\n );\n return (\n <SubscriptionsTranslationProvider value={api}>\n {children}\n </SubscriptionsTranslationProvider>\n );\n}\n","import { isThreeDsRequiredCreate } from \"@fluid-app/portal-core/pay-types\";\nimport type {\n CreatePaymentMethodResponse,\n ThreeDsRequiredCreateResult,\n} from \"@fluid-app/portal-core/pay-types\";\n\n/**\n * Build the subscription create-payment-method onSuccess handler. On\n * three_ds_required it hands off to the 3DS flow (no bind/close — begin()\n * resolves at modal-open). On a created PM it runs the legacy created path with\n * the new payment method id (the caller routes dropdown-vs-banner inside\n * onCreated).\n */\nexport function buildSubscriptionCardAddSuccess(deps: {\n begin: (created: ThreeDsRequiredCreateResult) => Promise<void>;\n onCreated: (paymentMethodId: number) => void;\n}) {\n return async (response: CreatePaymentMethodResponse) => {\n if (isThreeDsRequiredCreate(response)) {\n await deps.begin(response);\n return;\n }\n deps.onCreated(response.payment_method.id);\n };\n}\n","import type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport type { SubscriptionsDict } from \"@fluid-app/subscriptions-core/translation-dictionary\";\nimport type { TranslationApi } from \"@fluid-app/i18n/translation-api\";\n\nexport type T = TranslationApi<SubscriptionsDict>[\"t\"];\n\nconst UNIT_KEYS: Record<string, { singular: string; plural: string }> = {\n day: { singular: \"unit_day\", plural: \"unit_days\" },\n week: { singular: \"unit_week\", plural: \"unit_weeks\" },\n month: { singular: \"unit_month\", plural: \"unit_months\" },\n year: { singular: \"unit_year\", plural: \"unit_years\" },\n};\n\nfunction translatedUnit(unit: string, plural: boolean, t: T): string {\n const keys = UNIT_KEYS[unit.toLowerCase()];\n if (!keys) return unit;\n return t((plural ? keys.plural : keys.singular) as \"unit_day\");\n}\n\nexport type FilterKey = \"all\" | \"active\" | \"paused\" | \"cancelled\";\n\nexport type StatusKind =\n | \"active\"\n | \"paused\"\n | \"cancelled\"\n | \"pending\"\n | \"past_due\";\n\nexport interface MappedStatus {\n kind: StatusKind;\n label: string;\n}\n\n/** Status label keys — all non-parameterized so they can be passed to `t()` with no args. */\ntype StatusLabelKey =\n | \"list_status_active\"\n | \"list_status_paused\"\n | \"list_status_cancelled\"\n | \"list_status_completed\"\n | \"list_status_past_due\"\n | \"list_status_pending\";\n\n// US `canceled` and UK `cancelled` fold together; `past_due`/`past-due` too.\nconst STATUS_LOOKUP: Record<\n string,\n { kind: StatusKind; labelKey: StatusLabelKey }\n> = {\n active: { kind: \"active\", labelKey: \"list_status_active\" },\n paused: { kind: \"paused\", labelKey: \"list_status_paused\" },\n cancelled: { kind: \"cancelled\", labelKey: \"list_status_cancelled\" },\n canceled: { kind: \"cancelled\", labelKey: \"list_status_cancelled\" },\n completed: { kind: \"cancelled\", labelKey: \"list_status_completed\" },\n past_due: { kind: \"past_due\", labelKey: \"list_status_past_due\" },\n \"past-due\": { kind: \"past_due\", labelKey: \"list_status_past_due\" },\n pending: { kind: \"pending\", labelKey: \"list_status_pending\" },\n};\n\n/**\n * Map a raw subscription `status` string from the BFF onto our internal\n * status vocabulary. Unknown statuses pass through with `kind: \"pending\"`\n * and a capitalized raw label — never synthesize a colored pill that\n * pretends to be real status data.\n */\nexport function mapStatus(status: string, t: T): MappedStatus {\n const entry = STATUS_LOOKUP[(status || \"\").toLowerCase()];\n if (entry) return { kind: entry.kind, label: t(entry.labelKey) };\n return {\n kind: \"pending\",\n label: status ? status.charAt(0).toUpperCase() + status.slice(1) : \"—\",\n };\n}\n\n/**\n * Sort priority — past-due first (urgent), cancelled last. Used to order\n * subscriptions within the active grid before the cancelled section.\n */\nexport const STATUS_PRIORITY: Record<StatusKind, number> = {\n past_due: 0,\n active: 1,\n pending: 2,\n paused: 3,\n cancelled: 4,\n};\n\n/**\n * \"Active\" group = anything still actionable, including paused (can be\n * resumed). The cancelled section is reserved for cancelled subs only —\n * those are truly done and can't be acted on beyond viewing.\n */\nexport function isActiveKind(kind: StatusKind): boolean {\n return (\n kind === \"active\" ||\n kind === \"past_due\" ||\n kind === \"pending\" ||\n kind === \"paused\"\n );\n}\n\n/**\n * Filter predicate — status-only, does not need translation so we use a\n * stripped-down identity helper that satisfies the `T` signature.\n */\nexport function filterPredicate(\n filter: FilterKey,\n sub: subscriptions.SubscriptionListItem,\n): boolean {\n if (filter === \"all\") return true;\n // We only need the `kind` for filter classification — mapStatus's `t`\n // call for the label is irrelevant here. Cast a no-op identity so this\n // stays a pure filter without a translation dependency.\n const kind = mapStatusKindOnly(sub.status);\n // past_due belongs in Active — it's still actionable (user needs to fix\n // payment) and renders in the active grid by default. Excluding it here\n // would make the most-urgent subs vanish when the Active pill is selected.\n if (filter === \"active\")\n return kind === \"active\" || kind === \"pending\" || kind === \"past_due\";\n if (filter === \"paused\") return kind === \"paused\";\n if (filter === \"cancelled\") return kind === \"cancelled\";\n return true;\n}\n\n/** Lightweight status-kind lookup that doesn't need `t`. */\nexport function mapStatusKindOnly(status: string): StatusKind {\n const entry = STATUS_LOOKUP[(status || \"\").toLowerCase()];\n return entry?.kind ?? \"pending\";\n}\n\nexport function countByFilter(\n list: subscriptions.SubscriptionListItem[],\n): Record<FilterKey, number> {\n return {\n all: list.length,\n active: list.filter((s) => filterPredicate(\"active\", s)).length,\n paused: list.filter((s) => filterPredicate(\"paused\", s)).length,\n cancelled: list.filter((s) => filterPredicate(\"cancelled\", s)).length,\n };\n}\n\nexport function formatCadence(\n plan: subscriptions.SubscriptionListPlan,\n t: T,\n): string {\n const interval = plan.billing_interval;\n const unit = plan.billing_interval_unit;\n if (interval === 1 && unit === \"day\") return t(\"list_cadence_daily\");\n if (interval === 1 && unit === \"month\") return t(\"list_cadence_monthly\");\n if (interval === 1 && unit === \"week\") return t(\"list_cadence_weekly\");\n if (interval === 1 && unit === \"year\") return t(\"list_cadence_yearly\");\n if (interval === 3 && unit === \"month\") return t(\"list_cadence_quarterly\");\n if (interval > 1) {\n return t(\"list_cadence_every_n_units\", {\n n: String(interval),\n unit: translatedUnit(unit, true, t),\n });\n }\n return t(\"list_cadence_every_unit\", {\n unit: translatedUnit(unit, false, t),\n });\n}\n\nexport function pricingSuffix(\n plan: subscriptions.SubscriptionListPlan,\n t: T,\n): string {\n const unit = plan.billing_interval_unit;\n const interval = plan.billing_interval;\n if (interval === 1) {\n if (unit === \"month\") return t(\"list_price_per_month\");\n if (unit === \"week\") return t(\"list_price_per_week\");\n if (unit === \"year\") return t(\"list_price_per_year\");\n if (unit === \"day\") return t(\"list_price_per_day\");\n }\n return t(\"list_price_every_n_units\", {\n n: String(interval),\n unit: translatedUnit(unit, interval > 1, t),\n });\n}\n\nexport function formatLongDate(iso: string): string {\n // BFF date fields come in two shapes: pure calendar dates (\"2026-05-10\",\n // e.g. Bundle.next_bill_date) and datetimes (\"2026-05-10T07:00:00Z\", e.g.\n // Subscription.next_billing_date). For both we want to render the calendar\n // date the API meant, NOT shift it via timezone math — `new Date(...)` +\n // `toLocaleDateString()` would render UTC-midnight calendar dates as the\n // previous day for any user west of UTC. Pull Y/M/D from the front of the\n // string and format in UTC to keep the date stable across timezones.\n try {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(iso);\n if (!match) return iso;\n const y = Number(match[1]);\n const m = Number(match[2]);\n const d = Number(match[3]);\n if (!y || !m || !d) return iso;\n const date = new Date(Date.UTC(y, m - 1, d));\n return date.toLocaleDateString(undefined, {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: \"UTC\",\n });\n } catch {\n return iso;\n }\n}\n\n/**\n * Render the per-cycle subscription bill amount (`price × quantity`).\n *\n * `sub.price` (mapped from the BFF's `total`) is the per-unit price, not the\n * line total — the variant column it ultimately reads from is a plain\n * decimal column, and the detail page also computes `price * quantity` for\n * its bill rows. At qty=1 the multiplication is a no-op so the bug stayed\n * hidden until qty>1 surfaced the mismatch with the detail view.\n */\nexport function formatPrice(sub: subscriptions.SubscriptionListItem): string {\n return (sub.price * (sub.quantity ?? 1)).toFixed(2);\n}\n\n/** Detail-shape counterpart for bundle member rows. */\nexport function formatDetailPrice(\n sub: subscriptions.SubscriptionDetailSubscription,\n): string {\n return (sub.price * (sub.quantity ?? 1)).toFixed(2);\n}\n\nexport interface DetailDiscountLine {\n code: string;\n label: string;\n amountLabel: string;\n}\n\n/**\n * Build the discount line shown beneath a detail subscription's price —\n * the active attached discount's code plus the renewal discount amount.\n * Returns `null` when no active attachment exists or the computed amount\n * is not positive. Mirrors `formatDetailPrice`'s no-symbol formatting:\n * the portal adapter currently sets `currency.symbol` to `null`, so the\n * amount renders bare unless a symbol is actually present.\n */\nexport function detailDiscountLine(\n sub: subscriptions.SubscriptionDetailSubscription,\n t: T,\n): DetailDiscountLine | null {\n const attachment = sub.subscription_discounts?.find(\n (row) => row.removed_at == null,\n );\n const amount = sub.renewal_discount_total ?? 0;\n if (!attachment || amount <= 0) return null;\n\n return {\n code: attachment.discount.code,\n label: t(\"discount\"),\n amountLabel: `-${sub.currency?.symbol ?? \"\"}${amount.toFixed(2)}`,\n };\n}\n\nexport interface CycleProgress {\n /** 0..1 fraction of the cycle that has elapsed. */\n progress: number;\n /** \"Last bill 18 days ago\" — friendly label for the start of the cycle. */\n startLabel: string;\n /** \"Bills in 12 days\" — friendly label for the end of the cycle. */\n endLabel: string;\n}\n\n/**\n * Compute progress through a billing cycle. Returns `null` when either\n * date is missing, unparseable, or `end <= start`. `now` is injectable\n * for tests.\n */\nexport function computeCycleProgress(\n last: string | null,\n next: string | null,\n t: T,\n now: number = Date.now(),\n): CycleProgress | null {\n if (!last || !next) return null;\n const start = new Date(last).getTime();\n const end = new Date(next).getTime();\n if (!Number.isFinite(start) || !Number.isFinite(end) || end <= start) {\n return null;\n }\n const raw = (now - start) / (end - start);\n const progress = Math.max(0, Math.min(1, raw));\n return {\n progress,\n startLabel: friendlyDaysAgo(start, t, now),\n endLabel: friendlyDaysAhead(end, t, now),\n };\n}\n\nexport function friendlyDaysAgo(\n start: number,\n t: T,\n now: number = Date.now(),\n): string {\n const days = Math.max(0, Math.round((now - start) / (1000 * 60 * 60 * 24)));\n if (days === 0) return t(\"list_last_bill_today\");\n if (days === 1) return t(\"list_last_bill_yesterday\");\n return t(\"list_last_bill_n_days_ago\", { n: String(days) });\n}\n\nexport function friendlyDaysAhead(\n end: number,\n t: T,\n now: number = Date.now(),\n): string {\n const days = Math.round((end - now) / (1000 * 60 * 60 * 24));\n if (days < 0)\n return t(\"list_bill_overdue_n_days\", { n: String(Math.abs(days)) });\n if (days === 0) return t(\"list_bills_today\");\n if (days === 1) return t(\"list_bills_tomorrow\");\n return t(\"list_bills_in_n_days\", { n: String(days) });\n}\n","import { type JSX, useMemo, useState } from \"react\";\nimport {\n type subscriptions,\n useInfiniteSubscriptions,\n} from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { ImageOff, Package, Play, Repeat, AlertCircle } from \"lucide-react\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbList,\n BreadcrumbPage,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport { ScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport { MobileBottomSheet } from \"@fluid-app/ui-components/components/MobileBottomSheet\";\nimport {\n type CycleProgress as CycleProgressData,\n type FilterKey,\n type T,\n STATUS_PRIORITY,\n computeCycleProgress,\n countByFilter,\n detailDiscountLine,\n filterPredicate,\n formatCadence,\n formatDetailPrice,\n formatLongDate,\n formatPrice,\n isActiveKind,\n mapStatus,\n pricingSuffix,\n} from \"./portal-subscriptions-list-helpers\";\n\nexport type { FilterKey } from \"./portal-subscriptions-list-helpers\";\n\nconst UNIT_KEYS: Record<string, { singular: string; plural: string }> = {\n day: { singular: \"unit_day\", plural: \"unit_days\" },\n week: { singular: \"unit_week\", plural: \"unit_weeks\" },\n month: { singular: \"unit_month\", plural: \"unit_months\" },\n year: { singular: \"unit_year\", plural: \"unit_years\" },\n};\n\ninterface PortalSubscriptionsListProps {\n customerId: number | undefined;\n isLoadingCustomer?: boolean;\n onSubscriptionClick: (token: string) => void;\n onResume?: (sub: subscriptions.SubscriptionListItem) => void;\n onBundleClick?: () => void;\n bundles?: subscriptions.Bundle[];\n}\n\nconst EMPTY_BUNDLES: subscriptions.Bundle[] = [];\n\nexport function PortalSubscriptionsList({\n customerId,\n isLoadingCustomer,\n onSubscriptionClick,\n onResume,\n onBundleClick,\n bundles = EMPTY_BUNDLES,\n}: PortalSubscriptionsListProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const [filter, setFilter] = useState<FilterKey>(\"all\");\n const {\n data,\n isLoading,\n isError,\n refetch,\n fetchNextPage,\n hasNextPage,\n isFetchingNextPage,\n } = useInfiniteSubscriptions(\n { customerId, limit: 12 },\n { enabled: !!customerId && !isLoadingCustomer },\n );\n\n const list = useMemo(\n () => data?.pages.flatMap((p) => p.subscriptions) ?? [],\n [data],\n );\n const counts = useMemo(() => countByFilter(list), [list]);\n const filteredList = useMemo(\n () => list.filter((s) => filterPredicate(filter, s)),\n [list, filter],\n );\n\n // Real bundles only — singletons (size 1) come back from the bundles\n // endpoint too but they aren't \"bundled\" from the user's perspective.\n const relevantBundles = useMemo(\n () => bundles.filter((b) => b.subscription_count > 1),\n [bundles],\n );\n const bundledTokens = useMemo(() => {\n const tokens = new Set<string>();\n for (const bundle of relevantBundles) {\n for (const sub of bundle.subscriptions) {\n if (sub.subscription_token) tokens.add(sub.subscription_token);\n }\n }\n return tokens;\n }, [relevantBundles]);\n\n // Bundle cards only render in the \"all\" view because a bundle is a\n // billing-time grouping, not a status. Status-filtered views (active /\n // paused / cancelled) show every member sub as an individual card so the\n // filter answer stays direct.\n const showBundleSection = filter === \"all\" && relevantBundles.length > 0;\n\n const { activeSubs, inactiveSubs } = useMemo(() => {\n const sorted = filteredList\n .slice()\n .sort(\n (a, b) =>\n STATUS_PRIORITY[mapStatus(a.status, t).kind] -\n STATUS_PRIORITY[mapStatus(b.status, t).kind],\n );\n const activeCandidates = sorted.filter((s) =>\n isActiveKind(mapStatus(s.status, t).kind),\n );\n return {\n activeSubs: showBundleSection\n ? activeCandidates.filter(\n (s) => !bundledTokens.has(s.subscription_token),\n )\n : activeCandidates,\n inactiveSubs: sorted.filter(\n (s) => !isActiveKind(mapStatus(s.status, t).kind),\n ),\n };\n }, [filteredList, t, showBundleSection, bundledTokens]);\n\n return (\n <>\n <ScreenHeaderBreadcrumbs>\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n {t(\"breadcrumb\")}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n </ScreenHeaderBreadcrumbs>\n <div className=\"relative\">\n <div className=\"relative mx-auto max-w-4xl px-5 pt-8 pb-20 md:px-8\">\n <h1 className=\"text-foreground text-xl font-bold tracking-tight md:text-2xl\">\n {t(\"list_title\")}\n </h1>\n\n {list.length > 0 && (\n <FilterPills\n active={filter}\n counts={counts}\n onChange={setFilter}\n onBundleClick={onBundleClick}\n t={t}\n />\n )}\n\n {isLoading || isLoadingCustomer ? (\n <div className=\"mt-8 grid grid-cols-1 gap-5 md:grid-cols-2\">\n {Array(4)\n .fill(0)\n .map((_, i) => (\n <SubscriptionCardSkeleton key={i} />\n ))}\n </div>\n ) : isError ? (\n <ErrorState onRetry={() => refetch()} t={t} />\n ) : filteredList.length === 0 ? (\n <EmptyState filtered={filter !== \"all\" && list.length > 0} t={t} />\n ) : (\n <>\n {(showBundleSection || activeSubs.length > 0) && (\n // Single grid for bundle cards + regular subscription cards so\n // they share rows. CSS Grid's default `align-items: stretch`\n // makes every cell in the same row match heights, which is\n // what we want — the tallest card in a row sets the row\n // height and the others stretch to match.\n <div className=\"mt-6 grid grid-cols-1 gap-5 md:grid-cols-2\">\n {showBundleSection &&\n relevantBundles.map((bundle, i) => (\n <BundleCard\n key={`bundle-${i}-${bundle.next_bill_date}`}\n bundle={bundle}\n onSubscriptionClick={onSubscriptionClick}\n t={t}\n />\n ))}\n {activeSubs.map((sub) => (\n <SubscriptionCard\n key={sub.id}\n sub={sub}\n onClick={() =>\n onSubscriptionClick(sub.subscription_token)\n }\n onResume={onResume ? () => onResume(sub) : undefined}\n t={t}\n />\n ))}\n </div>\n )}\n\n {inactiveSubs.length > 0 && (\n <div className={activeSubs.length > 0 ? \"mt-10\" : \"mt-6\"}>\n <div className=\"text-muted-foreground mb-2 px-1 text-xs font-semibold\">\n {t(\"list_cancelled_section_label\", {\n n: String(inactiveSubs.length),\n })}\n </div>\n <div className=\"space-y-3\">\n {inactiveSubs.map((sub) => (\n <InactiveSubscriptionRow\n key={sub.id}\n sub={sub}\n onClick={() =>\n onSubscriptionClick(sub.subscription_token)\n }\n t={t}\n />\n ))}\n </div>\n </div>\n )}\n </>\n )}\n\n {hasNextPage && (\n <div className=\"mt-6 flex justify-center\">\n <button\n type=\"button\"\n onClick={() => fetchNextPage()}\n disabled={isFetchingNextPage}\n className=\"ring-border text-foreground hover:bg-muted inline-flex items-center gap-1 rounded-md bg-transparent px-3 py-1.5 text-xs font-bold ring-1 transition-all disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {isFetchingNextPage ? t(\"list_loading\") : t(\"list_load_more\")}\n </button>\n </div>\n )}\n </div>\n </div>\n </>\n );\n}\n\n// ─── Filter pills ─────────────────────────────────────────────────────────\n\nconst FILTER_KEYS: ReadonlyArray<{\n key: FilterKey;\n labelKey: \"all\" | \"active\" | \"list_filter_paused\" | \"list_filter_cancelled\";\n}> = [\n { key: \"all\", labelKey: \"all\" },\n { key: \"active\", labelKey: \"active\" },\n { key: \"paused\", labelKey: \"list_filter_paused\" },\n { key: \"cancelled\", labelKey: \"list_filter_cancelled\" },\n];\n\nfunction FilterPills({\n active,\n counts,\n onChange,\n onBundleClick,\n t,\n}: {\n active: FilterKey;\n counts: Record<FilterKey, number>;\n onChange: (k: FilterKey) => void;\n onBundleClick?: () => void;\n t: T;\n}): JSX.Element {\n return (\n <div className=\"-mx-1 mt-5 flex flex-wrap items-center gap-1.5 px-1\">\n {FILTER_KEYS.map((f) => {\n const isActive = f.key === active;\n const count = counts[f.key];\n return (\n <button\n key={f.key}\n type=\"button\"\n onClick={() => onChange(f.key)}\n className={`inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-bold transition-all ${\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"ring-border text-foreground hover:bg-muted bg-transparent ring-1\"\n }`}\n >\n {t(f.labelKey)}\n <span\n className={`text-xs tabular-nums ${\n isActive\n ? \"text-primary-foreground/70\"\n : \"text-muted-foreground\"\n }`}\n >\n {count}\n </span>\n </button>\n );\n })}\n {/* Bundling requires at least 2 subscriptions to merge — hide the\n button when the user has zero or one so they can't reach a step 1\n where the Next button is permanently disabled. Also hide when the\n tenant company has bundling disabled (the screen passes\n onBundleClick=undefined in that case). */}\n {counts.all >= 2 && onBundleClick && (\n <button\n type=\"button\"\n onClick={onBundleClick}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 ml-auto inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-bold transition-all\"\n >\n {t(\"list_bundle_cta\")}\n </button>\n )}\n </div>\n );\n}\n\n// ─── Bundle card ───────────────────────────────────────────────────────────\n// Renders a runtime bundle (a customer + address + bill date grouping) as a\n// single card containing each member subscription as a clickable row plus a\n// shared bill summary (date + summed amount). Members navigate to their\n// individual detail screens — bundle-level edit is a future affordance.\n\n// Cap inline member rows so every bundle card has the same height regardless\n// of how many subscriptions are in the bundle. Overflow lives behind a\n// \"+N more\" popover anchored to the card.\nconst BUNDLE_INLINE_LIMIT = 2;\n\nfunction BundleCard({\n bundle,\n onSubscriptionClick,\n t,\n}: {\n bundle: subscriptions.Bundle;\n onSubscriptionClick: (token: string) => void;\n t: T;\n}): JSX.Element {\n const [popoverOpen, setPopoverOpen] = useState(false);\n const { isMobile } = useSidebar();\n const total = bundle.subscriptions.reduce(\n (sum, s) => sum + s.price * (s.quantity ?? 1),\n 0,\n );\n const nextBillLong = bundle.next_bill_date\n ? formatLongDate(bundle.next_bill_date)\n : null;\n\n const inlineMembers = bundle.subscriptions.slice(0, BUNDLE_INLINE_LIMIT);\n const overflowCount = bundle.subscriptions.length - inlineMembers.length;\n\n const handleMemberClick = (token: string) => {\n onSubscriptionClick(token);\n setPopoverOpen(false);\n };\n\n return (\n <div className=\"ring-border hover:ring-foreground/10 relative flex flex-col gap-4 rounded-2xl bg-transparent p-5 shadow-sm ring-1 transition-all duration-300 hover:shadow-lg\">\n {/* Bundle header */}\n <div className=\"flex items-center gap-2\">\n <div className=\"bg-muted flex size-7 items-center justify-center rounded-full\">\n <Package className=\"text-foreground size-4\" strokeWidth={2} />\n </div>\n <div className=\"text-foreground text-xs font-bold\">\n {t(\"list_bundle_card_label\", {\n n: String(bundle.subscription_count),\n })}\n </div>\n </div>\n\n {/* Inline member rows (capped) */}\n <div className=\"flex flex-col\">\n {inlineMembers.map((sub) => (\n <BundleMemberRow\n key={sub.subscription_token}\n sub={sub}\n onClick={() => handleMemberClick(sub.subscription_token)}\n t={t}\n />\n ))}\n\n {overflowCount > 0 &&\n (isMobile ? (\n <>\n <button\n type=\"button\"\n onClick={() => setPopoverOpen(true)}\n className=\"text-muted-foreground hover:text-foreground focus-visible:ring-foreground/30 mt-1 inline-flex w-fit cursor-pointer items-center rounded-md px-2 py-1 text-xs font-bold transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n >\n {t(\"list_bundle_more_count\", { n: String(overflowCount) })}\n </button>\n <MobileBottomSheet\n open={popoverOpen}\n onOpenChange={setPopoverOpen}\n title={t(\"list_bundle_members_title\")}\n >\n <div className=\"flex flex-col px-2\">\n {bundle.subscriptions.map((sub) => (\n <BundleMemberRow\n key={sub.subscription_token}\n sub={sub}\n onClick={() => handleMemberClick(sub.subscription_token)}\n t={t}\n />\n ))}\n </div>\n </MobileBottomSheet>\n </>\n ) : (\n <Popover open={popoverOpen} onOpenChange={setPopoverOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground focus-visible:ring-foreground/30 mt-1 inline-flex w-fit cursor-pointer items-center rounded-md px-2 py-1 text-xs font-bold transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n >\n {t(\"list_bundle_more_count\", { n: String(overflowCount) })}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"bg-background ring-border w-80 rounded-2xl p-3 shadow-lg ring-1\"\n >\n <div className=\"text-muted-foreground px-2 pt-1 pb-2 text-xs font-bold uppercase\">\n {t(\"list_bundle_members_title\")}\n </div>\n <div className=\"flex max-h-80 flex-col overflow-y-auto\">\n {bundle.subscriptions.map((sub) => (\n <BundleMemberRow\n key={sub.subscription_token}\n sub={sub}\n onClick={() => handleMemberClick(sub.subscription_token)}\n t={t}\n />\n ))}\n </div>\n </PopoverContent>\n </Popover>\n ))}\n </div>\n\n {/* Shared bill summary — pushed to the bottom so the card height\n can stretch (auto-rows-fr) without the summary floating mid-card. */}\n <div className=\"bg-muted mt-auto rounded-xl px-4 py-3.5\">\n <div className=\"text-foreground text-sm font-bold\">\n {t(\"list_next_bill_label\")}\n </div>\n <div className=\"mt-3 grid grid-cols-2\">\n <div className=\"pr-4\">\n <div className=\"text-muted-foreground text-xs\">\n {t(\"list_bill_date\")}\n </div>\n <div className=\"text-foreground mt-1 text-base font-bold tracking-tight tabular-nums\">\n {nextBillLong ?? \"—\"}\n </div>\n </div>\n <div className=\"border-border border-l pl-4\">\n <div className=\"text-muted-foreground text-xs\">\n {t(\"list_bill_amount\")}\n </div>\n <div className=\"text-foreground mt-1 text-base font-bold tracking-tight tabular-nums\">\n {total.toFixed(2)}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction BundleMemberRow({\n sub,\n onClick,\n t,\n}: {\n sub: subscriptions.SubscriptionDetailSubscription;\n onClick: () => void;\n t: T;\n}): JSX.Element {\n const discountLine = detailDiscountLine(sub, t);\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"hover:bg-muted/60 focus-visible:ring-foreground/30 -mx-2 flex cursor-pointer items-center gap-3 rounded-lg p-2 text-left transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n >\n <div className=\"relative size-12 shrink-0\">\n {sub.variant.product.image_url ? (\n <img\n src={sub.variant.product.image_url}\n alt=\"\"\n className=\"ring-background size-12 rounded-lg bg-transparent object-cover ring-2\"\n />\n ) : (\n <div className=\"bg-muted ring-background text-muted-foreground flex size-12 items-center justify-center rounded-lg ring-2\">\n <ImageOff className=\"size-4\" strokeWidth={1.75} />\n </div>\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-foreground truncate text-xs font-bold\">\n {sub.variant.product.title || t(\"list_product_fallback\")}\n </div>\n <div className=\"text-muted-foreground truncate text-xs\">\n {bundleMemberCadence(sub.subscription_plan, t)}\n </div>\n </div>\n <div className=\"shrink-0 text-right\">\n <div className=\"text-foreground text-xs font-bold tabular-nums\">\n {formatDetailPrice(sub)}\n </div>\n {discountLine && (\n <div className=\"text-muted-foreground text-xs tabular-nums\">\n <span className=\"sr-only\">{discountLine.label} </span>\n {discountLine.code} {discountLine.amountLabel}\n </div>\n )}\n </div>\n </button>\n );\n}\n\n// `formatCadence` types its input to SubscriptionListPlan; bundle members are\n// SubscriptionDetailPlan which carries the same billing_interval fields.\n// Avoid an unsafe cast by re-implementing the small subset we need.\nfunction bundleMemberCadence(\n plan: { billing_interval: number; billing_interval_unit: string },\n t: T,\n): string {\n const { billing_interval: interval, billing_interval_unit: unit } = plan;\n if (interval === 1 && unit === \"day\") return t(\"list_cadence_daily\");\n if (interval === 1 && unit === \"month\") return t(\"list_cadence_monthly\");\n if (interval === 1 && unit === \"week\") return t(\"list_cadence_weekly\");\n if (interval === 1 && unit === \"year\") return t(\"list_cadence_yearly\");\n if (interval === 3 && unit === \"month\") return t(\"list_cadence_quarterly\");\n if (interval > 1) {\n const keys = UNIT_KEYS[unit.toLowerCase()];\n return t(\"list_cadence_every_n_units\", {\n n: String(interval),\n unit: keys ? t(keys.plural as \"unit_days\") : unit,\n });\n }\n const keys = UNIT_KEYS[unit.toLowerCase()];\n return t(\"list_cadence_every_unit\", {\n unit: keys ? t(keys.singular as \"unit_day\") : unit,\n });\n}\n\n// ─── Card ──────────────────────────────────────────────────────────────────\n\nfunction SubscriptionCard({\n sub,\n onClick,\n onResume,\n t,\n}: {\n sub: subscriptions.SubscriptionListItem;\n onClick: () => void;\n onResume?: () => void;\n t: T;\n}): JSX.Element {\n const status = mapStatus(sub.status, t);\n const isPaused = status.kind === \"paused\";\n const isCancelled = status.kind === \"cancelled\";\n const isPastDue = status.kind === \"past_due\";\n const cadence = formatCadence(sub.subscription_plan, t);\n const nextBillLong = sub.next_bill_date\n ? formatLongDate(sub.next_bill_date)\n : null;\n const lastBillLong = sub.last_bill_date\n ? formatLongDate(sub.last_bill_date)\n : null;\n const daysOverdue =\n isPastDue && sub.next_bill_date\n ? Math.max(\n 0,\n Math.round(\n (Date.now() - new Date(sub.next_bill_date).getTime()) /\n (1000 * 60 * 60 * 24),\n ),\n )\n : 0;\n const cycle = computeCycleProgress(sub.last_bill_date, sub.next_bill_date, t);\n const showCycle = cycle != null && !isPaused && !isCancelled && !isPastDue;\n\n return (\n <div\n className={`group has-[:focus-visible]:ring-foreground/30 relative flex flex-col gap-5 rounded-2xl p-5 ring-1 transition-all duration-300 hover:-translate-y-0.5 has-[:focus-visible]:ring-2 ${\n isPastDue\n ? \"from-destructive/10 via-destructive/[0.03] ring-destructive/15 hover:ring-destructive/30 bg-transparent bg-gradient-to-br to-transparent shadow-sm hover:shadow-lg\"\n : \"ring-foreground/5 hover:ring-foreground/10 bg-transparent shadow-sm hover:shadow-lg\"\n } ${isPaused || isCancelled ? \"opacity-90\" : \"\"}`}\n >\n <button\n type=\"button\"\n onClick={onClick}\n className=\"flex flex-1 cursor-pointer flex-col gap-5 text-left focus:outline-none\"\n >\n {/* Top: image + title */}\n <div className=\"flex items-start gap-4\">\n <Thumbnail\n product={sub.variant.product}\n muted={isPaused || isCancelled}\n t={t}\n />\n <div className=\"min-w-0 flex-1 pt-1\">\n <div className=\"text-foreground truncate text-base font-bold\">\n {sub.variant.product.title || t(\"list_product_fallback\")}\n </div>\n <div className=\"text-muted-foreground mt-0.5 text-sm\">\n {cadence}\n </div>\n {(isPaused || isCancelled || isPastDue) && (\n <div\n className={`mt-2 inline-flex items-center gap-1.5 text-xs font-semibold ${\n isPastDue ? \"text-destructive\" : \"text-muted-foreground/75\"\n }`}\n >\n <span\n className={`size-1.5 rounded-full ${\n isCancelled || isPastDue\n ? \"bg-destructive\"\n : \"bg-muted-foreground\"\n }`}\n />\n {status.label}\n </div>\n )}\n </div>\n </div>\n\n {/* Bill summary pinned to the bottom of the click area via mt-auto\n so when the card stretches (e.g. when a bundle in the same grid\n row is taller), empty space grows between the title and summary\n instead of below them. */}\n {isCancelled ? (\n <div className=\"bg-muted text-muted-foreground mt-auto rounded-xl px-4 py-3 text-sm font-semibold\">\n {status.label}\n </div>\n ) : (\n <div className=\"bg-muted mt-auto rounded-xl px-4 py-3.5\">\n <div\n className={`text-sm font-bold ${isPastDue ? \"text-destructive\" : \"text-foreground\"}`}\n >\n {isPastDue\n ? daysOverdue === 1\n ? t(\"list_bill_due_1_day_ago\")\n : daysOverdue > 0\n ? t(\"list_bill_due_n_days_ago\", {\n n: String(daysOverdue),\n })\n : t(\"list_bill_overdue\")\n : isPaused\n ? t(\"list_last_bill_label\")\n : t(\"list_next_bill_label\")}\n </div>\n <div className=\"mt-3 grid grid-cols-2\">\n <div className=\"pr-4\">\n <div className=\"text-muted-foreground text-xs\">\n {isPaused ? t(\"list_last_bill_date\") : t(\"list_bill_date\")}\n </div>\n <div\n className={`mt-1 text-base font-bold tracking-tight tabular-nums ${isPastDue ? \"text-destructive\" : \"text-foreground\"}`}\n >\n {(isPaused ? lastBillLong : nextBillLong) ?? \"—\"}\n </div>\n </div>\n <div className=\"border-border border-l pl-4\">\n <div className=\"text-muted-foreground text-xs\">\n {isPaused\n ? t(\"list_last_bill_amount\")\n : t(\"list_bill_amount\")}\n </div>\n <div className=\"text-foreground mt-1 text-base font-bold tracking-tight tabular-nums\">\n {formatPrice(sub)}\n </div>\n <div className=\"text-muted-foreground text-xs\">\n {pricingSuffix(sub.subscription_plan, t)}\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Cycle progress bar */}\n {showCycle && cycle && <CycleProgress cycle={cycle} />}\n </button>\n\n {/* Resume CTA */}\n {isPaused && (\n <button\n type=\"button\"\n onClick={onResume}\n disabled={!onResume}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 inline-flex w-full items-center justify-center gap-1.5 rounded-md py-2.5 text-xs font-bold transition-colors focus:outline-none disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Play className=\"size-3 fill-current\" strokeWidth={2.25} />\n {t(\"list_resume_cta\")}\n </button>\n )}\n </div>\n );\n}\n\n// ─── Cycle progress ───────────────────────────────────────────────────────\n\nfunction CycleProgress({ cycle }: { cycle: CycleProgressData }): JSX.Element {\n const pct = Math.round(cycle.progress * 100);\n return (\n <div>\n <div className=\"bg-muted relative h-1.5 overflow-hidden rounded-full\">\n <div\n className=\"bg-foreground absolute top-0 left-0 h-full rounded-full transition-all duration-500\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <div className=\"text-muted-foreground mt-2 flex items-center justify-between text-xs font-medium\">\n <span>{cycle.startLabel}</span>\n <span>{cycle.endLabel}</span>\n </div>\n </div>\n );\n}\n\n// ─── Inactive (condensed) row ─────────────────────────────────────────────\n\nfunction InactiveSubscriptionRow({\n sub,\n onClick,\n t,\n}: {\n sub: subscriptions.SubscriptionListItem;\n onClick: () => void;\n t: T;\n}): JSX.Element {\n const status = mapStatus(sub.status, t);\n const cadence = formatCadence(sub.subscription_plan, t);\n const detail = `${cadence} · ${status.label}`;\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"group ring-foreground/5 hover:ring-foreground/10 focus-visible:ring-foreground/30 flex w-full cursor-pointer items-center gap-3 rounded-2xl bg-transparent px-4 py-3 text-left shadow-sm ring-1 transition-all duration-300 hover:-translate-y-0.5 hover:shadow-lg focus-visible:ring-2 focus-visible:outline-none\"\n >\n <div className=\"relative size-10 shrink-0 opacity-60 saturate-50\">\n {sub.variant.product.image_url ? (\n <img\n src={sub.variant.product.image_url}\n alt=\"\"\n className=\"ring-background size-10 rounded-xl bg-transparent object-cover ring-[3px]\"\n />\n ) : (\n <div className=\"bg-muted ring-background text-muted-foreground flex size-10 items-center justify-center rounded-xl ring-[3px]\">\n <ImageOff className=\"size-4\" strokeWidth={1.75} />\n </div>\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-foreground truncate text-sm font-bold\">\n {sub.variant.product.title || t(\"list_product_fallback\")}\n </div>\n <div className=\"text-muted-foreground truncate text-xs\">{detail}</div>\n </div>\n </button>\n );\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\nfunction Thumbnail({\n product,\n muted,\n t,\n}: {\n product: subscriptions.SubscriptionListVariantProduct;\n muted?: boolean;\n t: T;\n}): JSX.Element {\n const wrapperClass = `relative size-24 shrink-0 transition-all ${muted ? \"saturate-50 opacity-60\" : \"\"}`;\n const imgClass =\n \"bg-transparent ring-background size-24 rounded-2xl object-cover ring-[3px] shadow-sm\";\n return (\n <div className={wrapperClass}>\n {product.image_url ? (\n <img src={product.image_url} alt=\"\" className={imgClass} />\n ) : (\n <div className=\"bg-muted ring-background text-muted-foreground flex size-24 items-center justify-center rounded-2xl shadow-sm ring-[3px]\">\n <ImageOff className=\"size-7\" strokeWidth={1.75} />\n </div>\n )}\n <div\n className=\"bg-primary text-primary-foreground ring-background absolute -top-1 -right-1 z-40 flex size-6 items-center justify-center rounded-full ring-2\"\n title={t(\"list_recurring_badge\")}\n >\n <Repeat className=\"size-3\" strokeWidth={2.75} />\n </div>\n </div>\n );\n}\n\n// ─── Empty / loading ───────────────────────────────────────────────────────\n\nfunction SubscriptionCardSkeleton(): JSX.Element {\n return (\n <div className=\"ring-border flex flex-col gap-5 rounded-2xl bg-transparent p-5 ring-1\">\n <div className=\"flex items-start gap-4\">\n <div className=\"bg-muted size-20 shrink-0 animate-pulse rounded-2xl\" />\n <div className=\"flex-1 space-y-2 pt-1\">\n <div className=\"bg-muted h-5 w-2/3 animate-pulse rounded\" />\n <div className=\"bg-muted h-4 w-1/2 animate-pulse rounded\" />\n </div>\n </div>\n <div className=\"bg-muted h-12 animate-pulse rounded\" />\n <div className=\"bg-muted h-6 animate-pulse rounded\" />\n </div>\n );\n}\n\nfunction EmptyState({\n filtered,\n t,\n}: {\n filtered?: boolean;\n t: T;\n}): JSX.Element {\n return (\n <div className=\"ring-border mx-auto mt-12 flex max-w-md flex-col items-center gap-2 rounded-2xl bg-transparent px-6 py-12 text-center ring-1\">\n <div className=\"text-foreground text-sm font-bold\">\n {filtered ? t(\"list_no_in_view\") : t(\"list_none_yet\")}\n </div>\n <div className=\"text-muted-foreground text-xs\">\n {filtered ? t(\"list_filtered_hint\") : t(\"list_empty_hint\")}\n </div>\n </div>\n );\n}\n\nfunction ErrorState({\n onRetry,\n t,\n}: {\n onRetry: () => void;\n t: T;\n}): JSX.Element {\n return (\n <div className=\"ring-border mx-auto mt-12 flex max-w-md flex-col items-center gap-2 rounded-2xl bg-transparent px-6 py-12 text-center ring-1\">\n <div className=\"bg-muted flex size-12 items-center justify-center rounded-full\">\n <AlertCircle className=\"text-muted-foreground size-5\" strokeWidth={2} />\n </div>\n <div className=\"text-foreground text-sm font-bold\">\n {t(\"list_load_failed_title\")}\n </div>\n <div className=\"text-muted-foreground text-xs\">\n {t(\"list_load_failed_hint\")}\n </div>\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 mt-2 inline-flex items-center gap-1 rounded-md px-3 py-1.5 text-xs font-bold transition-all\"\n >\n {t(\"list_try_again\")}\n </button>\n </div>\n );\n}\n","import type { fluidPay } from \"@fluid-app/fluid-pay-core\";\n\n/**\n * Mirrors fluid-checkout's `isPaymentMethodUsable`. A payment method is only\n * eligible for bundle attachment when it has a complete billing address.\n *\n * Note: the portal's `fluidPay.CustomerPaymentMethod` does not surface the\n * checkout-only `au_status` field, so we only check billing-address completeness.\n */\nexport function isPaymentMethodUsable(\n pm: fluidPay.CustomerPaymentMethod,\n): boolean {\n const addr = pm.billing_address;\n if (!addr) return false;\n return Boolean(\n addr.address1 && addr.city && addr.state && addr.zip && addr.country_code,\n );\n}\n","/**\n * Selectable range for the bundle bill-date picker: today at the bottom, the\n * bundle's edit cap at the top (2 years out for yearly cadences, 12 months for\n * everything else — see `getMaxEditableBillDate`). The API enforces the same\n * cap, so a date past it comes back as a 422 after the address and payment\n * steps rather than at the picker.\n *\n * Both ends are read in local time. `getMaxEditableBillDate` builds the cap\n * from local-midnight setters, so reading the floor in UTC would let the two\n * ends disagree by a day at large offsets.\n *\n * The predicates live here rather than in `DrawerStepDate` because the picker's\n * disabled state and `useBundleForm`'s cascade-clearing have to agree: a day\n * left selected but disabled looks pickable while Next silently refuses.\n */\nexport interface BillDateBounds {\n /** Earliest selectable date. */\n today: Date;\n /** Latest selectable date, i.e. the bundle's cap. */\n maxDate: Date;\n}\n\nexport function getDaysInMonth(year: number, month: number): number {\n return new Date(year, month + 1, 0).getDate();\n}\n\nexport function isYearOutOfRange(\n year: number,\n { today, maxDate }: BillDateBounds,\n): boolean {\n return year < today.getFullYear() || year > maxDate.getFullYear();\n}\n\nexport function isMonthOutOfRange(\n year: number,\n month: number,\n bounds: BillDateBounds,\n): boolean {\n const { today, maxDate } = bounds;\n if (isYearOutOfRange(year, bounds)) return true;\n if (year === maxDate.getFullYear() && month > maxDate.getMonth()) return true;\n if (year > today.getFullYear()) return false;\n return month < today.getMonth();\n}\n\nexport function isDayOutOfRange(\n year: number,\n month: number,\n day: number,\n bounds: BillDateBounds,\n): boolean {\n const { today, maxDate } = bounds;\n if (day > getDaysInMonth(year, month)) return true;\n if (isMonthOutOfRange(year, month, bounds)) return true;\n if (\n year === maxDate.getFullYear() &&\n month === maxDate.getMonth() &&\n day > maxDate.getDate()\n ) {\n return true;\n }\n if (year > today.getFullYear()) return false;\n if (month > today.getMonth()) return false;\n return day < today.getDate();\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { getMaxEditableBillDateForBundle } from \"@fluid-app/subscriptions-core/utils/subscription-helpers\";\nimport { isPaymentMethodUsable } from \"./payment-utils\";\nimport {\n isDayOutOfRange,\n isMonthOutOfRange,\n type BillDateBounds,\n} from \"./bill-date-bounds\";\nimport type { Step } from \"./types\";\n\ninterface UseBundleFormArgs {\n subscriptions: subscriptions.SubscriptionListItem[];\n addresses: fluidPay.CustomerAddress[];\n paymentMethods: fluidPay.CustomerPaymentMethod[];\n defaultAddressId?: number | null;\n defaultPaymentMethodId?: number | null;\n}\n\nexport interface BundleForm {\n step: Step;\n setStep: (s: Step) => void;\n selectedTokens: Set<string>;\n toggleToken: (token: string) => void;\n\n selectedYear: number;\n selectedMonth: number | null;\n selectedDay: number | null;\n setYear: (y: number) => void;\n setMonth: (m: number) => void;\n setDay: (d: number) => void;\n\n selectedAddressId: number | null;\n setSelectedAddressId: (id: number | null) => void;\n\n selectedPaymentMethodId: number | null;\n setSelectedPaymentMethodId: (id: number | null) => void;\n\n /** Selectable date range for the picker, driven by the bundle's cap. */\n bounds: BillDateBounds;\n\n canProceedFromStep1: boolean;\n canProceedFromStep2: boolean;\n canProceedFromStep3: boolean;\n canProceedFromStep4: boolean;\n\n /** \"YYYY-MM-DD\" or null when month/day not yet selected. */\n formattedDate: string | null;\n}\n\nfunction pickDefaultAddressId(\n addresses: fluidPay.CustomerAddress[],\n defaultAddressId: number | null | undefined,\n): number | null {\n if (defaultAddressId != null) {\n const match = addresses.find((a) => a.id === defaultAddressId);\n if (match) return match.id;\n }\n const flagged = addresses.find((a) => a.default);\n if (flagged) return flagged.id;\n return addresses[0]?.id ?? null;\n}\n\nfunction pickDefaultPaymentMethodId(\n paymentMethods: fluidPay.CustomerPaymentMethod[],\n defaultPaymentMethodId: number | null | undefined,\n): number | null {\n const usable = paymentMethods.filter(isPaymentMethodUsable);\n if (defaultPaymentMethodId != null) {\n const match = usable.find((pm) => pm.id === defaultPaymentMethodId);\n if (match) return match.id;\n }\n const flagged = usable.find((pm) => pm.default);\n if (flagged) return flagged.id;\n return usable[0]?.id ?? null;\n}\n\nexport function useBundleForm({\n subscriptions: subscriptionList,\n addresses,\n paymentMethods,\n defaultAddressId,\n defaultPaymentMethodId,\n}: UseBundleFormArgs): BundleForm {\n const [step, setStep] = useState<Step>(1);\n const [selectedTokens, setSelectedTokens] = useState<Set<string>>(\n () => new Set(),\n );\n const today = useMemo(() => new Date(), []);\n const [selectedYear, setYearState] = useState<number>(today.getFullYear());\n const [selectedMonth, setMonthState] = useState<number | null>(null);\n const [selectedDay, setDayState] = useState<number | null>(null);\n const [selectedAddressId, setSelectedAddressId] = useState<number | null>(\n () => pickDefaultAddressId(addresses, defaultAddressId),\n );\n const [selectedPaymentMethodId, setSelectedPaymentMethodId] = useState<\n number | null\n >(() => pickDefaultPaymentMethodId(paymentMethods, defaultPaymentMethodId));\n\n // When the user opens the drawer with an empty address book, then adds an\n // address inline (AddressFormDialog → query invalidates → `addresses` prop\n // refreshes), auto-select the new address so step 3's Next button enables\n // without requiring a manual tap. The lazy useState initializer above only\n // runs once at mount and would otherwise leave `selectedAddressId === null`\n // forever. Mirror logic for payment methods.\n useEffect(() => {\n if (selectedAddressId == null && addresses.length > 0) {\n setSelectedAddressId(pickDefaultAddressId(addresses, defaultAddressId));\n }\n }, [selectedAddressId, addresses, defaultAddressId]);\n\n useEffect(() => {\n if (\n selectedPaymentMethodId == null &&\n paymentMethods.some(isPaymentMethodUsable)\n ) {\n setSelectedPaymentMethodId(\n pickDefaultPaymentMethodId(paymentMethods, defaultPaymentMethodId),\n );\n }\n }, [selectedPaymentMethodId, paymentMethods, defaultPaymentMethodId]);\n\n const toggleToken = useCallback((token: string) => {\n setSelectedTokens((prev) => {\n const next = new Set(prev);\n if (next.has(token)) next.delete(token);\n else next.add(token);\n return next;\n });\n }, []);\n\n // Every selected subscription moves to one shared bill date, so the bundle\n // answers to its strictest member's cap: a single monthly member holds the\n // whole bundle to 12 months even when the rest are yearly. Walk the selected\n // tokens rather than filtering the list, so a token whose subscription isn't\n // in the loaded page counts as unknown cadence (12 months, fail closed)\n // instead of dropping out of the bound entirely.\n const bounds = useMemo<BillDateBounds>(() => {\n const members = Array.from(selectedTokens).map((token) => {\n const plan = subscriptionList.find(\n (sub) => sub.subscription_token === token,\n )?.subscription_plan;\n return {\n billingInterval: plan?.billing_interval,\n billingIntervalUnit: plan?.billing_interval_unit,\n };\n });\n return { today, maxDate: getMaxEditableBillDateForBundle(members, today) };\n }, [selectedTokens, subscriptionList, today]);\n\n // Cascade-clear month/day when year changes if month/day become invalid.\n const setYear = useCallback(\n (y: number) => {\n setYearState(y);\n if (selectedMonth == null) return;\n // Out of range covers both ends: a month before today and a month past\n // the bundle's cap (switching from 2027 to 2028 on a monthly bundle).\n if (isMonthOutOfRange(y, selectedMonth, bounds)) {\n setMonthState(null);\n setDayState(null);\n return;\n }\n // Same-month edge case: switching back to the current year while a day\n // from the current month is selected can leave the day in the past (e.g.\n // selectedDay=3 when today=May 7). Clear the day in that case so the\n // user doesn't unknowingly submit a past date and trip the BFF's\n // `next_bill_date_in_past` validator. The cap end works the same way.\n if (\n selectedDay != null &&\n isDayOutOfRange(y, selectedMonth, selectedDay, bounds)\n ) {\n setDayState(null);\n }\n },\n [selectedMonth, selectedDay, bounds],\n );\n\n // Clear the day when the month changes and the day no longer fits the range.\n // `isDayOutOfRange` starts with the days-in-month check, so one call covers\n // a short month (Jan 31 → Feb), a past-dated day (today is May 7; the user\n // picked July 3, then switched back to May — 3 fits in May but is past, and\n // would submit as a past date with no inline explanation) and a day beyond\n // the cap (switching into the capped month with a later day selected).\n const setMonth = useCallback(\n (m: number) => {\n setMonthState(m);\n if (\n selectedDay != null &&\n isDayOutOfRange(selectedYear, m, selectedDay, bounds)\n ) {\n setDayState(null);\n }\n },\n [selectedDay, selectedYear, bounds],\n );\n\n const setDay = useCallback((d: number) => setDayState(d), []);\n\n const canProceedFromStep1 = selectedTokens.size >= 2;\n // The picker disables out-of-range dates, but the cap itself moves: picking a\n // date on step 2 and then adding a monthly member back on step 1 tightens the\n // bundle from 2 years to 12 months and can leave the stored selection outside\n // the new bound. Re-check it here so Next blocks instead of the API 422ing\n // three steps later.\n const selectedDateOutOfRange =\n selectedMonth !== null &&\n selectedDay !== null &&\n isDayOutOfRange(selectedYear, selectedMonth, selectedDay, bounds);\n const canProceedFromStep2 =\n selectedMonth !== null && selectedDay !== null && !selectedDateOutOfRange;\n const canProceedFromStep3 = selectedAddressId != null;\n const canProceedFromStep4 = selectedPaymentMethodId != null;\n\n const formattedDate = useMemo(() => {\n if (selectedMonth == null || selectedDay == null) return null;\n const mm = String(selectedMonth + 1).padStart(2, \"0\");\n const dd = String(selectedDay).padStart(2, \"0\");\n return `${selectedYear}-${mm}-${dd}`;\n }, [selectedYear, selectedMonth, selectedDay]);\n\n return {\n step,\n setStep,\n selectedTokens,\n toggleToken,\n selectedYear,\n selectedMonth,\n selectedDay,\n setYear,\n setMonth,\n setDay,\n selectedAddressId,\n setSelectedAddressId,\n selectedPaymentMethodId,\n setSelectedPaymentMethodId,\n bounds,\n canProceedFromStep1,\n canProceedFromStep2,\n canProceedFromStep3,\n canProceedFromStep4,\n formattedDate,\n };\n}\n","import type { JSX } from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport type { Step } from \"./types\";\n\ninterface DrawerStepTabsProps {\n step: Step;\n onStepClick: (step: Step) => void;\n canProceedFromStep1: boolean;\n canProceedFromStep2: boolean;\n canProceedFromStep3: boolean;\n}\n\ntype TabLabelKey =\n | \"bundle_step_select\"\n | \"bundle_step_date\"\n | \"bundle_step_address\"\n | \"bundle_step_payment\";\n\nconst TABS: ReadonlyArray<{ id: Step; labelKey: TabLabelKey }> = [\n { id: 1, labelKey: \"bundle_step_select\" },\n { id: 2, labelKey: \"bundle_step_date\" },\n { id: 3, labelKey: \"bundle_step_address\" },\n { id: 4, labelKey: \"bundle_step_payment\" },\n];\n\nconst PROGRESS_BY_STEP: Record<Step, string> = {\n 1: \"0%\",\n 2: \"33%\",\n 3: \"66%\",\n 4: \"100%\",\n};\n\ntype StepMessageKey =\n | \"bundle_step1_message\"\n | \"bundle_step2_message\"\n | \"bundle_step3_message\"\n | \"bundle_step4_message\";\n\nexport function DrawerStepTabs({\n step,\n onStepClick,\n canProceedFromStep1,\n canProceedFromStep2,\n canProceedFromStep3,\n}: DrawerStepTabsProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n\n const handleClick = (target: Step) => {\n if (target < step) {\n onStepClick(target);\n } else if (target === 2 && canProceedFromStep1) {\n onStepClick(2);\n } else if (target === 3 && canProceedFromStep1 && canProceedFromStep2) {\n onStepClick(3);\n } else if (\n target === 4 &&\n canProceedFromStep1 &&\n canProceedFromStep2 &&\n canProceedFromStep3\n ) {\n onStepClick(4);\n }\n };\n\n const messageKey: StepMessageKey =\n step === 1\n ? \"bundle_step1_message\"\n : step === 2\n ? \"bundle_step2_message\"\n : step === 3\n ? \"bundle_step3_message\"\n : \"bundle_step4_message\";\n\n return (\n <div className=\"px-6 pt-4\">\n <div className=\"mb-2 flex items-center justify-between\">\n {TABS.map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => handleClick(tab.id)}\n className={`text-xs font-bold transition-colors ${\n step === tab.id\n ? \"text-foreground\"\n : step > tab.id\n ? \"text-muted-foreground cursor-pointer\"\n : \"text-muted-foreground/75\"\n }`}\n >\n {t(tab.labelKey)}\n </button>\n ))}\n </div>\n\n <div className=\"bg-muted relative h-1 rounded-full\">\n <div\n className=\"bg-primary absolute h-1 rounded-full transition-all duration-300\"\n style={{ width: PROGRESS_BY_STEP[step] }}\n />\n {TABS.map((tab, index) => (\n <div\n key={tab.id}\n className={`absolute top-1/2 size-3 rounded-full transition-colors ${\n step >= tab.id ? \"bg-primary\" : \"bg-muted ring-border ring-1\"\n }`}\n style={\n index === 0\n ? { left: 0, transform: \"translateY(-50%)\" }\n : index === TABS.length - 1\n ? { right: 0, transform: \"translateY(-50%)\" }\n : {\n left: `${(index / (TABS.length - 1)) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n }\n }\n />\n ))}\n </div>\n\n <div className=\"text-muted-foreground mt-3 flex items-center justify-center text-xs\">\n <span>{t(messageKey)}</span>\n </div>\n </div>\n );\n}\n","import type { JSX } from \"react\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { Check, Package, Repeat, Truck } from \"lucide-react\";\nimport {\n formatCadence,\n formatPrice,\n} from \"../portal-subscriptions-list-helpers\";\n\ninterface DrawerStepSelectProps {\n subscriptions: subscriptions.SubscriptionListItem[];\n selectedTokens: Set<string>;\n onToggle: (token: string) => void;\n}\n\nfunction formatBillDate(value: string | null): string {\n if (!value) return \"—\";\n // Mirror the calendar-date-from-the-front parse in `formatLongDate` so a\n // pure date string like \"2026-05-10\" doesn't get shifted to May 9 for\n // anyone west of UTC. Subscription.next_billing_date is a datetime; the\n // date prefix matches the same regex.\n try {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(value);\n if (!match) return \"—\";\n const y = Number(match[1]);\n const m = Number(match[2]);\n const d = Number(match[3]);\n if (!y || !m || !d) return \"—\";\n const date = new Date(Date.UTC(y, m - 1, d));\n return date.toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n timeZone: \"UTC\",\n });\n } catch {\n return \"—\";\n }\n}\n\nexport function DrawerStepSelect({\n subscriptions,\n selectedTokens,\n onToggle,\n}: DrawerStepSelectProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n <div className=\"bg-muted mt-2 rounded-2xl p-6 text-center\">\n <div className=\"mx-auto mb-3 flex size-14 items-center justify-center rounded-2xl bg-transparent shadow-sm\">\n <Truck className=\"text-foreground size-7\" strokeWidth={2} />\n </div>\n <h3 className=\"text-foreground text-sm font-bold\">\n {t(\"bundle_and_save\")}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n {t(\"bundle_select_subs\")}\n </p>\n </div>\n\n {subscriptions.length < 2 && (\n <div className=\"ring-border mt-4 rounded-2xl p-6 text-center ring-1\">\n <p className=\"text-muted-foreground text-xs\">\n {t(\"bundle_no_bundleable_subs\")}\n </p>\n </div>\n )}\n\n <div className=\"mt-4 space-y-2\">\n {subscriptions.length >= 2 &&\n subscriptions.map((sub) => {\n const isSelected = selectedTokens.has(sub.subscription_token);\n return (\n <div\n key={sub.subscription_token}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={() => onToggle(sub.subscription_token)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onToggle(sub.subscription_token);\n }\n }}\n className={`flex cursor-pointer items-start gap-3 rounded-2xl p-4 transition-all ${\n isSelected\n ? \"ring-primary bg-muted ring-2\"\n : \"ring-border hover:ring-foreground/20 ring-1\"\n }`}\n >\n <div className=\"pt-1\">\n <div\n className={`flex size-5 items-center justify-center rounded-full transition-colors ${\n isSelected ? \"bg-primary\" : \"ring-foreground/30 ring-2\"\n }`}\n >\n {isSelected && (\n <Check\n className=\"text-primary-foreground size-3\"\n strokeWidth={3}\n />\n )}\n </div>\n </div>\n\n {sub.variant?.product?.image_url ? (\n <img\n src={sub.variant.product.image_url}\n alt={sub.variant.product.title ?? \"\"}\n className=\"size-12 shrink-0 rounded-lg object-cover\"\n />\n ) : (\n <div className=\"bg-muted flex size-12 shrink-0 items-center justify-center rounded-lg\">\n <Package\n className=\"text-muted-foreground size-6\"\n strokeWidth={1.75}\n />\n </div>\n )}\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-foreground truncate text-xs font-bold\">\n {sub.variant?.product?.title ?? t(\"list_product_fallback\")}\n </p>\n <p className=\"text-foreground mt-0.5 text-xs\">\n {formatPrice(sub)}\n </p>\n {sub.customer?.full_name && (\n <p className=\"text-muted-foreground mt-0.5 truncate text-xs\">\n {sub.customer.full_name}\n </p>\n )}\n </div>\n\n <div className=\"shrink-0 text-right\">\n <div className=\"text-muted-foreground inline-flex items-center gap-1 text-xs\">\n <Repeat className=\"size-3\" strokeWidth={2} />\n {formatCadence(sub.subscription_plan, t)}\n </div>\n <p className=\"text-muted-foreground/75 mt-1 text-xs\">\n {formatBillDate(sub.next_bill_date)}\n </p>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n","import { useMemo, type JSX } from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n getDaysInMonth,\n isDayOutOfRange,\n isMonthOutOfRange,\n isYearOutOfRange,\n type BillDateBounds,\n} from \"./bill-date-bounds\";\n\ninterface DrawerStepDateProps {\n selectedYear: number;\n selectedMonth: number | null;\n selectedDay: number | null;\n onYearChange: (year: number) => void;\n onMonthChange: (month: number) => void;\n onDayChange: (day: number) => void;\n /**\n * Selectable range. Its ceiling is the bundle's bill-date cap, which the API\n * enforces too — without it the picker offers dates that only fail on submit.\n */\n bounds: BillDateBounds;\n}\n\nconst MONTHS = [\n \"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Aug\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dec\",\n];\n\nexport function DrawerStepDate({\n selectedYear,\n selectedMonth,\n selectedDay,\n onYearChange,\n onMonthChange,\n onDayChange,\n bounds,\n}: DrawerStepDateProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const currentYear = bounds.today.getFullYear();\n const availableYears = useMemo(\n () => [currentYear, currentYear + 1, currentYear + 2],\n [currentYear],\n );\n\n const isYearDisabled = (year: number): boolean =>\n isYearOutOfRange(year, bounds);\n\n const isMonthDisabled = (monthIndex: number): boolean =>\n isMonthOutOfRange(selectedYear, monthIndex, bounds);\n\n const daysInSelectedMonth =\n selectedMonth == null ? 31 : getDaysInMonth(selectedYear, selectedMonth);\n\n const isDayDisabled = (day: number): boolean => {\n if (selectedMonth == null) return true;\n return isDayOutOfRange(selectedYear, selectedMonth, day, bounds);\n };\n\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n <div className=\"mt-2\">\n <h3 className=\"text-foreground text-sm font-bold\">\n {t(\"bundle_select_new_bill_date\")}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n {t(\"bundle_select_new_bill_date_description\")}\n </p>\n </div>\n\n <div className=\"mt-6\">\n <h4 className=\"text-foreground mb-3 text-xs font-bold\">\n {t(\"bundle_year\")}\n </h4>\n <div className=\"grid grid-cols-3 gap-2\">\n {availableYears.map((year) => {\n const isActive = selectedYear === year;\n const disabled = isYearDisabled(year);\n return (\n <button\n key={year}\n type=\"button\"\n disabled={disabled}\n onClick={() => onYearChange(year)}\n className={`rounded-lg px-3 py-2.5 text-xs font-semibold transition-all ${\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"text-foreground ring-border hover:ring-foreground/20 bg-transparent ring-1\"\n } ${disabled ? \"cursor-not-allowed opacity-40\" : \"\"}`}\n >\n {year}\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"mt-6\">\n <h4 className=\"text-foreground mb-3 text-xs font-bold\">\n {t(\"bundle_month\")}\n </h4>\n <div className=\"grid grid-cols-4 gap-2\">\n {MONTHS.map((month, index) => {\n const isActive = selectedMonth === index;\n const disabled = isMonthDisabled(index);\n return (\n <button\n key={month}\n type=\"button\"\n disabled={disabled}\n onClick={() => onMonthChange(index)}\n className={`rounded-lg px-3 py-2.5 text-xs font-semibold transition-all ${\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"text-foreground ring-border hover:ring-foreground/20 bg-transparent ring-1\"\n } ${disabled ? \"cursor-not-allowed opacity-40\" : \"\"}`}\n >\n {month}\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"mt-6\">\n <h4 className=\"text-foreground mb-3 text-xs font-bold\">\n {t(\"bundle_day\")}\n </h4>\n <div className=\"grid grid-cols-8 gap-1.5\">\n {Array.from({ length: daysInSelectedMonth }, (_, i) => i + 1).map(\n (day) => {\n const isActive = selectedDay === day;\n const disabled = isDayDisabled(day);\n return (\n <button\n key={day}\n type=\"button\"\n disabled={disabled}\n onClick={() => onDayChange(day)}\n className={`rounded-lg py-2 text-xs font-semibold transition-all ${\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"text-foreground ring-border hover:ring-foreground/20 bg-transparent ring-1\"\n } ${disabled ? \"cursor-not-allowed opacity-40\" : \"\"}`}\n >\n {day}\n </button>\n );\n },\n )}\n </div>\n </div>\n </div>\n );\n}\n","import type { JSX } from \"react\";\nimport { Check } from \"lucide-react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { formatLongDate } from \"../portal-subscriptions-list-helpers\";\n\ninterface DrawerStepAddressProps {\n addresses: fluidPay.CustomerAddress[];\n selectedAddressId: number | null;\n onAddressSelect: (id: number) => void;\n onAddAddress: () => void;\n formattedSelectedDate: string | null;\n}\n\nexport function DrawerStepAddress({\n addresses,\n selectedAddressId,\n onAddressSelect,\n onAddAddress,\n formattedSelectedDate,\n}: DrawerStepAddressProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const hasFlaggedDefault = addresses.some((a) => a.default);\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n <div className=\"mt-2\">\n <h3 className=\"text-foreground text-sm font-bold\">\n {t(\"bundle_select_address\")}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n {t(\"bundle_select_address_description\")}\n </p>\n </div>\n\n {formattedSelectedDate && (\n <div className=\"bg-muted text-muted-foreground mt-4 rounded-lg px-4 py-2.5 text-xs\">\n {t(\"bundle_selected_bill_date\")}{\" \"}\n <span className=\"text-foreground font-semibold\">\n {formatLongDate(formattedSelectedDate)}\n </span>\n </div>\n )}\n\n <div className=\"mt-4 space-y-2\" role=\"radiogroup\">\n {addresses.map((address, index) => {\n const isSelected = selectedAddressId === address.id;\n const isDefault =\n address.default || (!hasFlaggedDefault && index === 0);\n return (\n <button\n key={address.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n onClick={() => onAddressSelect(address.id)}\n className={`flex h-auto w-full cursor-pointer items-start gap-3 rounded-2xl p-4 text-left transition-all ${\n isSelected\n ? \"ring-primary bg-muted ring-2\"\n : \"ring-border hover:ring-foreground/20 ring-1\"\n }`}\n >\n <div className=\"pt-0.5\">\n <div\n className={`flex size-5 items-center justify-center rounded-full transition-colors ${\n isSelected ? \"bg-primary\" : \"ring-foreground/30 ring-2\"\n }`}\n >\n {isSelected && (\n <Check\n className=\"text-primary-foreground size-3\"\n strokeWidth={3}\n />\n )}\n </div>\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {address.name && (\n <p className=\"text-foreground truncate text-xs font-bold\">\n {address.name}\n </p>\n )}\n {isDefault && (\n <span className=\"text-foreground ring-border rounded-full bg-transparent px-2 py-0.5 text-xs font-bold ring-1\">\n {t(\"bundle_default_badge\")}\n </span>\n )}\n </div>\n <p className=\"text-muted-foreground mt-0.5 truncate text-xs\">\n {address.address1}\n </p>\n <p className=\"text-muted-foreground truncate text-xs\">\n {[address.city, address.state].filter(Boolean).join(\", \")}{\" \"}\n {address.postal_code}\n </p>\n {address.phone && (\n <p className=\"text-muted-foreground truncate text-xs\">\n {address.phone}\n </p>\n )}\n </div>\n </button>\n );\n })}\n </div>\n\n <div className=\"mt-4 text-right\">\n <button\n type=\"button\"\n onClick={onAddAddress}\n className=\"text-foreground inline-flex items-center text-xs font-bold underline-offset-2 hover:underline\"\n >\n {t(\"bundle_add_new_address\")}\n </button>\n </div>\n </div>\n );\n}\n","import { useMemo, type JSX } from \"react\";\nimport { Check } from \"lucide-react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n PaymentIcon,\n getCardDisplayName,\n getPaymentMethodLogoBrand,\n} from \"@fluid-app/profile-ui/components/payment-method-card-internals\";\nimport { isPaymentMethodUsable } from \"./payment-utils\";\n\ninterface DrawerStepPaymentProps {\n paymentMethods: fluidPay.CustomerPaymentMethod[];\n selectedPaymentMethodId: number | null;\n onPaymentMethodSelect: (id: number) => void;\n onAddPaymentMethod: () => void;\n}\n\nexport function DrawerStepPayment({\n paymentMethods,\n selectedPaymentMethodId,\n onPaymentMethodSelect,\n onAddPaymentMethod,\n}: DrawerStepPaymentProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n // Filter to usable + sort default-first.\n const usable = useMemo(() => {\n const filtered = paymentMethods.filter(isPaymentMethodUsable);\n const defaultIdx = filtered.findIndex((pm) => pm.default);\n if (defaultIdx <= 0) return filtered;\n const defaultCard = filtered[defaultIdx];\n if (!defaultCard) return filtered;\n return [defaultCard, ...filtered.filter((_, i) => i !== defaultIdx)];\n }, [paymentMethods]);\n\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n <div className=\"mt-2\">\n <h3 className=\"text-foreground text-sm font-bold\">\n {t(\"bundle_select_payment\")}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n {t(\"bundle_select_payment_description\")}\n </p>\n </div>\n\n {usable.length === 0 && (\n <div className=\"bg-muted text-muted-foreground mt-4 rounded-lg px-4 py-3 text-xs\">\n {t(\"bundle_no_usable_payment_methods\")}\n </div>\n )}\n\n <div className=\"mt-4 space-y-2\" role=\"radiogroup\">\n {usable.map((pm) => {\n const isSelected = selectedPaymentMethodId === pm.id;\n const displayName = getCardDisplayName(pm);\n const expiry =\n pm.details.exp_month != null && pm.details.exp_year != null\n ? `${t(\"bundle_card_expires\")} ${pm.details.exp_month}/${pm.details.exp_year}`\n : null;\n return (\n <button\n key={pm.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n onClick={() => onPaymentMethodSelect(pm.id)}\n className={`flex h-auto w-full cursor-pointer items-start gap-3 rounded-2xl p-4 text-left transition-all ${\n isSelected\n ? \"ring-primary bg-muted ring-2\"\n : \"ring-border hover:ring-foreground/20 ring-1\"\n }`}\n >\n <div className=\"pt-0.5\">\n <div\n className={`flex size-5 items-center justify-center rounded-full transition-colors ${\n isSelected ? \"bg-primary\" : \"ring-foreground/30 ring-2\"\n }`}\n >\n {isSelected && (\n <Check\n className=\"text-primary-foreground size-3\"\n strokeWidth={3}\n />\n )}\n </div>\n </div>\n\n <div className=\"flex h-6 w-10 shrink-0 items-center justify-center\">\n <PaymentIcon\n logoUrl={pm.details.logo_url}\n brand={getPaymentMethodLogoBrand(pm)}\n alt={displayName}\n />\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"text-foreground text-xs font-bold\">\n {displayName}\n </p>\n {pm.default && (\n <span className=\"text-foreground ring-border rounded-full bg-transparent px-2 py-0.5 text-xs font-bold ring-1\">\n {t(\"bundle_default_badge\")}\n </span>\n )}\n </div>\n {expiry && (\n <p className=\"text-muted-foreground mt-0.5 text-xs\">\n {expiry}\n </p>\n )}\n </div>\n </button>\n );\n })}\n </div>\n\n <div className=\"mt-4 text-right\">\n <button\n type=\"button\"\n onClick={onAddPaymentMethod}\n className=\"text-foreground inline-flex items-center text-xs font-bold underline-offset-2 hover:underline\"\n >\n {t(\"bundle_add_new_card\")}\n </button>\n </div>\n </div>\n );\n}\n","import { type JSX } from \"react\";\nimport { Sheet, SheetContent, SheetTitle } from \"@fluid-app/ui-primitives\";\nimport { MobileBottomSheet } from \"@fluid-app/ui-components/components/MobileBottomSheet\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { useBundleForm } from \"./use-bundle-form\";\nimport { DrawerStepTabs } from \"./DrawerStepTabs\";\nimport { DrawerStepSelect } from \"./DrawerStepSelect\";\nimport { DrawerStepDate } from \"./DrawerStepDate\";\nimport { DrawerStepAddress } from \"./DrawerStepAddress\";\nimport { DrawerStepPayment } from \"./DrawerStepPayment\";\nimport type { Step } from \"./types\";\n\nexport interface BundleSubscriptionsDrawerProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n subscriptions: subscriptions.SubscriptionListItem[];\n addresses: fluidPay.CustomerAddress[];\n paymentMethods: fluidPay.CustomerPaymentMethod[];\n defaultAddressId?: number | null;\n defaultPaymentMethodId?: number | null;\n onAddAddress: () => void;\n onAddPaymentMethod: () => void;\n onSubmit: (params: {\n subscription_tokens: string[];\n next_bill_date: string;\n address_id: number;\n payment_method_id: number;\n }) => Promise<void>;\n isSubmitting?: boolean;\n}\n\nexport function BundleSubscriptionsDrawer({\n open,\n onOpenChange,\n subscriptions: subscriptionList,\n addresses,\n paymentMethods,\n defaultAddressId,\n defaultPaymentMethodId,\n onAddAddress,\n onAddPaymentMethod,\n onSubmit,\n isSubmitting,\n}: BundleSubscriptionsDrawerProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const { isMobile } = useSidebar();\n const form = useBundleForm({\n subscriptions: subscriptionList,\n addresses,\n paymentMethods,\n defaultAddressId,\n defaultPaymentMethodId,\n });\n\n const handleClose = () => onOpenChange(false);\n\n const handleNext = () => {\n if (form.step < 4) form.setStep((form.step + 1) as Step);\n };\n\n const handleBack = () => {\n if (form.step === 1) handleClose();\n else form.setStep((form.step - 1) as Step);\n };\n\n const handleSubmit = async () => {\n if (\n !form.canProceedFromStep1 ||\n !form.canProceedFromStep2 ||\n !form.canProceedFromStep3 ||\n !form.canProceedFromStep4 ||\n form.formattedDate == null ||\n form.selectedAddressId == null ||\n form.selectedPaymentMethodId == null\n ) {\n return;\n }\n await onSubmit({\n subscription_tokens: Array.from(form.selectedTokens),\n next_bill_date: form.formattedDate,\n address_id: form.selectedAddressId,\n payment_method_id: form.selectedPaymentMethodId,\n });\n };\n\n const nextDisabled =\n (form.step === 1 && !form.canProceedFromStep1) ||\n (form.step === 2 && !form.canProceedFromStep2) ||\n (form.step === 3 && !form.canProceedFromStep3);\n\n const content = (\n <div\n className={\n isMobile\n ? \"flex min-h-[65dvh] flex-col\"\n : \"flex min-h-0 flex-1 flex-col\"\n }\n >\n <DrawerStepTabs\n step={form.step}\n onStepClick={form.setStep}\n canProceedFromStep1={form.canProceedFromStep1}\n canProceedFromStep2={form.canProceedFromStep2}\n canProceedFromStep3={form.canProceedFromStep3}\n />\n\n {form.step === 1 && (\n <DrawerStepSelect\n subscriptions={subscriptionList}\n selectedTokens={form.selectedTokens}\n onToggle={form.toggleToken}\n />\n )}\n {form.step === 2 && (\n <DrawerStepDate\n selectedYear={form.selectedYear}\n selectedMonth={form.selectedMonth}\n selectedDay={form.selectedDay}\n onYearChange={form.setYear}\n onMonthChange={form.setMonth}\n onDayChange={form.setDay}\n bounds={form.bounds}\n />\n )}\n {form.step === 3 && (\n <DrawerStepAddress\n addresses={addresses}\n selectedAddressId={form.selectedAddressId}\n onAddressSelect={form.setSelectedAddressId}\n onAddAddress={onAddAddress}\n formattedSelectedDate={form.formattedDate}\n />\n )}\n {form.step === 4 && (\n <DrawerStepPayment\n paymentMethods={paymentMethods}\n selectedPaymentMethodId={form.selectedPaymentMethodId}\n onPaymentMethodSelect={form.setSelectedPaymentMethodId}\n onAddPaymentMethod={onAddPaymentMethod}\n />\n )}\n\n <div className=\"border-border flex shrink-0 items-center justify-between gap-3 border-t px-6 py-4\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"text-foreground ring-border hover:bg-muted rounded-lg bg-transparent px-6 py-2.5 text-xs font-bold ring-1 transition-all\"\n >\n {form.step === 1 ? t(\"bundle_done\") : t(\"bundle_back\")}\n </button>\n {form.step < 4 ? (\n <button\n type=\"button\"\n onClick={handleNext}\n disabled={nextDisabled}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 rounded-lg px-6 py-2.5 text-xs font-bold transition-all disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {t(\"next\")}\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!form.canProceedFromStep4 || isSubmitting}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 inline-flex min-w-[140px] items-center justify-center rounded-lg px-6 py-2.5 text-xs font-bold transition-all disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {isSubmitting ? (\n <span className=\"border-primary-foreground size-5 animate-spin rounded-full border-2 border-t-transparent\" />\n ) : (\n t(\"bundle_create\")\n )}\n </button>\n )}\n </div>\n </div>\n );\n\n if (isMobile) {\n return (\n <MobileBottomSheet\n open={open}\n onOpenChange={onOpenChange}\n title={t(\"bundle_subscriptions\")}\n >\n {content}\n </MobileBottomSheet>\n );\n }\n\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent\n side=\"right\"\n className=\"bg-background flex h-full w-full flex-col gap-0 p-0 sm:max-w-md\"\n >\n {/* Header */}\n <div className=\"border-border flex items-center justify-between border-b px-6 py-4\">\n <SheetTitle className=\"text-foreground text-base font-bold\">\n {t(\"bundle_subscriptions\")}\n </SheetTitle>\n {/* SheetContent already renders its own close (X) button via the shadcn primitive. */}\n </div>\n\n {content}\n </SheetContent>\n </Sheet>\n );\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport {\n FluidPayCoreProvider,\n type fluidPay,\n type State,\n} from \"@fluid-app/fluid-pay-core\";\nimport { isApiError } from \"@fluid-app/api-client-core\";\nimport {\n AddressFormDialog,\n CreditCardFormDialog,\n type CreditCardFormSubmitData,\n} from \"@fluid-app/profile-ui\";\nimport { useActiveLocale } from \"@fluid-app/i18n/locale-context\";\nimport {\n useBundles,\n useCreateBundle,\n useInfiniteSubscriptions,\n useUpdateSubscriptionInfo,\n} from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport { TOKEN_PROVIDER_VGS } from \"@fluid-app/portal-core/pay-types\";\nimport type { PayAddress } from \"@fluid-app/portal-core/pay-types\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { getBrowserInfo } from \"@fluid-app/fluid-pay-core/utils/browser-info\";\nimport { useCountriesApi } from \"@fluid-app/store-core/countries-api-context\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\nimport { useFluidContext } from \"../providers/FluidProvider\";\nimport { ProfileTranslationBridge } from \"../providers/ProfileTranslationBridge\";\nimport { payKeys, storeKeys } from \"../account/query-keys\";\nimport {\n createFluidPayApiAdapter,\n mapToFluidPayPaymentMethod,\n} from \"../adapters/fluid-pay-api-adapter\";\nimport { usePortalCardAdd3DSFlow } from \"../hooks/use-portal-card-add-3ds-flow\";\nimport { buildSubscriptionCardAddSuccess } from \"../subscriptions/subscription-card-add-success\";\nimport { PortalSubscriptionsList } from \"./subscriptions/PortalSubscriptionsList\";\nimport { BundleSubscriptionsDrawer } from \"./subscriptions/bundle-drawer/BundleSubscriptionsDrawer\";\nimport { mapStatusKindOnly } from \"./subscriptions/portal-subscriptions-list-helpers\";\nimport { useStore } from \"../hooks/use-store\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\n\ninterface SubscriptionsListScreenProps {\n customerId: number | undefined;\n isLoadingCustomer: boolean;\n onToast?: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n}\n\n// AddressFormDialog and CreditCardFormDialog accept their own free-form\n// translation function. Their label set is closed and not part of the\n// subscriptions dictionary, so we inline a small map and Title-Case any\n// unknown key (mirrors the pattern in PortalSubscriptionShippingAddressSection).\nconst ADDRESS_DIALOG_LABELS: Record<string, string> = {\n add_an_address: \"Add an Address\",\n add_address: \"Add Address\",\n edit_address: \"Edit Address\",\n delete_address: \"Delete Address\",\n delete_address_message:\n \"Are you sure you want to delete this address? This action cannot be undone.\",\n delete: \"Delete\",\n cancel: \"Cancel\",\n country: \"Country\",\n name: \"Name\",\n address_line_1: \"Address Line 1\",\n address_line_2: \"Apartment, suite, etc.\",\n city: \"City\",\n state: \"State\",\n province: \"Province\",\n zip_code: \"Zip Code\",\n postal_code: \"Postal Code\",\n select_state: \"Select state\",\n select_an_option: \"Select an option\",\n set_as_default_address: \"Set as default address\",\n save_address: \"Save Address\",\n deleting: \"Deleting…\",\n tap_to_confirm: \"Tap to confirm\",\n add_credit_card: \"Add Credit Card\",\n add_billing_address: \"Add billing address\",\n billing_address: \"Billing Address\",\n same_as_shipping: \"Same as shipping address\",\n use_a_different_address: \"Use a different address\",\n set_as_default_payment_method: \"Set as default payment method\",\n save_card: \"Save Card\",\n saving: \"Saving...\",\n securing: \"Loading secure form...\",\n};\n\nfunction addressDialogT(key: string): string {\n return (\n ADDRESS_DIALOG_LABELS[key] ??\n key\n .split(\"_\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \")\n );\n}\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n phone: raw.phone,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\nfunction SubscriptionsListScreenInner({\n customerId,\n isLoadingCustomer,\n onToast,\n}: SubscriptionsListScreenProps): React.JSX.Element {\n const { isMobile } = useSidebar();\n const { navigate } = useAppNavigation();\n const queryClient = useQueryClient();\n const payApi = usePayApi();\n const countriesApi = useCountriesApi();\n const { t } = useSubscriptionsTranslation();\n const { t: profileT } = useProfileTranslation();\n const { config } = useFluidContext();\n const { locale } = useActiveLocale();\n\n // Company-level bundling feature flag from the portal-tenant store endpoint.\n // The Rails BFF returns 422 on bundle endpoints when this is false, so we\n // hide every bundle entry point (CTA, drawer, list cards) rather than show\n // controls that are guaranteed to fail.\n const { data: store } = useStore();\n const bundlingEnabled = !!store?.bundle_subscriptions_enabled;\n\n const { data: addresses = [] } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n enabled: !!customerId && !isLoadingCustomer,\n });\n\n const { data: paymentMethods = [] } = useQuery({\n queryKey: payKeys.paymentMethods.list(),\n queryFn: async () => {\n const response = await payApi.fetchPaymentMethods();\n return response.payment_methods.map(mapToFluidPayPaymentMethod);\n },\n enabled: !!customerId && !isLoadingCustomer,\n });\n\n // Re-call useInfiniteSubscriptions here so the drawer can see the same flat\n // list without prop-drilling. TanStack Query dedupes the network request,\n // so this is just a cache-read after PortalSubscriptionsList has fetched.\n const { data: subscriptionsData } = useInfiniteSubscriptions(\n { customerId, limit: 12 },\n { enabled: !!customerId && !isLoadingCustomer },\n );\n const subscriptionsList = useMemo(\n () => subscriptionsData?.pages.flatMap((p) => p.subscriptions) ?? [],\n [subscriptionsData],\n );\n\n // Only active/paused/pending/past-due, currently un-bundled subs can be\n // bundled. Cancelled subs have no future billing for the bundler to align,\n // and already-bundled subs would re-trigger bundler.rb's composite-key\n // grouping rather than create a fresh group.\n const bundleableSubscriptions = useMemo(\n () =>\n subscriptionsList.filter(\n (s) =>\n mapStatusKindOnly(s.status) !== \"cancelled\" &&\n (s.bundled_subscriptions?.length ?? 0) === 0,\n ),\n [subscriptionsList],\n );\n\n // Authoritative source for runtime bundle groupings — the backend recomputes\n // group membership at request time from `bundler.rb`'s composite key\n // (customer + address + volume_rep + next_bill_date + digital). The list\n // component picks out `subscription_count > 1` for actual bundle cards.\n const { data: bundlesData } = useBundles({\n enabled: !!customerId && !isLoadingCustomer && bundlingEnabled,\n });\n\n // Drawer + dialog state.\n const [bundleDrawerOpen, setBundleDrawerOpen] = useState(false);\n const [bundleDrawerKey, setBundleDrawerKey] = useState(0);\n const [addressDialog, setAddressDialog] = useState<{\n open: boolean;\n selected: fluidPay.CustomerAddress | null;\n }>({ open: false, selected: null });\n const [isAddCardOpen, setIsAddCardOpen] = useState(false);\n const [saveCardError, setSaveCardError] = useState<string | null>(null);\n // `isBundling` covers the FULL handleBundle async span (createBundle +\n // per-token payment-method PUT loop), not just createBundle.isPending.\n // Without this, the submit button would re-enable after createBundle\n // resolved while the PUT loop was still in flight, allowing a duplicate\n // bundle creation request.\n const [isBundling, setIsBundling] = useState(false);\n\n const { data: countriesData } = useQuery({\n queryKey: storeKeys.countries(locale),\n queryFn: () => countriesApi.listCountries({ languageIso: locale }),\n enabled: addressDialog.open || isAddCardOpen,\n });\n const countryOptions = useMemo(\n () =>\n [...(countriesData?.countries ?? [])]\n .map((c) => ({ iso: c.code, name: c.name }))\n .sort((a, b) => a.name.localeCompare(b.name)),\n [countriesData],\n );\n const statesByCountry = useMemo(() => {\n const map = new Map<string, State[]>();\n for (const c of countriesData?.countries ?? []) {\n map.set(\n c.code,\n c.states.map((s) => ({ name: s.name, isoCode: s.code })),\n );\n }\n return map;\n }, [countriesData]);\n const fetchStatesFromCountries = useCallback(\n (countryCode: string): Promise<State[]> =>\n Promise.resolve(statesByCountry.get(countryCode) ?? []),\n [statesByCountry],\n );\n\n const createAddressMutation = useMutation({\n // Detect a server-side dedupe (POST /api/pay/addresses returns the existing\n // record when an identical address already exists, ignoring `name`). Snapshot\n // the current id set before the request and compare against the returned id.\n mutationFn: async (body: fluidPay.CreateAddressBody) => {\n const existingIds = new Set(addresses.map((a) => a.id));\n const address = await payApi.createAddress({\n address: {\n name: body.address.name,\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n phone: body.address.phone,\n default: body.address.default,\n },\n });\n return { address, deduped: existingIds.has(address.id) };\n },\n onSuccess: ({ deduped }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (deduped) {\n onToast?.(profileT(\"address_already_exists\"), \"warning\");\n } else {\n onToast?.(profileT(\"address_created\"), \"success\");\n }\n },\n onError: () => onToast?.(profileT(\"failed_to_create_address\"), \"error\"),\n });\n\n // Bridge for the 3DS modal that accepts `t: (key: string) => string`; the\n // adapter falls back to `key` for unknown keys, so widening is safe.\n const tFn = useCallback(\n (key: string): string => profileT(key as never),\n [profileT],\n );\n\n // Wire 3DS-on-card-add: when the BFF returns three_ds_required, hand off to the\n // challenge flow instead of treating the create as a saved card. Invalidation +\n // close + toast live in onApproved (3DS) and onCreated (non-3DS), never on the\n // raw mutation, so the three_ds_required path keeps the dialog open behind the\n // challenge modal. Mirrors the profile + per-subscription surfaces.\n const cardAdd3DS = usePortalCardAdd3DSFlow({\n payApi,\n t: tFn,\n onApproved: async () => {\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n setIsAddCardOpen(false);\n onToast?.(profileT(\"payment_method_added\"), \"success\");\n },\n onFailed: (message) => {\n setSaveCardError(message);\n },\n onCanceled: () => {},\n });\n\n const cardAddSuccess = buildSubscriptionCardAddSuccess({\n begin: cardAdd3DS.begin,\n onCreated: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.paymentMethods.all });\n setIsAddCardOpen(false);\n onToast?.(profileT(\"payment_method_added\"), \"success\");\n },\n });\n\n const addCreditCardMutation = useMutation({\n mutationFn: (data: CreditCardFormSubmitData) =>\n payApi.createPaymentMethod({\n payment_method: {\n type: \"card\",\n token: data.payment_method.token,\n token_provider: TOKEN_PROVIDER_VGS,\n exp_month: data.payment_method.exp_month,\n exp_year: data.payment_method.exp_year,\n cvv_token: data.payment_method.cvv_token,\n card_holder: data.payment_method.card_holder,\n default: data.set_as_default,\n ...(data.payment_method.bin ? { bin: data.payment_method.bin } : {}),\n ...(data.payment_method.last_four\n ? { last_four: data.payment_method.last_four }\n : {}),\n ...(data.payment_method.card_network\n ? { card_network: data.payment_method.card_network }\n : {}),\n },\n billing_address_id: data.billing_address_id,\n browser_info: getBrowserInfo(),\n }),\n onSuccess: cardAddSuccess,\n onError: () => onToast?.(profileT(\"failed_to_add_payment_method\"), \"error\"),\n });\n\n const createBundle = useCreateBundle();\n const updateSubscription = useUpdateSubscriptionInfo();\n\n const handleBundleClick = () => {\n setBundleDrawerKey((k) => k + 1);\n setBundleDrawerOpen(true);\n };\n\n const handleBundle = async (params: {\n subscription_tokens: string[];\n next_bill_date: string;\n address_id: number;\n payment_method_id: number;\n }) => {\n if (isBundling) return;\n setIsBundling(true);\n try {\n await createBundle.mutateAsync({\n subscription_tokens: params.subscription_tokens,\n next_bill_date: params.next_bill_date,\n address_id: params.address_id,\n });\n } catch (err) {\n // Surface the BFF's validation message (e.g. \"cannot bundle a cancelled\n // subscription\") instead of a generic \"Please try again\" — FetchClient\n // already extracts `data.message` from the JSON body into ApiError.\n // Only trust the message when it's a 4xx ApiError (real validation); on\n // 5xx or non-ApiError throws, fall through to the localized fallback so\n // users never see FetchClient's \"POST request failed\" default.\n const bffMessage =\n isApiError(err) && err.status >= 400 && err.status < 500\n ? err.message\n : undefined;\n const message = bffMessage ?? t(\"bundle_failed\");\n onToast?.(message, \"error\");\n setIsBundling(false);\n return;\n }\n\n // PUT-loop workaround: the BFF create endpoint accepts subscription_tokens,\n // next_bill_date, address_id, and volume_rep_id only — it does NOT honor\n // payment_method_id. Push the chosen payment method onto each member sub\n // via the existing per-subscription update endpoint. Settle all in\n // parallel so a single 4xx doesn't block the others.\n const results = await Promise.allSettled(\n params.subscription_tokens.map((token) =>\n updateSubscription.mutateAsync({\n subscriptionToken: token,\n body: { payment_method_id: params.payment_method_id },\n }),\n ),\n );\n const failedCount = results.filter((r) => r.status === \"rejected\").length;\n if (failedCount === 0) {\n onToast?.(t(\"bundle_succeeded\"), \"success\");\n } else {\n onToast?.(\n t(\"bundle_partial_payment_failure\", { n: String(failedCount) }),\n \"warning\",\n );\n }\n setBundleDrawerOpen(false);\n setIsBundling(false);\n };\n\n const goToDetail = (token: string) => navigate(`subscriptions/${token}`);\n\n return (\n <>\n <PortalSubscriptionsList\n customerId={customerId}\n isLoadingCustomer={isLoadingCustomer}\n onSubscriptionClick={goToDetail}\n onResume={(sub) => goToDetail(sub.subscription_token)}\n onBundleClick={\n bundlingEnabled && bundleableSubscriptions.length >= 2\n ? handleBundleClick\n : undefined\n }\n bundles={bundlingEnabled ? bundlesData : undefined}\n />\n\n {bundlingEnabled && (\n <BundleSubscriptionsDrawer\n key={bundleDrawerKey}\n open={bundleDrawerOpen}\n onOpenChange={setBundleDrawerOpen}\n subscriptions={bundleableSubscriptions}\n addresses={addresses}\n paymentMethods={paymentMethods}\n defaultAddressId={\n addresses.find((a) => a.default)?.id ?? addresses[0]?.id ?? null\n }\n defaultPaymentMethodId={\n paymentMethods.find((pm) => pm.default)?.id ??\n paymentMethods[0]?.id ??\n null\n }\n onAddAddress={() => setAddressDialog({ open: true, selected: null })}\n onAddPaymentMethod={() => setIsAddCardOpen(true)}\n onSubmit={handleBundle}\n isSubmitting={isBundling}\n />\n )}\n\n <AddressFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={addressDialog.open}\n onClose={() => setAddressDialog({ open: false, selected: null })}\n selectedAddress={addressDialog.selected}\n defaultCountry={\n addresses.find((a) => a.default)?.country_code ??\n config.countryIso ??\n \"US\"\n }\n languageIso={locale}\n t={addressDialogT}\n onSubmit={async (formData) => {\n try {\n await createAddressMutation.mutateAsync(formData);\n setAddressDialog({ open: false, selected: null });\n } catch {\n // toast surfaced via onError\n }\n }}\n isSubmitting={createAddressMutation.isPending}\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n />\n\n <CreditCardFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isAddCardOpen}\n onClose={() => {\n // Don't let the card dialog close mid-challenge — the 3DS modal owns\n // teardown while active.\n if (cardAdd3DS.isActive) return;\n setSaveCardError(null);\n setIsAddCardOpen(false);\n }}\n t={addressDialogT}\n error={saveCardError ?? undefined}\n onSubmit={async (data) => {\n setSaveCardError(null);\n try {\n await addCreditCardMutation.mutateAsync(data);\n // Close + toast are handled by cardAddSuccess (created) or the 3DS\n // flow (approved) — never here, so three_ds_required keeps the card\n // dialog open behind the challenge modal.\n } catch {\n // toast surfaced via onError\n }\n }}\n isSubmitting={addCreditCardMutation.isPending}\n jwt=\"\"\n savedAddresses={addresses}\n defaultBillingAddressId={addresses.find((a) => a.default)?.id}\n renderAddressFormDialog={({ isOpen, onClose, onAddressCreated }) => (\n <AddressFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isOpen}\n onClose={onClose}\n selectedAddress={null}\n defaultCountry={\n addresses.find((a) => a.default)?.country_code ??\n config.countryIso ??\n \"US\"\n }\n languageIso={locale}\n t={addressDialogT}\n onSubmit={async (formData) => {\n try {\n const { address } =\n await createAddressMutation.mutateAsync(formData);\n onAddressCreated(mapToFluidPayAddress(address));\n } catch {\n // toast surfaced via onError\n }\n }}\n isSubmitting={createAddressMutation.isPending}\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n />\n )}\n />\n {cardAdd3DS.modal}\n </>\n );\n}\n\nexport function SubscriptionsListScreen(\n props: SubscriptionsListScreenProps,\n): React.JSX.Element {\n const payApi = usePayApi();\n const fluidPayShim = useMemo(\n () => createFluidPayApiAdapter(payApi),\n [payApi],\n );\n return (\n <FluidPayCoreProvider api={fluidPayShim}>\n <ProfileTranslationBridge>\n <SubscriptionsListScreenInner {...props} />\n </ProfileTranslationBridge>\n </FluidPayCoreProvider>\n );\n}\n","import type React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Button,\n DialogFooter,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\n\nconst PAUSE_MONTH_OPTIONS = [1, 2, 3] as const;\nexport type PauseMonths = (typeof PAUSE_MONTH_OPTIONS)[number];\n\nexport interface CancelSubscriptionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void | Promise<unknown>;\n onPauseInstead: (months: PauseMonths) => void;\n errorMessage?: string;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function CancelSubscriptionDialog({\n open,\n onOpenChange,\n onConfirm,\n onPauseInstead,\n errorMessage,\n presentation = \"dialog\",\n}: CancelSubscriptionDialogProps): React.JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const [isPending, setIsPending] = useState(false);\n const [selectedMonths, setSelectedMonths] = useState<PauseMonths | null>(\n null,\n );\n\n useEffect(() => {\n if (!open) setSelectedMonths(null);\n }, [open]);\n\n const handleConfirm = async () => {\n const result = onConfirm();\n if (!(result instanceof Promise)) {\n onOpenChange(false);\n return;\n }\n setIsPending(true);\n try {\n await result;\n onOpenChange(false);\n } catch (error) {\n // Leave the dialog open so the parent can surface errorMessage inline.\n console.error(\"CancelSubscriptionDialog: action rejected\", error);\n } finally {\n setIsPending(false);\n }\n };\n\n const handlePause = () => {\n if (!selectedMonths) return;\n onPauseInstead(selectedMonths);\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(v) => !isPending && onOpenChange(v)}\n title={t(\"cancel_dialog_title\")}\n description={t(\"cancel_dialog_description\")}\n role=\"alertdialog\"\n presentation={presentation}\n >\n <div className=\"border-border space-y-2 rounded-md border p-3\">\n <p className=\"text-foreground text-sm font-medium\">\n {t(\"cancel_dialog_pause_question\")}\n </p>\n <Label\n htmlFor=\"cancel-pause-months\"\n className=\"text-foreground text-sm font-semibold\"\n >\n {t(\"pause_for\")}\n </Label>\n <Select\n value={selectedMonths ? String(selectedMonths) : undefined}\n onValueChange={(value) =>\n setSelectedMonths(value ? (Number(value) as PauseMonths) : null)\n }\n disabled={isPending}\n >\n <SelectTrigger id=\"cancel-pause-months\" className=\"w-full\">\n <SelectValue placeholder={t(\"select_duration\")} />\n </SelectTrigger>\n <SelectContent>\n {PAUSE_MONTH_OPTIONS.map((months) => (\n <SelectItem key={months} value={String(months)}>\n {months === 1\n ? t(\"month_singular\", { count: String(months) })\n : t(\"month_plural\", { count: String(months) })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Button\n variant=\"outline\"\n onClick={handlePause}\n disabled={isPending || !selectedMonths}\n className=\"w-full\"\n >\n {t(\"cancel_dialog_pause_button\")}\n </Button>\n </div>\n\n {errorMessage && (\n <p className=\"text-destructive text-left text-sm\">{errorMessage}</p>\n )}\n\n <DialogFooter className=\"flex-col gap-2 sm:flex-row sm:justify-end\">\n <Button\n variant=\"secondary\"\n onClick={() => onOpenChange(false)}\n disabled={isPending}\n >\n {t(\"cancel_dialog_cancel_button\")}\n </Button>\n {/*\n Plain Button rather than AlertDialogAction: Action auto-closes\n the dialog after onClick, which races handleConfirm's async\n path — the dialog would dismiss before the mutation settled,\n the spinner would never show, and an inline errorMessage would\n never be visible. handleConfirm calls onOpenChange itself on\n success and intentionally leaves the dialog open on rejection.\n */}\n <Button\n variant=\"destructive\"\n onClick={handleConfirm}\n disabled={isPending}\n >\n {isPending\n ? t(\"loading_ellipsis\")\n : t(\"cancel_dialog_confirm_button\")}\n </Button>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","/**\n * Format a number as currency (USD).\n */\nexport function formatCurrency(value: number): string {\n return new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }).format(value);\n}\n\n/**\n * Maps a billing_interval_unit to its singular/plural translation keys\n * (`unit_day`/`unit_days`, …). Single source of truth for cadence-unit\n * pluralization across the subscription detail screen and the bundled-with card.\n */\nexport const UNIT_KEYS: Record<string, { singular: string; plural: string }> = {\n day: { singular: \"unit_day\", plural: \"unit_days\" },\n week: { singular: \"unit_week\", plural: \"unit_weeks\" },\n month: { singular: \"unit_month\", plural: \"unit_months\" },\n year: { singular: \"unit_year\", plural: \"unit_years\" },\n};\n\n/** Statuses that have a corresponding `list_status_*` translation key. */\nexport const KNOWN_STATUSES = new Set([\n \"active\",\n \"paused\",\n \"cancelled\",\n \"completed\",\n \"past_due\",\n \"pending\",\n]);\n\n/**\n * Convert a snake_case or lowercase string to Start Case.\n * Replaces lodash startCase for simple status strings.\n */\nexport function startCase(str: string | undefined | null): string {\n if (!str) return \"\";\n return str.replace(/_/g, \" \").replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Format a Date as a long human-readable string (e.g. \"May 29, 2026\")\n * using the active locale so month names are translated.\n */\nexport function formatLongDate(date: Date, locale: string = \"en-US\"): string {\n try {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n } catch {\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n }\n}\n\n/**\n * Format a Date as a medium-length string (e.g. \"May 29, 2026\")\n * using abbreviated month names, locale-aware.\n */\nexport function formatMediumDate(date: Date, locale: string = \"en-US\"): string {\n try {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n }).format(date);\n } catch {\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n }).format(date);\n }\n}\n\n/**\n * Format a next bill date string in a locale-aware short format (UTC).\n */\nexport function formatNextBillDate(\n nextBillDate: string,\n locale: string = \"en-US\",\n): string {\n if (!nextBillDate) return \"\";\n const date = new Date(nextBillDate);\n if (isNaN(date.getTime())) return \"\";\n try {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n timeZone: \"UTC\",\n }).format(date);\n } catch {\n // Intl throws on invalid locale values — fall back to en-US rather\n // than crashing the component.\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n timeZone: \"UTC\",\n }).format(date);\n }\n}\n\n/**\n * Show the completed display status before any stale next bill date.\n */\nexport function formatNextBillDisplay(\n nextBillDate: string | null | undefined,\n displayStatus: string,\n labels: { completed: string; unavailable: string },\n locale: string = \"en-US\",\n): string {\n if (displayStatus === \"completed\") return labels.completed;\n\n return formatNextBillDate(nextBillDate ?? \"\", locale) || labels.unavailable;\n}\n","import type React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { calculateResumeDate } from \"@fluid-app/subscriptions-core\";\nimport { getMaxSkippableOrders } from \"@fluid-app/subscriptions-core/utils/subscription-helpers\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { Button, DialogFooter, Label } from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { formatLongDate } from \"../lib/format\";\n\ntype PauseType = \"indefinite\" | \"order_count\";\n\nexport type PauseSubscriptionSelection =\n | { type: \"indefinite\" }\n | { type: \"order_count\"; numberOfOrders: number };\n\nexport interface PauseSubscriptionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: (selection: PauseSubscriptionSelection) => void;\n isLoading?: boolean;\n errorMessage?: string;\n currentNextBillDate?: string | null;\n billingInterval?: number;\n billingIntervalUnit?: string;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function PauseSubscriptionDialog({\n open,\n onOpenChange,\n onConfirm,\n isLoading,\n errorMessage,\n currentNextBillDate,\n billingInterval = 1,\n billingIntervalUnit = \"month\",\n presentation = \"dialog\",\n}: PauseSubscriptionDialogProps): React.JSX.Element {\n const { t, locale } = useSubscriptionsTranslation();\n const [pauseType, setPauseType] = useState<PauseType>(\"indefinite\");\n const [selectedOrderCount, setSelectedOrderCount] = useState<number | null>(\n null,\n );\n\n // Only the counts the API would accept. Skipping N orders sets a bill date N\n // intervals out, and the API caps that date, so the old fixed 1-99 list\n // offered pauses that came back as a 422 naming number_of_orders.\n const maxSkippableOrders = getMaxSkippableOrders(\n billingInterval,\n billingIntervalUnit,\n currentNextBillDate,\n );\n const orderCountOptions = Array.from(\n { length: maxSkippableOrders },\n (_, i) => i + 1,\n );\n\n const calculatedResumeDate =\n selectedOrderCount && currentNextBillDate\n ? calculateResumeDate(\n billingInterval,\n billingIntervalUnit,\n selectedOrderCount,\n currentNextBillDate,\n )\n : null;\n\n // Reset selections whenever the dialog opens so stale state doesn't\n // leak across invocations.\n useEffect(() => {\n if (!open) return;\n setPauseType(\"indefinite\");\n setSelectedOrderCount(null);\n }, [open]);\n\n const handleConfirm = () => {\n if (pauseType === \"indefinite\") {\n onConfirm({ type: \"indefinite\" });\n return;\n }\n if (pauseType === \"order_count\" && selectedOrderCount) {\n onConfirm({\n type: \"order_count\",\n numberOfOrders: selectedOrderCount,\n });\n }\n };\n\n const handleDismiss = (next: boolean) => {\n if (!next) {\n setPauseType(\"indefinite\");\n setSelectedOrderCount(null);\n }\n onOpenChange(next);\n };\n\n const statusMessage = (() => {\n if (pauseType === \"indefinite\") {\n return (\n <>\n {t(\"pause_indefinite_message_prefix\")}{\" \"}\n <strong>{t(\"pause_indefinite_message_resume\")}</strong>{\" \"}\n {t(\"pause_indefinite_message_suffix\")}\n </>\n );\n }\n if (!selectedOrderCount) return null;\n const displayDate = calculatedResumeDate\n ? formatLongDate(calculatedResumeDate, locale)\n : t(\"a_future_date\");\n return (\n <>\n {t(\"pause_resume_message_prefix\")}{\" \"}\n <span className=\"font-semibold\">{displayDate}</span>\n {t(\"pause_resume_message_suffix\")}\n </>\n );\n })();\n\n const isActionDisabled = pauseType === \"order_count\" && !selectedOrderCount;\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleDismiss}\n title={t(\"pause_dialog_title\")}\n description={t(\"pause_dialog_description\")}\n presentation={presentation}\n >\n <div className=\"space-y-4\">\n <div className=\"space-y-4\">\n {/* Pause Indefinitely */}\n <div className=\"flex items-center gap-x-2\">\n <input\n id=\"pause-indefinitely\"\n type=\"radio\"\n checked={pauseType === \"indefinite\"}\n onChange={() => setPauseType(\"indefinite\")}\n className=\"border-border accent-primary size-4 focus:ring-0\"\n />\n <Label\n htmlFor=\"pause-indefinitely\"\n className=\"text-foreground cursor-pointer text-sm font-medium\"\n >\n {t(\"pause_indefinitely\")}\n </Label>\n </div>\n\n {/* Pause for Number of Orders */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-x-2\">\n <input\n id=\"pause-order-count\"\n type=\"radio\"\n checked={pauseType === \"order_count\"}\n onChange={() => setPauseType(\"order_count\")}\n // A subscription whose next bill date already sits near the cap\n // has no acceptable count, so the choice reads as unavailable\n // rather than opening an empty dropdown. Indefinite still works.\n disabled={maxSkippableOrders === 0}\n className=\"border-border accent-primary size-4 focus:ring-0 disabled:opacity-40\"\n />\n <Label\n htmlFor=\"pause-order-count\"\n className={`text-sm font-medium ${\n maxSkippableOrders === 0\n ? \"text-muted-foreground cursor-not-allowed\"\n : \"text-foreground cursor-pointer\"\n }`}\n >\n {t(\"pause_for_orders\")}\n </Label>\n </div>\n\n {pauseType === \"order_count\" && (\n <div className=\"ml-6 space-y-2\">\n <Label className=\"text-foreground text-sm font-semibold\">\n {t(\"choose_orders_to_skip\")}\n </Label>\n <select\n value={selectedOrderCount ?? \"\"}\n onChange={(e) =>\n setSelectedOrderCount(Number(e.target.value))\n }\n className=\"border-input bg-background focus:border-ring focus:ring-ring h-10 w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-hidden\"\n >\n <option value=\"\" disabled>\n {t(\"select\")}\n </option>\n {orderCountOptions.map((count) => (\n <option key={count} value={count}>\n {count}\n </option>\n ))}\n </select>\n </div>\n )}\n </div>\n\n {/* Status Message */}\n {statusMessage && (\n <div className=\"text-muted-foreground text-xs\">{statusMessage}</div>\n )}\n </div>\n </div>\n\n {errorMessage && (\n <p className=\"text-destructive text-left text-sm\">{errorMessage}</p>\n )}\n\n <DialogFooter>\n <div className=\"flex w-full flex-row justify-between gap-x-2\">\n <Button\n variant=\"outline\"\n className=\"h-10 min-w-[70px] rounded p-3\"\n onClick={() => handleDismiss(false)}\n >\n {t(\"pause_dialog_cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"h-10 min-w-[70px] rounded p-3\"\n onClick={handleConfirm}\n disabled={isActionDisabled || isLoading}\n >\n {isLoading ? (\n <div className=\"border-primary-foreground size-5 animate-spin rounded-full border-4 border-t-4 border-t-transparent\" />\n ) : (\n t(\"pause_dialog_action\")\n )}\n </Button>\n </div>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import { parse } from \"date-fns\";\n\nconst ISO_DATE = \"yyyy-MM-dd\";\n\n/**\n * Parse an ISO date string as local midnight. Accepts either a bare\n * \"yyyy-MM-dd\" or a full ISO timestamp — both are sliced to the date\n * portion first so the result lands on the intended calendar day\n * regardless of the viewer's timezone.\n */\nexport function parseIsoDate(value: string): Date {\n return parse(value.slice(0, 10), ISO_DATE, new Date());\n}\n","import type React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Button,\n Calendar,\n cn,\n DialogFooter,\n Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n PortalContainerProvider,\n} from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { addDays, format } from \"date-fns\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { formatLongDate } from \"../lib/format\";\nimport { parseIsoDate } from \"../lib/parse-iso-date\";\n\nexport interface ResumeSubscriptionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: (nextBillDate: string) => void;\n isLoading?: boolean;\n errorMessage?: string;\n /** Seeds the calendar; must be in the future. Defaults to tomorrow. */\n defaultNextBillDate?: string | null;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function ResumeSubscriptionDialog({\n open,\n onOpenChange,\n onConfirm,\n isLoading,\n errorMessage,\n defaultNextBillDate,\n presentation = \"dialog\",\n}: ResumeSubscriptionDialogProps): React.JSX.Element {\n const { t, locale } = useSubscriptionsTranslation();\n const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);\n const [calendarOpen, setCalendarOpen] = useState(false);\n // Anchor the popover's portal inside the dialog so Safari doesn't swallow\n // clicks on the calendar — Radix renders the popover into document.body by\n // default, but Dialog applies pointer-events: none to the body while open,\n // which kills clicks on a body-portaled popover in Safari/WebKit.\n const [popoverContainer, setPopoverContainer] =\n useState<HTMLDivElement | null>(null);\n\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n const minDate = addDays(today, 1);\n\n // Seed selected date when the dialog opens.\n useEffect(() => {\n if (!open) return;\n if (defaultNextBillDate) {\n const seeded = parseIsoDate(defaultNextBillDate);\n setSelectedDate(seeded < minDate ? minDate : seeded);\n } else {\n setSelectedDate(minDate);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, defaultNextBillDate]);\n\n const handleConfirm = () => {\n if (!selectedDate) return;\n onConfirm(format(selectedDate, \"yyyy-MM-dd\"));\n };\n\n const handleDismiss = (next: boolean) => {\n if (!next) {\n setSelectedDate(undefined);\n // Reset so the calendar never reopens already-open: the popover's portal\n // container unmounts on close, and reopening with it still open would\n // render into document.body for a frame, reviving the Safari click bug.\n setCalendarOpen(false);\n }\n onOpenChange(next);\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleDismiss}\n title={t(\"resume_dialog_title\")}\n description={t(\"resume_dialog_description\")}\n presentation={presentation}\n // Let the calendar popover float past the modal edge instead of being\n // cropped by the dialog's default overflow-hidden. The popover stays\n // portaled inside the dialog (see below) so WebKit still delivers its\n // clicks; this only stops the content box from clipping it.\n contentOverflow=\"visible\"\n >\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label className=\"text-foreground text-sm font-semibold\">\n {t(\"resume_date\")}\n </Label>\n {/* Render the popover into a fixed-positioned overlay nested inside\n the dialog rather than document.body. This sidesteps the\n WebKit/Safari issue where Dialog's body-level pointer-events:\n none silently blocks clicks on a body-portaled popover. The\n fixed overlay is `inset-0` + `pointer-events-none` so it doesn't\n capture stray clicks or affect dialog layout — only the popover\n content (which sets its own pointer-events: auto) is\n interactive. */}\n <PortalContainerProvider container={popoverContainer}>\n <Popover open={calendarOpen} onOpenChange={setCalendarOpen}>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n className={cn(\n \"border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground h-9 w-full justify-start border px-3 py-2 text-left font-normal\",\n !selectedDate &&\n \"text-muted-foreground hover:text-muted-foreground\",\n )}\n >\n {selectedDate ? (\n format(selectedDate, \"MM/dd/yyyy\")\n ) : (\n <span>{t(\"date_placeholder\")}</span>\n )}\n <CalendarIcon className=\"text-muted-foreground ml-auto size-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"bg-popover pointer-events-auto z-[9999] w-auto rounded-md border p-0 shadow-lg\"\n align=\"start\"\n sideOffset={4}\n >\n <Calendar\n mode=\"single\"\n selected={selectedDate}\n onSelect={(date) => {\n setSelectedDate(date);\n setCalendarOpen(false);\n }}\n disabled={(date) => date < minDate}\n defaultMonth={selectedDate}\n modifiersStyles={{\n selected: {\n backgroundColor: \"var(--primary)\",\n color: \"var(--primary-foreground)\",\n },\n }}\n initialFocus\n />\n </PopoverContent>\n </Popover>\n </PortalContainerProvider>\n <div\n ref={setPopoverContainer}\n className=\"pointer-events-none fixed inset-0 z-[9998]\"\n />\n {selectedDate && (\n <p className=\"text-muted-foreground text-xs\">\n {t(\"resume_charge_message_prefix\")}{\" \"}\n <span className=\"font-semibold\">\n {formatLongDate(selectedDate, locale)}\n </span>\n {t(\"resume_charge_message_suffix\")}\n </p>\n )}\n </div>\n </div>\n\n {errorMessage && (\n <p className=\"text-destructive text-left text-sm\">{errorMessage}</p>\n )}\n\n <DialogFooter>\n <div className=\"flex w-full flex-row justify-between gap-x-2\">\n <Button\n className=\"bg-muted text-foreground ring-border hover:bg-muted/80 h-10 min-w-[70px] rounded p-3 ring-1\"\n onClick={() => handleDismiss(false)}\n >\n {t(\"resume_dialog_cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"bg-primary text-primary-foreground h-10 min-w-[70px] rounded p-3 hover:opacity-90 disabled:opacity-50\"\n onClick={handleConfirm}\n disabled={!selectedDate || isLoading}\n >\n {isLoading ? (\n <div className=\"border-primary-foreground size-5 animate-spin rounded-full border-4 border-t-4 border-t-transparent\" />\n ) : (\n t(\"resume_dialog_action\")\n )}\n </Button>\n </div>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import type React from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { getMaxEditableBillDate } from \"@fluid-app/subscriptions-core/utils/subscription-helpers\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Button,\n Calendar,\n cn,\n DialogFooter,\n Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n PortalContainerProvider,\n} from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport {\n addDays,\n addMonths,\n addWeeks,\n addYears,\n format,\n isAfter,\n} from \"date-fns\";\nimport { CalendarIcon, ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { formatLongDate, formatMediumDate } from \"../lib/format\";\nimport { parseIsoDate } from \"../lib/parse-iso-date\";\n\nexport interface OtherSubscriptionForBillDate {\n token: string;\n productTitle: string;\n nextBillDate: string | null;\n billingInterval: number;\n billingIntervalUnit: string;\n}\n\nfunction advanceByInterval(date: Date, interval: number, unit: string): Date {\n const step = Math.max(1, interval);\n switch (unit.toLowerCase()) {\n case \"day\":\n return addDays(date, step);\n case \"week\":\n return addWeeks(date, step);\n case \"year\":\n return addYears(date, step);\n case \"month\":\n default:\n return addMonths(date, step);\n }\n}\n\nconst SUBSCRIPTION_COLORS = [\n \"#3b82f6\",\n \"#f97316\",\n \"#10b981\",\n \"#a855f7\",\n \"#ec4899\",\n \"#eab308\",\n \"#14b8a6\",\n \"#ef4444\",\n \"#0ea5e9\",\n \"#84cc16\",\n];\n\n// Cap projection iterations per subscription so a daily-interval row can't\n// run away tens of thousands of times across the 2-year horizon. Sized for\n// a weekly cycle (~104 over two years) — covers the longest realistic\n// non-daily case without truncating dots for the rep.\nconst MAX_PROJECTIONS_PER_SUB = 104;\n\nexport interface EditBillDateDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: (nextBillDate: string) => void;\n isLoading?: boolean;\n errorMessage?: string;\n currentNextBillDate?: string | null;\n billingInterval?: number;\n billingIntervalUnit?: string;\n otherSubscriptions?: OtherSubscriptionForBillDate[];\n onNavigateToSubscription?: (token: string) => void;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function EditBillDateDialog({\n open,\n onOpenChange,\n onConfirm,\n isLoading,\n errorMessage,\n currentNextBillDate,\n billingInterval = 1,\n billingIntervalUnit = \"month\",\n otherSubscriptions,\n onNavigateToSubscription,\n presentation = \"dialog\",\n}: EditBillDateDialogProps): React.JSX.Element {\n const { t, locale } = useSubscriptionsTranslation();\n const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);\n const [calendarOpen, setCalendarOpen] = useState(false);\n // Anchor the popover's portal inside the dialog so Safari doesn't\n // swallow clicks on the calendar — Radix renders the popover into\n // document.body by default, but Dialog applies pointer-events: none\n // to the body while open, which kills clicks on a body-portaled\n // popover in Safari/WebKit specifically.\n const [popoverContainer, setPopoverContainer] =\n useState<HTMLDivElement | null>(null);\n\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n const minDate = addDays(today, 1);\n // Yearly plans may move their bill date up to 2 years out, everything\n // else up to 12 months out.\n const maxDate = getMaxEditableBillDate(\n billingInterval,\n billingIntervalUnit,\n today,\n );\n\n const subscriptionsWithColor = useMemo(\n () =>\n (otherSubscriptions ?? []).map((sub, idx) => ({\n ...sub,\n color: SUBSCRIPTION_COLORS[idx % SUBSCRIPTION_COLORS.length] as string,\n })),\n [otherSubscriptions],\n );\n\n const billingColorsByDate = useMemo<Map<string, string[]>>(() => {\n const m = new Map<string, string[]>();\n const horizon = addYears(new Date(), 2);\n for (const sub of subscriptionsWithColor) {\n if (!sub.nextBillDate) continue;\n let d = parseIsoDate(sub.nextBillDate);\n let count = 0;\n while (!isAfter(d, horizon) && count < MAX_PROJECTIONS_PER_SUB) {\n const key = format(d, \"yyyy-MM-dd\");\n const arr = m.get(key) ?? [];\n arr.push(sub.color);\n m.set(key, arr);\n d = advanceByInterval(d, sub.billingInterval, sub.billingIntervalUnit);\n count++;\n }\n }\n return m;\n }, [subscriptionsWithColor]);\n\n // Memoize the components map: react-day-picker uses each entry's identity\n // as the React element type for every day cell, so a fresh object every\n // render unmounts/remounts all visible cells (visible flicker, lost cell\n // state).\n const calendarComponents = useMemo(\n () => ({\n DayContent: ({ date }: { date: Date }) => {\n const key = format(date, \"yyyy-MM-dd\");\n const colors = billingColorsByDate.get(key) ?? [];\n return (\n <div className=\"flex h-full w-full flex-col items-center justify-center\">\n <span className=\"leading-none\">{date.getDate()}</span>\n {colors.length > 0 && (\n <div className=\"mt-0.5 flex items-center justify-center gap-0.5\">\n {colors.map((c, i) => (\n <span\n key={`${key}-${i}`}\n className=\"size-1 rounded-[1px]\"\n style={{ backgroundColor: c }}\n />\n ))}\n </div>\n )}\n </div>\n );\n },\n IconLeft: ({\n className: iconClassName,\n ...iconProps\n }: React.ComponentProps<typeof ChevronLeft>) => (\n <ChevronLeft className={cn(\"h-4 w-4\", iconClassName)} {...iconProps} />\n ),\n IconRight: ({\n className: iconClassName,\n ...iconProps\n }: React.ComponentProps<typeof ChevronRight>) => (\n <ChevronRight className={cn(\"h-4 w-4\", iconClassName)} {...iconProps} />\n ),\n }),\n [billingColorsByDate],\n );\n\n useEffect(() => {\n if (!open) return;\n if (currentNextBillDate) {\n const initial = parseIsoDate(currentNextBillDate);\n setSelectedDate(\n initial < minDate ? minDate : initial > maxDate ? maxDate : initial,\n );\n } else {\n setSelectedDate(undefined);\n }\n // minDate/maxDate derive from `new Date()` — intentionally excluded so\n // this only runs on open transitions.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, currentNextBillDate]);\n\n const handleConfirm = () => {\n if (!selectedDate) return;\n onConfirm(format(selectedDate, \"yyyy-MM-dd\"));\n };\n\n const handleDismiss = (next: boolean) => {\n if (!next) {\n setSelectedDate(undefined);\n // Reset so the calendar never reopens already-open: the popover's portal\n // container unmounts on close, and reopening with it still open would\n // render into document.body for a frame, reviving the Safari click bug.\n setCalendarOpen(false);\n }\n onOpenChange(next);\n };\n\n const previewDate = selectedDate\n ? formatLongDate(selectedDate, locale)\n : currentNextBillDate\n ? formatLongDate(parseIsoDate(currentNextBillDate), locale)\n : t(\"a_future_date\");\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleDismiss}\n title={t(\"edit_bill_date_title\")}\n description={t(\"edit_bill_date_description\")}\n presentation={presentation}\n // Let the calendar popover float past the modal edge instead of being\n // cropped by the dialog's default overflow-hidden. The popover stays\n // portaled inside the dialog (see below) so WebKit still delivers its\n // clicks; this only stops the content box from clipping it.\n contentOverflow=\"visible\"\n >\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label className=\"text-foreground text-sm font-semibold\">\n {t(\"next_bill_date_label\")}\n </Label>\n {/* Render the popover into a fixed-positioned overlay nested\n inside the dialog rather than document.body. This sidesteps\n the WebKit/Safari issue where Dialog's body-level\n pointer-events: none silently blocks clicks on a body-\n portaled popover. The fixed overlay is `inset-0` +\n `pointer-events-none` so it doesn't capture stray clicks\n or affect dialog layout — only the popover content\n (which sets its own pointer-events: auto) is interactive. */}\n <PortalContainerProvider container={popoverContainer}>\n <Popover open={calendarOpen} onOpenChange={setCalendarOpen}>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n className={cn(\n \"border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground h-9 w-full justify-start border px-3 py-2 text-left font-normal\",\n !selectedDate &&\n \"text-muted-foreground hover:text-muted-foreground\",\n )}\n >\n {selectedDate ? (\n format(selectedDate, \"MM/dd/yyyy\")\n ) : (\n <span>{t(\"date_placeholder\")}</span>\n )}\n <CalendarIcon className=\"text-muted-foreground ml-auto size-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"bg-popover pointer-events-auto z-[9999] w-auto rounded-md border p-0 shadow-lg\"\n align=\"start\"\n sideOffset={4}\n >\n <Calendar\n mode=\"single\"\n selected={selectedDate}\n onSelect={(date) => {\n setSelectedDate(date);\n setCalendarOpen(false);\n }}\n disabled={(date) => date < minDate || date > maxDate}\n defaultMonth={\n selectedDate ??\n (currentNextBillDate\n ? parseIsoDate(currentNextBillDate)\n : undefined)\n }\n components={calendarComponents}\n initialFocus\n />\n </PopoverContent>\n </Popover>\n </PortalContainerProvider>\n </div>\n <div\n ref={setPopoverContainer}\n className=\"pointer-events-none fixed inset-0 z-[9998]\"\n />\n\n {selectedDate && (\n <div className=\"text-muted-foreground text-xs\">\n {t(\"bill_date_preview_prefix\")}{\" \"}\n <span className=\"font-semibold\">{previewDate}</span>\n {t(\"bill_date_preview_suffix\")}\n </div>\n )}\n\n {subscriptionsWithColor.length > 0 && (\n <div className=\"space-y-2\">\n <Label className=\"text-foreground text-sm font-semibold\">\n {t(\"your_other_subscriptions\")}\n </Label>\n <div className=\"border-border max-h-40 overflow-auto rounded-md border\">\n <table className=\"w-full table-fixed text-sm\">\n <thead className=\"bg-muted text-muted-foreground sticky top-0\">\n <tr>\n <th\n className=\"w-6 p-2\"\n aria-label={t(\"other_subs_color_aria\")}\n />\n <th className=\"px-3 py-2 text-left font-medium\">\n {t(\"other_subs_product\")}\n </th>\n <th className=\"w-28 px-3 py-2 text-left font-medium\">\n {t(\"other_subs_bill_date\")}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-border divide-y\">\n {subscriptionsWithColor.map((sub) => (\n <tr key={sub.token}>\n <td className=\"p-2\">\n <span\n aria-hidden\n className=\"inline-block size-2.5 rounded-full\"\n style={{ backgroundColor: sub.color }}\n />\n </td>\n <td\n className=\"overflow-hidden px-3 py-2\"\n title={sub.productTitle}\n >\n {onNavigateToSubscription ? (\n <button\n type=\"button\"\n onClick={() => {\n onNavigateToSubscription(sub.token);\n handleDismiss(false);\n }}\n className=\"text-primary block w-full truncate text-left hover:underline\"\n >\n {sub.productTitle}\n </button>\n ) : (\n <span className=\"text-foreground block truncate\">\n {sub.productTitle}\n </span>\n )}\n </td>\n <td className=\"text-muted-foreground px-3 py-2 whitespace-nowrap\">\n {sub.nextBillDate\n ? formatMediumDate(\n parseIsoDate(sub.nextBillDate),\n locale,\n )\n : \"—\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )}\n </div>\n\n {errorMessage && (\n <p className=\"text-destructive text-left text-sm\">{errorMessage}</p>\n )}\n\n <DialogFooter>\n <div className=\"flex w-full flex-row justify-between gap-x-2\">\n <Button\n variant=\"outline\"\n className=\"h-10 min-w-[70px] rounded p-3\"\n onClick={() => handleDismiss(false)}\n >\n {t(\"edit_bill_date_cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"h-10 min-w-[70px] rounded p-3\"\n onClick={handleConfirm}\n disabled={!selectedDate || isLoading}\n >\n {isLoading ? (\n <div className=\"border-primary-foreground size-5 animate-spin rounded-full border-4 border-t-4 border-t-transparent\" />\n ) : (\n t(\"edit_bill_date_action\")\n )}\n </Button>\n </div>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { JSX } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nconst STATUS_COLORS: Record<string, string> = {\n active: \"bg-green-100 text-green-800\",\n paused: \"bg-gray-100 text-gray-800\",\n cancelled: \"bg-red-100 text-red-800\",\n pending: \"bg-yellow-100 text-yellow-800\",\n inactive: \"bg-gray-100 text-gray-800\",\n disabled: \"bg-red-100 text-red-800\",\n past_due: \"bg-gray-100 text-gray-800\",\n};\n\nconst STATUS_DOT_COLORS: Record<string, string> = {\n active: \"bg-green-500\",\n paused: \"bg-gray-400\",\n cancelled: \"bg-red-500\",\n pending: \"bg-yellow-500\",\n inactive: \"bg-gray-400\",\n disabled: \"bg-red-500\",\n past_due: \"bg-gray-400\",\n};\n\nexport interface StatusPillProps {\n status: string | undefined | null;\n children: React.ReactNode;\n}\n\nexport function StatusPill({ status, children }: StatusPillProps): JSX.Element {\n const key = status?.toLowerCase() ?? \"\";\n const pillColor = STATUS_COLORS[key] ?? \"bg-gray-100 text-gray-800\";\n const dotColor = STATUS_DOT_COLORS[key] ?? \"bg-gray-400\";\n\n return (\n <span\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium\",\n pillColor,\n )}\n >\n <span className={cn(\"h-1.5 w-1.5 rounded-full\", dotColor)} />\n {children}\n </span>\n );\n}\n","import type { JSX } from \"react\";\nimport { Button } from \"@fluid-app/ui-primitives\";\nimport { CreditCard, RefreshCw } from \"lucide-react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { cn } from \"../lib/cn\";\n\nexport interface PastDueBannerProps {\n productTitle?: string | null;\n // Body copy is derived from these three fields:\n // next_retry_at null → \"payment failed, update your card\"\n // next_retry_at set, decline_count = 1 → initial bill failed; first retry queued\n // → \"we'll try your payment again\"\n // next_retry_at set, decline_count >= 2 → at least one retry has already failed\n // and another is queued → \"the last\n // retry didn't go through\" copy with a\n // bucketed time estimate.\n // Using decline_count (not last_failed_at) is what distinguishes the\n // initial-failure state from the retry-failed state — last_failed_at is\n // populated on every failure including the first.\n nextRetryAt?: string | null;\n declineCount?: number | null;\n onUpdatePaymentClick?: () => void;\n onRetryPaymentClick?: () => void;\n onWaiveFailedCycleClick?: () => void;\n savedMethodLabel?: string | null;\n isRetryingPayment?: boolean;\n isCheckingWaiver?: boolean;\n recoveryDisabled?: boolean;\n className?: string;\n}\n\nexport function PastDueBanner({\n productTitle,\n nextRetryAt,\n declineCount,\n onUpdatePaymentClick,\n onRetryPaymentClick,\n onWaiveFailedCycleClick,\n savedMethodLabel,\n isRetryingPayment = false,\n isCheckingWaiver = false,\n recoveryDisabled = false,\n className,\n}: PastDueBannerProps): JSX.Element | null {\n const { t } = useSubscriptionsTranslation();\n const retryScheduled = nextRetryAt != null;\n // A retry has actually failed only when decline_count >= 2 — the first\n // failure (decline_count = 1) is the initial billing attempt, not a retry.\n // last_failed_at alone is not a sufficient signal: it's populated on every\n // failure including the first.\n const previousAttemptFailed = retryScheduled && (declineCount ?? 0) >= 2;\n\n const heading = retryScheduled\n ? productTitle\n ? t(\"past_due_banner_heading_retry_scheduled_for_product\", {\n product: productTitle,\n })\n : t(\"past_due_banner_heading_retry_scheduled\")\n : productTitle\n ? t(\"past_due_banner_heading_for_product\", { product: productTitle })\n : t(\"past_due_banner_heading\");\n\n // Bucket the time-until-next-retry into stable, readable ranges.\n // RetryFailedPaymentsJob ticks every 5 minutes (actual retry runs\n // within ~5 min of next_retry_at), so precision isn't load-bearing —\n // a hyper-precise countdown would churn on every render and read\n // like a to-the-second promise.\n // 2h backoff → \"in the next few hours\"\n // 6h backoff → \"in the next few hours\"\n // 24h backoff → \"within a day\"\n const whenLabel = (() => {\n if (!nextRetryAt) return t(\"past_due_retry_when_shortly\");\n const ms = new Date(nextRetryAt).getTime() - Date.now();\n if (ms < 60_000) return t(\"past_due_retry_when_shortly\");\n if (ms < 12 * 60 * 60 * 1000) return t(\"past_due_retry_when_few_hours\");\n return t(\"past_due_retry_when_within_day\");\n })();\n\n const body = previousAttemptFailed\n ? t(\"past_due_banner_body_retry_failed\", { when: whenLabel })\n : retryScheduled\n ? t(\"past_due_banner_body_retry_scheduled\")\n : t(\"past_due_banner_body\");\n const retryLabel = savedMethodLabel\n ? t(\"retry_saved_payment\", { method: savedMethodLabel })\n : t(\"retry_payment\");\n\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n \"border-destructive/50 bg-background rounded-xl border p-4 shadow-sm sm:p-5\",\n className,\n )}\n >\n <div className=\"flex items-start gap-3 sm:gap-4\">\n <div className=\"bg-destructive/10 text-destructive mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-full\">\n <CreditCard className=\"size-4\" aria-hidden />\n </div>\n <div className=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-foreground text-base font-bold tracking-tight sm:text-lg\">\n {heading}\n </h3>\n <p className=\"text-muted-foreground text-sm leading-relaxed\">\n {body}\n </p>\n </div>\n\n {(onRetryPaymentClick || onUpdatePaymentClick) && (\n <div className=\"flex flex-wrap gap-2\">\n {onRetryPaymentClick && (\n <Button\n type=\"button\"\n size=\"default\"\n onClick={onRetryPaymentClick}\n disabled={recoveryDisabled || isRetryingPayment}\n aria-busy={isRetryingPayment}\n className=\"active:scale-[0.99]\"\n >\n <span\n aria-hidden\n className={cn(\n \"inline-flex\",\n isRetryingPayment && \"animate-spin\",\n )}\n >\n <RefreshCw className=\"size-4\" />\n </span>\n {isRetryingPayment ? t(\"retrying_payment\") : retryLabel}\n </Button>\n )}\n {onUpdatePaymentClick && (\n <Button\n type=\"button\"\n variant={onRetryPaymentClick ? \"outline\" : \"default\"}\n size=\"default\"\n onClick={onUpdatePaymentClick}\n disabled={recoveryDisabled}\n className=\"active:scale-[0.99]\"\n >\n {t(\"change_payment_method\")}\n </Button>\n )}\n </div>\n )}\n\n {isCheckingWaiver ? (\n <span className=\"text-muted-foreground inline-flex items-center gap-1.5 text-xs\">\n <RefreshCw className=\"size-3 animate-spin\" aria-hidden />\n {t(\"checking_failed_cycle_waiver\")}\n </span>\n ) : (\n onWaiveFailedCycleClick && (\n <button\n type=\"button\"\n onClick={onWaiveFailedCycleClick}\n disabled={recoveryDisabled}\n className=\"text-muted-foreground hover:text-foreground w-fit text-left text-sm underline-offset-4 hover:underline disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {t(\"waive_failed_cycle\")}\n </button>\n )\n )}\n </div>\n </div>\n </div>\n );\n}\n","import type { JSX } from \"react\";\nimport {\n getFailedCycleWaiverSummary,\n type subscriptions,\n} from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\n\nexport interface FailedCycleWaiverDialogProps {\n open: boolean;\n preview: subscriptions.FailedCycleWaiverPreview | null;\n timezone: string;\n isPending: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function FailedCycleWaiverDialog({\n open,\n preview,\n timezone,\n isPending,\n onOpenChange,\n onConfirm,\n presentation = \"dialog\",\n}: FailedCycleWaiverDialogProps): JSX.Element {\n const { t, locale } = useSubscriptionsTranslation();\n const schedule =\n preview?.next_bill_date != null && preview.next_ship_date != null\n ? getFailedCycleWaiverSummary({\n nextBillDate: preview.next_bill_date,\n nextShipDate: preview.next_ship_date,\n locale,\n timezone,\n })\n : null;\n const canConfirm = preview?.eligible === true && schedule != null;\n\n const content = (\n <>\n {schedule != null && (\n <div className=\"border-border bg-muted/60 rounded-lg border px-4 py-3\">\n {schedule.kind === \"combined\" ? (\n <p className=\"text-foreground text-sm font-medium\">\n {t(\"failed_cycle_waiver_next_bill_and_ship\", {\n date: schedule.date,\n })}\n </p>\n ) : (\n <div className=\"space-y-1\">\n <p className=\"text-foreground text-sm font-medium\">\n {t(\"failed_cycle_waiver_next_bill\", {\n date: schedule.billDate,\n })}\n </p>\n <p className=\"text-foreground text-sm font-medium\">\n {t(\"failed_cycle_waiver_next_ship\", {\n date: schedule.shipDate,\n })}\n </p>\n </div>\n )}\n </div>\n )}\n\n <DialogFooter className=\"gap-2 sm:justify-between\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={isPending}\n >\n {t(\"failed_cycle_waiver_go_back\")}\n </Button>\n <Button\n type=\"button\"\n onClick={onConfirm}\n disabled={!canConfirm || isPending}\n aria-busy={isPending}\n >\n {isPending && (\n <span\n aria-hidden\n className=\"border-primary-foreground size-4 animate-spin rounded-full border-2 border-t-transparent\"\n />\n )}\n {t(\"failed_cycle_waiver_confirm\")}\n </Button>\n </DialogFooter>\n </>\n );\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!isPending) onOpenChange(nextOpen);\n };\n\n if (presentation === \"bottom-sheet\") {\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={t(\"failed_cycle_waiver_dialog_title\")}\n description={t(\"failed_cycle_waiver_dialog_description\")}\n presentation=\"bottom-sheet\"\n size=\"compact\"\n >\n {content}\n </ResponsiveDialog>\n );\n }\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent\n className=\"rounded-xl sm:max-w-md\"\n showCloseButton={!isPending}\n >\n <DialogHeader className=\"gap-2 text-left\">\n <DialogTitle className=\"text-xl font-semibold tracking-tight\">\n {t(\"failed_cycle_waiver_dialog_title\")}\n </DialogTitle>\n <DialogDescription className=\"text-sm leading-6\">\n {t(\"failed_cycle_waiver_dialog_description\")}\n </DialogDescription>\n </DialogHeader>\n {content}\n </DialogContent>\n </Dialog>\n );\n}\n","import type React from \"react\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { ImageOff } from \"lucide-react\";\nimport { formatCurrency, UNIT_KEYS } from \"../lib/format\";\n\nexport interface BundledWithCardProps {\n bundledSubscriptions: subscriptions.BundledSubscription[];\n /** Token of the subscription whose detail page this card renders on. */\n currentToken: string;\n /**\n * The parent subscription's plan. Bundle members share the parent's bill\n * date, so its cadence drives both the subhead (\"1 month\") and the per-row\n * plan label (\"Monthly Subscription\"). The lightweight bundled-subscription\n * payload carries no per-sibling plan of its own.\n */\n plan: subscriptions.SubscriptionDetailPlan;\n onNavigateToSubscription?: (token: string) => void;\n}\n\n/**\n * \"Bundled with subscription\" card shown on the subscription detail screen\n * between the upcoming-order summary and the product row. Lists the sibling\n * subscriptions that share this subscription's bill date and shipment. Renders\n * nothing when the subscription is not part of a bundle.\n */\nexport function BundledWithCard({\n bundledSubscriptions,\n currentToken,\n plan,\n onNavigateToSubscription,\n}: BundledWithCardProps): React.JSX.Element | null {\n const { t } = useSubscriptionsTranslation();\n\n const siblings = bundledSubscriptions.filter(\n (sib) => sib.subscription_token !== currentToken,\n );\n const firstSibling = siblings[0];\n if (!firstSibling) {\n return null;\n }\n\n const unit = plan.billing_interval_unit.toLowerCase();\n const interval = plan.billing_interval;\n const unitKeys = UNIT_KEYS[unit];\n\n // \"1 month\" / \"3 months\" — interval form for the subhead.\n const cadenceInterval = t(\"bundled_with_cadence_n_units\", {\n n: String(interval),\n unit: unitKeys\n ? interval === 1\n ? t(unitKeys.singular as \"unit_day\")\n : t(unitKeys.plural as \"unit_days\")\n : plan.billing_interval_unit,\n });\n\n // \"Monthly\" / \"Quarterly\" / \"Every 5 weeks\" — adjective form for row labels.\n let cadenceAdjective: string;\n if (interval === 1 && unit === \"day\")\n cadenceAdjective = t(\"list_cadence_daily\");\n else if (interval === 1 && unit === \"week\")\n cadenceAdjective = t(\"list_cadence_weekly\");\n else if (interval === 1 && unit === \"month\")\n cadenceAdjective = t(\"list_cadence_monthly\");\n else if (interval === 1 && unit === \"year\")\n cadenceAdjective = t(\"list_cadence_yearly\");\n else if (interval === 3 && unit === \"month\")\n cadenceAdjective = t(\"list_cadence_quarterly\");\n else\n cadenceAdjective = t(\"list_cadence_every_n_units\", {\n n: String(interval),\n unit: unitKeys\n ? t(unitKeys.plural as \"unit_days\")\n : plan.billing_interval_unit,\n });\n\n const rowPlanLabel = t(\"bundled_with_plan_label\", {\n cadence: cadenceAdjective,\n });\n const headerToken = `#${firstSibling.subscription_token.slice(-8).toUpperCase()}`;\n\n return (\n <div className=\"border-border bg-background my-3 rounded-xl border p-4\">\n <div className=\"text-foreground text-sm font-bold\">\n {t(\"bundled_with_title\")}{\" \"}\n {onNavigateToSubscription ? (\n <button\n type=\"button\"\n onClick={() =>\n onNavigateToSubscription(firstSibling.subscription_token)\n }\n className=\"text-primary focus-visible:ring-foreground/30 rounded font-bold hover:underline focus-visible:ring-2 focus-visible:outline-none\"\n >\n {headerToken}\n </button>\n ) : (\n <span className=\"text-primary font-bold\">{headerToken}</span>\n )}\n </div>\n <p className=\"text-muted-foreground mt-0.5 text-xs\">\n {t(\"bundled_with_subhead\", { cadence: cadenceInterval })}\n </p>\n\n <div className=\"mt-3 flex flex-col gap-0.5\">\n {siblings.map((sib) => {\n const rowContent = (\n <>\n <div className=\"bg-muted size-12 shrink-0 overflow-hidden rounded-lg\">\n {sib.image_url ? (\n <img\n src={sib.image_url}\n alt=\"\"\n className=\"size-full object-cover\"\n />\n ) : (\n <div className=\"text-muted-foreground flex size-full items-center justify-center\">\n <ImageOff className=\"size-4\" strokeWidth={1.75} />\n </div>\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p\n className=\"text-foreground truncate text-sm font-medium\"\n title={sib.product_title}\n >\n {sib.product_title || t(\"list_product_fallback\")}\n </p>\n {sib.variant_title && (\n <p className=\"text-muted-foreground truncate text-xs\">\n {sib.variant_title}\n </p>\n )}\n <p className=\"text-foreground text-sm font-medium\">\n {formatCurrency(sib.price)}\n </p>\n </div>\n <span className=\"text-muted-foreground shrink-0 text-xs\">\n {rowPlanLabel}\n </span>\n </>\n );\n\n return onNavigateToSubscription ? (\n <button\n key={sib.subscription_token}\n type=\"button\"\n onClick={() => onNavigateToSubscription(sib.subscription_token)}\n className=\"hover:bg-muted/60 focus-visible:ring-foreground/30 -mx-2 flex items-center gap-3 rounded-lg p-2 text-left transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n >\n {rowContent}\n </button>\n ) : (\n <div\n key={sib.subscription_token}\n className=\"-mx-2 flex items-center gap-3 rounded-lg p-2\"\n >\n {rowContent}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n","import { useState, useEffect, useMemo, useRef, useCallback } from \"react\";\nimport type React from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type {\n subscriptions,\n SubscriptionActionPolicy,\n} from \"@fluid-app/subscriptions-core\";\nimport {\n useSubscription,\n useSubscriptions,\n usePauseSubscription,\n useResumeSubscription,\n useSkipSubscription,\n useCancelSubscription,\n useReactivateSubscription,\n useRetryStatusPolling,\n useRetrySubscription,\n useFailedCycleWaiverPreview,\n useWaiveFailedCycle,\n useUpdateSubscriptionInfo,\n subscriptionsKeys,\n formatDate,\n formatOptionalDate,\n formatTime,\n getNextBillDisplay,\n calculateNextBillDate,\n computeSubscriptionPricing,\n getFailedCycleWaiverSummary,\n getSubscriptionActionPolicy,\n getSubscriptionDisplayStatus,\n hasPendingSubscriptionSkip,\n isSubscriptionCompleted,\n} from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n getPaymentBrandName,\n normalizeCardBrand,\n} from \"@fluid-app/payments-display/brands\";\nimport {\n isCardPaymentDescriptor,\n normalizePaymentDescriptor,\n paymentDescriptorLabel,\n resolvePaymentMethodDisplay,\n} from \"@fluid-app/payments-display/display\";\nimport type { ResolvedPaymentMethodDisplay } from \"@fluid-app/payments-display/ports\";\nimport {\n SkipForward,\n Pause,\n Play,\n XCircle,\n RotateCcw,\n CalendarDays,\n Ellipsis,\n Minus,\n Plus,\n} from \"lucide-react\";\nimport { addMonths, format } from \"date-fns\";\nimport {\n Badge,\n Skeleton,\n Button,\n Input,\n cn,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport { MobileActionSheet } from \"@fluid-app/ui-components/components/MobileActionSheet\";\nimport type { ResponsiveDialogPresentation } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport {\n CancelSubscriptionDialog,\n type PauseMonths,\n} from \"./cancel-subscription-dialog\";\nimport {\n PauseSubscriptionDialog,\n type PauseSubscriptionSelection,\n} from \"./pause-subscription-dialog\";\nimport { ResumeSubscriptionDialog } from \"./resume-subscription-dialog\";\nimport { EditBillDateDialog } from \"./edit-bill-date-dialog\";\nimport { StatusPill } from \"./status-pill\";\nimport { PastDueBanner } from \"./past-due-banner\";\nimport { FailedCycleWaiverDialog } from \"./failed-cycle-waiver-dialog\";\nimport { BundledWithCard } from \"./bundled-with-card\";\nimport {\n startCase,\n formatCurrency,\n KNOWN_STATUSES,\n UNIT_KEYS,\n} from \"../lib/format\";\n\n/** Map a billing_interval_unit to its shorthand cadence key (daily/weekly/…), or null. */\nfunction getCadenceKey(unit: string): string | null {\n switch (unit.toLowerCase()) {\n case \"day\":\n return \"daily\";\n case \"week\":\n return \"weekly\";\n case \"month\":\n return \"monthly\";\n case \"year\":\n return \"yearly\";\n default:\n return null;\n }\n}\n\nfunction isRecoveryStateChanged(error: unknown): boolean {\n // The envelope, so the shapes below are distinct server responses rather than\n // the same one read at two nesting levels to cover both producers.\n if (!isRecord(error) || error.status !== 422 || !isRecord(error.body)) {\n return false;\n }\n\n const body = error.body;\n const portalDetails = isRecord(body.error) ? body.error.details : undefined;\n const recoveryStates = [\n body.recovery_state,\n isRecord(portalDetails) ? portalDetails.recovery_state : undefined,\n isRecord(body.errors) ? body.errors.recovery_state : undefined,\n ];\n\n return recoveryStates.some(\n (recoveryState) =>\n Array.isArray(recoveryState) && recoveryState.includes(\"changed\"),\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport interface PaymentMethodSlotContext {\n paymentMethod: subscriptions.SubscriptionDetailPaymentMethod;\n subscriptionToken: string;\n customerId: number;\n countryCode: string;\n disabled: boolean;\n onRecoveryStateChange?: (state: {\n subscriptionToken: string;\n isBusy: boolean;\n }) => void;\n}\n\nexport interface ShippingAddressSlotContext {\n /**\n * Stable FK to the subscription's anchored address row. Prefer this\n * over `address.id` for identity comparisons — `address.id` is null\n * whenever the BE serves the snapshot rather than the live row.\n */\n addressId: number | null;\n address: subscriptions.SubscriptionDetailAddress | null;\n subscriptionToken: string;\n customerId: number;\n countryCode: string;\n disabled: boolean;\n}\n\nexport interface AutoApplyPointsSlotContext {\n /**\n * The customer's stored choice for this subscription. The control renders\n * from this rather than from a local default, so a reload shows what they\n * actually chose. `undefined` means the payload carried nothing.\n */\n autoApplyPoints?: boolean;\n /**\n * Whether the company runs a points program. The host is expected to render\n * nothing when this is false: a control that cannot act should not appear.\n */\n pointsEnabled?: boolean;\n subscriptionToken: string;\n disabled: boolean;\n /**\n * The set that will actually bill alongside this subscription, when the\n * payload carried one. Optional so hosts on a server that does not populate\n * it, and non-portal hosts that never render a bundle dialog, are\n * unaffected. Deliberately not `bundled_subscriptions`: that is the display\n * set and the two can legitimately differ.\n */\n renewalBundle?: subscriptions.SubscriptionRenewalBundle | null;\n}\n\nexport interface ReactivateDialogSlotContext {\n /** Whether the reactivate confirmation dialog is open. */\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /**\n * Run the reactivation. Pass the confirmed `addressId` to repoint the\n * subscription's shipping address, or omit it to keep the current one.\n */\n onConfirm: (params: { addressId?: number | null }) => void;\n /** True while the reactivation request is in flight. */\n isLoading: boolean;\n /** True when the last reactivation attempt failed — lets the dialog show inline feedback. */\n isError: boolean;\n subscriptionToken: string;\n}\n\ntype SubscriptionPaymentDetails = {\n last4?: string;\n last_four?: string;\n card_network?: string;\n card_brand?: string;\n logo_url?: string;\n};\n\nfunction resolveSubscriptionPaymentMethodDisplay(\n paymentMethod: subscriptions.SubscriptionDetailPaymentMethod,\n details: SubscriptionPaymentDetails | null,\n): ResolvedPaymentMethodDisplay {\n const last4 = details?.last4 ?? details?.last_four;\n const cardBrand =\n normalizeCardBrand(details?.card_brand) ??\n normalizeCardBrand(details?.card_network);\n const isCard =\n last4 != null ||\n normalizePaymentDescriptor(details?.card_brand) != null ||\n normalizePaymentDescriptor(details?.card_network) != null ||\n cardBrand != null ||\n isCardPaymentDescriptor(paymentMethod.source) ||\n isCardPaymentDescriptor(paymentMethod.payment_type);\n\n if (isCard) {\n return resolvePaymentMethodDisplay({\n kind: \"card\",\n brand: cardBrand,\n last4,\n logoUrl: details?.logo_url,\n });\n }\n\n const fallbackLabel = paymentDescriptorLabel(\n paymentMethod.payment_type,\n paymentMethod.source,\n );\n return resolvePaymentMethodDisplay({\n kind: \"non_card\",\n brand: fallbackLabel,\n fallbackLabel,\n logoUrl: details?.logo_url,\n });\n}\n\nfunction getSavedPaymentMethodLabel(\n paymentMethod: subscriptions.SubscriptionDetailPaymentMethod | null,\n): string | null {\n if (!paymentMethod) return null;\n\n const details =\n (paymentMethod.details as SubscriptionPaymentDetails | null) ?? null;\n const display = resolveSubscriptionPaymentMethodDisplay(\n paymentMethod,\n details,\n );\n\n if (display.kind === \"card\") {\n const last4 = details?.last4 ?? details?.last_four;\n const brandName = getPaymentBrandName(display.brand);\n return brandName && last4 ? `${brandName} •••• ${last4}` : null;\n }\n\n const descriptor = paymentDescriptorLabel(\n paymentMethod.payment_type,\n paymentMethod.source,\n );\n return descriptor ? display.label : null;\n}\n\nfunction PaymentMethodLogo({\n display,\n}: {\n display: ResolvedPaymentMethodDisplay;\n}) {\n const [logoErrored, setLogoErrored] = useState(false);\n const logoUrl = logoErrored\n ? display.logo.fallbackUrl\n : display.logo.primaryUrl;\n\n useEffect(() => {\n setLogoErrored(false);\n }, [display.logo.fallbackUrl, display.logo.primaryUrl]);\n\n return (\n <img\n src={logoUrl}\n alt={display.accessibilityLabel}\n className=\"h-6 max-w-16 shrink-0 object-contain\"\n onError={() => setLogoErrored(true)}\n />\n );\n}\n\nexport interface SubscriptionDetailProps {\n token: string;\n onNotFound?: () => void;\n onError?: (error: Error) => void;\n onSuccess?: (\n message: string,\n severity?: \"success\" | \"error\" | \"warning\",\n ) => void;\n onMutationError?: (message: string, error: unknown) => void;\n /**\n * Called when the Edit Bill Date dialog wants to navigate the host app to\n * another subscription's detail page (clicking a row in the calendar's\n * \"Your other subscriptions\" list).\n */\n onNavigateToSubscription?: (token: string) => void;\n /**\n * Optional render-prop for the Payment Method block. When provided, replaces\n * the read-only display so consumers can wire change/add UX. Default falls\n * back to a read-only summary.\n */\n renderPaymentMethod?: (ctx: PaymentMethodSlotContext) => React.JSX.Element;\n /**\n * Optional render-prop for the Shipping Address block. When provided,\n * replaces the read-only display so consumers can wire change/add UX.\n * Default falls back to a read-only summary.\n */\n renderShippingAddress?: (\n ctx: ShippingAddressSlotContext,\n ) => React.JSX.Element;\n /**\n * Optional render-prop for the auto-apply-points block. There is NO default\n * read-only fallback, unlike the slots above, and that asymmetry is\n * deliberate: baking a control into this component's default tree would ship\n * it to the checkout-hosted subscription screens as well, which is the\n * management surface O-6 defers to a later phase. A host that omits this slot\n * renders nothing, which is what keeps that deferral mechanical rather than\n * accidental.\n */\n renderAutoApplyPoints?: (\n ctx: AutoApplyPointsSlotContext,\n ) => React.JSX.Element;\n /**\n * Optional render-prop for the reactivation confirmation dialog. When\n * provided, clicking Reactivate opens the dialog so the consumer can\n * confirm a shipping address before reactivating (CURRENT-2204). When\n * omitted, Reactivate runs immediately against the current address.\n */\n renderReactivateDialog?: (\n ctx: ReactivateDialogSlotContext,\n ) => React.JSX.Element;\n /**\n * Called when the past-due banner's \"Update payment method\" button is\n * clicked. Consumers should open their Add Payment Method dialog. If\n * omitted, the banner falls back to scrolling the payment-method section\n * into view.\n */\n onUpdatePaymentClick?: () => void;\n presentation?: ResponsiveDialogPresentation;\n}\n\nfunction SubscriptionDetailSkeleton() {\n return (\n <div className=\"flex flex-col lg:grid lg:grid-cols-8\">\n {/* Left: items skeleton */}\n <div className=\"bg-muted flex flex-col items-center px-8 lg:col-span-4\">\n <div className=\"w-full max-w-lg py-6\">\n <Skeleton className=\"mb-4 h-6 w-48\" />\n <div className=\"grid grid-cols-2 gap-4\">\n <Skeleton className=\"h-16 w-full rounded\" />\n <Skeleton className=\"h-16 w-full rounded\" />\n </div>\n <div className=\"mt-6 flex items-center gap-x-4\">\n <Skeleton className=\"size-24 rounded\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-1/2\" />\n <Skeleton className=\"h-4 w-1/4\" />\n </div>\n </div>\n <div className=\"mt-6 space-y-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-5 w-full\" />\n </div>\n </div>\n </div>\n {/* Right: management skeleton */}\n <div className=\"bg-background col-span-4 px-8 pt-4\">\n <div className=\"mx-auto max-w-lg\">\n <Skeleton className=\"mb-3 h-5 w-32\" />\n <div className=\"grid grid-cols-2 gap-3\">\n <Skeleton className=\"h-10 w-full rounded\" />\n <Skeleton className=\"h-10 w-full rounded\" />\n </div>\n <div className=\"mt-6 space-y-4\">\n <Skeleton className=\"h-5 w-40\" />\n <div className=\"flex gap-4\">\n <Skeleton className=\"h-12 flex-1 rounded\" />\n <Skeleton className=\"h-12 flex-1 rounded\" />\n </div>\n </div>\n <div className=\"mt-6 space-y-4\">\n <Skeleton className=\"h-5 w-40\" />\n <Skeleton className=\"h-16 w-full rounded\" />\n <Skeleton className=\"h-16 w-full rounded\" />\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n/* ── Left column: product & order summary ──────────────────────────── */\n\n/* ── Quantity input ─────────────────────────────────────────────────\n The displayed value is local string state so the user can backspace\n a single-digit quantity without React snapping it back. We only\n forward valid positive integers to onQuantityChange; on blur we\n restore the last committed quantity if the field was left empty\n or invalid.\n\n Two focus-retention quirks worth keeping in mind:\n - Toggling `disabled` blurs a focused input (especially WebKit).\n Use `readOnly` while the mutation is in flight instead so the\n user keeps their cursor as they tweak the value.\n - We skip the prop-sync useEffect while the field is focused —\n writing `inputValue` again on a server confirmation doesn't change\n anything visible, but the controlled-input value write is enough\n to drop focus on mobile Safari. The post-blur restore on line ~186\n handles the unfocused case. */\n\nfunction QuantityInput({\n inputId,\n quantity,\n maxQuantity,\n isUpdatingQuantity,\n onQuantityChange,\n quantityAriaLabel,\n decrementAriaLabel,\n incrementAriaLabel,\n}: {\n inputId: string;\n quantity: number;\n maxQuantity: number | null;\n isUpdatingQuantity: boolean;\n onQuantityChange: (next: number) => void;\n quantityAriaLabel: string;\n decrementAriaLabel: string;\n incrementAriaLabel: string;\n}) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState(String(quantity));\n // Captured the moment focus enters the field. Backspacing from \"12\"\n // through \"1\" to \"\" commits an intermediate quantity of 1 to the\n // parent, so on blur we can't trust the live `quantity` prop as the\n // restore target — use the value the user started with.\n const focusEntryQuantityRef = useRef(quantity);\n // Local debounce on commit. Without this, every keystroke fires\n // onQuantityChange, which the parent uses to update pendingQuantity\n // synchronously — so intermediate values (e.g. the \"1\" mid-way through\n // backspacing \"12\" to retype) flash in the order summary before the\n // user is done typing.\n const commitTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // Keep the latest onQuantityChange in a ref so the debounced timer\n // doesn't fire with a stale closure if the parent re-renders within\n // the 500ms window with a new callback identity.\n const onQuantityChangeRef = useRef(onQuantityChange);\n useEffect(() => {\n onQuantityChangeRef.current = onQuantityChange;\n }, [onQuantityChange]);\n\n useEffect(\n () => () => {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current);\n },\n [],\n );\n\n useEffect(() => {\n if (\n typeof document !== \"undefined\" &&\n document.activeElement === inputRef.current\n ) {\n return;\n }\n setInputValue(String(quantity));\n }, [quantity]);\n\n const scheduleCommit = (next: number) => {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current);\n commitTimerRef.current = setTimeout(() => {\n onQuantityChangeRef.current(next);\n // Move the restore baseline forward — once a value successfully\n // commits, that's what an empty-blur should fall back to, not\n // the value at focus-entry.\n focusEntryQuantityRef.current = next;\n }, 500);\n };\n\n // Drive the +/− disabled state from the in-flight value so the buttons\n // stay in sync with what the user sees mid-edit, instead of lagging\n // 500ms behind the committed quantity.\n const parsedInput = parseInt(inputValue, 10);\n const currentValue =\n Number.isFinite(parsedInput) && parsedInput > 0 ? parsedInput : quantity;\n const decrementDisabled = isUpdatingQuantity || currentValue <= 1;\n const incrementDisabled =\n isUpdatingQuantity || (maxQuantity != null && currentValue >= maxQuantity);\n\n // Single clamp source so the typing path enforces the same min/max\n // window the +/− buttons gate visually — without this, typing 999 with\n // a max_quantity of 10 would commit 999 even though `+` is disabled.\n const clampToBounds = (n: number): number =>\n maxQuantity != null\n ? Math.min(maxQuantity, Math.max(1, n))\n : Math.max(1, n);\n\n const stepBy = (delta: 1 | -1) => {\n const clamped = clampToBounds(currentValue + delta);\n if (clamped === currentValue) return;\n setInputValue(String(clamped));\n scheduleCommit(clamped);\n };\n\n const stepperButtonClass = cn(\n \"text-muted-foreground hover:text-foreground hover:bg-muted flex h-7 w-7 shrink-0 items-center justify-center rounded-full shadow-xs disabled:cursor-not-allowed\",\n );\n\n return (\n <div\n className={cn(\n \"border-border bg-background focus-within:border-ring focus-within:ring-ring/50 flex h-7.5 items-center justify-between rounded-2xl border focus-within:ring-[3px]\",\n isUpdatingQuantity && \"opacity-60\",\n )}\n >\n <button\n type=\"button\"\n onClick={() => stepBy(-1)}\n disabled={decrementDisabled}\n aria-label={decrementAriaLabel}\n aria-controls={inputId}\n className={cn(stepperButtonClass, decrementDisabled && \"opacity-40\")}\n >\n <Minus className=\"size-3\" />\n </button>\n <Input\n ref={inputRef}\n id={inputId}\n type=\"number\"\n min={1}\n max={maxQuantity ?? undefined}\n step={1}\n value={inputValue}\n onFocus={() => {\n // Capture the displayed value, not the committed `quantity` —\n // a + click before focus updates inputValue but its 500ms\n // debounce may not have fired yet, so the committed prop is\n // stale. Without this, an erase-then-blur restores to the\n // pre-+ value and silently discards the click.\n focusEntryQuantityRef.current = currentValue;\n }}\n onChange={(e) => {\n const raw = e.target.value;\n setInputValue(raw);\n if (raw === \"\") {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current);\n return;\n }\n const next = parseInt(raw, 10);\n if (Number.isFinite(next) && next > 0) {\n scheduleCommit(clampToBounds(next));\n }\n }}\n onBlur={() => {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current);\n const parsed = parseInt(inputValue, 10);\n if (Number.isFinite(parsed) && parsed > 0) {\n const clamped = clampToBounds(parsed);\n // Snap the displayed value back to the cap on blur so the\n // user sees the bound that was applied to the committed value.\n if (clamped !== parsed) {\n setInputValue(String(clamped));\n }\n if (clamped !== quantity) {\n onQuantityChange(clamped);\n }\n focusEntryQuantityRef.current = clamped;\n } else {\n const restore = focusEntryQuantityRef.current;\n setInputValue(String(restore));\n if (restore !== quantity) {\n onQuantityChange(restore);\n }\n }\n }}\n readOnly={isUpdatingQuantity}\n className=\"text-foreground h-7 w-10 rounded-none border-0 bg-transparent px-0 text-center text-xs font-semibold shadow-none [-moz-appearance:textfield] focus-visible:border-0 focus-visible:ring-0 md:text-xs [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none\"\n aria-label={quantityAriaLabel}\n />\n <button\n type=\"button\"\n onClick={() => stepBy(1)}\n disabled={incrementDisabled}\n aria-label={incrementAriaLabel}\n aria-controls={inputId}\n className={cn(stepperButtonClass, incrementDisabled && \"opacity-40\")}\n >\n <Plus className=\"size-3\" />\n </button>\n </div>\n );\n}\n\n/**\n * One itemized discount row in the pricing summary: label, optional code\n * pill(s), and a negative amount. Codes render as pills on the line rather than\n * baked into the label text. `code` accepts a single code or a list so stacked\n * codes are supported if the pricing model ever exposes more than one.\n */\nfunction DiscountLine({\n label,\n amount,\n code,\n}: {\n label: string;\n amount: string;\n code?: string | string[] | null;\n}) {\n const codes = (Array.isArray(code) ? code : code ? [code] : []).filter(\n Boolean,\n );\n return (\n <div className=\"mt-2 flex items-start justify-between gap-2 text-sm\">\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1\">\n <p className=\"text-muted-foreground text-sm font-medium\">{label}</p>\n {codes.map((c, i) => (\n <Badge key={`${c}-${i}`} variant=\"secondary\">\n {c}\n </Badge>\n ))}\n </div>\n <p className=\"text-muted-foreground text-sm font-medium whitespace-nowrap\">\n -{amount}\n </p>\n </div>\n );\n}\n\nfunction SubscriptionItemsSection({\n subscription,\n displayQuantity,\n displayNextBillDate,\n canEditQuantity = false,\n onQuantityChange,\n isUpdatingQuantity = false,\n onNavigateToSubscription,\n}: {\n subscription: subscriptions.SubscriptionDetailSubscription;\n displayQuantity?: number;\n displayNextBillDate?: string;\n canEditQuantity?: boolean;\n onQuantityChange?: (next: number) => void;\n isUpdatingQuantity?: boolean;\n onNavigateToSubscription?: (token: string) => void;\n}) {\n const { t, locale } = useSubscriptionsTranslation();\n const variant = subscription.variant;\n const product = variant?.product;\n const quantity = displayQuantity ?? subscription.quantity;\n const displayStatus = getSubscriptionDisplayStatus(subscription);\n const paymentFailed = displayStatus === \"past_due\";\n const quantityInputId = `subscription-${subscription.subscription_token}-quantity`;\n const pricing = computeSubscriptionPricing(subscription);\n const subtotal = formatCurrency(pricing.subtotalUnit * quantity);\n const totalPrice = formatCurrency(pricing.totalUnit * quantity);\n const effectiveNextBillDate =\n displayNextBillDate ?? subscription.next_bill_date;\n const nextOrderTimeOfDay =\n displayStatus === \"completed\"\n ? \"\"\n : formatTime(effectiveNextBillDate, subscription.timezone, locale);\n const nextBillDisplayLabels = {\n cancelled: t(\"date_cancelled\"),\n completed: t(\"list_status_completed\"),\n paused: t(\"date_paused\"),\n notAvailable: t(\"date_not_available\"),\n };\n\n return (\n <section className=\"bg-muted flex w-full flex-col items-center rounded-lg p-8 lg:col-span-4 lg:self-start\">\n <div className=\"flex w-full max-w-lg flex-col\">\n {/* Upcoming order summary */}\n <div>\n <h2 className=\"text-foreground mb-2 text-lg font-medium\">\n {t(\"your_upcoming_order\")}\n </h2>\n <div className=\"text-muted-foreground\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"border-border border-r pr-4\">\n <div className=\"text-muted-foreground mb-1 text-sm\">\n {paymentFailed\n ? t(\"payment_failed_on\")\n : t(\"next_order_date\")}\n </div>\n <div className=\"text-foreground text-2xl font-bold\">\n {paymentFailed\n ? subscription.last_failed_at\n ? formatOptionalDate(subscription.last_failed_at, locale)\n : \"—\"\n : getNextBillDisplay(\n effectiveNextBillDate,\n displayStatus,\n nextBillDisplayLabels,\n locale,\n )}\n </div>\n {nextOrderTimeOfDay && (\n <div className=\"text-muted-foreground mt-1 text-xs\">\n {nextOrderTimeOfDay} ({subscription.timezone})\n </div>\n )}\n </div>\n <div className=\"pl-4\">\n <div className=\"text-muted-foreground mb-1 text-sm\">\n {t(\"next_bill_amount\")}\n </div>\n <div className=\"text-foreground text-2xl font-bold\">\n {totalPrice}\n </div>\n </div>\n </div>\n <hr className=\"border-border mt-4\" />\n </div>\n </div>\n\n <BundledWithCard\n bundledSubscriptions={subscription.bundled_subscriptions ?? []}\n currentToken={subscription.subscription_token}\n plan={subscription.subscription_plan}\n onNavigateToSubscription={onNavigateToSubscription}\n />\n\n {/* Product row */}\n <div className=\"py-6\">\n <div className=\"flex flex-row items-center gap-x-4\">\n <div className=\"flex min-w-0 flex-1 flex-row gap-x-4\">\n <div className=\"relative shrink-0\">\n <div className=\"bg-muted h-24 w-24 overflow-hidden rounded\">\n {product?.image_url ? (\n <img\n src={product.image_url}\n alt={variant?.title || t(\"product_image_alt\")}\n width={96}\n height={96}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"text-muted-foreground flex size-full items-center justify-center\">\n {t(\"no_image\")}\n </div>\n )}\n {quantity > 1 && (\n <span className=\"bg-foreground text-background absolute -top-2 -right-2 z-10 flex h-6 w-6 items-center justify-center rounded-full text-xs font-medium\">\n {quantity}\n </span>\n )}\n </div>\n </div>\n <div className=\"flex min-w-0 flex-col gap-y-0.5\">\n <p\n className=\"text-foreground truncate text-sm font-medium\"\n title={product?.title}\n >\n {product?.title}\n </p>\n {variant?.title && product?.title && (\n <p className=\"text-muted-foreground text-sm\">\n {variant.title}\n </p>\n )}\n <div>\n <p className=\"text-foreground text-sm font-medium\">\n {formatCurrency(subscription.price * quantity)}\n </p>\n </div>\n </div>\n </div>\n {canEditQuantity && onQuantityChange && (\n <div className=\"flex shrink-0 flex-col items-center\">\n <label\n htmlFor={quantityInputId}\n className=\"text-muted-foreground mb-1 text-xs\"\n >\n {t(\"quantity_label\")}\n </label>\n <QuantityInput\n inputId={quantityInputId}\n quantity={quantity}\n maxQuantity={subscription.subscription_plan.max_quantity}\n isUpdatingQuantity={isUpdatingQuantity}\n onQuantityChange={onQuantityChange}\n quantityAriaLabel={t(\"quantity_aria\")}\n decrementAriaLabel={t(\"decrease_quantity_aria\")}\n incrementAriaLabel={t(\"increase_quantity_aria\")}\n />\n </div>\n )}\n </div>\n </div>\n\n {/* Pricing summary */}\n <div>\n {pricing.hasDiscount && (\n <>\n <div className=\"flex justify-between text-sm\">\n <p className=\"text-muted-foreground text-sm font-medium\">\n {t(\"subtotal\")}\n </p>\n <p className=\"text-muted-foreground text-sm font-medium\">\n {subtotal}\n </p>\n </div>\n {pricing.attachedDiscountUnit > 0 && (\n <DiscountLine\n label={t(\"discount\")}\n code={pricing.attachedDiscountCode}\n amount={formatCurrency(\n pricing.attachedDiscountUnit * quantity,\n )}\n />\n )}\n </>\n )}\n <div className=\"mt-4 flex items-center justify-between text-base font-medium\">\n <p className=\"text-muted-foreground text-sm font-medium\">\n {t(\"total_label\")}\n </p>\n <p className=\"text-foreground text-base font-bold\">{totalPrice}</p>\n </div>\n <span className=\"text-muted-foreground text-xs\">\n {t(\"tax_shipping_note\")}\n </span>\n </div>\n </div>\n </section>\n );\n}\n\n/* ── Right column: actions & details ───────────────────────────────── */\n\nfunction SubscriptionManagementSection({\n subscription,\n actionPolicy,\n isMutating,\n paymentMethodDisabled,\n onPaymentRecoveryStateChange,\n onSkip,\n onPause,\n onResume,\n onCancel,\n onReactivate,\n onEditBillDate,\n renderPaymentMethod,\n renderShippingAddress,\n renderAutoApplyPoints,\n presentation,\n}: {\n subscription: subscriptions.SubscriptionDetailSubscription;\n actionPolicy: SubscriptionActionPolicy;\n isMutating: boolean;\n paymentMethodDisabled: boolean;\n onPaymentRecoveryStateChange: (state: {\n subscriptionToken: string;\n isBusy: boolean;\n }) => void;\n onSkip: () => void;\n onPause: () => void;\n onResume: () => void;\n onCancel: () => void;\n onReactivate: () => void;\n onEditBillDate: () => void;\n renderPaymentMethod?: (ctx: PaymentMethodSlotContext) => React.JSX.Element;\n renderShippingAddress?: (\n ctx: ShippingAddressSlotContext,\n ) => React.JSX.Element;\n renderAutoApplyPoints?: (\n ctx: AutoApplyPointsSlotContext,\n ) => React.JSX.Element;\n presentation: ResponsiveDialogPresentation;\n}) {\n const { t, locale } = useSubscriptionsTranslation();\n const [actionMenuOpen, setActionMenuOpen] = useState(false);\n const plan = subscription.subscription_plan;\n const quantity = subscription.quantity;\n const totalPrice = formatCurrency(subscription.price * quantity);\n const displayStatus = getSubscriptionDisplayStatus(subscription);\n\n const cadenceKey = getCadenceKey(plan.billing_interval_unit);\n const interval = plan.billing_interval;\n const unitKeys = UNIT_KEYS[plan.billing_interval_unit.toLowerCase()];\n\n let cadenceLabel: string;\n if (interval === 1 && cadenceKey) {\n cadenceLabel = t(`list_cadence_${cadenceKey}` as \"list_cadence_monthly\");\n } else if (unitKeys) {\n cadenceLabel = t(\"list_cadence_every_n_units\", {\n n: String(interval),\n unit: t(unitKeys.plural as \"unit_days\"),\n });\n } else {\n cadenceLabel = t(\"list_cadence_every_unit\", {\n unit: startCase(plan.billing_interval_unit),\n });\n }\n\n const paymentMethod = subscription.payment_method;\n const paymentDetails =\n (paymentMethod?.details as SubscriptionPaymentDetails | null) ?? null;\n const paymentDisplay = paymentMethod\n ? resolveSubscriptionPaymentMethodDisplay(paymentMethod, paymentDetails)\n : null;\n\n const actionButtonClass =\n \"flex h-auto flex-row items-center justify-center gap-2 overflow-hidden border border-border bg-muted py-2 text-xs whitespace-nowrap text-foreground hover:bg-accent sm:text-sm\";\n\n return (\n <div className=\"bg-background col-span-4 flex-auto px-8 pt-4\">\n <div className=\"mx-auto max-w-lg lg:mx-0 lg:mr-auto\">\n {actionPolicy.order.length > 0 && (\n <div className=\"border-border mb-6 border-b pb-6\">\n <h2 className=\"text-foreground mb-3 text-sm/6 font-semibold\">\n {t(\"your_upcoming_order\")}\n </h2>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {actionPolicy.order.includes(\"skip_next_order\") && (\n <Button\n variant=\"outline\"\n onClick={onSkip}\n disabled={isMutating || !subscription.next_bill_date}\n className={actionButtonClass}\n >\n <SkipForward className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{t(\"skip_next_order\")}</span>\n </Button>\n )}\n {actionPolicy.order.includes(\"edit_bill_date\") && (\n <Button\n variant=\"outline\"\n onClick={onEditBillDate}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <CalendarDays className=\"size-3 shrink-0\" />\n <span className=\"truncate\">{t(\"edit_bill_date\")}</span>\n </Button>\n )}\n </div>\n </div>\n )}\n\n {/* Subscription Details */}\n <div className=\"border-border mb-4 border-b\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h3 className=\"text-foreground text-sm/6 font-semibold\">\n {t(\"subscription_details\")}\n </h3>\n <div className=\"flex items-center gap-2\">\n <StatusPill status={displayStatus}>\n {KNOWN_STATUSES.has(displayStatus)\n ? t(`list_status_${displayStatus}` as \"list_status_active\")\n : startCase(displayStatus)}\n </StatusPill>\n {actionPolicy.menu.length > 0 &&\n (presentation === \"bottom-sheet\" ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n disabled={isMutating}\n aria-label={t(\"more_subscription_actions\")}\n onClick={() => setActionMenuOpen(true)}\n >\n <Ellipsis className=\"size-4\" aria-hidden />\n </Button>\n <MobileActionSheet\n open={actionMenuOpen}\n onOpenChange={setActionMenuOpen}\n title={t(\"more_subscription_actions\")}\n actions={[\n ...(actionPolicy.menu.includes(\"pause_subscription\")\n ? [\n {\n id: \"pause\",\n label: t(\"pause_subscription\"),\n onSelect: onPause,\n },\n ]\n : []),\n ...(actionPolicy.menu.includes(\"cancel_subscription\")\n ? [\n {\n id: \"cancel\",\n label: t(\"cancel_subscription\"),\n variant: \"destructive\" as const,\n onSelect: onCancel,\n },\n ]\n : []),\n ]}\n />\n </>\n ) : (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n disabled={isMutating}\n aria-label={t(\"more_subscription_actions\")}\n >\n <Ellipsis className=\"size-4\" aria-hidden />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {actionPolicy.menu.includes(\"pause_subscription\") && (\n <DropdownMenuItem onSelect={onPause}>\n <Pause className=\"size-4\" aria-hidden />\n {t(\"pause_subscription\")}\n </DropdownMenuItem>\n )}\n {actionPolicy.menu.includes(\"cancel_subscription\") && (\n <DropdownMenuItem\n onSelect={onCancel}\n className=\"text-destructive focus:text-destructive\"\n >\n <XCircle className=\"size-4\" aria-hidden />\n {t(\"cancel_subscription\")}\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n ))}\n </div>\n </div>\n {actionPolicy.primary === \"resume_subscription\" && (\n <Button\n type=\"button\"\n onClick={onResume}\n disabled={isMutating}\n className=\"mb-4 w-full\"\n >\n <Play className=\"size-4\" aria-hidden />\n {t(\"resume_subscription\")}\n </Button>\n )}\n {actionPolicy.primary === \"reactivate_subscription\" && (\n <Button\n type=\"button\"\n onClick={onReactivate}\n disabled={isMutating}\n className=\"mb-4 w-full\"\n >\n <RotateCcw className=\"size-4\" aria-hidden />\n {t(\"reactivate_subscription\")}\n </Button>\n )}\n <div className=\"divide-border mb-4 flex divide-x\">\n <div className=\"flex-1 pr-4\">\n <div className=\"text-muted-foreground text-sm\">\n {t(\"order_frequency\")}\n </div>\n <div className=\"text-foreground font-medium\">{cadenceLabel}</div>\n </div>\n {subscription.last_ship_date && (\n <div className=\"flex-1 px-4\">\n <div className=\"text-muted-foreground text-sm\">\n {t(\"last_shipped\")}\n </div>\n <div className=\"text-foreground font-medium\">\n {formatOptionalDate(subscription.last_ship_date, locale)}\n </div>\n </div>\n )}\n {subscription.last_bill_date && (\n <div className=\"flex-1 px-4\">\n <div className=\"text-muted-foreground text-sm\">\n {t(\"last_bill_amount\")}\n </div>\n <div className=\"text-foreground font-medium\">{totalPrice}</div>\n <div className=\"text-muted-foreground text-xs\">\n {formatDate(subscription.last_bill_date, locale)}\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Payment & Shipping */}\n <div className=\"pt-2\">\n <h3 className=\"text-foreground mb-4 text-sm/6 font-semibold\">\n {t(\"payment_and_shipping\")}\n </h3>\n <div className=\"flex flex-col\">\n {/* Shipping Address */}\n {renderShippingAddress\n ? renderShippingAddress({\n addressId: subscription.address_id,\n address: subscription.address,\n subscriptionToken: subscription.subscription_token,\n customerId: subscription.customer?.id ?? 0,\n countryCode: subscription.address?.country_code ?? \"US\",\n disabled: isSubscriptionCompleted(subscription),\n })\n : subscription.address && (\n <div className=\"border-border mb-6 border-b pb-4\">\n <div className=\"text-muted-foreground mt-3 mb-1 text-sm\">\n {t(\"shipping_address\")}\n </div>\n <div className=\"text-foreground text-sm\">\n <p className=\"font-medium\">{subscription.address.name}</p>\n <p>{subscription.address.address1}</p>\n {subscription.address.address2 && (\n <p>{subscription.address.address2}</p>\n )}\n <p>\n {[subscription.address.city, subscription.address.state]\n .filter(Boolean)\n .join(\", \")}{\" \"}\n {subscription.address.postal_code}\n </p>\n {subscription.address.country_code && (\n <p>{subscription.address.country_code}</p>\n )}\n {subscription.address.phone && (\n <p>{subscription.address.phone}</p>\n )}\n </div>\n </div>\n )}\n\n {/* Payment Method */}\n {paymentMethod &&\n (renderPaymentMethod ? (\n <div\n id=\"subscription-payment-method-section\"\n className=\"scroll-mt-24\"\n >\n {renderPaymentMethod({\n paymentMethod,\n subscriptionToken: subscription.subscription_token,\n customerId: subscription.customer?.id ?? 0,\n countryCode: subscription.address?.country_code ?? \"US\",\n disabled: paymentMethodDisabled,\n onRecoveryStateChange: onPaymentRecoveryStateChange,\n })}\n </div>\n ) : (\n <div\n id=\"subscription-payment-method-section\"\n className=\"border-border mb-6 scroll-mt-24 border-b pb-4\"\n >\n <div className=\"text-muted-foreground mb-1 text-sm\">\n {t(\"payment_method\")}\n </div>\n <div className=\"text-foreground flex items-center gap-2 text-sm\">\n {paymentDisplay && (\n <PaymentMethodLogo display={paymentDisplay} />\n )}\n {paymentDisplay && (\n <span className=\"font-medium\">\n {paymentDisplay.label}\n </span>\n )}\n </div>\n </div>\n ))}\n\n {/* Automatic points redemption on renewals. Rendered only when the\n host supplies the slot: this component also backs the\n checkout-hosted subscription screens, which do not yet have a\n management surface for it. */}\n {renderAutoApplyPoints?.({\n autoApplyPoints: subscription.auto_apply_points,\n pointsEnabled: subscription.points_enabled,\n subscriptionToken: subscription.subscription_token,\n disabled: isSubscriptionCompleted(subscription),\n renewalBundle: subscription.renewal_bundle,\n })}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n/* ── Order history (own section, full-width below the grid) ────────── */\n\nfunction OrderHistorySection({\n subscription,\n}: {\n subscription: subscriptions.SubscriptionDetailSubscription;\n}) {\n const { t, locale } = useSubscriptionsTranslation();\n if (subscription.orders.length === 0) return null;\n return (\n <section className=\"mt-6 px-8 pt-6 pb-8\">\n <h3 className=\"text-foreground mb-3 text-sm/6 font-semibold\">\n {t(\"subscription_order_history\")}\n </h3>\n <div className=\"border-border overflow-x-auto rounded-md border\">\n <table className=\"divide-border min-w-full divide-y text-sm\">\n <thead className=\"bg-muted\">\n <tr>\n <th className=\"text-muted-foreground py-2 pr-3 pl-3 text-left font-medium\">\n {t(\"order\")}\n </th>\n <th className=\"text-muted-foreground px-3 py-2 text-left font-medium\">\n {t(\"date\")}\n </th>\n <th className=\"text-muted-foreground px-3 py-2 text-left font-medium\">\n {t(\"status\")}\n </th>\n <th className=\"text-muted-foreground py-2 pr-3 pl-3 text-right font-medium\">\n {t(\"amount\")}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-border divide-y\">\n {subscription.orders.map((order) => (\n <tr key={order.id}>\n <td className=\"text-foreground py-2 pr-3 pl-3 font-medium\">\n {order.order_number ?? `#${order.id}`}\n </td>\n <td className=\"text-muted-foreground px-3 py-2\">\n {formatDate(order.created_at.split(\"T\")[0] ?? \"\", locale)}\n </td>\n <td className=\"px-3 py-2\">\n <StatusPill status={order.status}>\n {KNOWN_STATUSES.has(order.status)\n ? t(`list_status_${order.status}` as \"list_status_active\")\n : startCase(order.status)}\n </StatusPill>\n </td>\n <td className=\"text-foreground py-2 pr-3 pl-3 text-right\">\n {order.amount != null\n ? formatCurrency(Number(order.amount))\n : t(\"not_available\")}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </section>\n );\n}\n\n/* ── Main component ────────────────────────────────────────────────── */\n\nexport function SubscriptionDetail({\n token,\n onNotFound,\n onError,\n onSuccess,\n onMutationError,\n onNavigateToSubscription,\n renderPaymentMethod,\n renderShippingAddress,\n renderAutoApplyPoints,\n renderReactivateDialog,\n onUpdatePaymentClick,\n presentation = \"dialog\",\n}: SubscriptionDetailProps): React.JSX.Element | null {\n const { t, locale } = useSubscriptionsTranslation();\n const queryClient = useQueryClient();\n const latestSubscriptionTokenRef = useRef(token);\n latestSubscriptionTokenRef.current = token;\n const [childPaymentRecoveryToken, setChildPaymentRecoveryToken] = useState<\n string | null\n >(null);\n const handlePaymentRecoveryStateChange = useCallback(\n ({\n subscriptionToken,\n isBusy,\n }: {\n subscriptionToken: string;\n isBusy: boolean;\n }) => {\n setChildPaymentRecoveryToken((currentToken) => {\n if (isBusy) return subscriptionToken;\n return currentToken === subscriptionToken ? null : currentToken;\n });\n },\n [],\n );\n const [showCancelModal, setShowCancelModal] = useState(false);\n const [showPauseModal, setShowPauseModal] = useState(false);\n const [showResumeModal, setShowResumeModal] = useState(false);\n const [showReactivateModal, setShowReactivateModal] = useState(false);\n const [showEditBillDateModal, setShowEditBillDateModal] = useState(false);\n const [waiverDialogToken, setWaiverDialogToken] = useState<string | null>(\n null,\n );\n const [pendingNextBillDate, setPendingNextBillDate] = useState<string | null>(\n null,\n );\n const { data, isLoading, error } = useSubscription(token);\n const subscription = data?.subscription;\n const customerId = subscription?.customer?.id ?? 0;\n const waiverPreviewEnabled =\n subscription?.status === \"past_due\" &&\n !isSubscriptionCompleted(subscription) &&\n subscription.next_retry_at == null;\n const waiverPreviewQuery = useFailedCycleWaiverPreview(token, {\n enabled: waiverPreviewEnabled,\n });\n const isWaiverPreviewLoading =\n waiverPreviewEnabled && waiverPreviewQuery.isFetching;\n const waiverPreview = waiverPreviewQuery.data?.failed_cycle_waiver;\n const waiverSchedule =\n waiverPreview?.next_bill_date != null &&\n waiverPreview.next_ship_date != null\n ? getFailedCycleWaiverSummary({\n nextBillDate: waiverPreview.next_bill_date,\n nextShipDate: waiverPreview.next_ship_date,\n locale,\n timezone: subscription?.timezone ?? \"UTC\",\n })\n : null;\n const canWaiveFailedCycle =\n waiverPreviewEnabled &&\n !isWaiverPreviewLoading &&\n !waiverPreviewQuery.isError &&\n waiverPreview?.eligible === true &&\n waiverSchedule != null;\n\n const retryPolling = useRetryStatusPolling({\n subscriptionToken: token,\n onSucceeded: () => onSuccess?.(t(\"payment_retry_succeeded\"), \"success\"),\n onFailed: () => onSuccess?.(t(\"payment_retry_failed\"), \"error\"),\n onTimedOut: () => onSuccess?.(t(\"payment_retry_processing\"), \"warning\"),\n });\n\n const retrySubscription = useRetrySubscription({\n onSuccess: ({ subscriptionToken }: { subscriptionToken: string }) => {\n if (latestSubscriptionTokenRef.current === subscriptionToken) {\n retryPolling.start();\n }\n },\n onError: (\n err: unknown,\n { subscriptionToken }: { subscriptionToken: string },\n ) => {\n if (latestSubscriptionTokenRef.current === subscriptionToken) {\n onMutationError?.(t(\"unable_to_retry_payment\"), err);\n }\n },\n });\n\n const waiverMutation = useWaiveFailedCycle({\n onSuccess: ({ subscriptionToken }) => {\n setWaiverDialogToken((dialogToken) =>\n dialogToken === subscriptionToken ? null : dialogToken,\n );\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n onSuccess?.(t(\"failed_cycle_waiver_succeeded\"), \"success\");\n },\n onError: (err: unknown, { subscriptionToken }) => {\n if (isRecoveryStateChanged(err)) {\n void Promise.all([\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(subscriptionToken),\n exact: true,\n }),\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.failedCycleWaiver(subscriptionToken),\n exact: true,\n }),\n ]);\n\n setWaiverDialogToken((dialogToken) =>\n dialogToken === subscriptionToken ? null : dialogToken,\n );\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n onSuccess?.(t(\"failed_cycle_waiver_state_changed\"), \"warning\");\n return;\n }\n\n if (latestSubscriptionTokenRef.current !== subscriptionToken) {\n setWaiverDialogToken((dialogToken) =>\n dialogToken === subscriptionToken ? null : dialogToken,\n );\n return;\n }\n\n onMutationError?.(t(\"generic_error\"), err);\n },\n });\n\n // Customer's other active subscriptions, only loaded once the bill-date\n // dialog opens — feeds the calendar's color-coded dots. The portal-tenant\n // BFF list endpoint scopes server-side to the member's own customer\n // record (PortalTenant::SubscriptionBrowser), so we don't pass customerId\n // — and we don't gate on it either, since the detail mapper hardcodes\n // customer.id to 0 today.\n //\n // Capped at 100 — a customer with more than 100 subscriptions will be\n // missing some dots from the calendar. Matches the practical ceiling of\n // every other \"list customer's subscriptions\" surface; if/when we have a\n // real-world customer past that, swap to cursor pagination here.\n const customerSubscriptionsQuery = useSubscriptions(\n { perPage: 100 },\n { enabled: showEditBillDateModal },\n );\n const otherSubscriptionsForBillDate = useMemo(\n () =>\n (customerSubscriptionsQuery.data?.subscriptions ?? [])\n .filter((s) => s.subscription_token !== token)\n .map((s) => ({\n token: s.subscription_token,\n productTitle: s.variant?.product?.title ?? t(\"breadcrumb\"),\n nextBillDate: s.next_bill_date,\n billingInterval: s.subscription_plan?.billing_interval ?? 1,\n billingIntervalUnit:\n s.subscription_plan?.billing_interval_unit ?? \"month\",\n })),\n [customerSubscriptionsQuery.data, token, t],\n );\n\n const pauseMutation = usePauseSubscription({\n onSuccess: () => onSuccess?.(t(\"subscription_paused\")),\n onError: (err: unknown) => onMutationError?.(t(\"failed_to_pause\"), err),\n });\n\n const resumeMutation = useResumeSubscription({\n onSuccess: () => onSuccess?.(t(\"subscription_resumed\")),\n onError: (err: unknown) => onMutationError?.(t(\"failed_to_resume\"), err),\n });\n\n const skipMutation = useSkipSubscription({\n onSuccess: () => onSuccess?.(t(\"next_billing_skipped\")),\n onError: (err: unknown) => onMutationError?.(t(\"failed_to_skip\"), err),\n });\n\n const cancelMutation = useCancelSubscription({\n onSuccess: () => {\n onSuccess?.(t(\"subscription_cancelled\"));\n setShowCancelModal(false);\n },\n onError: (err: unknown) => onMutationError?.(t(\"failed_to_cancel\"), err),\n });\n\n const reactivateMutation = useReactivateSubscription({\n onSuccess: () => onSuccess?.(t(\"subscription_reactivated\")),\n onError: (err: unknown) =>\n onMutationError?.(t(\"failed_to_reactivate\"), err),\n });\n\n const [pendingQuantity, setPendingQuantity] = useState<number | null>(null);\n const quantityDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(\n null,\n );\n\n const quantityMutation = useUpdateSubscriptionInfo({\n onSuccess: ({ subscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n // Keep pendingQuantity set so the displayed amounts stay on the\n // new value while the invalidated query refetches. The effect\n // below clears it once the refetched subscription carries the\n // same quantity — avoids a flicker back to the old amounts.\n onSuccess?.(t(\"quantity_updated\"));\n },\n onError: (err: unknown, { subscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n setPendingQuantity(null);\n onMutationError?.(t(\"failed_to_update_quantity\"), err);\n },\n });\n\n const editBillDateMutation = useUpdateSubscriptionInfo({\n onSuccess: ({ subscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n onSuccess?.(t(\"bill_date_updated\"));\n setShowEditBillDateModal(false);\n },\n onError: (err: unknown, { subscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n setPendingNextBillDate(null);\n onMutationError?.(t(\"failed_to_update_bill_date\"), err);\n },\n });\n\n const serverNextBillDate = data?.subscription.next_bill_date ?? null;\n useEffect(() => {\n if (\n pendingNextBillDate != null &&\n serverNextBillDate != null &&\n serverNextBillDate.startsWith(pendingNextBillDate)\n ) {\n setPendingNextBillDate(null);\n }\n }, [pendingNextBillDate, serverNextBillDate]);\n\n const serverQuantity = data?.subscription.quantity;\n useEffect(() => {\n if (pendingQuantity != null && serverQuantity === pendingQuantity) {\n setPendingQuantity(null);\n }\n }, [pendingQuantity, serverQuantity]);\n\n useEffect(\n () => () => {\n if (quantityDebounceRef.current)\n clearTimeout(quantityDebounceRef.current);\n },\n [],\n );\n\n const quantityMutate = quantityMutation.mutate;\n const handleQuantityChange = useCallback(\n (next: number) => {\n const clamped = Math.max(1, next);\n setPendingQuantity(clamped);\n if (quantityDebounceRef.current)\n clearTimeout(quantityDebounceRef.current);\n quantityDebounceRef.current = setTimeout(() => {\n const current = data?.subscription.quantity;\n if (clamped === current) {\n setPendingQuantity(null);\n return;\n }\n quantityMutate({\n subscriptionToken: token,\n body: { quantity: clamped },\n });\n }, 500);\n },\n [data?.subscription.quantity, quantityMutate, token],\n );\n\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const onNotFoundRef = useRef(onNotFound);\n onNotFoundRef.current = onNotFound;\n\n useEffect(() => {\n if (!isLoading && error) {\n onErrorRef.current?.(error as Error);\n }\n }, [isLoading, error]);\n\n useEffect(() => {\n if (!isLoading && !error && !subscription) {\n onNotFoundRef.current?.();\n }\n }, [isLoading, error, subscription]);\n\n if (isLoading) {\n return <SubscriptionDetailSkeleton />;\n }\n\n if (!subscription) {\n return null;\n }\n\n const plan = subscription.subscription_plan;\n const displayStatus = getSubscriptionDisplayStatus(subscription);\n const isActive = displayStatus === \"active\";\n const actionPolicy = getSubscriptionActionPolicy({\n status: subscription.status,\n billingCycleLimitReached: subscription.billing_cycle_limit_reached,\n nextRetryAt: subscription.next_retry_at,\n nextBillDate: subscription.next_bill_date,\n allowSkipping: subscription.subscription_plan.allow_skipping,\n maxSkips: subscription.subscription_plan.max_skips,\n skippedCount: subscription.skipped_count,\n hasPendingSkip: hasPendingSubscriptionSkip(subscription.subscription_skips),\n canChangePaymentMethod: true,\n canWaiveFailedCycle,\n isWaiverPreviewLoading,\n });\n const directParentRecoveryDisabled =\n (retrySubscription.isPending &&\n retrySubscription.variables?.subscriptionToken === token) ||\n retryPolling.isProcessing;\n const independentParentMutationDisabled =\n pauseMutation.isPending ||\n resumeMutation.isPending ||\n skipMutation.isPending ||\n cancelMutation.isPending ||\n reactivateMutation.isPending ||\n editBillDateMutation.isPending;\n const childPaymentRecoveryDisabled = childPaymentRecoveryToken === token;\n const waiverMutationPending =\n waiverMutation.isPending &&\n waiverMutation.variables?.subscriptionToken === token;\n const aggregateRecoveryDisabled =\n directParentRecoveryDisabled ||\n childPaymentRecoveryDisabled ||\n waiverMutationPending;\n const paymentMethodDisabled =\n isSubscriptionCompleted(subscription) ||\n directParentRecoveryDisabled ||\n waiverMutationPending ||\n independentParentMutationDisabled;\n const isMutating =\n independentParentMutationDisabled || aggregateRecoveryDisabled;\n\n const handlePauseConfirm = (selection: PauseSubscriptionSelection) => {\n const pauseParams: subscriptions.PauseSubscriptionParams = { customerId };\n if (selection.type === \"order_count\") {\n pauseParams.numberOfOrders = selection.numberOfOrders;\n }\n pauseMutation.mutate(\n { subscriptionToken: token, pauseParams },\n { onSuccess: () => setShowPauseModal(false) },\n );\n };\n\n const handleResumeConfirm = (nextBillDate: string) => {\n resumeMutation.mutate(\n {\n subscriptionToken: token,\n resumeParams: { customerId, nextBillDate },\n },\n { onSuccess: () => setShowResumeModal(false) },\n );\n };\n\n const handleSkip = () => {\n const nextBillDate = calculateNextBillDate(\n plan.billing_interval,\n plan.billing_interval_unit,\n );\n skipMutation.mutate({\n subscriptionToken: token,\n skipParams: { customerId, nextBillDate },\n });\n };\n\n const handleCancel = () => {\n cancelMutation.mutate({ subscriptionToken: token, customerId });\n };\n\n const handleReactivate = () => {\n // When a consumer supplies the confirmation dialog, open it so the\n // customer can confirm the shipping address first; otherwise reactivate\n // immediately against the subscription's current address.\n if (renderReactivateDialog) {\n setShowReactivateModal(true);\n return;\n }\n reactivateMutation.mutate({\n subscriptionToken: token,\n reactivateParams: {},\n });\n };\n\n const handleRetryPayment = () => {\n if (aggregateRecoveryDisabled) return;\n retrySubscription.mutate({ subscriptionToken: token });\n };\n\n const savedPaymentMethodLabel = getSavedPaymentMethodLabel(\n subscription.payment_method ?? null,\n );\n\n const handleReactivateConfirm = ({\n addressId,\n }: {\n addressId?: number | null;\n }) => {\n reactivateMutation.mutate(\n {\n subscriptionToken: token,\n reactivateParams: addressId != null ? { address_id: addressId } : {},\n },\n { onSuccess: () => setShowReactivateModal(false) },\n );\n };\n\n return (\n <>\n {displayStatus === \"past_due\" && (\n <div className=\"mb-4 px-2 sm:px-0 lg:mb-6\">\n <PastDueBanner\n productTitle={subscription.variant?.product?.title ?? null}\n nextRetryAt={subscription.next_retry_at ?? null}\n declineCount={subscription.decline_count ?? null}\n savedMethodLabel={savedPaymentMethodLabel}\n onRetryPaymentClick={\n actionPolicy.recovery?.primary === \"retry_payment\"\n ? handleRetryPayment\n : undefined\n }\n isRetryingPayment={directParentRecoveryDisabled}\n isCheckingWaiver={actionPolicy.recovery?.isCheckingWaiver === true}\n recoveryDisabled={aggregateRecoveryDisabled}\n onUpdatePaymentClick={\n onUpdatePaymentClick ??\n (() => {\n const el = document.getElementById(\n \"subscription-payment-method-section\",\n );\n if (el) {\n el.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n }\n })\n }\n onWaiveFailedCycleClick={\n actionPolicy.recovery?.tertiary === \"waive_failed_cycle\"\n ? () => setWaiverDialogToken(token)\n : undefined\n }\n />\n </div>\n )}\n <div className=\"flex flex-col lg:grid lg:grid-cols-8\">\n <SubscriptionItemsSection\n subscription={subscription}\n displayQuantity={pendingQuantity ?? undefined}\n displayNextBillDate={pendingNextBillDate ?? undefined}\n canEditQuantity={isActive}\n onQuantityChange={handleQuantityChange}\n isUpdatingQuantity={quantityMutation.isPending}\n onNavigateToSubscription={onNavigateToSubscription}\n />\n <SubscriptionManagementSection\n subscription={subscription}\n actionPolicy={actionPolicy}\n isMutating={isMutating}\n paymentMethodDisabled={paymentMethodDisabled}\n onPaymentRecoveryStateChange={handlePaymentRecoveryStateChange}\n onSkip={handleSkip}\n onPause={() => setShowPauseModal(true)}\n onResume={() => setShowResumeModal(true)}\n onCancel={() => setShowCancelModal(true)}\n onReactivate={handleReactivate}\n onEditBillDate={() => setShowEditBillDateModal(true)}\n renderPaymentMethod={renderPaymentMethod}\n renderShippingAddress={renderShippingAddress}\n renderAutoApplyPoints={renderAutoApplyPoints}\n presentation={presentation}\n />\n </div>\n <OrderHistorySection subscription={subscription} />\n <CancelSubscriptionDialog\n open={showCancelModal}\n presentation={presentation}\n onOpenChange={setShowCancelModal}\n onConfirm={handleCancel}\n onPauseInstead={(months: PauseMonths) => {\n setShowCancelModal(false);\n pauseMutation.mutate({\n subscriptionToken: token,\n pauseParams: {\n customerId,\n nextBillDate: format(addMonths(new Date(), months), \"yyyy-MM-dd\"),\n },\n });\n }}\n />\n <EditBillDateDialog\n open={showEditBillDateModal}\n presentation={presentation}\n onOpenChange={(next) => {\n if (!next) editBillDateMutation.reset();\n setShowEditBillDateModal(next);\n }}\n onConfirm={(nextBillDate) => {\n setPendingNextBillDate(nextBillDate);\n editBillDateMutation.mutate({\n subscriptionToken: token,\n body: { next_bill_date: nextBillDate },\n });\n }}\n isLoading={editBillDateMutation.isPending}\n errorMessage={\n editBillDateMutation.isError ? t(\"bill_date_error\") : undefined\n }\n currentNextBillDate={subscription.next_bill_date}\n billingInterval={plan.billing_interval}\n billingIntervalUnit={plan.billing_interval_unit}\n otherSubscriptions={otherSubscriptionsForBillDate}\n onNavigateToSubscription={onNavigateToSubscription}\n />\n <PauseSubscriptionDialog\n open={showPauseModal}\n presentation={presentation}\n onOpenChange={(next) => {\n if (!next) pauseMutation.reset();\n setShowPauseModal(next);\n }}\n onConfirm={handlePauseConfirm}\n isLoading={pauseMutation.isPending}\n errorMessage={pauseMutation.isError ? t(\"generic_error\") : undefined}\n currentNextBillDate={subscription.next_bill_date}\n billingInterval={plan.billing_interval}\n billingIntervalUnit={plan.billing_interval_unit}\n />\n <ResumeSubscriptionDialog\n open={showResumeModal}\n presentation={presentation}\n onOpenChange={(next) => {\n if (!next) resumeMutation.reset();\n setShowResumeModal(next);\n }}\n onConfirm={handleResumeConfirm}\n isLoading={resumeMutation.isPending}\n errorMessage={resumeMutation.isError ? t(\"generic_error\") : undefined}\n defaultNextBillDate={calculateNextBillDate(\n plan.billing_interval,\n plan.billing_interval_unit,\n )}\n />\n <FailedCycleWaiverDialog\n open={waiverDialogToken === token}\n presentation={presentation}\n preview={\n waiverDialogToken === token\n ? (waiverPreviewQuery.data?.failed_cycle_waiver ?? null)\n : null\n }\n timezone={subscription.timezone ?? \"UTC\"}\n isPending={waiverMutationPending}\n onOpenChange={(open) => {\n if (!open) {\n setWaiverDialogToken((dialogToken) =>\n dialogToken === token ? null : dialogToken,\n );\n }\n }}\n onConfirm={() => {\n if (waiverDialogToken !== token || waiverMutationPending) return;\n waiverMutation.mutate({ subscriptionToken: token });\n }}\n />\n {renderReactivateDialog?.({\n open: showReactivateModal,\n onOpenChange: (next) => {\n if (!next) reactivateMutation.reset();\n setShowReactivateModal(next);\n },\n onConfirm: handleReactivateConfirm,\n isLoading: reactivateMutation.isPending,\n isError: reactivateMutation.isError,\n subscriptionToken: token,\n })}\n </>\n );\n}\n\nexport interface SubscriptionActionsProps {\n isActive: boolean;\n isPaused: boolean;\n isCancelled: boolean;\n isMutating: boolean;\n allowSkipping: boolean | null;\n onPause: () => void;\n onResume: () => void;\n onSkip: () => void;\n onCancel: () => void;\n onReactivate: () => void;\n}\n\nexport function SubscriptionActions({\n isActive,\n isPaused,\n isCancelled,\n isMutating,\n allowSkipping,\n onPause,\n onResume,\n onSkip,\n onCancel,\n onReactivate,\n}: SubscriptionActionsProps): React.JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const actionButtonClass =\n \"flex h-auto flex-row items-center justify-center gap-2 overflow-hidden border border-border bg-muted py-2 text-xs whitespace-nowrap text-foreground hover:bg-accent sm:text-sm\";\n\n return (\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {isActive && (\n <>\n {allowSkipping && (\n <Button\n variant=\"outline\"\n onClick={onSkip}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <SkipForward className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{t(\"skip_next\")}</span>\n </Button>\n )}\n <Button\n variant=\"outline\"\n onClick={onPause}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <Pause className=\"size-3 shrink-0\" />\n <span className=\"truncate\">{t(\"pause\")}</span>\n </Button>\n <Button\n variant=\"outline\"\n onClick={onCancel}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <XCircle className=\"size-3 shrink-0\" />\n <span className=\"truncate\">{t(\"cancel\")}</span>\n </Button>\n </>\n )}\n {isPaused && (\n <>\n <Button\n variant=\"outline\"\n onClick={onResume}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <Play className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{t(\"resume\")}</span>\n </Button>\n <Button\n variant=\"outline\"\n onClick={onCancel}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <XCircle className=\"size-3 shrink-0\" />\n <span className=\"truncate\">{t(\"cancel\")}</span>\n </Button>\n </>\n )}\n {isCancelled && (\n <Button\n variant=\"outline\"\n onClick={onReactivate}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <RotateCcw className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{t(\"reactivate\")}</span>\n </Button>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport type React from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@fluid-app/ui-primitives\";\nimport { ScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport type { ResponsiveDialogPresentation } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport {\n SubscriptionDetail,\n type PaymentMethodSlotContext,\n type ShippingAddressSlotContext,\n type AutoApplyPointsSlotContext,\n type ReactivateDialogSlotContext,\n} from \"../components/subscription-detail\";\n\nexport interface SubscriptionDetailScreenProps {\n token: string;\n onNavigateToList: () => void;\n onNavigateToSubscription?: (token: string) => void;\n onNotFound?: () => void;\n onError?: (error: Error) => void;\n onSuccess?: (\n message: string,\n severity?: \"success\" | \"error\" | \"warning\",\n ) => void;\n onMutationError?: (message: string, error: unknown) => void;\n renderPaymentMethod?: (ctx: PaymentMethodSlotContext) => React.JSX.Element;\n renderShippingAddress?: (\n ctx: ShippingAddressSlotContext,\n ) => React.JSX.Element;\n renderAutoApplyPoints?: (\n ctx: AutoApplyPointsSlotContext,\n ) => React.JSX.Element;\n renderReactivateDialog?: (\n ctx: ReactivateDialogSlotContext,\n ) => React.JSX.Element;\n onUpdatePaymentClick?: () => void;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function SubscriptionDetailScreen({\n token,\n onNavigateToList,\n onNavigateToSubscription,\n onNotFound,\n onError,\n onSuccess,\n onMutationError,\n renderPaymentMethod,\n renderShippingAddress,\n renderAutoApplyPoints,\n renderReactivateDialog,\n onUpdatePaymentClick,\n presentation = \"dialog\",\n}: SubscriptionDetailScreenProps): React.JSX.Element {\n const { t } = useSubscriptionsTranslation();\n\n return (\n <>\n <ScreenHeaderBreadcrumbs>\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbLink\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n onNavigateToList();\n }}\n >\n {t(\"breadcrumb\")}\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n {t(\"breadcrumb_detail\", { token })}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n </ScreenHeaderBreadcrumbs>\n <div className=\"mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-10 lg:py-8\">\n <SubscriptionDetail\n token={token}\n onNotFound={onNotFound}\n onError={onError}\n onSuccess={onSuccess}\n onMutationError={onMutationError}\n onNavigateToSubscription={onNavigateToSubscription}\n renderPaymentMethod={renderPaymentMethod}\n renderShippingAddress={renderShippingAddress}\n renderAutoApplyPoints={renderAutoApplyPoints}\n renderReactivateDialog={renderReactivateDialog}\n onUpdatePaymentClick={onUpdatePaymentClick}\n presentation={presentation}\n />\n </div>\n </>\n );\n}\n","import { useId, useState, type JSX } from \"react\";\nimport { cn, Skeleton } from \"@fluid-app/ui-primitives\";\nimport { ChevronDown } from \"lucide-react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport {\n PaymentIcon,\n getCardDisplayName,\n getCardExpiry,\n getPaymentMethodLogoBrand,\n} from \"@fluid-app/profile-ui/components/payment-method-card-internals\";\nimport { EllipsesDropdown } from \"@fluid-app/profile-ui\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport type { ResponsiveDialogPresentation } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\n\ninterface SelectablePaymentMethodDropdownProps {\n title: string;\n displayPaymentMethod: fluidPay.CustomerPaymentMethod | null;\n paymentMethodList: fluidPay.CustomerPaymentMethod[];\n selectedPaymentMethodId: number;\n onSelectPaymentMethod: (\n paymentMethod: fluidPay.CustomerPaymentMethod,\n ) => void;\n onAddPaymentMethodClick: () => void;\n onEditPaymentMethod?: (paymentMethod: fluidPay.CustomerPaymentMethod) => void;\n onDeletePaymentMethod?: (\n paymentMethod: fluidPay.CustomerPaymentMethod,\n ) => void;\n onMakeDefaultPaymentMethod?: (\n paymentMethod: fluidPay.CustomerPaymentMethod,\n ) => void;\n addPaymentMethodLabel?: string;\n showAddButton?: boolean;\n isLoading?: boolean;\n /** Disable selection while a parent mutation is in flight. */\n isPending?: boolean;\n className?: string;\n presentation?: ResponsiveDialogPresentation;\n}\n\n/**\n * Selectable variant of profile-ui's PaymentMethodDropdown — same chrome\n * (accordion, collapsed summary, list, add button), with rows that\n * commit a selection through onSelectPaymentMethod when clicked.\n */\nexport function SelectablePaymentMethodDropdown({\n title,\n displayPaymentMethod,\n paymentMethodList,\n selectedPaymentMethodId,\n onSelectPaymentMethod,\n onAddPaymentMethodClick,\n onEditPaymentMethod,\n onDeletePaymentMethod,\n onMakeDefaultPaymentMethod,\n addPaymentMethodLabel: addPaymentMethodLabelProp,\n showAddButton = true,\n isLoading = false,\n isPending = false,\n className = \"\",\n presentation = \"dialog\",\n}: SelectablePaymentMethodDropdownProps): JSX.Element {\n const { t } = useProfileTranslation();\n const addPaymentMethodLabel =\n addPaymentMethodLabelProp ?? t(\"add_a_payment_method\");\n const [isOpen, setIsOpen] = useState(false);\n const sectionId = useId();\n const collapsedExpiry = displayPaymentMethod\n ? getCardExpiry(displayPaymentMethod, t(\"card_expires\"))\n : null;\n\n return (\n <div className={cn(\"border-border mb-6 border-b pb-4\", className)}>\n <button\n type=\"button\"\n aria-expanded={isOpen}\n aria-controls={sectionId}\n onClick={() => setIsOpen((prev) => !prev)}\n className=\"flex w-full flex-row items-center justify-between\"\n >\n <span className=\"text-muted-foreground text-sm\">{title}</span>\n <ChevronDown\n className={cn(\n \"text-muted-foreground h-4 w-4 transition-transform duration-200\",\n isOpen && \"rotate-180\",\n )}\n />\n </button>\n\n {/* Collapsed summary — shows the subscription's current payment method\n inline. Clicking expands. Mirrors checkout's payment-method-dropdown\n collapse behavior. */}\n {!isOpen && displayPaymentMethod && (\n <button\n type=\"button\"\n onClick={() => setIsOpen(true)}\n className=\"mt-1 mb-2 flex w-full cursor-pointer flex-row items-center gap-3 text-left\"\n >\n <div className=\"flex h-6 w-10 flex-shrink-0 items-center justify-center\">\n <PaymentIcon\n logoUrl={displayPaymentMethod.details.logo_url}\n brand={getPaymentMethodLogoBrand(displayPaymentMethod)}\n alt={getCardDisplayName(displayPaymentMethod)}\n />\n </div>\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"text-foreground text-sm font-medium\">\n {getCardDisplayName(displayPaymentMethod, t(\"card_fallback\"))}\n </span>\n {collapsedExpiry && (\n <span className=\"text-muted-foreground text-sm\">\n {collapsedExpiry}\n </span>\n )}\n </div>\n </button>\n )}\n\n {isOpen && (\n <div\n id={sectionId}\n role=\"listbox\"\n aria-label={title}\n className=\"mt-5 flex max-h-[400px] flex-col gap-y-4 overflow-y-auto pr-0.5\"\n >\n {isLoading ? (\n <>\n {[1, 2].map((i) => (\n <div\n key={`skeleton-${i}`}\n className=\"bg-muted flex flex-row items-center gap-x-2 rounded-sm p-3\"\n >\n <Skeleton className=\"h-6 w-10\" />\n <div className=\"flex flex-col gap-y-1\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-4 w-24\" />\n </div>\n </div>\n ))}\n </>\n ) : (\n paymentMethodList.map((paymentMethod) => {\n const isSelected = selectedPaymentMethodId === paymentMethod.id;\n const expiry = getCardExpiry(paymentMethod, t(\"card_expires\"));\n const handleSelect = () => {\n if (isPending) return;\n onSelectPaymentMethod(paymentMethod);\n };\n return (\n <div\n key={paymentMethod.id}\n role=\"option\"\n tabIndex={isPending ? -1 : 0}\n aria-selected={isSelected}\n aria-disabled={isPending}\n onClick={handleSelect}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleSelect();\n }\n }}\n className={cn(\n \"text-foreground flex w-full flex-row items-center justify-between gap-3 rounded-sm p-3 text-left transition-colors\",\n \"not-aria-disabled:cursor-pointer aria-disabled:cursor-not-allowed aria-disabled:opacity-60\",\n isSelected\n ? \"bg-background border-border border\"\n : \"bg-muted hover:bg-muted/80 border border-transparent\",\n )}\n >\n <div className=\"flex min-w-0 flex-row items-center gap-3\">\n <div className=\"flex h-6 w-10 flex-shrink-0 items-center justify-center\">\n <PaymentIcon\n logoUrl={paymentMethod.details.logo_url}\n brand={getPaymentMethodLogoBrand(paymentMethod)}\n alt={getCardDisplayName(paymentMethod)}\n />\n </div>\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"text-foreground text-sm font-medium\">\n {getCardDisplayName(paymentMethod)}\n </span>\n {expiry && (\n <span className=\"text-muted-foreground text-sm\">\n {expiry}\n </span>\n )}\n </div>\n </div>\n <div className=\"flex shrink-0 flex-row items-center gap-2\">\n {paymentMethod.default && (\n <span className=\"bg-primary text-primary-foreground rounded px-2 py-0.5 text-xs font-medium\">\n {t(\"default\")}\n </span>\n )}\n {(onEditPaymentMethod ||\n onDeletePaymentMethod ||\n onMakeDefaultPaymentMethod) && (\n <span\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <EllipsesDropdown\n presentation={presentation}\n onEdit={\n onEditPaymentMethod\n ? () => onEditPaymentMethod(paymentMethod)\n : undefined\n }\n onDelete={\n onDeletePaymentMethod\n ? () => onDeletePaymentMethod(paymentMethod)\n : undefined\n }\n onMakeDefault={\n !paymentMethod.default && onMakeDefaultPaymentMethod\n ? () => onMakeDefaultPaymentMethod(paymentMethod)\n : undefined\n }\n />\n </span>\n )}\n </div>\n </div>\n );\n })\n )}\n </div>\n )}\n\n {showAddButton && (\n <button\n type=\"button\"\n disabled={isPending}\n className=\"text-foreground mt-3 text-left text-sm disabled:cursor-not-allowed disabled:opacity-60\"\n onClick={onAddPaymentMethodClick}\n >\n {addPaymentMethodLabel}\n </button>\n )}\n </div>\n );\n}\n","import type { QueryClient } from \"@tanstack/react-query\";\nimport {\n isSubscriptionCompleted,\n subscriptionsKeys,\n type subscriptions,\n} from \"@fluid-app/subscriptions-core\";\n\nexport function isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionToken: string,\n completedSubscriptionToken: string,\n): boolean {\n return latestSubscriptionToken === completedSubscriptionToken;\n}\n\nexport async function invalidateSubscriptionPaymentRecoveryCache(\n queryClient: QueryClient,\n subscriptionToken: string,\n): Promise<void> {\n await Promise.all([\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists }),\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n }),\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(subscriptionToken),\n }),\n ]);\n}\n\nexport async function completeSubscriptionPaymentUpdate(args: {\n queryClient: QueryClient;\n updatedSubscriptionToken: string;\n getLatestSubscriptionToken: () => string;\n isExternallyDisabled: () => boolean;\n queueRetry: (subscriptionToken: string) => void;\n notifyUpdated: () => void;\n}): Promise<void> {\n const cached =\n args.queryClient.getQueryData<subscriptions.SubscriptionDetail>(\n subscriptionsKeys.detail(args.updatedSubscriptionToken),\n );\n if (\n cached?.subscription.status === \"past_due\" &&\n !isSubscriptionCompleted(cached.subscription)\n ) {\n args.queueRetry(args.updatedSubscriptionToken);\n return;\n }\n\n await invalidateSubscriptionPaymentRecoveryCache(\n args.queryClient,\n args.updatedSubscriptionToken,\n );\n if (\n isCurrentSubscriptionPaymentAttempt(\n args.getLatestSubscriptionToken(),\n args.updatedSubscriptionToken,\n ) &&\n !args.isExternallyDisabled()\n ) {\n args.notifyUpdated();\n }\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type JSX,\n} from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport {\n FluidPayCoreProvider,\n type State,\n type fluidPay,\n} from \"@fluid-app/fluid-pay-core\";\nimport {\n AddressFormDialog,\n ConfirmActionDialog,\n CreditCardFormDialog,\n EditPaymentMethodDialog,\n type CreditCardFormSubmitData,\n type EditPaymentMethodFormData,\n} from \"@fluid-app/profile-ui\";\nimport { useActiveLocale } from \"@fluid-app/i18n/locale-context\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { SelectablePaymentMethodDropdown } from \"./SelectablePaymentMethodDropdown\";\nimport {\n useRetryStatusPolling,\n useRetrySubscription,\n useUpdateSubscriptionInfo,\n} from \"@fluid-app/subscriptions-core\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport type { PaymentMethodSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport { TOKEN_PROVIDER_VGS } from \"@fluid-app/portal-core/pay-types\";\nimport type {\n PayAddress,\n UpdatePaymentMethodBody,\n} from \"@fluid-app/portal-core/pay-types\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { useCountriesApi } from \"@fluid-app/store-core/countries-api-context\";\nimport { payKeys, storeKeys } from \"../account/query-keys\";\nimport {\n createFluidPayApiAdapter,\n mapToFluidPayPaymentMethod,\n} from \"../adapters/fluid-pay-api-adapter\";\nimport { ProfileTranslationBridge } from \"../providers/ProfileTranslationBridge\";\nimport { getBrowserInfo } from \"@fluid-app/fluid-pay-core/utils/browser-info\";\nimport { usePortalCardAdd3DSFlow } from \"../hooks/use-portal-card-add-3ds-flow\";\nimport { buildSubscriptionCardAddSuccess } from \"./subscription-card-add-success\";\nimport {\n completeSubscriptionPaymentUpdate,\n invalidateSubscriptionPaymentRecoveryCache,\n isCurrentSubscriptionPaymentAttempt,\n} from \"./subscription-payment-recovery\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n phone: raw.phone,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\n// Map the subscription's payment_method shape (which lives on\n// SubscriptionDetail and uses different field names than PayApi) to the\n// fluidPay shape PaymentMethodDropdown consumes.\nfunction subscriptionPaymentMethodToFluidPay(\n raw: subscriptions.SubscriptionDetailPaymentMethod,\n): fluidPay.CustomerPaymentMethod {\n const details = raw.details as {\n last4?: string;\n card_network?: string;\n card_brand?: string;\n logo_url?: string;\n exp_month?: number | string;\n exp_year?: number | string;\n } | null;\n return {\n id: raw.id,\n created_at: raw.created_at,\n default: raw.default,\n details: {\n card_network: details?.card_network ?? null,\n card_brand: details?.card_brand ?? details?.card_network ?? null,\n last_four: details?.last4 ?? \"\",\n exp_month:\n details?.exp_month != null ? Number(details.exp_month) : undefined,\n exp_year:\n details?.exp_year != null ? Number(details.exp_year) : undefined,\n logo_url: details?.logo_url,\n },\n billing_address: null,\n payment_type: raw.payment_type,\n source: raw.source,\n updated_at: raw.updated_at,\n };\n}\n\ntype PaymentMethodSectionProps = PaymentMethodSlotContext & {\n // severity defaults to \"success\"; the async-retry outcome uses \"error\" to\n // surface a declined charge through the same toast channel.\n onSuccess?: (\n message: string,\n severity?: \"success\" | \"error\" | \"warning\",\n ) => void;\n onError?: (message: string, error: unknown) => void;\n // Optional controlled props so a parent (e.g. the past-due banner CTA in\n // SubscriptionDetailScreen) can open the Add Payment Method dialog from\n // outside this section. When omitted, the section manages the dialog\n // internally as before.\n addDialogOpen?: boolean;\n onAddDialogOpenChange?: (open: boolean) => void;\n};\n\nexport function PortalSubscriptionPaymentMethodSection(\n props: PaymentMethodSectionProps,\n): JSX.Element {\n return (\n <ProfileTranslationBridge>\n <PortalSubscriptionPaymentMethodSectionInner {...props} />\n </ProfileTranslationBridge>\n );\n}\n\nfunction PortalSubscriptionPaymentMethodSectionInner({\n paymentMethod: currentPaymentMethod,\n subscriptionToken,\n disabled,\n onRecoveryStateChange,\n onSuccess,\n onError,\n addDialogOpen,\n onAddDialogOpenChange,\n}: PaymentMethodSectionProps): JSX.Element {\n const { isMobile } = useSidebar();\n const { t: profileT } = useProfileTranslation();\n const { t: subsT } = useSubscriptionsTranslation();\n const { locale } = useActiveLocale();\n const latestSubscriptionTokenRef = useRef(subscriptionToken);\n latestSubscriptionTokenRef.current = subscriptionToken;\n const externallyDisabledRef = useRef(disabled);\n externallyDisabledRef.current = disabled;\n const cardAddSubscriptionTokenRef = useRef<string | null>(null);\n const walletMutationSubscriptionTokenRef = useRef<string | null>(null);\n const isCurrentPaymentAttempt = (\n attemptSubscriptionToken: string | null,\n ): attemptSubscriptionToken is string =>\n attemptSubscriptionToken !== null &&\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n attemptSubscriptionToken,\n );\n\n // Bridge for fluid-pay-ui dialogs that accept `t: (key: string) => string`.\n // The underlying adapter falls back to `key` for unknown keys, so widening\n // the key type is safe at runtime.\n const tFn = useCallback(\n (key: string): string => profileT(key as never),\n [profileT],\n );\n\n const payApi = usePayApi();\n const queryClient = useQueryClient();\n const fluidPayShim = useMemo(\n () => createFluidPayApiAdapter(payApi),\n [payApi],\n );\n\n const [internalAddDialogOpen, setInternalAddDialogOpen] = useState(false);\n const isAddDialogOpen = addDialogOpen ?? internalAddDialogOpen;\n const setIsAddDialogOpen = useCallback(\n (next: boolean) => {\n if (onAddDialogOpenChange) onAddDialogOpenChange(next);\n else setInternalAddDialogOpen(next);\n },\n [onAddDialogOpenChange],\n );\n // Track whether the most recent dialog-open came from the dropdown's\n // \"Add Payment Method\" (internal — just save to wallet) or from a\n // banner/action trigger via the controlled addDialogOpen prop (external\n // — swap the subscription onto the new card after creating it).\n const dropdownInitiatedAddRef = useRef(false);\n const [editingPaymentMethod, setEditingPaymentMethod] =\n useState<fluidPay.CustomerPaymentMethod | null>(null);\n const [deletingPaymentMethod, setDeletingPaymentMethod] =\n useState<fluidPay.CustomerPaymentMethod | null>(null);\n const [deleteError, setDeleteError] = useState<string | undefined>(undefined);\n const [saveCardError, setSaveCardError] = useState<string | null>(null);\n const previousDialogSubscriptionTokenRef = useRef(subscriptionToken);\n\n const { data: paymentMethods = [], isLoading: isLoadingMethods } = useQuery({\n queryKey: payKeys.paymentMethods.list(),\n queryFn: async () => {\n const response = await payApi.fetchPaymentMethods();\n return response.payment_methods.map(mapToFluidPayPaymentMethod);\n },\n });\n\n const { data: addresses = [] } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n enabled: isAddDialogOpen,\n });\n\n const countriesApi = useCountriesApi();\n const { data: countriesData } = useQuery({\n queryKey: storeKeys.countries(locale),\n queryFn: () => countriesApi.listCountries({ languageIso: locale }),\n enabled: isAddDialogOpen || editingPaymentMethod !== null,\n });\n const countryOptions = useMemo(\n () =>\n [...(countriesData?.countries ?? [])]\n .map((c) => ({ iso: c.code, name: c.name }))\n .sort((a, b) => a.name.localeCompare(b.name)),\n [countriesData],\n );\n const statesByCountry = useMemo(() => {\n const map = new Map<string, State[]>();\n for (const c of countriesData?.countries ?? []) {\n map.set(\n c.code,\n c.states.map((s) => ({ name: s.name, isoCode: s.code })),\n );\n }\n return map;\n }, [countriesData]);\n const fetchStatesFromCountries = useCallback(\n (countryCode: string): Promise<State[]> =>\n Promise.resolve(statesByCountry.get(countryCode) ?? []),\n [statesByCountry],\n );\n\n // The retry queues an async charge and returns with the sub still past_due,\n // so poll for the outcome rather than leaving the stale \"we're trying your\n // payment again\" copy up until the customer refreshes (CURRENT-1877). Hosted\n // here (not in the past-due banner) so the success toast survives the banner\n // unmounting when status flips to active.\n const retryStatusPolling = useRetryStatusPolling({\n subscriptionToken,\n onSucceeded: () => onSuccess?.(subsT(\"payment_retry_succeeded\")),\n onFailed: () => onSuccess?.(subsT(\"payment_retry_failed\"), \"error\"),\n // The charge is taking longer than the poll window — confirm the card\n // saved so the customer isn't left with no feedback (the banner keeps the\n // \"we'll update once processed\" copy).\n onTimedOut: () => onSuccess?.(subsT(\"payment_retry_processing\")),\n });\n\n const retrySubscription = useRetrySubscription({\n onSuccess: ({ subscriptionToken: queuedSubscriptionToken }) => {\n if (\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n queuedSubscriptionToken,\n ) &&\n !externallyDisabledRef.current\n ) {\n retryStatusPolling.start();\n }\n },\n onError: async (err, { subscriptionToken: failedSubscriptionToken }) => {\n await invalidateSubscriptionPaymentRecoveryCache(\n queryClient,\n failedSubscriptionToken,\n );\n if (\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n failedSubscriptionToken,\n )\n ) {\n onError?.(\"Failed to queue retry\", err);\n }\n },\n });\n\n const updateSubscription = useUpdateSubscriptionInfo({\n // Skip the hook's auto-invalidate so we coalesce into a single\n // refetch — either retrySubscription's onSuccess (past_due path)\n // or the explicit invalidate below (non-past-due path).\n skipAutoInvalidate: true,\n onSuccess: async ({ subscriptionToken: updatedSubscriptionToken }) => {\n // Explicit retry as a separate request, only when the sub was\n // past_due. Decoupled from the update endpoint per SRP — and\n // gated client-side so non-past-due subs don't fire a redundant\n // request (backend would no-op, but we don't want to ask).\n //\n // Toast + invalidation are deferred to whichever path runs:\n // - past_due: skip the \"payment method updated\" toast — the retry\n // outcome (succeeded/failed/processing) is the relevant feedback\n // and fires a moment later, so a bare \"updated\" here would read as\n // contradictory against a subsequent decline. useRetrySubscription\n // invalidates on its own onSuccess (single refetch covers both).\n // - non-past_due: confirm the update and invalidate inline.\n await completeSubscriptionPaymentUpdate({\n queryClient,\n updatedSubscriptionToken,\n getLatestSubscriptionToken: () => latestSubscriptionTokenRef.current,\n isExternallyDisabled: () => externallyDisabledRef.current,\n queueRetry: (subscriptionToken) =>\n retrySubscription.mutate({ subscriptionToken }),\n notifyUpdated: () =>\n onSuccess?.(profileT(\"default_payment_method_updated\")),\n });\n },\n onError: (err, { subscriptionToken: failedSubscriptionToken }) => {\n if (\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n failedSubscriptionToken,\n )\n ) {\n onError?.(profileT(\"failed_to_update_payment_method\"), err);\n }\n },\n });\n\n // Route a freshly-created (or 3DS-approved) payment method per how the Add\n // dialog was opened. Only chain the subscription's payment-method swap when\n // the dialog was opened externally (banner CTA / \"Update Payment Method\"\n // action) — those signal intent to bill this subscription on the new card.\n // The dropdown's \"Add Payment Method\" path just adds to the wallet; the\n // customer can switch later via onSelectPaymentMethod.\n //\n // Toast handling: skip \"payment_method_added\" on the external path because\n // updateSubscription's onSuccess will fire the more relevant\n // \"default_payment_method_updated\" toast a moment later, and two success\n // toasts in rapid succession is noise.\n const routeCreatedPaymentMethod = (paymentMethodId: number) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (\n !isCurrentPaymentAttempt(initiatedSubscriptionToken) ||\n externallyDisabledRef.current\n ) {\n return;\n }\n\n const wasDropdownInitiated = dropdownInitiatedAddRef.current;\n dropdownInitiatedAddRef.current = false;\n if (wasDropdownInitiated) {\n onSuccess?.(profileT(\"payment_method_added\"));\n } else {\n updateSubscription.mutate({\n subscriptionToken: initiatedSubscriptionToken,\n body: { payment_method_id: paymentMethodId },\n });\n }\n };\n\n // Orchestrates the bank-challenge step when card add returns three_ds_required.\n // begin() resolves the moment the challenge modal opens — so dialog close and\n // the routing live ONLY here (onApproved) and on the created branch\n // (onCreated below), never on the three_ds_required branch.\n const cardAdd3DS = usePortalCardAdd3DSFlow({\n payApi,\n t: tFn,\n onApproved: async (approved) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (!isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n return;\n }\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n setIsAddDialogOpen(false);\n routeCreatedPaymentMethod(approved.payment_method.id);\n },\n onFailed: (message) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n setSaveCardError(message);\n }\n },\n onCanceled: () => {},\n });\n\n useEffect(() => {\n const tokenChanged =\n previousDialogSubscriptionTokenRef.current !== subscriptionToken;\n if (tokenChanged) {\n previousDialogSubscriptionTokenRef.current = subscriptionToken;\n dropdownInitiatedAddRef.current = false;\n setEditingPaymentMethod(null);\n setDeletingPaymentMethod(null);\n setDeleteError(undefined);\n setSaveCardError(null);\n }\n\n const staleCardAttempt =\n cardAddSubscriptionTokenRef.current !== null &&\n cardAddSubscriptionTokenRef.current !== subscriptionToken;\n if (!cardAdd3DS.isActive && (tokenChanged || staleCardAttempt)) {\n cardAddSubscriptionTokenRef.current = null;\n setIsAddDialogOpen(false);\n }\n }, [cardAdd3DS.isActive, setIsAddDialogOpen, subscriptionToken]);\n\n const cardAddSuccess = buildSubscriptionCardAddSuccess({\n begin: cardAdd3DS.begin,\n onCreated: (paymentMethodId) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (!isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n return;\n }\n queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n setIsAddDialogOpen(false);\n routeCreatedPaymentMethod(paymentMethodId);\n },\n });\n\n // Invalidation lives in the 3DS handlers (onApproved) and the created branch\n // (onCreated above), never in mutationFn — on the three_ds_required path the\n // mutation resolves the moment the challenge opens, so invalidating here would\n // refetch the list mid-challenge before the card is confirmed. Mirrors the\n // profile surface.\n const addCardMutation = useMutation({\n mutationFn: (data: CreditCardFormSubmitData) =>\n payApi.createPaymentMethod({\n payment_method: {\n type: \"card\",\n token: data.payment_method.token,\n token_provider: TOKEN_PROVIDER_VGS,\n exp_month: data.payment_method.exp_month,\n exp_year: data.payment_method.exp_year,\n cvv_token: data.payment_method.cvv_token,\n card_holder: data.payment_method.card_holder,\n default: data.set_as_default,\n ...(data.payment_method.bin ? { bin: data.payment_method.bin } : {}),\n ...(data.payment_method.last_four\n ? { last_four: data.payment_method.last_four }\n : {}),\n ...(data.payment_method.card_network\n ? { card_network: data.payment_method.card_network }\n : {}),\n },\n billing_address_id: data.billing_address_id,\n browser_info: getBrowserInfo(),\n }),\n onSuccess: async (response) => {\n if (!isCurrentPaymentAttempt(cardAddSubscriptionTokenRef.current)) {\n return;\n }\n await cardAddSuccess(response);\n },\n onError: (err) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onError?.(profileT(\"failed_to_add_payment_method\"), err);\n }\n },\n });\n\n const createAddressMutation = useMutation({\n mutationFn: (body: fluidPay.CreateAddressBody) => {\n return payApi.createAddress({\n address: {\n name: body.address.name,\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n phone: body.address.phone,\n },\n });\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n },\n onError: (err) => {\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onError?.(profileT(\"failed_to_create_address\"), err);\n }\n },\n });\n\n const updatePaymentMethodMutation = useMutation({\n mutationFn: ({\n paymentMethodId,\n data,\n }: {\n paymentMethodId: number;\n data: EditPaymentMethodFormData;\n }) =>\n payApi.updatePaymentMethod(paymentMethodId, {\n payment_method: {\n default: data.set_as_default,\n billing_address: {\n name: data.billing_address.name,\n street1: data.billing_address.address1,\n street2: data.billing_address.address2 ?? null,\n city: data.billing_address.city,\n state: data.billing_address.state,\n zip: data.billing_address.zip,\n country: data.billing_address.country_code,\n },\n },\n }),\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onSuccess?.(profileT(\"default_payment_method_updated\"));\n }\n },\n onError: (err) => {\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onError?.(profileT(\"failed_to_update_payment_method\"), err);\n }\n },\n });\n\n const deletePaymentMethodMutation = useMutation({\n mutationFn: (paymentMethodId: number) =>\n payApi.deletePaymentMethod(paymentMethodId),\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onSuccess?.(profileT(\"payment_method_deleted\"));\n }\n },\n });\n\n const makeDefaultPaymentMethodMutation = useMutation({\n mutationFn: (pm: fluidPay.CustomerPaymentMethod) => {\n const body: UpdatePaymentMethodBody = {\n payment_method: { default: true },\n };\n if (pm.billing_address) {\n body.payment_method.billing_address = {\n name: pm.billing_address.name,\n street1: pm.billing_address.address1 ?? \"\",\n street2: pm.billing_address.address2 ?? null,\n city: pm.billing_address.city ?? \"\",\n state: pm.billing_address.state ?? \"\",\n zip: pm.billing_address.zip ?? \"\",\n country: pm.billing_address.country_code ?? \"\",\n };\n }\n return payApi.updatePaymentMethod(pm.id, body);\n },\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onSuccess?.(profileT(\"default_payment_method_updated\"));\n }\n },\n onError: (err) => {\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onError?.(profileT(\"failed_to_set_default_payment_method\"), err);\n }\n },\n });\n\n // Fall back to the subscription's own payment method when the customer's\n // list doesn't contain it yet (initial load) or no longer contains it (card\n // was removed in another session). Without the fallback the collapsed\n // accordion header would render blank.\n const displayed =\n paymentMethods.find((pm) => pm.id === currentPaymentMethod.id) ??\n subscriptionPaymentMethodToFluidPay(currentPaymentMethod);\n\n const walletMutationPending =\n createAddressMutation.isPending ||\n updatePaymentMethodMutation.isPending ||\n deletePaymentMethodMutation.isPending ||\n makeDefaultPaymentMethodMutation.isPending;\n const cardAddPending = addCardMutation.isPending || cardAdd3DS.isActive;\n const hasAnyLocalPaymentActivity =\n updateSubscription.isPending ||\n retrySubscription.isPending ||\n retryStatusPolling.isProcessing ||\n cardAddPending ||\n walletMutationPending;\n const localPaymentActivity =\n (updateSubscription.isPending &&\n updateSubscription.variables?.subscriptionToken === subscriptionToken) ||\n (retrySubscription.isPending &&\n retrySubscription.variables?.subscriptionToken === subscriptionToken) ||\n retryStatusPolling.isProcessing ||\n (cardAddPending &&\n cardAddSubscriptionTokenRef.current === subscriptionToken) ||\n (walletMutationPending &&\n walletMutationSubscriptionTokenRef.current === subscriptionToken);\n const paymentActionsDisabled = disabled || hasAnyLocalPaymentActivity;\n\n useEffect(() => {\n onRecoveryStateChange?.({\n subscriptionToken,\n isBusy: localPaymentActivity,\n });\n }, [localPaymentActivity, onRecoveryStateChange, subscriptionToken]);\n\n useEffect(\n () => () => {\n onRecoveryStateChange?.({\n subscriptionToken,\n isBusy: false,\n });\n },\n [onRecoveryStateChange, subscriptionToken],\n );\n\n const handleConfirmDelete = async () => {\n if (paymentActionsDisabled || !deletingPaymentMethod) return;\n const initiatedSubscriptionToken = subscriptionToken;\n walletMutationSubscriptionTokenRef.current = initiatedSubscriptionToken;\n setDeleteError(undefined);\n try {\n await deletePaymentMethodMutation.mutateAsync(deletingPaymentMethod.id);\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n setDeletingPaymentMethod(null);\n }\n } catch (err) {\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n setDeleteError(\n err instanceof Error\n ? err.message\n : profileT(\"unable_to_delete_payment_method\"),\n );\n }\n }\n };\n\n return (\n <FluidPayCoreProvider api={fluidPayShim}>\n <SelectablePaymentMethodDropdown\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={subsT(\"payment_method\")}\n displayPaymentMethod={displayed}\n paymentMethodList={paymentMethods}\n onAddPaymentMethodClick={() => {\n if (paymentActionsDisabled) return;\n dropdownInitiatedAddRef.current = true;\n setIsAddDialogOpen(true);\n }}\n addPaymentMethodLabel={profileT(\"add_payment_method_action\")}\n showAddButton\n isLoading={isLoadingMethods}\n isPending={paymentActionsDisabled}\n selectedPaymentMethodId={currentPaymentMethod.id}\n onSelectPaymentMethod={(pm) => {\n if (paymentActionsDisabled || pm.id === currentPaymentMethod.id) {\n return;\n }\n updateSubscription.mutate({\n subscriptionToken,\n body: { payment_method_id: pm.id },\n });\n }}\n onEditPaymentMethod={\n paymentActionsDisabled\n ? undefined\n : (pm) => setEditingPaymentMethod(pm)\n }\n onDeletePaymentMethod={\n paymentActionsDisabled\n ? undefined\n : (pm) => {\n setDeleteError(undefined);\n setDeletingPaymentMethod(pm);\n }\n }\n onMakeDefaultPaymentMethod={\n paymentActionsDisabled\n ? undefined\n : (pm) => {\n walletMutationSubscriptionTokenRef.current = subscriptionToken;\n makeDefaultPaymentMethodMutation.mutate(pm);\n }\n }\n />\n\n <CreditCardFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isAddDialogOpen}\n onClose={() => {\n // Don't let the card dialog close while a 3DS challenge is in flight —\n // the bank-verification modal renders behind it and would be stranded.\n if (cardAdd3DS.isActive) return;\n // Reset the dropdown-initiated flag on every close (abandon or\n // post-submit) so a stale \"true\" from a closed-without-submit\n // dropdown attempt can't suppress the subscription swap on the\n // next banner/action open.\n dropdownInitiatedAddRef.current = false;\n cardAddSubscriptionTokenRef.current = null;\n setSaveCardError(null);\n setIsAddDialogOpen(false);\n }}\n error={saveCardError ?? undefined}\n t={tFn}\n onSubmit={async (data) => {\n if (paymentActionsDisabled) return;\n cardAddSubscriptionTokenRef.current = subscriptionToken;\n setSaveCardError(null);\n try {\n // Closure happens in cardAddSuccess (created PM) / the 3DS\n // onApproved branch — NOT here, since a three_ds_required response\n // resolves successfully while the bank check is still pending.\n await addCardMutation.mutateAsync(data);\n } catch {\n // onError surfaces the toast; swallow here so CreditCardFormDialog\n // doesn't see an unhandled rejection from its onSubmit handler.\n }\n }}\n isSubmitting={paymentActionsDisabled}\n jwt=\"\"\n savedAddresses={addresses}\n defaultBillingAddressId={addresses.find((a) => a.default)?.id}\n renderAddressFormDialog={({ isOpen, onClose, onAddressCreated }) => (\n <AddressFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isOpen}\n onClose={onClose}\n selectedAddress={null}\n t={tFn}\n onSubmit={async (formData) => {\n if (paymentActionsDisabled) return;\n const initiatedSubscriptionToken = subscriptionToken;\n walletMutationSubscriptionTokenRef.current =\n initiatedSubscriptionToken;\n try {\n const created =\n await createAddressMutation.mutateAsync(formData);\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onAddressCreated(mapToFluidPayAddress(created));\n }\n } catch {\n // onError surfaces the toast.\n }\n }}\n isSubmitting={paymentActionsDisabled}\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n languageIso={locale}\n />\n )}\n />\n\n {cardAdd3DS.modal}\n\n <EditPaymentMethodDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={editingPaymentMethod !== null}\n paymentMethod={editingPaymentMethod}\n billingAddress={editingPaymentMethod?.billing_address ?? null}\n onClose={() => setEditingPaymentMethod(null)}\n onSubmit={async (data) => {\n if (paymentActionsDisabled || !editingPaymentMethod) return;\n const initiatedSubscriptionToken = subscriptionToken;\n walletMutationSubscriptionTokenRef.current =\n initiatedSubscriptionToken;\n try {\n await updatePaymentMethodMutation.mutateAsync({\n paymentMethodId: editingPaymentMethod.id,\n data,\n });\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n setEditingPaymentMethod(null);\n }\n } catch {\n // onError surfaces the toast.\n }\n }}\n isSubmitting={paymentActionsDisabled}\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n languageIso={locale}\n />\n\n <ConfirmActionDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={profileT(\"delete_credit_card\")}\n description={profileT(\"delete_credit_card_message\")}\n actionText={profileT(\"delete\")}\n openDialog={deletingPaymentMethod !== null}\n setOpenDialog={(open) => {\n if (!open) {\n setDeletingPaymentMethod(null);\n setDeleteError(undefined);\n }\n }}\n onAction={handleConfirmDelete}\n errorMsg={deleteError}\n isLoading={paymentActionsDisabled}\n />\n </FluidPayCoreProvider>\n );\n}\n","import { useId, useState, type JSX } from \"react\";\nimport { cn, Skeleton } from \"@fluid-app/ui-primitives\";\nimport { ChevronDown } from \"lucide-react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { EllipsesDropdown } from \"@fluid-app/profile-ui\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport type { ResponsiveDialogPresentation } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\n\ninterface SelectableAddressDropdownProps {\n title: string;\n displayAddress: fluidPay.CustomerAddress | null;\n addressList: fluidPay.CustomerAddress[];\n selectedAddressId: number;\n onSelectAddress: (address: fluidPay.CustomerAddress) => void;\n onAddAddressClick: () => void;\n onEditAddress?: (address: fluidPay.CustomerAddress) => void;\n onDeleteAddress?: (address: fluidPay.CustomerAddress) => void;\n onMakeDefaultAddress?: (address: fluidPay.CustomerAddress) => void;\n addAddressLabel?: string;\n showAddButton?: boolean;\n isLoading?: boolean;\n /** Disable selection while a parent mutation is in flight. */\n isPending?: boolean;\n /** Start expanded (list visible) instead of collapsed to the summary. */\n defaultOpen?: boolean;\n className?: string;\n presentation?: ResponsiveDialogPresentation;\n}\n\nfunction formatLine1(address: fluidPay.CustomerAddress): string {\n return [address.address1, address.address2].filter(Boolean).join(\", \");\n}\n\nfunction formatCityStateZip(address: fluidPay.CustomerAddress): string {\n const cityState = [address.city, address.state].filter(Boolean).join(\", \");\n return [cityState, address.postal_code].filter(Boolean).join(\" \");\n}\n\n/**\n * Selectable variant of profile-ui's AddressDropdown, mirroring\n * SelectablePaymentMethodDropdown. Flat layout (no Card wrapper) so it\n * sits inline next to the payment method dropdown in the subscription\n * detail's Payment & Shipping section.\n */\nexport function SelectableAddressDropdown({\n title,\n displayAddress,\n addressList,\n selectedAddressId,\n onSelectAddress,\n onAddAddressClick,\n onEditAddress,\n onDeleteAddress,\n onMakeDefaultAddress,\n addAddressLabel: addAddressLabelProp,\n showAddButton = true,\n isLoading = false,\n isPending = false,\n defaultOpen = false,\n className = \"\",\n presentation = \"dialog\",\n}: SelectableAddressDropdownProps): JSX.Element {\n const { t } = useProfileTranslation();\n const addAddressLabel = addAddressLabelProp ?? t(\"add_an_address\");\n const [isOpen, setIsOpen] = useState(defaultOpen);\n const sectionId = useId();\n\n return (\n <div className={cn(\"border-border mb-6 border-b pb-4\", className)}>\n <button\n type=\"button\"\n aria-expanded={isOpen}\n aria-controls={sectionId}\n onClick={() => setIsOpen((prev) => !prev)}\n className=\"flex w-full flex-row items-center justify-between\"\n >\n <span className=\"text-muted-foreground text-sm\">{title}</span>\n <ChevronDown\n className={cn(\n \"text-muted-foreground h-4 w-4 transition-transform duration-200\",\n isOpen && \"rotate-180\",\n )}\n />\n </button>\n\n {/* Collapsed summary — shows the subscription's current address inline.\n Clicking expands. Mirrors checkout's address-dropdown collapse\n behavior. */}\n {!isOpen && displayAddress && (\n <button\n type=\"button\"\n onClick={() => setIsOpen(true)}\n className=\"mt-1 mb-2 flex w-full cursor-pointer flex-col text-left\"\n >\n <span className=\"text-foreground text-sm font-medium\">\n {displayAddress.name}\n {displayAddress.name && displayAddress.address1 ? \", \" : \"\"}\n {displayAddress.address1}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n {formatCityStateZip(displayAddress)}\n </span>\n {displayAddress.phone && (\n <span className=\"text-muted-foreground text-sm\">\n {displayAddress.phone}\n </span>\n )}\n </button>\n )}\n\n {isOpen && (\n <div\n id={sectionId}\n role=\"listbox\"\n aria-label={title}\n className=\"mt-5 flex max-h-[400px] flex-col gap-y-4 overflow-y-auto pr-0.5\"\n >\n {isLoading ? (\n <>\n {[1, 2].map((i) => (\n <div key={`skeleton-${i}`} className=\"bg-muted rounded-sm p-3\">\n <Skeleton className=\"mb-1 h-4 w-32\" />\n <Skeleton className=\"mb-1 h-4 w-48\" />\n <Skeleton className=\"h-4 w-40\" />\n </div>\n ))}\n </>\n ) : (\n addressList.map((address) => {\n const isSelected = selectedAddressId === address.id;\n const handleSelect = () => {\n if (isPending) return;\n onSelectAddress(address);\n };\n return (\n <div\n key={address.id}\n role=\"option\"\n tabIndex={isPending ? -1 : 0}\n aria-selected={isSelected}\n aria-disabled={isPending}\n onClick={handleSelect}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleSelect();\n }\n }}\n className={cn(\n \"text-foreground flex w-full flex-row items-center justify-between gap-3 rounded-sm p-3 text-left transition-colors\",\n \"not-aria-disabled:cursor-pointer aria-disabled:cursor-not-allowed aria-disabled:opacity-60\",\n isSelected\n ? \"bg-background border-border border\"\n : \"bg-muted hover:bg-muted/80 border border-transparent\",\n )}\n >\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"text-foreground text-sm font-medium\">\n {address.name}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n {formatLine1(address)}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n {formatCityStateZip(address)}\n </span>\n {address.phone && (\n <span className=\"text-muted-foreground text-sm\">\n {address.phone}\n </span>\n )}\n </div>\n <div className=\"flex shrink-0 flex-row items-center gap-2\">\n {address.default && (\n <span className=\"bg-primary text-primary-foreground rounded px-2 py-0.5 text-xs font-medium\">\n {t(\"default\")}\n </span>\n )}\n {(onEditAddress ||\n onDeleteAddress ||\n onMakeDefaultAddress) && (\n <span\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <EllipsesDropdown\n presentation={presentation}\n onEdit={\n onEditAddress\n ? () => onEditAddress(address)\n : undefined\n }\n onDelete={\n onDeleteAddress\n ? () => onDeleteAddress(address)\n : undefined\n }\n onMakeDefault={\n !address.default && onMakeDefaultAddress\n ? () => onMakeDefaultAddress(address)\n : undefined\n }\n />\n </span>\n )}\n </div>\n </div>\n );\n })\n )}\n </div>\n )}\n\n {showAddButton && (\n <button\n type=\"button\"\n disabled={isPending}\n className=\"text-foreground mt-3 text-left text-sm disabled:cursor-not-allowed disabled:opacity-60\"\n onClick={onAddAddressClick}\n >\n {addAddressLabel}\n </button>\n )}\n </div>\n );\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type JSX,\n} from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport {\n FluidPayCoreProvider,\n type fluidPay,\n type State,\n} from \"@fluid-app/fluid-pay-core\";\nimport { AddressFormDialog, ConfirmActionDialog } from \"@fluid-app/profile-ui\";\nimport { useActiveLocale } from \"@fluid-app/i18n/locale-context\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { useUpdateSubscriptionInfo } from \"@fluid-app/subscriptions-core\";\nimport type { ShippingAddressSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport type { PayAddress } from \"@fluid-app/portal-core/pay-types\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { useCountriesApi } from \"@fluid-app/store-core/countries-api-context\";\nimport { payKeys, storeKeys } from \"../account/query-keys\";\nimport { createFluidPayApiAdapter } from \"../adapters/fluid-pay-api-adapter\";\nimport { useFluidContext } from \"../providers/FluidProvider\";\nimport { ProfileTranslationBridge } from \"../providers/ProfileTranslationBridge\";\nimport { SelectableAddressDropdown } from \"./SelectableAddressDropdown\";\nimport { isCurrentSubscriptionPaymentAttempt } from \"./subscription-payment-recovery\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n phone: raw.phone,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\n// Fall back when the customer's saved-address list doesn't contain the\n// subscription's current address (initial load before fetch, or address\n// removed in another session). Without this the collapsed accordion\n// header would render blank.\n//\n// `id` may be null when the BE serves the snapshot rather than the live\n// row; this fallback is display-only (identity comparisons use the\n// addressId prop instead), so 0 is a safe sentinel matching the\n// `addressId ?? 0` pattern elsewhere in this component.\nfunction subscriptionAddressToFluidPay(\n raw: ShippingAddressSlotContext[\"address\"],\n): fluidPay.CustomerAddress | null {\n if (!raw) return null;\n return {\n id: raw.id ?? 0,\n address1: raw.address1,\n address2: raw.address2,\n city: raw.city,\n country_code: raw.country_code,\n default: raw.default,\n name: raw.name,\n postal_code: raw.postal_code,\n phone: raw.phone ?? null,\n state: raw.state,\n subdivision_code: raw.subdivision_code,\n };\n}\n\ntype ShippingAddressSectionProps = ShippingAddressSlotContext & {\n // `severity` is omitted for normal success and set to \"warning\" when the\n // backend deduped an address create (existing record returned). Callers that\n // ignore the second argument default to a success toast.\n onSuccess?: (message: string, severity?: \"success\" | \"warning\") => void;\n onError?: (message: string, error: unknown) => void;\n};\n\nexport function PortalSubscriptionShippingAddressSection(\n props: ShippingAddressSectionProps,\n): JSX.Element {\n return (\n <ProfileTranslationBridge>\n <PortalSubscriptionShippingAddressSectionInner {...props} />\n </ProfileTranslationBridge>\n );\n}\n\nfunction PortalSubscriptionShippingAddressSectionInner({\n addressId,\n address: currentAddress,\n subscriptionToken,\n disabled,\n onSuccess,\n onError,\n}: ShippingAddressSectionProps): JSX.Element {\n const { isMobile } = useSidebar();\n const { t: profileT } = useProfileTranslation();\n const { t: subsT } = useSubscriptionsTranslation();\n const { config } = useFluidContext();\n const { locale } = useActiveLocale();\n const latestSubscriptionTokenRef = useRef(subscriptionToken);\n latestSubscriptionTokenRef.current = subscriptionToken;\n const isCurrentAddressAttempt = (attemptSubscriptionToken: string) =>\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n attemptSubscriptionToken,\n );\n\n // Bridge for fluid-pay-ui dialogs that accept `t: (key: string) => string`.\n // The underlying adapter falls back to `key` for unknown keys, so widening\n // the key type is safe at runtime.\n const tFn = useCallback(\n (key: string): string => profileT(key as never),\n [profileT],\n );\n\n const payApi = usePayApi();\n const queryClient = useQueryClient();\n const fluidPayShim = useMemo(\n () => createFluidPayApiAdapter(payApi),\n [payApi],\n );\n\n const [isFormDialogOpen, setIsFormDialogOpen] = useState(false);\n const [editingAddress, setEditingAddress] =\n useState<fluidPay.CustomerAddress | null>(null);\n const [deletingAddress, setDeletingAddress] =\n useState<fluidPay.CustomerAddress | null>(null);\n const [deleteError, setDeleteError] = useState<string | undefined>(undefined);\n const previousDialogSubscriptionTokenRef = useRef(subscriptionToken);\n\n useEffect(() => {\n if (previousDialogSubscriptionTokenRef.current === subscriptionToken) {\n return;\n }\n\n previousDialogSubscriptionTokenRef.current = subscriptionToken;\n setIsFormDialogOpen(false);\n setEditingAddress(null);\n setDeletingAddress(null);\n setDeleteError(undefined);\n }, [subscriptionToken]);\n\n const { data: addresses = [], isLoading } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n });\n\n const countriesApi = useCountriesApi();\n const { data: countriesData } = useQuery({\n queryKey: storeKeys.countries(locale),\n queryFn: () => countriesApi.listCountries({ languageIso: locale }),\n enabled: isFormDialogOpen,\n });\n const countryOptions = useMemo(\n () =>\n [...(countriesData?.countries ?? [])]\n .map((c) => ({ iso: c.code, name: c.name }))\n .sort((a, b) => a.name.localeCompare(b.name)),\n [countriesData],\n );\n const statesByCountry = useMemo(() => {\n const map = new Map<string, State[]>();\n for (const c of countriesData?.countries ?? []) {\n map.set(\n c.code,\n c.states.map((s) => ({ name: s.name, isoCode: s.code })),\n );\n }\n return map;\n }, [countriesData]);\n const fetchStatesFromCountries = useCallback(\n (countryCode: string): Promise<State[]> =>\n Promise.resolve(statesByCountry.get(countryCode) ?? []),\n [statesByCountry],\n );\n\n const updateSubscription = useUpdateSubscriptionInfo({\n onSuccess: ({ subscriptionToken: updatedSubscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== updatedSubscriptionToken) {\n return;\n }\n onSuccess?.(profileT(\"shipping_address_updated\"));\n },\n onError: (err, { subscriptionToken: failedSubscriptionToken }) => {\n if (latestSubscriptionTokenRef.current === failedSubscriptionToken) {\n onError?.(profileT(\"failed_to_update_shipping_address\"), err);\n }\n },\n });\n\n const createAddressMutation = useMutation({\n // Detect a server-side dedupe (POST /api/pay/addresses returns the existing\n // record when an identical address already exists, ignoring `name`). Snapshot\n // the current id set before the request and compare against the returned id.\n mutationFn: async ({\n body,\n }: {\n subscriptionToken: string;\n body: fluidPay.CreateAddressBody;\n }) => {\n const existingIds = new Set(addresses.map((a) => a.id));\n const address = await payApi.createAddress({\n address: {\n name: body.address.name,\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n phone: body.address.phone,\n default: body.address.default,\n },\n });\n return { address, deduped: existingIds.has(address.id) };\n },\n onSuccess: ({ deduped }, { subscriptionToken }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (!isCurrentAddressAttempt(subscriptionToken)) return;\n if (deduped) {\n onSuccess?.(profileT(\"address_already_exists\"), \"warning\");\n } else {\n onSuccess?.(profileT(\"address_created\"), \"success\");\n }\n },\n onError: (err, { subscriptionToken }) => {\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onError?.(profileT(\"failed_to_create_address\"), err);\n }\n },\n });\n\n const updateAddressMutation = useMutation({\n mutationFn: ({\n addressId,\n body,\n }: {\n subscriptionToken: string;\n addressId: number;\n body: fluidPay.CreateAddressBody;\n }) =>\n payApi.updateAddress(addressId, {\n address: {\n name: body.address.name,\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n phone: body.address.phone,\n default: body.address.default,\n },\n }),\n onSuccess: (_address, { subscriptionToken }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onSuccess?.(profileT(\"address_updated\"));\n }\n },\n onError: (err, { subscriptionToken }) => {\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onError?.(profileT(\"failed_to_update_address\"), err);\n }\n },\n });\n\n const deleteAddressMutation = useMutation({\n mutationFn: ({\n addressId,\n }: {\n subscriptionToken: string;\n addressId: number;\n }) => payApi.deleteAddress(addressId),\n onSuccess: (_address, { subscriptionToken }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onSuccess?.(profileT(\"address_deleted\"));\n }\n },\n });\n\n const makeDefaultAddressMutation = useMutation({\n mutationFn: ({\n address,\n }: {\n subscriptionToken: string;\n address: fluidPay.CustomerAddress;\n }) =>\n payApi.updateAddress(address.id, {\n address: {\n name: address.name ?? null,\n street1: address.address1 ?? \"\",\n street2: address.address2,\n city: address.city ?? \"\",\n state: address.state ?? \"\",\n zip: address.postal_code ?? \"\",\n country: address.country_code ?? \"\",\n phone: address.phone,\n default: true,\n },\n }),\n onSuccess: (_address, { subscriptionToken }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onSuccess?.(profileT(\"default_address_updated\"));\n }\n },\n onError: (err, { subscriptionToken }) => {\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onError?.(profileT(\"failed_to_update_default_address\"), err);\n }\n },\n });\n\n // Match against the stable FK (addressId), not currentAddress.id — the\n // latter is null when the subscription resolved through the snapshot path.\n // Fall back to content matching when subscription and pay address ID spaces\n // differ so omitted fields such as `phone` still come from the saved record.\n const displayed =\n (addressId !== null\n ? addresses.find((a) => a.id === addressId)\n : undefined) ??\n (currentAddress\n ? addresses.find(\n (a) =>\n a.address1 === currentAddress.address1 &&\n a.postal_code === currentAddress.postal_code &&\n a.city === currentAddress.city,\n )\n : undefined) ??\n subscriptionAddressToFluidPay(currentAddress);\n\n const handleCloseFormDialog = () => {\n setIsFormDialogOpen(false);\n setEditingAddress(null);\n };\n\n const handleConfirmDelete = async () => {\n if (!deletingAddress) return;\n const initiatedSubscriptionToken = subscriptionToken;\n setDeleteError(undefined);\n try {\n await deleteAddressMutation.mutateAsync({\n subscriptionToken: initiatedSubscriptionToken,\n addressId: deletingAddress.id,\n });\n if (isCurrentAddressAttempt(initiatedSubscriptionToken)) {\n setDeletingAddress(null);\n }\n } catch (err) {\n if (isCurrentAddressAttempt(initiatedSubscriptionToken)) {\n setDeleteError(\n err instanceof Error\n ? err.message\n : profileT(\"unable_to_delete_address\"),\n );\n }\n }\n };\n\n return (\n <FluidPayCoreProvider api={fluidPayShim}>\n <SelectableAddressDropdown\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={subsT(\"shipping_address\")}\n displayAddress={displayed}\n addressList={addresses}\n selectedAddressId={addressId ?? 0}\n onSelectAddress={(addr) => {\n if (addr.id === addressId) return;\n updateSubscription.mutate({\n subscriptionToken,\n body: { address_id: addr.id },\n });\n }}\n onAddAddressClick={() => {\n setEditingAddress(null);\n setIsFormDialogOpen(true);\n }}\n onEditAddress={\n disabled\n ? undefined\n : (addr) => {\n setEditingAddress(addr);\n setIsFormDialogOpen(true);\n }\n }\n onDeleteAddress={\n disabled\n ? undefined\n : (addr) => {\n setDeleteError(undefined);\n setDeletingAddress(addr);\n }\n }\n onMakeDefaultAddress={\n disabled\n ? undefined\n : (addr) =>\n makeDefaultAddressMutation.mutate({\n subscriptionToken,\n address: addr,\n })\n }\n addAddressLabel={profileT(\"add_an_address_action\")}\n showAddButton={!disabled}\n isLoading={isLoading}\n isPending={\n disabled ||\n updateSubscription.isPending ||\n createAddressMutation.isPending ||\n updateAddressMutation.isPending ||\n deleteAddressMutation.isPending ||\n makeDefaultAddressMutation.isPending\n }\n />\n\n <AddressFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isFormDialogOpen}\n onClose={handleCloseFormDialog}\n selectedAddress={editingAddress}\n defaultCountry={\n addresses.find((a) => a.default)?.country_code ??\n currentAddress?.country_code ??\n config.countryIso ??\n \"US\"\n }\n languageIso={locale}\n t={tFn}\n onSubmit={async (data: fluidPay.CreateAddressBody) => {\n const initiatedSubscriptionToken = subscriptionToken;\n try {\n if (editingAddress) {\n await updateAddressMutation.mutateAsync({\n subscriptionToken: initiatedSubscriptionToken,\n addressId: editingAddress.id,\n body: data,\n });\n } else {\n await createAddressMutation.mutateAsync({\n subscriptionToken: initiatedSubscriptionToken,\n body: data,\n });\n }\n if (isCurrentAddressAttempt(initiatedSubscriptionToken)) {\n handleCloseFormDialog();\n }\n } catch {\n // onError surfaces the toast; swallow here so AddressFormDialog\n // doesn't see an unhandled rejection from its onSubmit handler.\n }\n }}\n isSubmitting={\n createAddressMutation.isPending || updateAddressMutation.isPending\n }\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n />\n\n <ConfirmActionDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={profileT(\"delete_address\")}\n description={profileT(\"delete_address_message\")}\n actionText={profileT(\"delete\")}\n openDialog={deletingAddress !== null}\n setOpenDialog={(open) => {\n if (!open) {\n setDeletingAddress(null);\n setDeleteError(undefined);\n }\n }}\n onAction={handleConfirmDelete}\n errorMsg={deleteError}\n isLoading={deleteAddressMutation.isPending}\n />\n </FluidPayCoreProvider>\n );\n}\n","import { useRef } from \"react\";\nimport {\n useMutation,\n useQueryClient,\n type UseMutationResult,\n} from \"@tanstack/react-query\";\nimport { useAutoApplyPointsApi } from \"../auto-apply-points-api-context\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport type {\n AutoApplyPointsScope,\n AutoApplyPointsWriteResult,\n} from \"../auto-apply-points-api\";\nimport type { subscriptions } from \"../types\";\n\nexport type UpdateAutoApplyPointsVariables = {\n subscriptionToken: string;\n autoApplyPoints: boolean;\n scope: AutoApplyPointsScope;\n /**\n * Every token the caller believes belongs to this bundle at the moment it\n * fires the write, independent of what the server ends up resolving.\n * Never crosses the AutoApplyPointsApi port - mutationFn below forwards\n * only the three fields above. Purely client-side bookkeeping: a\n * subscription-scoped write reports only the target as resolved, but\n * every sibling's cached renewal_bundle embeds this subscription's\n * contribution to the aggregate auto_apply_points_state, so a sibling the\n * server never mentions can still be showing a stale aggregate. Also\n * widens writeInFlight below so a second write reaching a sibling that\n * isn't the target can still disable that sibling's own control.\n */\n bundleTokens?: string[];\n};\n\nexport type UpdateAutoApplyPointsOutcome = {\n result: AutoApplyPointsWriteResult;\n /**\n * Whether the refetched payload confirms the value that was written. False\n * means the write landed and the read did not, which the caller reports\n * differently from a clean success.\n */\n refreshed: boolean;\n variables: UpdateAutoApplyPointsVariables;\n};\n\n/**\n * Writes the points opt-in through the AutoApplyPointsApi port.\n *\n * The first four guarantees below came from useUpdateSubscriptionInfo, which\n * this replaces for the portal's control. Restated rather than inherited,\n * because invalidating the same keys does not reproduce them: the mutation\n * can settle while the switch still shows the old value, and the\n * partial-success path can vanish silently. The last two are specific to\n * this hook's bundle-aware writes, which useUpdateSubscriptionInfo never had\n * to consider.\n *\n * 1. Awaits the target detail refetch before leaving pending.\n * 2. Keeps the list invalidation, unconditionally on success.\n * 3. Retains the stale-token guard, scoped to the consumer callback only.\n * 4. Surfaces the partial outcome via `refreshed: false`.\n * 5. Invalidates the union of the server's resolved tokens and the caller's\n * own `bundleTokens`, not the server's set alone -- a subscription-scoped\n * write only resolves its target, but every sibling's cached bundle\n * aggregate still shifts.\n * 6. Never lets a stalled sibling invalidation hold up the target's own\n * awaited refetch.\n */\nexport function useUpdateAutoApplyPoints({\n currentSubscriptionToken,\n onSuccess,\n onError,\n}: {\n /**\n * The token on screen right now. A response for anything else is discarded,\n * so an outcome never lands on a sibling the customer navigated to.\n */\n currentSubscriptionToken?: string;\n onSuccess?: (outcome: UpdateAutoApplyPointsOutcome) => void;\n onError?: (error: unknown, variables: UpdateAutoApplyPointsVariables) => void;\n} = {}): UseMutationResult<\n AutoApplyPointsWriteResult,\n unknown,\n UpdateAutoApplyPointsVariables\n> {\n const api = useAutoApplyPointsApi();\n const queryClient = useQueryClient();\n\n // A ref rather than the prop directly: the callbacks below close over the\n // render in which the mutation started, so reading the prop would compare\n // against a stale token.\n const latestTokenRef = useRef(currentSubscriptionToken);\n latestTokenRef.current = currentSubscriptionToken;\n\n return useMutation({\n mutationFn: ({\n subscriptionToken,\n autoApplyPoints,\n scope,\n }: UpdateAutoApplyPointsVariables) =>\n api.updateAutoApplyPoints({ subscriptionToken, autoApplyPoints, scope }),\n onSuccess: async (result, variables) => {\n // Cache work runs unconditionally, regardless of which subscription is\n // on screen right now: the write already landed, so skipping the\n // refresh would leave the cache wrong with nothing left to correct it.\n // A customer who navigates away mid-write and back within the\n // library's staleTime window would otherwise see the pre-write value.\n // Only the consumer-facing callback below is guarded.\n\n // Every sibling the write could have moved: what the server actually\n // resolved, unioned with what the caller already knew was in the\n // bundle when it fired (bundleTokens). The union matters because a\n // subscription-scoped write reports only the target as resolved, yet\n // every other member's cached renewal_bundle still embeds this\n // subscription's contribution to the aggregate auto_apply_points_state\n // -- a sibling the server never mentions can still be showing a stale\n // aggregate. The target itself is excluded: it gets the explicit,\n // awaited refetch below rather than an invalidate, and\n // invalidateQueries internally calls refetchQueries on the same\n // instance, so leaving it in this set would race a second,\n // unawaited refetch against the one awaited next.\n const siblingTokens = [\n ...new Set([\n ...result.resolvedSubscriptionTokens,\n ...(variables.bundleTokens ?? []),\n ]),\n ].filter((token) => token !== variables.subscriptionToken);\n\n // Not awaited: the target refetch just below is the one thing the\n // caller is actually waiting on, and an actively-observed sibling GET\n // that hangs must not hold that up. Each invalidation swallows its own\n // rejection so a failed sibling fetch can't surface as an unhandled\n // rejection now that nothing awaits this Promise.all.\n void Promise.all(\n siblingTokens.map((token) =>\n queryClient\n .invalidateQueries({\n queryKey: subscriptionsKeys.detail(token),\n exact: true,\n })\n .catch(() => {}),\n ),\n );\n\n // Bare prefixes, not the parameterized list()/infiniteList() calls:\n // those are genuine wildcards, matching every cached query under them.\n // list() with no arguments carries an `undefined` params slot, which\n // never matches a real cached query (every caller passes concrete\n // params), so it silently invalidates nothing.\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n });\n\n // Awaited on purpose: leaving pending before the server's answer is in\n // hand would report success next to a control still showing the old\n // value. `exact` matters, since key filters match by prefix and the\n // failed-cycle-waiver key is a child of detail(token).\n await queryClient.refetchQueries({\n queryKey: subscriptionsKeys.detail(variables.subscriptionToken),\n exact: true,\n });\n\n // Guards only the outcome reported to the caller: a response that\n // settles after the screen moved to a sibling must not land there.\n if (\n latestTokenRef.current &&\n latestTokenRef.current !== variables.subscriptionToken\n ) {\n return;\n }\n\n const refreshedDetail =\n queryClient.getQueryData<subscriptions.SubscriptionDetail>(\n subscriptionsKeys.detail(variables.subscriptionToken),\n );\n\n onSuccess?.({\n result,\n refreshed:\n refreshedDetail?.subscription.auto_apply_points ===\n variables.autoApplyPoints,\n variables,\n });\n },\n onError: (error, variables) => {\n if (\n latestTokenRef.current &&\n latestTokenRef.current !== variables.subscriptionToken\n ) {\n return;\n }\n onError?.(error, variables);\n },\n });\n}\n","import type { AutoApplyPointsSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport type {\n subscriptions,\n AutoApplyPointsScope,\n} from \"@fluid-app/subscriptions-core\";\n\nexport interface AutoApplyPointsControlState {\n /** Whether the control belongs on this subscription at all. */\n visible: boolean;\n checked: boolean;\n disabled: boolean;\n}\n\n/**\n * Resolve what the auto-apply-points switch shows, from server state alone.\n *\n * Three rules, each written against a specific way this can go wrong:\n *\n * - A company that does not run a points program never sees the control. An\n * absent `pointsEnabled` counts as off rather than on: the field is\n * additive, so an older payload, or a read path that quietly drops it,\n * must hide a setting that could not act instead of offering it.\n * - `checked` comes from the payload and never from a default. Defaulting to\n * off would render the switch unset while the server held the customer's\n * opt-in, which reads as \"their choice was lost\".\n * - An in-flight write disables the control and leaves it showing the last\n * value the server confirmed. Because there is no optimistic state, a\n * failed write has nothing to roll back and cannot leave the switch\n * misreporting what is stored.\n */\nexport function autoApplyPointsControlState(input: {\n autoApplyPoints: AutoApplyPointsSlotContext[\"autoApplyPoints\"];\n pointsEnabled: AutoApplyPointsSlotContext[\"pointsEnabled\"];\n subscriptionDisabled: boolean;\n writeInFlight: boolean;\n}): AutoApplyPointsControlState {\n return {\n visible: input.pointsEnabled === true,\n checked: input.autoApplyPoints === true,\n disabled: input.subscriptionDisabled || input.writeInFlight,\n };\n}\n\n/** Which write path a toggle should take. */\nexport type AutoApplyPointsWriteRoute = \"fallback\" | \"write\" | \"confirm\";\n\n/**\n * Decide how a toggle is written, from the payload alone.\n *\n * Three rules, each against a specific way this can go wrong:\n *\n * - No renewal bundle means the server did not populate it, so the\n * bundle-aware port cannot be used: it requires a scope and both token\n * arrays, and such a server sends neither. The shared write handles it.\n * - One member, or none, is not a group. Asking a customer to confirm a\n * fan-out that reaches nothing but the subscription in front of them is a\n * dialog with no decision in it.\n * - More than one member means the write reaches subscriptions the customer\n * is not looking at, so they are asked first.\n *\n * Returns \"fallback\", \"write\" or \"confirm\".\n */\nexport function autoApplyPointsWriteRoute(input: {\n renewalBundle?: subscriptions.SubscriptionRenewalBundle | null;\n}): AutoApplyPointsWriteRoute {\n if (!input.renewalBundle) return \"fallback\";\n\n return input.renewalBundle.members.length > 1 ? \"confirm\" : \"write\";\n}\n\n/**\n * Whether the server resolved a different set than the customer agreed to.\n *\n * The expected set is scope-specific, and that is the whole point. After\n * \"Just this one\" the server deliberately returns the target alone while the\n * dialog rendered every member, so comparing the response against the\n * rendered set would report drift on the most common path. The comparison is\n * order-insensitive because neither side promises an order.\n *\n * Returns true when the customer should be told the group changed.\n */\nexport function autoApplyPointsMembershipDrifted(input: {\n confirmedScope: AutoApplyPointsScope;\n renderedTokens: string[];\n targetToken: string;\n resolvedTokens: string[];\n}): boolean {\n const expected =\n input.confirmedScope === \"bundle\"\n ? input.renderedTokens\n : [input.targetToken];\n\n return (\n [...input.resolvedTokens].sort().join(\"\\u0000\") !==\n [...expected].sort().join(\"\\u0000\")\n );\n}\n","import type { JSX } from \"react\";\nimport { Button, DialogFooter } from \"@fluid-app/ui-primitives\";\nimport { ResponsiveDialog } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\n\n/**\n * Asks whether a points opt-in applies to the whole renewal group.\n *\n * Names every member, because the customer is agreeing to a change on\n * subscriptions other than the one on screen. Paused members are named and\n * labelled: they bill, so they are affected. Built on ResponsiveDialog, the\n * same primitive PortalReactivateSubscriptionDialog uses one file over, so\n * this gets a focus trap, escape-to-close and backdrop dismissal for free\n * rather than reimplementing dialog semantics by hand.\n */\nexport function BundleFanOutDialog({\n bundle,\n pointsLabel,\n nextValue,\n onConfirmAll,\n onConfirmOne,\n onCancel,\n}: {\n bundle: subscriptions.SubscriptionRenewalBundle;\n pointsLabel: string;\n /**\n * The value the switch is being set to. The title and the \"Apply to all\"\n * button read as an instruction to turn the setting on, which is backwards\n * when the customer just turned an enabled subscription off -- this picks\n * the matching copy so the confirmation describes what the button\n * actually does.\n */\n nextValue: boolean;\n onConfirmAll: () => void;\n onConfirmOne: () => void;\n onCancel: () => void;\n}): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const { isMobile } = useSidebar();\n\n return (\n <ResponsiveDialog\n open\n onOpenChange={(next) => {\n if (!next) onCancel();\n }}\n title={t(\n nextValue\n ? \"auto_apply_points_bundle_title\"\n : \"auto_apply_points_bundle_title_off\",\n { label: pointsLabel },\n )}\n description={t(\"auto_apply_points_bundle_body\")}\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n >\n <ul className=\"space-y-1 text-sm\">\n {bundle.members.map((bundleMember) => (\n <li key={bundleMember.subscription_token} className=\"text-foreground\">\n {bundleMember.status === \"paused\"\n ? t(\"auto_apply_points_bundle_member_paused\", {\n name: bundleMember.label,\n })\n : bundleMember.label}\n </li>\n ))}\n </ul>\n <DialogFooter>\n <Button\n type=\"button\"\n className=\"bg-muted text-foreground ring-border hover:bg-muted/80 h-10 min-w-[70px] rounded p-3 ring-1\"\n onClick={onCancel}\n >\n {t(\"auto_apply_points_bundle_cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"bg-muted text-foreground ring-border hover:bg-muted/80 h-10 min-w-[70px] rounded p-3 ring-1\"\n onClick={onConfirmOne}\n >\n {t(\"auto_apply_points_bundle_confirm_one\")}\n </Button>\n <Button\n type=\"button\"\n className=\"bg-primary text-primary-foreground h-10 min-w-[70px] rounded p-3 hover:opacity-90\"\n onClick={onConfirmAll}\n >\n {t(\n nextValue\n ? \"auto_apply_points_bundle_confirm_all\"\n : \"auto_apply_points_bundle_confirm_all_off\",\n )}\n </Button>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import { useId, useRef, useState, type JSX } from \"react\";\nimport { useIsFetching, useQueryClient } from \"@tanstack/react-query\";\nimport { Switch } from \"@fluid-app/ui-primitives\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n subscriptionsKeys,\n useUpdateSubscriptionInfo,\n BundleMembershipConflictError,\n type subscriptions,\n type AutoApplyPointsScope,\n} from \"@fluid-app/subscriptions-core\";\nimport { useUpdateAutoApplyPoints } from \"@fluid-app/subscriptions-core/hooks\";\nimport type { AutoApplyPointsSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport { useOptionalStore } from \"@fluid-app/portal-react/hooks/use-optional-store\";\nimport {\n autoApplyPointsControlState,\n autoApplyPointsWriteRoute,\n autoApplyPointsMembershipDrifted,\n} from \"./subscription-auto-apply-points\";\nimport { isCurrentSubscriptionPaymentAttempt } from \"./subscription-payment-recovery\";\nimport { BundleFanOutDialog } from \"./BundleFanOutDialog\";\n\ntype AutoApplyPointsSectionProps = AutoApplyPointsSlotContext & {\n // `severity` is \"warning\" when the write landed but the refreshed payload\n // did not come back, matching how the shipping section reports a partial\n // outcome. Callers that ignore it default to a success toast.\n onSuccess?: (message: string, severity?: \"success\" | \"warning\") => void;\n // Optional: the bundle-conflict branch below has already fully translated\n // the failure into customer-facing copy, so it calls onError with nothing\n // else to append.\n onError?: (message: string, error?: unknown) => void;\n};\n\n/**\n * Lets a customer turn automatic points redemption on or off for one\n * subscription. The switch reads the stored choice from the payload and writes\n * through the subscription update the portal already owns, so an explicit\n * \"off\" is a real write rather than a locally remembered preference.\n */\nexport function PortalSubscriptionAutoApplyPointsSection({\n autoApplyPoints,\n pointsEnabled,\n subscriptionToken,\n disabled,\n renewalBundle,\n onSuccess,\n onError,\n}: AutoApplyPointsSectionProps): JSX.Element | null {\n const { t } = useSubscriptionsTranslation();\n const labelId = useId();\n const queryClient = useQueryClient();\n // Tolerates a host that mounts this screen without a StoreApiProvider, and\n // shares its cache entry with the profile screen's own store query.\n const { data: store } = useOptionalStore();\n const pointsLabel = store?.reward_points_label_plural || \"points\";\n\n // The detail screen can move to a sibling subscription while a write is\n // still open. Compare the settling write's token against the one on screen\n // now so a toast never lands on the wrong subscription.\n const latestSubscriptionTokenRef = useRef(subscriptionToken);\n latestSubscriptionTokenRef.current = subscriptionToken;\n\n // Set once the customer picks a value on a multi-member bundle, while the\n // fan-out dialog waits for \"Apply to all\" / \"Just this one\" / cancel.\n const [pendingValue, setPendingValue] = useState<boolean | null>(null);\n // Guards a confirm() call that lands after the dialog has already been\n // settled: two rapid clicks on the same button, or one on each button, can\n // both fire before React re-renders and removes them, since pendingValue\n // alone can't distinguish \"first click\" from \"second click racing it\" -\n // both read the same value from the same render. Reset whenever a fresh\n // dialog opens, in requestChange below.\n const confirmedRef = useRef(false);\n\n // Resets the dialog if the detail screen moves to a different subscription\n // while it is open. The section does not unmount across that move (see the\n // comment above), so without this a stale pendingValue would keep A's\n // dialog open, listing A's members, over B's underlying bundle - and a\n // confirm there would compare B's resolved set against A's renderedTokens.\n // Adjusted during rendering rather than in an effect: this reacts to a\n // prop change with a state reset, not a side effect, matching the house\n // rule against useEffect for syncing state.\n const [dialogSubscriptionToken, setDialogSubscriptionToken] =\n useState(subscriptionToken);\n if (subscriptionToken !== dialogSubscriptionToken) {\n setDialogSubscriptionToken(subscriptionToken);\n setPendingValue(null);\n confirmedRef.current = false;\n }\n\n const updateSubscription = useUpdateSubscriptionInfo({\n // Async on purpose: the hook returns this promise from its own onSuccess,\n // so awaiting the refreshed payload keeps the mutation pending until the\n // server's answer is in hand. Reporting success before then would put a\n // toast next to a control still showing the pre-write value.\n onSuccess: async ({\n subscriptionToken: updatedSubscriptionToken,\n body,\n }) => {\n if (\n !isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n updatedSubscriptionToken,\n )\n ) {\n return;\n }\n\n // Refetching an already-fetching query joins the in-flight request\n // rather than issuing a second one, so this does not double the round\n // trip the hook's own invalidation already started.\n await queryClient.refetchQueries({\n queryKey: subscriptionsKeys.detail(updatedSubscriptionToken),\n exact: true,\n });\n\n if (\n !isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n updatedSubscriptionToken,\n )\n ) {\n return;\n }\n\n const refreshed =\n queryClient.getQueryData<subscriptions.SubscriptionDetail>(\n subscriptionsKeys.detail(updatedSubscriptionToken),\n );\n\n // The write landed and the read did not, so the switch is about to show\n // a value the server no longer holds. Say that plainly instead of\n // claiming success next to a control that contradicts it. Same case and\n // same wording as the checkout's own auto-apply control.\n if (\n refreshed?.subscription.auto_apply_points !== body.auto_apply_points\n ) {\n onSuccess?.(\n t(\"auto_apply_points_saved_but_not_refreshed\", {\n label: pointsLabel,\n }),\n \"warning\",\n );\n return;\n }\n\n onSuccess?.(t(\"auto_apply_points_updated\", { label: pointsLabel }));\n },\n onError: (error, { subscriptionToken: failedSubscriptionToken }) => {\n if (\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n failedSubscriptionToken,\n )\n ) {\n onError?.(\n t(\"failed_to_update_auto_apply_points\", { label: pointsLabel }),\n error,\n );\n }\n },\n });\n\n // Bundle-aware write for a renewal group of more than one member. The hook\n // already scopes its own consumer callbacks to the current subscription\n // token, so no isCurrentSubscriptionPaymentAttempt guard is needed here.\n const fanOut = useUpdateAutoApplyPoints({\n currentSubscriptionToken: subscriptionToken,\n onSuccess: ({ result, refreshed, variables }) => {\n if (\n autoApplyPointsMembershipDrifted({\n confirmedScope: variables.scope,\n // The set this write was fired with, not the ref. The ref tracks\n // whichever dialog opened most recently, so a write on A that\n // settles after the customer opened B's dialog and navigated back\n // to A would be judged against B's members and warn about a drift\n // that never happened. The variables travel with their own\n // mutation, so they cannot be overwritten by a later one.\n renderedTokens: variables.bundleTokens ?? [],\n targetToken: variables.subscriptionToken,\n resolvedTokens: result.resolvedSubscriptionTokens,\n })\n ) {\n onSuccess?.(\n t(\"auto_apply_points_bundle_membership_changed\"),\n \"warning\",\n );\n return;\n }\n if (!refreshed) {\n onSuccess?.(\n t(\"auto_apply_points_saved_but_not_refreshed\", {\n label: pointsLabel,\n }),\n \"warning\",\n );\n return;\n }\n onSuccess?.(t(\"auto_apply_points_updated\", { label: pointsLabel }));\n },\n onError: (error) => {\n if (error instanceof BundleMembershipConflictError) {\n // No second argument: this message is already fully translated\n // customer-facing copy, not raw error detail for the screen to\n // append.\n onError?.(t(\"auto_apply_points_bundle_conflict_retry\"));\n return;\n }\n onError?.(\n t(\"failed_to_update_auto_apply_points\", { label: pointsLabel }),\n error,\n );\n },\n });\n\n // The update hook invalidates the detail query without awaiting the refetch,\n // so the mutation stops being pending while the switch still holds the value\n // it had before the write. Counting that refetch as in-flight keeps the\n // switch disabled until the server's answer arrives, rather than briefly\n // offering a control that reports the old setting under a success toast.\n // `exact` matters: query-key filters match by prefix by default, and\n // subscriptionsKeys.failedCycleWaiver(token) is a child of detail(token).\n // Without it, a past-due subscription fetching its waiver preview would\n // disable this switch for a query that has nothing to do with points.\n const detailRefetching =\n useIsFetching({\n queryKey: subscriptionsKeys.detail(subscriptionToken),\n exact: true,\n }) > 0;\n\n const control = autoApplyPointsControlState({\n autoApplyPoints,\n pointsEnabled,\n subscriptionDisabled: disabled,\n // Scoped to the write's own subscription, matching\n // PortalSubscriptionPaymentMethodSection. The detail screen preserves this\n // mutation across a move to a sibling subscription, so an unscoped\n // isPending would disable B's switch for a request belonging to A. The\n // fanOut branch also checks bundleTokens, not just the target: a\n // bundle-scoped write in flight for A also writes B, so without this a\n // customer who navigates to B mid-write would find its switch enabled\n // and could fire a second, overlapping write that races the first --\n // whichever commits last silently wins, possibly undoing the customer's\n // more recent choice.\n writeInFlight:\n (updateSubscription.isPending &&\n updateSubscription.variables?.subscriptionToken ===\n subscriptionToken) ||\n (fanOut.isPending &&\n (fanOut.variables?.subscriptionToken === subscriptionToken ||\n fanOut.variables?.bundleTokens?.includes(subscriptionToken))) ||\n detailRefetching,\n });\n\n // Routes a toggle to the write it needs: the shared subscription update on\n // a server that sent no renewal bundle, a direct bundle-aware write when\n // the bundle has nothing else in it, or the fan-out dialog when the write\n // would reach subscriptions the customer isn't looking at.\n function requestChange(next: boolean): void {\n const route = autoApplyPointsWriteRoute({ renewalBundle });\n\n if (route === \"fallback\") {\n updateSubscription.mutate({\n subscriptionToken,\n body: { auto_apply_points: next },\n });\n return;\n }\n if (route === \"write\") {\n fanOut.mutate({\n subscriptionToken,\n autoApplyPoints: next,\n scope: \"subscription\",\n bundleTokens: [subscriptionToken],\n });\n return;\n }\n confirmedRef.current = false;\n setPendingValue(next);\n }\n\n // Settles the dialog: writes at the confirmed scope. confirmedRef is the\n // real guard against a second call racing the first - the dialog only\n // mounts while pendingValue is set, so a `pendingValue === null` check\n // alone can't tell \"first click\" from \"second click before the re-render\n // that removes the buttons\"; both would read the same pendingValue.\n function confirm(scope: AutoApplyPointsScope): void {\n if (confirmedRef.current) return;\n confirmedRef.current = true;\n\n const next = pendingValue;\n setPendingValue(null);\n if (next === null) return;\n\n // Read off the same `renewalBundle` the dialog rendered in this very\n // render, so the drift baseline is whatever the customer had on screen\n // when they clicked. A snapshot frozen at dialog-open would disagree\n // with the list they were looking at as soon as the detail refetched\n // mid-dialog, and drift would then fire against a set nobody saw.\n fanOut.mutate({\n subscriptionToken,\n autoApplyPoints: next,\n scope,\n bundleTokens:\n renewalBundle?.members.map((member) => member.subscription_token) ?? [],\n });\n }\n\n if (!control.visible) return null;\n\n return (\n <div className=\"border-border mb-6 border-b pb-4\">\n <div className=\"flex items-start justify-between gap-4\">\n <div>\n <p id={labelId} className=\"text-foreground text-sm font-medium\">\n {t(\"auto_apply_points_each_renewal\", { label: pointsLabel })}\n </p>\n <p className=\"text-muted-foreground mt-1 text-sm\">\n {t(\"auto_apply_points_partial_balance\")}\n </p>\n </div>\n <Switch\n aria-labelledby={labelId}\n checked={control.checked}\n disabled={control.disabled}\n onCheckedChange={requestChange}\n />\n </div>\n {pendingValue !== null && renewalBundle ? (\n <BundleFanOutDialog\n bundle={renewalBundle}\n pointsLabel={pointsLabel}\n nextValue={pendingValue}\n onConfirmAll={() => confirm(\"bundle\")}\n onConfirmOne={() => confirm(\"subscription\")}\n onCancel={() => setPendingValue(null)}\n />\n ) : null}\n </div>\n );\n}\n","import { useEffect, useMemo, useState, type JSX } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { Button, DialogFooter } from \"@fluid-app/ui-primitives\";\nimport { ResponsiveDialog } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport type { ReactivateDialogSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport type { PayAddress } from \"@fluid-app/portal-core/pay-types\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { payKeys } from \"../account/query-keys\";\nimport { ProfileTranslationBridge } from \"../providers/ProfileTranslationBridge\";\nimport { SelectableAddressDropdown } from \"./SelectableAddressDropdown\";\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n phone: raw.phone,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\n/**\n * Portal reactivation dialog. Confirms the shipping address before a rep\n * reactivates a cancelled subscription so it can't silently ship to an\n * address the customer has since removed (CURRENT-2204). Passing no\n * address_id keeps the subscription's current address — used only when the\n * customer has no saved addresses to choose from.\n */\nexport function PortalReactivateSubscriptionDialog(\n props: ReactivateDialogSlotContext,\n): JSX.Element {\n return (\n <ProfileTranslationBridge>\n <PortalReactivateSubscriptionDialogInner {...props} />\n </ProfileTranslationBridge>\n );\n}\n\nfunction PortalReactivateSubscriptionDialogInner({\n open,\n onOpenChange,\n onConfirm,\n isLoading,\n isError,\n}: ReactivateDialogSlotContext): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const { isMobile } = useSidebar();\n const payApi = usePayApi();\n\n const { data: addresses = [], isLoading: addressesLoading } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n enabled: open,\n });\n\n const [selectedAddressId, setSelectedAddressId] = useState<number | null>(\n null,\n );\n\n // No pre-selection: reactivation must be an explicit address confirmation\n // (CURRENT-2204), so the rep picks an address before Reactivate enables.\n // Reset each time the dialog opens so a prior pick doesn't leak across opens.\n useEffect(() => {\n if (open) setSelectedAddressId(null);\n }, [open]);\n\n // Ignore a selection that is no longer in the list (e.g. removed by a\n // refetch while the dialog is open) so a stale address_id can't be sent.\n const effectiveAddressId =\n selectedAddressId != null &&\n addresses.some((a) => a.id === selectedAddressId)\n ? selectedAddressId\n : null;\n\n const displayAddress = useMemo(\n () => addresses.find((a) => a.id === effectiveAddressId) ?? null,\n [addresses, effectiveAddressId],\n );\n\n const addressesReady = !addressesLoading;\n const emptyBook = addressesReady && addresses.length === 0;\n const canSubmit = (effectiveAddressId != null || emptyBook) && !isLoading;\n\n const handleOpenChange = (next: boolean) => {\n if (!next) setSelectedAddressId(null);\n onOpenChange(next);\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={t(\"reactivate_subscription\")}\n description={t(\"reactivate_dialog_description\")}\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n >\n <div className=\"space-y-4\">\n {!emptyBook && (\n <div>\n <SelectableAddressDropdown\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={t(\"shipping_address\")}\n displayAddress={displayAddress}\n addressList={addresses}\n selectedAddressId={effectiveAddressId ?? 0}\n onSelectAddress={(addr) => setSelectedAddressId(addr.id)}\n onAddAddressClick={() => {}}\n showAddButton={false}\n isLoading={addressesLoading}\n isPending={isLoading}\n defaultOpen\n />\n {effectiveAddressId == null && (\n <p className=\"text-destructive mt-1 text-xs\">\n {t(\"reactivate_select_address\")}\n </p>\n )}\n </div>\n )}\n </div>\n\n {isError && (\n <p className=\"text-destructive text-left text-sm\">\n {t(\"failed_to_reactivate\")}\n </p>\n )}\n\n <DialogFooter>\n <div className=\"flex w-full flex-row justify-between gap-x-2\">\n <Button\n className=\"bg-muted text-foreground ring-border hover:bg-muted/80 h-10 min-w-[70px] rounded p-3 ring-1\"\n onClick={() => handleOpenChange(false)}\n >\n {t(\"cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"bg-primary text-primary-foreground h-10 min-w-[70px] rounded p-3 hover:opacity-90 disabled:opacity-50\"\n onClick={() => onConfirm({ addressId: effectiveAddressId })}\n disabled={!canSubmit}\n >\n {isLoading ? (\n <div className=\"border-primary-foreground size-5 animate-spin rounded-full border-4 border-t-4 border-t-transparent\" />\n ) : (\n t(\"reactivate\")\n )}\n </Button>\n </div>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import { useCallback, useState } from \"react\";\nimport { SubscriptionDetailScreen as SubscriptionDetailScreenContent } from \"@fluid-app/subscriptions-ui/screens/SubscriptionDetailScreen\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\nimport { PortalSubscriptionPaymentMethodSection } from \"../subscriptions/PortalSubscriptionPaymentMethodSection\";\nimport { PortalSubscriptionShippingAddressSection } from \"../subscriptions/PortalSubscriptionShippingAddressSection\";\nimport { PortalSubscriptionAutoApplyPointsSection } from \"../subscriptions/PortalSubscriptionAutoApplyPointsSection\";\nimport { PortalReactivateSubscriptionDialog } from \"../subscriptions/PortalReactivateSubscriptionDialog\";\n\ninterface SubscriptionDetailScreenProps {\n token: string;\n onToast: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n}\n\nexport function SubscriptionDetailScreen({\n token,\n onToast,\n}: SubscriptionDetailScreenProps): React.JSX.Element {\n const { navigate } = useAppNavigation();\n const { t } = useSubscriptionsTranslation();\n const { isMobile } = useSidebar();\n // Lift the Add Payment Method dialog state so the past-due banner's\n // \"Update your card\" CTA and the in-section payment-method dropdown\n // open the same dialog. Without this, the banner would have to\n // duplicate the \"Add Payment Method\" mounting logic, or scroll\n // (which the subscriptions-ui fallback does for non-portal hosts).\n const [addPaymentDialogOpen, setAddPaymentDialogOpen] = useState(false);\n\n const handleNavigateToList = useCallback(\n () => navigate(\"subscriptions\"),\n [navigate],\n );\n\n const handleNavigateToSubscription = useCallback(\n (nextToken: string) => navigate(`subscriptions/${nextToken}`),\n [navigate],\n );\n\n const handleNotFound = useCallback(() => {\n onToast(t(\"subscription_not_found\"), \"warning\");\n navigate(\"subscriptions\");\n }, [onToast, navigate, t]);\n\n const handleError = useCallback(\n (err: unknown) => {\n const message = err instanceof Error ? err.message : t(\"error_occurred\");\n onToast(t(\"failed_to_load_subscription\", { message }), \"error\");\n },\n [onToast, t],\n );\n\n const handleSuccess = useCallback(\n (\n message: string,\n severity: \"success\" | \"error\" | \"warning\" = \"success\",\n ) => {\n onToast(message, severity);\n },\n [onToast],\n );\n\n const handleMutationError = useCallback(\n (message: string, err: unknown) => {\n const detail = err instanceof Error ? err.message : t(\"error_occurred\");\n onToast(`${message}: ${detail}`, \"error\");\n },\n [onToast, t],\n );\n\n return (\n <SubscriptionDetailScreenContent\n token={token}\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n onNavigateToList={handleNavigateToList}\n onNavigateToSubscription={handleNavigateToSubscription}\n onNotFound={handleNotFound}\n onError={handleError}\n onSuccess={handleSuccess}\n onMutationError={handleMutationError}\n onUpdatePaymentClick={() => setAddPaymentDialogOpen(true)}\n renderPaymentMethod={(ctx) => (\n <PortalSubscriptionPaymentMethodSection\n {...ctx}\n onSuccess={(msg, severity) => onToast(msg, severity ?? \"success\")}\n onError={(msg, err) => {\n const detail =\n err instanceof Error ? err.message : t(\"error_occurred\");\n onToast(`${msg}: ${detail}`, \"error\");\n }}\n addDialogOpen={addPaymentDialogOpen}\n onAddDialogOpenChange={setAddPaymentDialogOpen}\n />\n )}\n renderShippingAddress={(ctx) => (\n <PortalSubscriptionShippingAddressSection\n {...ctx}\n onSuccess={(msg, severity) => onToast(msg, severity ?? \"success\")}\n onError={(msg, err) => {\n const detail =\n err instanceof Error ? err.message : t(\"error_occurred\");\n onToast(`${msg}: ${detail}`, \"error\");\n }}\n />\n )}\n renderAutoApplyPoints={(ctx) => (\n <PortalSubscriptionAutoApplyPointsSection\n {...ctx}\n onSuccess={(msg, severity) => onToast(msg, severity ?? \"success\")}\n onError={(msg, err) => {\n // Unlike the payment-method and shipping-address handlers above,\n // err can be genuinely absent here: the bundle-conflict path\n // calls onError with only the (already fully translated)\n // message, so appending a fallback string on top of it would\n // read as untranslated debug detail glued onto real copy.\n const detail = err instanceof Error ? err.message : undefined;\n onToast(detail ? `${msg}: ${detail}` : msg, \"error\");\n }}\n />\n )}\n renderReactivateDialog={(ctx) => (\n <PortalReactivateSubscriptionDialog {...ctx} />\n )}\n />\n );\n}\n","import type { ComponentProps } from \"react\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n PaddingOptions,\n} from \"../types\";\nimport type { WidgetPropertySchema } from \"../registries/property-schema-types\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\nimport { useAccount } from \"../hooks/use-account\";\nimport { PortalSubscriptionsApiProvider } from \"../subscriptions/PortalSubscriptionsApiProvider\";\nimport { PortalBundlesApiProvider } from \"../subscriptions/PortalBundlesApiProvider\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { SubscriptionsTranslationBridge } from \"../providers/SubscriptionsTranslationBridge\";\nimport { SubscriptionsListScreen } from \"./SubscriptionsListScreen\";\nimport { SubscriptionDetailScreen } from \"./SubscriptionDetailScreen\";\n\nfunction AccountErrorFallback(): React.JSX.Element {\n const { t } = useSubscriptionsTranslation();\n return (\n <div className=\"text-muted-foreground px-4 py-8 text-center text-sm\">\n {t(\"account_load_error\")}\n </div>\n );\n}\n\ntype SubscriptionsScreenProps = ComponentProps<\"div\"> & {\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n onToast?: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n};\n\nfunction defaultToast(message: string, type: \"success\" | \"error\" | \"warning\") {\n fluidToast({ title: message, type });\n}\n\nexport function SubscriptionsScreen({\n onToast,\n /* eslint-disable @typescript-eslint/no-unused-vars -- destructured to exclude from divProps spread */\n background,\n textColor,\n accentColor,\n padding,\n borderRadius,\n /* eslint-enable @typescript-eslint/no-unused-vars */\n ...divProps\n}: SubscriptionsScreenProps): React.JSX.Element {\n const { currentSlug } = useAppNavigation();\n const effectiveToast = onToast ?? defaultToast;\n\n // Parse slug: \"subscriptions\" → list, \"subscriptions/{token}\" → detail\n const detailToken = currentSlug.split(\"/\")[1];\n const isDetailView = detailToken !== undefined;\n\n const { data: account } = useAccount();\n const customerId = account?.id;\n const isLoadingCustomer = account === undefined;\n const isCustomerError = false;\n\n return (\n <div {...divProps}>\n <SubscriptionsTranslationBridge>\n <PortalSubscriptionsApiProvider>\n <PortalBundlesApiProvider>\n {isDetailView ? (\n <SubscriptionDetailScreen\n token={detailToken}\n onToast={effectiveToast}\n />\n ) : isCustomerError && !isLoadingCustomer ? (\n <AccountErrorFallback />\n ) : (\n <SubscriptionsListScreen\n customerId={customerId}\n isLoadingCustomer={isLoadingCustomer}\n onToast={effectiveToast}\n />\n )}\n </PortalBundlesApiProvider>\n </PortalSubscriptionsApiProvider>\n </SubscriptionsTranslationBridge>\n </div>\n );\n}\n\nexport const subscriptionsScreenPropertySchema: WidgetPropertySchema = {\n widgetType: \"SubscriptionsScreen\",\n displayName: \"Subscriptions Screen\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [],\n} as const satisfies WidgetPropertySchema;\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SubscriptionsScreen-BgMCPJx0.mjs","names":["getInternalDefaultOptions","getDefaultOptions","defaultLocale","portalTenant.subscriptionsList","portalTenant.subscriptionsShow","portalTenant.subscriptionsPause","portalTenant.subscriptionsResume","portalTenant.subscriptionsSkip","portalTenant.subscriptionsCancel","portalTenant.subscriptionsReactivate","portalTenant.subscriptionsRetry","portalTenant.subscriptionsFailedCycleWaiverPreview","portalTenant.subscriptionsFailedCycleWaiverCreate","portalTenant.subscriptionsUpdate","portalTenant.subscriptionsUpdate","portalTenant.subscriptionBundlesList","portalTenant.subscriptionBundlesCreate","UNIT_KEYS","formatLongDate","UNIT_KEYS","formatLongDate","formatLongDate","mapToFluidPayAddress","cn","Calendar","cn","Calendar","cn","SubscriptionDetailScreen","cn","mapToFluidPayAddress","cn","mapToFluidPayAddress","SubscriptionDetailScreenContent"],"sources":["../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/getDefaultOptions.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/getISODay.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/transpose.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/Setter.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/EraParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/constants.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/utils.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/YearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/LocalWeekYearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISOWeekYearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ExtendedYearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/QuarterParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/StandAloneQuarterParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/MonthParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/StandAloneMonthParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/setWeek.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/LocalWeekParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/setISOWeek.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISOWeekParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/DateParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/DayOfYearParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/setDay.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/DayParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/LocalDayParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/StandAloneLocalDayParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/setISODay.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISODayParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/AMPMParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/AMPMMidnightParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/DayPeriodParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/Hour1to12Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/Hour0to23Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/Hour0To11Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/Hour1To24Parser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/MinuteParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/SecondParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/FractionOfSecondParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISOTimezoneWithZParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/ISOTimezoneParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/TimestampSecondsParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers/TimestampMillisecondsParser.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse/_lib/parsers.js","../../../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/parse.js","../../../subscriptions/core/src/subscriptions-api-context.ts","../../../subscriptions/core/src/provider.tsx","../../../subscriptions/core/src/query-keys.ts","../../../subscriptions/core/src/bundles-api-context.ts","../../../subscriptions/core/src/bundles-provider.tsx","../../../subscriptions/core/src/hooks/use-subscriptions.ts","../../../subscriptions/core/src/hooks/use-infinite-subscriptions.ts","../../../subscriptions/core/src/hooks/use-subscription.ts","../../../subscriptions/core/src/hooks/use-pause-subscription.ts","../../../subscriptions/core/src/hooks/use-resume-subscription.ts","../../../subscriptions/core/src/hooks/use-skip-subscription.ts","../../../subscriptions/core/src/hooks/use-cancel-subscription.ts","../../../subscriptions/core/src/hooks/use-reactivate-subscription.ts","../../../subscriptions/core/src/hooks/use-retry-subscription.ts","../../../subscriptions/core/src/utils/retry-outcome.ts","../../../subscriptions/core/src/hooks/use-retry-status-polling.ts","../../../subscriptions/core/src/hooks/use-failed-cycle-waiver-preview.ts","../../../subscriptions/core/src/hooks/use-waive-failed-cycle.ts","../../../subscriptions/core/src/hooks/use-update-subscription-info.ts","../../../subscriptions/core/src/hooks/use-bundles.ts","../../../subscriptions/core/src/hooks/use-create-bundle.ts","../../../subscriptions/core/src/utils/subscription-helpers.ts","../../../subscriptions/core/src/utils/subscription-actions.ts","../../../subscriptions/core/src/utils/failed-cycle-waiver.ts","../../../subscriptions/core/src/auto-apply-points-api.ts","../../../subscriptions/core/src/auto-apply-points-api-context.ts","../src/adapters/subscriptions-api-adapter.ts","../src/adapters/auto-apply-points-api-adapter.ts","../src/subscriptions/PortalSubscriptionsApiProvider.tsx","../src/adapters/bundles-api-adapter.ts","../src/subscriptions/PortalBundlesApiProvider.tsx","../../../subscriptions/core/src/translation-api-context.ts","../src/providers/SubscriptionsTranslationBridge.tsx","../src/subscriptions/subscription-card-add-success.ts","../src/screens/subscriptions/portal-subscriptions-list-helpers.ts","../src/screens/subscriptions/PortalSubscriptionsList.tsx","../src/screens/subscriptions/bundle-drawer/payment-utils.ts","../src/screens/subscriptions/bundle-drawer/bill-date-bounds.ts","../src/screens/subscriptions/bundle-drawer/use-bundle-form.ts","../src/screens/subscriptions/bundle-drawer/DrawerStepTabs.tsx","../src/screens/subscriptions/bundle-drawer/DrawerStepSelect.tsx","../src/screens/subscriptions/bundle-drawer/DrawerStepDate.tsx","../src/screens/subscriptions/bundle-drawer/DrawerStepAddress.tsx","../src/screens/subscriptions/bundle-drawer/DrawerStepPayment.tsx","../src/screens/subscriptions/bundle-drawer/BundleSubscriptionsDrawer.tsx","../src/screens/SubscriptionsListScreen.tsx","../../../subscriptions/ui/src/components/cancel-subscription-dialog.tsx","../../../subscriptions/ui/src/lib/format.ts","../../../subscriptions/ui/src/components/pause-subscription-dialog.tsx","../../../subscriptions/ui/src/lib/parse-iso-date.ts","../../../subscriptions/ui/src/components/resume-subscription-dialog.tsx","../../../subscriptions/ui/src/components/edit-bill-date-dialog.tsx","../../../subscriptions/ui/src/lib/cn.ts","../../../subscriptions/ui/src/components/status-pill.tsx","../../../subscriptions/ui/src/components/past-due-banner.tsx","../../../subscriptions/ui/src/components/failed-cycle-waiver-dialog.tsx","../../../subscriptions/ui/src/components/bundled-with-card.tsx","../../../subscriptions/ui/src/components/subscription-detail.tsx","../../../subscriptions/ui/src/screens/SubscriptionDetailScreen.tsx","../src/subscriptions/SelectablePaymentMethodDropdown.tsx","../src/subscriptions/subscription-payment-recovery.ts","../src/subscriptions/PortalSubscriptionPaymentMethodSection.tsx","../src/subscriptions/SelectableAddressDropdown.tsx","../src/subscriptions/PortalSubscriptionShippingAddressSection.tsx","../../../subscriptions/core/src/hooks/use-update-auto-apply-points.ts","../src/subscriptions/subscription-auto-apply-points.ts","../src/subscriptions/BundleFanOutDialog.tsx","../src/subscriptions/PortalSubscriptionAutoApplyPointsSection.tsx","../src/subscriptions/PortalReactivateSubscriptionDialog.tsx","../src/screens/SubscriptionDetailScreen.tsx","../src/screens/SubscriptionsScreen.tsx"],"sourcesContent":["import { getDefaultOptions as getInternalDefaultOptions } from \"./_lib/defaultOptions.js\";\n\n/**\n * @name getDefaultOptions\n * @category Common Helpers\n * @summary Get default options.\n * @pure false\n *\n * @description\n * Returns an object that contains defaults for\n * `options.locale`, `options.weekStartsOn` and `options.firstWeekContainsDate`\n * arguments for all functions.\n *\n * You can change these with [setDefaultOptions](https://date-fns.org/docs/setDefaultOptions).\n *\n * @returns The default options\n *\n * @example\n * const result = getDefaultOptions()\n * //=> {}\n *\n * @example\n * setDefaultOptions({ weekStarsOn: 1, firstWeekContainsDate: 4 })\n * const result = getDefaultOptions()\n * //=> { weekStarsOn: 1, firstWeekContainsDate: 4 }\n */\nexport function getDefaultOptions() {\n return Object.assign({}, getInternalDefaultOptions());\n}\n\n// Fallback for modularized imports:\nexport default getDefaultOptions;\n","import { toDate } from \"./toDate.js\";\n\n/**\n * The {@link getISODay} function options.\n */\n\n/**\n * @name getISODay\n * @category Weekday Helpers\n * @summary Get the day of the ISO week of the given date.\n *\n * @description\n * Get the day of the ISO week of the given date,\n * which is 7 for Sunday, 1 for Monday etc.\n *\n * ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date\n *\n * @param date - The given date\n * @param options - An object with options\n *\n * @returns The day of ISO week\n *\n * @example\n * // Which day of the ISO week is 26 February 2012?\n * const result = getISODay(new Date(2012, 1, 26))\n * //=> 7\n */\nexport function getISODay(date, options) {\n const day = toDate(date, options?.in).getDay();\n return day === 0 ? 7 : day;\n}\n\n// Fallback for modularized imports:\nexport default getISODay;\n","import { constructFrom } from \"./constructFrom.js\";\n\n/**\n * @name transpose\n * @category Generic Helpers\n * @summary Transpose the date to the given constructor.\n *\n * @description\n * The function transposes the date to the given constructor. It helps you\n * to transpose the date in the system time zone to say `UTCDate` or any other\n * date extension.\n *\n * @typeParam InputDate - The input `Date` type derived from the passed argument.\n * @typeParam ResultDate - The result `Date` type derived from the passed constructor.\n *\n * @param date - The date to use values from\n * @param constructor - The date constructor to use\n *\n * @returns Date transposed to the given constructor\n *\n * @example\n * // Create July 10, 2022 00:00 in locale time zone\n * const date = new Date(2022, 6, 10)\n * //=> 'Sun Jul 10 2022 00:00:00 GMT+0800 (Singapore Standard Time)'\n *\n * @example\n * // Transpose the date to July 10, 2022 00:00 in UTC\n * transpose(date, UTCDate)\n * //=> 'Sun Jul 10 2022 00:00:00 GMT+0000 (Coordinated Universal Time)'\n */\nexport function transpose(date, constructor) {\n const date_ = isConstructor(constructor)\n ? new constructor(0)\n : constructFrom(constructor, 0);\n date_.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());\n date_.setHours(\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n date.getMilliseconds(),\n );\n return date_;\n}\n\nfunction isConstructor(constructor) {\n return (\n typeof constructor === \"function\" &&\n constructor.prototype?.constructor === constructor\n );\n}\n\n// Fallback for modularized imports:\nexport default transpose;\n","import { constructFrom } from \"../../constructFrom.js\";\nimport { transpose } from \"../../transpose.js\";\n\nconst TIMEZONE_UNIT_PRIORITY = 10;\n\nexport class Setter {\n subPriority = 0;\n\n validate(_utcDate, _options) {\n return true;\n }\n}\n\nexport class ValueSetter extends Setter {\n constructor(\n value,\n\n validateValue,\n\n setValue,\n\n priority,\n subPriority,\n ) {\n super();\n this.value = value;\n this.validateValue = validateValue;\n this.setValue = setValue;\n this.priority = priority;\n if (subPriority) {\n this.subPriority = subPriority;\n }\n }\n\n validate(date, options) {\n return this.validateValue(date, this.value, options);\n }\n\n set(date, flags, options) {\n return this.setValue(date, flags, this.value, options);\n }\n}\n\nexport class DateTimezoneSetter extends Setter {\n priority = TIMEZONE_UNIT_PRIORITY;\n subPriority = -1;\n\n constructor(context, reference) {\n super();\n this.context = context || ((date) => constructFrom(reference, date));\n }\n\n set(date, flags) {\n if (flags.timestampIsSet) return date;\n return constructFrom(date, transpose(date, this.context));\n }\n}\n","import { ValueSetter } from \"./Setter.js\";\n\nexport class Parser {\n run(dateString, token, match, options) {\n const result = this.parse(dateString, token, match, options);\n if (!result) {\n return null;\n }\n\n return {\n setter: new ValueSetter(\n result.value,\n this.validate,\n this.set,\n this.priority,\n this.subPriority,\n ),\n rest: result.rest,\n };\n }\n\n validate(_utcDate, _value, _options) {\n return true;\n }\n}\n","import { Parser } from \"../Parser.js\";\n\nexport class EraParser extends Parser {\n priority = 140;\n\n parse(dateString, token, match) {\n switch (token) {\n // AD, BC\n case \"G\":\n case \"GG\":\n case \"GGG\":\n return (\n match.era(dateString, { width: \"abbreviated\" }) ||\n match.era(dateString, { width: \"narrow\" })\n );\n\n // A, B\n case \"GGGGG\":\n return match.era(dateString, { width: \"narrow\" });\n // Anno Domini, Before Christ\n case \"GGGG\":\n default:\n return (\n match.era(dateString, { width: \"wide\" }) ||\n match.era(dateString, { width: \"abbreviated\" }) ||\n match.era(dateString, { width: \"narrow\" })\n );\n }\n }\n\n set(date, flags, value) {\n flags.era = value;\n date.setFullYear(value, 0, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"R\", \"u\", \"t\", \"T\"];\n}\n","export const numericPatterns = {\n month: /^(1[0-2]|0?\\d)/, // 0 to 12\n date: /^(3[0-1]|[0-2]?\\d)/, // 0 to 31\n dayOfYear: /^(36[0-6]|3[0-5]\\d|[0-2]?\\d?\\d)/, // 0 to 366\n week: /^(5[0-3]|[0-4]?\\d)/, // 0 to 53\n hour23h: /^(2[0-3]|[0-1]?\\d)/, // 0 to 23\n hour24h: /^(2[0-4]|[0-1]?\\d)/, // 0 to 24\n hour11h: /^(1[0-1]|0?\\d)/, // 0 to 11\n hour12h: /^(1[0-2]|0?\\d)/, // 0 to 12\n minute: /^[0-5]?\\d/, // 0 to 59\n second: /^[0-5]?\\d/, // 0 to 59\n\n singleDigit: /^\\d/, // 0 to 9\n twoDigits: /^\\d{1,2}/, // 0 to 99\n threeDigits: /^\\d{1,3}/, // 0 to 999\n fourDigits: /^\\d{1,4}/, // 0 to 9999\n\n anyDigitsSigned: /^-?\\d+/,\n singleDigitSigned: /^-?\\d/, // 0 to 9, -0 to -9\n twoDigitsSigned: /^-?\\d{1,2}/, // 0 to 99, -0 to -99\n threeDigitsSigned: /^-?\\d{1,3}/, // 0 to 999, -0 to -999\n fourDigitsSigned: /^-?\\d{1,4}/, // 0 to 9999, -0 to -9999\n};\n\nexport const timezonePatterns = {\n basicOptionalMinutes: /^([+-])(\\d{2})(\\d{2})?|Z/,\n basic: /^([+-])(\\d{2})(\\d{2})|Z/,\n basicOptionalSeconds: /^([+-])(\\d{2})(\\d{2})((\\d{2}))?|Z/,\n extended: /^([+-])(\\d{2}):(\\d{2})|Z/,\n extendedOptionalSeconds: /^([+-])(\\d{2}):(\\d{2})(:(\\d{2}))?|Z/,\n};\n","import {\n millisecondsInHour,\n millisecondsInMinute,\n millisecondsInSecond,\n} from \"../../constants.js\";\n\nimport { numericPatterns } from \"./constants.js\";\n\nexport function mapValue(parseFnResult, mapFn) {\n if (!parseFnResult) {\n return parseFnResult;\n }\n\n return {\n value: mapFn(parseFnResult.value),\n rest: parseFnResult.rest,\n };\n}\n\nexport function parseNumericPattern(pattern, dateString) {\n const matchResult = dateString.match(pattern);\n\n if (!matchResult) {\n return null;\n }\n\n return {\n value: parseInt(matchResult[0], 10),\n rest: dateString.slice(matchResult[0].length),\n };\n}\n\nexport function parseTimezonePattern(pattern, dateString) {\n const matchResult = dateString.match(pattern);\n\n if (!matchResult) {\n return null;\n }\n\n // Input is 'Z'\n if (matchResult[0] === \"Z\") {\n return {\n value: 0,\n rest: dateString.slice(1),\n };\n }\n\n const sign = matchResult[1] === \"+\" ? 1 : -1;\n const hours = matchResult[2] ? parseInt(matchResult[2], 10) : 0;\n const minutes = matchResult[3] ? parseInt(matchResult[3], 10) : 0;\n const seconds = matchResult[5] ? parseInt(matchResult[5], 10) : 0;\n\n return {\n value:\n sign *\n (hours * millisecondsInHour +\n minutes * millisecondsInMinute +\n seconds * millisecondsInSecond),\n rest: dateString.slice(matchResult[0].length),\n };\n}\n\nexport function parseAnyDigitsSigned(dateString) {\n return parseNumericPattern(numericPatterns.anyDigitsSigned, dateString);\n}\n\nexport function parseNDigits(n, dateString) {\n switch (n) {\n case 1:\n return parseNumericPattern(numericPatterns.singleDigit, dateString);\n case 2:\n return parseNumericPattern(numericPatterns.twoDigits, dateString);\n case 3:\n return parseNumericPattern(numericPatterns.threeDigits, dateString);\n case 4:\n return parseNumericPattern(numericPatterns.fourDigits, dateString);\n default:\n return parseNumericPattern(new RegExp(\"^\\\\d{1,\" + n + \"}\"), dateString);\n }\n}\n\nexport function parseNDigitsSigned(n, dateString) {\n switch (n) {\n case 1:\n return parseNumericPattern(numericPatterns.singleDigitSigned, dateString);\n case 2:\n return parseNumericPattern(numericPatterns.twoDigitsSigned, dateString);\n case 3:\n return parseNumericPattern(numericPatterns.threeDigitsSigned, dateString);\n case 4:\n return parseNumericPattern(numericPatterns.fourDigitsSigned, dateString);\n default:\n return parseNumericPattern(new RegExp(\"^-?\\\\d{1,\" + n + \"}\"), dateString);\n }\n}\n\nexport function dayPeriodEnumToHours(dayPeriod) {\n switch (dayPeriod) {\n case \"morning\":\n return 4;\n case \"evening\":\n return 17;\n case \"pm\":\n case \"noon\":\n case \"afternoon\":\n return 12;\n case \"am\":\n case \"midnight\":\n case \"night\":\n default:\n return 0;\n }\n}\n\nexport function normalizeTwoDigitYear(twoDigitYear, currentYear) {\n const isCommonEra = currentYear > 0;\n // Absolute number of the current year:\n // 1 -> 1 AC\n // 0 -> 1 BC\n // -1 -> 2 BC\n const absCurrentYear = isCommonEra ? currentYear : 1 - currentYear;\n\n let result;\n if (absCurrentYear <= 50) {\n result = twoDigitYear || 100;\n } else {\n const rangeEnd = absCurrentYear + 50;\n const rangeEndCentury = Math.trunc(rangeEnd / 100) * 100;\n const isPreviousCentury = twoDigitYear >= rangeEnd % 100;\n result = twoDigitYear + rangeEndCentury - (isPreviousCentury ? 100 : 0);\n }\n\n return isCommonEra ? result : 1 - result;\n}\n\nexport function isLeapYearIndex(year) {\n return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0);\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { mapValue, normalizeTwoDigitYear, parseNDigits } from \"../utils.js\";\n\n// From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns\n// | Year | y | yy | yyy | yyyy | yyyyy |\n// |----------|-------|----|-------|-------|-------|\n// | AD 1 | 1 | 01 | 001 | 0001 | 00001 |\n// | AD 12 | 12 | 12 | 012 | 0012 | 00012 |\n// | AD 123 | 123 | 23 | 123 | 0123 | 00123 |\n// | AD 1234 | 1234 | 34 | 1234 | 1234 | 01234 |\n// | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |\nexport class YearParser extends Parser {\n priority = 130;\n incompatibleTokens = [\"Y\", \"R\", \"u\", \"w\", \"I\", \"i\", \"e\", \"c\", \"t\", \"T\"];\n\n parse(dateString, token, match) {\n const valueCallback = (year) => ({\n year,\n isTwoDigitYear: token === \"yy\",\n });\n\n switch (token) {\n case \"y\":\n return mapValue(parseNDigits(4, dateString), valueCallback);\n case \"yo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"year\",\n }),\n valueCallback,\n );\n default:\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n }\n }\n\n validate(_date, value) {\n return value.isTwoDigitYear || value.year > 0;\n }\n\n set(date, flags, value) {\n const currentYear = date.getFullYear();\n\n if (value.isTwoDigitYear) {\n const normalizedTwoDigitYear = normalizeTwoDigitYear(\n value.year,\n currentYear,\n );\n date.setFullYear(normalizedTwoDigitYear, 0, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n const year =\n !(\"era\" in flags) || flags.era === 1 ? value.year : 1 - value.year;\n date.setFullYear(year, 0, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n}\n","import { getWeekYear } from \"../../../getWeekYear.js\";\n\nimport { startOfWeek } from \"../../../startOfWeek.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, normalizeTwoDigitYear, parseNDigits } from \"../utils.js\";\n\n// Local week-numbering year\nexport class LocalWeekYearParser extends Parser {\n priority = 130;\n\n parse(dateString, token, match) {\n const valueCallback = (year) => ({\n year,\n isTwoDigitYear: token === \"YY\",\n });\n\n switch (token) {\n case \"Y\":\n return mapValue(parseNDigits(4, dateString), valueCallback);\n case \"Yo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"year\",\n }),\n valueCallback,\n );\n default:\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n }\n }\n\n validate(_date, value) {\n return value.isTwoDigitYear || value.year > 0;\n }\n\n set(date, flags, value, options) {\n const currentYear = getWeekYear(date, options);\n\n if (value.isTwoDigitYear) {\n const normalizedTwoDigitYear = normalizeTwoDigitYear(\n value.year,\n currentYear,\n );\n date.setFullYear(\n normalizedTwoDigitYear,\n 0,\n options.firstWeekContainsDate,\n );\n date.setHours(0, 0, 0, 0);\n return startOfWeek(date, options);\n }\n\n const year =\n !(\"era\" in flags) || flags.era === 1 ? value.year : 1 - value.year;\n date.setFullYear(year, 0, options.firstWeekContainsDate);\n date.setHours(0, 0, 0, 0);\n return startOfWeek(date, options);\n }\n\n incompatibleTokens = [\n \"y\",\n \"R\",\n \"u\",\n \"Q\",\n \"q\",\n \"M\",\n \"L\",\n \"I\",\n \"d\",\n \"D\",\n \"i\",\n \"t\",\n \"T\",\n ];\n}\n","import { startOfISOWeek } from \"../../../startOfISOWeek.js\";\nimport { constructFrom } from \"../../../constructFrom.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigitsSigned } from \"../utils.js\";\n\n// ISO week-numbering year\nexport class ISOWeekYearParser extends Parser {\n priority = 130;\n\n parse(dateString, token) {\n if (token === \"R\") {\n return parseNDigitsSigned(4, dateString);\n }\n\n return parseNDigitsSigned(token.length, dateString);\n }\n\n set(date, _flags, value) {\n const firstWeekOfYear = constructFrom(date, 0);\n firstWeekOfYear.setFullYear(value, 0, 4);\n firstWeekOfYear.setHours(0, 0, 0, 0);\n return startOfISOWeek(firstWeekOfYear);\n }\n\n incompatibleTokens = [\n \"G\",\n \"y\",\n \"Y\",\n \"u\",\n \"Q\",\n \"q\",\n \"M\",\n \"L\",\n \"w\",\n \"d\",\n \"D\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { parseNDigitsSigned } from \"../utils.js\";\n\nexport class ExtendedYearParser extends Parser {\n priority = 130;\n\n parse(dateString, token) {\n if (token === \"u\") {\n return parseNDigitsSigned(4, dateString);\n }\n\n return parseNDigitsSigned(token.length, dateString);\n }\n\n set(date, _flags, value) {\n date.setFullYear(value, 0, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"G\", \"y\", \"Y\", \"R\", \"w\", \"I\", \"i\", \"e\", \"c\", \"t\", \"T\"];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { parseNDigits } from \"../utils.js\";\n\nexport class QuarterParser extends Parser {\n priority = 120;\n\n parse(dateString, token, match) {\n switch (token) {\n // 1, 2, 3, 4\n case \"Q\":\n case \"QQ\": // 01, 02, 03, 04\n return parseNDigits(token.length, dateString);\n // 1st, 2nd, 3rd, 4th\n case \"Qo\":\n return match.ordinalNumber(dateString, { unit: \"quarter\" });\n // Q1, Q2, Q3, Q4\n case \"QQQ\":\n return (\n match.quarter(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.quarter(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n\n // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n case \"QQQQQ\":\n return match.quarter(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n // 1st quarter, 2nd quarter, ...\n case \"QQQQ\":\n default:\n return (\n match.quarter(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.quarter(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.quarter(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 4;\n }\n\n set(date, _flags, value) {\n date.setMonth((value - 1) * 3, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"M\",\n \"L\",\n \"w\",\n \"I\",\n \"d\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { parseNDigits } from \"../utils.js\";\n\nexport class StandAloneQuarterParser extends Parser {\n priority = 120;\n\n parse(dateString, token, match) {\n switch (token) {\n // 1, 2, 3, 4\n case \"q\":\n case \"qq\": // 01, 02, 03, 04\n return parseNDigits(token.length, dateString);\n // 1st, 2nd, 3rd, 4th\n case \"qo\":\n return match.ordinalNumber(dateString, { unit: \"quarter\" });\n // Q1, Q2, Q3, Q4\n case \"qqq\":\n return (\n match.quarter(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.quarter(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n })\n );\n\n // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n case \"qqqqq\":\n return match.quarter(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n });\n // 1st quarter, 2nd quarter, ...\n case \"qqqq\":\n default:\n return (\n match.quarter(dateString, {\n width: \"wide\",\n context: \"standalone\",\n }) ||\n match.quarter(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.quarter(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 4;\n }\n\n set(date, _flags, value) {\n date.setMonth((value - 1) * 3, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"Q\",\n \"M\",\n \"L\",\n \"w\",\n \"I\",\n \"d\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class MonthParser extends Parser {\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"Q\",\n \"L\",\n \"w\",\n \"I\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n\n priority = 110;\n\n parse(dateString, token, match) {\n const valueCallback = (value) => value - 1;\n\n switch (token) {\n // 1, 2, ..., 12\n case \"M\":\n return mapValue(\n parseNumericPattern(numericPatterns.month, dateString),\n valueCallback,\n );\n // 01, 02, ..., 12\n case \"MM\":\n return mapValue(parseNDigits(2, dateString), valueCallback);\n // 1st, 2nd, ..., 12th\n case \"Mo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"month\",\n }),\n valueCallback,\n );\n // Jan, Feb, ..., Dec\n case \"MMM\":\n return (\n match.month(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.month(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // J, F, ..., D\n case \"MMMMM\":\n return match.month(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n // January, February, ..., December\n case \"MMMM\":\n default:\n return (\n match.month(dateString, { width: \"wide\", context: \"formatting\" }) ||\n match.month(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.month(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 11;\n }\n\n set(date, _flags, value) {\n date.setMonth(value, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class StandAloneMonthParser extends Parser {\n priority = 110;\n\n parse(dateString, token, match) {\n const valueCallback = (value) => value - 1;\n\n switch (token) {\n // 1, 2, ..., 12\n case \"L\":\n return mapValue(\n parseNumericPattern(numericPatterns.month, dateString),\n valueCallback,\n );\n // 01, 02, ..., 12\n case \"LL\":\n return mapValue(parseNDigits(2, dateString), valueCallback);\n // 1st, 2nd, ..., 12th\n case \"Lo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"month\",\n }),\n valueCallback,\n );\n // Jan, Feb, ..., Dec\n case \"LLL\":\n return (\n match.month(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.month(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n\n // J, F, ..., D\n case \"LLLLL\":\n return match.month(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n });\n // January, February, ..., December\n case \"LLLL\":\n default:\n return (\n match.month(dateString, { width: \"wide\", context: \"standalone\" }) ||\n match.month(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.month(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 11;\n }\n\n set(date, _flags, value) {\n date.setMonth(value, 1);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"Q\",\n \"M\",\n \"w\",\n \"I\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { getWeek } from \"./getWeek.js\";\nimport { toDate } from \"./toDate.js\";\n\n/**\n * The {@link setWeek} function options.\n */\n\n/**\n * @name setWeek\n * @category Week Helpers\n * @summary Set the local week to the given date.\n *\n * @description\n * Set the local week to the given date, saving the weekday number.\n * The exact calculation depends on the values of\n * `options.weekStartsOn` (which is the index of the first day of the week)\n * and `options.firstWeekContainsDate` (which is the day of January, which is always in\n * the first week of the week-numbering year)\n *\n * Week numbering: https://en.wikipedia.org/wiki/Week#The_ISO_week_date_system\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The date to be changed\n * @param week - The week of the new date\n * @param options - An object with options\n *\n * @returns The new date with the local week set\n *\n * @example\n * // Set the 1st week to 2 January 2005 with default options:\n * const result = setWeek(new Date(2005, 0, 2), 1)\n * //=> Sun Dec 26 2004 00:00:00\n *\n * @example\n * // Set the 1st week to 2 January 2005,\n * // if Monday is the first day of the week,\n * // and the first week of the year always contains 4 January:\n * const result = setWeek(new Date(2005, 0, 2), 1, {\n * weekStartsOn: 1,\n * firstWeekContainsDate: 4\n * })\n * //=> Sun Jan 4 2004 00:00:00\n */\nexport function setWeek(date, week, options) {\n const date_ = toDate(date, options?.in);\n const diff = getWeek(date_, options) - week;\n date_.setDate(date_.getDate() - diff * 7);\n return toDate(date_, options?.in);\n}\n\n// Fallback for modularized imports:\nexport default setWeek;\n","import { setWeek } from \"../../../setWeek.js\";\nimport { startOfWeek } from \"../../../startOfWeek.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\n// Local week of year\nexport class LocalWeekParser extends Parser {\n priority = 100;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"w\":\n return parseNumericPattern(numericPatterns.week, dateString);\n case \"wo\":\n return match.ordinalNumber(dateString, { unit: \"week\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 53;\n }\n\n set(date, _flags, value, options) {\n return startOfWeek(setWeek(date, value, options), options);\n }\n\n incompatibleTokens = [\n \"y\",\n \"R\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"I\",\n \"d\",\n \"D\",\n \"i\",\n \"t\",\n \"T\",\n ];\n}\n","import { getISOWeek } from \"./getISOWeek.js\";\nimport { toDate } from \"./toDate.js\";\n\n/**\n * The {@link setISOWeek} function options.\n */\n\n/**\n * @name setISOWeek\n * @category ISO Week Helpers\n * @summary Set the ISO week to the given date.\n *\n * @description\n * Set the ISO week to the given date, saving the weekday number.\n *\n * ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The `Date` type of the context function.\n *\n * @param date - The date to be changed\n * @param week - The ISO week of the new date\n * @param options - An object with options\n *\n * @returns The new date with the ISO week set\n *\n * @example\n * // Set the 53rd ISO week to 7 August 2004:\n * const result = setISOWeek(new Date(2004, 7, 7), 53)\n * //=> Sat Jan 01 2005 00:00:00\n */\nexport function setISOWeek(date, week, options) {\n const _date = toDate(date, options?.in);\n const diff = getISOWeek(_date, options) - week;\n _date.setDate(_date.getDate() - diff * 7);\n return _date;\n}\n\n// Fallback for modularized imports:\nexport default setISOWeek;\n","import { setISOWeek } from \"../../../setISOWeek.js\";\nimport { startOfISOWeek } from \"../../../startOfISOWeek.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\n// ISO week of year\nexport class ISOWeekParser extends Parser {\n priority = 100;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"I\":\n return parseNumericPattern(numericPatterns.week, dateString);\n case \"Io\":\n return match.ordinalNumber(dateString, { unit: \"week\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 53;\n }\n\n set(date, _flags, value) {\n return startOfISOWeek(setISOWeek(date, value));\n }\n\n incompatibleTokens = [\n \"y\",\n \"Y\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"w\",\n \"d\",\n \"D\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport {\n isLeapYearIndex,\n parseNDigits,\n parseNumericPattern,\n} from \"../utils.js\";\n\nconst DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\nconst DAYS_IN_MONTH_LEAP_YEAR = [\n 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,\n];\n\n// Day of the month\nexport class DateParser extends Parser {\n priority = 90;\n subPriority = 1;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"d\":\n return parseNumericPattern(numericPatterns.date, dateString);\n case \"do\":\n return match.ordinalNumber(dateString, { unit: \"date\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(date, value) {\n const year = date.getFullYear();\n const isLeapYear = isLeapYearIndex(year);\n const month = date.getMonth();\n if (isLeapYear) {\n return value >= 1 && value <= DAYS_IN_MONTH_LEAP_YEAR[month];\n } else {\n return value >= 1 && value <= DAYS_IN_MONTH[month];\n }\n }\n\n set(date, _flags, value) {\n date.setDate(value);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"Q\",\n \"w\",\n \"I\",\n \"D\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport {\n isLeapYearIndex,\n parseNDigits,\n parseNumericPattern,\n} from \"../utils.js\";\n\nexport class DayOfYearParser extends Parser {\n priority = 90;\n\n subpriority = 1;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"D\":\n case \"DD\":\n return parseNumericPattern(numericPatterns.dayOfYear, dateString);\n case \"Do\":\n return match.ordinalNumber(dateString, { unit: \"date\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(date, value) {\n const year = date.getFullYear();\n const isLeapYear = isLeapYearIndex(year);\n if (isLeapYear) {\n return value >= 1 && value <= 366;\n } else {\n return value >= 1 && value <= 365;\n }\n }\n\n set(date, _flags, value) {\n date.setMonth(0, value);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"Y\",\n \"R\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"w\",\n \"I\",\n \"d\",\n \"E\",\n \"i\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { getDefaultOptions } from \"./_lib/defaultOptions.js\";\nimport { addDays } from \"./addDays.js\";\nimport { toDate } from \"./toDate.js\";\n\n/**\n * The {@link setDay} function options.\n */\n\n/**\n * @name setDay\n * @category Weekday Helpers\n * @summary Set the day of the week to the given date.\n *\n * @description\n * Set the day of the week to the given date.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The date to be changed\n * @param day - The day of the week of the new date\n * @param options - An object with options.\n *\n * @returns The new date with the day of the week set\n *\n * @example\n * // Set week day to Sunday, with the default weekStartsOn of Sunday:\n * const result = setDay(new Date(2014, 8, 1), 0)\n * //=> Sun Aug 31 2014 00:00:00\n *\n * @example\n * // Set week day to Sunday, with a weekStartsOn of Monday:\n * const result = setDay(new Date(2014, 8, 1), 0, { weekStartsOn: 1 })\n * //=> Sun Sep 07 2014 00:00:00\n */\nexport function setDay(date, day, options) {\n const defaultOptions = getDefaultOptions();\n const weekStartsOn =\n options?.weekStartsOn ??\n options?.locale?.options?.weekStartsOn ??\n defaultOptions.weekStartsOn ??\n defaultOptions.locale?.options?.weekStartsOn ??\n 0;\n\n const date_ = toDate(date, options?.in);\n const currentDay = date_.getDay();\n\n const remainder = day % 7;\n const dayIndex = (remainder + 7) % 7;\n\n const delta = 7 - weekStartsOn;\n const diff =\n day < 0 || day > 6\n ? day - ((currentDay + delta) % 7)\n : ((dayIndex + delta) % 7) - ((currentDay + delta) % 7);\n return addDays(date_, diff, options);\n}\n\n// Fallback for modularized imports:\nexport default setDay;\n","import { setDay } from \"../../../setDay.js\";\nimport { Parser } from \"../Parser.js\";\n\n// Day of week\nexport class DayParser extends Parser {\n priority = 90;\n\n parse(dateString, token, match) {\n switch (token) {\n // Tue\n case \"E\":\n case \"EE\":\n case \"EEE\":\n return (\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // T\n case \"EEEEE\":\n return match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n // Tu\n case \"EEEEEE\":\n return (\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // Tuesday\n case \"EEEE\":\n default:\n return (\n match.day(dateString, { width: \"wide\", context: \"formatting\" }) ||\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 6;\n }\n\n set(date, _flags, value, options) {\n date = setDay(date, value, options);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"D\", \"i\", \"e\", \"c\", \"t\", \"T\"];\n}\n","import { setDay } from \"../../../setDay.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits } from \"../utils.js\";\n\n// Local day of week\nexport class LocalDayParser extends Parser {\n priority = 90;\n parse(dateString, token, match, options) {\n const valueCallback = (value) => {\n // We want here floor instead of trunc, so we get -7 for value 0 instead of 0\n const wholeWeekDays = Math.floor((value - 1) / 7) * 7;\n return ((value + options.weekStartsOn + 6) % 7) + wholeWeekDays;\n };\n\n switch (token) {\n // 3\n case \"e\":\n case \"ee\": // 03\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n // 3rd\n case \"eo\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"day\",\n }),\n valueCallback,\n );\n // Tue\n case \"eee\":\n return (\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // T\n case \"eeeee\":\n return match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n // Tu\n case \"eeeeee\":\n return (\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n\n // Tuesday\n case \"eeee\":\n default:\n return (\n match.day(dateString, { width: \"wide\", context: \"formatting\" }) ||\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"formatting\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"formatting\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 6;\n }\n\n set(date, _flags, value, options) {\n date = setDay(date, value, options);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"y\",\n \"R\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"I\",\n \"d\",\n \"D\",\n \"E\",\n \"i\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { setDay } from \"../../../setDay.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits } from \"../utils.js\";\n\n// Stand-alone local day of week\nexport class StandAloneLocalDayParser extends Parser {\n priority = 90;\n\n parse(dateString, token, match, options) {\n const valueCallback = (value) => {\n // We want here floor instead of trunc, so we get -7 for value 0 instead of 0\n const wholeWeekDays = Math.floor((value - 1) / 7) * 7;\n return ((value + options.weekStartsOn + 6) % 7) + wholeWeekDays;\n };\n\n switch (token) {\n // 3\n case \"c\":\n case \"cc\": // 03\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n // 3rd\n case \"co\":\n return mapValue(\n match.ordinalNumber(dateString, {\n unit: \"day\",\n }),\n valueCallback,\n );\n // Tue\n case \"ccc\":\n return (\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"standalone\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n\n // T\n case \"ccccc\":\n return match.day(dateString, {\n width: \"narrow\",\n context: \"standalone\",\n });\n // Tu\n case \"cccccc\":\n return (\n match.day(dateString, { width: \"short\", context: \"standalone\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n\n // Tuesday\n case \"cccc\":\n default:\n return (\n match.day(dateString, { width: \"wide\", context: \"standalone\" }) ||\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"standalone\",\n }) ||\n match.day(dateString, { width: \"short\", context: \"standalone\" }) ||\n match.day(dateString, { width: \"narrow\", context: \"standalone\" })\n );\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 6;\n }\n\n set(date, _flags, value, options) {\n date = setDay(date, value, options);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"y\",\n \"R\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"I\",\n \"d\",\n \"D\",\n \"E\",\n \"i\",\n \"e\",\n \"t\",\n \"T\",\n ];\n}\n","import { addDays } from \"./addDays.js\";\nimport { getISODay } from \"./getISODay.js\";\nimport { toDate } from \"./toDate.js\";\n\n/**\n * The {@link setISODay} function options.\n */\n\n/**\n * @name setISODay\n * @category Weekday Helpers\n * @summary Set the day of the ISO week to the given date.\n *\n * @description\n * Set the day of the ISO week to the given date.\n * ISO week starts with Monday.\n * 7 is the index of Sunday, 1 is the index of Monday, etc.\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param date - The date to be changed\n * @param day - The day of the ISO week of the new date\n * @param options - An object with options\n *\n * @returns The new date with the day of the ISO week set\n *\n * @example\n * // Set Sunday to 1 September 2014:\n * const result = setISODay(new Date(2014, 8, 1), 7)\n * //=> Sun Sep 07 2014 00:00:00\n */\nexport function setISODay(date, day, options) {\n const date_ = toDate(date, options?.in);\n const currentDay = getISODay(date_, options);\n const diff = day - currentDay;\n return addDays(date_, diff, options);\n}\n\n// Fallback for modularized imports:\nexport default setISODay;\n","import { setISODay } from \"../../../setISODay.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits } from \"../utils.js\";\n\n// ISO day of week\nexport class ISODayParser extends Parser {\n priority = 90;\n\n parse(dateString, token, match) {\n const valueCallback = (value) => {\n if (value === 0) {\n return 7;\n }\n return value;\n };\n\n switch (token) {\n // 2\n case \"i\":\n case \"ii\": // 02\n return parseNDigits(token.length, dateString);\n // 2nd\n case \"io\":\n return match.ordinalNumber(dateString, { unit: \"day\" });\n // Tue\n case \"iii\":\n return mapValue(\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"short\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n }),\n valueCallback,\n );\n // T\n case \"iiiii\":\n return mapValue(\n match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n }),\n valueCallback,\n );\n // Tu\n case \"iiiiii\":\n return mapValue(\n match.day(dateString, {\n width: \"short\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n }),\n valueCallback,\n );\n // Tuesday\n case \"iiii\":\n default:\n return mapValue(\n match.day(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"short\",\n context: \"formatting\",\n }) ||\n match.day(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n }),\n valueCallback,\n );\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 7;\n }\n\n set(date, _flags, value) {\n date = setISODay(date, value);\n date.setHours(0, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\n \"y\",\n \"Y\",\n \"u\",\n \"q\",\n \"Q\",\n \"M\",\n \"L\",\n \"w\",\n \"d\",\n \"D\",\n \"E\",\n \"e\",\n \"c\",\n \"t\",\n \"T\",\n ];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { dayPeriodEnumToHours } from \"../utils.js\";\n\nexport class AMPMParser extends Parser {\n priority = 80;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"a\":\n case \"aa\":\n case \"aaa\":\n return (\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n\n case \"aaaaa\":\n return match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n case \"aaaa\":\n default:\n return (\n match.dayPeriod(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n }\n }\n\n set(date, _flags, value) {\n date.setHours(dayPeriodEnumToHours(value), 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"b\", \"B\", \"H\", \"k\", \"t\", \"T\"];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { dayPeriodEnumToHours } from \"../utils.js\";\n\nexport class AMPMMidnightParser extends Parser {\n priority = 80;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"b\":\n case \"bb\":\n case \"bbb\":\n return (\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n\n case \"bbbbb\":\n return match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n case \"bbbb\":\n default:\n return (\n match.dayPeriod(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n }\n }\n\n set(date, _flags, value) {\n date.setHours(dayPeriodEnumToHours(value), 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"a\", \"B\", \"H\", \"k\", \"t\", \"T\"];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { dayPeriodEnumToHours } from \"../utils.js\";\n\n// in the morning, in the afternoon, in the evening, at night\nexport class DayPeriodParser extends Parser {\n priority = 80;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"B\":\n case \"BB\":\n case \"BBB\":\n return (\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n\n case \"BBBBB\":\n return match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n });\n case \"BBBB\":\n default:\n return (\n match.dayPeriod(dateString, {\n width: \"wide\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"abbreviated\",\n context: \"formatting\",\n }) ||\n match.dayPeriod(dateString, {\n width: \"narrow\",\n context: \"formatting\",\n })\n );\n }\n }\n\n set(date, _flags, value) {\n date.setHours(dayPeriodEnumToHours(value), 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"a\", \"b\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class Hour1to12Parser extends Parser {\n priority = 70;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"h\":\n return parseNumericPattern(numericPatterns.hour12h, dateString);\n case \"ho\":\n return match.ordinalNumber(dateString, { unit: \"hour\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 12;\n }\n\n set(date, _flags, value) {\n const isPM = date.getHours() >= 12;\n if (isPM && value < 12) {\n date.setHours(value + 12, 0, 0, 0);\n } else if (!isPM && value === 12) {\n date.setHours(0, 0, 0, 0);\n } else {\n date.setHours(value, 0, 0, 0);\n }\n return date;\n }\n\n incompatibleTokens = [\"H\", \"K\", \"k\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class Hour0to23Parser extends Parser {\n priority = 70;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"H\":\n return parseNumericPattern(numericPatterns.hour23h, dateString);\n case \"Ho\":\n return match.ordinalNumber(dateString, { unit: \"hour\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 23;\n }\n\n set(date, _flags, value) {\n date.setHours(value, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"a\", \"b\", \"h\", \"K\", \"k\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class Hour0To11Parser extends Parser {\n priority = 70;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"K\":\n return parseNumericPattern(numericPatterns.hour11h, dateString);\n case \"Ko\":\n return match.ordinalNumber(dateString, { unit: \"hour\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 11;\n }\n\n set(date, _flags, value) {\n const isPM = date.getHours() >= 12;\n if (isPM && value < 12) {\n date.setHours(value + 12, 0, 0, 0);\n } else {\n date.setHours(value, 0, 0, 0);\n }\n return date;\n }\n\n incompatibleTokens = [\"h\", \"H\", \"k\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class Hour1To24Parser extends Parser {\n priority = 70;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"k\":\n return parseNumericPattern(numericPatterns.hour24h, dateString);\n case \"ko\":\n return match.ordinalNumber(dateString, { unit: \"hour\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 1 && value <= 24;\n }\n\n set(date, _flags, value) {\n const hours = value <= 24 ? value % 24 : value;\n date.setHours(hours, 0, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"a\", \"b\", \"h\", \"H\", \"K\", \"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class MinuteParser extends Parser {\n priority = 60;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"m\":\n return parseNumericPattern(numericPatterns.minute, dateString);\n case \"mo\":\n return match.ordinalNumber(dateString, { unit: \"minute\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 59;\n }\n\n set(date, _flags, value) {\n date.setMinutes(value, 0, 0);\n return date;\n }\n\n incompatibleTokens = [\"t\", \"T\"];\n}\n","import { numericPatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseNDigits, parseNumericPattern } from \"../utils.js\";\n\nexport class SecondParser extends Parser {\n priority = 50;\n\n parse(dateString, token, match) {\n switch (token) {\n case \"s\":\n return parseNumericPattern(numericPatterns.second, dateString);\n case \"so\":\n return match.ordinalNumber(dateString, { unit: \"second\" });\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n\n validate(_date, value) {\n return value >= 0 && value <= 59;\n }\n\n set(date, _flags, value) {\n date.setSeconds(value, 0);\n return date;\n }\n\n incompatibleTokens = [\"t\", \"T\"];\n}\n","import { Parser } from \"../Parser.js\";\n\nimport { mapValue, parseNDigits } from \"../utils.js\";\n\nexport class FractionOfSecondParser extends Parser {\n priority = 30;\n\n parse(dateString, token) {\n const valueCallback = (value) =>\n Math.trunc(value * Math.pow(10, -token.length + 3));\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n }\n\n set(date, _flags, value) {\n date.setMilliseconds(value);\n return date;\n }\n\n incompatibleTokens = [\"t\", \"T\"];\n}\n","import { constructFrom } from \"../../../constructFrom.js\";\nimport { getTimezoneOffsetInMilliseconds } from \"../../../_lib/getTimezoneOffsetInMilliseconds.js\";\nimport { timezonePatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseTimezonePattern } from \"../utils.js\";\n\n// Timezone (ISO-8601. +00:00 is `'Z'`)\nexport class ISOTimezoneWithZParser extends Parser {\n priority = 10;\n\n parse(dateString, token) {\n switch (token) {\n case \"X\":\n return parseTimezonePattern(\n timezonePatterns.basicOptionalMinutes,\n dateString,\n );\n case \"XX\":\n return parseTimezonePattern(timezonePatterns.basic, dateString);\n case \"XXXX\":\n return parseTimezonePattern(\n timezonePatterns.basicOptionalSeconds,\n dateString,\n );\n case \"XXXXX\":\n return parseTimezonePattern(\n timezonePatterns.extendedOptionalSeconds,\n dateString,\n );\n case \"XXX\":\n default:\n return parseTimezonePattern(timezonePatterns.extended, dateString);\n }\n }\n\n set(date, flags, value) {\n if (flags.timestampIsSet) return date;\n return constructFrom(\n date,\n date.getTime() - getTimezoneOffsetInMilliseconds(date) - value,\n );\n }\n\n incompatibleTokens = [\"t\", \"T\", \"x\"];\n}\n","import { constructFrom } from \"../../../constructFrom.js\";\nimport { getTimezoneOffsetInMilliseconds } from \"../../../_lib/getTimezoneOffsetInMilliseconds.js\";\nimport { timezonePatterns } from \"../constants.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseTimezonePattern } from \"../utils.js\";\n\n// Timezone (ISO-8601)\nexport class ISOTimezoneParser extends Parser {\n priority = 10;\n\n parse(dateString, token) {\n switch (token) {\n case \"x\":\n return parseTimezonePattern(\n timezonePatterns.basicOptionalMinutes,\n dateString,\n );\n case \"xx\":\n return parseTimezonePattern(timezonePatterns.basic, dateString);\n case \"xxxx\":\n return parseTimezonePattern(\n timezonePatterns.basicOptionalSeconds,\n dateString,\n );\n case \"xxxxx\":\n return parseTimezonePattern(\n timezonePatterns.extendedOptionalSeconds,\n dateString,\n );\n case \"xxx\":\n default:\n return parseTimezonePattern(timezonePatterns.extended, dateString);\n }\n }\n\n set(date, flags, value) {\n if (flags.timestampIsSet) return date;\n return constructFrom(\n date,\n date.getTime() - getTimezoneOffsetInMilliseconds(date) - value,\n );\n }\n\n incompatibleTokens = [\"t\", \"T\", \"X\"];\n}\n","import { constructFrom } from \"../../../constructFrom.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseAnyDigitsSigned } from \"../utils.js\";\n\nexport class TimestampSecondsParser extends Parser {\n priority = 40;\n\n parse(dateString) {\n return parseAnyDigitsSigned(dateString);\n }\n\n set(date, _flags, value) {\n return [constructFrom(date, value * 1000), { timestampIsSet: true }];\n }\n\n incompatibleTokens = \"*\";\n}\n","import { constructFrom } from \"../../../constructFrom.js\";\nimport { Parser } from \"../Parser.js\";\n\nimport { parseAnyDigitsSigned } from \"../utils.js\";\n\nexport class TimestampMillisecondsParser extends Parser {\n priority = 20;\n\n parse(dateString) {\n return parseAnyDigitsSigned(dateString);\n }\n\n set(date, _flags, value) {\n return [constructFrom(date, value), { timestampIsSet: true }];\n }\n\n incompatibleTokens = \"*\";\n}\n","import { EraParser } from \"./parsers/EraParser.js\";\nimport { YearParser } from \"./parsers/YearParser.js\";\nimport { LocalWeekYearParser } from \"./parsers/LocalWeekYearParser.js\";\nimport { ISOWeekYearParser } from \"./parsers/ISOWeekYearParser.js\";\nimport { ExtendedYearParser } from \"./parsers/ExtendedYearParser.js\";\nimport { QuarterParser } from \"./parsers/QuarterParser.js\";\nimport { StandAloneQuarterParser } from \"./parsers/StandAloneQuarterParser.js\";\nimport { MonthParser } from \"./parsers/MonthParser.js\";\nimport { StandAloneMonthParser } from \"./parsers/StandAloneMonthParser.js\";\nimport { LocalWeekParser } from \"./parsers/LocalWeekParser.js\";\nimport { ISOWeekParser } from \"./parsers/ISOWeekParser.js\";\nimport { DateParser } from \"./parsers/DateParser.js\";\nimport { DayOfYearParser } from \"./parsers/DayOfYearParser.js\";\nimport { DayParser } from \"./parsers/DayParser.js\";\nimport { LocalDayParser } from \"./parsers/LocalDayParser.js\";\nimport { StandAloneLocalDayParser } from \"./parsers/StandAloneLocalDayParser.js\";\nimport { ISODayParser } from \"./parsers/ISODayParser.js\";\nimport { AMPMParser } from \"./parsers/AMPMParser.js\";\nimport { AMPMMidnightParser } from \"./parsers/AMPMMidnightParser.js\";\nimport { DayPeriodParser } from \"./parsers/DayPeriodParser.js\";\nimport { Hour1to12Parser } from \"./parsers/Hour1to12Parser.js\";\nimport { Hour0to23Parser } from \"./parsers/Hour0to23Parser.js\";\nimport { Hour0To11Parser } from \"./parsers/Hour0To11Parser.js\";\nimport { Hour1To24Parser } from \"./parsers/Hour1To24Parser.js\";\nimport { MinuteParser } from \"./parsers/MinuteParser.js\";\nimport { SecondParser } from \"./parsers/SecondParser.js\";\nimport { FractionOfSecondParser } from \"./parsers/FractionOfSecondParser.js\";\nimport { ISOTimezoneWithZParser } from \"./parsers/ISOTimezoneWithZParser.js\";\nimport { ISOTimezoneParser } from \"./parsers/ISOTimezoneParser.js\";\nimport { TimestampSecondsParser } from \"./parsers/TimestampSecondsParser.js\";\nimport { TimestampMillisecondsParser } from \"./parsers/TimestampMillisecondsParser.js\";\n\n/*\n * | | Unit | | Unit |\n * |-----|--------------------------------|-----|--------------------------------|\n * | a | AM, PM | A* | Milliseconds in day |\n * | b | AM, PM, noon, midnight | B | Flexible day period |\n * | c | Stand-alone local day of week | C* | Localized hour w/ day period |\n * | d | Day of month | D | Day of year |\n * | e | Local day of week | E | Day of week |\n * | f | | F* | Day of week in month |\n * | g* | Modified Julian day | G | Era |\n * | h | Hour [1-12] | H | Hour [0-23] |\n * | i! | ISO day of week | I! | ISO week of year |\n * | j* | Localized hour w/ day period | J* | Localized hour w/o day period |\n * | k | Hour [1-24] | K | Hour [0-11] |\n * | l* | (deprecated) | L | Stand-alone month |\n * | m | Minute | M | Month |\n * | n | | N | |\n * | o! | Ordinal number modifier | O* | Timezone (GMT) |\n * | p | | P | |\n * | q | Stand-alone quarter | Q | Quarter |\n * | r* | Related Gregorian year | R! | ISO week-numbering year |\n * | s | Second | S | Fraction of second |\n * | t! | Seconds timestamp | T! | Milliseconds timestamp |\n * | u | Extended year | U* | Cyclic year |\n * | v* | Timezone (generic non-locat.) | V* | Timezone (location) |\n * | w | Local week of year | W* | Week of month |\n * | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |\n * | y | Year (abs) | Y | Local week-numbering year |\n * | z* | Timezone (specific non-locat.) | Z* | Timezone (aliases) |\n *\n * Letters marked by * are not implemented but reserved by Unicode standard.\n *\n * Letters marked by ! are non-standard, but implemented by date-fns:\n * - `o` modifies the previous token to turn it into an ordinal (see `parse` docs)\n * - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,\n * i.e. 7 for Sunday, 1 for Monday, etc.\n * - `I` is ISO week of year, as opposed to `w` which is local week of year.\n * - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.\n * `R` is supposed to be used in conjunction with `I` and `i`\n * for universal ISO week-numbering date, whereas\n * `Y` is supposed to be used in conjunction with `w` and `e`\n * for week-numbering date specific to the locale.\n */\nexport const parsers = {\n G: new EraParser(),\n y: new YearParser(),\n Y: new LocalWeekYearParser(),\n R: new ISOWeekYearParser(),\n u: new ExtendedYearParser(),\n Q: new QuarterParser(),\n q: new StandAloneQuarterParser(),\n M: new MonthParser(),\n L: new StandAloneMonthParser(),\n w: new LocalWeekParser(),\n I: new ISOWeekParser(),\n d: new DateParser(),\n D: new DayOfYearParser(),\n E: new DayParser(),\n e: new LocalDayParser(),\n c: new StandAloneLocalDayParser(),\n i: new ISODayParser(),\n a: new AMPMParser(),\n b: new AMPMMidnightParser(),\n B: new DayPeriodParser(),\n h: new Hour1to12Parser(),\n H: new Hour0to23Parser(),\n K: new Hour0To11Parser(),\n k: new Hour1To24Parser(),\n m: new MinuteParser(),\n s: new SecondParser(),\n S: new FractionOfSecondParser(),\n X: new ISOTimezoneWithZParser(),\n x: new ISOTimezoneParser(),\n t: new TimestampSecondsParser(),\n T: new TimestampMillisecondsParser(),\n};\n","import { defaultLocale } from \"./_lib/defaultLocale.js\";\nimport { longFormatters } from \"./_lib/format/longFormatters.js\";\nimport {\n isProtectedDayOfYearToken,\n isProtectedWeekYearToken,\n warnOrThrowProtectedError,\n} from \"./_lib/protectedTokens.js\";\nimport { constructFrom } from \"./constructFrom.js\";\nimport { getDefaultOptions } from \"./getDefaultOptions.js\";\nimport { toDate } from \"./toDate.js\";\n\nimport { DateTimezoneSetter } from \"./parse/_lib/Setter.js\";\nimport { parsers } from \"./parse/_lib/parsers.js\";\n\n// Rexports of internal for libraries to use.\n// See: https://github.com/date-fns/date-fns/issues/3638#issuecomment-1877082874\nexport { longFormatters, parsers };\n\n/**\n * The {@link parse} function options.\n */\n\n// This RegExp consists of three parts separated by `|`:\n// - [yYQqMLwIdDecihHKkms]o matches any available ordinal number token\n// (one of the certain letters followed by `o`)\n// - (\\w)\\1* matches any sequences of the same letter\n// - '' matches two quote characters in a row\n// - '(''|[^'])+('|$) matches anything surrounded by two quote characters ('),\n// except a single quote symbol, which ends the sequence.\n// Two quote characters do not end the sequence.\n// If there is no matching single quote\n// then the sequence will continue until the end of the string.\n// - . matches any single character unmatched by previous parts of the RegExps\nconst formattingTokensRegExp =\n /[yYQqMLwIdDecihHKkms]o|(\\w)\\1*|''|'(''|[^'])+('|$)|./g;\n\n// This RegExp catches symbols escaped by quotes, and also\n// sequences of symbols P, p, and the combinations like `PPPPPPPppppp`\nconst longFormattingTokensRegExp = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;\n\nconst escapedStringRegExp = /^'([^]*?)'?$/;\nconst doubleQuoteRegExp = /''/g;\n\nconst notWhitespaceRegExp = /\\S/;\nconst unescapedLatinCharacterRegExp = /[a-zA-Z]/;\n\n/**\n * @name parse\n * @category Common Helpers\n * @summary Parse the date.\n *\n * @description\n * Return the date parsed from string using the given format string.\n *\n * > ⚠️ Please note that the `format` tokens differ from Moment.js and other libraries.\n * > See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * The characters in the format string wrapped between two single quotes characters (') are escaped.\n * Two single quotes in a row, whether inside or outside a quoted sequence, represent a 'real' single quote.\n *\n * Format of the format string is based on Unicode Technical Standard #35:\n * https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n * with a few additions (see note 5 below the table).\n *\n * Not all tokens are compatible. Combinations that don't make sense or could lead to bugs are prohibited\n * and will throw `RangeError`. For example usage of 24-hour format token with AM/PM token will throw an exception:\n *\n * ```javascript\n * parse('23 AM', 'HH a', new Date())\n * //=> RangeError: The format string mustn't contain `HH` and `a` at the same time\n * ```\n *\n * See the compatibility table: https://docs.google.com/spreadsheets/d/e/2PACX-1vQOPU3xUhplll6dyoMmVUXHKl_8CRDs6_ueLmex3SoqwhuolkuN3O05l4rqx5h1dKX8eb46Ul-CCSrq/pubhtml?gid=0&single=true\n *\n * Accepted format string patterns:\n * | Unit |Prior| Pattern | Result examples | Notes |\n * |---------------------------------|-----|---------|-----------------------------------|-------|\n * | Era | 140 | G..GGG | AD, BC | |\n * | | | GGGG | Anno Domini, Before Christ | 2 |\n * | | | GGGGG | A, B | |\n * | Calendar year | 130 | y | 44, 1, 1900, 2017, 9999 | 4 |\n * | | | yo | 44th, 1st, 1900th, 9999999th | 4,5 |\n * | | | yy | 44, 01, 00, 17 | 4 |\n * | | | yyy | 044, 001, 123, 999 | 4 |\n * | | | yyyy | 0044, 0001, 1900, 2017 | 4 |\n * | | | yyyyy | ... | 2,4 |\n * | Local week-numbering year | 130 | Y | 44, 1, 1900, 2017, 9000 | 4 |\n * | | | Yo | 44th, 1st, 1900th, 9999999th | 4,5 |\n * | | | YY | 44, 01, 00, 17 | 4,6 |\n * | | | YYY | 044, 001, 123, 999 | 4 |\n * | | | YYYY | 0044, 0001, 1900, 2017 | 4,6 |\n * | | | YYYYY | ... | 2,4 |\n * | ISO week-numbering year | 130 | R | -43, 1, 1900, 2017, 9999, -9999 | 4,5 |\n * | | | RR | -43, 01, 00, 17 | 4,5 |\n * | | | RRR | -043, 001, 123, 999, -999 | 4,5 |\n * | | | RRRR | -0043, 0001, 2017, 9999, -9999 | 4,5 |\n * | | | RRRRR | ... | 2,4,5 |\n * | Extended year | 130 | u | -43, 1, 1900, 2017, 9999, -999 | 4 |\n * | | | uu | -43, 01, 99, -99 | 4 |\n * | | | uuu | -043, 001, 123, 999, -999 | 4 |\n * | | | uuuu | -0043, 0001, 2017, 9999, -9999 | 4 |\n * | | | uuuuu | ... | 2,4 |\n * | Quarter (formatting) | 120 | Q | 1, 2, 3, 4 | |\n * | | | Qo | 1st, 2nd, 3rd, 4th | 5 |\n * | | | QQ | 01, 02, 03, 04 | |\n * | | | QQQ | Q1, Q2, Q3, Q4 | |\n * | | | QQQQ | 1st quarter, 2nd quarter, ... | 2 |\n * | | | QQQQQ | 1, 2, 3, 4 | 4 |\n * | Quarter (stand-alone) | 120 | q | 1, 2, 3, 4 | |\n * | | | qo | 1st, 2nd, 3rd, 4th | 5 |\n * | | | qq | 01, 02, 03, 04 | |\n * | | | qqq | Q1, Q2, Q3, Q4 | |\n * | | | qqqq | 1st quarter, 2nd quarter, ... | 2 |\n * | | | qqqqq | 1, 2, 3, 4 | 3 |\n * | Month (formatting) | 110 | M | 1, 2, ..., 12 | |\n * | | | Mo | 1st, 2nd, ..., 12th | 5 |\n * | | | MM | 01, 02, ..., 12 | |\n * | | | MMM | Jan, Feb, ..., Dec | |\n * | | | MMMM | January, February, ..., December | 2 |\n * | | | MMMMM | J, F, ..., D | |\n * | Month (stand-alone) | 110 | L | 1, 2, ..., 12 | |\n * | | | Lo | 1st, 2nd, ..., 12th | 5 |\n * | | | LL | 01, 02, ..., 12 | |\n * | | | LLL | Jan, Feb, ..., Dec | |\n * | | | LLLL | January, February, ..., December | 2 |\n * | | | LLLLL | J, F, ..., D | |\n * | Local week of year | 100 | w | 1, 2, ..., 53 | |\n * | | | wo | 1st, 2nd, ..., 53th | 5 |\n * | | | ww | 01, 02, ..., 53 | |\n * | ISO week of year | 100 | I | 1, 2, ..., 53 | 5 |\n * | | | Io | 1st, 2nd, ..., 53th | 5 |\n * | | | II | 01, 02, ..., 53 | 5 |\n * | Day of month | 90 | d | 1, 2, ..., 31 | |\n * | | | do | 1st, 2nd, ..., 31st | 5 |\n * | | | dd | 01, 02, ..., 31 | |\n * | Day of year | 90 | D | 1, 2, ..., 365, 366 | 7 |\n * | | | Do | 1st, 2nd, ..., 365th, 366th | 5 |\n * | | | DD | 01, 02, ..., 365, 366 | 7 |\n * | | | DDD | 001, 002, ..., 365, 366 | |\n * | | | DDDD | ... | 2 |\n * | Day of week (formatting) | 90 | E..EEE | Mon, Tue, Wed, ..., Sun | |\n * | | | EEEE | Monday, Tuesday, ..., Sunday | 2 |\n * | | | EEEEE | M, T, W, T, F, S, S | |\n * | | | EEEEEE | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | ISO day of week (formatting) | 90 | i | 1, 2, 3, ..., 7 | 5 |\n * | | | io | 1st, 2nd, ..., 7th | 5 |\n * | | | ii | 01, 02, ..., 07 | 5 |\n * | | | iii | Mon, Tue, Wed, ..., Sun | 5 |\n * | | | iiii | Monday, Tuesday, ..., Sunday | 2,5 |\n * | | | iiiii | M, T, W, T, F, S, S | 5 |\n * | | | iiiiii | Mo, Tu, We, Th, Fr, Sa, Su | 5 |\n * | Local day of week (formatting) | 90 | e | 2, 3, 4, ..., 1 | |\n * | | | eo | 2nd, 3rd, ..., 1st | 5 |\n * | | | ee | 02, 03, ..., 01 | |\n * | | | eee | Mon, Tue, Wed, ..., Sun | |\n * | | | eeee | Monday, Tuesday, ..., Sunday | 2 |\n * | | | eeeee | M, T, W, T, F, S, S | |\n * | | | eeeeee | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | Local day of week (stand-alone) | 90 | c | 2, 3, 4, ..., 1 | |\n * | | | co | 2nd, 3rd, ..., 1st | 5 |\n * | | | cc | 02, 03, ..., 01 | |\n * | | | ccc | Mon, Tue, Wed, ..., Sun | |\n * | | | cccc | Monday, Tuesday, ..., Sunday | 2 |\n * | | | ccccc | M, T, W, T, F, S, S | |\n * | | | cccccc | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | AM, PM | 80 | a..aaa | AM, PM | |\n * | | | aaaa | a.m., p.m. | 2 |\n * | | | aaaaa | a, p | |\n * | AM, PM, noon, midnight | 80 | b..bbb | AM, PM, noon, midnight | |\n * | | | bbbb | a.m., p.m., noon, midnight | 2 |\n * | | | bbbbb | a, p, n, mi | |\n * | Flexible day period | 80 | B..BBB | at night, in the morning, ... | |\n * | | | BBBB | at night, in the morning, ... | 2 |\n * | | | BBBBB | at night, in the morning, ... | |\n * | Hour [1-12] | 70 | h | 1, 2, ..., 11, 12 | |\n * | | | ho | 1st, 2nd, ..., 11th, 12th | 5 |\n * | | | hh | 01, 02, ..., 11, 12 | |\n * | Hour [0-23] | 70 | H | 0, 1, 2, ..., 23 | |\n * | | | Ho | 0th, 1st, 2nd, ..., 23rd | 5 |\n * | | | HH | 00, 01, 02, ..., 23 | |\n * | Hour [0-11] | 70 | K | 1, 2, ..., 11, 0 | |\n * | | | Ko | 1st, 2nd, ..., 11th, 0th | 5 |\n * | | | KK | 01, 02, ..., 11, 00 | |\n * | Hour [1-24] | 70 | k | 24, 1, 2, ..., 23 | |\n * | | | ko | 24th, 1st, 2nd, ..., 23rd | 5 |\n * | | | kk | 24, 01, 02, ..., 23 | |\n * | Minute | 60 | m | 0, 1, ..., 59 | |\n * | | | mo | 0th, 1st, ..., 59th | 5 |\n * | | | mm | 00, 01, ..., 59 | |\n * | Second | 50 | s | 0, 1, ..., 59 | |\n * | | | so | 0th, 1st, ..., 59th | 5 |\n * | | | ss | 00, 01, ..., 59 | |\n * | Seconds timestamp | 40 | t | 512969520 | |\n * | | | tt | ... | 2 |\n * | Fraction of second | 30 | S | 0, 1, ..., 9 | |\n * | | | SS | 00, 01, ..., 99 | |\n * | | | SSS | 000, 001, ..., 999 | |\n * | | | SSSS | ... | 2 |\n * | Milliseconds timestamp | 20 | T | 512969520900 | |\n * | | | TT | ... | 2 |\n * | Timezone (ISO-8601 w/ Z) | 10 | X | -08, +0530, Z | |\n * | | | XX | -0800, +0530, Z | |\n * | | | XXX | -08:00, +05:30, Z | |\n * | | | XXXX | -0800, +0530, Z, +123456 | 2 |\n * | | | XXXXX | -08:00, +05:30, Z, +12:34:56 | |\n * | Timezone (ISO-8601 w/o Z) | 10 | x | -08, +0530, +00 | |\n * | | | xx | -0800, +0530, +0000 | |\n * | | | xxx | -08:00, +05:30, +00:00 | 2 |\n * | | | xxxx | -0800, +0530, +0000, +123456 | |\n * | | | xxxxx | -08:00, +05:30, +00:00, +12:34:56 | |\n * | Long localized date | NA | P | 05/29/1453 | 5,8 |\n * | | | PP | May 29, 1453 | |\n * | | | PPP | May 29th, 1453 | |\n * | | | PPPP | Sunday, May 29th, 1453 | 2,5,8 |\n * | Long localized time | NA | p | 12:00 AM | 5,8 |\n * | | | pp | 12:00:00 AM | |\n * | Combination of date and time | NA | Pp | 05/29/1453, 12:00 AM | |\n * | | | PPpp | May 29, 1453, 12:00:00 AM | |\n * | | | PPPpp | May 29th, 1453 at ... | |\n * | | | PPPPpp | Sunday, May 29th, 1453 at ... | 2,5,8 |\n * Notes:\n * 1. \"Formatting\" units (e.g. formatting quarter) in the default en-US locale\n * are the same as \"stand-alone\" units, but are different in some languages.\n * \"Formatting\" units are declined according to the rules of the language\n * in the context of a date. \"Stand-alone\" units are always nominative singular.\n * In `format` function, they will produce different result:\n *\n * `format(new Date(2017, 10, 6), 'do LLLL', {locale: cs}) //=> '6. listopad'`\n *\n * `format(new Date(2017, 10, 6), 'do MMMM', {locale: cs}) //=> '6. listopadu'`\n *\n * `parse` will try to match both formatting and stand-alone units interchangeably.\n *\n * 2. Any sequence of the identical letters is a pattern, unless it is escaped by\n * the single quote characters (see below).\n * If the sequence is longer than listed in table:\n * - for numerical units (`yyyyyyyy`) `parse` will try to match a number\n * as wide as the sequence\n * - for text units (`MMMMMMMM`) `parse` will try to match the widest variation of the unit.\n * These variations are marked with \"2\" in the last column of the table.\n *\n * 3. `QQQQQ` and `qqqqq` could be not strictly numerical in some locales.\n * These tokens represent the shortest form of the quarter.\n *\n * 4. The main difference between `y` and `u` patterns are B.C. years:\n *\n * | Year | `y` | `u` |\n * |------|-----|-----|\n * | AC 1 | 1 | 1 |\n * | BC 1 | 1 | 0 |\n * | BC 2 | 2 | -1 |\n *\n * Also `yy` will try to guess the century of two digit year by proximity with `referenceDate`:\n *\n * `parse('50', 'yy', new Date(2018, 0, 1)) //=> Sat Jan 01 2050 00:00:00`\n *\n * `parse('75', 'yy', new Date(2018, 0, 1)) //=> Wed Jan 01 1975 00:00:00`\n *\n * while `uu` will just assign the year as is:\n *\n * `parse('50', 'uu', new Date(2018, 0, 1)) //=> Sat Jan 01 0050 00:00:00`\n *\n * `parse('75', 'uu', new Date(2018, 0, 1)) //=> Tue Jan 01 0075 00:00:00`\n *\n * The same difference is true for local and ISO week-numbering years (`Y` and `R`),\n * except local week-numbering years are dependent on `options.weekStartsOn`\n * and `options.firstWeekContainsDate` (compare [setISOWeekYear](https://date-fns.org/docs/setISOWeekYear)\n * and [setWeekYear](https://date-fns.org/docs/setWeekYear)).\n *\n * 5. These patterns are not in the Unicode Technical Standard #35:\n * - `i`: ISO day of week\n * - `I`: ISO week of year\n * - `R`: ISO week-numbering year\n * - `o`: ordinal number modifier\n * - `P`: long localized date\n * - `p`: long localized time\n *\n * 6. `YY` and `YYYY` tokens represent week-numbering years but they are often confused with years.\n * You should enable `options.useAdditionalWeekYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * 7. `D` and `DD` tokens represent days of the year but they are often confused with days of the month.\n * You should enable `options.useAdditionalDayOfYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * 8. `P+` tokens do not have a defined priority since they are merely aliases to other tokens based\n * on the given locale.\n *\n * using `en-US` locale: `P` => `MM/dd/yyyy`\n * using `en-US` locale: `p` => `hh:mm a`\n * using `pt-BR` locale: `P` => `dd/MM/yyyy`\n * using `pt-BR` locale: `p` => `HH:mm`\n *\n * Values will be assigned to the date in the descending order of its unit's priority.\n * Units of an equal priority overwrite each other in the order of appearance.\n *\n * If no values of higher priority are parsed (e.g. when parsing string 'January 1st' without a year),\n * the values will be taken from 3rd argument `referenceDate` which works as a context of parsing.\n *\n * `referenceDate` must be passed for correct work of the function.\n * If you're not sure which `referenceDate` to supply, create a new instance of Date:\n * `parse('02/11/2014', 'MM/dd/yyyy', new Date())`\n * In this case parsing will be done in the context of the current date.\n * If `referenceDate` is `Invalid Date` or a value not convertible to valid `Date`,\n * then `Invalid Date` will be returned.\n *\n * The result may vary by locale.\n *\n * If `formatString` matches with `dateString` but does not provides tokens, `referenceDate` will be returned.\n *\n * If parsing failed, `Invalid Date` will be returned.\n * Invalid Date is a Date, whose time value is NaN.\n * Time value of Date: http://es5.github.io/#x15.9.1.1\n *\n * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).\n * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.\n *\n * @param dateStr - The string to parse\n * @param formatStr - The string of tokens\n * @param referenceDate - defines values missing from the parsed dateString\n * @param options - An object with options.\n * see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * @returns The parsed date\n *\n * @throws `options.locale` must contain `match` property\n * @throws use `yyyy` instead of `YYYY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws use `yy` instead of `YY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws use `d` instead of `D` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws use `dd` instead of `DD` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws format string contains an unescaped latin alphabet character\n *\n * @example\n * // Parse 11 February 2014 from middle-endian format:\n * var result = parse('02/11/2014', 'MM/dd/yyyy', new Date())\n * //=> Tue Feb 11 2014 00:00:00\n *\n * @example\n * // Parse 28th of February in Esperanto locale in the context of 2010 year:\n * import eo from 'date-fns/locale/eo'\n * var result = parse('28-a de februaro', \"do 'de' MMMM\", new Date(2010, 0, 1), {\n * locale: eo\n * })\n * //=> Sun Feb 28 2010 00:00:00\n */\nexport function parse(dateStr, formatStr, referenceDate, options) {\n const invalidDate = () => constructFrom(options?.in || referenceDate, NaN);\n const defaultOptions = getDefaultOptions();\n const locale = options?.locale ?? defaultOptions.locale ?? defaultLocale;\n\n const firstWeekContainsDate =\n options?.firstWeekContainsDate ??\n options?.locale?.options?.firstWeekContainsDate ??\n defaultOptions.firstWeekContainsDate ??\n defaultOptions.locale?.options?.firstWeekContainsDate ??\n 1;\n\n const weekStartsOn =\n options?.weekStartsOn ??\n options?.locale?.options?.weekStartsOn ??\n defaultOptions.weekStartsOn ??\n defaultOptions.locale?.options?.weekStartsOn ??\n 0;\n\n if (!formatStr)\n return dateStr ? invalidDate() : toDate(referenceDate, options?.in);\n\n const subFnOptions = {\n firstWeekContainsDate,\n weekStartsOn,\n locale,\n };\n\n // If timezone isn't specified, it will try to use the context or\n // the reference date and fallback to the system time zone.\n const setters = [new DateTimezoneSetter(options?.in, referenceDate)];\n\n const tokens = formatStr\n .match(longFormattingTokensRegExp)\n .map((substring) => {\n const firstCharacter = substring[0];\n if (firstCharacter in longFormatters) {\n const longFormatter = longFormatters[firstCharacter];\n return longFormatter(substring, locale.formatLong);\n }\n return substring;\n })\n .join(\"\")\n .match(formattingTokensRegExp);\n\n const usedTokens = [];\n\n for (let token of tokens) {\n if (\n !options?.useAdditionalWeekYearTokens &&\n isProtectedWeekYearToken(token)\n ) {\n warnOrThrowProtectedError(token, formatStr, dateStr);\n }\n if (\n !options?.useAdditionalDayOfYearTokens &&\n isProtectedDayOfYearToken(token)\n ) {\n warnOrThrowProtectedError(token, formatStr, dateStr);\n }\n\n const firstCharacter = token[0];\n const parser = parsers[firstCharacter];\n if (parser) {\n const { incompatibleTokens } = parser;\n if (Array.isArray(incompatibleTokens)) {\n const incompatibleToken = usedTokens.find(\n (usedToken) =>\n incompatibleTokens.includes(usedToken.token) ||\n usedToken.token === firstCharacter,\n );\n if (incompatibleToken) {\n throw new RangeError(\n `The format string mustn't contain \\`${incompatibleToken.fullToken}\\` and \\`${token}\\` at the same time`,\n );\n }\n } else if (parser.incompatibleTokens === \"*\" && usedTokens.length > 0) {\n throw new RangeError(\n `The format string mustn't contain \\`${token}\\` and any other token at the same time`,\n );\n }\n\n usedTokens.push({ token: firstCharacter, fullToken: token });\n\n const parseResult = parser.run(\n dateStr,\n token,\n locale.match,\n subFnOptions,\n );\n\n if (!parseResult) {\n return invalidDate();\n }\n\n setters.push(parseResult.setter);\n\n dateStr = parseResult.rest;\n } else {\n if (firstCharacter.match(unescapedLatinCharacterRegExp)) {\n throw new RangeError(\n \"Format string contains an unescaped latin alphabet character `\" +\n firstCharacter +\n \"`\",\n );\n }\n\n // Replace two single quote characters with one single quote character\n if (token === \"''\") {\n token = \"'\";\n } else if (firstCharacter === \"'\") {\n token = cleanEscapedString(token);\n }\n\n // Cut token from string, or, if string doesn't match the token, return Invalid Date\n if (dateStr.indexOf(token) === 0) {\n dateStr = dateStr.slice(token.length);\n } else {\n return invalidDate();\n }\n }\n }\n\n // Check if the remaining input contains something other than whitespace\n if (dateStr.length > 0 && notWhitespaceRegExp.test(dateStr)) {\n return invalidDate();\n }\n\n const uniquePrioritySetters = setters\n .map((setter) => setter.priority)\n .sort((a, b) => b - a)\n .filter((priority, index, array) => array.indexOf(priority) === index)\n .map((priority) =>\n setters\n .filter((setter) => setter.priority === priority)\n .sort((a, b) => b.subPriority - a.subPriority),\n )\n .map((setterArray) => setterArray[0]);\n\n let date = toDate(referenceDate, options?.in);\n\n if (isNaN(+date)) return invalidDate();\n\n const flags = {};\n for (const setter of uniquePrioritySetters) {\n if (!setter.validate(date, subFnOptions)) {\n return invalidDate();\n }\n\n const result = setter.set(date, flags, subFnOptions);\n // Result is tuple (date, flags)\n if (Array.isArray(result)) {\n date = result[0];\n Object.assign(flags, result[1]);\n // Result is date\n } else {\n date = result;\n }\n }\n\n return date;\n}\n\nfunction cleanEscapedString(input) {\n return input.match(escapedStringRegExp)[1].replace(doubleQuoteRegExp, \"'\");\n}\n\n// Fallback for modularized imports:\nexport default parse;\n","import { createContext, use } from \"react\";\nimport type { SubscriptionsApi } from \"./subscriptions-api\";\n\nconst SubscriptionsApiContext = createContext<SubscriptionsApi | null>(null);\n\nexport const SubscriptionsApiProvider = SubscriptionsApiContext.Provider;\n\nexport function useSubscriptionsApi(): SubscriptionsApi {\n const api = use(SubscriptionsApiContext);\n if (!api) {\n throw new Error(\n \"useSubscriptionsApi must be used within a SubscriptionsCoreProvider\",\n );\n }\n return api;\n}\n","import type { JSX } from \"react\";\nimport type { SubscriptionsApi } from \"./subscriptions-api\";\nimport { SubscriptionsApiProvider } from \"./subscriptions-api-context\";\n\nexport interface SubscriptionsCoreProviderProps {\n api: SubscriptionsApi;\n children: React.ReactNode;\n}\n\nexport function SubscriptionsCoreProvider({\n api,\n children,\n}: SubscriptionsCoreProviderProps): JSX.Element {\n return (\n <SubscriptionsApiProvider value={api}>{children}</SubscriptionsApiProvider>\n );\n}\n","import type { subscriptions } from \"./types\";\n\nexport const subscriptionsKeys = {\n all: [\"subscriptions\"] as const,\n lists: [\"subscriptions\", \"list\"] as const,\n list: (params?: subscriptions.FetchSubscriptionsParams) =>\n [...subscriptionsKeys.lists, params] as const,\n infiniteLists: [\"subscriptions\", \"infinite-list\"] as const,\n infiniteList: (\n params: Omit<subscriptions.FetchSubscriptionsParams, \"cursor\" | \"page\">,\n ) => [...subscriptionsKeys.infiniteLists, params] as const,\n detail: (token: string) =>\n [...subscriptionsKeys.all, \"detail\", token] as const,\n failedCycleWaiver: (token: string) =>\n [...subscriptionsKeys.detail(token), \"failed-cycle-waiver\"] as const,\n} as const;\n\nexport const bundlesKeys = {\n all: [\"subscription_bundles\"] as const,\n list: () => [...bundlesKeys.all, \"list\"] as const,\n} as const;\n","import { createContext, use } from \"react\";\nimport type { BundlesApi } from \"./bundles-api\";\n\nconst BundlesApiContext = createContext<BundlesApi | null>(null);\n\nexport const BundlesApiProvider = BundlesApiContext.Provider;\n\nexport function useBundlesApi(): BundlesApi {\n const api = use(BundlesApiContext);\n if (!api) {\n throw new Error(\"useBundlesApi must be used within a BundlesCoreProvider\");\n }\n return api;\n}\n","import type { JSX } from \"react\";\nimport type { BundlesApi } from \"./bundles-api\";\nimport { BundlesApiProvider } from \"./bundles-api-context\";\n\nexport interface BundlesCoreProviderProps {\n api: BundlesApi;\n children: React.ReactNode;\n}\n\nexport function BundlesCoreProvider({\n api,\n children,\n}: BundlesCoreProviderProps): JSX.Element {\n return <BundlesApiProvider value={api}>{children}</BundlesApiProvider>;\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useSubscriptions(\n params: subscriptions.FetchSubscriptionsParams,\n options?: { enabled?: boolean },\n) {\n const api = useSubscriptionsApi();\n return useQuery({\n queryKey: subscriptionsKeys.list(params),\n queryFn: () => api.fetchCustomerSubscriptions(params),\n enabled: options?.enabled ?? !!params.customerId,\n });\n}\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useInfiniteSubscriptions(\n params: Omit<subscriptions.FetchSubscriptionsParams, \"cursor\" | \"page\">,\n options?: { enabled?: boolean },\n) {\n const api = useSubscriptionsApi();\n return useInfiniteQuery({\n queryKey: subscriptionsKeys.infiniteList(params),\n queryFn: ({ pageParam }) =>\n api.fetchCustomerSubscriptions({\n ...params,\n cursor: pageParam,\n limit: params.limit ?? params.perPage,\n }),\n getNextPageParam: (lastPage) =>\n lastPage.meta?.pagination?.next_cursor ?? undefined,\n initialPageParam: undefined as string | undefined,\n enabled: options?.enabled ?? !!params.customerId,\n });\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useSubscription(\n token: string,\n options?: { enabled?: boolean },\n) {\n const api = useSubscriptionsApi();\n return useQuery({\n queryKey: subscriptionsKeys.detail(token),\n queryFn: () => api.fetchSubscription(token),\n enabled: (options?.enabled ?? true) && !!token,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function usePauseSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: {\n subscriptionToken: string;\n pauseParams: subscriptions.PauseSubscriptionParams;\n }) => api.pauseSubscription(params.subscriptionToken, params.pauseParams),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useResumeSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: {\n subscriptionToken: string;\n resumeParams: subscriptions.ResumeSubscriptionParams;\n }) => api.resumeSubscription(params.subscriptionToken, params.resumeParams),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useSkipSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: {\n subscriptionToken: string;\n skipParams: subscriptions.SkipSubscriptionParams;\n }) => api.skipSubscription(params.subscriptionToken, params.skipParams),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useCancelSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: { subscriptionToken: string; customerId?: number }) =>\n api.cancelSubscription(params.subscriptionToken, params.customerId),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useReactivateSubscription(options?: {\n onSuccess?: () => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: {\n subscriptionToken: string;\n reactivateParams: subscriptions.ReactivateSubscriptionParams;\n }) =>\n api.reactivateSubscription(\n params.subscriptionToken,\n params.reactivateParams,\n ),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.();\n },\n onError: (error: unknown) => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onError?.(error);\n },\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\n// Wraps the explicit retry endpoint. The customer-facing UI calls this\n// after a successful payment-method update so the retry is opt-in\n// (vs. a side-effect of the update). See SubscriptionsApi#retrySubscription.\nexport function useRetrySubscription(options?: {\n onSuccess?: (variables: { subscriptionToken: string }) => void;\n onError?: (error: unknown, variables: { subscriptionToken: string }) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: { subscriptionToken: string }) =>\n api.retrySubscription(params.subscriptionToken),\n onSuccess: (_subscription, variables) => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(variables.subscriptionToken),\n });\n options?.onSuccess?.(variables);\n },\n onError: (error, variables) => options?.onError?.(error, variables),\n });\n}\n","// Decision logic for polling a past_due subscription after a payment retry is\n// queued. The retry charges asynchronously and returns with the sub still\n// past_due (last_failed_at reset), so the outcome is read from later polls:\n//\n// succeeded → status became \"active\" (the charge went through). Success is\n// specifically the past_due → active transition.\n// failed → still past_due AND last_failed_at advanced past the baseline\n// captured when polling started (a fresh decline, not a stale\n// read of the prior failure)\n// ended → some other terminal status (e.g. a concurrent cancel/pause):\n// stop polling, but don't claim the charge succeeded\n// pending → none of the above yet; keep polling\n//\n// Kept pure (no React) so it's unit-testable without a DOM/query harness.\nexport type RetryOutcome = \"pending\" | \"succeeded\" | \"failed\" | \"ended\";\n\nexport function resolveRetryOutcome(params: {\n status: string;\n lastFailedAt: string | null;\n baselineLastFailedAt: string | null;\n}): RetryOutcome {\n if (params.status === \"active\") return \"succeeded\";\n if (params.status !== \"past_due\") return \"ended\";\n if (\n params.lastFailedAt != null &&\n params.lastFailedAt !== params.baselineLastFailedAt\n ) {\n return \"failed\";\n }\n return \"pending\";\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\nimport { resolveRetryOutcome } from \"../utils/retry-outcome\";\n\n// A payment retry on a past_due subscription does not charge synchronously:\n// the retry endpoint resets the dunning state, enqueues an immediate billing\n// attempt, and returns with the subscription still past_due. The charge runs\n// seconds later, so the outcome can only be observed by polling the\n// subscription after the retry is queued.\n//\n// success → status flips to \"active\"\n// failure → status stays \"past_due\" and last_failed_at is set again\n// (the retry reset last_failed_at first, so a value newer than the\n// baseline captured at start() is this attempt's failure)\nconst POLL_INTERVAL_MS = 2_500;\n// The immediate billing attempt runs within seconds; stop polling well after\n// that so a stuck worker (or a backend where only the slow dunning cron runs)\n// doesn't leave the UI processing forever.\nconst POLL_TIMEOUT_MS = 30_000;\n\ntype RetryPollingAttempt = {\n subscriptionToken: string;\n phase: \"pending\" | \"failed\";\n baselineLastFailedAt: string | null;\n};\n\nexport function createRetryPollingAttempt(\n subscriptionToken: string,\n baselineLastFailedAt: string | null,\n): RetryPollingAttempt {\n return {\n subscriptionToken,\n phase: \"pending\",\n baselineLastFailedAt,\n };\n}\n\nexport function retryPollingAttemptForToken(\n attempt: RetryPollingAttempt | null,\n subscriptionToken: string,\n): RetryPollingAttempt | null {\n return attempt?.subscriptionToken === subscriptionToken ? attempt : null;\n}\n\ntype Args = {\n subscriptionToken: string;\n // Host-agnostic outcome callbacks — this package has no toast/UI layer, so\n // the consumer surfaces feedback (toasts, etc.) however it likes.\n onSucceeded?: () => void;\n onFailed?: () => void;\n onTimedOut?: () => void;\n};\n\ntype RetryStatusPolling = {\n // Begin polling for the outcome. Call after the retry has been queued.\n start: () => void;\n // The charge outcome is still being polled.\n isProcessing: boolean;\n // The most recent retry was declined.\n hasFailed: boolean;\n};\n\nexport function useRetryStatusPolling({\n subscriptionToken,\n onSucceeded,\n onFailed,\n onTimedOut,\n}: Args): RetryStatusPolling {\n const api = useSubscriptionsApi();\n const [attempt, setAttempt] = useState<RetryPollingAttempt | null>(null);\n const attemptRef = useRef<RetryPollingAttempt | null>(null);\n const currentTokenRef = useRef(subscriptionToken);\n currentTokenRef.current = subscriptionToken;\n const currentAttempt = retryPollingAttemptForToken(\n attempt,\n subscriptionToken,\n );\n\n useEffect(() => {\n if (\n attemptRef.current !== null &&\n attemptRef.current.subscriptionToken !== subscriptionToken\n ) {\n attemptRef.current = null;\n setAttempt(null);\n }\n }, [subscriptionToken]);\n\n // Latest-ref the outcome callbacks. Consumers pass inline arrows that change\n // identity every render; keeping them out of the effect deps means the\n // polling/timeout effects re-run only on real state changes (phase / polled\n // status), not on unrelated parent re-renders — so the 30s timer isn't\n // silently reset and the outcome can't double-fire.\n const callbacks = useRef({ onSucceeded, onFailed, onTimedOut });\n useEffect(() => {\n callbacks.current = { onSucceeded, onFailed, onTimedOut };\n }, [onSucceeded, onFailed, onTimedOut]);\n\n const { data: polled } = useQuery({\n queryKey: subscriptionsKeys.detail(subscriptionToken),\n queryFn: () => api.fetchSubscription(subscriptionToken),\n enabled: currentAttempt?.phase === \"pending\",\n refetchInterval:\n currentAttempt?.phase === \"pending\" ? POLL_INTERVAL_MS : false,\n refetchIntervalInBackground: true,\n });\n\n const polledStatus = polled?.subscription.status;\n const polledLastFailedAt = polled?.subscription.last_failed_at;\n const latestPolledRef = useRef({\n subscriptionToken,\n lastFailedAt: polledLastFailedAt ?? null,\n });\n latestPolledRef.current = {\n subscriptionToken,\n lastFailedAt: polledLastFailedAt ?? null,\n };\n\n useEffect(() => {\n if (currentAttempt?.phase !== \"pending\" || polledStatus === undefined) {\n return;\n }\n\n const outcome = resolveRetryOutcome({\n status: polledStatus,\n lastFailedAt: polledLastFailedAt ?? null,\n baselineLastFailedAt: currentAttempt.baselineLastFailedAt,\n });\n if (currentTokenRef.current !== currentAttempt.subscriptionToken) return;\n\n if (outcome === \"succeeded\") {\n attemptRef.current = null;\n setAttempt(null);\n callbacks.current.onSucceeded?.();\n } else if (outcome === \"failed\") {\n const failedAttempt: RetryPollingAttempt = {\n ...currentAttempt,\n phase: \"failed\",\n };\n attemptRef.current = failedAttempt;\n setAttempt(failedAttempt);\n callbacks.current.onFailed?.();\n } else if (outcome === \"ended\") {\n // A concurrent action moved the sub to another terminal state — stop\n // polling without reporting a success or failure.\n attemptRef.current = null;\n setAttempt(null);\n }\n }, [currentAttempt, polledStatus, polledLastFailedAt]);\n\n useEffect(() => {\n if (currentAttempt?.phase !== \"pending\") return;\n const attemptToken = currentAttempt.subscriptionToken;\n const timeout = setTimeout(() => {\n const activeAttempt = retryPollingAttemptForToken(\n attemptRef.current,\n currentTokenRef.current,\n );\n if (\n activeAttempt?.subscriptionToken !== attemptToken ||\n activeAttempt.phase !== \"pending\"\n ) {\n return;\n }\n\n attemptRef.current = null;\n setAttempt(null);\n callbacks.current.onTimedOut?.();\n }, POLL_TIMEOUT_MS);\n return () => clearTimeout(timeout);\n }, [currentAttempt]);\n\n return {\n start: () => {\n const currentToken = currentTokenRef.current;\n const latestPolled = latestPolledRef.current;\n const nextAttempt = createRetryPollingAttempt(\n currentToken,\n latestPolled.subscriptionToken === currentToken\n ? latestPolled.lastFailedAt\n : null,\n );\n attemptRef.current = nextAttempt;\n setAttempt(nextAttempt);\n },\n isProcessing: currentAttempt?.phase === \"pending\",\n hasFailed: currentAttempt?.phase === \"failed\",\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nfunction hasNumericStatus(error: unknown): error is { status: number } {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof error.status === \"number\"\n );\n}\n\nexport function shouldRetryFailedCycleWaiverPreview(\n failureCount: number,\n error: unknown,\n): boolean {\n if (hasNumericStatus(error) && error.status >= 400 && error.status < 500) {\n return false;\n }\n\n return failureCount < 1;\n}\n\nexport function useFailedCycleWaiverPreview(\n subscriptionToken: string,\n options: { enabled: boolean },\n) {\n const api = useSubscriptionsApi();\n\n return useQuery({\n queryKey: subscriptionsKeys.failedCycleWaiver(subscriptionToken),\n queryFn: () => api.fetchFailedCycleWaiverPreview(subscriptionToken),\n enabled: options.enabled && subscriptionToken.length > 0,\n retry: shouldRetryFailedCycleWaiverPreview,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport function useWaiveFailedCycle(options?: {\n onSuccess?: (variables: { subscriptionToken: string }) => void;\n onError?: (error: unknown, variables: { subscriptionToken: string }) => void;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: { subscriptionToken: string }) =>\n api.waiveFailedCycle(params.subscriptionToken),\n onSuccess: (_subscription, variables) => {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(variables.subscriptionToken),\n });\n options?.onSuccess?.(variables);\n },\n onError: (error, variables) => options?.onError?.(error, variables),\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport { useSubscriptionsApi } from \"../subscriptions-api-context\";\n\nexport type UpdateSubscriptionInfoVariables = {\n subscriptionToken: string;\n body: Partial<\n Pick<\n subscriptions.UpdateSubscriptionInfoBody,\n | \"payment_method_id\"\n | \"quantity\"\n | \"address_id\"\n | \"next_bill_date\"\n | \"auto_apply_points\"\n >\n >;\n};\n\nexport function useUpdateSubscriptionInfo(options?: {\n onSuccess?: (\n variables: UpdateSubscriptionInfoVariables,\n ) => void | Promise<void>;\n onError?: (\n error: unknown,\n variables: UpdateSubscriptionInfoVariables,\n ) => void;\n // Opt out of the hook's auto-invalidation when the consumer needs\n // to chain another mutation (e.g. payment-method update → retry).\n // Without this, the auto-invalidate fires immediately on update\n // success and the chained mutation triggers a second refetch later\n // — two round-trips for one orchestrated flow. Consumers that opt\n // out are responsible for calling invalidateQueries themselves\n // after their orchestration completes.\n skipAutoInvalidate?: boolean;\n}) {\n const api = useSubscriptionsApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: UpdateSubscriptionInfoVariables) =>\n api.updateSubscriptionInfo(params.subscriptionToken, params.body),\n onSuccess: (_subscription, variables) => {\n if (!options?.skipAutoInvalidate) {\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(variables.subscriptionToken),\n });\n }\n return options?.onSuccess?.(variables);\n },\n onError: (error, variables) => options?.onError?.(error, variables),\n });\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { bundlesKeys } from \"../query-keys\";\nimport { useBundlesApi } from \"../bundles-api-context\";\n\nexport function useBundles(options?: { enabled?: boolean }) {\n const api = useBundlesApi();\n return useQuery({\n queryKey: bundlesKeys.list(),\n queryFn: () => api.fetchBundles(),\n enabled: options?.enabled ?? true,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { subscriptions } from \"../types\";\nimport { bundlesKeys, subscriptionsKeys } from \"../query-keys\";\nimport { useBundlesApi } from \"../bundles-api-context\";\n\nexport function useCreateBundle(options?: {\n onSuccess?: (bundle: subscriptions.Bundle) => void;\n onError?: (error: unknown) => void;\n}) {\n const api = useBundlesApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: subscriptions.CreateBundleParams) =>\n api.createBundle(params),\n onSuccess: (bundle) => {\n queryClient.invalidateQueries({ queryKey: bundlesKeys.all });\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.all });\n options?.onSuccess?.(bundle);\n },\n onError: options?.onError,\n });\n}\n","interface SubscriptionPriceItem {\n allow_subscription: boolean;\n subscription_interval: number | null;\n subscription_price_in_currency: string | null;\n}\n\n/** Minimal shape needed to derive a subscription's displayed pricing. */\ninterface SubscriptionPricingInput {\n price: number;\n /**\n * Next-renewal first-class discount total (per unit). Already includes the\n * legacy renewal callback amount and the price cap, computed server-side —\n * the client cannot derive it.\n */\n renewal_discount_total?: number | null;\n subscription_discounts?:\n | { discount: { code: string }; removed_at: string | null }[]\n | null;\n}\n\ninterface ScheduledProcessingInput {\n status: string;\n nextRetryAt: string | null;\n}\n\n/** Per-unit pricing lines for a subscription detail summary. */\nexport interface SubscriptionPricingBreakdown {\n /** Recurring price shown on the subtotal line (per unit). */\n subtotalUnit: number;\n /** First-class attached renewal discount per unit; 0 if none. */\n attachedDiscountUnit: number;\n /** Active attachment's code, or null (e.g. a callback-only amount). */\n attachedDiscountCode: string | null;\n /** Net price charged next renewal (price − attached, floored at 0), per unit. */\n totalUnit: number;\n /** True when a discount line should render. */\n hasDiscount: boolean;\n}\n\n/**\n * Derive the per-unit pricing summary for a subscription detail view.\n *\n * Subtotal is `price`; the total subtracts the attached discount, matching\n * how the renewal order is billed. `original_price` is the catalog price\n * from when the subscription was created, not a discount on the next order,\n * so it stays out. Callers multiply the per-unit values by the quantity.\n */\nexport function computeSubscriptionPricing(\n subscription: SubscriptionPricingInput,\n): SubscriptionPricingBreakdown {\n const price = subscription.price;\n const attachedDiscountUnit = Math.max(\n subscription.renewal_discount_total ?? 0,\n 0,\n );\n const activeAttachment =\n subscription.subscription_discounts?.find((d) => d.removed_at == null) ??\n null;\n const attachedDiscountCode =\n attachedDiscountUnit > 0 ? (activeAttachment?.discount.code ?? null) : null;\n\n return {\n subtotalUnit: price,\n attachedDiscountUnit,\n attachedDiscountCode,\n totalUnit: Math.max(price - attachedDiscountUnit, 0),\n hasDiscount: attachedDiscountUnit > 0,\n };\n}\n\nexport function getSubscriptionPrice(\n item: SubscriptionPriceItem,\n): string | null {\n if (!item.allow_subscription) return null;\n const intervalText =\n item.subscription_interval === 1\n ? \"month\"\n : `${item.subscription_interval} mo.`;\n return `${item.subscription_price_in_currency}/${intervalText}`;\n}\n\nexport function canResumeScheduledProcessing(\n subscription: ScheduledProcessingInput,\n): boolean {\n return subscription.status === \"past_due\" && subscription.nextRetryAt == null;\n}\n\nexport function formatSubscriptionFrequency(frequency: string): string {\n if (frequency === \"day\") return \"Daily\";\n if (frequency === \"week\") return \"Weekly\";\n if (frequency === \"month\") return \"Monthly\";\n if (frequency === \"year\") return \"Yearly\";\n return frequency;\n}\n\nexport function calculateResumeDate(\n billingInterval: number,\n billingIntervalUnit: string,\n orderCount: number,\n fromDate?: string | Date | null,\n): Date {\n let startDate: Date;\n\n if (fromDate) {\n if (typeof fromDate === \"string\") {\n startDate = new Date(\n fromDate + (fromDate.includes(\"T\") ? \"\" : \"T12:00:00.000Z\"),\n );\n } else {\n startDate = new Date(\n Date.UTC(\n fromDate.getUTCFullYear(),\n fromDate.getUTCMonth(),\n fromDate.getUTCDate(),\n 12,\n 0,\n 0,\n 0,\n ),\n );\n }\n } else {\n const now = new Date();\n startDate = new Date(\n Date.UTC(\n now.getUTCFullYear(),\n now.getUTCMonth(),\n now.getUTCDate(),\n 12,\n 0,\n 0,\n 0,\n ),\n );\n }\n\n const baseDate = new Date(startDate.getTime());\n const totalIntervals = billingInterval * orderCount;\n\n switch (billingIntervalUnit.toLowerCase()) {\n case \"day\":\n baseDate.setUTCDate(baseDate.getUTCDate() + totalIntervals);\n break;\n case \"week\":\n baseDate.setUTCDate(baseDate.getUTCDate() + totalIntervals * 7);\n break;\n case \"month\": {\n const currentMonth = baseDate.getUTCMonth();\n const currentDay = baseDate.getUTCDate();\n baseDate.setUTCMonth(currentMonth + totalIntervals);\n if (baseDate.getUTCDate() !== currentDay) {\n baseDate.setUTCDate(0);\n }\n break;\n }\n case \"year\":\n baseDate.setUTCFullYear(baseDate.getUTCFullYear() + totalIntervals);\n break;\n default: {\n const defaultMonth = baseDate.getUTCMonth();\n const defaultDay = baseDate.getUTCDate();\n baseDate.setUTCMonth(defaultMonth + totalIntervals);\n if (baseDate.getUTCDate() !== defaultDay) {\n baseDate.setUTCDate(0);\n }\n }\n }\n\n return baseDate;\n}\n\nexport function isYearlyBillingCycle(\n billingInterval: number = 1,\n billingIntervalUnit: string = \"month\",\n): boolean {\n const step = Math.max(1, billingInterval);\n switch (billingIntervalUnit.toLowerCase()) {\n case \"year\":\n return true;\n case \"month\":\n return step >= 12;\n case \"week\":\n return step >= 52;\n case \"day\":\n return step >= 365;\n default:\n return false;\n }\n}\n\n/**\n * Latest date a subscription's bill date may be edited to: 2 years out for\n * yearly plans, 12 months out for everything else.\n */\nexport function getMaxEditableBillDate(\n billingInterval: number = 1,\n billingIntervalUnit: string = \"month\",\n from: Date = new Date(),\n): Date {\n const maxDate = new Date(from.getTime());\n maxDate.setHours(0, 0, 0, 0);\n const day = maxDate.getDate();\n if (isYearlyBillingCycle(billingInterval, billingIntervalUnit)) {\n maxDate.setFullYear(maxDate.getFullYear() + 2);\n } else {\n maxDate.setMonth(maxDate.getMonth() + 12);\n }\n // The native setters overflow when the target month lacks the source day\n // (Feb 29 → Mar 1); roll back to the end of the intended month.\n if (maxDate.getDate() !== day) {\n maxDate.setDate(0);\n }\n return maxDate;\n}\n\nexport interface BillingCadence {\n billingInterval?: number;\n billingIntervalUnit?: string;\n}\n\n/**\n * Latest date a whole bundle's bill date may be edited to. Every member moves\n * to one shared date, so the strictest member binds: a bundle holding one\n * monthly plan is capped at 12 months even if its other members are yearly.\n *\n * An empty list falls back to the 12-month cap, which is also what a member of\n * unknown cadence resolves to via getMaxEditableBillDate's own default.\n */\nexport function getMaxEditableBillDateForBundle(\n members: BillingCadence[],\n from: Date = new Date(),\n): Date {\n const caps = members.map((member) =>\n getMaxEditableBillDate(\n member.billingInterval,\n member.billingIntervalUnit,\n from,\n ),\n );\n const [first, ...rest] = caps;\n if (!first) return getMaxEditableBillDate(1, \"month\", from);\n\n return rest.reduce(\n (strictest, current) => (current < strictest ? current : strictest),\n first,\n );\n}\n\nexport function calculateNextBillDate(\n billingInterval: number = 1,\n billingIntervalUnit: string = \"month\",\n): string {\n const now = new Date();\n const nextBillDate = new Date(now);\n\n switch (billingIntervalUnit.toLowerCase()) {\n case \"day\":\n nextBillDate.setDate(now.getDate() + billingInterval);\n break;\n case \"week\":\n nextBillDate.setDate(now.getDate() + billingInterval * 7);\n break;\n case \"month\":\n nextBillDate.setMonth(now.getMonth() + billingInterval);\n break;\n case \"year\":\n nextBillDate.setFullYear(now.getFullYear() + billingInterval);\n break;\n default:\n nextBillDate.setMonth(now.getMonth() + billingInterval);\n }\n\n return nextBillDate.toISOString().split(\"T\")[0] || \"\";\n}\n\n/** Longest pause the dialogs have ever offered, before the cap narrows it. */\nconst MAX_SKIPPABLE_ORDERS = 99;\n\n/**\n * How many upcoming orders a pause may skip: the largest count whose resume\n * date still lands inside the bill-date cap.\n *\n * Pausing for a number of orders sets a bill date like any other edit, so the\n * API caps the date it derives from that count, 2 years out for a yearly cadence\n * and 12 months for everything else, and rejects the request naming\n * number_of_orders. Offering counts past that offers a pause the API refuses.\n *\n * Returns 0 when even a single skip overshoots, which happens on a subscription\n * whose next bill date already sits near the cap. Callers should read that as\n * \"pausing by order count is unavailable here\" and leave the indefinite pause.\n *\n * The two ends deliberately measure from different places: the resume date\n * counts forward from the current bill date, the cap counts forward from today.\n * The API stays the backstop, so the exact boundary count depends on its\n * resume-date arithmetic agreeing with calculateResumeDate.\n */\nexport function getMaxSkippableOrders(\n billingInterval: number = 1,\n billingIntervalUnit: string = \"month\",\n currentNextBillDate?: string | Date | null,\n from: Date = new Date(),\n): number {\n const cap = getMaxEditableBillDate(\n billingInterval,\n billingIntervalUnit,\n from,\n );\n let allowed = 0;\n\n for (let count = 1; count <= MAX_SKIPPABLE_ORDERS; count += 1) {\n // `from` stands in for the bill date when the subscription has none, so the\n // resume date and the cap are measured from the same day. Passing\n // currentNextBillDate straight through let calculateResumeDate fall back to\n // its own new Date() in that branch, which read the wall clock while the cap\n // read the injected date — the two drifted apart and the boundary answer\n // changed from one day to the next.\n const resume = calculateResumeDate(\n billingInterval,\n billingIntervalUnit,\n count,\n currentNextBillDate ?? from,\n );\n // calculateResumeDate anchors at noon UTC, so its UTC fields carry the\n // calendar date it means, while the cap is a local-midnight date. Rebuild\n // the resume date locally so the comparison cannot slip a day at large\n // offsets, the same reason the bill-date pickers read both ends locally.\n const resumeDate = new Date(\n resume.getUTCFullYear(),\n resume.getUTCMonth(),\n resume.getUTCDate(),\n );\n if (resumeDate > cap) break;\n allowed = count;\n }\n\n return allowed;\n}\n\nexport function formatDate(\n dateString: string,\n locale: string = \"en-US\",\n): string {\n if (!dateString) return \"\";\n\n const datePortion = dateString.split(\"T\")[0] ?? dateString;\n const parts = datePortion.split(\"-\");\n if (parts.length !== 3) return \"\";\n\n const [year, month, day] = parts.map(Number);\n if (!year || !month || !day) return \"\";\n const date = new Date(year, month - 1, day);\n\n try {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n } catch {\n // Intl throws on invalid locale values — fall back to en-US rather\n // than crashing the component.\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n }\n}\n\nexport function formatOptionalDate(\n dateString: string | null | undefined,\n locale: string = \"en-US\",\n fallback: string = \"—\",\n): string {\n if (!dateString) return fallback;\n\n const datePortion = dateString.split(\"T\")[0];\n if (!datePortion) return fallback;\n\n const parts = datePortion.split(\"-\").map(Number);\n if (parts.length !== 3) return fallback;\n const [year, month, day] = parts;\n if (year == null || month == null || day == null) return fallback;\n\n const date = new Date(year, month - 1, day);\n const isExactDate =\n date.getFullYear() === year &&\n date.getMonth() === month - 1 &&\n date.getDate() === day;\n if (!isExactDate) return fallback;\n\n try {\n return new Intl.DateTimeFormat(locale.replaceAll(\"_\", \"-\"), {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n } catch {\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n }\n}\n\n// Formats the time-of-day portion of an ISO timestamp in the given IANA\n// timezone. Returns \"\" when no timezone is supplied — the next-order display\n// intentionally omits the time line in that case (the BFF can't promise the\n// stored time-of-day is meaningful without a zone to interpret it in).\nexport function formatTime(\n dateString: string | null | undefined,\n timezone: string | null | undefined,\n locale: string = \"en-US\",\n): string {\n if (!dateString || !timezone) return \"\";\n const date = new Date(dateString);\n if (Number.isNaN(date.getTime())) return \"\";\n try {\n return new Intl.DateTimeFormat(locale, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n timeZone: timezone,\n }).format(date);\n } catch {\n // Intl throws on unknown IANA identifiers — fall back to no time rather\n // than crashing the row.\n return \"\";\n }\n}\n\nexport function getNextBillDisplay(\n nextBillDate: string | null | undefined,\n displayStatus: string,\n labels: {\n cancelled: string;\n completed: string;\n paused: string;\n notAvailable: string;\n } = {\n cancelled: \"Cancelled\",\n completed: \"Completed\",\n paused: \"Paused\",\n notAvailable: \"N/A\",\n },\n locale: string = \"en-US\",\n): string {\n if (displayStatus === \"completed\") return labels.completed;\n if (displayStatus === \"cancelled\") return labels.cancelled;\n if (nextBillDate) return formatDate(nextBillDate, locale);\n if (displayStatus === \"paused\") return labels.paused;\n return labels.notAvailable;\n}\n\nexport function calculateSubscriptionPrice(\n totalPrice: number,\n subscribeAndSave: string | null | undefined,\n quantity: number,\n): string {\n if (!subscribeAndSave) return totalPrice.toFixed(2);\n\n const unitDiscountAmount = parseFloat(subscribeAndSave);\n if (isNaN(unitDiscountAmount)) return totalPrice.toFixed(2);\n\n const subscriptionAmount = totalPrice - unitDiscountAmount * quantity;\n return subscriptionAmount.toFixed(2);\n}\n","export type SubscriptionAction =\n | \"skip_next_order\"\n | \"undo_skip\"\n | \"edit_bill_date\"\n | \"pause_subscription\"\n | \"resume_subscription\"\n | \"cancel_subscription\"\n | \"reactivate_subscription\"\n | \"retry_payment\"\n | \"change_payment_method\";\n\nexport interface SubscriptionActionPolicyInput {\n status: string;\n billingCycleLimitReached?: boolean;\n nextRetryAt?: string | null;\n nextBillDate: string | null;\n allowSkipping: boolean | null;\n maxSkips: number | null;\n skippedCount: number | null;\n hasPendingSkip: boolean;\n canUndoSkip?: boolean;\n canChangePaymentMethod: boolean;\n canWaiveFailedCycle?: boolean;\n isWaiverPreviewLoading?: boolean;\n}\n\nexport interface SubscriptionRecoveryActions {\n state: \"exhausted\" | \"scheduled\";\n primary: \"retry_payment\" | null;\n secondary: \"change_payment_method\" | null;\n tertiary: \"waive_failed_cycle\" | null;\n isCheckingWaiver: boolean;\n}\n\nexport interface SubscriptionActionPolicy {\n primary: \"resume_subscription\" | \"reactivate_subscription\" | null;\n order: SubscriptionAction[];\n menu: SubscriptionAction[];\n recovery: SubscriptionRecoveryActions | null;\n}\n\ninterface SubscriptionSkipInput {\n skipped_date: string;\n unskipped_at?: string | null;\n}\n\n/**\n * The one rule for a completed subscription: its current plan's\n * billing-cycle limit is reached. Every \"completed\" presentation and\n * gate reads this, so a new terminal condition lands here once.\n */\nexport function isSubscriptionCompleted(\n subscription: { billing_cycle_limit_reached?: boolean } | null | undefined,\n): boolean {\n return subscription?.billing_cycle_limit_reached === true;\n}\n\nexport function getSubscriptionDisplayStatus(subscription: {\n status: string;\n billing_cycle_limit_reached?: boolean;\n}): string {\n return isSubscriptionCompleted(subscription)\n ? \"completed\"\n : subscription.status;\n}\n\nexport function hasPendingSubscriptionSkip(\n skips: readonly SubscriptionSkipInput[] | null | undefined,\n today: Date = new Date(),\n): boolean {\n if (!skips?.length) return false;\n\n const todayUtc = Date.UTC(\n today.getUTCFullYear(),\n today.getUTCMonth(),\n today.getUTCDate(),\n );\n\n return skips.some((skip) => {\n if (skip.unskipped_at != null) return false;\n const skippedDate = new Date(`${skip.skipped_date.slice(0, 10)}T00:00:00Z`);\n return (\n !Number.isNaN(skippedDate.getTime()) && skippedDate.getTime() >= todayUtc\n );\n });\n}\n\nexport function getSubscriptionActionPolicy(\n subscription: SubscriptionActionPolicyInput,\n): SubscriptionActionPolicy {\n const status = getSubscriptionDisplayStatus({\n status: subscription.status,\n billing_cycle_limit_reached: subscription.billingCycleLimitReached,\n });\n\n if (status === \"active\") {\n const skipAllowanceAvailable =\n subscription.maxSkips == null ||\n (subscription.skippedCount ?? 0) < subscription.maxSkips;\n const canSkip =\n subscription.allowSkipping === true &&\n subscription.nextBillDate != null &&\n skipAllowanceAvailable;\n const order: SubscriptionAction[] = [];\n\n if (subscription.hasPendingSkip) {\n if (subscription.canUndoSkip) order.push(\"undo_skip\");\n } else if (canSkip) {\n order.push(\"skip_next_order\");\n }\n order.push(\"edit_bill_date\");\n\n return {\n primary: null,\n order,\n menu: [\"pause_subscription\", \"cancel_subscription\"],\n recovery: null,\n };\n }\n\n if (status === \"paused\") {\n return {\n primary: \"resume_subscription\",\n order: [],\n menu: [\"cancel_subscription\"],\n recovery: null,\n };\n }\n\n if (status === \"cancelled\") {\n return {\n primary: \"reactivate_subscription\",\n order: [],\n menu: [],\n recovery: null,\n };\n }\n\n if (status === \"past_due\") {\n const isExhausted = subscription.nextRetryAt == null;\n const secondary = subscription.canChangePaymentMethod\n ? \"change_payment_method\"\n : null;\n\n return {\n primary: null,\n order: [],\n menu: [\"cancel_subscription\"],\n recovery: {\n state: isExhausted ? \"exhausted\" : \"scheduled\",\n primary: isExhausted ? \"retry_payment\" : null,\n secondary,\n tertiary:\n isExhausted &&\n subscription.isWaiverPreviewLoading !== true &&\n subscription.canWaiveFailedCycle === true\n ? \"waive_failed_cycle\"\n : null,\n isCheckingWaiver:\n isExhausted && subscription.isWaiverPreviewLoading === true,\n },\n };\n }\n\n if (status === \"completed\") {\n return { primary: null, order: [], menu: [], recovery: null };\n }\n\n if ([\"pending\", \"trial\"].includes(status)) {\n return {\n primary: null,\n order: [],\n menu: [\"cancel_subscription\"],\n recovery: null,\n };\n }\n\n return { primary: null, order: [], menu: [], recovery: null };\n}\n","export type FailedCycleWaiverSummary =\n | { kind: \"combined\"; date: string }\n | { kind: \"separate\"; billDate: string; shipDate: string };\n\nconst ISO_INSTANT_PATTERN =\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?(Z|[+-]\\d{2}:\\d{2})$/;\n\nexport function getFailedCycleWaiverSummary(input: {\n nextBillDate: string;\n nextShipDate: string;\n locale: string;\n timezone: string;\n}): FailedCycleWaiverSummary | null {\n const billDate = parseIsoInstant(input.nextBillDate);\n const shipDate = parseIsoInstant(input.nextShipDate);\n if (billDate == null || shipDate == null) return null;\n\n const calendarFormatter = createCalendarDateFormatter(input.timezone);\n const displayFormatter = createDisplayDateFormatter(\n input.locale,\n input.timezone,\n );\n if (calendarFormatter == null || displayFormatter == null) return null;\n\n const billCalendarDate = getCalendarDateIdentity(calendarFormatter, billDate);\n const shipCalendarDate = getCalendarDateIdentity(calendarFormatter, shipDate);\n if (billCalendarDate == null || shipCalendarDate == null) return null;\n\n const formattedBillDate = displayFormatter.format(billDate);\n const formattedShipDate = displayFormatter.format(shipDate);\n\n if (billCalendarDate === shipCalendarDate) {\n return { kind: \"combined\", date: formattedBillDate };\n }\n\n return {\n kind: \"separate\",\n billDate: formattedBillDate,\n shipDate: formattedShipDate,\n };\n}\n\nfunction parseIsoInstant(input: string): Date | null {\n const match = ISO_INSTANT_PATTERN.exec(input);\n if (match == null) return null;\n\n const [, yearText, monthText, dayText, hourText, minuteText, secondText] =\n match;\n const offset = match[8];\n if (\n yearText == null ||\n monthText == null ||\n dayText == null ||\n hourText == null ||\n minuteText == null ||\n secondText == null ||\n offset == null\n ) {\n return null;\n }\n\n const year = Number(yearText);\n const month = Number(monthText);\n const day = Number(dayText);\n const hour = Number(hourText);\n const minute = Number(minuteText);\n const second = Number(secondText);\n\n if (\n month < 1 ||\n month > 12 ||\n day < 1 ||\n day > daysInMonth(year, month) ||\n hour > 23 ||\n minute > 59 ||\n second > 59 ||\n !isValidOffset(offset)\n ) {\n return null;\n }\n\n const instant = new Date(input);\n return Number.isNaN(instant.getTime()) ? null : instant;\n}\n\nfunction daysInMonth(year: number, month: number): number {\n if (month === 2) {\n const isLeapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);\n return isLeapYear ? 29 : 28;\n }\n\n return [4, 6, 9, 11].includes(month) ? 30 : 31;\n}\n\nfunction isValidOffset(offset: string): boolean {\n if (offset === \"Z\") return true;\n\n const offsetHour = Number(offset.slice(1, 3));\n const offsetMinute = Number(offset.slice(4, 6));\n return offsetHour <= 23 && offsetMinute <= 59;\n}\n\nfunction createCalendarDateFormatter(\n timezone: string,\n): Intl.DateTimeFormat | null {\n try {\n return new Intl.DateTimeFormat(\"en-US-u-ca-gregory-nu-latn\", {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n timeZone: timezone,\n });\n } catch {\n return null;\n }\n}\n\nfunction createDisplayDateFormatter(\n locale: string,\n timezone: string,\n): Intl.DateTimeFormat | null {\n const normalizedLocale = locale.trim().replaceAll(\"_\", \"-\");\n if (!normalizedLocale) return null;\n\n let supportedLocale: string | undefined;\n try {\n [supportedLocale] = Intl.DateTimeFormat.supportedLocalesOf(\n [normalizedLocale],\n { localeMatcher: \"lookup\" },\n );\n } catch {\n return null;\n }\n if (supportedLocale == null) return null;\n\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n timeZone: timezone,\n };\n\n try {\n return new Intl.DateTimeFormat(supportedLocale, options);\n } catch {\n return null;\n }\n}\n\nfunction getCalendarDateIdentity(\n formatter: Intl.DateTimeFormat,\n instant: Date,\n): string | null {\n const parts = formatter.formatToParts(instant);\n const year = parts.find((part) => part.type === \"year\")?.value;\n const month = parts.find((part) => part.type === \"month\")?.value;\n const day = parts.find((part) => part.type === \"day\")?.value;\n if (year == null || month == null || day == null) return null;\n\n return `${year}-${month}-${day}`;\n}\n","/** How far an auto-apply-points write reaches. */\nexport type AutoApplyPointsScope = \"subscription\" | \"bundle\";\n\n/**\n * The two token sets the server reports for one write.\n *\n * The update response's `subscription` resource deliberately does not cross\n * this port: the hook refetches detail immediately, so a partial resource here\n * would be a second source of truth for data nothing reads. Only these two\n * sets cross, because only they are unavailable any other way.\n */\nexport type AutoApplyPointsWriteResult = {\n /** Every subscription the write was resolved against. */\n resolvedSubscriptionTokens: string[];\n /** The subset whose stored value actually moved. */\n changedSubscriptionTokens: string[];\n};\n\n/**\n * Bundle membership changed under a bundle-scoped write and the server's retry\n * did not settle, so nothing was written and the customer can try again.\n *\n * Transport-free on purpose. Thrown only for HTTP 409 whose `error.code` is\n * `bundle_membership_conflict`; every other failure stays generic. A named\n * domain error rather than a discriminated result because TanStack Query's\n * error channel wants a throw, and this keeps the happy path free of\n * branching while still giving the component a stable signal to catch.\n */\nexport class BundleMembershipConflictError extends Error {\n constructor(message: string) {\n super(message);\n // Explicit, because extending a built-in loses the subclass name under\n // some transpilation targets and the name is what shows up in logs.\n this.name = \"BundleMembershipConflictError\";\n }\n}\n\n/** The portal's write for the renewal-bundle points opt-in. */\nexport interface AutoApplyPointsApi {\n /**\n * Write the opt-in at the requested scope.\n *\n * Throws BundleMembershipConflictError on a settled-out conflict; any other\n * failure throws whatever the transport produced.\n */\n updateAutoApplyPoints(input: {\n subscriptionToken: string;\n autoApplyPoints: boolean;\n scope: AutoApplyPointsScope;\n }): Promise<AutoApplyPointsWriteResult>;\n}\n","import { createContext, type Provider, use } from \"react\";\nimport type { AutoApplyPointsApi } from \"./auto-apply-points-api\";\n\nconst AutoApplyPointsApiContext = createContext<AutoApplyPointsApi | null>(\n null,\n);\n\nexport const AutoApplyPointsApiProvider: Provider<AutoApplyPointsApi | null> =\n AutoApplyPointsApiContext.Provider;\n\nexport function useAutoApplyPointsApi(): AutoApplyPointsApi {\n const api = use(AutoApplyPointsApiContext);\n if (!api) {\n throw new Error(\n \"useAutoApplyPointsApi must be used within an AutoApplyPointsApiProvider\",\n );\n }\n return api;\n}\n","import type { SubscriptionsApi } from \"@fluid-app/subscriptions-core\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport type { PortalTenantHeyApiClient } from \"@fluid-app/portal-tenant-api-client/client\";\nimport * as portalTenant from \"@fluid-app/portal-tenant-api-client/sdk\";\n\n/**\n * Maps the BFF meta envelope to the port's expected shape.\n */\nfunction mapMeta(raw: { request_id?: string | null; timestamp?: string }): {\n request_id: string;\n timestamp: string;\n} {\n return {\n request_id: raw.request_id ?? \"\",\n timestamp: raw.timestamp ?? \"\",\n };\n}\n\ntype BffSubscriptionResponse = NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionsShow>>\n>;\n\ntype BffListResponse = NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionsList>>\n>;\n\ntype BffFailedCycleWaiverPreviewResponse = NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionsFailedCycleWaiverPreview>>\n>;\n\n// `subscriptionsShow` is the only action whose response narrows `subscription`\n// to `SubscriptionDetailResource` (renewal_bundle required, since show is the\n// only action that populates it). Every other subscription action\n// (pause/resume/skip/cancel/reactivate/retry/waiver-create/update) returns the\n// looser `Subscription` shape. `mapDetailSubscription` never reads\n// renewal_bundle, so it is typed to that common denominator rather than the\n// show-specific response, letting every action's response satisfy it.\ntype BffSubscription = NonNullable<\n NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionsPause>>\n >[\"subscription\"]\n>;\n\n// Structural envelope shared by every subscription action response. Narrower\n// than each action's exact generated type (which vary in whether\n// subscription/meta are required and which carry extra fields), but every one\n// of them is assignable to it.\ntype BffSubscriptionActionResponse = {\n subscription?: BffSubscription;\n meta?: BffSubscriptionResponse[\"meta\"];\n};\n\n/**\n * Narrows the generated generic Meta schema to the shared port shape without\n * rebuilding the BFF response or dropping transport-only fields. The\n * portal-tenant BFF serves meta.request_id as null (the contract allows it),\n * so only a non-string, non-null request_id is rejected.\n */\nfunction assertSharedFailedCycleWaiverPreview(\n response: BffFailedCycleWaiverPreviewResponse,\n): asserts response is BffFailedCycleWaiverPreviewResponse &\n subscriptions.FailedCycleWaiverPreviewResponse {\n const meta = response.meta;\n if (\n meta != null &&\n ((meta.request_id != null && typeof meta.request_id !== \"string\") ||\n typeof meta.timestamp !== \"string\")\n ) {\n throw new Error(\"Failed-cycle waiver preview metadata is invalid\");\n }\n}\n\n/**\n * Safely parses a price string to a number, returning the fallback if the\n * result is NaN (e.g. non-numeric strings from a malformed BFF response).\n */\nfunction safeParsePrice(\n value: string | null | undefined,\n fallback = 0,\n): number {\n if (!value) return fallback;\n const parsed = parseFloat(value);\n return Number.isNaN(parsed) ? fallback : parsed;\n}\n\n/**\n * Maps a BFF subscription detail response to the port's SubscriptionDetail.\n *\n * The BFF returns a flat Subscription schema (plan_name, product, etc.) while\n * the port expects richly nested objects (subscription_plan, variant.product).\n * This explicitly maps every field the UI accesses so undefined-property crashes\n * are caught here at the adapter boundary rather than deep in the component tree.\n */\nexport function mapDetailSubscription(\n bff: BffSubscription,\n): subscriptions.SubscriptionDetailSubscription {\n const price = safeParsePrice(bff.total);\n\n return {\n id: bff.id ?? 0,\n subscription_token: bff.token ?? \"\",\n status: bff.status ?? \"\",\n billing_cycle_limit_reached: bff.billing_cycle_limit_reached ?? false,\n successful_billing_cycles: bff.successful_billing_cycles ?? 0,\n quantity: bff.quantity ?? 1,\n price,\n original_price: safeParsePrice(bff.original_price, price),\n next_bill_date: bff.next_billing_date ?? null,\n last_bill_date: bff.last_billing_date ?? null,\n timezone: bff.timezone ?? null,\n next_ship_date: null,\n last_ship_date: bff.last_shipping_date ?? null,\n disabled: false,\n attempts: 0,\n // The portal-tenant OpenAPI schema dropped last_failed_at/next_retry_at\n // from the Subscription response, but the BFF still returns them at runtime\n // and downstream components (past-due-banner, subscription-detail) rely on\n // them. Read through a cast until the schema is restored. Tracked in\n // CURRENT-1069.\n last_failed_at:\n ((bff as Record<string, unknown>).last_failed_at as\n | string\n | null\n | undefined) ?? null,\n next_retry_at:\n ((bff as Record<string, unknown>).next_retry_at as\n | string\n | null\n | undefined) ?? null,\n // decline_count drives the banner's \"we're trying again\" vs \"the last\n // retry didn't go through\" branch. Same cast-through-Record pattern as\n // last_failed_at/next_retry_at above until the OpenAPI schema is\n // regenerated to include it.\n decline_count:\n ((bff as Record<string, unknown>).decline_count as\n | number\n | null\n | undefined) ?? null,\n skipped_count: 0,\n max_skips: null,\n cancelled_at: null,\n created_at: bff.created_at ?? \"\",\n updated_at: bff.updated_at ?? \"\",\n notes: null,\n // Copied WITHOUT a `??` default, deliberately. This mapper is a whitelist,\n // so a field it omits reaches the UI as undefined with no type error, and a\n // default here would erase the difference between \"the company has no\n // points program\" and \"the customer turned this off\". points_enabled gates\n // whether the control renders at all, and auto_apply_points is the state it\n // renders from, so collapsing either one breaks a different thing.\n auto_apply_points: bff.auto_apply_points,\n points_enabled: bff.points_enabled,\n subscription_plan: {\n id: bff.plan?.id ?? 0,\n name: bff.plan?.name ?? bff.plan_name ?? \"\",\n billing_interval: bff.plan?.billing_interval ?? 1,\n billing_interval_unit:\n bff.plan?.billing_interval_unit ?? bff.interval ?? \"month\",\n billing_frequency_in_words: bff.plan?.billing_interval_unit\n ? `Every ${bff.plan.billing_interval ?? 1} ${bff.plan.billing_interval_unit}`\n : \"\",\n shipping_interval: 1,\n shipping_interval_unit:\n bff.plan?.billing_interval_unit ?? bff.interval ?? \"month\",\n trial_period: null,\n trial_period_unit: null,\n split_volume: false,\n allow_skipping: bff.plan?.allow_skipping ?? false,\n max_skips: bff.plan?.max_skips ?? null,\n allow_max_billing_cycles: bff.plan?.allow_max_billing_cycles ?? false,\n max_billing_cycles: bff.plan?.max_billing_cycles ?? null,\n price_adjustment_type: null,\n price_adjustment_amount: null,\n // Variant-level cap exposed via `bff.product.max_quantity` (the BFF\n // sources it from `variants.subscription_max_qty` gated on\n // `limit_subscription`). The FE port still keys it under\n // `subscription_plan` for back-compat with the existing UI consumer.\n max_quantity: bff.product?.max_quantity ?? null,\n active: true,\n company_default: null,\n created_at: \"\",\n updated_at: \"\",\n products_count: null,\n subscribers_count: null,\n },\n customer: {\n id: 0,\n account_id: null,\n first_name: null,\n last_name: null,\n full_name: bff.customer_name ?? \"\",\n email: \"\",\n verified_email: null,\n phone: null,\n orders_count: null,\n created_at: \"\",\n display_total_spent: \"0\",\n metadata: {},\n user_company_id: null,\n external_id: null,\n last_order_id: null,\n notes: null,\n active: true,\n total_spent: 0,\n customer_notes: [],\n default_address: null,\n addresses: [],\n active_subscriptions_count: 0,\n inactive_subscriptions_count: 0,\n is_rep: false,\n },\n variant: {\n id: bff.product?.id ?? 0,\n title: bff.product?.variant_name ?? \"\",\n image_url: bff.product?.image_url ?? null,\n image_path: null,\n sku: null,\n primary_image: bff.product?.image_url ?? null,\n price: bff.total ? safeParsePrice(bff.total) : null,\n price_in_currency: bff.total ?? \"0\",\n options: [],\n product: {\n id: bff.product?.id ?? 0,\n title: bff.product?.name ?? \"\",\n image_url: bff.product?.image_url ?? null,\n image_path: null,\n price: bff.total ? safeParsePrice(bff.total) : null,\n cv: null,\n tax: null,\n sku: null,\n price_in_currency: bff.total ?? \"0\",\n tax_in_currency: \"0\",\n cv_in_currency: \"0\",\n },\n },\n address_id: bff.address_id ?? null,\n address: bff.address\n ? {\n id: bff.address.id ?? null,\n name: bff.address.name ?? null,\n address1: bff.address.address1 ?? \"\",\n address2: bff.address.address2 ?? null,\n city: bff.address.city ?? \"\",\n state: bff.address.state ?? \"\",\n subdivision_code: null,\n postal_code: bff.address.postal_code ?? \"\",\n country_code: bff.address.country_code ?? null,\n default: false,\n }\n : {\n id: null,\n name: null,\n address1: \"\",\n address2: null,\n city: \"\",\n state: \"\",\n subdivision_code: null,\n postal_code: \"\",\n country_code: null,\n default: false,\n },\n payment_method: bff.payment_method\n ? {\n id: bff.payment_method.id ?? 0,\n source: bff.payment_method.source ?? \"\",\n payment_type:\n bff.payment_method.payment_type ?? bff.payment_method.source ?? \"\",\n created_at: \"\",\n updated_at: \"\",\n default: false,\n details: {\n card_network: bff.payment_method.card_network ?? undefined,\n last4: bff.payment_method.last4 ?? undefined,\n },\n }\n : {\n id: 0,\n source: \"\",\n payment_type: \"\",\n created_at: \"\",\n updated_at: \"\",\n default: false,\n details: {},\n },\n currency: {\n id: 0,\n name: bff.currency ?? null,\n code: bff.currency ?? \"USD\",\n rate: null,\n active: true,\n symbol: null,\n },\n country: { id: 0, name: \"\", iso: \"\" },\n company: { id: 0, name: \"\" },\n subscription_skips: [],\n orders: [],\n bundled_items: bff.bundled_items\n ? bff.bundled_items.map((item) => ({\n quantity: item.quantity ?? 0,\n product_id: item.product_id ?? 0,\n variant_id: item.variant_id ?? 0,\n option_titles: item.option_titles ?? [],\n product_title: item.product_title ?? \"\",\n variant_title: item.variant_title ?? \"\",\n display_to_customer: item.display_to_customer ?? true,\n }))\n : undefined,\n bundled_subscriptions: bff.bundled_subscriptions\n ? bff.bundled_subscriptions.map((sib) => ({\n subscription_token: sib.subscription_token ?? \"\",\n product_title: sib.product_title ?? \"\",\n variant_title: sib.variant_title ?? null,\n price: sib.price ?? 0,\n image_url: sib.image_url ?? null,\n }))\n : undefined,\n // The portal-tenant OpenAPI client type lags the Rails schema (same lag as\n // last_failed_at above — tracked in CURRENT-1069), so these first-class\n // subscription-discount fields are read through a cast until the generated\n // client is regenerated. The BFF returns them at runtime; the\n // subscription-detail pricing summary relies on them to render the attached\n // discount line and net total. renewal_discount_total is coerced because\n // the BFF serializes other money fields (total, original_price) as strings\n // and could normalize this one the same way later.\n subscription_discounts:\n ((bff as Record<string, unknown>).subscription_discounts as\n | subscriptions.SubscriptionDiscountAttachment[]\n | undefined) ?? [],\n renewal_discount_total:\n Number((bff as Record<string, unknown>).renewal_discount_total ?? 0) || 0,\n // Passed through as the server sent it. Both null and undefined take\n // the same fallback route (autoApplyPointsWriteRoute falsy-checks it),\n // so collapsing one into the other would discard what the server said\n // and buy nothing.\n renewal_bundle: bff.renewal_bundle,\n };\n}\n\nfunction mapSubscriptionDetail(\n response: BffSubscriptionActionResponse,\n): subscriptions.SubscriptionDetail {\n const bff = response.subscription;\n if (!bff) {\n throw new Error(\n \"BFF returned a successful response but subscription data was missing\",\n );\n }\n return {\n subscription: mapDetailSubscription(bff),\n meta: response.meta ? mapMeta(response.meta) : undefined,\n };\n}\n\n/**\n * Maps a BFF list subscription to the port's SubscriptionListItem.\n *\n * The BFF returns a flat shape with `product` and `quantity` while the port\n * expects nested `variant.product` (from the admin API). This bridges the two\n * so the UI layer sees a consistent shape regardless of which API backs it.\n */\nfunction mapListItem(\n bff: NonNullable<BffListResponse[\"subscriptions\"]>[number],\n): subscriptions.SubscriptionListItem {\n return {\n id: bff.id ?? 0,\n subscription_token: bff.token ?? \"\",\n created_at: bff.created_at ?? \"\",\n customer: {\n id: 0,\n account_id: \"\",\n active: true,\n display_total_spent: \"0\",\n email: \"\",\n first_name: \"\",\n full_name: bff.customer_name ?? \"\",\n is_rep: false,\n last_name: \"\",\n orders_count: 0,\n phone: null,\n total_spent: \"0\",\n user_company_id: null,\n },\n last_bill_date: null,\n next_bill_date: bff.next_billing_date ?? null,\n price: safeParsePrice(bff.total),\n quantity: bff.quantity ?? 1,\n status: bff.status ?? \"\",\n billing_cycle_limit_reached: bff.billing_cycle_limit_reached ?? false,\n successful_billing_cycles: bff.successful_billing_cycles ?? 0,\n subscription_plan: {\n // The flat top-level `bff.interval` is a denormalized convenience that\n // does NOT carry a numeric interval — it's a single descriptor like\n // \"monthly\". The accurate fields are on `bff.plan` (number + unit), so\n // a quarterly subscription returns interval=3 / unit=\"month\" there.\n id: bff.plan?.id ?? 0,\n active: true,\n billing_interval: bff.plan?.billing_interval ?? 1,\n billing_interval_unit: bff.plan?.billing_interval_unit ?? \"\",\n shipping_interval: bff.plan?.billing_interval ?? 1,\n shipping_interval_unit: bff.plan?.billing_interval_unit ?? \"\",\n },\n variant: {\n id: bff.product?.id ?? 0,\n title: bff.product?.variant_name ?? \"\",\n product: {\n id: bff.product?.id ?? 0,\n title: bff.product?.name ?? \"\",\n image_url: bff.product?.image_url ?? \"\",\n price_in_currency: bff.total ?? \"0\",\n },\n },\n bundled_subscriptions: (bff.bundled_subscriptions ?? []).map((b) => ({\n subscription_token: b.subscription_token ?? \"\",\n product_title: b.product_title ?? \"\",\n variant_title: b.variant_title ?? null,\n price: b.price ?? 0,\n image_url: b.image_url ?? null,\n })),\n };\n}\n\nfunction mapSubscriptionList(\n response: BffListResponse,\n): subscriptions.SubscriptionsResponse {\n const raw = response.meta ?? {};\n return {\n subscriptions: (response.subscriptions ?? []).map(mapListItem),\n meta: {\n ...mapMeta(raw),\n pagination: raw.pagination\n ? {\n cursor: raw.pagination.cursor ?? null,\n limit: raw.pagination.limit,\n next_cursor: raw.pagination.next_cursor ?? null,\n prev_cursor: raw.pagination.prev_cursor ?? null,\n }\n : undefined,\n },\n };\n}\n\n/**\n * Creates a SubscriptionsApi-compatible adapter backed by the portal-tenant BFF.\n *\n * Uses async/await with explicit field mapping. The BFF returns simplified\n * subscription types compared to the full admin API; the adapter maps the\n * response envelope and provides runtime defaults for optional fields.\n */\nexport function createPortalSubscriptionsAdapter(\n client: PortalTenantHeyApiClient,\n): SubscriptionsApi {\n return {\n fetchCustomerSubscriptions: async (\n params: subscriptions.FetchSubscriptionsParams,\n ) => {\n const rawStatus = params.status;\n const status =\n rawStatus === \"active\" || rawStatus === \"inactive\"\n ? rawStatus\n : undefined;\n const response = await portalTenant.subscriptionsList({\n client,\n query: {\n \"page[cursor]\": params.cursor,\n \"page[limit]\": params.limit ?? params.perPage,\n status,\n q: params.search ?? undefined,\n },\n });\n return mapSubscriptionList(response);\n },\n\n fetchSubscription: async (subscriptionToken: string) => {\n const response = await portalTenant.subscriptionsShow({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n pauseSubscription: async (\n subscriptionToken: string,\n params: subscriptions.PauseSubscriptionParams,\n ) => {\n const body: {\n next_bill_date?: string;\n number_of_orders?: number;\n } = {};\n if (params.nextBillDate != null)\n body.next_bill_date = params.nextBillDate;\n if (params.numberOfOrders != null)\n body.number_of_orders = params.numberOfOrders;\n const response = await portalTenant.subscriptionsPause({\n client,\n path: { token: subscriptionToken },\n body,\n });\n return mapSubscriptionDetail(response);\n },\n\n resumeSubscription: async (\n subscriptionToken: string,\n params: subscriptions.ResumeSubscriptionParams,\n ) => {\n const body = params.nextBillDate\n ? { next_bill_date: params.nextBillDate }\n : undefined;\n const response = await portalTenant.subscriptionsResume({\n client,\n path: { token: subscriptionToken },\n body,\n });\n return mapSubscriptionDetail(response);\n },\n\n skipSubscription: async (\n subscriptionToken: string,\n _params: subscriptions.SkipSubscriptionParams,\n ) => {\n const response = await portalTenant.subscriptionsSkip({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n cancelSubscription: async (\n subscriptionToken: string,\n _customerId?: number,\n ) => {\n const response = await portalTenant.subscriptionsCancel({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n reactivateSubscription: async (\n subscriptionToken: string,\n params: subscriptions.ReactivateSubscriptionParams,\n ) => {\n const response = await portalTenant.subscriptionsReactivate({\n client,\n path: { token: subscriptionToken },\n body:\n params.address_id != null\n ? { address_id: params.address_id }\n : undefined,\n });\n return mapSubscriptionDetail(response);\n },\n\n retrySubscription: async (subscriptionToken: string) => {\n const response = await portalTenant.subscriptionsRetry({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n fetchFailedCycleWaiverPreview: async (subscriptionToken: string) => {\n const response = await portalTenant.subscriptionsFailedCycleWaiverPreview(\n {\n client,\n path: { token: subscriptionToken },\n },\n );\n assertSharedFailedCycleWaiverPreview(response);\n return response;\n },\n\n waiveFailedCycle: async (subscriptionToken: string) => {\n const response = await portalTenant.subscriptionsFailedCycleWaiverCreate({\n client,\n path: { token: subscriptionToken },\n });\n return mapSubscriptionDetail(response);\n },\n\n updateSubscriptionInfo: async (\n subscriptionToken: string,\n body: Partial<\n Pick<\n subscriptions.UpdateSubscriptionInfoBody,\n | \"payment_method_id\"\n | \"quantity\"\n | \"address_id\"\n | \"next_bill_date\"\n | \"auto_apply_points\"\n >\n >,\n ) => {\n const subscription: {\n payment_method_id?: number;\n quantity?: number;\n address_id?: number;\n next_bill_date?: string;\n auto_apply_points?: boolean;\n } = {};\n if (body.payment_method_id != null) {\n subscription.payment_method_id = body.payment_method_id;\n }\n if (body.quantity != null) {\n subscription.quantity = body.quantity;\n }\n if (body.address_id != null) {\n subscription.address_id = body.address_id;\n }\n if (body.next_bill_date != null) {\n subscription.next_bill_date = body.next_bill_date;\n }\n // `!= null` rather than `!== undefined`, matching every sibling above.\n // Both let an explicit `false` through, which is what turning the setting\n // off depends on; a truthiness check is what would drop it.\n if (body.auto_apply_points != null) {\n subscription.auto_apply_points = body.auto_apply_points;\n }\n const response = await portalTenant.subscriptionsUpdate({\n client,\n path: { token: subscriptionToken },\n body: { subscription },\n });\n return mapSubscriptionDetail(response);\n },\n };\n}\n","// Import shape copied verbatim from subscriptions-api-adapter.ts, the\n// neighbour the AGENTS contract names as the pattern to follow.\nimport * as portalTenant from \"@fluid-app/portal-tenant-api-client/sdk\";\nimport type { PortalTenantHeyApiClient } from \"@fluid-app/portal-tenant-api-client/client\";\nimport { isApiError, toApiErrorBody } from \"@fluid-app/api-client-core\";\nimport {\n BundleMembershipConflictError,\n type AutoApplyPointsApi,\n type AutoApplyPointsWriteResult,\n} from \"@fluid-app/subscriptions-core\";\n\n/**\n * Whether a thrown value is the server's settled-out bundle conflict.\n *\n * isApiError alone cannot answer this: it narrows `body` to\n * `Record<string, unknown> | null`, which leaves `body.error` as `unknown`.\n * toApiErrorBody is the repo's helper for that nested-envelope narrowing.\n * Only a string `code` counts, because anything else is not this failure and\n * must not select the retry path.\n */\nfunction isBundleMembershipConflict(error: unknown): boolean {\n if (!isApiError(error) || error.status !== 409) return false;\n\n const envelope = toApiErrorBody(error.body?.error);\n return envelope?.code === \"bundle_membership_conflict\";\n}\n\n/**\n * The portal's implementation of the auto-apply-points write.\n *\n * Owns transport, request mapping, response mapping, and mapping only\n * 409-plus-bundle_membership_conflict to the typed domain error. Every other\n * failure passes through generic.\n */\nexport function createAutoApplyPointsApiAdapter(\n client: PortalTenantHeyApiClient,\n): AutoApplyPointsApi {\n return {\n async updateAutoApplyPoints({ subscriptionToken, autoApplyPoints, scope }) {\n try {\n const response = await portalTenant.subscriptionsUpdate({\n client,\n path: { token: subscriptionToken },\n body: {\n subscription: {\n auto_apply_points: autoApplyPoints,\n auto_apply_points_scope: scope,\n },\n },\n });\n\n // The response's `subscription` resource deliberately does not cross\n // the port; the hook refetches detail, so a partial resource here\n // would be a second source of truth nothing reads.\n return {\n resolvedSubscriptionTokens:\n response.resolved_subscription_tokens ?? [],\n changedSubscriptionTokens: response.changed_subscription_tokens ?? [],\n } satisfies AutoApplyPointsWriteResult;\n } catch (error) {\n if (isBundleMembershipConflict(error)) {\n throw new BundleMembershipConflictError(\n \"Bundle membership changed while the write was in flight\",\n );\n }\n throw error;\n }\n },\n };\n}\n","import { useMemo, type ReactElement, type ReactNode } from \"react\";\nimport {\n AutoApplyPointsApiProvider,\n SubscriptionsCoreProvider,\n} from \"@fluid-app/subscriptions-core\";\nimport { usePortalTenantClient } from \"../providers/PortalTenantClientProvider\";\nimport { createPortalSubscriptionsAdapter } from \"../adapters/subscriptions-api-adapter\";\nimport { createAutoApplyPointsApiAdapter } from \"../adapters/auto-apply-points-api-adapter\";\n\nexport function PortalSubscriptionsApiProvider({\n children,\n}: {\n children: ReactNode;\n}): ReactElement {\n const client = usePortalTenantClient();\n\n const api = useMemo(() => createPortalSubscriptionsAdapter(client), [client]);\n // Memoized so a re-render does not hand consumers a new port identity,\n // which would invalidate every dependent memo downstream.\n const autoApplyPointsApi = useMemo(\n () => createAutoApplyPointsApiAdapter(client),\n [client],\n );\n\n return (\n <SubscriptionsCoreProvider api={api}>\n <AutoApplyPointsApiProvider value={autoApplyPointsApi}>\n {children}\n </AutoApplyPointsApiProvider>\n </SubscriptionsCoreProvider>\n );\n}\n","import type { BundlesApi } from \"@fluid-app/subscriptions-core\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport type { PortalTenantHeyApiClient } from \"@fluid-app/portal-tenant-api-client/client\";\nimport * as portalTenant from \"@fluid-app/portal-tenant-api-client/sdk\";\nimport { mapDetailSubscription } from \"./subscriptions-api-adapter\";\n\ntype BffBundleListResponse = NonNullable<\n Awaited<ReturnType<typeof portalTenant.subscriptionBundlesList>>\n>;\ntype BffBundle = NonNullable<\n BffBundleListResponse[\"subscription_bundles\"]\n>[number];\n\ntype BffSubscriptionInBundle = NonNullable<BffBundle[\"subscriptions\"]>[number];\n\nfunction mapAddress(\n bff: BffBundle[\"address\"],\n): subscriptions.SubscriptionDetailAddress | null {\n if (!bff) return null;\n return {\n id: bff.id ?? 0,\n name: bff.name ?? null,\n address1: bff.address1 ?? \"\",\n address2: bff.address2 ?? null,\n city: bff.city ?? \"\",\n state: bff.state ?? \"\",\n subdivision_code: null,\n postal_code: bff.postal_code ?? \"\",\n country_code: bff.country_code ?? null,\n default: false,\n };\n}\n\nfunction mapVolumeRep(\n bff: BffBundle[\"volume_rep\"],\n): subscriptions.BundleVolumeRep | null {\n if (!bff) return null;\n return {\n id: bff.id ?? 0,\n email: bff.email ?? null,\n full_name: bff.full_name ?? null,\n image_url: bff.image_url ?? null,\n };\n}\n\nfunction mapBundle(bff: BffBundle): subscriptions.Bundle {\n return {\n next_bill_date: bff.next_bill_date ?? null,\n subscription_count: bff.subscription_count ?? 0,\n address: mapAddress(bff.address),\n volume_rep: mapVolumeRep(bff.volume_rep),\n subscriptions: (bff.subscriptions ?? []).map((s) =>\n // The bundle's subscriptions field uses the same Subscription schema as\n // the subscriptions_show endpoint, so the existing detail mapper works\n // unchanged.\n mapDetailSubscription(s as BffSubscriptionInBundle),\n ),\n };\n}\n\nexport function createPortalBundlesAdapter(\n client: PortalTenantHeyApiClient,\n): BundlesApi {\n return {\n fetchBundles: async () => {\n const response = await portalTenant.subscriptionBundlesList({ client });\n return (response.subscription_bundles ?? []).map(mapBundle);\n },\n\n createBundle: async (params: subscriptions.CreateBundleParams) => {\n const bundle: {\n subscription_tokens: string[];\n next_bill_date: string;\n address_id?: number | null;\n volume_rep_id?: number | null;\n } = {\n subscription_tokens: params.subscription_tokens,\n next_bill_date: params.next_bill_date,\n };\n if (params.address_id !== undefined)\n bundle.address_id = params.address_id;\n if (params.volume_rep_id !== undefined)\n bundle.volume_rep_id = params.volume_rep_id;\n\n const response = await portalTenant.subscriptionBundlesCreate({\n client,\n body: { bundle },\n });\n const bff = response.subscription_bundle;\n if (!bff) {\n throw new Error(\n \"BFF returned a successful response but bundle data was missing\",\n );\n }\n return mapBundle(bff);\n },\n };\n}\n","import { useMemo, type ReactElement, type ReactNode } from \"react\";\nimport { BundlesCoreProvider } from \"@fluid-app/subscriptions-core\";\nimport { usePortalTenantClient } from \"../providers/PortalTenantClientProvider\";\nimport { createPortalBundlesAdapter } from \"../adapters/bundles-api-adapter\";\n\nexport function PortalBundlesApiProvider({\n children,\n}: {\n children: ReactNode;\n}): ReactElement {\n const client = usePortalTenantClient();\n const api = useMemo(() => createPortalBundlesAdapter(client), [client]);\n return <BundlesCoreProvider api={api}>{children}</BundlesCoreProvider>;\n}\n","import type { Provider } from \"react\";\nimport { createTranslationContext } from \"@fluid-app/i18n/translation-api-context-factory\";\nimport type { TranslationApi } from \"@fluid-app/i18n/translation-api\";\nimport type { SubscriptionsDict } from \"./translation-dictionary\";\n\nconst { Provider: SubscriptionsProvider, useTranslation } =\n createTranslationContext<SubscriptionsDict>(\"Subscriptions\");\n\nexport const SubscriptionsTranslationProvider: Provider<TranslationApi<SubscriptionsDict> | null> =\n SubscriptionsProvider;\nexport const useSubscriptionsTranslation = useTranslation;\n","import { useMemo, type ReactNode } from \"react\";\nimport { useActiveLocale } from \"@fluid-app/i18n/locale-context\";\nimport { useDomainDict } from \"@fluid-app/i18n/use-domain-dict\";\nimport {\n subscriptionsDomain,\n createSubscriptionsTranslationAdapter,\n} from \"@fluid-app/subscriptions-core/translation-adapter\";\nimport { SubscriptionsTranslationProvider } from \"@fluid-app/subscriptions-core/translation-api-context\";\n\nexport function SubscriptionsTranslationBridge({\n children,\n}: {\n children: ReactNode;\n}): React.JSX.Element {\n const { locale } = useActiveLocale();\n const dict = useDomainDict(subscriptionsDomain, locale);\n const api = useMemo(\n () => createSubscriptionsTranslationAdapter(locale, dict),\n [locale, dict],\n );\n return (\n <SubscriptionsTranslationProvider value={api}>\n {children}\n </SubscriptionsTranslationProvider>\n );\n}\n","import { isThreeDsRequiredCreate } from \"@fluid-app/portal-core/pay-types\";\nimport type {\n CreatePaymentMethodResponse,\n ThreeDsRequiredCreateResult,\n} from \"@fluid-app/portal-core/pay-types\";\n\n/**\n * Build the subscription create-payment-method onSuccess handler. On\n * three_ds_required it hands off to the 3DS flow (no bind/close — begin()\n * resolves at modal-open). On a created PM it runs the legacy created path with\n * the new payment method id (the caller routes dropdown-vs-banner inside\n * onCreated).\n */\nexport function buildSubscriptionCardAddSuccess(deps: {\n begin: (created: ThreeDsRequiredCreateResult) => Promise<void>;\n onCreated: (paymentMethodId: number) => void;\n}) {\n return async (response: CreatePaymentMethodResponse) => {\n if (isThreeDsRequiredCreate(response)) {\n await deps.begin(response);\n return;\n }\n deps.onCreated(response.payment_method.id);\n };\n}\n","import type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport type { SubscriptionsDict } from \"@fluid-app/subscriptions-core/translation-dictionary\";\nimport type { TranslationApi } from \"@fluid-app/i18n/translation-api\";\n\nexport type T = TranslationApi<SubscriptionsDict>[\"t\"];\n\nconst UNIT_KEYS: Record<string, { singular: string; plural: string }> = {\n day: { singular: \"unit_day\", plural: \"unit_days\" },\n week: { singular: \"unit_week\", plural: \"unit_weeks\" },\n month: { singular: \"unit_month\", plural: \"unit_months\" },\n year: { singular: \"unit_year\", plural: \"unit_years\" },\n};\n\nfunction translatedUnit(unit: string, plural: boolean, t: T): string {\n const keys = UNIT_KEYS[unit.toLowerCase()];\n if (!keys) return unit;\n return t((plural ? keys.plural : keys.singular) as \"unit_day\");\n}\n\nexport type FilterKey = \"all\" | \"active\" | \"paused\" | \"cancelled\";\n\nexport type StatusKind =\n | \"active\"\n | \"paused\"\n | \"cancelled\"\n | \"pending\"\n | \"past_due\";\n\nexport interface MappedStatus {\n kind: StatusKind;\n label: string;\n}\n\n/** Status label keys — all non-parameterized so they can be passed to `t()` with no args. */\ntype StatusLabelKey =\n | \"list_status_active\"\n | \"list_status_paused\"\n | \"list_status_cancelled\"\n | \"list_status_completed\"\n | \"list_status_past_due\"\n | \"list_status_pending\";\n\n// US `canceled` and UK `cancelled` fold together; `past_due`/`past-due` too.\nconst STATUS_LOOKUP: Record<\n string,\n { kind: StatusKind; labelKey: StatusLabelKey }\n> = {\n active: { kind: \"active\", labelKey: \"list_status_active\" },\n paused: { kind: \"paused\", labelKey: \"list_status_paused\" },\n cancelled: { kind: \"cancelled\", labelKey: \"list_status_cancelled\" },\n canceled: { kind: \"cancelled\", labelKey: \"list_status_cancelled\" },\n completed: { kind: \"cancelled\", labelKey: \"list_status_completed\" },\n past_due: { kind: \"past_due\", labelKey: \"list_status_past_due\" },\n \"past-due\": { kind: \"past_due\", labelKey: \"list_status_past_due\" },\n pending: { kind: \"pending\", labelKey: \"list_status_pending\" },\n};\n\n/**\n * Map a raw subscription `status` string from the BFF onto our internal\n * status vocabulary. Unknown statuses pass through with `kind: \"pending\"`\n * and a capitalized raw label — never synthesize a colored pill that\n * pretends to be real status data.\n */\nexport function mapStatus(status: string, t: T): MappedStatus {\n const entry = STATUS_LOOKUP[(status || \"\").toLowerCase()];\n if (entry) return { kind: entry.kind, label: t(entry.labelKey) };\n return {\n kind: \"pending\",\n label: status ? status.charAt(0).toUpperCase() + status.slice(1) : \"—\",\n };\n}\n\n/**\n * Sort priority — past-due first (urgent), cancelled last. Used to order\n * subscriptions within the active grid before the cancelled section.\n */\nexport const STATUS_PRIORITY: Record<StatusKind, number> = {\n past_due: 0,\n active: 1,\n pending: 2,\n paused: 3,\n cancelled: 4,\n};\n\n/**\n * \"Active\" group = anything still actionable, including paused (can be\n * resumed). The cancelled section is reserved for cancelled subs only —\n * those are truly done and can't be acted on beyond viewing.\n */\nexport function isActiveKind(kind: StatusKind): boolean {\n return (\n kind === \"active\" ||\n kind === \"past_due\" ||\n kind === \"pending\" ||\n kind === \"paused\"\n );\n}\n\n/**\n * Filter predicate — status-only, does not need translation so we use a\n * stripped-down identity helper that satisfies the `T` signature.\n */\nexport function filterPredicate(\n filter: FilterKey,\n sub: subscriptions.SubscriptionListItem,\n): boolean {\n if (filter === \"all\") return true;\n // We only need the `kind` for filter classification — mapStatus's `t`\n // call for the label is irrelevant here. Cast a no-op identity so this\n // stays a pure filter without a translation dependency.\n const kind = mapStatusKindOnly(sub.status);\n // past_due belongs in Active — it's still actionable (user needs to fix\n // payment) and renders in the active grid by default. Excluding it here\n // would make the most-urgent subs vanish when the Active pill is selected.\n if (filter === \"active\")\n return kind === \"active\" || kind === \"pending\" || kind === \"past_due\";\n if (filter === \"paused\") return kind === \"paused\";\n if (filter === \"cancelled\") return kind === \"cancelled\";\n return true;\n}\n\n/** Lightweight status-kind lookup that doesn't need `t`. */\nexport function mapStatusKindOnly(status: string): StatusKind {\n const entry = STATUS_LOOKUP[(status || \"\").toLowerCase()];\n return entry?.kind ?? \"pending\";\n}\n\nexport function countByFilter(\n list: subscriptions.SubscriptionListItem[],\n): Record<FilterKey, number> {\n return {\n all: list.length,\n active: list.filter((s) => filterPredicate(\"active\", s)).length,\n paused: list.filter((s) => filterPredicate(\"paused\", s)).length,\n cancelled: list.filter((s) => filterPredicate(\"cancelled\", s)).length,\n };\n}\n\nexport function formatCadence(\n plan: subscriptions.SubscriptionListPlan,\n t: T,\n): string {\n const interval = plan.billing_interval;\n const unit = plan.billing_interval_unit;\n if (interval === 1 && unit === \"day\") return t(\"list_cadence_daily\");\n if (interval === 1 && unit === \"month\") return t(\"list_cadence_monthly\");\n if (interval === 1 && unit === \"week\") return t(\"list_cadence_weekly\");\n if (interval === 1 && unit === \"year\") return t(\"list_cadence_yearly\");\n if (interval === 3 && unit === \"month\") return t(\"list_cadence_quarterly\");\n if (interval > 1) {\n return t(\"list_cadence_every_n_units\", {\n n: String(interval),\n unit: translatedUnit(unit, true, t),\n });\n }\n return t(\"list_cadence_every_unit\", {\n unit: translatedUnit(unit, false, t),\n });\n}\n\nexport function pricingSuffix(\n plan: subscriptions.SubscriptionListPlan,\n t: T,\n): string {\n const unit = plan.billing_interval_unit;\n const interval = plan.billing_interval;\n if (interval === 1) {\n if (unit === \"month\") return t(\"list_price_per_month\");\n if (unit === \"week\") return t(\"list_price_per_week\");\n if (unit === \"year\") return t(\"list_price_per_year\");\n if (unit === \"day\") return t(\"list_price_per_day\");\n }\n return t(\"list_price_every_n_units\", {\n n: String(interval),\n unit: translatedUnit(unit, interval > 1, t),\n });\n}\n\nexport function formatLongDate(iso: string): string {\n // BFF date fields come in two shapes: pure calendar dates (\"2026-05-10\",\n // e.g. Bundle.next_bill_date) and datetimes (\"2026-05-10T07:00:00Z\", e.g.\n // Subscription.next_billing_date). For both we want to render the calendar\n // date the API meant, NOT shift it via timezone math — `new Date(...)` +\n // `toLocaleDateString()` would render UTC-midnight calendar dates as the\n // previous day for any user west of UTC. Pull Y/M/D from the front of the\n // string and format in UTC to keep the date stable across timezones.\n try {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(iso);\n if (!match) return iso;\n const y = Number(match[1]);\n const m = Number(match[2]);\n const d = Number(match[3]);\n if (!y || !m || !d) return iso;\n const date = new Date(Date.UTC(y, m - 1, d));\n return date.toLocaleDateString(undefined, {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: \"UTC\",\n });\n } catch {\n return iso;\n }\n}\n\n/**\n * Render the per-cycle subscription bill amount (`price × quantity`).\n *\n * `sub.price` (mapped from the BFF's `total`) is the per-unit price, not the\n * line total — the variant column it ultimately reads from is a plain\n * decimal column, and the detail page also computes `price * quantity` for\n * its bill rows. At qty=1 the multiplication is a no-op so the bug stayed\n * hidden until qty>1 surfaced the mismatch with the detail view.\n */\nexport function formatPrice(sub: subscriptions.SubscriptionListItem): string {\n return (sub.price * (sub.quantity ?? 1)).toFixed(2);\n}\n\n/** Detail-shape counterpart for bundle member rows. */\nexport function formatDetailPrice(\n sub: subscriptions.SubscriptionDetailSubscription,\n): string {\n return (sub.price * (sub.quantity ?? 1)).toFixed(2);\n}\n\nexport interface DetailDiscountLine {\n code: string;\n label: string;\n amountLabel: string;\n}\n\n/**\n * Build the discount line shown beneath a detail subscription's price —\n * the active attached discount's code plus the renewal discount amount.\n * Returns `null` when no active attachment exists or the computed amount\n * is not positive. Mirrors `formatDetailPrice`'s no-symbol formatting:\n * the portal adapter currently sets `currency.symbol` to `null`, so the\n * amount renders bare unless a symbol is actually present.\n */\nexport function detailDiscountLine(\n sub: subscriptions.SubscriptionDetailSubscription,\n t: T,\n): DetailDiscountLine | null {\n const attachment = sub.subscription_discounts?.find(\n (row) => row.removed_at == null,\n );\n const amount = sub.renewal_discount_total ?? 0;\n if (!attachment || amount <= 0) return null;\n\n return {\n code: attachment.discount.code,\n label: t(\"discount\"),\n amountLabel: `-${sub.currency?.symbol ?? \"\"}${amount.toFixed(2)}`,\n };\n}\n\nexport interface CycleProgress {\n /** 0..1 fraction of the cycle that has elapsed. */\n progress: number;\n /** \"Last bill 18 days ago\" — friendly label for the start of the cycle. */\n startLabel: string;\n /** \"Bills in 12 days\" — friendly label for the end of the cycle. */\n endLabel: string;\n}\n\n/**\n * Compute progress through a billing cycle. Returns `null` when either\n * date is missing, unparseable, or `end <= start`. `now` is injectable\n * for tests.\n */\nexport function computeCycleProgress(\n last: string | null,\n next: string | null,\n t: T,\n now: number = Date.now(),\n): CycleProgress | null {\n if (!last || !next) return null;\n const start = new Date(last).getTime();\n const end = new Date(next).getTime();\n if (!Number.isFinite(start) || !Number.isFinite(end) || end <= start) {\n return null;\n }\n const raw = (now - start) / (end - start);\n const progress = Math.max(0, Math.min(1, raw));\n return {\n progress,\n startLabel: friendlyDaysAgo(start, t, now),\n endLabel: friendlyDaysAhead(end, t, now),\n };\n}\n\nexport function friendlyDaysAgo(\n start: number,\n t: T,\n now: number = Date.now(),\n): string {\n const days = Math.max(0, Math.round((now - start) / (1000 * 60 * 60 * 24)));\n if (days === 0) return t(\"list_last_bill_today\");\n if (days === 1) return t(\"list_last_bill_yesterday\");\n return t(\"list_last_bill_n_days_ago\", { n: String(days) });\n}\n\nexport function friendlyDaysAhead(\n end: number,\n t: T,\n now: number = Date.now(),\n): string {\n const days = Math.round((end - now) / (1000 * 60 * 60 * 24));\n if (days < 0)\n return t(\"list_bill_overdue_n_days\", { n: String(Math.abs(days)) });\n if (days === 0) return t(\"list_bills_today\");\n if (days === 1) return t(\"list_bills_tomorrow\");\n return t(\"list_bills_in_n_days\", { n: String(days) });\n}\n","import { type JSX, useMemo, useState } from \"react\";\nimport {\n type subscriptions,\n useInfiniteSubscriptions,\n} from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { ImageOff, Package, Play, Repeat, AlertCircle } from \"lucide-react\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbList,\n BreadcrumbPage,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport { ScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport { MobileBottomSheet } from \"@fluid-app/ui-components/components/MobileBottomSheet\";\nimport {\n type CycleProgress as CycleProgressData,\n type FilterKey,\n type T,\n STATUS_PRIORITY,\n computeCycleProgress,\n countByFilter,\n detailDiscountLine,\n filterPredicate,\n formatCadence,\n formatDetailPrice,\n formatLongDate,\n formatPrice,\n isActiveKind,\n mapStatus,\n pricingSuffix,\n} from \"./portal-subscriptions-list-helpers\";\n\nexport type { FilterKey } from \"./portal-subscriptions-list-helpers\";\n\nconst UNIT_KEYS: Record<string, { singular: string; plural: string }> = {\n day: { singular: \"unit_day\", plural: \"unit_days\" },\n week: { singular: \"unit_week\", plural: \"unit_weeks\" },\n month: { singular: \"unit_month\", plural: \"unit_months\" },\n year: { singular: \"unit_year\", plural: \"unit_years\" },\n};\n\ninterface PortalSubscriptionsListProps {\n customerId: number | undefined;\n isLoadingCustomer?: boolean;\n onSubscriptionClick: (token: string) => void;\n onResume?: (sub: subscriptions.SubscriptionListItem) => void;\n onBundleClick?: () => void;\n bundles?: subscriptions.Bundle[];\n}\n\nconst EMPTY_BUNDLES: subscriptions.Bundle[] = [];\n\nexport function PortalSubscriptionsList({\n customerId,\n isLoadingCustomer,\n onSubscriptionClick,\n onResume,\n onBundleClick,\n bundles = EMPTY_BUNDLES,\n}: PortalSubscriptionsListProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const [filter, setFilter] = useState<FilterKey>(\"all\");\n const {\n data,\n isLoading,\n isError,\n refetch,\n fetchNextPage,\n hasNextPage,\n isFetchingNextPage,\n } = useInfiniteSubscriptions(\n { customerId, limit: 12 },\n { enabled: !!customerId && !isLoadingCustomer },\n );\n\n const list = useMemo(\n () => data?.pages.flatMap((p) => p.subscriptions) ?? [],\n [data],\n );\n const counts = useMemo(() => countByFilter(list), [list]);\n const filteredList = useMemo(\n () => list.filter((s) => filterPredicate(filter, s)),\n [list, filter],\n );\n\n // Real bundles only — singletons (size 1) come back from the bundles\n // endpoint too but they aren't \"bundled\" from the user's perspective.\n const relevantBundles = useMemo(\n () => bundles.filter((b) => b.subscription_count > 1),\n [bundles],\n );\n const bundledTokens = useMemo(() => {\n const tokens = new Set<string>();\n for (const bundle of relevantBundles) {\n for (const sub of bundle.subscriptions) {\n if (sub.subscription_token) tokens.add(sub.subscription_token);\n }\n }\n return tokens;\n }, [relevantBundles]);\n\n // Bundle cards only render in the \"all\" view because a bundle is a\n // billing-time grouping, not a status. Status-filtered views (active /\n // paused / cancelled) show every member sub as an individual card so the\n // filter answer stays direct.\n const showBundleSection = filter === \"all\" && relevantBundles.length > 0;\n\n const { activeSubs, inactiveSubs } = useMemo(() => {\n const sorted = filteredList\n .slice()\n .sort(\n (a, b) =>\n STATUS_PRIORITY[mapStatus(a.status, t).kind] -\n STATUS_PRIORITY[mapStatus(b.status, t).kind],\n );\n const activeCandidates = sorted.filter((s) =>\n isActiveKind(mapStatus(s.status, t).kind),\n );\n return {\n activeSubs: showBundleSection\n ? activeCandidates.filter(\n (s) => !bundledTokens.has(s.subscription_token),\n )\n : activeCandidates,\n inactiveSubs: sorted.filter(\n (s) => !isActiveKind(mapStatus(s.status, t).kind),\n ),\n };\n }, [filteredList, t, showBundleSection, bundledTokens]);\n\n return (\n <>\n <ScreenHeaderBreadcrumbs>\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n {t(\"breadcrumb\")}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n </ScreenHeaderBreadcrumbs>\n <div className=\"relative\">\n <div className=\"relative mx-auto max-w-4xl px-5 pt-8 pb-20 md:px-8\">\n <h1 className=\"text-foreground text-xl font-bold tracking-tight md:text-2xl\">\n {t(\"list_title\")}\n </h1>\n\n {list.length > 0 && (\n <FilterPills\n active={filter}\n counts={counts}\n onChange={setFilter}\n onBundleClick={onBundleClick}\n t={t}\n />\n )}\n\n {isLoading || isLoadingCustomer ? (\n <div className=\"mt-8 grid grid-cols-1 gap-5 md:grid-cols-2\">\n {Array(4)\n .fill(0)\n .map((_, i) => (\n <SubscriptionCardSkeleton key={i} />\n ))}\n </div>\n ) : isError ? (\n <ErrorState onRetry={() => refetch()} t={t} />\n ) : filteredList.length === 0 ? (\n <EmptyState filtered={filter !== \"all\" && list.length > 0} t={t} />\n ) : (\n <>\n {(showBundleSection || activeSubs.length > 0) && (\n // Single grid for bundle cards + regular subscription cards so\n // they share rows. CSS Grid's default `align-items: stretch`\n // makes every cell in the same row match heights, which is\n // what we want — the tallest card in a row sets the row\n // height and the others stretch to match.\n <div className=\"mt-6 grid grid-cols-1 gap-5 md:grid-cols-2\">\n {showBundleSection &&\n relevantBundles.map((bundle, i) => (\n <BundleCard\n key={`bundle-${i}-${bundle.next_bill_date}`}\n bundle={bundle}\n onSubscriptionClick={onSubscriptionClick}\n t={t}\n />\n ))}\n {activeSubs.map((sub) => (\n <SubscriptionCard\n key={sub.id}\n sub={sub}\n onClick={() =>\n onSubscriptionClick(sub.subscription_token)\n }\n onResume={onResume ? () => onResume(sub) : undefined}\n t={t}\n />\n ))}\n </div>\n )}\n\n {inactiveSubs.length > 0 && (\n <div className={activeSubs.length > 0 ? \"mt-10\" : \"mt-6\"}>\n <div className=\"text-muted-foreground mb-2 px-1 text-xs font-semibold\">\n {t(\"list_cancelled_section_label\", {\n n: String(inactiveSubs.length),\n })}\n </div>\n <div className=\"space-y-3\">\n {inactiveSubs.map((sub) => (\n <InactiveSubscriptionRow\n key={sub.id}\n sub={sub}\n onClick={() =>\n onSubscriptionClick(sub.subscription_token)\n }\n t={t}\n />\n ))}\n </div>\n </div>\n )}\n </>\n )}\n\n {hasNextPage && (\n <div className=\"mt-6 flex justify-center\">\n <button\n type=\"button\"\n onClick={() => fetchNextPage()}\n disabled={isFetchingNextPage}\n className=\"ring-border text-foreground hover:bg-muted inline-flex items-center gap-1 rounded-md bg-transparent px-3 py-1.5 text-xs font-bold ring-1 transition-all disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {isFetchingNextPage ? t(\"list_loading\") : t(\"list_load_more\")}\n </button>\n </div>\n )}\n </div>\n </div>\n </>\n );\n}\n\n// ─── Filter pills ─────────────────────────────────────────────────────────\n\nconst FILTER_KEYS: ReadonlyArray<{\n key: FilterKey;\n labelKey: \"all\" | \"active\" | \"list_filter_paused\" | \"list_filter_cancelled\";\n}> = [\n { key: \"all\", labelKey: \"all\" },\n { key: \"active\", labelKey: \"active\" },\n { key: \"paused\", labelKey: \"list_filter_paused\" },\n { key: \"cancelled\", labelKey: \"list_filter_cancelled\" },\n];\n\nfunction FilterPills({\n active,\n counts,\n onChange,\n onBundleClick,\n t,\n}: {\n active: FilterKey;\n counts: Record<FilterKey, number>;\n onChange: (k: FilterKey) => void;\n onBundleClick?: () => void;\n t: T;\n}): JSX.Element {\n return (\n <div className=\"-mx-1 mt-5 flex flex-wrap items-center gap-1.5 px-1\">\n {FILTER_KEYS.map((f) => {\n const isActive = f.key === active;\n const count = counts[f.key];\n return (\n <button\n key={f.key}\n type=\"button\"\n onClick={() => onChange(f.key)}\n className={`inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-bold transition-all ${\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"ring-border text-foreground hover:bg-muted bg-transparent ring-1\"\n }`}\n >\n {t(f.labelKey)}\n <span\n className={`text-xs tabular-nums ${\n isActive\n ? \"text-primary-foreground/70\"\n : \"text-muted-foreground\"\n }`}\n >\n {count}\n </span>\n </button>\n );\n })}\n {/* Bundling requires at least 2 subscriptions to merge — hide the\n button when the user has zero or one so they can't reach a step 1\n where the Next button is permanently disabled. Also hide when the\n tenant company has bundling disabled (the screen passes\n onBundleClick=undefined in that case). */}\n {counts.all >= 2 && onBundleClick && (\n <button\n type=\"button\"\n onClick={onBundleClick}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 ml-auto inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-bold transition-all\"\n >\n {t(\"list_bundle_cta\")}\n </button>\n )}\n </div>\n );\n}\n\n// ─── Bundle card ───────────────────────────────────────────────────────────\n// Renders a runtime bundle (a customer + address + bill date grouping) as a\n// single card containing each member subscription as a clickable row plus a\n// shared bill summary (date + summed amount). Members navigate to their\n// individual detail screens — bundle-level edit is a future affordance.\n\n// Cap inline member rows so every bundle card has the same height regardless\n// of how many subscriptions are in the bundle. Overflow lives behind a\n// \"+N more\" popover anchored to the card.\nconst BUNDLE_INLINE_LIMIT = 2;\n\nfunction BundleCard({\n bundle,\n onSubscriptionClick,\n t,\n}: {\n bundle: subscriptions.Bundle;\n onSubscriptionClick: (token: string) => void;\n t: T;\n}): JSX.Element {\n const [popoverOpen, setPopoverOpen] = useState(false);\n const { isMobile } = useSidebar();\n const total = bundle.subscriptions.reduce(\n (sum, s) => sum + s.price * (s.quantity ?? 1),\n 0,\n );\n const nextBillLong = bundle.next_bill_date\n ? formatLongDate(bundle.next_bill_date)\n : null;\n\n const inlineMembers = bundle.subscriptions.slice(0, BUNDLE_INLINE_LIMIT);\n const overflowCount = bundle.subscriptions.length - inlineMembers.length;\n\n const handleMemberClick = (token: string) => {\n onSubscriptionClick(token);\n setPopoverOpen(false);\n };\n\n return (\n <div className=\"ring-border hover:ring-foreground/10 relative flex flex-col gap-4 rounded-2xl bg-transparent p-5 shadow-sm ring-1 transition-all duration-300 hover:shadow-lg\">\n {/* Bundle header */}\n <div className=\"flex items-center gap-2\">\n <div className=\"bg-muted flex size-7 items-center justify-center rounded-full\">\n <Package className=\"text-foreground size-4\" strokeWidth={2} />\n </div>\n <div className=\"text-foreground text-xs font-bold\">\n {t(\"list_bundle_card_label\", {\n n: String(bundle.subscription_count),\n })}\n </div>\n </div>\n\n {/* Inline member rows (capped) */}\n <div className=\"flex flex-col\">\n {inlineMembers.map((sub) => (\n <BundleMemberRow\n key={sub.subscription_token}\n sub={sub}\n onClick={() => handleMemberClick(sub.subscription_token)}\n t={t}\n />\n ))}\n\n {overflowCount > 0 &&\n (isMobile ? (\n <>\n <button\n type=\"button\"\n onClick={() => setPopoverOpen(true)}\n className=\"text-muted-foreground hover:text-foreground focus-visible:ring-foreground/30 mt-1 inline-flex w-fit cursor-pointer items-center rounded-md px-2 py-1 text-xs font-bold transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n >\n {t(\"list_bundle_more_count\", { n: String(overflowCount) })}\n </button>\n <MobileBottomSheet\n open={popoverOpen}\n onOpenChange={setPopoverOpen}\n title={t(\"list_bundle_members_title\")}\n >\n <div className=\"flex flex-col px-2\">\n {bundle.subscriptions.map((sub) => (\n <BundleMemberRow\n key={sub.subscription_token}\n sub={sub}\n onClick={() => handleMemberClick(sub.subscription_token)}\n t={t}\n />\n ))}\n </div>\n </MobileBottomSheet>\n </>\n ) : (\n <Popover open={popoverOpen} onOpenChange={setPopoverOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground focus-visible:ring-foreground/30 mt-1 inline-flex w-fit cursor-pointer items-center rounded-md px-2 py-1 text-xs font-bold transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n >\n {t(\"list_bundle_more_count\", { n: String(overflowCount) })}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"bg-background ring-border w-80 rounded-2xl p-3 shadow-lg ring-1\"\n >\n <div className=\"text-muted-foreground px-2 pt-1 pb-2 text-xs font-bold uppercase\">\n {t(\"list_bundle_members_title\")}\n </div>\n <div className=\"flex max-h-80 flex-col overflow-y-auto\">\n {bundle.subscriptions.map((sub) => (\n <BundleMemberRow\n key={sub.subscription_token}\n sub={sub}\n onClick={() => handleMemberClick(sub.subscription_token)}\n t={t}\n />\n ))}\n </div>\n </PopoverContent>\n </Popover>\n ))}\n </div>\n\n {/* Shared bill summary — pushed to the bottom so the card height\n can stretch (auto-rows-fr) without the summary floating mid-card. */}\n <div className=\"bg-muted mt-auto rounded-xl px-4 py-3.5\">\n <div className=\"text-foreground text-sm font-bold\">\n {t(\"list_next_bill_label\")}\n </div>\n <div className=\"mt-3 grid grid-cols-2\">\n <div className=\"pr-4\">\n <div className=\"text-muted-foreground text-xs\">\n {t(\"list_bill_date\")}\n </div>\n <div className=\"text-foreground mt-1 text-base font-bold tracking-tight tabular-nums\">\n {nextBillLong ?? \"—\"}\n </div>\n </div>\n <div className=\"border-border border-l pl-4\">\n <div className=\"text-muted-foreground text-xs\">\n {t(\"list_bill_amount\")}\n </div>\n <div className=\"text-foreground mt-1 text-base font-bold tracking-tight tabular-nums\">\n {total.toFixed(2)}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction BundleMemberRow({\n sub,\n onClick,\n t,\n}: {\n sub: subscriptions.SubscriptionDetailSubscription;\n onClick: () => void;\n t: T;\n}): JSX.Element {\n const discountLine = detailDiscountLine(sub, t);\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"hover:bg-muted/60 focus-visible:ring-foreground/30 -mx-2 flex cursor-pointer items-center gap-3 rounded-lg p-2 text-left transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n >\n <div className=\"relative size-12 shrink-0\">\n {sub.variant.product.image_url ? (\n <img\n src={sub.variant.product.image_url}\n alt=\"\"\n className=\"ring-background size-12 rounded-lg bg-transparent object-cover ring-2\"\n />\n ) : (\n <div className=\"bg-muted ring-background text-muted-foreground flex size-12 items-center justify-center rounded-lg ring-2\">\n <ImageOff className=\"size-4\" strokeWidth={1.75} />\n </div>\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-foreground truncate text-xs font-bold\">\n {sub.variant.product.title || t(\"list_product_fallback\")}\n </div>\n <div className=\"text-muted-foreground truncate text-xs\">\n {bundleMemberCadence(sub.subscription_plan, t)}\n </div>\n </div>\n <div className=\"shrink-0 text-right\">\n <div className=\"text-foreground text-xs font-bold tabular-nums\">\n {formatDetailPrice(sub)}\n </div>\n {discountLine && (\n <div className=\"text-muted-foreground text-xs tabular-nums\">\n <span className=\"sr-only\">{discountLine.label} </span>\n {discountLine.code} {discountLine.amountLabel}\n </div>\n )}\n </div>\n </button>\n );\n}\n\n// `formatCadence` types its input to SubscriptionListPlan; bundle members are\n// SubscriptionDetailPlan which carries the same billing_interval fields.\n// Avoid an unsafe cast by re-implementing the small subset we need.\nfunction bundleMemberCadence(\n plan: { billing_interval: number; billing_interval_unit: string },\n t: T,\n): string {\n const { billing_interval: interval, billing_interval_unit: unit } = plan;\n if (interval === 1 && unit === \"day\") return t(\"list_cadence_daily\");\n if (interval === 1 && unit === \"month\") return t(\"list_cadence_monthly\");\n if (interval === 1 && unit === \"week\") return t(\"list_cadence_weekly\");\n if (interval === 1 && unit === \"year\") return t(\"list_cadence_yearly\");\n if (interval === 3 && unit === \"month\") return t(\"list_cadence_quarterly\");\n if (interval > 1) {\n const keys = UNIT_KEYS[unit.toLowerCase()];\n return t(\"list_cadence_every_n_units\", {\n n: String(interval),\n unit: keys ? t(keys.plural as \"unit_days\") : unit,\n });\n }\n const keys = UNIT_KEYS[unit.toLowerCase()];\n return t(\"list_cadence_every_unit\", {\n unit: keys ? t(keys.singular as \"unit_day\") : unit,\n });\n}\n\n// ─── Card ──────────────────────────────────────────────────────────────────\n\nfunction SubscriptionCard({\n sub,\n onClick,\n onResume,\n t,\n}: {\n sub: subscriptions.SubscriptionListItem;\n onClick: () => void;\n onResume?: () => void;\n t: T;\n}): JSX.Element {\n const status = mapStatus(sub.status, t);\n const isPaused = status.kind === \"paused\";\n const isCancelled = status.kind === \"cancelled\";\n const isPastDue = status.kind === \"past_due\";\n const cadence = formatCadence(sub.subscription_plan, t);\n const nextBillLong = sub.next_bill_date\n ? formatLongDate(sub.next_bill_date)\n : null;\n const lastBillLong = sub.last_bill_date\n ? formatLongDate(sub.last_bill_date)\n : null;\n const daysOverdue =\n isPastDue && sub.next_bill_date\n ? Math.max(\n 0,\n Math.round(\n (Date.now() - new Date(sub.next_bill_date).getTime()) /\n (1000 * 60 * 60 * 24),\n ),\n )\n : 0;\n const cycle = computeCycleProgress(sub.last_bill_date, sub.next_bill_date, t);\n const showCycle = cycle != null && !isPaused && !isCancelled && !isPastDue;\n\n return (\n <div\n className={`group has-[:focus-visible]:ring-foreground/30 relative flex flex-col gap-5 rounded-2xl p-5 ring-1 transition-all duration-300 hover:-translate-y-0.5 has-[:focus-visible]:ring-2 ${\n isPastDue\n ? \"from-destructive/10 via-destructive/[0.03] ring-destructive/15 hover:ring-destructive/30 bg-transparent bg-gradient-to-br to-transparent shadow-sm hover:shadow-lg\"\n : \"ring-foreground/5 hover:ring-foreground/10 bg-transparent shadow-sm hover:shadow-lg\"\n } ${isPaused || isCancelled ? \"opacity-90\" : \"\"}`}\n >\n <button\n type=\"button\"\n onClick={onClick}\n className=\"flex flex-1 cursor-pointer flex-col gap-5 text-left focus:outline-none\"\n >\n {/* Top: image + title */}\n <div className=\"flex items-start gap-4\">\n <Thumbnail\n product={sub.variant.product}\n muted={isPaused || isCancelled}\n t={t}\n />\n <div className=\"min-w-0 flex-1 pt-1\">\n <div className=\"text-foreground truncate text-base font-bold\">\n {sub.variant.product.title || t(\"list_product_fallback\")}\n </div>\n <div className=\"text-muted-foreground mt-0.5 text-sm\">\n {cadence}\n </div>\n {(isPaused || isCancelled || isPastDue) && (\n <div\n className={`mt-2 inline-flex items-center gap-1.5 text-xs font-semibold ${\n isPastDue ? \"text-destructive\" : \"text-muted-foreground/75\"\n }`}\n >\n <span\n className={`size-1.5 rounded-full ${\n isCancelled || isPastDue\n ? \"bg-destructive\"\n : \"bg-muted-foreground\"\n }`}\n />\n {status.label}\n </div>\n )}\n </div>\n </div>\n\n {/* Bill summary pinned to the bottom of the click area via mt-auto\n so when the card stretches (e.g. when a bundle in the same grid\n row is taller), empty space grows between the title and summary\n instead of below them. */}\n {isCancelled ? (\n <div className=\"bg-muted text-muted-foreground mt-auto rounded-xl px-4 py-3 text-sm font-semibold\">\n {status.label}\n </div>\n ) : (\n <div className=\"bg-muted mt-auto rounded-xl px-4 py-3.5\">\n <div\n className={`text-sm font-bold ${isPastDue ? \"text-destructive\" : \"text-foreground\"}`}\n >\n {isPastDue\n ? daysOverdue === 1\n ? t(\"list_bill_due_1_day_ago\")\n : daysOverdue > 0\n ? t(\"list_bill_due_n_days_ago\", {\n n: String(daysOverdue),\n })\n : t(\"list_bill_overdue\")\n : isPaused\n ? t(\"list_last_bill_label\")\n : t(\"list_next_bill_label\")}\n </div>\n <div className=\"mt-3 grid grid-cols-2\">\n <div className=\"pr-4\">\n <div className=\"text-muted-foreground text-xs\">\n {isPaused ? t(\"list_last_bill_date\") : t(\"list_bill_date\")}\n </div>\n <div\n className={`mt-1 text-base font-bold tracking-tight tabular-nums ${isPastDue ? \"text-destructive\" : \"text-foreground\"}`}\n >\n {(isPaused ? lastBillLong : nextBillLong) ?? \"—\"}\n </div>\n </div>\n <div className=\"border-border border-l pl-4\">\n <div className=\"text-muted-foreground text-xs\">\n {isPaused\n ? t(\"list_last_bill_amount\")\n : t(\"list_bill_amount\")}\n </div>\n <div className=\"text-foreground mt-1 text-base font-bold tracking-tight tabular-nums\">\n {formatPrice(sub)}\n </div>\n <div className=\"text-muted-foreground text-xs\">\n {pricingSuffix(sub.subscription_plan, t)}\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Cycle progress bar */}\n {showCycle && cycle && <CycleProgress cycle={cycle} />}\n </button>\n\n {/* Resume CTA */}\n {isPaused && (\n <button\n type=\"button\"\n onClick={onResume}\n disabled={!onResume}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 inline-flex w-full items-center justify-center gap-1.5 rounded-md py-2.5 text-xs font-bold transition-colors focus:outline-none disabled:cursor-not-allowed disabled:opacity-40\"\n >\n <Play className=\"size-3 fill-current\" strokeWidth={2.25} />\n {t(\"list_resume_cta\")}\n </button>\n )}\n </div>\n );\n}\n\n// ─── Cycle progress ───────────────────────────────────────────────────────\n\nfunction CycleProgress({ cycle }: { cycle: CycleProgressData }): JSX.Element {\n const pct = Math.round(cycle.progress * 100);\n return (\n <div>\n <div className=\"bg-muted relative h-1.5 overflow-hidden rounded-full\">\n <div\n className=\"bg-foreground absolute top-0 left-0 h-full rounded-full transition-all duration-500\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <div className=\"text-muted-foreground mt-2 flex items-center justify-between text-xs font-medium\">\n <span>{cycle.startLabel}</span>\n <span>{cycle.endLabel}</span>\n </div>\n </div>\n );\n}\n\n// ─── Inactive (condensed) row ─────────────────────────────────────────────\n\nfunction InactiveSubscriptionRow({\n sub,\n onClick,\n t,\n}: {\n sub: subscriptions.SubscriptionListItem;\n onClick: () => void;\n t: T;\n}): JSX.Element {\n const status = mapStatus(sub.status, t);\n const cadence = formatCadence(sub.subscription_plan, t);\n const detail = `${cadence} · ${status.label}`;\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"group ring-foreground/5 hover:ring-foreground/10 focus-visible:ring-foreground/30 flex w-full cursor-pointer items-center gap-3 rounded-2xl bg-transparent px-4 py-3 text-left shadow-sm ring-1 transition-all duration-300 hover:-translate-y-0.5 hover:shadow-lg focus-visible:ring-2 focus-visible:outline-none\"\n >\n <div className=\"relative size-10 shrink-0 opacity-60 saturate-50\">\n {sub.variant.product.image_url ? (\n <img\n src={sub.variant.product.image_url}\n alt=\"\"\n className=\"ring-background size-10 rounded-xl bg-transparent object-cover ring-[3px]\"\n />\n ) : (\n <div className=\"bg-muted ring-background text-muted-foreground flex size-10 items-center justify-center rounded-xl ring-[3px]\">\n <ImageOff className=\"size-4\" strokeWidth={1.75} />\n </div>\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-foreground truncate text-sm font-bold\">\n {sub.variant.product.title || t(\"list_product_fallback\")}\n </div>\n <div className=\"text-muted-foreground truncate text-xs\">{detail}</div>\n </div>\n </button>\n );\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\nfunction Thumbnail({\n product,\n muted,\n t,\n}: {\n product: subscriptions.SubscriptionListVariantProduct;\n muted?: boolean;\n t: T;\n}): JSX.Element {\n const wrapperClass = `relative size-24 shrink-0 transition-all ${muted ? \"saturate-50 opacity-60\" : \"\"}`;\n const imgClass =\n \"bg-transparent ring-background size-24 rounded-2xl object-cover ring-[3px] shadow-sm\";\n return (\n <div className={wrapperClass}>\n {product.image_url ? (\n <img src={product.image_url} alt=\"\" className={imgClass} />\n ) : (\n <div className=\"bg-muted ring-background text-muted-foreground flex size-24 items-center justify-center rounded-2xl shadow-sm ring-[3px]\">\n <ImageOff className=\"size-7\" strokeWidth={1.75} />\n </div>\n )}\n <div\n className=\"bg-primary text-primary-foreground ring-background absolute -top-1 -right-1 z-40 flex size-6 items-center justify-center rounded-full ring-2\"\n title={t(\"list_recurring_badge\")}\n >\n <Repeat className=\"size-3\" strokeWidth={2.75} />\n </div>\n </div>\n );\n}\n\n// ─── Empty / loading ───────────────────────────────────────────────────────\n\nfunction SubscriptionCardSkeleton(): JSX.Element {\n return (\n <div className=\"ring-border flex flex-col gap-5 rounded-2xl bg-transparent p-5 ring-1\">\n <div className=\"flex items-start gap-4\">\n <div className=\"bg-muted size-20 shrink-0 animate-pulse rounded-2xl\" />\n <div className=\"flex-1 space-y-2 pt-1\">\n <div className=\"bg-muted h-5 w-2/3 animate-pulse rounded\" />\n <div className=\"bg-muted h-4 w-1/2 animate-pulse rounded\" />\n </div>\n </div>\n <div className=\"bg-muted h-12 animate-pulse rounded\" />\n <div className=\"bg-muted h-6 animate-pulse rounded\" />\n </div>\n );\n}\n\nfunction EmptyState({\n filtered,\n t,\n}: {\n filtered?: boolean;\n t: T;\n}): JSX.Element {\n return (\n <div className=\"ring-border mx-auto mt-12 flex max-w-md flex-col items-center gap-2 rounded-2xl bg-transparent px-6 py-12 text-center ring-1\">\n <div className=\"text-foreground text-sm font-bold\">\n {filtered ? t(\"list_no_in_view\") : t(\"list_none_yet\")}\n </div>\n <div className=\"text-muted-foreground text-xs\">\n {filtered ? t(\"list_filtered_hint\") : t(\"list_empty_hint\")}\n </div>\n </div>\n );\n}\n\nfunction ErrorState({\n onRetry,\n t,\n}: {\n onRetry: () => void;\n t: T;\n}): JSX.Element {\n return (\n <div className=\"ring-border mx-auto mt-12 flex max-w-md flex-col items-center gap-2 rounded-2xl bg-transparent px-6 py-12 text-center ring-1\">\n <div className=\"bg-muted flex size-12 items-center justify-center rounded-full\">\n <AlertCircle className=\"text-muted-foreground size-5\" strokeWidth={2} />\n </div>\n <div className=\"text-foreground text-sm font-bold\">\n {t(\"list_load_failed_title\")}\n </div>\n <div className=\"text-muted-foreground text-xs\">\n {t(\"list_load_failed_hint\")}\n </div>\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 mt-2 inline-flex items-center gap-1 rounded-md px-3 py-1.5 text-xs font-bold transition-all\"\n >\n {t(\"list_try_again\")}\n </button>\n </div>\n );\n}\n","import type { fluidPay } from \"@fluid-app/fluid-pay-core\";\n\n/**\n * Mirrors fluid-checkout's `isPaymentMethodUsable`. A payment method is only\n * eligible for bundle attachment when it has a complete billing address.\n *\n * Note: the portal's `fluidPay.CustomerPaymentMethod` does not surface the\n * checkout-only `au_status` field, so we only check billing-address completeness.\n */\nexport function isPaymentMethodUsable(\n pm: fluidPay.CustomerPaymentMethod,\n): boolean {\n const addr = pm.billing_address;\n if (!addr) return false;\n return Boolean(\n addr.address1 && addr.city && addr.state && addr.zip && addr.country_code,\n );\n}\n","/**\n * Selectable range for the bundle bill-date picker: today at the bottom, the\n * bundle's edit cap at the top (2 years out for yearly cadences, 12 months for\n * everything else — see `getMaxEditableBillDate`). The API enforces the same\n * cap, so a date past it comes back as a 422 after the address and payment\n * steps rather than at the picker.\n *\n * Both ends are read in local time. `getMaxEditableBillDate` builds the cap\n * from local-midnight setters, so reading the floor in UTC would let the two\n * ends disagree by a day at large offsets.\n *\n * The predicates live here rather than in `DrawerStepDate` because the picker's\n * disabled state and `useBundleForm`'s cascade-clearing have to agree: a day\n * left selected but disabled looks pickable while Next silently refuses.\n */\nexport interface BillDateBounds {\n /** Earliest selectable date. */\n today: Date;\n /** Latest selectable date, i.e. the bundle's cap. */\n maxDate: Date;\n}\n\nexport function getDaysInMonth(year: number, month: number): number {\n return new Date(year, month + 1, 0).getDate();\n}\n\nexport function isYearOutOfRange(\n year: number,\n { today, maxDate }: BillDateBounds,\n): boolean {\n return year < today.getFullYear() || year > maxDate.getFullYear();\n}\n\nexport function isMonthOutOfRange(\n year: number,\n month: number,\n bounds: BillDateBounds,\n): boolean {\n const { today, maxDate } = bounds;\n if (isYearOutOfRange(year, bounds)) return true;\n if (year === maxDate.getFullYear() && month > maxDate.getMonth()) return true;\n if (year > today.getFullYear()) return false;\n return month < today.getMonth();\n}\n\nexport function isDayOutOfRange(\n year: number,\n month: number,\n day: number,\n bounds: BillDateBounds,\n): boolean {\n const { today, maxDate } = bounds;\n if (day > getDaysInMonth(year, month)) return true;\n if (isMonthOutOfRange(year, month, bounds)) return true;\n if (\n year === maxDate.getFullYear() &&\n month === maxDate.getMonth() &&\n day > maxDate.getDate()\n ) {\n return true;\n }\n if (year > today.getFullYear()) return false;\n if (month > today.getMonth()) return false;\n return day < today.getDate();\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { getMaxEditableBillDateForBundle } from \"@fluid-app/subscriptions-core/utils/subscription-helpers\";\nimport { isPaymentMethodUsable } from \"./payment-utils\";\nimport {\n isDayOutOfRange,\n isMonthOutOfRange,\n type BillDateBounds,\n} from \"./bill-date-bounds\";\nimport type { Step } from \"./types\";\n\ninterface UseBundleFormArgs {\n subscriptions: subscriptions.SubscriptionListItem[];\n addresses: fluidPay.CustomerAddress[];\n paymentMethods: fluidPay.CustomerPaymentMethod[];\n defaultAddressId?: number | null;\n defaultPaymentMethodId?: number | null;\n}\n\nexport interface BundleForm {\n step: Step;\n setStep: (s: Step) => void;\n selectedTokens: Set<string>;\n toggleToken: (token: string) => void;\n\n selectedYear: number;\n selectedMonth: number | null;\n selectedDay: number | null;\n setYear: (y: number) => void;\n setMonth: (m: number) => void;\n setDay: (d: number) => void;\n\n selectedAddressId: number | null;\n setSelectedAddressId: (id: number | null) => void;\n\n selectedPaymentMethodId: number | null;\n setSelectedPaymentMethodId: (id: number | null) => void;\n\n /** Selectable date range for the picker, driven by the bundle's cap. */\n bounds: BillDateBounds;\n\n canProceedFromStep1: boolean;\n canProceedFromStep2: boolean;\n canProceedFromStep3: boolean;\n canProceedFromStep4: boolean;\n\n /** \"YYYY-MM-DD\" or null when month/day not yet selected. */\n formattedDate: string | null;\n}\n\nfunction pickDefaultAddressId(\n addresses: fluidPay.CustomerAddress[],\n defaultAddressId: number | null | undefined,\n): number | null {\n if (defaultAddressId != null) {\n const match = addresses.find((a) => a.id === defaultAddressId);\n if (match) return match.id;\n }\n const flagged = addresses.find((a) => a.default);\n if (flagged) return flagged.id;\n return addresses[0]?.id ?? null;\n}\n\nfunction pickDefaultPaymentMethodId(\n paymentMethods: fluidPay.CustomerPaymentMethod[],\n defaultPaymentMethodId: number | null | undefined,\n): number | null {\n const usable = paymentMethods.filter(isPaymentMethodUsable);\n if (defaultPaymentMethodId != null) {\n const match = usable.find((pm) => pm.id === defaultPaymentMethodId);\n if (match) return match.id;\n }\n const flagged = usable.find((pm) => pm.default);\n if (flagged) return flagged.id;\n return usable[0]?.id ?? null;\n}\n\nexport function useBundleForm({\n subscriptions: subscriptionList,\n addresses,\n paymentMethods,\n defaultAddressId,\n defaultPaymentMethodId,\n}: UseBundleFormArgs): BundleForm {\n const [step, setStep] = useState<Step>(1);\n const [selectedTokens, setSelectedTokens] = useState<Set<string>>(\n () => new Set(),\n );\n const today = useMemo(() => new Date(), []);\n const [selectedYear, setYearState] = useState<number>(today.getFullYear());\n const [selectedMonth, setMonthState] = useState<number | null>(null);\n const [selectedDay, setDayState] = useState<number | null>(null);\n const [selectedAddressId, setSelectedAddressId] = useState<number | null>(\n () => pickDefaultAddressId(addresses, defaultAddressId),\n );\n const [selectedPaymentMethodId, setSelectedPaymentMethodId] = useState<\n number | null\n >(() => pickDefaultPaymentMethodId(paymentMethods, defaultPaymentMethodId));\n\n // When the user opens the drawer with an empty address book, then adds an\n // address inline (AddressFormDialog → query invalidates → `addresses` prop\n // refreshes), auto-select the new address so step 3's Next button enables\n // without requiring a manual tap. The lazy useState initializer above only\n // runs once at mount and would otherwise leave `selectedAddressId === null`\n // forever. Mirror logic for payment methods.\n useEffect(() => {\n if (selectedAddressId == null && addresses.length > 0) {\n setSelectedAddressId(pickDefaultAddressId(addresses, defaultAddressId));\n }\n }, [selectedAddressId, addresses, defaultAddressId]);\n\n useEffect(() => {\n if (\n selectedPaymentMethodId == null &&\n paymentMethods.some(isPaymentMethodUsable)\n ) {\n setSelectedPaymentMethodId(\n pickDefaultPaymentMethodId(paymentMethods, defaultPaymentMethodId),\n );\n }\n }, [selectedPaymentMethodId, paymentMethods, defaultPaymentMethodId]);\n\n const toggleToken = useCallback((token: string) => {\n setSelectedTokens((prev) => {\n const next = new Set(prev);\n if (next.has(token)) next.delete(token);\n else next.add(token);\n return next;\n });\n }, []);\n\n // Every selected subscription moves to one shared bill date, so the bundle\n // answers to its strictest member's cap: a single monthly member holds the\n // whole bundle to 12 months even when the rest are yearly. Walk the selected\n // tokens rather than filtering the list, so a token whose subscription isn't\n // in the loaded page counts as unknown cadence (12 months, fail closed)\n // instead of dropping out of the bound entirely.\n const bounds = useMemo<BillDateBounds>(() => {\n const members = Array.from(selectedTokens).map((token) => {\n const plan = subscriptionList.find(\n (sub) => sub.subscription_token === token,\n )?.subscription_plan;\n return {\n billingInterval: plan?.billing_interval,\n billingIntervalUnit: plan?.billing_interval_unit,\n };\n });\n return { today, maxDate: getMaxEditableBillDateForBundle(members, today) };\n }, [selectedTokens, subscriptionList, today]);\n\n // Cascade-clear month/day when year changes if month/day become invalid.\n const setYear = useCallback(\n (y: number) => {\n setYearState(y);\n if (selectedMonth == null) return;\n // Out of range covers both ends: a month before today and a month past\n // the bundle's cap (switching from 2027 to 2028 on a monthly bundle).\n if (isMonthOutOfRange(y, selectedMonth, bounds)) {\n setMonthState(null);\n setDayState(null);\n return;\n }\n // Same-month edge case: switching back to the current year while a day\n // from the current month is selected can leave the day in the past (e.g.\n // selectedDay=3 when today=May 7). Clear the day in that case so the\n // user doesn't unknowingly submit a past date and trip the BFF's\n // `next_bill_date_in_past` validator. The cap end works the same way.\n if (\n selectedDay != null &&\n isDayOutOfRange(y, selectedMonth, selectedDay, bounds)\n ) {\n setDayState(null);\n }\n },\n [selectedMonth, selectedDay, bounds],\n );\n\n // Clear the day when the month changes and the day no longer fits the range.\n // `isDayOutOfRange` starts with the days-in-month check, so one call covers\n // a short month (Jan 31 → Feb), a past-dated day (today is May 7; the user\n // picked July 3, then switched back to May — 3 fits in May but is past, and\n // would submit as a past date with no inline explanation) and a day beyond\n // the cap (switching into the capped month with a later day selected).\n const setMonth = useCallback(\n (m: number) => {\n setMonthState(m);\n if (\n selectedDay != null &&\n isDayOutOfRange(selectedYear, m, selectedDay, bounds)\n ) {\n setDayState(null);\n }\n },\n [selectedDay, selectedYear, bounds],\n );\n\n const setDay = useCallback((d: number) => setDayState(d), []);\n\n const canProceedFromStep1 = selectedTokens.size >= 2;\n // The picker disables out-of-range dates, but the cap itself moves: picking a\n // date on step 2 and then adding a monthly member back on step 1 tightens the\n // bundle from 2 years to 12 months and can leave the stored selection outside\n // the new bound. Re-check it here so Next blocks instead of the API 422ing\n // three steps later.\n const selectedDateOutOfRange =\n selectedMonth !== null &&\n selectedDay !== null &&\n isDayOutOfRange(selectedYear, selectedMonth, selectedDay, bounds);\n const canProceedFromStep2 =\n selectedMonth !== null && selectedDay !== null && !selectedDateOutOfRange;\n const canProceedFromStep3 = selectedAddressId != null;\n const canProceedFromStep4 = selectedPaymentMethodId != null;\n\n const formattedDate = useMemo(() => {\n if (selectedMonth == null || selectedDay == null) return null;\n const mm = String(selectedMonth + 1).padStart(2, \"0\");\n const dd = String(selectedDay).padStart(2, \"0\");\n return `${selectedYear}-${mm}-${dd}`;\n }, [selectedYear, selectedMonth, selectedDay]);\n\n return {\n step,\n setStep,\n selectedTokens,\n toggleToken,\n selectedYear,\n selectedMonth,\n selectedDay,\n setYear,\n setMonth,\n setDay,\n selectedAddressId,\n setSelectedAddressId,\n selectedPaymentMethodId,\n setSelectedPaymentMethodId,\n bounds,\n canProceedFromStep1,\n canProceedFromStep2,\n canProceedFromStep3,\n canProceedFromStep4,\n formattedDate,\n };\n}\n","import type { JSX } from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport type { Step } from \"./types\";\n\ninterface DrawerStepTabsProps {\n step: Step;\n onStepClick: (step: Step) => void;\n canProceedFromStep1: boolean;\n canProceedFromStep2: boolean;\n canProceedFromStep3: boolean;\n}\n\ntype TabLabelKey =\n | \"bundle_step_select\"\n | \"bundle_step_date\"\n | \"bundle_step_address\"\n | \"bundle_step_payment\";\n\nconst TABS: ReadonlyArray<{ id: Step; labelKey: TabLabelKey }> = [\n { id: 1, labelKey: \"bundle_step_select\" },\n { id: 2, labelKey: \"bundle_step_date\" },\n { id: 3, labelKey: \"bundle_step_address\" },\n { id: 4, labelKey: \"bundle_step_payment\" },\n];\n\nconst PROGRESS_BY_STEP: Record<Step, string> = {\n 1: \"0%\",\n 2: \"33%\",\n 3: \"66%\",\n 4: \"100%\",\n};\n\ntype StepMessageKey =\n | \"bundle_step1_message\"\n | \"bundle_step2_message\"\n | \"bundle_step3_message\"\n | \"bundle_step4_message\";\n\nexport function DrawerStepTabs({\n step,\n onStepClick,\n canProceedFromStep1,\n canProceedFromStep2,\n canProceedFromStep3,\n}: DrawerStepTabsProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n\n const handleClick = (target: Step) => {\n if (target < step) {\n onStepClick(target);\n } else if (target === 2 && canProceedFromStep1) {\n onStepClick(2);\n } else if (target === 3 && canProceedFromStep1 && canProceedFromStep2) {\n onStepClick(3);\n } else if (\n target === 4 &&\n canProceedFromStep1 &&\n canProceedFromStep2 &&\n canProceedFromStep3\n ) {\n onStepClick(4);\n }\n };\n\n const messageKey: StepMessageKey =\n step === 1\n ? \"bundle_step1_message\"\n : step === 2\n ? \"bundle_step2_message\"\n : step === 3\n ? \"bundle_step3_message\"\n : \"bundle_step4_message\";\n\n return (\n <div className=\"px-6 pt-4\">\n <div className=\"mb-2 flex items-center justify-between\">\n {TABS.map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => handleClick(tab.id)}\n className={`text-xs font-bold transition-colors ${\n step === tab.id\n ? \"text-foreground\"\n : step > tab.id\n ? \"text-muted-foreground cursor-pointer\"\n : \"text-muted-foreground/75\"\n }`}\n >\n {t(tab.labelKey)}\n </button>\n ))}\n </div>\n\n <div className=\"bg-muted relative h-1 rounded-full\">\n <div\n className=\"bg-primary absolute h-1 rounded-full transition-all duration-300\"\n style={{ width: PROGRESS_BY_STEP[step] }}\n />\n {TABS.map((tab, index) => (\n <div\n key={tab.id}\n className={`absolute top-1/2 size-3 rounded-full transition-colors ${\n step >= tab.id ? \"bg-primary\" : \"bg-muted ring-border ring-1\"\n }`}\n style={\n index === 0\n ? { left: 0, transform: \"translateY(-50%)\" }\n : index === TABS.length - 1\n ? { right: 0, transform: \"translateY(-50%)\" }\n : {\n left: `${(index / (TABS.length - 1)) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n }\n }\n />\n ))}\n </div>\n\n <div className=\"text-muted-foreground mt-3 flex items-center justify-center text-xs\">\n <span>{t(messageKey)}</span>\n </div>\n </div>\n );\n}\n","import type { JSX } from \"react\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { Check, Package, Repeat, Truck } from \"lucide-react\";\nimport {\n formatCadence,\n formatPrice,\n} from \"../portal-subscriptions-list-helpers\";\n\ninterface DrawerStepSelectProps {\n subscriptions: subscriptions.SubscriptionListItem[];\n selectedTokens: Set<string>;\n onToggle: (token: string) => void;\n}\n\nfunction formatBillDate(value: string | null): string {\n if (!value) return \"—\";\n // Mirror the calendar-date-from-the-front parse in `formatLongDate` so a\n // pure date string like \"2026-05-10\" doesn't get shifted to May 9 for\n // anyone west of UTC. Subscription.next_billing_date is a datetime; the\n // date prefix matches the same regex.\n try {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(value);\n if (!match) return \"—\";\n const y = Number(match[1]);\n const m = Number(match[2]);\n const d = Number(match[3]);\n if (!y || !m || !d) return \"—\";\n const date = new Date(Date.UTC(y, m - 1, d));\n return date.toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n timeZone: \"UTC\",\n });\n } catch {\n return \"—\";\n }\n}\n\nexport function DrawerStepSelect({\n subscriptions,\n selectedTokens,\n onToggle,\n}: DrawerStepSelectProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n <div className=\"bg-muted mt-2 rounded-2xl p-6 text-center\">\n <div className=\"mx-auto mb-3 flex size-14 items-center justify-center rounded-2xl bg-transparent shadow-sm\">\n <Truck className=\"text-foreground size-7\" strokeWidth={2} />\n </div>\n <h3 className=\"text-foreground text-sm font-bold\">\n {t(\"bundle_and_save\")}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n {t(\"bundle_select_subs\")}\n </p>\n </div>\n\n {subscriptions.length < 2 && (\n <div className=\"ring-border mt-4 rounded-2xl p-6 text-center ring-1\">\n <p className=\"text-muted-foreground text-xs\">\n {t(\"bundle_no_bundleable_subs\")}\n </p>\n </div>\n )}\n\n <div className=\"mt-4 space-y-2\">\n {subscriptions.length >= 2 &&\n subscriptions.map((sub) => {\n const isSelected = selectedTokens.has(sub.subscription_token);\n return (\n <div\n key={sub.subscription_token}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={() => onToggle(sub.subscription_token)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onToggle(sub.subscription_token);\n }\n }}\n className={`flex cursor-pointer items-start gap-3 rounded-2xl p-4 transition-all ${\n isSelected\n ? \"ring-primary bg-muted ring-2\"\n : \"ring-border hover:ring-foreground/20 ring-1\"\n }`}\n >\n <div className=\"pt-1\">\n <div\n className={`flex size-5 items-center justify-center rounded-full transition-colors ${\n isSelected ? \"bg-primary\" : \"ring-foreground/30 ring-2\"\n }`}\n >\n {isSelected && (\n <Check\n className=\"text-primary-foreground size-3\"\n strokeWidth={3}\n />\n )}\n </div>\n </div>\n\n {sub.variant?.product?.image_url ? (\n <img\n src={sub.variant.product.image_url}\n alt={sub.variant.product.title ?? \"\"}\n className=\"size-12 shrink-0 rounded-lg object-cover\"\n />\n ) : (\n <div className=\"bg-muted flex size-12 shrink-0 items-center justify-center rounded-lg\">\n <Package\n className=\"text-muted-foreground size-6\"\n strokeWidth={1.75}\n />\n </div>\n )}\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-foreground truncate text-xs font-bold\">\n {sub.variant?.product?.title ?? t(\"list_product_fallback\")}\n </p>\n <p className=\"text-foreground mt-0.5 text-xs\">\n {formatPrice(sub)}\n </p>\n {sub.customer?.full_name && (\n <p className=\"text-muted-foreground mt-0.5 truncate text-xs\">\n {sub.customer.full_name}\n </p>\n )}\n </div>\n\n <div className=\"shrink-0 text-right\">\n <div className=\"text-muted-foreground inline-flex items-center gap-1 text-xs\">\n <Repeat className=\"size-3\" strokeWidth={2} />\n {formatCadence(sub.subscription_plan, t)}\n </div>\n <p className=\"text-muted-foreground/75 mt-1 text-xs\">\n {formatBillDate(sub.next_bill_date)}\n </p>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n","import { useMemo, type JSX } from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n getDaysInMonth,\n isDayOutOfRange,\n isMonthOutOfRange,\n isYearOutOfRange,\n type BillDateBounds,\n} from \"./bill-date-bounds\";\n\ninterface DrawerStepDateProps {\n selectedYear: number;\n selectedMonth: number | null;\n selectedDay: number | null;\n onYearChange: (year: number) => void;\n onMonthChange: (month: number) => void;\n onDayChange: (day: number) => void;\n /**\n * Selectable range. Its ceiling is the bundle's bill-date cap, which the API\n * enforces too — without it the picker offers dates that only fail on submit.\n */\n bounds: BillDateBounds;\n}\n\nconst MONTHS = [\n \"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Aug\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dec\",\n];\n\nexport function DrawerStepDate({\n selectedYear,\n selectedMonth,\n selectedDay,\n onYearChange,\n onMonthChange,\n onDayChange,\n bounds,\n}: DrawerStepDateProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const currentYear = bounds.today.getFullYear();\n const availableYears = useMemo(\n () => [currentYear, currentYear + 1, currentYear + 2],\n [currentYear],\n );\n\n const isYearDisabled = (year: number): boolean =>\n isYearOutOfRange(year, bounds);\n\n const isMonthDisabled = (monthIndex: number): boolean =>\n isMonthOutOfRange(selectedYear, monthIndex, bounds);\n\n const daysInSelectedMonth =\n selectedMonth == null ? 31 : getDaysInMonth(selectedYear, selectedMonth);\n\n const isDayDisabled = (day: number): boolean => {\n if (selectedMonth == null) return true;\n return isDayOutOfRange(selectedYear, selectedMonth, day, bounds);\n };\n\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n <div className=\"mt-2\">\n <h3 className=\"text-foreground text-sm font-bold\">\n {t(\"bundle_select_new_bill_date\")}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n {t(\"bundle_select_new_bill_date_description\")}\n </p>\n </div>\n\n <div className=\"mt-6\">\n <h4 className=\"text-foreground mb-3 text-xs font-bold\">\n {t(\"bundle_year\")}\n </h4>\n <div className=\"grid grid-cols-3 gap-2\">\n {availableYears.map((year) => {\n const isActive = selectedYear === year;\n const disabled = isYearDisabled(year);\n return (\n <button\n key={year}\n type=\"button\"\n disabled={disabled}\n onClick={() => onYearChange(year)}\n className={`rounded-lg px-3 py-2.5 text-xs font-semibold transition-all ${\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"text-foreground ring-border hover:ring-foreground/20 bg-transparent ring-1\"\n } ${disabled ? \"cursor-not-allowed opacity-40\" : \"\"}`}\n >\n {year}\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"mt-6\">\n <h4 className=\"text-foreground mb-3 text-xs font-bold\">\n {t(\"bundle_month\")}\n </h4>\n <div className=\"grid grid-cols-4 gap-2\">\n {MONTHS.map((month, index) => {\n const isActive = selectedMonth === index;\n const disabled = isMonthDisabled(index);\n return (\n <button\n key={month}\n type=\"button\"\n disabled={disabled}\n onClick={() => onMonthChange(index)}\n className={`rounded-lg px-3 py-2.5 text-xs font-semibold transition-all ${\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"text-foreground ring-border hover:ring-foreground/20 bg-transparent ring-1\"\n } ${disabled ? \"cursor-not-allowed opacity-40\" : \"\"}`}\n >\n {month}\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"mt-6\">\n <h4 className=\"text-foreground mb-3 text-xs font-bold\">\n {t(\"bundle_day\")}\n </h4>\n <div className=\"grid grid-cols-8 gap-1.5\">\n {Array.from({ length: daysInSelectedMonth }, (_, i) => i + 1).map(\n (day) => {\n const isActive = selectedDay === day;\n const disabled = isDayDisabled(day);\n return (\n <button\n key={day}\n type=\"button\"\n disabled={disabled}\n onClick={() => onDayChange(day)}\n className={`rounded-lg py-2 text-xs font-semibold transition-all ${\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"text-foreground ring-border hover:ring-foreground/20 bg-transparent ring-1\"\n } ${disabled ? \"cursor-not-allowed opacity-40\" : \"\"}`}\n >\n {day}\n </button>\n );\n },\n )}\n </div>\n </div>\n </div>\n );\n}\n","import type { JSX } from \"react\";\nimport { Check } from \"lucide-react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { formatLongDate } from \"../portal-subscriptions-list-helpers\";\n\ninterface DrawerStepAddressProps {\n addresses: fluidPay.CustomerAddress[];\n selectedAddressId: number | null;\n onAddressSelect: (id: number) => void;\n onAddAddress: () => void;\n formattedSelectedDate: string | null;\n}\n\nexport function DrawerStepAddress({\n addresses,\n selectedAddressId,\n onAddressSelect,\n onAddAddress,\n formattedSelectedDate,\n}: DrawerStepAddressProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const hasFlaggedDefault = addresses.some((a) => a.default);\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n <div className=\"mt-2\">\n <h3 className=\"text-foreground text-sm font-bold\">\n {t(\"bundle_select_address\")}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n {t(\"bundle_select_address_description\")}\n </p>\n </div>\n\n {formattedSelectedDate && (\n <div className=\"bg-muted text-muted-foreground mt-4 rounded-lg px-4 py-2.5 text-xs\">\n {t(\"bundle_selected_bill_date\")}{\" \"}\n <span className=\"text-foreground font-semibold\">\n {formatLongDate(formattedSelectedDate)}\n </span>\n </div>\n )}\n\n <div className=\"mt-4 space-y-2\" role=\"radiogroup\">\n {addresses.map((address, index) => {\n const isSelected = selectedAddressId === address.id;\n const isDefault =\n address.default || (!hasFlaggedDefault && index === 0);\n return (\n <button\n key={address.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n onClick={() => onAddressSelect(address.id)}\n className={`flex h-auto w-full cursor-pointer items-start gap-3 rounded-2xl p-4 text-left transition-all ${\n isSelected\n ? \"ring-primary bg-muted ring-2\"\n : \"ring-border hover:ring-foreground/20 ring-1\"\n }`}\n >\n <div className=\"pt-0.5\">\n <div\n className={`flex size-5 items-center justify-center rounded-full transition-colors ${\n isSelected ? \"bg-primary\" : \"ring-foreground/30 ring-2\"\n }`}\n >\n {isSelected && (\n <Check\n className=\"text-primary-foreground size-3\"\n strokeWidth={3}\n />\n )}\n </div>\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {address.name && (\n <p className=\"text-foreground truncate text-xs font-bold\">\n {address.name}\n </p>\n )}\n {isDefault && (\n <span className=\"text-foreground ring-border rounded-full bg-transparent px-2 py-0.5 text-xs font-bold ring-1\">\n {t(\"bundle_default_badge\")}\n </span>\n )}\n </div>\n <p className=\"text-muted-foreground mt-0.5 truncate text-xs\">\n {address.address1}\n </p>\n <p className=\"text-muted-foreground truncate text-xs\">\n {[address.city, address.state].filter(Boolean).join(\", \")}{\" \"}\n {address.postal_code}\n </p>\n {address.phone && (\n <p className=\"text-muted-foreground truncate text-xs\">\n {address.phone}\n </p>\n )}\n </div>\n </button>\n );\n })}\n </div>\n\n <div className=\"mt-4 text-right\">\n <button\n type=\"button\"\n onClick={onAddAddress}\n className=\"text-foreground inline-flex items-center text-xs font-bold underline-offset-2 hover:underline\"\n >\n {t(\"bundle_add_new_address\")}\n </button>\n </div>\n </div>\n );\n}\n","import { useMemo, type JSX } from \"react\";\nimport { Check } from \"lucide-react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n PaymentIcon,\n getCardDisplayName,\n getPaymentMethodLogoBrand,\n} from \"@fluid-app/profile-ui/components/payment-method-card-internals\";\nimport { isPaymentMethodUsable } from \"./payment-utils\";\n\ninterface DrawerStepPaymentProps {\n paymentMethods: fluidPay.CustomerPaymentMethod[];\n selectedPaymentMethodId: number | null;\n onPaymentMethodSelect: (id: number) => void;\n onAddPaymentMethod: () => void;\n}\n\nexport function DrawerStepPayment({\n paymentMethods,\n selectedPaymentMethodId,\n onPaymentMethodSelect,\n onAddPaymentMethod,\n}: DrawerStepPaymentProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n // Filter to usable + sort default-first.\n const usable = useMemo(() => {\n const filtered = paymentMethods.filter(isPaymentMethodUsable);\n const defaultIdx = filtered.findIndex((pm) => pm.default);\n if (defaultIdx <= 0) return filtered;\n const defaultCard = filtered[defaultIdx];\n if (!defaultCard) return filtered;\n return [defaultCard, ...filtered.filter((_, i) => i !== defaultIdx)];\n }, [paymentMethods]);\n\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n <div className=\"mt-2\">\n <h3 className=\"text-foreground text-sm font-bold\">\n {t(\"bundle_select_payment\")}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n {t(\"bundle_select_payment_description\")}\n </p>\n </div>\n\n {usable.length === 0 && (\n <div className=\"bg-muted text-muted-foreground mt-4 rounded-lg px-4 py-3 text-xs\">\n {t(\"bundle_no_usable_payment_methods\")}\n </div>\n )}\n\n <div className=\"mt-4 space-y-2\" role=\"radiogroup\">\n {usable.map((pm) => {\n const isSelected = selectedPaymentMethodId === pm.id;\n const displayName = getCardDisplayName(pm);\n const expiry =\n pm.details.exp_month != null && pm.details.exp_year != null\n ? `${t(\"bundle_card_expires\")} ${pm.details.exp_month}/${pm.details.exp_year}`\n : null;\n return (\n <button\n key={pm.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n onClick={() => onPaymentMethodSelect(pm.id)}\n className={`flex h-auto w-full cursor-pointer items-start gap-3 rounded-2xl p-4 text-left transition-all ${\n isSelected\n ? \"ring-primary bg-muted ring-2\"\n : \"ring-border hover:ring-foreground/20 ring-1\"\n }`}\n >\n <div className=\"pt-0.5\">\n <div\n className={`flex size-5 items-center justify-center rounded-full transition-colors ${\n isSelected ? \"bg-primary\" : \"ring-foreground/30 ring-2\"\n }`}\n >\n {isSelected && (\n <Check\n className=\"text-primary-foreground size-3\"\n strokeWidth={3}\n />\n )}\n </div>\n </div>\n\n <div className=\"flex h-6 w-10 shrink-0 items-center justify-center\">\n <PaymentIcon\n logoUrl={pm.details.logo_url}\n brand={getPaymentMethodLogoBrand(pm)}\n alt={displayName}\n />\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"text-foreground text-xs font-bold\">\n {displayName}\n </p>\n {pm.default && (\n <span className=\"text-foreground ring-border rounded-full bg-transparent px-2 py-0.5 text-xs font-bold ring-1\">\n {t(\"bundle_default_badge\")}\n </span>\n )}\n </div>\n {expiry && (\n <p className=\"text-muted-foreground mt-0.5 text-xs\">\n {expiry}\n </p>\n )}\n </div>\n </button>\n );\n })}\n </div>\n\n <div className=\"mt-4 text-right\">\n <button\n type=\"button\"\n onClick={onAddPaymentMethod}\n className=\"text-foreground inline-flex items-center text-xs font-bold underline-offset-2 hover:underline\"\n >\n {t(\"bundle_add_new_card\")}\n </button>\n </div>\n </div>\n );\n}\n","import { type JSX } from \"react\";\nimport { Sheet, SheetContent, SheetTitle } from \"@fluid-app/ui-primitives\";\nimport { MobileBottomSheet } from \"@fluid-app/ui-components/components/MobileBottomSheet\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { useBundleForm } from \"./use-bundle-form\";\nimport { DrawerStepTabs } from \"./DrawerStepTabs\";\nimport { DrawerStepSelect } from \"./DrawerStepSelect\";\nimport { DrawerStepDate } from \"./DrawerStepDate\";\nimport { DrawerStepAddress } from \"./DrawerStepAddress\";\nimport { DrawerStepPayment } from \"./DrawerStepPayment\";\nimport type { Step } from \"./types\";\n\nexport interface BundleSubscriptionsDrawerProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n subscriptions: subscriptions.SubscriptionListItem[];\n addresses: fluidPay.CustomerAddress[];\n paymentMethods: fluidPay.CustomerPaymentMethod[];\n defaultAddressId?: number | null;\n defaultPaymentMethodId?: number | null;\n onAddAddress: () => void;\n onAddPaymentMethod: () => void;\n onSubmit: (params: {\n subscription_tokens: string[];\n next_bill_date: string;\n address_id: number;\n payment_method_id: number;\n }) => Promise<void>;\n isSubmitting?: boolean;\n}\n\nexport function BundleSubscriptionsDrawer({\n open,\n onOpenChange,\n subscriptions: subscriptionList,\n addresses,\n paymentMethods,\n defaultAddressId,\n defaultPaymentMethodId,\n onAddAddress,\n onAddPaymentMethod,\n onSubmit,\n isSubmitting,\n}: BundleSubscriptionsDrawerProps): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const { isMobile } = useSidebar();\n const form = useBundleForm({\n subscriptions: subscriptionList,\n addresses,\n paymentMethods,\n defaultAddressId,\n defaultPaymentMethodId,\n });\n\n const handleClose = () => onOpenChange(false);\n\n const handleNext = () => {\n if (form.step < 4) form.setStep((form.step + 1) as Step);\n };\n\n const handleBack = () => {\n if (form.step === 1) handleClose();\n else form.setStep((form.step - 1) as Step);\n };\n\n const handleSubmit = async () => {\n if (\n !form.canProceedFromStep1 ||\n !form.canProceedFromStep2 ||\n !form.canProceedFromStep3 ||\n !form.canProceedFromStep4 ||\n form.formattedDate == null ||\n form.selectedAddressId == null ||\n form.selectedPaymentMethodId == null\n ) {\n return;\n }\n await onSubmit({\n subscription_tokens: Array.from(form.selectedTokens),\n next_bill_date: form.formattedDate,\n address_id: form.selectedAddressId,\n payment_method_id: form.selectedPaymentMethodId,\n });\n };\n\n const nextDisabled =\n (form.step === 1 && !form.canProceedFromStep1) ||\n (form.step === 2 && !form.canProceedFromStep2) ||\n (form.step === 3 && !form.canProceedFromStep3);\n\n const content = (\n <div\n className={\n isMobile\n ? \"flex min-h-[65dvh] flex-col\"\n : \"flex min-h-0 flex-1 flex-col\"\n }\n >\n <DrawerStepTabs\n step={form.step}\n onStepClick={form.setStep}\n canProceedFromStep1={form.canProceedFromStep1}\n canProceedFromStep2={form.canProceedFromStep2}\n canProceedFromStep3={form.canProceedFromStep3}\n />\n\n {form.step === 1 && (\n <DrawerStepSelect\n subscriptions={subscriptionList}\n selectedTokens={form.selectedTokens}\n onToggle={form.toggleToken}\n />\n )}\n {form.step === 2 && (\n <DrawerStepDate\n selectedYear={form.selectedYear}\n selectedMonth={form.selectedMonth}\n selectedDay={form.selectedDay}\n onYearChange={form.setYear}\n onMonthChange={form.setMonth}\n onDayChange={form.setDay}\n bounds={form.bounds}\n />\n )}\n {form.step === 3 && (\n <DrawerStepAddress\n addresses={addresses}\n selectedAddressId={form.selectedAddressId}\n onAddressSelect={form.setSelectedAddressId}\n onAddAddress={onAddAddress}\n formattedSelectedDate={form.formattedDate}\n />\n )}\n {form.step === 4 && (\n <DrawerStepPayment\n paymentMethods={paymentMethods}\n selectedPaymentMethodId={form.selectedPaymentMethodId}\n onPaymentMethodSelect={form.setSelectedPaymentMethodId}\n onAddPaymentMethod={onAddPaymentMethod}\n />\n )}\n\n <div className=\"border-border flex shrink-0 items-center justify-between gap-3 border-t px-6 py-4\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"text-foreground ring-border hover:bg-muted rounded-lg bg-transparent px-6 py-2.5 text-xs font-bold ring-1 transition-all\"\n >\n {form.step === 1 ? t(\"bundle_done\") : t(\"bundle_back\")}\n </button>\n {form.step < 4 ? (\n <button\n type=\"button\"\n onClick={handleNext}\n disabled={nextDisabled}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 rounded-lg px-6 py-2.5 text-xs font-bold transition-all disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {t(\"next\")}\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!form.canProceedFromStep4 || isSubmitting}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 inline-flex min-w-[140px] items-center justify-center rounded-lg px-6 py-2.5 text-xs font-bold transition-all disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {isSubmitting ? (\n <span className=\"border-primary-foreground size-5 animate-spin rounded-full border-2 border-t-transparent\" />\n ) : (\n t(\"bundle_create\")\n )}\n </button>\n )}\n </div>\n </div>\n );\n\n if (isMobile) {\n return (\n <MobileBottomSheet\n open={open}\n onOpenChange={onOpenChange}\n title={t(\"bundle_subscriptions\")}\n >\n {content}\n </MobileBottomSheet>\n );\n }\n\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent\n side=\"right\"\n className=\"bg-background flex h-full w-full flex-col gap-0 p-0 sm:max-w-md\"\n >\n {/* Header */}\n <div className=\"border-border flex items-center justify-between border-b px-6 py-4\">\n <SheetTitle className=\"text-foreground text-base font-bold\">\n {t(\"bundle_subscriptions\")}\n </SheetTitle>\n {/* SheetContent already renders its own close (X) button via the shadcn primitive. */}\n </div>\n\n {content}\n </SheetContent>\n </Sheet>\n );\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport {\n FluidPayCoreProvider,\n type fluidPay,\n type State,\n} from \"@fluid-app/fluid-pay-core\";\nimport { isApiError } from \"@fluid-app/api-client-core\";\nimport {\n AddressFormDialog,\n CreditCardFormDialog,\n type CreditCardFormSubmitData,\n} from \"@fluid-app/profile-ui\";\nimport { useActiveLocale } from \"@fluid-app/i18n/locale-context\";\nimport {\n useBundles,\n useCreateBundle,\n useInfiniteSubscriptions,\n useUpdateSubscriptionInfo,\n} from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport { TOKEN_PROVIDER_VGS } from \"@fluid-app/portal-core/pay-types\";\nimport type { PayAddress } from \"@fluid-app/portal-core/pay-types\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { getBrowserInfo } from \"@fluid-app/fluid-pay-core/utils/browser-info\";\nimport { useCountriesApi } from \"@fluid-app/store-core/countries-api-context\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\nimport { useFluidContext } from \"../providers/FluidProvider\";\nimport { ProfileTranslationBridge } from \"../providers/ProfileTranslationBridge\";\nimport { payKeys, storeKeys } from \"../account/query-keys\";\nimport {\n createFluidPayApiAdapter,\n mapToFluidPayPaymentMethod,\n} from \"../adapters/fluid-pay-api-adapter\";\nimport { usePortalCardAdd3DSFlow } from \"../hooks/use-portal-card-add-3ds-flow\";\nimport { buildSubscriptionCardAddSuccess } from \"../subscriptions/subscription-card-add-success\";\nimport { PortalSubscriptionsList } from \"./subscriptions/PortalSubscriptionsList\";\nimport { BundleSubscriptionsDrawer } from \"./subscriptions/bundle-drawer/BundleSubscriptionsDrawer\";\nimport { mapStatusKindOnly } from \"./subscriptions/portal-subscriptions-list-helpers\";\nimport { useStore } from \"../hooks/use-store\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\n\ninterface SubscriptionsListScreenProps {\n customerId: number | undefined;\n isLoadingCustomer: boolean;\n onToast?: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n}\n\n// AddressFormDialog and CreditCardFormDialog accept their own free-form\n// translation function. Their label set is closed and not part of the\n// subscriptions dictionary, so we inline a small map and Title-Case any\n// unknown key (mirrors the pattern in PortalSubscriptionShippingAddressSection).\nconst ADDRESS_DIALOG_LABELS: Record<string, string> = {\n add_an_address: \"Add an Address\",\n add_address: \"Add Address\",\n edit_address: \"Edit Address\",\n delete_address: \"Delete Address\",\n delete_address_message:\n \"Are you sure you want to delete this address? This action cannot be undone.\",\n delete: \"Delete\",\n cancel: \"Cancel\",\n country: \"Country\",\n name: \"Name\",\n address_line_1: \"Address Line 1\",\n address_line_2: \"Apartment, suite, etc.\",\n city: \"City\",\n state: \"State\",\n province: \"Province\",\n zip_code: \"Zip Code\",\n postal_code: \"Postal Code\",\n select_state: \"Select state\",\n select_an_option: \"Select an option\",\n set_as_default_address: \"Set as default address\",\n save_address: \"Save Address\",\n deleting: \"Deleting…\",\n tap_to_confirm: \"Tap to confirm\",\n add_credit_card: \"Add Credit Card\",\n add_billing_address: \"Add billing address\",\n billing_address: \"Billing Address\",\n same_as_shipping: \"Same as shipping address\",\n use_a_different_address: \"Use a different address\",\n set_as_default_payment_method: \"Set as default payment method\",\n save_card: \"Save Card\",\n saving: \"Saving...\",\n securing: \"Loading secure form...\",\n};\n\nfunction addressDialogT(key: string): string {\n return (\n ADDRESS_DIALOG_LABELS[key] ??\n key\n .split(\"_\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \")\n );\n}\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n phone: raw.phone,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\nfunction SubscriptionsListScreenInner({\n customerId,\n isLoadingCustomer,\n onToast,\n}: SubscriptionsListScreenProps): React.JSX.Element {\n const { isMobile } = useSidebar();\n const { navigate } = useAppNavigation();\n const queryClient = useQueryClient();\n const payApi = usePayApi();\n const countriesApi = useCountriesApi();\n const { t } = useSubscriptionsTranslation();\n const { t: profileT } = useProfileTranslation();\n const { config } = useFluidContext();\n const { locale } = useActiveLocale();\n\n // Company-level bundling feature flag from the portal-tenant store endpoint.\n // The Rails BFF returns 422 on bundle endpoints when this is false, so we\n // hide every bundle entry point (CTA, drawer, list cards) rather than show\n // controls that are guaranteed to fail.\n const { data: store } = useStore();\n const bundlingEnabled = !!store?.bundle_subscriptions_enabled;\n\n const { data: addresses = [] } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n enabled: !!customerId && !isLoadingCustomer,\n });\n\n const { data: paymentMethods = [] } = useQuery({\n queryKey: payKeys.paymentMethods.list(),\n queryFn: async () => {\n const response = await payApi.fetchPaymentMethods();\n return response.payment_methods.map(mapToFluidPayPaymentMethod);\n },\n enabled: !!customerId && !isLoadingCustomer,\n });\n\n // Re-call useInfiniteSubscriptions here so the drawer can see the same flat\n // list without prop-drilling. TanStack Query dedupes the network request,\n // so this is just a cache-read after PortalSubscriptionsList has fetched.\n const { data: subscriptionsData } = useInfiniteSubscriptions(\n { customerId, limit: 12 },\n { enabled: !!customerId && !isLoadingCustomer },\n );\n const subscriptionsList = useMemo(\n () => subscriptionsData?.pages.flatMap((p) => p.subscriptions) ?? [],\n [subscriptionsData],\n );\n\n // Only active/paused/pending/past-due, currently un-bundled subs can be\n // bundled. Cancelled subs have no future billing for the bundler to align,\n // and already-bundled subs would re-trigger bundler.rb's composite-key\n // grouping rather than create a fresh group.\n const bundleableSubscriptions = useMemo(\n () =>\n subscriptionsList.filter(\n (s) =>\n mapStatusKindOnly(s.status) !== \"cancelled\" &&\n (s.bundled_subscriptions?.length ?? 0) === 0,\n ),\n [subscriptionsList],\n );\n\n // Authoritative source for runtime bundle groupings — the backend recomputes\n // group membership at request time from `bundler.rb`'s composite key\n // (customer + address + volume_rep + next_bill_date + digital). The list\n // component picks out `subscription_count > 1` for actual bundle cards.\n const { data: bundlesData } = useBundles({\n enabled: !!customerId && !isLoadingCustomer && bundlingEnabled,\n });\n\n // Drawer + dialog state.\n const [bundleDrawerOpen, setBundleDrawerOpen] = useState(false);\n const [bundleDrawerKey, setBundleDrawerKey] = useState(0);\n const [addressDialog, setAddressDialog] = useState<{\n open: boolean;\n selected: fluidPay.CustomerAddress | null;\n }>({ open: false, selected: null });\n const [isAddCardOpen, setIsAddCardOpen] = useState(false);\n const [saveCardError, setSaveCardError] = useState<string | null>(null);\n // `isBundling` covers the FULL handleBundle async span (createBundle +\n // per-token payment-method PUT loop), not just createBundle.isPending.\n // Without this, the submit button would re-enable after createBundle\n // resolved while the PUT loop was still in flight, allowing a duplicate\n // bundle creation request.\n const [isBundling, setIsBundling] = useState(false);\n\n const { data: countriesData } = useQuery({\n queryKey: storeKeys.countries(locale),\n queryFn: () => countriesApi.listCountries({ languageIso: locale }),\n enabled: addressDialog.open || isAddCardOpen,\n });\n const countryOptions = useMemo(\n () =>\n [...(countriesData?.countries ?? [])]\n .map((c) => ({ iso: c.code, name: c.name }))\n .sort((a, b) => a.name.localeCompare(b.name)),\n [countriesData],\n );\n const statesByCountry = useMemo(() => {\n const map = new Map<string, State[]>();\n for (const c of countriesData?.countries ?? []) {\n map.set(\n c.code,\n c.states.map((s) => ({ name: s.name, isoCode: s.code })),\n );\n }\n return map;\n }, [countriesData]);\n const fetchStatesFromCountries = useCallback(\n (countryCode: string): Promise<State[]> =>\n Promise.resolve(statesByCountry.get(countryCode) ?? []),\n [statesByCountry],\n );\n\n const createAddressMutation = useMutation({\n // Detect a server-side dedupe (POST /api/pay/addresses returns the existing\n // record when an identical address already exists, ignoring `name`). Snapshot\n // the current id set before the request and compare against the returned id.\n mutationFn: async (body: fluidPay.CreateAddressBody) => {\n const existingIds = new Set(addresses.map((a) => a.id));\n const address = await payApi.createAddress({\n address: {\n name: body.address.name,\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n phone: body.address.phone,\n default: body.address.default,\n },\n });\n return { address, deduped: existingIds.has(address.id) };\n },\n onSuccess: ({ deduped }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (deduped) {\n onToast?.(profileT(\"address_already_exists\"), \"warning\");\n } else {\n onToast?.(profileT(\"address_created\"), \"success\");\n }\n },\n onError: () => onToast?.(profileT(\"failed_to_create_address\"), \"error\"),\n });\n\n // Bridge for the 3DS modal that accepts `t: (key: string) => string`; the\n // adapter falls back to `key` for unknown keys, so widening is safe.\n const tFn = useCallback(\n (key: string): string => profileT(key as never),\n [profileT],\n );\n\n // Wire 3DS-on-card-add: when the BFF returns three_ds_required, hand off to the\n // challenge flow instead of treating the create as a saved card. Invalidation +\n // close + toast live in onApproved (3DS) and onCreated (non-3DS), never on the\n // raw mutation, so the three_ds_required path keeps the dialog open behind the\n // challenge modal. Mirrors the profile + per-subscription surfaces.\n const cardAdd3DS = usePortalCardAdd3DSFlow({\n payApi,\n t: tFn,\n onApproved: async () => {\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n setIsAddCardOpen(false);\n onToast?.(profileT(\"payment_method_added\"), \"success\");\n },\n onFailed: (message) => {\n setSaveCardError(message);\n },\n onCanceled: () => {},\n });\n\n const cardAddSuccess = buildSubscriptionCardAddSuccess({\n begin: cardAdd3DS.begin,\n onCreated: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.paymentMethods.all });\n setIsAddCardOpen(false);\n onToast?.(profileT(\"payment_method_added\"), \"success\");\n },\n });\n\n const addCreditCardMutation = useMutation({\n mutationFn: (data: CreditCardFormSubmitData) =>\n payApi.createPaymentMethod({\n payment_method: {\n type: \"card\",\n token: data.payment_method.token,\n token_provider: TOKEN_PROVIDER_VGS,\n exp_month: data.payment_method.exp_month,\n exp_year: data.payment_method.exp_year,\n cvv_token: data.payment_method.cvv_token,\n card_holder: data.payment_method.card_holder,\n default: data.set_as_default,\n ...(data.payment_method.bin ? { bin: data.payment_method.bin } : {}),\n ...(data.payment_method.last_four\n ? { last_four: data.payment_method.last_four }\n : {}),\n ...(data.payment_method.card_network\n ? { card_network: data.payment_method.card_network }\n : {}),\n },\n billing_address_id: data.billing_address_id,\n browser_info: getBrowserInfo(),\n }),\n onSuccess: cardAddSuccess,\n onError: () => onToast?.(profileT(\"failed_to_add_payment_method\"), \"error\"),\n });\n\n const createBundle = useCreateBundle();\n const updateSubscription = useUpdateSubscriptionInfo();\n\n const handleBundleClick = () => {\n setBundleDrawerKey((k) => k + 1);\n setBundleDrawerOpen(true);\n };\n\n const handleBundle = async (params: {\n subscription_tokens: string[];\n next_bill_date: string;\n address_id: number;\n payment_method_id: number;\n }) => {\n if (isBundling) return;\n setIsBundling(true);\n try {\n await createBundle.mutateAsync({\n subscription_tokens: params.subscription_tokens,\n next_bill_date: params.next_bill_date,\n address_id: params.address_id,\n });\n } catch (err) {\n // Surface the BFF's validation message (e.g. \"cannot bundle a cancelled\n // subscription\") instead of a generic \"Please try again\" — FetchClient\n // already extracts `data.message` from the JSON body into ApiError.\n // Only trust the message when it's a 4xx ApiError (real validation); on\n // 5xx or non-ApiError throws, fall through to the localized fallback so\n // users never see FetchClient's \"POST request failed\" default.\n const bffMessage =\n isApiError(err) && err.status >= 400 && err.status < 500\n ? err.message\n : undefined;\n const message = bffMessage ?? t(\"bundle_failed\");\n onToast?.(message, \"error\");\n setIsBundling(false);\n return;\n }\n\n // PUT-loop workaround: the BFF create endpoint accepts subscription_tokens,\n // next_bill_date, address_id, and volume_rep_id only — it does NOT honor\n // payment_method_id. Push the chosen payment method onto each member sub\n // via the existing per-subscription update endpoint. Settle all in\n // parallel so a single 4xx doesn't block the others.\n const results = await Promise.allSettled(\n params.subscription_tokens.map((token) =>\n updateSubscription.mutateAsync({\n subscriptionToken: token,\n body: { payment_method_id: params.payment_method_id },\n }),\n ),\n );\n const failedCount = results.filter((r) => r.status === \"rejected\").length;\n if (failedCount === 0) {\n onToast?.(t(\"bundle_succeeded\"), \"success\");\n } else {\n onToast?.(\n t(\"bundle_partial_payment_failure\", { n: String(failedCount) }),\n \"warning\",\n );\n }\n setBundleDrawerOpen(false);\n setIsBundling(false);\n };\n\n const goToDetail = (token: string) => navigate(`subscriptions/${token}`);\n\n return (\n <>\n <PortalSubscriptionsList\n customerId={customerId}\n isLoadingCustomer={isLoadingCustomer}\n onSubscriptionClick={goToDetail}\n onResume={(sub) => goToDetail(sub.subscription_token)}\n onBundleClick={\n bundlingEnabled && bundleableSubscriptions.length >= 2\n ? handleBundleClick\n : undefined\n }\n bundles={bundlingEnabled ? bundlesData : undefined}\n />\n\n {bundlingEnabled && (\n <BundleSubscriptionsDrawer\n key={bundleDrawerKey}\n open={bundleDrawerOpen}\n onOpenChange={setBundleDrawerOpen}\n subscriptions={bundleableSubscriptions}\n addresses={addresses}\n paymentMethods={paymentMethods}\n defaultAddressId={\n addresses.find((a) => a.default)?.id ?? addresses[0]?.id ?? null\n }\n defaultPaymentMethodId={\n paymentMethods.find((pm) => pm.default)?.id ??\n paymentMethods[0]?.id ??\n null\n }\n onAddAddress={() => setAddressDialog({ open: true, selected: null })}\n onAddPaymentMethod={() => setIsAddCardOpen(true)}\n onSubmit={handleBundle}\n isSubmitting={isBundling}\n />\n )}\n\n <AddressFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={addressDialog.open}\n onClose={() => setAddressDialog({ open: false, selected: null })}\n selectedAddress={addressDialog.selected}\n defaultCountry={\n addresses.find((a) => a.default)?.country_code ??\n config.countryIso ??\n \"US\"\n }\n languageIso={locale}\n t={addressDialogT}\n onSubmit={async (formData) => {\n try {\n await createAddressMutation.mutateAsync(formData);\n setAddressDialog({ open: false, selected: null });\n } catch {\n // toast surfaced via onError\n }\n }}\n isSubmitting={createAddressMutation.isPending}\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n />\n\n <CreditCardFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isAddCardOpen}\n onClose={() => {\n // Don't let the card dialog close mid-challenge — the 3DS modal owns\n // teardown while active.\n if (cardAdd3DS.isActive) return;\n setSaveCardError(null);\n setIsAddCardOpen(false);\n }}\n t={addressDialogT}\n error={saveCardError ?? undefined}\n onSubmit={async (data) => {\n setSaveCardError(null);\n try {\n await addCreditCardMutation.mutateAsync(data);\n // Close + toast are handled by cardAddSuccess (created) or the 3DS\n // flow (approved) — never here, so three_ds_required keeps the card\n // dialog open behind the challenge modal.\n } catch {\n // toast surfaced via onError\n }\n }}\n isSubmitting={addCreditCardMutation.isPending}\n jwt=\"\"\n savedAddresses={addresses}\n defaultBillingAddressId={addresses.find((a) => a.default)?.id}\n renderAddressFormDialog={({ isOpen, onClose, onAddressCreated }) => (\n <AddressFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isOpen}\n onClose={onClose}\n selectedAddress={null}\n defaultCountry={\n addresses.find((a) => a.default)?.country_code ??\n config.countryIso ??\n \"US\"\n }\n languageIso={locale}\n t={addressDialogT}\n onSubmit={async (formData) => {\n try {\n const { address } =\n await createAddressMutation.mutateAsync(formData);\n onAddressCreated(mapToFluidPayAddress(address));\n } catch {\n // toast surfaced via onError\n }\n }}\n isSubmitting={createAddressMutation.isPending}\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n />\n )}\n />\n {cardAdd3DS.modal}\n </>\n );\n}\n\nexport function SubscriptionsListScreen(\n props: SubscriptionsListScreenProps,\n): React.JSX.Element {\n const payApi = usePayApi();\n const fluidPayShim = useMemo(\n () => createFluidPayApiAdapter(payApi),\n [payApi],\n );\n return (\n <FluidPayCoreProvider api={fluidPayShim}>\n <ProfileTranslationBridge>\n <SubscriptionsListScreenInner {...props} />\n </ProfileTranslationBridge>\n </FluidPayCoreProvider>\n );\n}\n","import type React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Button,\n DialogFooter,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\n\nconst PAUSE_MONTH_OPTIONS = [1, 2, 3] as const;\nexport type PauseMonths = (typeof PAUSE_MONTH_OPTIONS)[number];\n\nexport interface CancelSubscriptionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void | Promise<unknown>;\n onPauseInstead: (months: PauseMonths) => void;\n errorMessage?: string;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function CancelSubscriptionDialog({\n open,\n onOpenChange,\n onConfirm,\n onPauseInstead,\n errorMessage,\n presentation = \"dialog\",\n}: CancelSubscriptionDialogProps): React.JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const [isPending, setIsPending] = useState(false);\n const [selectedMonths, setSelectedMonths] = useState<PauseMonths | null>(\n null,\n );\n\n useEffect(() => {\n if (!open) setSelectedMonths(null);\n }, [open]);\n\n const handleConfirm = async () => {\n const result = onConfirm();\n if (!(result instanceof Promise)) {\n onOpenChange(false);\n return;\n }\n setIsPending(true);\n try {\n await result;\n onOpenChange(false);\n } catch (error) {\n // Leave the dialog open so the parent can surface errorMessage inline.\n console.error(\"CancelSubscriptionDialog: action rejected\", error);\n } finally {\n setIsPending(false);\n }\n };\n\n const handlePause = () => {\n if (!selectedMonths) return;\n onPauseInstead(selectedMonths);\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(v) => !isPending && onOpenChange(v)}\n title={t(\"cancel_dialog_title\")}\n description={t(\"cancel_dialog_description\")}\n role=\"alertdialog\"\n presentation={presentation}\n >\n <div className=\"border-border space-y-2 rounded-md border p-3\">\n <p className=\"text-foreground text-sm font-medium\">\n {t(\"cancel_dialog_pause_question\")}\n </p>\n <Label\n htmlFor=\"cancel-pause-months\"\n className=\"text-foreground text-sm font-semibold\"\n >\n {t(\"pause_for\")}\n </Label>\n <Select\n value={selectedMonths ? String(selectedMonths) : undefined}\n onValueChange={(value) =>\n setSelectedMonths(value ? (Number(value) as PauseMonths) : null)\n }\n disabled={isPending}\n >\n <SelectTrigger id=\"cancel-pause-months\" className=\"w-full\">\n <SelectValue placeholder={t(\"select_duration\")} />\n </SelectTrigger>\n <SelectContent>\n {PAUSE_MONTH_OPTIONS.map((months) => (\n <SelectItem key={months} value={String(months)}>\n {months === 1\n ? t(\"month_singular\", { count: String(months) })\n : t(\"month_plural\", { count: String(months) })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Button\n variant=\"outline\"\n onClick={handlePause}\n disabled={isPending || !selectedMonths}\n className=\"w-full\"\n >\n {t(\"cancel_dialog_pause_button\")}\n </Button>\n </div>\n\n {errorMessage && (\n <p className=\"text-destructive text-left text-sm\">{errorMessage}</p>\n )}\n\n <DialogFooter className=\"flex-col gap-2 sm:flex-row sm:justify-end\">\n <Button\n variant=\"secondary\"\n onClick={() => onOpenChange(false)}\n disabled={isPending}\n >\n {t(\"cancel_dialog_cancel_button\")}\n </Button>\n {/*\n Plain Button rather than AlertDialogAction: Action auto-closes\n the dialog after onClick, which races handleConfirm's async\n path — the dialog would dismiss before the mutation settled,\n the spinner would never show, and an inline errorMessage would\n never be visible. handleConfirm calls onOpenChange itself on\n success and intentionally leaves the dialog open on rejection.\n */}\n <Button\n variant=\"destructive\"\n onClick={handleConfirm}\n disabled={isPending}\n >\n {isPending\n ? t(\"loading_ellipsis\")\n : t(\"cancel_dialog_confirm_button\")}\n </Button>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","/**\n * Format a number as currency (USD).\n */\nexport function formatCurrency(value: number): string {\n return new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }).format(value);\n}\n\n/**\n * Maps a billing_interval_unit to its singular/plural translation keys\n * (`unit_day`/`unit_days`, …). Single source of truth for cadence-unit\n * pluralization across the subscription detail screen and the bundled-with card.\n */\nexport const UNIT_KEYS: Record<string, { singular: string; plural: string }> = {\n day: { singular: \"unit_day\", plural: \"unit_days\" },\n week: { singular: \"unit_week\", plural: \"unit_weeks\" },\n month: { singular: \"unit_month\", plural: \"unit_months\" },\n year: { singular: \"unit_year\", plural: \"unit_years\" },\n};\n\n/** Statuses that have a corresponding `list_status_*` translation key. */\nexport const KNOWN_STATUSES = new Set([\n \"active\",\n \"paused\",\n \"cancelled\",\n \"completed\",\n \"past_due\",\n \"pending\",\n]);\n\n/**\n * Convert a snake_case or lowercase string to Start Case.\n * Replaces lodash startCase for simple status strings.\n */\nexport function startCase(str: string | undefined | null): string {\n if (!str) return \"\";\n return str.replace(/_/g, \" \").replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Format a Date as a long human-readable string (e.g. \"May 29, 2026\")\n * using the active locale so month names are translated.\n */\nexport function formatLongDate(date: Date, locale: string = \"en-US\"): string {\n try {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n } catch {\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n }).format(date);\n }\n}\n\n/**\n * Format a Date as a medium-length string (e.g. \"May 29, 2026\")\n * using abbreviated month names, locale-aware.\n */\nexport function formatMediumDate(date: Date, locale: string = \"en-US\"): string {\n try {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n }).format(date);\n } catch {\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n }).format(date);\n }\n}\n\n/**\n * Format a next bill date string in a locale-aware short format (UTC).\n */\nexport function formatNextBillDate(\n nextBillDate: string,\n locale: string = \"en-US\",\n): string {\n if (!nextBillDate) return \"\";\n const date = new Date(nextBillDate);\n if (isNaN(date.getTime())) return \"\";\n try {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n timeZone: \"UTC\",\n }).format(date);\n } catch {\n // Intl throws on invalid locale values — fall back to en-US rather\n // than crashing the component.\n return new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n timeZone: \"UTC\",\n }).format(date);\n }\n}\n\n/**\n * Show the completed display status before any stale next bill date.\n */\nexport function formatNextBillDisplay(\n nextBillDate: string | null | undefined,\n displayStatus: string,\n labels: { completed: string; unavailable: string },\n locale: string = \"en-US\",\n): string {\n if (displayStatus === \"completed\") return labels.completed;\n\n return formatNextBillDate(nextBillDate ?? \"\", locale) || labels.unavailable;\n}\n","import type React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { calculateResumeDate } from \"@fluid-app/subscriptions-core\";\nimport { getMaxSkippableOrders } from \"@fluid-app/subscriptions-core/utils/subscription-helpers\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { Button, DialogFooter, Label } from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { formatLongDate } from \"../lib/format\";\n\ntype PauseType = \"indefinite\" | \"order_count\";\n\nexport type PauseSubscriptionSelection =\n | { type: \"indefinite\" }\n | { type: \"order_count\"; numberOfOrders: number };\n\nexport interface PauseSubscriptionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: (selection: PauseSubscriptionSelection) => void;\n isLoading?: boolean;\n errorMessage?: string;\n currentNextBillDate?: string | null;\n billingInterval?: number;\n billingIntervalUnit?: string;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function PauseSubscriptionDialog({\n open,\n onOpenChange,\n onConfirm,\n isLoading,\n errorMessage,\n currentNextBillDate,\n billingInterval = 1,\n billingIntervalUnit = \"month\",\n presentation = \"dialog\",\n}: PauseSubscriptionDialogProps): React.JSX.Element {\n const { t, locale } = useSubscriptionsTranslation();\n const [pauseType, setPauseType] = useState<PauseType>(\"indefinite\");\n const [selectedOrderCount, setSelectedOrderCount] = useState<number | null>(\n null,\n );\n\n // Only the counts the API would accept. Skipping N orders sets a bill date N\n // intervals out, and the API caps that date, so the old fixed 1-99 list\n // offered pauses that came back as a 422 naming number_of_orders.\n const maxSkippableOrders = getMaxSkippableOrders(\n billingInterval,\n billingIntervalUnit,\n currentNextBillDate,\n );\n const orderCountOptions = Array.from(\n { length: maxSkippableOrders },\n (_, i) => i + 1,\n );\n\n const calculatedResumeDate =\n selectedOrderCount && currentNextBillDate\n ? calculateResumeDate(\n billingInterval,\n billingIntervalUnit,\n selectedOrderCount,\n currentNextBillDate,\n )\n : null;\n\n // Reset selections whenever the dialog opens so stale state doesn't\n // leak across invocations.\n useEffect(() => {\n if (!open) return;\n setPauseType(\"indefinite\");\n setSelectedOrderCount(null);\n }, [open]);\n\n const handleConfirm = () => {\n if (pauseType === \"indefinite\") {\n onConfirm({ type: \"indefinite\" });\n return;\n }\n if (pauseType === \"order_count\" && selectedOrderCount) {\n onConfirm({\n type: \"order_count\",\n numberOfOrders: selectedOrderCount,\n });\n }\n };\n\n const handleDismiss = (next: boolean) => {\n if (!next) {\n setPauseType(\"indefinite\");\n setSelectedOrderCount(null);\n }\n onOpenChange(next);\n };\n\n const statusMessage = (() => {\n if (pauseType === \"indefinite\") {\n return (\n <>\n {t(\"pause_indefinite_message_prefix\")}{\" \"}\n <strong>{t(\"pause_indefinite_message_resume\")}</strong>{\" \"}\n {t(\"pause_indefinite_message_suffix\")}\n </>\n );\n }\n if (!selectedOrderCount) return null;\n const displayDate = calculatedResumeDate\n ? formatLongDate(calculatedResumeDate, locale)\n : t(\"a_future_date\");\n return (\n <>\n {t(\"pause_resume_message_prefix\")}{\" \"}\n <span className=\"font-semibold\">{displayDate}</span>\n {t(\"pause_resume_message_suffix\")}\n </>\n );\n })();\n\n const isActionDisabled = pauseType === \"order_count\" && !selectedOrderCount;\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleDismiss}\n title={t(\"pause_dialog_title\")}\n description={t(\"pause_dialog_description\")}\n presentation={presentation}\n >\n <div className=\"space-y-4\">\n <div className=\"space-y-4\">\n {/* Pause Indefinitely */}\n <div className=\"flex items-center gap-x-2\">\n <input\n id=\"pause-indefinitely\"\n type=\"radio\"\n checked={pauseType === \"indefinite\"}\n onChange={() => setPauseType(\"indefinite\")}\n className=\"border-border accent-primary size-4 focus:ring-0\"\n />\n <Label\n htmlFor=\"pause-indefinitely\"\n className=\"text-foreground cursor-pointer text-sm font-medium\"\n >\n {t(\"pause_indefinitely\")}\n </Label>\n </div>\n\n {/* Pause for Number of Orders */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-x-2\">\n <input\n id=\"pause-order-count\"\n type=\"radio\"\n checked={pauseType === \"order_count\"}\n onChange={() => setPauseType(\"order_count\")}\n // A subscription whose next bill date already sits near the cap\n // has no acceptable count, so the choice reads as unavailable\n // rather than opening an empty dropdown. Indefinite still works.\n disabled={maxSkippableOrders === 0}\n className=\"border-border accent-primary size-4 focus:ring-0 disabled:opacity-40\"\n />\n <Label\n htmlFor=\"pause-order-count\"\n className={`text-sm font-medium ${\n maxSkippableOrders === 0\n ? \"text-muted-foreground cursor-not-allowed\"\n : \"text-foreground cursor-pointer\"\n }`}\n >\n {t(\"pause_for_orders\")}\n </Label>\n </div>\n\n {pauseType === \"order_count\" && (\n <div className=\"ml-6 space-y-2\">\n <Label className=\"text-foreground text-sm font-semibold\">\n {t(\"choose_orders_to_skip\")}\n </Label>\n <select\n value={selectedOrderCount ?? \"\"}\n onChange={(e) =>\n setSelectedOrderCount(Number(e.target.value))\n }\n className=\"border-input bg-background focus:border-ring focus:ring-ring h-10 w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-hidden\"\n >\n <option value=\"\" disabled>\n {t(\"select\")}\n </option>\n {orderCountOptions.map((count) => (\n <option key={count} value={count}>\n {count}\n </option>\n ))}\n </select>\n </div>\n )}\n </div>\n\n {/* Status Message */}\n {statusMessage && (\n <div className=\"text-muted-foreground text-xs\">{statusMessage}</div>\n )}\n </div>\n </div>\n\n {errorMessage && (\n <p className=\"text-destructive text-left text-sm\">{errorMessage}</p>\n )}\n\n <DialogFooter>\n <div className=\"flex w-full flex-row justify-between gap-x-2\">\n <Button\n variant=\"outline\"\n className=\"h-10 min-w-[70px] rounded p-3\"\n onClick={() => handleDismiss(false)}\n >\n {t(\"pause_dialog_cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"h-10 min-w-[70px] rounded p-3\"\n onClick={handleConfirm}\n disabled={isActionDisabled || isLoading}\n >\n {isLoading ? (\n <div className=\"border-primary-foreground size-5 animate-spin rounded-full border-4 border-t-4 border-t-transparent\" />\n ) : (\n t(\"pause_dialog_action\")\n )}\n </Button>\n </div>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import { parse } from \"date-fns\";\n\nconst ISO_DATE = \"yyyy-MM-dd\";\n\n/**\n * Parse an ISO date string as local midnight. Accepts either a bare\n * \"yyyy-MM-dd\" or a full ISO timestamp — both are sliced to the date\n * portion first so the result lands on the intended calendar day\n * regardless of the viewer's timezone.\n */\nexport function parseIsoDate(value: string): Date {\n return parse(value.slice(0, 10), ISO_DATE, new Date());\n}\n","import type React from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Button,\n Calendar,\n cn,\n DialogFooter,\n Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n PortalContainerProvider,\n} from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { addDays, format } from \"date-fns\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { formatLongDate } from \"../lib/format\";\nimport { parseIsoDate } from \"../lib/parse-iso-date\";\n\nexport interface ResumeSubscriptionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: (nextBillDate: string) => void;\n isLoading?: boolean;\n errorMessage?: string;\n /** Seeds the calendar; must be in the future. Defaults to tomorrow. */\n defaultNextBillDate?: string | null;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function ResumeSubscriptionDialog({\n open,\n onOpenChange,\n onConfirm,\n isLoading,\n errorMessage,\n defaultNextBillDate,\n presentation = \"dialog\",\n}: ResumeSubscriptionDialogProps): React.JSX.Element {\n const { t, locale } = useSubscriptionsTranslation();\n const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);\n const [calendarOpen, setCalendarOpen] = useState(false);\n // Anchor the popover's portal inside the dialog so Safari doesn't swallow\n // clicks on the calendar — Radix renders the popover into document.body by\n // default, but Dialog applies pointer-events: none to the body while open,\n // which kills clicks on a body-portaled popover in Safari/WebKit.\n const [popoverContainer, setPopoverContainer] =\n useState<HTMLDivElement | null>(null);\n\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n const minDate = addDays(today, 1);\n\n // Seed selected date when the dialog opens.\n useEffect(() => {\n if (!open) return;\n if (defaultNextBillDate) {\n const seeded = parseIsoDate(defaultNextBillDate);\n setSelectedDate(seeded < minDate ? minDate : seeded);\n } else {\n setSelectedDate(minDate);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, defaultNextBillDate]);\n\n const handleConfirm = () => {\n if (!selectedDate) return;\n onConfirm(format(selectedDate, \"yyyy-MM-dd\"));\n };\n\n const handleDismiss = (next: boolean) => {\n if (!next) {\n setSelectedDate(undefined);\n // Reset so the calendar never reopens already-open: the popover's portal\n // container unmounts on close, and reopening with it still open would\n // render into document.body for a frame, reviving the Safari click bug.\n setCalendarOpen(false);\n }\n onOpenChange(next);\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleDismiss}\n title={t(\"resume_dialog_title\")}\n description={t(\"resume_dialog_description\")}\n presentation={presentation}\n // Let the calendar popover float past the modal edge instead of being\n // cropped by the dialog's default overflow-hidden. The popover stays\n // portaled inside the dialog (see below) so WebKit still delivers its\n // clicks; this only stops the content box from clipping it.\n contentOverflow=\"visible\"\n >\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label className=\"text-foreground text-sm font-semibold\">\n {t(\"resume_date\")}\n </Label>\n {/* Render the popover into a fixed-positioned overlay nested inside\n the dialog rather than document.body. This sidesteps the\n WebKit/Safari issue where Dialog's body-level pointer-events:\n none silently blocks clicks on a body-portaled popover. The\n fixed overlay is `inset-0` + `pointer-events-none` so it doesn't\n capture stray clicks or affect dialog layout — only the popover\n content (which sets its own pointer-events: auto) is\n interactive. */}\n <PortalContainerProvider container={popoverContainer}>\n <Popover open={calendarOpen} onOpenChange={setCalendarOpen}>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n className={cn(\n \"border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground h-9 w-full justify-start border px-3 py-2 text-left font-normal\",\n !selectedDate &&\n \"text-muted-foreground hover:text-muted-foreground\",\n )}\n >\n {selectedDate ? (\n format(selectedDate, \"MM/dd/yyyy\")\n ) : (\n <span>{t(\"date_placeholder\")}</span>\n )}\n <CalendarIcon className=\"text-muted-foreground ml-auto size-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"bg-popover pointer-events-auto z-[9999] w-auto rounded-md border p-0 shadow-lg\"\n align=\"start\"\n sideOffset={4}\n >\n <Calendar\n mode=\"single\"\n selected={selectedDate}\n onSelect={(date) => {\n setSelectedDate(date);\n setCalendarOpen(false);\n }}\n disabled={(date) => date < minDate}\n defaultMonth={selectedDate}\n modifiersStyles={{\n selected: {\n backgroundColor: \"var(--primary)\",\n color: \"var(--primary-foreground)\",\n },\n }}\n initialFocus\n />\n </PopoverContent>\n </Popover>\n </PortalContainerProvider>\n <div\n ref={setPopoverContainer}\n className=\"pointer-events-none fixed inset-0 z-[9998]\"\n />\n {selectedDate && (\n <p className=\"text-muted-foreground text-xs\">\n {t(\"resume_charge_message_prefix\")}{\" \"}\n <span className=\"font-semibold\">\n {formatLongDate(selectedDate, locale)}\n </span>\n {t(\"resume_charge_message_suffix\")}\n </p>\n )}\n </div>\n </div>\n\n {errorMessage && (\n <p className=\"text-destructive text-left text-sm\">{errorMessage}</p>\n )}\n\n <DialogFooter>\n <div className=\"flex w-full flex-row justify-between gap-x-2\">\n <Button\n className=\"bg-muted text-foreground ring-border hover:bg-muted/80 h-10 min-w-[70px] rounded p-3 ring-1\"\n onClick={() => handleDismiss(false)}\n >\n {t(\"resume_dialog_cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"bg-primary text-primary-foreground h-10 min-w-[70px] rounded p-3 hover:opacity-90 disabled:opacity-50\"\n onClick={handleConfirm}\n disabled={!selectedDate || isLoading}\n >\n {isLoading ? (\n <div className=\"border-primary-foreground size-5 animate-spin rounded-full border-4 border-t-4 border-t-transparent\" />\n ) : (\n t(\"resume_dialog_action\")\n )}\n </Button>\n </div>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import type React from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { getMaxEditableBillDate } from \"@fluid-app/subscriptions-core/utils/subscription-helpers\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Button,\n Calendar,\n cn,\n DialogFooter,\n Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n PortalContainerProvider,\n} from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport {\n addDays,\n addMonths,\n addWeeks,\n addYears,\n format,\n isAfter,\n} from \"date-fns\";\nimport { CalendarIcon, ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { formatLongDate, formatMediumDate } from \"../lib/format\";\nimport { parseIsoDate } from \"../lib/parse-iso-date\";\n\nexport interface OtherSubscriptionForBillDate {\n token: string;\n productTitle: string;\n nextBillDate: string | null;\n billingInterval: number;\n billingIntervalUnit: string;\n}\n\nfunction advanceByInterval(date: Date, interval: number, unit: string): Date {\n const step = Math.max(1, interval);\n switch (unit.toLowerCase()) {\n case \"day\":\n return addDays(date, step);\n case \"week\":\n return addWeeks(date, step);\n case \"year\":\n return addYears(date, step);\n case \"month\":\n default:\n return addMonths(date, step);\n }\n}\n\nconst SUBSCRIPTION_COLORS = [\n \"#3b82f6\",\n \"#f97316\",\n \"#10b981\",\n \"#a855f7\",\n \"#ec4899\",\n \"#eab308\",\n \"#14b8a6\",\n \"#ef4444\",\n \"#0ea5e9\",\n \"#84cc16\",\n];\n\n// Cap projection iterations per subscription so a daily-interval row can't\n// run away tens of thousands of times across the 2-year horizon. Sized for\n// a weekly cycle (~104 over two years) — covers the longest realistic\n// non-daily case without truncating dots for the rep.\nconst MAX_PROJECTIONS_PER_SUB = 104;\n\nexport interface EditBillDateDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: (nextBillDate: string) => void;\n isLoading?: boolean;\n errorMessage?: string;\n currentNextBillDate?: string | null;\n billingInterval?: number;\n billingIntervalUnit?: string;\n otherSubscriptions?: OtherSubscriptionForBillDate[];\n onNavigateToSubscription?: (token: string) => void;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function EditBillDateDialog({\n open,\n onOpenChange,\n onConfirm,\n isLoading,\n errorMessage,\n currentNextBillDate,\n billingInterval = 1,\n billingIntervalUnit = \"month\",\n otherSubscriptions,\n onNavigateToSubscription,\n presentation = \"dialog\",\n}: EditBillDateDialogProps): React.JSX.Element {\n const { t, locale } = useSubscriptionsTranslation();\n const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);\n const [calendarOpen, setCalendarOpen] = useState(false);\n // Anchor the popover's portal inside the dialog so Safari doesn't\n // swallow clicks on the calendar — Radix renders the popover into\n // document.body by default, but Dialog applies pointer-events: none\n // to the body while open, which kills clicks on a body-portaled\n // popover in Safari/WebKit specifically.\n const [popoverContainer, setPopoverContainer] =\n useState<HTMLDivElement | null>(null);\n\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n const minDate = addDays(today, 1);\n // Yearly plans may move their bill date up to 2 years out, everything\n // else up to 12 months out.\n const maxDate = getMaxEditableBillDate(\n billingInterval,\n billingIntervalUnit,\n today,\n );\n\n const subscriptionsWithColor = useMemo(\n () =>\n (otherSubscriptions ?? []).map((sub, idx) => ({\n ...sub,\n color: SUBSCRIPTION_COLORS[idx % SUBSCRIPTION_COLORS.length] as string,\n })),\n [otherSubscriptions],\n );\n\n const billingColorsByDate = useMemo<Map<string, string[]>>(() => {\n const m = new Map<string, string[]>();\n const horizon = addYears(new Date(), 2);\n for (const sub of subscriptionsWithColor) {\n if (!sub.nextBillDate) continue;\n let d = parseIsoDate(sub.nextBillDate);\n let count = 0;\n while (!isAfter(d, horizon) && count < MAX_PROJECTIONS_PER_SUB) {\n const key = format(d, \"yyyy-MM-dd\");\n const arr = m.get(key) ?? [];\n arr.push(sub.color);\n m.set(key, arr);\n d = advanceByInterval(d, sub.billingInterval, sub.billingIntervalUnit);\n count++;\n }\n }\n return m;\n }, [subscriptionsWithColor]);\n\n // Memoize the components map: react-day-picker uses each entry's identity\n // as the React element type for every day cell, so a fresh object every\n // render unmounts/remounts all visible cells (visible flicker, lost cell\n // state).\n const calendarComponents = useMemo(\n () => ({\n DayContent: ({ date }: { date: Date }) => {\n const key = format(date, \"yyyy-MM-dd\");\n const colors = billingColorsByDate.get(key) ?? [];\n return (\n <div className=\"flex h-full w-full flex-col items-center justify-center\">\n <span className=\"leading-none\">{date.getDate()}</span>\n {colors.length > 0 && (\n <div className=\"mt-0.5 flex items-center justify-center gap-0.5\">\n {colors.map((c, i) => (\n <span\n key={`${key}-${i}`}\n className=\"size-1 rounded-[1px]\"\n style={{ backgroundColor: c }}\n />\n ))}\n </div>\n )}\n </div>\n );\n },\n IconLeft: ({\n className: iconClassName,\n ...iconProps\n }: React.ComponentProps<typeof ChevronLeft>) => (\n <ChevronLeft className={cn(\"h-4 w-4\", iconClassName)} {...iconProps} />\n ),\n IconRight: ({\n className: iconClassName,\n ...iconProps\n }: React.ComponentProps<typeof ChevronRight>) => (\n <ChevronRight className={cn(\"h-4 w-4\", iconClassName)} {...iconProps} />\n ),\n }),\n [billingColorsByDate],\n );\n\n useEffect(() => {\n if (!open) return;\n if (currentNextBillDate) {\n const initial = parseIsoDate(currentNextBillDate);\n setSelectedDate(\n initial < minDate ? minDate : initial > maxDate ? maxDate : initial,\n );\n } else {\n setSelectedDate(undefined);\n }\n // minDate/maxDate derive from `new Date()` — intentionally excluded so\n // this only runs on open transitions.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, currentNextBillDate]);\n\n const handleConfirm = () => {\n if (!selectedDate) return;\n onConfirm(format(selectedDate, \"yyyy-MM-dd\"));\n };\n\n const handleDismiss = (next: boolean) => {\n if (!next) {\n setSelectedDate(undefined);\n // Reset so the calendar never reopens already-open: the popover's portal\n // container unmounts on close, and reopening with it still open would\n // render into document.body for a frame, reviving the Safari click bug.\n setCalendarOpen(false);\n }\n onOpenChange(next);\n };\n\n const previewDate = selectedDate\n ? formatLongDate(selectedDate, locale)\n : currentNextBillDate\n ? formatLongDate(parseIsoDate(currentNextBillDate), locale)\n : t(\"a_future_date\");\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleDismiss}\n title={t(\"edit_bill_date_title\")}\n description={t(\"edit_bill_date_description\")}\n presentation={presentation}\n // Let the calendar popover float past the modal edge instead of being\n // cropped by the dialog's default overflow-hidden. The popover stays\n // portaled inside the dialog (see below) so WebKit still delivers its\n // clicks; this only stops the content box from clipping it.\n contentOverflow=\"visible\"\n >\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label className=\"text-foreground text-sm font-semibold\">\n {t(\"next_bill_date_label\")}\n </Label>\n {/* Render the popover into a fixed-positioned overlay nested\n inside the dialog rather than document.body. This sidesteps\n the WebKit/Safari issue where Dialog's body-level\n pointer-events: none silently blocks clicks on a body-\n portaled popover. The fixed overlay is `inset-0` +\n `pointer-events-none` so it doesn't capture stray clicks\n or affect dialog layout — only the popover content\n (which sets its own pointer-events: auto) is interactive. */}\n <PortalContainerProvider container={popoverContainer}>\n <Popover open={calendarOpen} onOpenChange={setCalendarOpen}>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n className={cn(\n \"border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground h-9 w-full justify-start border px-3 py-2 text-left font-normal\",\n !selectedDate &&\n \"text-muted-foreground hover:text-muted-foreground\",\n )}\n >\n {selectedDate ? (\n format(selectedDate, \"MM/dd/yyyy\")\n ) : (\n <span>{t(\"date_placeholder\")}</span>\n )}\n <CalendarIcon className=\"text-muted-foreground ml-auto size-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"bg-popover pointer-events-auto z-[9999] w-auto rounded-md border p-0 shadow-lg\"\n align=\"start\"\n sideOffset={4}\n >\n <Calendar\n mode=\"single\"\n selected={selectedDate}\n onSelect={(date) => {\n setSelectedDate(date);\n setCalendarOpen(false);\n }}\n disabled={(date) => date < minDate || date > maxDate}\n defaultMonth={\n selectedDate ??\n (currentNextBillDate\n ? parseIsoDate(currentNextBillDate)\n : undefined)\n }\n components={calendarComponents}\n initialFocus\n />\n </PopoverContent>\n </Popover>\n </PortalContainerProvider>\n </div>\n <div\n ref={setPopoverContainer}\n className=\"pointer-events-none fixed inset-0 z-[9998]\"\n />\n\n {selectedDate && (\n <div className=\"text-muted-foreground text-xs\">\n {t(\"bill_date_preview_prefix\")}{\" \"}\n <span className=\"font-semibold\">{previewDate}</span>\n {t(\"bill_date_preview_suffix\")}\n </div>\n )}\n\n {subscriptionsWithColor.length > 0 && (\n <div className=\"space-y-2\">\n <Label className=\"text-foreground text-sm font-semibold\">\n {t(\"your_other_subscriptions\")}\n </Label>\n <div className=\"border-border max-h-40 overflow-auto rounded-md border\">\n <table className=\"w-full table-fixed text-sm\">\n <thead className=\"bg-muted text-muted-foreground sticky top-0\">\n <tr>\n <th\n className=\"w-6 p-2\"\n aria-label={t(\"other_subs_color_aria\")}\n />\n <th className=\"px-3 py-2 text-left font-medium\">\n {t(\"other_subs_product\")}\n </th>\n <th className=\"w-28 px-3 py-2 text-left font-medium\">\n {t(\"other_subs_bill_date\")}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-border divide-y\">\n {subscriptionsWithColor.map((sub) => (\n <tr key={sub.token}>\n <td className=\"p-2\">\n <span\n aria-hidden\n className=\"inline-block size-2.5 rounded-full\"\n style={{ backgroundColor: sub.color }}\n />\n </td>\n <td\n className=\"overflow-hidden px-3 py-2\"\n title={sub.productTitle}\n >\n {onNavigateToSubscription ? (\n <button\n type=\"button\"\n onClick={() => {\n onNavigateToSubscription(sub.token);\n handleDismiss(false);\n }}\n className=\"text-primary block w-full truncate text-left hover:underline\"\n >\n {sub.productTitle}\n </button>\n ) : (\n <span className=\"text-foreground block truncate\">\n {sub.productTitle}\n </span>\n )}\n </td>\n <td className=\"text-muted-foreground px-3 py-2 whitespace-nowrap\">\n {sub.nextBillDate\n ? formatMediumDate(\n parseIsoDate(sub.nextBillDate),\n locale,\n )\n : \"—\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )}\n </div>\n\n {errorMessage && (\n <p className=\"text-destructive text-left text-sm\">{errorMessage}</p>\n )}\n\n <DialogFooter>\n <div className=\"flex w-full flex-row justify-between gap-x-2\">\n <Button\n variant=\"outline\"\n className=\"h-10 min-w-[70px] rounded p-3\"\n onClick={() => handleDismiss(false)}\n >\n {t(\"edit_bill_date_cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"h-10 min-w-[70px] rounded p-3\"\n onClick={handleConfirm}\n disabled={!selectedDate || isLoading}\n >\n {isLoading ? (\n <div className=\"border-primary-foreground size-5 animate-spin rounded-full border-4 border-t-4 border-t-transparent\" />\n ) : (\n t(\"edit_bill_date_action\")\n )}\n </Button>\n </div>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { JSX } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nconst STATUS_COLORS: Record<string, string> = {\n active: \"bg-green-100 text-green-800\",\n paused: \"bg-gray-100 text-gray-800\",\n cancelled: \"bg-red-100 text-red-800\",\n pending: \"bg-yellow-100 text-yellow-800\",\n inactive: \"bg-gray-100 text-gray-800\",\n disabled: \"bg-red-100 text-red-800\",\n past_due: \"bg-gray-100 text-gray-800\",\n};\n\nconst STATUS_DOT_COLORS: Record<string, string> = {\n active: \"bg-green-500\",\n paused: \"bg-gray-400\",\n cancelled: \"bg-red-500\",\n pending: \"bg-yellow-500\",\n inactive: \"bg-gray-400\",\n disabled: \"bg-red-500\",\n past_due: \"bg-gray-400\",\n};\n\nexport interface StatusPillProps {\n status: string | undefined | null;\n children: React.ReactNode;\n}\n\nexport function StatusPill({ status, children }: StatusPillProps): JSX.Element {\n const key = status?.toLowerCase() ?? \"\";\n const pillColor = STATUS_COLORS[key] ?? \"bg-gray-100 text-gray-800\";\n const dotColor = STATUS_DOT_COLORS[key] ?? \"bg-gray-400\";\n\n return (\n <span\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium\",\n pillColor,\n )}\n >\n <span className={cn(\"h-1.5 w-1.5 rounded-full\", dotColor)} />\n {children}\n </span>\n );\n}\n","import type { JSX } from \"react\";\nimport { Button } from \"@fluid-app/ui-primitives\";\nimport { CreditCard, RefreshCw } from \"lucide-react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { cn } from \"../lib/cn\";\n\nexport interface PastDueBannerProps {\n productTitle?: string | null;\n // Body copy is derived from these three fields:\n // next_retry_at null → \"payment failed, update your card\"\n // next_retry_at set, decline_count = 1 → initial bill failed; first retry queued\n // → \"we'll try your payment again\"\n // next_retry_at set, decline_count >= 2 → at least one retry has already failed\n // and another is queued → \"the last\n // retry didn't go through\" copy with a\n // bucketed time estimate.\n // Using decline_count (not last_failed_at) is what distinguishes the\n // initial-failure state from the retry-failed state — last_failed_at is\n // populated on every failure including the first.\n nextRetryAt?: string | null;\n declineCount?: number | null;\n onUpdatePaymentClick?: () => void;\n onRetryPaymentClick?: () => void;\n onWaiveFailedCycleClick?: () => void;\n savedMethodLabel?: string | null;\n isRetryingPayment?: boolean;\n isCheckingWaiver?: boolean;\n recoveryDisabled?: boolean;\n className?: string;\n}\n\nexport function PastDueBanner({\n productTitle,\n nextRetryAt,\n declineCount,\n onUpdatePaymentClick,\n onRetryPaymentClick,\n onWaiveFailedCycleClick,\n savedMethodLabel,\n isRetryingPayment = false,\n isCheckingWaiver = false,\n recoveryDisabled = false,\n className,\n}: PastDueBannerProps): JSX.Element | null {\n const { t } = useSubscriptionsTranslation();\n const retryScheduled = nextRetryAt != null;\n // A retry has actually failed only when decline_count >= 2 — the first\n // failure (decline_count = 1) is the initial billing attempt, not a retry.\n // last_failed_at alone is not a sufficient signal: it's populated on every\n // failure including the first.\n const previousAttemptFailed = retryScheduled && (declineCount ?? 0) >= 2;\n\n const heading = retryScheduled\n ? productTitle\n ? t(\"past_due_banner_heading_retry_scheduled_for_product\", {\n product: productTitle,\n })\n : t(\"past_due_banner_heading_retry_scheduled\")\n : productTitle\n ? t(\"past_due_banner_heading_for_product\", { product: productTitle })\n : t(\"past_due_banner_heading\");\n\n // Bucket the time-until-next-retry into stable, readable ranges.\n // RetryFailedPaymentsJob ticks every 5 minutes (actual retry runs\n // within ~5 min of next_retry_at), so precision isn't load-bearing —\n // a hyper-precise countdown would churn on every render and read\n // like a to-the-second promise.\n // 2h backoff → \"in the next few hours\"\n // 6h backoff → \"in the next few hours\"\n // 24h backoff → \"within a day\"\n const whenLabel = (() => {\n if (!nextRetryAt) return t(\"past_due_retry_when_shortly\");\n const ms = new Date(nextRetryAt).getTime() - Date.now();\n if (ms < 60_000) return t(\"past_due_retry_when_shortly\");\n if (ms < 12 * 60 * 60 * 1000) return t(\"past_due_retry_when_few_hours\");\n return t(\"past_due_retry_when_within_day\");\n })();\n\n const body = previousAttemptFailed\n ? t(\"past_due_banner_body_retry_failed\", { when: whenLabel })\n : retryScheduled\n ? t(\"past_due_banner_body_retry_scheduled\")\n : t(\"past_due_banner_body\");\n const retryLabel = savedMethodLabel\n ? t(\"retry_saved_payment\", { method: savedMethodLabel })\n : t(\"retry_payment\");\n\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n \"border-destructive/50 bg-background rounded-xl border p-4 shadow-sm sm:p-5\",\n className,\n )}\n >\n <div className=\"flex items-start gap-3 sm:gap-4\">\n <div className=\"bg-destructive/10 text-destructive mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-full\">\n <CreditCard className=\"size-4\" aria-hidden />\n </div>\n <div className=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-foreground text-base font-bold tracking-tight sm:text-lg\">\n {heading}\n </h3>\n <p className=\"text-muted-foreground text-sm leading-relaxed\">\n {body}\n </p>\n </div>\n\n {(onRetryPaymentClick || onUpdatePaymentClick) && (\n <div className=\"flex flex-wrap gap-2\">\n {onRetryPaymentClick && (\n <Button\n type=\"button\"\n size=\"default\"\n onClick={onRetryPaymentClick}\n disabled={recoveryDisabled || isRetryingPayment}\n aria-busy={isRetryingPayment}\n className=\"active:scale-[0.99]\"\n >\n <span\n aria-hidden\n className={cn(\n \"inline-flex\",\n isRetryingPayment && \"animate-spin\",\n )}\n >\n <RefreshCw className=\"size-4\" />\n </span>\n {isRetryingPayment ? t(\"retrying_payment\") : retryLabel}\n </Button>\n )}\n {onUpdatePaymentClick && (\n <Button\n type=\"button\"\n variant={onRetryPaymentClick ? \"outline\" : \"default\"}\n size=\"default\"\n onClick={onUpdatePaymentClick}\n disabled={recoveryDisabled}\n className=\"active:scale-[0.99]\"\n >\n {t(\"change_payment_method\")}\n </Button>\n )}\n </div>\n )}\n\n {isCheckingWaiver ? (\n <span className=\"text-muted-foreground inline-flex items-center gap-1.5 text-xs\">\n <RefreshCw className=\"size-3 animate-spin\" aria-hidden />\n {t(\"checking_failed_cycle_waiver\")}\n </span>\n ) : (\n onWaiveFailedCycleClick && (\n <button\n type=\"button\"\n onClick={onWaiveFailedCycleClick}\n disabled={recoveryDisabled}\n className=\"text-muted-foreground hover:text-foreground w-fit text-left text-sm underline-offset-4 hover:underline disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {t(\"waive_failed_cycle\")}\n </button>\n )\n )}\n </div>\n </div>\n </div>\n );\n}\n","import type { JSX } from \"react\";\nimport {\n getFailedCycleWaiverSummary,\n type subscriptions,\n} from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@fluid-app/ui-primitives\";\nimport {\n ResponsiveDialog,\n type ResponsiveDialogPresentation,\n} from \"@fluid-app/ui-components/components/ResponsiveDialog\";\n\nexport interface FailedCycleWaiverDialogProps {\n open: boolean;\n preview: subscriptions.FailedCycleWaiverPreview | null;\n timezone: string;\n isPending: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function FailedCycleWaiverDialog({\n open,\n preview,\n timezone,\n isPending,\n onOpenChange,\n onConfirm,\n presentation = \"dialog\",\n}: FailedCycleWaiverDialogProps): JSX.Element {\n const { t, locale } = useSubscriptionsTranslation();\n const schedule =\n preview?.next_bill_date != null && preview.next_ship_date != null\n ? getFailedCycleWaiverSummary({\n nextBillDate: preview.next_bill_date,\n nextShipDate: preview.next_ship_date,\n locale,\n timezone,\n })\n : null;\n const canConfirm = preview?.eligible === true && schedule != null;\n\n const content = (\n <>\n {schedule != null && (\n <div className=\"border-border bg-muted/60 rounded-lg border px-4 py-3\">\n {schedule.kind === \"combined\" ? (\n <p className=\"text-foreground text-sm font-medium\">\n {t(\"failed_cycle_waiver_next_bill_and_ship\", {\n date: schedule.date,\n })}\n </p>\n ) : (\n <div className=\"space-y-1\">\n <p className=\"text-foreground text-sm font-medium\">\n {t(\"failed_cycle_waiver_next_bill\", {\n date: schedule.billDate,\n })}\n </p>\n <p className=\"text-foreground text-sm font-medium\">\n {t(\"failed_cycle_waiver_next_ship\", {\n date: schedule.shipDate,\n })}\n </p>\n </div>\n )}\n </div>\n )}\n\n <DialogFooter className=\"gap-2 sm:justify-between\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={isPending}\n >\n {t(\"failed_cycle_waiver_go_back\")}\n </Button>\n <Button\n type=\"button\"\n onClick={onConfirm}\n disabled={!canConfirm || isPending}\n aria-busy={isPending}\n >\n {isPending && (\n <span\n aria-hidden\n className=\"border-primary-foreground size-4 animate-spin rounded-full border-2 border-t-transparent\"\n />\n )}\n {t(\"failed_cycle_waiver_confirm\")}\n </Button>\n </DialogFooter>\n </>\n );\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!isPending) onOpenChange(nextOpen);\n };\n\n if (presentation === \"bottom-sheet\") {\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={t(\"failed_cycle_waiver_dialog_title\")}\n description={t(\"failed_cycle_waiver_dialog_description\")}\n presentation=\"bottom-sheet\"\n size=\"compact\"\n >\n {content}\n </ResponsiveDialog>\n );\n }\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent\n className=\"rounded-xl sm:max-w-md\"\n showCloseButton={!isPending}\n >\n <DialogHeader className=\"gap-2 text-left\">\n <DialogTitle className=\"text-xl font-semibold tracking-tight\">\n {t(\"failed_cycle_waiver_dialog_title\")}\n </DialogTitle>\n <DialogDescription className=\"text-sm leading-6\">\n {t(\"failed_cycle_waiver_dialog_description\")}\n </DialogDescription>\n </DialogHeader>\n {content}\n </DialogContent>\n </Dialog>\n );\n}\n","import type React from \"react\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { ImageOff } from \"lucide-react\";\nimport { formatCurrency, UNIT_KEYS } from \"../lib/format\";\n\nexport interface BundledWithCardProps {\n bundledSubscriptions: subscriptions.BundledSubscription[];\n /** Token of the subscription whose detail page this card renders on. */\n currentToken: string;\n /**\n * The parent subscription's plan. Bundle members share the parent's bill\n * date, so its cadence drives both the subhead (\"1 month\") and the per-row\n * plan label (\"Monthly Subscription\"). The lightweight bundled-subscription\n * payload carries no per-sibling plan of its own.\n */\n plan: subscriptions.SubscriptionDetailPlan;\n onNavigateToSubscription?: (token: string) => void;\n}\n\n/**\n * \"Bundled with subscription\" card shown on the subscription detail screen\n * between the upcoming-order summary and the product row. Lists the sibling\n * subscriptions that share this subscription's bill date and shipment. Renders\n * nothing when the subscription is not part of a bundle.\n */\nexport function BundledWithCard({\n bundledSubscriptions,\n currentToken,\n plan,\n onNavigateToSubscription,\n}: BundledWithCardProps): React.JSX.Element | null {\n const { t } = useSubscriptionsTranslation();\n\n const siblings = bundledSubscriptions.filter(\n (sib) => sib.subscription_token !== currentToken,\n );\n const firstSibling = siblings[0];\n if (!firstSibling) {\n return null;\n }\n\n const unit = plan.billing_interval_unit.toLowerCase();\n const interval = plan.billing_interval;\n const unitKeys = UNIT_KEYS[unit];\n\n // \"1 month\" / \"3 months\" — interval form for the subhead.\n const cadenceInterval = t(\"bundled_with_cadence_n_units\", {\n n: String(interval),\n unit: unitKeys\n ? interval === 1\n ? t(unitKeys.singular as \"unit_day\")\n : t(unitKeys.plural as \"unit_days\")\n : plan.billing_interval_unit,\n });\n\n // \"Monthly\" / \"Quarterly\" / \"Every 5 weeks\" — adjective form for row labels.\n let cadenceAdjective: string;\n if (interval === 1 && unit === \"day\")\n cadenceAdjective = t(\"list_cadence_daily\");\n else if (interval === 1 && unit === \"week\")\n cadenceAdjective = t(\"list_cadence_weekly\");\n else if (interval === 1 && unit === \"month\")\n cadenceAdjective = t(\"list_cadence_monthly\");\n else if (interval === 1 && unit === \"year\")\n cadenceAdjective = t(\"list_cadence_yearly\");\n else if (interval === 3 && unit === \"month\")\n cadenceAdjective = t(\"list_cadence_quarterly\");\n else\n cadenceAdjective = t(\"list_cadence_every_n_units\", {\n n: String(interval),\n unit: unitKeys\n ? t(unitKeys.plural as \"unit_days\")\n : plan.billing_interval_unit,\n });\n\n const rowPlanLabel = t(\"bundled_with_plan_label\", {\n cadence: cadenceAdjective,\n });\n const headerToken = `#${firstSibling.subscription_token.slice(-8).toUpperCase()}`;\n\n return (\n <div className=\"border-border bg-background my-3 rounded-xl border p-4\">\n <div className=\"text-foreground text-sm font-bold\">\n {t(\"bundled_with_title\")}{\" \"}\n {onNavigateToSubscription ? (\n <button\n type=\"button\"\n onClick={() =>\n onNavigateToSubscription(firstSibling.subscription_token)\n }\n className=\"text-primary focus-visible:ring-foreground/30 rounded font-bold hover:underline focus-visible:ring-2 focus-visible:outline-none\"\n >\n {headerToken}\n </button>\n ) : (\n <span className=\"text-primary font-bold\">{headerToken}</span>\n )}\n </div>\n <p className=\"text-muted-foreground mt-0.5 text-xs\">\n {t(\"bundled_with_subhead\", { cadence: cadenceInterval })}\n </p>\n\n <div className=\"mt-3 flex flex-col gap-0.5\">\n {siblings.map((sib) => {\n const rowContent = (\n <>\n <div className=\"bg-muted size-12 shrink-0 overflow-hidden rounded-lg\">\n {sib.image_url ? (\n <img\n src={sib.image_url}\n alt=\"\"\n className=\"size-full object-cover\"\n />\n ) : (\n <div className=\"text-muted-foreground flex size-full items-center justify-center\">\n <ImageOff className=\"size-4\" strokeWidth={1.75} />\n </div>\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p\n className=\"text-foreground truncate text-sm font-medium\"\n title={sib.product_title}\n >\n {sib.product_title || t(\"list_product_fallback\")}\n </p>\n {sib.variant_title && (\n <p className=\"text-muted-foreground truncate text-xs\">\n {sib.variant_title}\n </p>\n )}\n <p className=\"text-foreground text-sm font-medium\">\n {formatCurrency(sib.price)}\n </p>\n </div>\n <span className=\"text-muted-foreground shrink-0 text-xs\">\n {rowPlanLabel}\n </span>\n </>\n );\n\n return onNavigateToSubscription ? (\n <button\n key={sib.subscription_token}\n type=\"button\"\n onClick={() => onNavigateToSubscription(sib.subscription_token)}\n className=\"hover:bg-muted/60 focus-visible:ring-foreground/30 -mx-2 flex items-center gap-3 rounded-lg p-2 text-left transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n >\n {rowContent}\n </button>\n ) : (\n <div\n key={sib.subscription_token}\n className=\"-mx-2 flex items-center gap-3 rounded-lg p-2\"\n >\n {rowContent}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n","import { useState, useEffect, useMemo, useRef, useCallback } from \"react\";\nimport type React from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type {\n subscriptions,\n SubscriptionActionPolicy,\n} from \"@fluid-app/subscriptions-core\";\nimport {\n useSubscription,\n useSubscriptions,\n usePauseSubscription,\n useResumeSubscription,\n useSkipSubscription,\n useCancelSubscription,\n useReactivateSubscription,\n useRetryStatusPolling,\n useRetrySubscription,\n useFailedCycleWaiverPreview,\n useWaiveFailedCycle,\n useUpdateSubscriptionInfo,\n subscriptionsKeys,\n formatDate,\n formatOptionalDate,\n formatTime,\n getNextBillDisplay,\n calculateNextBillDate,\n computeSubscriptionPricing,\n getFailedCycleWaiverSummary,\n getSubscriptionActionPolicy,\n getSubscriptionDisplayStatus,\n hasPendingSubscriptionSkip,\n isSubscriptionCompleted,\n} from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n getPaymentBrandName,\n normalizeCardBrand,\n} from \"@fluid-app/payments-display/brands\";\nimport {\n isCardPaymentDescriptor,\n normalizePaymentDescriptor,\n paymentDescriptorLabel,\n resolvePaymentMethodDisplay,\n} from \"@fluid-app/payments-display/display\";\nimport type { ResolvedPaymentMethodDisplay } from \"@fluid-app/payments-display/ports\";\nimport {\n SkipForward,\n Pause,\n Play,\n XCircle,\n RotateCcw,\n CalendarDays,\n Ellipsis,\n Minus,\n Plus,\n} from \"lucide-react\";\nimport { addMonths, format } from \"date-fns\";\nimport {\n Badge,\n Skeleton,\n Button,\n Input,\n cn,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport { MobileActionSheet } from \"@fluid-app/ui-components/components/MobileActionSheet\";\nimport type { ResponsiveDialogPresentation } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport {\n CancelSubscriptionDialog,\n type PauseMonths,\n} from \"./cancel-subscription-dialog\";\nimport {\n PauseSubscriptionDialog,\n type PauseSubscriptionSelection,\n} from \"./pause-subscription-dialog\";\nimport { ResumeSubscriptionDialog } from \"./resume-subscription-dialog\";\nimport { EditBillDateDialog } from \"./edit-bill-date-dialog\";\nimport { StatusPill } from \"./status-pill\";\nimport { PastDueBanner } from \"./past-due-banner\";\nimport { FailedCycleWaiverDialog } from \"./failed-cycle-waiver-dialog\";\nimport { BundledWithCard } from \"./bundled-with-card\";\nimport {\n startCase,\n formatCurrency,\n KNOWN_STATUSES,\n UNIT_KEYS,\n} from \"../lib/format\";\n\n/** Map a billing_interval_unit to its shorthand cadence key (daily/weekly/…), or null. */\nfunction getCadenceKey(unit: string): string | null {\n switch (unit.toLowerCase()) {\n case \"day\":\n return \"daily\";\n case \"week\":\n return \"weekly\";\n case \"month\":\n return \"monthly\";\n case \"year\":\n return \"yearly\";\n default:\n return null;\n }\n}\n\nfunction isRecoveryStateChanged(error: unknown): boolean {\n // The envelope, so the shapes below are distinct server responses rather than\n // the same one read at two nesting levels to cover both producers.\n if (!isRecord(error) || error.status !== 422 || !isRecord(error.body)) {\n return false;\n }\n\n const body = error.body;\n const portalDetails = isRecord(body.error) ? body.error.details : undefined;\n const recoveryStates = [\n body.recovery_state,\n isRecord(portalDetails) ? portalDetails.recovery_state : undefined,\n isRecord(body.errors) ? body.errors.recovery_state : undefined,\n ];\n\n return recoveryStates.some(\n (recoveryState) =>\n Array.isArray(recoveryState) && recoveryState.includes(\"changed\"),\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport interface PaymentMethodSlotContext {\n paymentMethod: subscriptions.SubscriptionDetailPaymentMethod;\n subscriptionToken: string;\n customerId: number;\n countryCode: string;\n disabled: boolean;\n onRecoveryStateChange?: (state: {\n subscriptionToken: string;\n isBusy: boolean;\n }) => void;\n}\n\nexport interface ShippingAddressSlotContext {\n /**\n * Stable FK to the subscription's anchored address row. Prefer this\n * over `address.id` for identity comparisons — `address.id` is null\n * whenever the BE serves the snapshot rather than the live row.\n */\n addressId: number | null;\n address: subscriptions.SubscriptionDetailAddress | null;\n subscriptionToken: string;\n customerId: number;\n countryCode: string;\n disabled: boolean;\n}\n\nexport interface AutoApplyPointsSlotContext {\n /**\n * The customer's stored choice for this subscription. The control renders\n * from this rather than from a local default, so a reload shows what they\n * actually chose. `undefined` means the payload carried nothing.\n */\n autoApplyPoints?: boolean;\n /**\n * Whether the company runs a points program. The host is expected to render\n * nothing when this is false: a control that cannot act should not appear.\n */\n pointsEnabled?: boolean;\n subscriptionToken: string;\n disabled: boolean;\n /**\n * The set that will actually bill alongside this subscription, when the\n * payload carried one. Optional so hosts on a server that does not populate\n * it, and non-portal hosts that never render a bundle dialog, are\n * unaffected. Deliberately not `bundled_subscriptions`: that is the display\n * set and the two can legitimately differ.\n */\n renewalBundle?: subscriptions.SubscriptionRenewalBundle | null;\n}\n\nexport interface ReactivateDialogSlotContext {\n /** Whether the reactivate confirmation dialog is open. */\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /**\n * Run the reactivation. Pass the confirmed `addressId` to repoint the\n * subscription's shipping address, or omit it to keep the current one.\n */\n onConfirm: (params: { addressId?: number | null }) => void;\n /** True while the reactivation request is in flight. */\n isLoading: boolean;\n /** True when the last reactivation attempt failed — lets the dialog show inline feedback. */\n isError: boolean;\n subscriptionToken: string;\n}\n\ntype SubscriptionPaymentDetails = {\n last4?: string;\n last_four?: string;\n card_network?: string;\n card_brand?: string;\n logo_url?: string;\n};\n\nfunction resolveSubscriptionPaymentMethodDisplay(\n paymentMethod: subscriptions.SubscriptionDetailPaymentMethod,\n details: SubscriptionPaymentDetails | null,\n): ResolvedPaymentMethodDisplay {\n const last4 = details?.last4 ?? details?.last_four;\n const cardBrand =\n normalizeCardBrand(details?.card_brand) ??\n normalizeCardBrand(details?.card_network);\n const isCard =\n last4 != null ||\n normalizePaymentDescriptor(details?.card_brand) != null ||\n normalizePaymentDescriptor(details?.card_network) != null ||\n cardBrand != null ||\n isCardPaymentDescriptor(paymentMethod.source) ||\n isCardPaymentDescriptor(paymentMethod.payment_type);\n\n if (isCard) {\n return resolvePaymentMethodDisplay({\n kind: \"card\",\n brand: cardBrand,\n last4,\n logoUrl: details?.logo_url,\n });\n }\n\n const fallbackLabel = paymentDescriptorLabel(\n paymentMethod.payment_type,\n paymentMethod.source,\n );\n return resolvePaymentMethodDisplay({\n kind: \"non_card\",\n brand: fallbackLabel,\n fallbackLabel,\n logoUrl: details?.logo_url,\n });\n}\n\nfunction getSavedPaymentMethodLabel(\n paymentMethod: subscriptions.SubscriptionDetailPaymentMethod | null,\n): string | null {\n if (!paymentMethod) return null;\n\n const details =\n (paymentMethod.details as SubscriptionPaymentDetails | null) ?? null;\n const display = resolveSubscriptionPaymentMethodDisplay(\n paymentMethod,\n details,\n );\n\n if (display.kind === \"card\") {\n const last4 = details?.last4 ?? details?.last_four;\n const brandName = getPaymentBrandName(display.brand);\n return brandName && last4 ? `${brandName} •••• ${last4}` : null;\n }\n\n const descriptor = paymentDescriptorLabel(\n paymentMethod.payment_type,\n paymentMethod.source,\n );\n return descriptor ? display.label : null;\n}\n\nfunction PaymentMethodLogo({\n display,\n}: {\n display: ResolvedPaymentMethodDisplay;\n}) {\n const [logoErrored, setLogoErrored] = useState(false);\n const logoUrl = logoErrored\n ? display.logo.fallbackUrl\n : display.logo.primaryUrl;\n\n useEffect(() => {\n setLogoErrored(false);\n }, [display.logo.fallbackUrl, display.logo.primaryUrl]);\n\n return (\n <img\n src={logoUrl}\n alt={display.accessibilityLabel}\n className=\"h-6 max-w-16 shrink-0 object-contain\"\n onError={() => setLogoErrored(true)}\n />\n );\n}\n\nexport interface SubscriptionDetailProps {\n token: string;\n onNotFound?: () => void;\n onError?: (error: Error) => void;\n onSuccess?: (\n message: string,\n severity?: \"success\" | \"error\" | \"warning\",\n ) => void;\n onMutationError?: (message: string, error: unknown) => void;\n /**\n * Called when the Edit Bill Date dialog wants to navigate the host app to\n * another subscription's detail page (clicking a row in the calendar's\n * \"Your other subscriptions\" list).\n */\n onNavigateToSubscription?: (token: string) => void;\n /**\n * Optional render-prop for the Payment Method block. When provided, replaces\n * the read-only display so consumers can wire change/add UX. Default falls\n * back to a read-only summary.\n */\n renderPaymentMethod?: (ctx: PaymentMethodSlotContext) => React.JSX.Element;\n /**\n * Optional render-prop for the Shipping Address block. When provided,\n * replaces the read-only display so consumers can wire change/add UX.\n * Default falls back to a read-only summary.\n */\n renderShippingAddress?: (\n ctx: ShippingAddressSlotContext,\n ) => React.JSX.Element;\n /**\n * Optional render-prop for the auto-apply-points block. There is NO default\n * read-only fallback, unlike the slots above, and that asymmetry is\n * deliberate: baking a control into this component's default tree would ship\n * it to the checkout-hosted subscription screens as well, which is the\n * management surface O-6 defers to a later phase. A host that omits this slot\n * renders nothing, which is what keeps that deferral mechanical rather than\n * accidental.\n */\n renderAutoApplyPoints?: (\n ctx: AutoApplyPointsSlotContext,\n ) => React.JSX.Element;\n /**\n * Optional render-prop for the reactivation confirmation dialog. When\n * provided, clicking Reactivate opens the dialog so the consumer can\n * confirm a shipping address before reactivating (CURRENT-2204). When\n * omitted, Reactivate runs immediately against the current address.\n */\n renderReactivateDialog?: (\n ctx: ReactivateDialogSlotContext,\n ) => React.JSX.Element;\n /**\n * Called when the past-due banner's \"Update payment method\" button is\n * clicked. Consumers should open their Add Payment Method dialog. If\n * omitted, the banner falls back to scrolling the payment-method section\n * into view.\n */\n onUpdatePaymentClick?: () => void;\n presentation?: ResponsiveDialogPresentation;\n}\n\nfunction SubscriptionDetailSkeleton() {\n return (\n <div className=\"flex flex-col lg:grid lg:grid-cols-8\">\n {/* Left: items skeleton */}\n <div className=\"bg-muted flex flex-col items-center px-8 lg:col-span-4\">\n <div className=\"w-full max-w-lg py-6\">\n <Skeleton className=\"mb-4 h-6 w-48\" />\n <div className=\"grid grid-cols-2 gap-4\">\n <Skeleton className=\"h-16 w-full rounded\" />\n <Skeleton className=\"h-16 w-full rounded\" />\n </div>\n <div className=\"mt-6 flex items-center gap-x-4\">\n <Skeleton className=\"size-24 rounded\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-1/2\" />\n <Skeleton className=\"h-4 w-1/4\" />\n </div>\n </div>\n <div className=\"mt-6 space-y-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-5 w-full\" />\n </div>\n </div>\n </div>\n {/* Right: management skeleton */}\n <div className=\"bg-background col-span-4 px-8 pt-4\">\n <div className=\"mx-auto max-w-lg\">\n <Skeleton className=\"mb-3 h-5 w-32\" />\n <div className=\"grid grid-cols-2 gap-3\">\n <Skeleton className=\"h-10 w-full rounded\" />\n <Skeleton className=\"h-10 w-full rounded\" />\n </div>\n <div className=\"mt-6 space-y-4\">\n <Skeleton className=\"h-5 w-40\" />\n <div className=\"flex gap-4\">\n <Skeleton className=\"h-12 flex-1 rounded\" />\n <Skeleton className=\"h-12 flex-1 rounded\" />\n </div>\n </div>\n <div className=\"mt-6 space-y-4\">\n <Skeleton className=\"h-5 w-40\" />\n <Skeleton className=\"h-16 w-full rounded\" />\n <Skeleton className=\"h-16 w-full rounded\" />\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n/* ── Left column: product & order summary ──────────────────────────── */\n\n/* ── Quantity input ─────────────────────────────────────────────────\n The displayed value is local string state so the user can backspace\n a single-digit quantity without React snapping it back. We only\n forward valid positive integers to onQuantityChange; on blur we\n restore the last committed quantity if the field was left empty\n or invalid.\n\n Two focus-retention quirks worth keeping in mind:\n - Toggling `disabled` blurs a focused input (especially WebKit).\n Use `readOnly` while the mutation is in flight instead so the\n user keeps their cursor as they tweak the value.\n - We skip the prop-sync useEffect while the field is focused —\n writing `inputValue` again on a server confirmation doesn't change\n anything visible, but the controlled-input value write is enough\n to drop focus on mobile Safari. The post-blur restore on line ~186\n handles the unfocused case. */\n\nfunction QuantityInput({\n inputId,\n quantity,\n maxQuantity,\n isUpdatingQuantity,\n onQuantityChange,\n quantityAriaLabel,\n decrementAriaLabel,\n incrementAriaLabel,\n}: {\n inputId: string;\n quantity: number;\n maxQuantity: number | null;\n isUpdatingQuantity: boolean;\n onQuantityChange: (next: number) => void;\n quantityAriaLabel: string;\n decrementAriaLabel: string;\n incrementAriaLabel: string;\n}) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState(String(quantity));\n // Captured the moment focus enters the field. Backspacing from \"12\"\n // through \"1\" to \"\" commits an intermediate quantity of 1 to the\n // parent, so on blur we can't trust the live `quantity` prop as the\n // restore target — use the value the user started with.\n const focusEntryQuantityRef = useRef(quantity);\n // Local debounce on commit. Without this, every keystroke fires\n // onQuantityChange, which the parent uses to update pendingQuantity\n // synchronously — so intermediate values (e.g. the \"1\" mid-way through\n // backspacing \"12\" to retype) flash in the order summary before the\n // user is done typing.\n const commitTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // Keep the latest onQuantityChange in a ref so the debounced timer\n // doesn't fire with a stale closure if the parent re-renders within\n // the 500ms window with a new callback identity.\n const onQuantityChangeRef = useRef(onQuantityChange);\n useEffect(() => {\n onQuantityChangeRef.current = onQuantityChange;\n }, [onQuantityChange]);\n\n useEffect(\n () => () => {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current);\n },\n [],\n );\n\n useEffect(() => {\n if (\n typeof document !== \"undefined\" &&\n document.activeElement === inputRef.current\n ) {\n return;\n }\n setInputValue(String(quantity));\n }, [quantity]);\n\n const scheduleCommit = (next: number) => {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current);\n commitTimerRef.current = setTimeout(() => {\n onQuantityChangeRef.current(next);\n // Move the restore baseline forward — once a value successfully\n // commits, that's what an empty-blur should fall back to, not\n // the value at focus-entry.\n focusEntryQuantityRef.current = next;\n }, 500);\n };\n\n // Drive the +/− disabled state from the in-flight value so the buttons\n // stay in sync with what the user sees mid-edit, instead of lagging\n // 500ms behind the committed quantity.\n const parsedInput = parseInt(inputValue, 10);\n const currentValue =\n Number.isFinite(parsedInput) && parsedInput > 0 ? parsedInput : quantity;\n const decrementDisabled = isUpdatingQuantity || currentValue <= 1;\n const incrementDisabled =\n isUpdatingQuantity || (maxQuantity != null && currentValue >= maxQuantity);\n\n // Single clamp source so the typing path enforces the same min/max\n // window the +/− buttons gate visually — without this, typing 999 with\n // a max_quantity of 10 would commit 999 even though `+` is disabled.\n const clampToBounds = (n: number): number =>\n maxQuantity != null\n ? Math.min(maxQuantity, Math.max(1, n))\n : Math.max(1, n);\n\n const stepBy = (delta: 1 | -1) => {\n const clamped = clampToBounds(currentValue + delta);\n if (clamped === currentValue) return;\n setInputValue(String(clamped));\n scheduleCommit(clamped);\n };\n\n const stepperButtonClass = cn(\n \"text-muted-foreground hover:text-foreground hover:bg-muted flex h-7 w-7 shrink-0 items-center justify-center rounded-full shadow-xs disabled:cursor-not-allowed\",\n );\n\n return (\n <div\n className={cn(\n \"border-border bg-background focus-within:border-ring focus-within:ring-ring/50 flex h-7.5 items-center justify-between rounded-2xl border focus-within:ring-[3px]\",\n isUpdatingQuantity && \"opacity-60\",\n )}\n >\n <button\n type=\"button\"\n onClick={() => stepBy(-1)}\n disabled={decrementDisabled}\n aria-label={decrementAriaLabel}\n aria-controls={inputId}\n className={cn(stepperButtonClass, decrementDisabled && \"opacity-40\")}\n >\n <Minus className=\"size-3\" />\n </button>\n <Input\n ref={inputRef}\n id={inputId}\n type=\"number\"\n min={1}\n max={maxQuantity ?? undefined}\n step={1}\n value={inputValue}\n onFocus={() => {\n // Capture the displayed value, not the committed `quantity` —\n // a + click before focus updates inputValue but its 500ms\n // debounce may not have fired yet, so the committed prop is\n // stale. Without this, an erase-then-blur restores to the\n // pre-+ value and silently discards the click.\n focusEntryQuantityRef.current = currentValue;\n }}\n onChange={(e) => {\n const raw = e.target.value;\n setInputValue(raw);\n if (raw === \"\") {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current);\n return;\n }\n const next = parseInt(raw, 10);\n if (Number.isFinite(next) && next > 0) {\n scheduleCommit(clampToBounds(next));\n }\n }}\n onBlur={() => {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current);\n const parsed = parseInt(inputValue, 10);\n if (Number.isFinite(parsed) && parsed > 0) {\n const clamped = clampToBounds(parsed);\n // Snap the displayed value back to the cap on blur so the\n // user sees the bound that was applied to the committed value.\n if (clamped !== parsed) {\n setInputValue(String(clamped));\n }\n if (clamped !== quantity) {\n onQuantityChange(clamped);\n }\n focusEntryQuantityRef.current = clamped;\n } else {\n const restore = focusEntryQuantityRef.current;\n setInputValue(String(restore));\n if (restore !== quantity) {\n onQuantityChange(restore);\n }\n }\n }}\n readOnly={isUpdatingQuantity}\n className=\"text-foreground h-7 w-10 rounded-none border-0 bg-transparent px-0 text-center text-xs font-semibold shadow-none [-moz-appearance:textfield] focus-visible:border-0 focus-visible:ring-0 md:text-xs [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none\"\n aria-label={quantityAriaLabel}\n />\n <button\n type=\"button\"\n onClick={() => stepBy(1)}\n disabled={incrementDisabled}\n aria-label={incrementAriaLabel}\n aria-controls={inputId}\n className={cn(stepperButtonClass, incrementDisabled && \"opacity-40\")}\n >\n <Plus className=\"size-3\" />\n </button>\n </div>\n );\n}\n\n/**\n * One itemized discount row in the pricing summary: label, optional code\n * pill(s), and a negative amount. Codes render as pills on the line rather than\n * baked into the label text. `code` accepts a single code or a list so stacked\n * codes are supported if the pricing model ever exposes more than one.\n */\nfunction DiscountLine({\n label,\n amount,\n code,\n}: {\n label: string;\n amount: string;\n code?: string | string[] | null;\n}) {\n const codes = (Array.isArray(code) ? code : code ? [code] : []).filter(\n Boolean,\n );\n return (\n <div className=\"mt-2 flex items-start justify-between gap-2 text-sm\">\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1\">\n <p className=\"text-muted-foreground text-sm font-medium\">{label}</p>\n {codes.map((c, i) => (\n <Badge key={`${c}-${i}`} variant=\"secondary\">\n {c}\n </Badge>\n ))}\n </div>\n <p className=\"text-muted-foreground text-sm font-medium whitespace-nowrap\">\n -{amount}\n </p>\n </div>\n );\n}\n\nfunction SubscriptionItemsSection({\n subscription,\n displayQuantity,\n displayNextBillDate,\n canEditQuantity = false,\n onQuantityChange,\n isUpdatingQuantity = false,\n onNavigateToSubscription,\n}: {\n subscription: subscriptions.SubscriptionDetailSubscription;\n displayQuantity?: number;\n displayNextBillDate?: string;\n canEditQuantity?: boolean;\n onQuantityChange?: (next: number) => void;\n isUpdatingQuantity?: boolean;\n onNavigateToSubscription?: (token: string) => void;\n}) {\n const { t, locale } = useSubscriptionsTranslation();\n const variant = subscription.variant;\n const product = variant?.product;\n const quantity = displayQuantity ?? subscription.quantity;\n const displayStatus = getSubscriptionDisplayStatus(subscription);\n const paymentFailed = displayStatus === \"past_due\";\n const quantityInputId = `subscription-${subscription.subscription_token}-quantity`;\n const pricing = computeSubscriptionPricing(subscription);\n const subtotal = formatCurrency(pricing.subtotalUnit * quantity);\n const totalPrice = formatCurrency(pricing.totalUnit * quantity);\n const effectiveNextBillDate =\n displayNextBillDate ?? subscription.next_bill_date;\n const nextOrderTimeOfDay =\n displayStatus === \"completed\"\n ? \"\"\n : formatTime(effectiveNextBillDate, subscription.timezone, locale);\n const nextBillDisplayLabels = {\n cancelled: t(\"date_cancelled\"),\n completed: t(\"list_status_completed\"),\n paused: t(\"date_paused\"),\n notAvailable: t(\"date_not_available\"),\n };\n\n return (\n <section className=\"bg-muted flex w-full flex-col items-center rounded-lg p-8 lg:col-span-4 lg:self-start\">\n <div className=\"flex w-full max-w-lg flex-col\">\n {/* Upcoming order summary */}\n <div>\n <h2 className=\"text-foreground mb-2 text-lg font-medium\">\n {t(\"your_upcoming_order\")}\n </h2>\n <div className=\"text-muted-foreground\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"border-border border-r pr-4\">\n <div className=\"text-muted-foreground mb-1 text-sm\">\n {paymentFailed\n ? t(\"payment_failed_on\")\n : t(\"next_order_date\")}\n </div>\n <div className=\"text-foreground text-2xl font-bold\">\n {paymentFailed\n ? subscription.last_failed_at\n ? formatOptionalDate(subscription.last_failed_at, locale)\n : \"—\"\n : getNextBillDisplay(\n effectiveNextBillDate,\n displayStatus,\n nextBillDisplayLabels,\n locale,\n )}\n </div>\n {nextOrderTimeOfDay && (\n <div className=\"text-muted-foreground mt-1 text-xs\">\n {nextOrderTimeOfDay} ({subscription.timezone})\n </div>\n )}\n </div>\n <div className=\"pl-4\">\n <div className=\"text-muted-foreground mb-1 text-sm\">\n {t(\"next_bill_amount\")}\n </div>\n <div className=\"text-foreground text-2xl font-bold\">\n {totalPrice}\n </div>\n </div>\n </div>\n <hr className=\"border-border mt-4\" />\n </div>\n </div>\n\n <BundledWithCard\n bundledSubscriptions={subscription.bundled_subscriptions ?? []}\n currentToken={subscription.subscription_token}\n plan={subscription.subscription_plan}\n onNavigateToSubscription={onNavigateToSubscription}\n />\n\n {/* Product row */}\n <div className=\"py-6\">\n <div className=\"flex flex-row items-center gap-x-4\">\n <div className=\"flex min-w-0 flex-1 flex-row gap-x-4\">\n <div className=\"relative shrink-0\">\n <div className=\"bg-muted h-24 w-24 overflow-hidden rounded\">\n {product?.image_url ? (\n <img\n src={product.image_url}\n alt={variant?.title || t(\"product_image_alt\")}\n width={96}\n height={96}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"text-muted-foreground flex size-full items-center justify-center\">\n {t(\"no_image\")}\n </div>\n )}\n {quantity > 1 && (\n <span className=\"bg-foreground text-background absolute -top-2 -right-2 z-10 flex h-6 w-6 items-center justify-center rounded-full text-xs font-medium\">\n {quantity}\n </span>\n )}\n </div>\n </div>\n <div className=\"flex min-w-0 flex-col gap-y-0.5\">\n <p\n className=\"text-foreground truncate text-sm font-medium\"\n title={product?.title}\n >\n {product?.title}\n </p>\n {variant?.title && product?.title && (\n <p className=\"text-muted-foreground text-sm\">\n {variant.title}\n </p>\n )}\n <div>\n <p className=\"text-foreground text-sm font-medium\">\n {formatCurrency(subscription.price * quantity)}\n </p>\n </div>\n </div>\n </div>\n {canEditQuantity && onQuantityChange && (\n <div className=\"flex shrink-0 flex-col items-center\">\n <label\n htmlFor={quantityInputId}\n className=\"text-muted-foreground mb-1 text-xs\"\n >\n {t(\"quantity_label\")}\n </label>\n <QuantityInput\n inputId={quantityInputId}\n quantity={quantity}\n maxQuantity={subscription.subscription_plan.max_quantity}\n isUpdatingQuantity={isUpdatingQuantity}\n onQuantityChange={onQuantityChange}\n quantityAriaLabel={t(\"quantity_aria\")}\n decrementAriaLabel={t(\"decrease_quantity_aria\")}\n incrementAriaLabel={t(\"increase_quantity_aria\")}\n />\n </div>\n )}\n </div>\n </div>\n\n {/* Pricing summary */}\n <div>\n {pricing.hasDiscount && (\n <>\n <div className=\"flex justify-between text-sm\">\n <p className=\"text-muted-foreground text-sm font-medium\">\n {t(\"subtotal\")}\n </p>\n <p className=\"text-muted-foreground text-sm font-medium\">\n {subtotal}\n </p>\n </div>\n {pricing.attachedDiscountUnit > 0 && (\n <DiscountLine\n label={t(\"discount\")}\n code={pricing.attachedDiscountCode}\n amount={formatCurrency(\n pricing.attachedDiscountUnit * quantity,\n )}\n />\n )}\n </>\n )}\n <div className=\"mt-4 flex items-center justify-between text-base font-medium\">\n <p className=\"text-muted-foreground text-sm font-medium\">\n {t(\"total_label\")}\n </p>\n <p className=\"text-foreground text-base font-bold\">{totalPrice}</p>\n </div>\n <span className=\"text-muted-foreground text-xs\">\n {t(\"tax_shipping_note\")}\n </span>\n </div>\n </div>\n </section>\n );\n}\n\n/* ── Right column: actions & details ───────────────────────────────── */\n\nfunction SubscriptionManagementSection({\n subscription,\n actionPolicy,\n isMutating,\n paymentMethodDisabled,\n onPaymentRecoveryStateChange,\n onSkip,\n onPause,\n onResume,\n onCancel,\n onReactivate,\n onEditBillDate,\n renderPaymentMethod,\n renderShippingAddress,\n renderAutoApplyPoints,\n presentation,\n}: {\n subscription: subscriptions.SubscriptionDetailSubscription;\n actionPolicy: SubscriptionActionPolicy;\n isMutating: boolean;\n paymentMethodDisabled: boolean;\n onPaymentRecoveryStateChange: (state: {\n subscriptionToken: string;\n isBusy: boolean;\n }) => void;\n onSkip: () => void;\n onPause: () => void;\n onResume: () => void;\n onCancel: () => void;\n onReactivate: () => void;\n onEditBillDate: () => void;\n renderPaymentMethod?: (ctx: PaymentMethodSlotContext) => React.JSX.Element;\n renderShippingAddress?: (\n ctx: ShippingAddressSlotContext,\n ) => React.JSX.Element;\n renderAutoApplyPoints?: (\n ctx: AutoApplyPointsSlotContext,\n ) => React.JSX.Element;\n presentation: ResponsiveDialogPresentation;\n}) {\n const { t, locale } = useSubscriptionsTranslation();\n const [actionMenuOpen, setActionMenuOpen] = useState(false);\n const plan = subscription.subscription_plan;\n const quantity = subscription.quantity;\n const totalPrice = formatCurrency(subscription.price * quantity);\n const displayStatus = getSubscriptionDisplayStatus(subscription);\n\n const cadenceKey = getCadenceKey(plan.billing_interval_unit);\n const interval = plan.billing_interval;\n const unitKeys = UNIT_KEYS[plan.billing_interval_unit.toLowerCase()];\n\n let cadenceLabel: string;\n if (interval === 1 && cadenceKey) {\n cadenceLabel = t(`list_cadence_${cadenceKey}` as \"list_cadence_monthly\");\n } else if (unitKeys) {\n cadenceLabel = t(\"list_cadence_every_n_units\", {\n n: String(interval),\n unit: t(unitKeys.plural as \"unit_days\"),\n });\n } else {\n cadenceLabel = t(\"list_cadence_every_unit\", {\n unit: startCase(plan.billing_interval_unit),\n });\n }\n\n const paymentMethod = subscription.payment_method;\n const paymentDetails =\n (paymentMethod?.details as SubscriptionPaymentDetails | null) ?? null;\n const paymentDisplay = paymentMethod\n ? resolveSubscriptionPaymentMethodDisplay(paymentMethod, paymentDetails)\n : null;\n\n const actionButtonClass =\n \"flex h-auto flex-row items-center justify-center gap-2 overflow-hidden border border-border bg-muted py-2 text-xs whitespace-nowrap text-foreground hover:bg-accent sm:text-sm\";\n\n return (\n <div className=\"bg-background col-span-4 flex-auto px-8 pt-4\">\n <div className=\"mx-auto max-w-lg lg:mx-0 lg:mr-auto\">\n {actionPolicy.order.length > 0 && (\n <div className=\"border-border mb-6 border-b pb-6\">\n <h2 className=\"text-foreground mb-3 text-sm/6 font-semibold\">\n {t(\"your_upcoming_order\")}\n </h2>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {actionPolicy.order.includes(\"skip_next_order\") && (\n <Button\n variant=\"outline\"\n onClick={onSkip}\n disabled={isMutating || !subscription.next_bill_date}\n className={actionButtonClass}\n >\n <SkipForward className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{t(\"skip_next_order\")}</span>\n </Button>\n )}\n {actionPolicy.order.includes(\"edit_bill_date\") && (\n <Button\n variant=\"outline\"\n onClick={onEditBillDate}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <CalendarDays className=\"size-3 shrink-0\" />\n <span className=\"truncate\">{t(\"edit_bill_date\")}</span>\n </Button>\n )}\n </div>\n </div>\n )}\n\n {/* Subscription Details */}\n <div className=\"border-border mb-4 border-b\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h3 className=\"text-foreground text-sm/6 font-semibold\">\n {t(\"subscription_details\")}\n </h3>\n <div className=\"flex items-center gap-2\">\n <StatusPill status={displayStatus}>\n {KNOWN_STATUSES.has(displayStatus)\n ? t(`list_status_${displayStatus}` as \"list_status_active\")\n : startCase(displayStatus)}\n </StatusPill>\n {actionPolicy.menu.length > 0 &&\n (presentation === \"bottom-sheet\" ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n disabled={isMutating}\n aria-label={t(\"more_subscription_actions\")}\n onClick={() => setActionMenuOpen(true)}\n >\n <Ellipsis className=\"size-4\" aria-hidden />\n </Button>\n <MobileActionSheet\n open={actionMenuOpen}\n onOpenChange={setActionMenuOpen}\n title={t(\"more_subscription_actions\")}\n actions={[\n ...(actionPolicy.menu.includes(\"pause_subscription\")\n ? [\n {\n id: \"pause\",\n label: t(\"pause_subscription\"),\n onSelect: onPause,\n },\n ]\n : []),\n ...(actionPolicy.menu.includes(\"cancel_subscription\")\n ? [\n {\n id: \"cancel\",\n label: t(\"cancel_subscription\"),\n variant: \"destructive\" as const,\n onSelect: onCancel,\n },\n ]\n : []),\n ]}\n />\n </>\n ) : (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n disabled={isMutating}\n aria-label={t(\"more_subscription_actions\")}\n >\n <Ellipsis className=\"size-4\" aria-hidden />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {actionPolicy.menu.includes(\"pause_subscription\") && (\n <DropdownMenuItem onSelect={onPause}>\n <Pause className=\"size-4\" aria-hidden />\n {t(\"pause_subscription\")}\n </DropdownMenuItem>\n )}\n {actionPolicy.menu.includes(\"cancel_subscription\") && (\n <DropdownMenuItem\n onSelect={onCancel}\n className=\"text-destructive focus:text-destructive\"\n >\n <XCircle className=\"size-4\" aria-hidden />\n {t(\"cancel_subscription\")}\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n ))}\n </div>\n </div>\n {actionPolicy.primary === \"resume_subscription\" && (\n <Button\n type=\"button\"\n onClick={onResume}\n disabled={isMutating}\n className=\"mb-4 w-full\"\n >\n <Play className=\"size-4\" aria-hidden />\n {t(\"resume_subscription\")}\n </Button>\n )}\n {actionPolicy.primary === \"reactivate_subscription\" && (\n <Button\n type=\"button\"\n onClick={onReactivate}\n disabled={isMutating}\n className=\"mb-4 w-full\"\n >\n <RotateCcw className=\"size-4\" aria-hidden />\n {t(\"reactivate_subscription\")}\n </Button>\n )}\n <div className=\"divide-border mb-4 flex divide-x\">\n <div className=\"flex-1 pr-4\">\n <div className=\"text-muted-foreground text-sm\">\n {t(\"order_frequency\")}\n </div>\n <div className=\"text-foreground font-medium\">{cadenceLabel}</div>\n </div>\n {subscription.last_ship_date && (\n <div className=\"flex-1 px-4\">\n <div className=\"text-muted-foreground text-sm\">\n {t(\"last_shipped\")}\n </div>\n <div className=\"text-foreground font-medium\">\n {formatOptionalDate(subscription.last_ship_date, locale)}\n </div>\n </div>\n )}\n {subscription.last_bill_date && (\n <div className=\"flex-1 px-4\">\n <div className=\"text-muted-foreground text-sm\">\n {t(\"last_bill_amount\")}\n </div>\n <div className=\"text-foreground font-medium\">{totalPrice}</div>\n <div className=\"text-muted-foreground text-xs\">\n {formatDate(subscription.last_bill_date, locale)}\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Payment & Shipping */}\n <div className=\"pt-2\">\n <h3 className=\"text-foreground mb-4 text-sm/6 font-semibold\">\n {t(\"payment_and_shipping\")}\n </h3>\n <div className=\"flex flex-col\">\n {/* Shipping Address */}\n {renderShippingAddress\n ? renderShippingAddress({\n addressId: subscription.address_id,\n address: subscription.address,\n subscriptionToken: subscription.subscription_token,\n customerId: subscription.customer?.id ?? 0,\n countryCode: subscription.address?.country_code ?? \"US\",\n disabled: isSubscriptionCompleted(subscription),\n })\n : subscription.address && (\n <div className=\"border-border mb-6 border-b pb-4\">\n <div className=\"text-muted-foreground mt-3 mb-1 text-sm\">\n {t(\"shipping_address\")}\n </div>\n <div className=\"text-foreground text-sm\">\n <p className=\"font-medium\">{subscription.address.name}</p>\n <p>{subscription.address.address1}</p>\n {subscription.address.address2 && (\n <p>{subscription.address.address2}</p>\n )}\n <p>\n {[subscription.address.city, subscription.address.state]\n .filter(Boolean)\n .join(\", \")}{\" \"}\n {subscription.address.postal_code}\n </p>\n {subscription.address.country_code && (\n <p>{subscription.address.country_code}</p>\n )}\n {subscription.address.phone && (\n <p>{subscription.address.phone}</p>\n )}\n </div>\n </div>\n )}\n\n {/* Payment Method */}\n {paymentMethod &&\n (renderPaymentMethod ? (\n <div\n id=\"subscription-payment-method-section\"\n className=\"scroll-mt-24\"\n >\n {renderPaymentMethod({\n paymentMethod,\n subscriptionToken: subscription.subscription_token,\n customerId: subscription.customer?.id ?? 0,\n countryCode: subscription.address?.country_code ?? \"US\",\n disabled: paymentMethodDisabled,\n onRecoveryStateChange: onPaymentRecoveryStateChange,\n })}\n </div>\n ) : (\n <div\n id=\"subscription-payment-method-section\"\n className=\"border-border mb-6 scroll-mt-24 border-b pb-4\"\n >\n <div className=\"text-muted-foreground mb-1 text-sm\">\n {t(\"payment_method\")}\n </div>\n <div className=\"text-foreground flex items-center gap-2 text-sm\">\n {paymentDisplay && (\n <PaymentMethodLogo display={paymentDisplay} />\n )}\n {paymentDisplay && (\n <span className=\"font-medium\">\n {paymentDisplay.label}\n </span>\n )}\n </div>\n </div>\n ))}\n\n {/* Automatic points redemption on renewals. Rendered only when the\n host supplies the slot: this component also backs the\n checkout-hosted subscription screens, which do not yet have a\n management surface for it. */}\n {renderAutoApplyPoints?.({\n autoApplyPoints: subscription.auto_apply_points,\n pointsEnabled: subscription.points_enabled,\n subscriptionToken: subscription.subscription_token,\n disabled: isSubscriptionCompleted(subscription),\n renewalBundle: subscription.renewal_bundle,\n })}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n/* ── Order history (own section, full-width below the grid) ────────── */\n\nfunction OrderHistorySection({\n subscription,\n}: {\n subscription: subscriptions.SubscriptionDetailSubscription;\n}) {\n const { t, locale } = useSubscriptionsTranslation();\n if (subscription.orders.length === 0) return null;\n return (\n <section className=\"mt-6 px-8 pt-6 pb-8\">\n <h3 className=\"text-foreground mb-3 text-sm/6 font-semibold\">\n {t(\"subscription_order_history\")}\n </h3>\n <div className=\"border-border overflow-x-auto rounded-md border\">\n <table className=\"divide-border min-w-full divide-y text-sm\">\n <thead className=\"bg-muted\">\n <tr>\n <th className=\"text-muted-foreground py-2 pr-3 pl-3 text-left font-medium\">\n {t(\"order\")}\n </th>\n <th className=\"text-muted-foreground px-3 py-2 text-left font-medium\">\n {t(\"date\")}\n </th>\n <th className=\"text-muted-foreground px-3 py-2 text-left font-medium\">\n {t(\"status\")}\n </th>\n <th className=\"text-muted-foreground py-2 pr-3 pl-3 text-right font-medium\">\n {t(\"amount\")}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-border divide-y\">\n {subscription.orders.map((order) => (\n <tr key={order.id}>\n <td className=\"text-foreground py-2 pr-3 pl-3 font-medium\">\n {order.order_number ?? `#${order.id}`}\n </td>\n <td className=\"text-muted-foreground px-3 py-2\">\n {formatDate(order.created_at.split(\"T\")[0] ?? \"\", locale)}\n </td>\n <td className=\"px-3 py-2\">\n <StatusPill status={order.status}>\n {KNOWN_STATUSES.has(order.status)\n ? t(`list_status_${order.status}` as \"list_status_active\")\n : startCase(order.status)}\n </StatusPill>\n </td>\n <td className=\"text-foreground py-2 pr-3 pl-3 text-right\">\n {order.amount != null\n ? formatCurrency(Number(order.amount))\n : t(\"not_available\")}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </section>\n );\n}\n\n/* ── Main component ────────────────────────────────────────────────── */\n\nexport function SubscriptionDetail({\n token,\n onNotFound,\n onError,\n onSuccess,\n onMutationError,\n onNavigateToSubscription,\n renderPaymentMethod,\n renderShippingAddress,\n renderAutoApplyPoints,\n renderReactivateDialog,\n onUpdatePaymentClick,\n presentation = \"dialog\",\n}: SubscriptionDetailProps): React.JSX.Element | null {\n const { t, locale } = useSubscriptionsTranslation();\n const queryClient = useQueryClient();\n const latestSubscriptionTokenRef = useRef(token);\n latestSubscriptionTokenRef.current = token;\n const [childPaymentRecoveryToken, setChildPaymentRecoveryToken] = useState<\n string | null\n >(null);\n const handlePaymentRecoveryStateChange = useCallback(\n ({\n subscriptionToken,\n isBusy,\n }: {\n subscriptionToken: string;\n isBusy: boolean;\n }) => {\n setChildPaymentRecoveryToken((currentToken) => {\n if (isBusy) return subscriptionToken;\n return currentToken === subscriptionToken ? null : currentToken;\n });\n },\n [],\n );\n const [showCancelModal, setShowCancelModal] = useState(false);\n const [showPauseModal, setShowPauseModal] = useState(false);\n const [showResumeModal, setShowResumeModal] = useState(false);\n const [showReactivateModal, setShowReactivateModal] = useState(false);\n const [showEditBillDateModal, setShowEditBillDateModal] = useState(false);\n const [waiverDialogToken, setWaiverDialogToken] = useState<string | null>(\n null,\n );\n const [pendingNextBillDate, setPendingNextBillDate] = useState<string | null>(\n null,\n );\n const { data, isLoading, error } = useSubscription(token);\n const subscription = data?.subscription;\n const customerId = subscription?.customer?.id ?? 0;\n const waiverPreviewEnabled =\n subscription?.status === \"past_due\" &&\n !isSubscriptionCompleted(subscription) &&\n subscription.next_retry_at == null;\n const waiverPreviewQuery = useFailedCycleWaiverPreview(token, {\n enabled: waiverPreviewEnabled,\n });\n const isWaiverPreviewLoading =\n waiverPreviewEnabled && waiverPreviewQuery.isFetching;\n const waiverPreview = waiverPreviewQuery.data?.failed_cycle_waiver;\n const waiverSchedule =\n waiverPreview?.next_bill_date != null &&\n waiverPreview.next_ship_date != null\n ? getFailedCycleWaiverSummary({\n nextBillDate: waiverPreview.next_bill_date,\n nextShipDate: waiverPreview.next_ship_date,\n locale,\n timezone: subscription?.timezone ?? \"UTC\",\n })\n : null;\n const canWaiveFailedCycle =\n waiverPreviewEnabled &&\n !isWaiverPreviewLoading &&\n !waiverPreviewQuery.isError &&\n waiverPreview?.eligible === true &&\n waiverSchedule != null;\n\n const retryPolling = useRetryStatusPolling({\n subscriptionToken: token,\n onSucceeded: () => onSuccess?.(t(\"payment_retry_succeeded\"), \"success\"),\n onFailed: () => onSuccess?.(t(\"payment_retry_failed\"), \"error\"),\n onTimedOut: () => onSuccess?.(t(\"payment_retry_processing\"), \"warning\"),\n });\n\n const retrySubscription = useRetrySubscription({\n onSuccess: ({ subscriptionToken }: { subscriptionToken: string }) => {\n if (latestSubscriptionTokenRef.current === subscriptionToken) {\n retryPolling.start();\n }\n },\n onError: (\n err: unknown,\n { subscriptionToken }: { subscriptionToken: string },\n ) => {\n if (latestSubscriptionTokenRef.current === subscriptionToken) {\n onMutationError?.(t(\"unable_to_retry_payment\"), err);\n }\n },\n });\n\n const waiverMutation = useWaiveFailedCycle({\n onSuccess: ({ subscriptionToken }) => {\n setWaiverDialogToken((dialogToken) =>\n dialogToken === subscriptionToken ? null : dialogToken,\n );\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n onSuccess?.(t(\"failed_cycle_waiver_succeeded\"), \"success\");\n },\n onError: (err: unknown, { subscriptionToken }) => {\n if (isRecoveryStateChanged(err)) {\n void Promise.all([\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(subscriptionToken),\n exact: true,\n }),\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.failedCycleWaiver(subscriptionToken),\n exact: true,\n }),\n ]);\n\n setWaiverDialogToken((dialogToken) =>\n dialogToken === subscriptionToken ? null : dialogToken,\n );\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n onSuccess?.(t(\"failed_cycle_waiver_state_changed\"), \"warning\");\n return;\n }\n\n if (latestSubscriptionTokenRef.current !== subscriptionToken) {\n setWaiverDialogToken((dialogToken) =>\n dialogToken === subscriptionToken ? null : dialogToken,\n );\n return;\n }\n\n onMutationError?.(t(\"generic_error\"), err);\n },\n });\n\n // Customer's other active subscriptions, only loaded once the bill-date\n // dialog opens — feeds the calendar's color-coded dots. The portal-tenant\n // BFF list endpoint scopes server-side to the member's own customer\n // record (PortalTenant::SubscriptionBrowser), so we don't pass customerId\n // — and we don't gate on it either, since the detail mapper hardcodes\n // customer.id to 0 today.\n //\n // Capped at 100 — a customer with more than 100 subscriptions will be\n // missing some dots from the calendar. Matches the practical ceiling of\n // every other \"list customer's subscriptions\" surface; if/when we have a\n // real-world customer past that, swap to cursor pagination here.\n const customerSubscriptionsQuery = useSubscriptions(\n { perPage: 100 },\n { enabled: showEditBillDateModal },\n );\n const otherSubscriptionsForBillDate = useMemo(\n () =>\n (customerSubscriptionsQuery.data?.subscriptions ?? [])\n .filter((s) => s.subscription_token !== token)\n .map((s) => ({\n token: s.subscription_token,\n productTitle: s.variant?.product?.title ?? t(\"breadcrumb\"),\n nextBillDate: s.next_bill_date,\n billingInterval: s.subscription_plan?.billing_interval ?? 1,\n billingIntervalUnit:\n s.subscription_plan?.billing_interval_unit ?? \"month\",\n })),\n [customerSubscriptionsQuery.data, token, t],\n );\n\n const pauseMutation = usePauseSubscription({\n onSuccess: () => onSuccess?.(t(\"subscription_paused\")),\n onError: (err: unknown) => onMutationError?.(t(\"failed_to_pause\"), err),\n });\n\n const resumeMutation = useResumeSubscription({\n onSuccess: () => onSuccess?.(t(\"subscription_resumed\")),\n onError: (err: unknown) => onMutationError?.(t(\"failed_to_resume\"), err),\n });\n\n const skipMutation = useSkipSubscription({\n onSuccess: () => onSuccess?.(t(\"next_billing_skipped\")),\n onError: (err: unknown) => onMutationError?.(t(\"failed_to_skip\"), err),\n });\n\n const cancelMutation = useCancelSubscription({\n onSuccess: () => {\n onSuccess?.(t(\"subscription_cancelled\"));\n setShowCancelModal(false);\n },\n onError: (err: unknown) => onMutationError?.(t(\"failed_to_cancel\"), err),\n });\n\n const reactivateMutation = useReactivateSubscription({\n onSuccess: () => onSuccess?.(t(\"subscription_reactivated\")),\n onError: (err: unknown) =>\n onMutationError?.(t(\"failed_to_reactivate\"), err),\n });\n\n const [pendingQuantity, setPendingQuantity] = useState<number | null>(null);\n const quantityDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(\n null,\n );\n\n const quantityMutation = useUpdateSubscriptionInfo({\n onSuccess: ({ subscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n // Keep pendingQuantity set so the displayed amounts stay on the\n // new value while the invalidated query refetches. The effect\n // below clears it once the refetched subscription carries the\n // same quantity — avoids a flicker back to the old amounts.\n onSuccess?.(t(\"quantity_updated\"));\n },\n onError: (err: unknown, { subscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n setPendingQuantity(null);\n onMutationError?.(t(\"failed_to_update_quantity\"), err);\n },\n });\n\n const editBillDateMutation = useUpdateSubscriptionInfo({\n onSuccess: ({ subscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n onSuccess?.(t(\"bill_date_updated\"));\n setShowEditBillDateModal(false);\n },\n onError: (err: unknown, { subscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== subscriptionToken) return;\n setPendingNextBillDate(null);\n onMutationError?.(t(\"failed_to_update_bill_date\"), err);\n },\n });\n\n const serverNextBillDate = data?.subscription.next_bill_date ?? null;\n useEffect(() => {\n if (\n pendingNextBillDate != null &&\n serverNextBillDate != null &&\n serverNextBillDate.startsWith(pendingNextBillDate)\n ) {\n setPendingNextBillDate(null);\n }\n }, [pendingNextBillDate, serverNextBillDate]);\n\n const serverQuantity = data?.subscription.quantity;\n useEffect(() => {\n if (pendingQuantity != null && serverQuantity === pendingQuantity) {\n setPendingQuantity(null);\n }\n }, [pendingQuantity, serverQuantity]);\n\n useEffect(\n () => () => {\n if (quantityDebounceRef.current)\n clearTimeout(quantityDebounceRef.current);\n },\n [],\n );\n\n const quantityMutate = quantityMutation.mutate;\n const handleQuantityChange = useCallback(\n (next: number) => {\n const clamped = Math.max(1, next);\n setPendingQuantity(clamped);\n if (quantityDebounceRef.current)\n clearTimeout(quantityDebounceRef.current);\n quantityDebounceRef.current = setTimeout(() => {\n const current = data?.subscription.quantity;\n if (clamped === current) {\n setPendingQuantity(null);\n return;\n }\n quantityMutate({\n subscriptionToken: token,\n body: { quantity: clamped },\n });\n }, 500);\n },\n [data?.subscription.quantity, quantityMutate, token],\n );\n\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const onNotFoundRef = useRef(onNotFound);\n onNotFoundRef.current = onNotFound;\n\n useEffect(() => {\n if (!isLoading && error) {\n onErrorRef.current?.(error as Error);\n }\n }, [isLoading, error]);\n\n useEffect(() => {\n if (!isLoading && !error && !subscription) {\n onNotFoundRef.current?.();\n }\n }, [isLoading, error, subscription]);\n\n if (isLoading) {\n return <SubscriptionDetailSkeleton />;\n }\n\n if (!subscription) {\n return null;\n }\n\n const plan = subscription.subscription_plan;\n const displayStatus = getSubscriptionDisplayStatus(subscription);\n const isActive = displayStatus === \"active\";\n const actionPolicy = getSubscriptionActionPolicy({\n status: subscription.status,\n billingCycleLimitReached: subscription.billing_cycle_limit_reached,\n nextRetryAt: subscription.next_retry_at,\n nextBillDate: subscription.next_bill_date,\n allowSkipping: subscription.subscription_plan.allow_skipping,\n maxSkips: subscription.subscription_plan.max_skips,\n skippedCount: subscription.skipped_count,\n hasPendingSkip: hasPendingSubscriptionSkip(subscription.subscription_skips),\n canChangePaymentMethod: true,\n canWaiveFailedCycle,\n isWaiverPreviewLoading,\n });\n const directParentRecoveryDisabled =\n (retrySubscription.isPending &&\n retrySubscription.variables?.subscriptionToken === token) ||\n retryPolling.isProcessing;\n const independentParentMutationDisabled =\n pauseMutation.isPending ||\n resumeMutation.isPending ||\n skipMutation.isPending ||\n cancelMutation.isPending ||\n reactivateMutation.isPending ||\n editBillDateMutation.isPending;\n const childPaymentRecoveryDisabled = childPaymentRecoveryToken === token;\n const waiverMutationPending =\n waiverMutation.isPending &&\n waiverMutation.variables?.subscriptionToken === token;\n const aggregateRecoveryDisabled =\n directParentRecoveryDisabled ||\n childPaymentRecoveryDisabled ||\n waiverMutationPending;\n const paymentMethodDisabled =\n isSubscriptionCompleted(subscription) ||\n directParentRecoveryDisabled ||\n waiverMutationPending ||\n independentParentMutationDisabled;\n const isMutating =\n independentParentMutationDisabled || aggregateRecoveryDisabled;\n\n const handlePauseConfirm = (selection: PauseSubscriptionSelection) => {\n const pauseParams: subscriptions.PauseSubscriptionParams = { customerId };\n if (selection.type === \"order_count\") {\n pauseParams.numberOfOrders = selection.numberOfOrders;\n }\n pauseMutation.mutate(\n { subscriptionToken: token, pauseParams },\n { onSuccess: () => setShowPauseModal(false) },\n );\n };\n\n const handleResumeConfirm = (nextBillDate: string) => {\n resumeMutation.mutate(\n {\n subscriptionToken: token,\n resumeParams: { customerId, nextBillDate },\n },\n { onSuccess: () => setShowResumeModal(false) },\n );\n };\n\n const handleSkip = () => {\n const nextBillDate = calculateNextBillDate(\n plan.billing_interval,\n plan.billing_interval_unit,\n );\n skipMutation.mutate({\n subscriptionToken: token,\n skipParams: { customerId, nextBillDate },\n });\n };\n\n const handleCancel = () => {\n cancelMutation.mutate({ subscriptionToken: token, customerId });\n };\n\n const handleReactivate = () => {\n // When a consumer supplies the confirmation dialog, open it so the\n // customer can confirm the shipping address first; otherwise reactivate\n // immediately against the subscription's current address.\n if (renderReactivateDialog) {\n setShowReactivateModal(true);\n return;\n }\n reactivateMutation.mutate({\n subscriptionToken: token,\n reactivateParams: {},\n });\n };\n\n const handleRetryPayment = () => {\n if (aggregateRecoveryDisabled) return;\n retrySubscription.mutate({ subscriptionToken: token });\n };\n\n const savedPaymentMethodLabel = getSavedPaymentMethodLabel(\n subscription.payment_method ?? null,\n );\n\n const handleReactivateConfirm = ({\n addressId,\n }: {\n addressId?: number | null;\n }) => {\n reactivateMutation.mutate(\n {\n subscriptionToken: token,\n reactivateParams: addressId != null ? { address_id: addressId } : {},\n },\n { onSuccess: () => setShowReactivateModal(false) },\n );\n };\n\n return (\n <>\n {displayStatus === \"past_due\" && (\n <div className=\"mb-4 px-2 sm:px-0 lg:mb-6\">\n <PastDueBanner\n productTitle={subscription.variant?.product?.title ?? null}\n nextRetryAt={subscription.next_retry_at ?? null}\n declineCount={subscription.decline_count ?? null}\n savedMethodLabel={savedPaymentMethodLabel}\n onRetryPaymentClick={\n actionPolicy.recovery?.primary === \"retry_payment\"\n ? handleRetryPayment\n : undefined\n }\n isRetryingPayment={directParentRecoveryDisabled}\n isCheckingWaiver={actionPolicy.recovery?.isCheckingWaiver === true}\n recoveryDisabled={aggregateRecoveryDisabled}\n onUpdatePaymentClick={\n onUpdatePaymentClick ??\n (() => {\n const el = document.getElementById(\n \"subscription-payment-method-section\",\n );\n if (el) {\n el.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n }\n })\n }\n onWaiveFailedCycleClick={\n actionPolicy.recovery?.tertiary === \"waive_failed_cycle\"\n ? () => setWaiverDialogToken(token)\n : undefined\n }\n />\n </div>\n )}\n <div className=\"flex flex-col lg:grid lg:grid-cols-8\">\n <SubscriptionItemsSection\n subscription={subscription}\n displayQuantity={pendingQuantity ?? undefined}\n displayNextBillDate={pendingNextBillDate ?? undefined}\n canEditQuantity={isActive}\n onQuantityChange={handleQuantityChange}\n isUpdatingQuantity={quantityMutation.isPending}\n onNavigateToSubscription={onNavigateToSubscription}\n />\n <SubscriptionManagementSection\n subscription={subscription}\n actionPolicy={actionPolicy}\n isMutating={isMutating}\n paymentMethodDisabled={paymentMethodDisabled}\n onPaymentRecoveryStateChange={handlePaymentRecoveryStateChange}\n onSkip={handleSkip}\n onPause={() => setShowPauseModal(true)}\n onResume={() => setShowResumeModal(true)}\n onCancel={() => setShowCancelModal(true)}\n onReactivate={handleReactivate}\n onEditBillDate={() => setShowEditBillDateModal(true)}\n renderPaymentMethod={renderPaymentMethod}\n renderShippingAddress={renderShippingAddress}\n renderAutoApplyPoints={renderAutoApplyPoints}\n presentation={presentation}\n />\n </div>\n <OrderHistorySection subscription={subscription} />\n <CancelSubscriptionDialog\n open={showCancelModal}\n presentation={presentation}\n onOpenChange={setShowCancelModal}\n onConfirm={handleCancel}\n onPauseInstead={(months: PauseMonths) => {\n setShowCancelModal(false);\n pauseMutation.mutate({\n subscriptionToken: token,\n pauseParams: {\n customerId,\n nextBillDate: format(addMonths(new Date(), months), \"yyyy-MM-dd\"),\n },\n });\n }}\n />\n <EditBillDateDialog\n open={showEditBillDateModal}\n presentation={presentation}\n onOpenChange={(next) => {\n if (!next) editBillDateMutation.reset();\n setShowEditBillDateModal(next);\n }}\n onConfirm={(nextBillDate) => {\n setPendingNextBillDate(nextBillDate);\n editBillDateMutation.mutate({\n subscriptionToken: token,\n body: { next_bill_date: nextBillDate },\n });\n }}\n isLoading={editBillDateMutation.isPending}\n errorMessage={\n editBillDateMutation.isError ? t(\"bill_date_error\") : undefined\n }\n currentNextBillDate={subscription.next_bill_date}\n billingInterval={plan.billing_interval}\n billingIntervalUnit={plan.billing_interval_unit}\n otherSubscriptions={otherSubscriptionsForBillDate}\n onNavigateToSubscription={onNavigateToSubscription}\n />\n <PauseSubscriptionDialog\n open={showPauseModal}\n presentation={presentation}\n onOpenChange={(next) => {\n if (!next) pauseMutation.reset();\n setShowPauseModal(next);\n }}\n onConfirm={handlePauseConfirm}\n isLoading={pauseMutation.isPending}\n errorMessage={pauseMutation.isError ? t(\"generic_error\") : undefined}\n currentNextBillDate={subscription.next_bill_date}\n billingInterval={plan.billing_interval}\n billingIntervalUnit={plan.billing_interval_unit}\n />\n <ResumeSubscriptionDialog\n open={showResumeModal}\n presentation={presentation}\n onOpenChange={(next) => {\n if (!next) resumeMutation.reset();\n setShowResumeModal(next);\n }}\n onConfirm={handleResumeConfirm}\n isLoading={resumeMutation.isPending}\n errorMessage={resumeMutation.isError ? t(\"generic_error\") : undefined}\n defaultNextBillDate={calculateNextBillDate(\n plan.billing_interval,\n plan.billing_interval_unit,\n )}\n />\n <FailedCycleWaiverDialog\n open={waiverDialogToken === token}\n presentation={presentation}\n preview={\n waiverDialogToken === token\n ? (waiverPreviewQuery.data?.failed_cycle_waiver ?? null)\n : null\n }\n timezone={subscription.timezone ?? \"UTC\"}\n isPending={waiverMutationPending}\n onOpenChange={(open) => {\n if (!open) {\n setWaiverDialogToken((dialogToken) =>\n dialogToken === token ? null : dialogToken,\n );\n }\n }}\n onConfirm={() => {\n if (waiverDialogToken !== token || waiverMutationPending) return;\n waiverMutation.mutate({ subscriptionToken: token });\n }}\n />\n {renderReactivateDialog?.({\n open: showReactivateModal,\n onOpenChange: (next) => {\n if (!next) reactivateMutation.reset();\n setShowReactivateModal(next);\n },\n onConfirm: handleReactivateConfirm,\n isLoading: reactivateMutation.isPending,\n isError: reactivateMutation.isError,\n subscriptionToken: token,\n })}\n </>\n );\n}\n\nexport interface SubscriptionActionsProps {\n isActive: boolean;\n isPaused: boolean;\n isCancelled: boolean;\n isMutating: boolean;\n allowSkipping: boolean | null;\n onPause: () => void;\n onResume: () => void;\n onSkip: () => void;\n onCancel: () => void;\n onReactivate: () => void;\n}\n\nexport function SubscriptionActions({\n isActive,\n isPaused,\n isCancelled,\n isMutating,\n allowSkipping,\n onPause,\n onResume,\n onSkip,\n onCancel,\n onReactivate,\n}: SubscriptionActionsProps): React.JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const actionButtonClass =\n \"flex h-auto flex-row items-center justify-center gap-2 overflow-hidden border border-border bg-muted py-2 text-xs whitespace-nowrap text-foreground hover:bg-accent sm:text-sm\";\n\n return (\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {isActive && (\n <>\n {allowSkipping && (\n <Button\n variant=\"outline\"\n onClick={onSkip}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <SkipForward className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{t(\"skip_next\")}</span>\n </Button>\n )}\n <Button\n variant=\"outline\"\n onClick={onPause}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <Pause className=\"size-3 shrink-0\" />\n <span className=\"truncate\">{t(\"pause\")}</span>\n </Button>\n <Button\n variant=\"outline\"\n onClick={onCancel}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <XCircle className=\"size-3 shrink-0\" />\n <span className=\"truncate\">{t(\"cancel\")}</span>\n </Button>\n </>\n )}\n {isPaused && (\n <>\n <Button\n variant=\"outline\"\n onClick={onResume}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <Play className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{t(\"resume\")}</span>\n </Button>\n <Button\n variant=\"outline\"\n onClick={onCancel}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <XCircle className=\"size-3 shrink-0\" />\n <span className=\"truncate\">{t(\"cancel\")}</span>\n </Button>\n </>\n )}\n {isCancelled && (\n <Button\n variant=\"outline\"\n onClick={onReactivate}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <RotateCcw className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{t(\"reactivate\")}</span>\n </Button>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport type React from \"react\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@fluid-app/ui-primitives\";\nimport { ScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport type { ResponsiveDialogPresentation } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport {\n SubscriptionDetail,\n type PaymentMethodSlotContext,\n type ShippingAddressSlotContext,\n type AutoApplyPointsSlotContext,\n type ReactivateDialogSlotContext,\n} from \"../components/subscription-detail\";\n\nexport interface SubscriptionDetailScreenProps {\n token: string;\n onNavigateToList: () => void;\n onNavigateToSubscription?: (token: string) => void;\n onNotFound?: () => void;\n onError?: (error: Error) => void;\n onSuccess?: (\n message: string,\n severity?: \"success\" | \"error\" | \"warning\",\n ) => void;\n onMutationError?: (message: string, error: unknown) => void;\n renderPaymentMethod?: (ctx: PaymentMethodSlotContext) => React.JSX.Element;\n renderShippingAddress?: (\n ctx: ShippingAddressSlotContext,\n ) => React.JSX.Element;\n renderAutoApplyPoints?: (\n ctx: AutoApplyPointsSlotContext,\n ) => React.JSX.Element;\n renderReactivateDialog?: (\n ctx: ReactivateDialogSlotContext,\n ) => React.JSX.Element;\n onUpdatePaymentClick?: () => void;\n presentation?: ResponsiveDialogPresentation;\n}\n\nexport function SubscriptionDetailScreen({\n token,\n onNavigateToList,\n onNavigateToSubscription,\n onNotFound,\n onError,\n onSuccess,\n onMutationError,\n renderPaymentMethod,\n renderShippingAddress,\n renderAutoApplyPoints,\n renderReactivateDialog,\n onUpdatePaymentClick,\n presentation = \"dialog\",\n}: SubscriptionDetailScreenProps): React.JSX.Element {\n const { t } = useSubscriptionsTranslation();\n\n return (\n <>\n <ScreenHeaderBreadcrumbs>\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbLink\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n onNavigateToList();\n }}\n >\n {t(\"breadcrumb\")}\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n {t(\"breadcrumb_detail\", { token })}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n </ScreenHeaderBreadcrumbs>\n <div className=\"mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-10 lg:py-8\">\n <SubscriptionDetail\n token={token}\n onNotFound={onNotFound}\n onError={onError}\n onSuccess={onSuccess}\n onMutationError={onMutationError}\n onNavigateToSubscription={onNavigateToSubscription}\n renderPaymentMethod={renderPaymentMethod}\n renderShippingAddress={renderShippingAddress}\n renderAutoApplyPoints={renderAutoApplyPoints}\n renderReactivateDialog={renderReactivateDialog}\n onUpdatePaymentClick={onUpdatePaymentClick}\n presentation={presentation}\n />\n </div>\n </>\n );\n}\n","import { useId, useState, type JSX } from \"react\";\nimport { cn, Skeleton } from \"@fluid-app/ui-primitives\";\nimport { ChevronDown } from \"lucide-react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport {\n PaymentIcon,\n getCardDisplayName,\n getCardExpiry,\n getPaymentMethodLogoBrand,\n} from \"@fluid-app/profile-ui/components/payment-method-card-internals\";\nimport { EllipsesDropdown } from \"@fluid-app/profile-ui\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport type { ResponsiveDialogPresentation } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\n\ninterface SelectablePaymentMethodDropdownProps {\n title: string;\n displayPaymentMethod: fluidPay.CustomerPaymentMethod | null;\n paymentMethodList: fluidPay.CustomerPaymentMethod[];\n selectedPaymentMethodId: number;\n onSelectPaymentMethod: (\n paymentMethod: fluidPay.CustomerPaymentMethod,\n ) => void;\n onAddPaymentMethodClick: () => void;\n onEditPaymentMethod?: (paymentMethod: fluidPay.CustomerPaymentMethod) => void;\n onDeletePaymentMethod?: (\n paymentMethod: fluidPay.CustomerPaymentMethod,\n ) => void;\n onMakeDefaultPaymentMethod?: (\n paymentMethod: fluidPay.CustomerPaymentMethod,\n ) => void;\n addPaymentMethodLabel?: string;\n showAddButton?: boolean;\n isLoading?: boolean;\n /** Disable selection while a parent mutation is in flight. */\n isPending?: boolean;\n className?: string;\n presentation?: ResponsiveDialogPresentation;\n}\n\n/**\n * Selectable variant of profile-ui's PaymentMethodDropdown — same chrome\n * (accordion, collapsed summary, list, add button), with rows that\n * commit a selection through onSelectPaymentMethod when clicked.\n */\nexport function SelectablePaymentMethodDropdown({\n title,\n displayPaymentMethod,\n paymentMethodList,\n selectedPaymentMethodId,\n onSelectPaymentMethod,\n onAddPaymentMethodClick,\n onEditPaymentMethod,\n onDeletePaymentMethod,\n onMakeDefaultPaymentMethod,\n addPaymentMethodLabel: addPaymentMethodLabelProp,\n showAddButton = true,\n isLoading = false,\n isPending = false,\n className = \"\",\n presentation = \"dialog\",\n}: SelectablePaymentMethodDropdownProps): JSX.Element {\n const { t } = useProfileTranslation();\n const addPaymentMethodLabel =\n addPaymentMethodLabelProp ?? t(\"add_a_payment_method\");\n const [isOpen, setIsOpen] = useState(false);\n const sectionId = useId();\n const collapsedExpiry = displayPaymentMethod\n ? getCardExpiry(displayPaymentMethod, t(\"card_expires\"))\n : null;\n\n return (\n <div className={cn(\"border-border mb-6 border-b pb-4\", className)}>\n <button\n type=\"button\"\n aria-expanded={isOpen}\n aria-controls={sectionId}\n onClick={() => setIsOpen((prev) => !prev)}\n className=\"flex w-full flex-row items-center justify-between\"\n >\n <span className=\"text-muted-foreground text-sm\">{title}</span>\n <ChevronDown\n className={cn(\n \"text-muted-foreground h-4 w-4 transition-transform duration-200\",\n isOpen && \"rotate-180\",\n )}\n />\n </button>\n\n {/* Collapsed summary — shows the subscription's current payment method\n inline. Clicking expands. Mirrors checkout's payment-method-dropdown\n collapse behavior. */}\n {!isOpen && displayPaymentMethod && (\n <button\n type=\"button\"\n onClick={() => setIsOpen(true)}\n className=\"mt-1 mb-2 flex w-full cursor-pointer flex-row items-center gap-3 text-left\"\n >\n <div className=\"flex h-6 w-10 flex-shrink-0 items-center justify-center\">\n <PaymentIcon\n logoUrl={displayPaymentMethod.details.logo_url}\n brand={getPaymentMethodLogoBrand(displayPaymentMethod)}\n alt={getCardDisplayName(displayPaymentMethod)}\n />\n </div>\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"text-foreground text-sm font-medium\">\n {getCardDisplayName(displayPaymentMethod, t(\"card_fallback\"))}\n </span>\n {collapsedExpiry && (\n <span className=\"text-muted-foreground text-sm\">\n {collapsedExpiry}\n </span>\n )}\n </div>\n </button>\n )}\n\n {isOpen && (\n <div\n id={sectionId}\n role=\"listbox\"\n aria-label={title}\n className=\"mt-5 flex max-h-[400px] flex-col gap-y-4 overflow-y-auto pr-0.5\"\n >\n {isLoading ? (\n <>\n {[1, 2].map((i) => (\n <div\n key={`skeleton-${i}`}\n className=\"bg-muted flex flex-row items-center gap-x-2 rounded-sm p-3\"\n >\n <Skeleton className=\"h-6 w-10\" />\n <div className=\"flex flex-col gap-y-1\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-4 w-24\" />\n </div>\n </div>\n ))}\n </>\n ) : (\n paymentMethodList.map((paymentMethod) => {\n const isSelected = selectedPaymentMethodId === paymentMethod.id;\n const expiry = getCardExpiry(paymentMethod, t(\"card_expires\"));\n const handleSelect = () => {\n if (isPending) return;\n onSelectPaymentMethod(paymentMethod);\n };\n return (\n <div\n key={paymentMethod.id}\n role=\"option\"\n tabIndex={isPending ? -1 : 0}\n aria-selected={isSelected}\n aria-disabled={isPending}\n onClick={handleSelect}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleSelect();\n }\n }}\n className={cn(\n \"text-foreground flex w-full flex-row items-center justify-between gap-3 rounded-sm p-3 text-left transition-colors\",\n \"not-aria-disabled:cursor-pointer aria-disabled:cursor-not-allowed aria-disabled:opacity-60\",\n isSelected\n ? \"bg-background border-border border\"\n : \"bg-muted hover:bg-muted/80 border border-transparent\",\n )}\n >\n <div className=\"flex min-w-0 flex-row items-center gap-3\">\n <div className=\"flex h-6 w-10 flex-shrink-0 items-center justify-center\">\n <PaymentIcon\n logoUrl={paymentMethod.details.logo_url}\n brand={getPaymentMethodLogoBrand(paymentMethod)}\n alt={getCardDisplayName(paymentMethod)}\n />\n </div>\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"text-foreground text-sm font-medium\">\n {getCardDisplayName(paymentMethod)}\n </span>\n {expiry && (\n <span className=\"text-muted-foreground text-sm\">\n {expiry}\n </span>\n )}\n </div>\n </div>\n <div className=\"flex shrink-0 flex-row items-center gap-2\">\n {paymentMethod.default && (\n <span className=\"bg-primary text-primary-foreground rounded px-2 py-0.5 text-xs font-medium\">\n {t(\"default\")}\n </span>\n )}\n {(onEditPaymentMethod ||\n onDeletePaymentMethod ||\n onMakeDefaultPaymentMethod) && (\n <span\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <EllipsesDropdown\n presentation={presentation}\n onEdit={\n onEditPaymentMethod\n ? () => onEditPaymentMethod(paymentMethod)\n : undefined\n }\n onDelete={\n onDeletePaymentMethod\n ? () => onDeletePaymentMethod(paymentMethod)\n : undefined\n }\n onMakeDefault={\n !paymentMethod.default && onMakeDefaultPaymentMethod\n ? () => onMakeDefaultPaymentMethod(paymentMethod)\n : undefined\n }\n />\n </span>\n )}\n </div>\n </div>\n );\n })\n )}\n </div>\n )}\n\n {showAddButton && (\n <button\n type=\"button\"\n disabled={isPending}\n className=\"text-foreground mt-3 text-left text-sm disabled:cursor-not-allowed disabled:opacity-60\"\n onClick={onAddPaymentMethodClick}\n >\n {addPaymentMethodLabel}\n </button>\n )}\n </div>\n );\n}\n","import type { QueryClient } from \"@tanstack/react-query\";\nimport {\n isSubscriptionCompleted,\n subscriptionsKeys,\n type subscriptions,\n} from \"@fluid-app/subscriptions-core\";\n\nexport function isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionToken: string,\n completedSubscriptionToken: string,\n): boolean {\n return latestSubscriptionToken === completedSubscriptionToken;\n}\n\nexport async function invalidateSubscriptionPaymentRecoveryCache(\n queryClient: QueryClient,\n subscriptionToken: string,\n): Promise<void> {\n await Promise.all([\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists }),\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n }),\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.detail(subscriptionToken),\n }),\n ]);\n}\n\nexport async function completeSubscriptionPaymentUpdate(args: {\n queryClient: QueryClient;\n updatedSubscriptionToken: string;\n getLatestSubscriptionToken: () => string;\n isExternallyDisabled: () => boolean;\n queueRetry: (subscriptionToken: string) => void;\n notifyUpdated: () => void;\n}): Promise<void> {\n const cached =\n args.queryClient.getQueryData<subscriptions.SubscriptionDetail>(\n subscriptionsKeys.detail(args.updatedSubscriptionToken),\n );\n if (\n cached?.subscription.status === \"past_due\" &&\n !isSubscriptionCompleted(cached.subscription)\n ) {\n args.queueRetry(args.updatedSubscriptionToken);\n return;\n }\n\n await invalidateSubscriptionPaymentRecoveryCache(\n args.queryClient,\n args.updatedSubscriptionToken,\n );\n if (\n isCurrentSubscriptionPaymentAttempt(\n args.getLatestSubscriptionToken(),\n args.updatedSubscriptionToken,\n ) &&\n !args.isExternallyDisabled()\n ) {\n args.notifyUpdated();\n }\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type JSX,\n} from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport {\n FluidPayCoreProvider,\n type State,\n type fluidPay,\n} from \"@fluid-app/fluid-pay-core\";\nimport {\n AddressFormDialog,\n ConfirmActionDialog,\n CreditCardFormDialog,\n EditPaymentMethodDialog,\n type CreditCardFormSubmitData,\n type EditPaymentMethodFormData,\n} from \"@fluid-app/profile-ui\";\nimport { useActiveLocale } from \"@fluid-app/i18n/locale-context\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { SelectablePaymentMethodDropdown } from \"./SelectablePaymentMethodDropdown\";\nimport {\n useRetryStatusPolling,\n useRetrySubscription,\n useUpdateSubscriptionInfo,\n} from \"@fluid-app/subscriptions-core\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport type { PaymentMethodSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport { TOKEN_PROVIDER_VGS } from \"@fluid-app/portal-core/pay-types\";\nimport type {\n PayAddress,\n UpdatePaymentMethodBody,\n} from \"@fluid-app/portal-core/pay-types\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { useCountriesApi } from \"@fluid-app/store-core/countries-api-context\";\nimport { payKeys, storeKeys } from \"../account/query-keys\";\nimport {\n createFluidPayApiAdapter,\n mapToFluidPayPaymentMethod,\n} from \"../adapters/fluid-pay-api-adapter\";\nimport { ProfileTranslationBridge } from \"../providers/ProfileTranslationBridge\";\nimport { getBrowserInfo } from \"@fluid-app/fluid-pay-core/utils/browser-info\";\nimport { usePortalCardAdd3DSFlow } from \"../hooks/use-portal-card-add-3ds-flow\";\nimport { buildSubscriptionCardAddSuccess } from \"./subscription-card-add-success\";\nimport {\n completeSubscriptionPaymentUpdate,\n invalidateSubscriptionPaymentRecoveryCache,\n isCurrentSubscriptionPaymentAttempt,\n} from \"./subscription-payment-recovery\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n phone: raw.phone,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\n// Map the subscription's payment_method shape (which lives on\n// SubscriptionDetail and uses different field names than PayApi) to the\n// fluidPay shape PaymentMethodDropdown consumes.\nfunction subscriptionPaymentMethodToFluidPay(\n raw: subscriptions.SubscriptionDetailPaymentMethod,\n): fluidPay.CustomerPaymentMethod {\n const details = raw.details as {\n last4?: string;\n card_network?: string;\n card_brand?: string;\n logo_url?: string;\n exp_month?: number | string;\n exp_year?: number | string;\n } | null;\n return {\n id: raw.id,\n created_at: raw.created_at,\n default: raw.default,\n details: {\n card_network: details?.card_network ?? null,\n card_brand: details?.card_brand ?? details?.card_network ?? null,\n last_four: details?.last4 ?? \"\",\n exp_month:\n details?.exp_month != null ? Number(details.exp_month) : undefined,\n exp_year:\n details?.exp_year != null ? Number(details.exp_year) : undefined,\n logo_url: details?.logo_url,\n },\n billing_address: null,\n payment_type: raw.payment_type,\n source: raw.source,\n updated_at: raw.updated_at,\n };\n}\n\ntype PaymentMethodSectionProps = PaymentMethodSlotContext & {\n // severity defaults to \"success\"; the async-retry outcome uses \"error\" to\n // surface a declined charge through the same toast channel.\n onSuccess?: (\n message: string,\n severity?: \"success\" | \"error\" | \"warning\",\n ) => void;\n onError?: (message: string, error: unknown) => void;\n // Optional controlled props so a parent (e.g. the past-due banner CTA in\n // SubscriptionDetailScreen) can open the Add Payment Method dialog from\n // outside this section. When omitted, the section manages the dialog\n // internally as before.\n addDialogOpen?: boolean;\n onAddDialogOpenChange?: (open: boolean) => void;\n};\n\nexport function PortalSubscriptionPaymentMethodSection(\n props: PaymentMethodSectionProps,\n): JSX.Element {\n return (\n <ProfileTranslationBridge>\n <PortalSubscriptionPaymentMethodSectionInner {...props} />\n </ProfileTranslationBridge>\n );\n}\n\nfunction PortalSubscriptionPaymentMethodSectionInner({\n paymentMethod: currentPaymentMethod,\n subscriptionToken,\n disabled,\n onRecoveryStateChange,\n onSuccess,\n onError,\n addDialogOpen,\n onAddDialogOpenChange,\n}: PaymentMethodSectionProps): JSX.Element {\n const { isMobile } = useSidebar();\n const { t: profileT } = useProfileTranslation();\n const { t: subsT } = useSubscriptionsTranslation();\n const { locale } = useActiveLocale();\n const latestSubscriptionTokenRef = useRef(subscriptionToken);\n latestSubscriptionTokenRef.current = subscriptionToken;\n const externallyDisabledRef = useRef(disabled);\n externallyDisabledRef.current = disabled;\n const cardAddSubscriptionTokenRef = useRef<string | null>(null);\n const walletMutationSubscriptionTokenRef = useRef<string | null>(null);\n const isCurrentPaymentAttempt = (\n attemptSubscriptionToken: string | null,\n ): attemptSubscriptionToken is string =>\n attemptSubscriptionToken !== null &&\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n attemptSubscriptionToken,\n );\n\n // Bridge for fluid-pay-ui dialogs that accept `t: (key: string) => string`.\n // The underlying adapter falls back to `key` for unknown keys, so widening\n // the key type is safe at runtime.\n const tFn = useCallback(\n (key: string): string => profileT(key as never),\n [profileT],\n );\n\n const payApi = usePayApi();\n const queryClient = useQueryClient();\n const fluidPayShim = useMemo(\n () => createFluidPayApiAdapter(payApi),\n [payApi],\n );\n\n const [internalAddDialogOpen, setInternalAddDialogOpen] = useState(false);\n const isAddDialogOpen = addDialogOpen ?? internalAddDialogOpen;\n const setIsAddDialogOpen = useCallback(\n (next: boolean) => {\n if (onAddDialogOpenChange) onAddDialogOpenChange(next);\n else setInternalAddDialogOpen(next);\n },\n [onAddDialogOpenChange],\n );\n // Track whether the most recent dialog-open came from the dropdown's\n // \"Add Payment Method\" (internal — just save to wallet) or from a\n // banner/action trigger via the controlled addDialogOpen prop (external\n // — swap the subscription onto the new card after creating it).\n const dropdownInitiatedAddRef = useRef(false);\n const [editingPaymentMethod, setEditingPaymentMethod] =\n useState<fluidPay.CustomerPaymentMethod | null>(null);\n const [deletingPaymentMethod, setDeletingPaymentMethod] =\n useState<fluidPay.CustomerPaymentMethod | null>(null);\n const [deleteError, setDeleteError] = useState<string | undefined>(undefined);\n const [saveCardError, setSaveCardError] = useState<string | null>(null);\n const previousDialogSubscriptionTokenRef = useRef(subscriptionToken);\n\n const { data: paymentMethods = [], isLoading: isLoadingMethods } = useQuery({\n queryKey: payKeys.paymentMethods.list(),\n queryFn: async () => {\n const response = await payApi.fetchPaymentMethods();\n return response.payment_methods.map(mapToFluidPayPaymentMethod);\n },\n });\n\n const { data: addresses = [] } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n enabled: isAddDialogOpen,\n });\n\n const countriesApi = useCountriesApi();\n const { data: countriesData } = useQuery({\n queryKey: storeKeys.countries(locale),\n queryFn: () => countriesApi.listCountries({ languageIso: locale }),\n enabled: isAddDialogOpen || editingPaymentMethod !== null,\n });\n const countryOptions = useMemo(\n () =>\n [...(countriesData?.countries ?? [])]\n .map((c) => ({ iso: c.code, name: c.name }))\n .sort((a, b) => a.name.localeCompare(b.name)),\n [countriesData],\n );\n const statesByCountry = useMemo(() => {\n const map = new Map<string, State[]>();\n for (const c of countriesData?.countries ?? []) {\n map.set(\n c.code,\n c.states.map((s) => ({ name: s.name, isoCode: s.code })),\n );\n }\n return map;\n }, [countriesData]);\n const fetchStatesFromCountries = useCallback(\n (countryCode: string): Promise<State[]> =>\n Promise.resolve(statesByCountry.get(countryCode) ?? []),\n [statesByCountry],\n );\n\n // The retry queues an async charge and returns with the sub still past_due,\n // so poll for the outcome rather than leaving the stale \"we're trying your\n // payment again\" copy up until the customer refreshes (CURRENT-1877). Hosted\n // here (not in the past-due banner) so the success toast survives the banner\n // unmounting when status flips to active.\n const retryStatusPolling = useRetryStatusPolling({\n subscriptionToken,\n onSucceeded: () => onSuccess?.(subsT(\"payment_retry_succeeded\")),\n onFailed: () => onSuccess?.(subsT(\"payment_retry_failed\"), \"error\"),\n // The charge is taking longer than the poll window — confirm the card\n // saved so the customer isn't left with no feedback (the banner keeps the\n // \"we'll update once processed\" copy).\n onTimedOut: () => onSuccess?.(subsT(\"payment_retry_processing\")),\n });\n\n const retrySubscription = useRetrySubscription({\n onSuccess: ({ subscriptionToken: queuedSubscriptionToken }) => {\n if (\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n queuedSubscriptionToken,\n ) &&\n !externallyDisabledRef.current\n ) {\n retryStatusPolling.start();\n }\n },\n onError: async (err, { subscriptionToken: failedSubscriptionToken }) => {\n await invalidateSubscriptionPaymentRecoveryCache(\n queryClient,\n failedSubscriptionToken,\n );\n if (\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n failedSubscriptionToken,\n )\n ) {\n onError?.(\"Failed to queue retry\", err);\n }\n },\n });\n\n const updateSubscription = useUpdateSubscriptionInfo({\n // Skip the hook's auto-invalidate so we coalesce into a single\n // refetch — either retrySubscription's onSuccess (past_due path)\n // or the explicit invalidate below (non-past-due path).\n skipAutoInvalidate: true,\n onSuccess: async ({ subscriptionToken: updatedSubscriptionToken }) => {\n // Explicit retry as a separate request, only when the sub was\n // past_due. Decoupled from the update endpoint per SRP — and\n // gated client-side so non-past-due subs don't fire a redundant\n // request (backend would no-op, but we don't want to ask).\n //\n // Toast + invalidation are deferred to whichever path runs:\n // - past_due: skip the \"payment method updated\" toast — the retry\n // outcome (succeeded/failed/processing) is the relevant feedback\n // and fires a moment later, so a bare \"updated\" here would read as\n // contradictory against a subsequent decline. useRetrySubscription\n // invalidates on its own onSuccess (single refetch covers both).\n // - non-past_due: confirm the update and invalidate inline.\n await completeSubscriptionPaymentUpdate({\n queryClient,\n updatedSubscriptionToken,\n getLatestSubscriptionToken: () => latestSubscriptionTokenRef.current,\n isExternallyDisabled: () => externallyDisabledRef.current,\n queueRetry: (subscriptionToken) =>\n retrySubscription.mutate({ subscriptionToken }),\n notifyUpdated: () =>\n onSuccess?.(profileT(\"default_payment_method_updated\")),\n });\n },\n onError: (err, { subscriptionToken: failedSubscriptionToken }) => {\n if (\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n failedSubscriptionToken,\n )\n ) {\n onError?.(profileT(\"failed_to_update_payment_method\"), err);\n }\n },\n });\n\n // Route a freshly-created (or 3DS-approved) payment method per how the Add\n // dialog was opened. Only chain the subscription's payment-method swap when\n // the dialog was opened externally (banner CTA / \"Update Payment Method\"\n // action) — those signal intent to bill this subscription on the new card.\n // The dropdown's \"Add Payment Method\" path just adds to the wallet; the\n // customer can switch later via onSelectPaymentMethod.\n //\n // Toast handling: skip \"payment_method_added\" on the external path because\n // updateSubscription's onSuccess will fire the more relevant\n // \"default_payment_method_updated\" toast a moment later, and two success\n // toasts in rapid succession is noise.\n const routeCreatedPaymentMethod = (paymentMethodId: number) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (\n !isCurrentPaymentAttempt(initiatedSubscriptionToken) ||\n externallyDisabledRef.current\n ) {\n return;\n }\n\n const wasDropdownInitiated = dropdownInitiatedAddRef.current;\n dropdownInitiatedAddRef.current = false;\n if (wasDropdownInitiated) {\n onSuccess?.(profileT(\"payment_method_added\"));\n } else {\n updateSubscription.mutate({\n subscriptionToken: initiatedSubscriptionToken,\n body: { payment_method_id: paymentMethodId },\n });\n }\n };\n\n // Orchestrates the bank-challenge step when card add returns three_ds_required.\n // begin() resolves the moment the challenge modal opens — so dialog close and\n // the routing live ONLY here (onApproved) and on the created branch\n // (onCreated below), never on the three_ds_required branch.\n const cardAdd3DS = usePortalCardAdd3DSFlow({\n payApi,\n t: tFn,\n onApproved: async (approved) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (!isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n return;\n }\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n setIsAddDialogOpen(false);\n routeCreatedPaymentMethod(approved.payment_method.id);\n },\n onFailed: (message) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n setSaveCardError(message);\n }\n },\n onCanceled: () => {},\n });\n\n useEffect(() => {\n const tokenChanged =\n previousDialogSubscriptionTokenRef.current !== subscriptionToken;\n if (tokenChanged) {\n previousDialogSubscriptionTokenRef.current = subscriptionToken;\n dropdownInitiatedAddRef.current = false;\n setEditingPaymentMethod(null);\n setDeletingPaymentMethod(null);\n setDeleteError(undefined);\n setSaveCardError(null);\n }\n\n const staleCardAttempt =\n cardAddSubscriptionTokenRef.current !== null &&\n cardAddSubscriptionTokenRef.current !== subscriptionToken;\n if (!cardAdd3DS.isActive && (tokenChanged || staleCardAttempt)) {\n cardAddSubscriptionTokenRef.current = null;\n setIsAddDialogOpen(false);\n }\n }, [cardAdd3DS.isActive, setIsAddDialogOpen, subscriptionToken]);\n\n const cardAddSuccess = buildSubscriptionCardAddSuccess({\n begin: cardAdd3DS.begin,\n onCreated: (paymentMethodId) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (!isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n return;\n }\n queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n setIsAddDialogOpen(false);\n routeCreatedPaymentMethod(paymentMethodId);\n },\n });\n\n // Invalidation lives in the 3DS handlers (onApproved) and the created branch\n // (onCreated above), never in mutationFn — on the three_ds_required path the\n // mutation resolves the moment the challenge opens, so invalidating here would\n // refetch the list mid-challenge before the card is confirmed. Mirrors the\n // profile surface.\n const addCardMutation = useMutation({\n mutationFn: (data: CreditCardFormSubmitData) =>\n payApi.createPaymentMethod({\n payment_method: {\n type: \"card\",\n token: data.payment_method.token,\n token_provider: TOKEN_PROVIDER_VGS,\n exp_month: data.payment_method.exp_month,\n exp_year: data.payment_method.exp_year,\n cvv_token: data.payment_method.cvv_token,\n card_holder: data.payment_method.card_holder,\n default: data.set_as_default,\n ...(data.payment_method.bin ? { bin: data.payment_method.bin } : {}),\n ...(data.payment_method.last_four\n ? { last_four: data.payment_method.last_four }\n : {}),\n ...(data.payment_method.card_network\n ? { card_network: data.payment_method.card_network }\n : {}),\n },\n billing_address_id: data.billing_address_id,\n browser_info: getBrowserInfo(),\n }),\n onSuccess: async (response) => {\n if (!isCurrentPaymentAttempt(cardAddSubscriptionTokenRef.current)) {\n return;\n }\n await cardAddSuccess(response);\n },\n onError: (err) => {\n const initiatedSubscriptionToken = cardAddSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onError?.(profileT(\"failed_to_add_payment_method\"), err);\n }\n },\n });\n\n const createAddressMutation = useMutation({\n mutationFn: (body: fluidPay.CreateAddressBody) => {\n return payApi.createAddress({\n address: {\n name: body.address.name,\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n phone: body.address.phone,\n },\n });\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n },\n onError: (err) => {\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onError?.(profileT(\"failed_to_create_address\"), err);\n }\n },\n });\n\n const updatePaymentMethodMutation = useMutation({\n mutationFn: ({\n paymentMethodId,\n data,\n }: {\n paymentMethodId: number;\n data: EditPaymentMethodFormData;\n }) =>\n payApi.updatePaymentMethod(paymentMethodId, {\n payment_method: {\n default: data.set_as_default,\n billing_address: {\n name: data.billing_address.name,\n street1: data.billing_address.address1,\n street2: data.billing_address.address2 ?? null,\n city: data.billing_address.city,\n state: data.billing_address.state,\n zip: data.billing_address.zip,\n country: data.billing_address.country_code,\n },\n },\n }),\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onSuccess?.(profileT(\"default_payment_method_updated\"));\n }\n },\n onError: (err) => {\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onError?.(profileT(\"failed_to_update_payment_method\"), err);\n }\n },\n });\n\n const deletePaymentMethodMutation = useMutation({\n mutationFn: (paymentMethodId: number) =>\n payApi.deletePaymentMethod(paymentMethodId),\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onSuccess?.(profileT(\"payment_method_deleted\"));\n }\n },\n });\n\n const makeDefaultPaymentMethodMutation = useMutation({\n mutationFn: (pm: fluidPay.CustomerPaymentMethod) => {\n const body: UpdatePaymentMethodBody = {\n payment_method: { default: true },\n };\n if (pm.billing_address) {\n body.payment_method.billing_address = {\n name: pm.billing_address.name,\n street1: pm.billing_address.address1 ?? \"\",\n street2: pm.billing_address.address2 ?? null,\n city: pm.billing_address.city ?? \"\",\n state: pm.billing_address.state ?? \"\",\n zip: pm.billing_address.zip ?? \"\",\n country: pm.billing_address.country_code ?? \"\",\n };\n }\n return payApi.updatePaymentMethod(pm.id, body);\n },\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onSuccess?.(profileT(\"default_payment_method_updated\"));\n }\n },\n onError: (err) => {\n const initiatedSubscriptionToken =\n walletMutationSubscriptionTokenRef.current;\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onError?.(profileT(\"failed_to_set_default_payment_method\"), err);\n }\n },\n });\n\n // Fall back to the subscription's own payment method when the customer's\n // list doesn't contain it yet (initial load) or no longer contains it (card\n // was removed in another session). Without the fallback the collapsed\n // accordion header would render blank.\n const displayed =\n paymentMethods.find((pm) => pm.id === currentPaymentMethod.id) ??\n subscriptionPaymentMethodToFluidPay(currentPaymentMethod);\n\n const walletMutationPending =\n createAddressMutation.isPending ||\n updatePaymentMethodMutation.isPending ||\n deletePaymentMethodMutation.isPending ||\n makeDefaultPaymentMethodMutation.isPending;\n const cardAddPending = addCardMutation.isPending || cardAdd3DS.isActive;\n const hasAnyLocalPaymentActivity =\n updateSubscription.isPending ||\n retrySubscription.isPending ||\n retryStatusPolling.isProcessing ||\n cardAddPending ||\n walletMutationPending;\n const localPaymentActivity =\n (updateSubscription.isPending &&\n updateSubscription.variables?.subscriptionToken === subscriptionToken) ||\n (retrySubscription.isPending &&\n retrySubscription.variables?.subscriptionToken === subscriptionToken) ||\n retryStatusPolling.isProcessing ||\n (cardAddPending &&\n cardAddSubscriptionTokenRef.current === subscriptionToken) ||\n (walletMutationPending &&\n walletMutationSubscriptionTokenRef.current === subscriptionToken);\n const paymentActionsDisabled = disabled || hasAnyLocalPaymentActivity;\n\n useEffect(() => {\n onRecoveryStateChange?.({\n subscriptionToken,\n isBusy: localPaymentActivity,\n });\n }, [localPaymentActivity, onRecoveryStateChange, subscriptionToken]);\n\n useEffect(\n () => () => {\n onRecoveryStateChange?.({\n subscriptionToken,\n isBusy: false,\n });\n },\n [onRecoveryStateChange, subscriptionToken],\n );\n\n const handleConfirmDelete = async () => {\n if (paymentActionsDisabled || !deletingPaymentMethod) return;\n const initiatedSubscriptionToken = subscriptionToken;\n walletMutationSubscriptionTokenRef.current = initiatedSubscriptionToken;\n setDeleteError(undefined);\n try {\n await deletePaymentMethodMutation.mutateAsync(deletingPaymentMethod.id);\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n setDeletingPaymentMethod(null);\n }\n } catch (err) {\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n setDeleteError(\n err instanceof Error\n ? err.message\n : profileT(\"unable_to_delete_payment_method\"),\n );\n }\n }\n };\n\n return (\n <FluidPayCoreProvider api={fluidPayShim}>\n <SelectablePaymentMethodDropdown\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={subsT(\"payment_method\")}\n displayPaymentMethod={displayed}\n paymentMethodList={paymentMethods}\n onAddPaymentMethodClick={() => {\n if (paymentActionsDisabled) return;\n dropdownInitiatedAddRef.current = true;\n setIsAddDialogOpen(true);\n }}\n addPaymentMethodLabel={profileT(\"add_payment_method_action\")}\n showAddButton\n isLoading={isLoadingMethods}\n isPending={paymentActionsDisabled}\n selectedPaymentMethodId={currentPaymentMethod.id}\n onSelectPaymentMethod={(pm) => {\n if (paymentActionsDisabled || pm.id === currentPaymentMethod.id) {\n return;\n }\n updateSubscription.mutate({\n subscriptionToken,\n body: { payment_method_id: pm.id },\n });\n }}\n onEditPaymentMethod={\n paymentActionsDisabled\n ? undefined\n : (pm) => setEditingPaymentMethod(pm)\n }\n onDeletePaymentMethod={\n paymentActionsDisabled\n ? undefined\n : (pm) => {\n setDeleteError(undefined);\n setDeletingPaymentMethod(pm);\n }\n }\n onMakeDefaultPaymentMethod={\n paymentActionsDisabled\n ? undefined\n : (pm) => {\n walletMutationSubscriptionTokenRef.current = subscriptionToken;\n makeDefaultPaymentMethodMutation.mutate(pm);\n }\n }\n />\n\n <CreditCardFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isAddDialogOpen}\n onClose={() => {\n // Don't let the card dialog close while a 3DS challenge is in flight —\n // the bank-verification modal renders behind it and would be stranded.\n if (cardAdd3DS.isActive) return;\n // Reset the dropdown-initiated flag on every close (abandon or\n // post-submit) so a stale \"true\" from a closed-without-submit\n // dropdown attempt can't suppress the subscription swap on the\n // next banner/action open.\n dropdownInitiatedAddRef.current = false;\n cardAddSubscriptionTokenRef.current = null;\n setSaveCardError(null);\n setIsAddDialogOpen(false);\n }}\n error={saveCardError ?? undefined}\n t={tFn}\n onSubmit={async (data) => {\n if (paymentActionsDisabled) return;\n cardAddSubscriptionTokenRef.current = subscriptionToken;\n setSaveCardError(null);\n try {\n // Closure happens in cardAddSuccess (created PM) / the 3DS\n // onApproved branch — NOT here, since a three_ds_required response\n // resolves successfully while the bank check is still pending.\n await addCardMutation.mutateAsync(data);\n } catch {\n // onError surfaces the toast; swallow here so CreditCardFormDialog\n // doesn't see an unhandled rejection from its onSubmit handler.\n }\n }}\n isSubmitting={paymentActionsDisabled}\n jwt=\"\"\n savedAddresses={addresses}\n defaultBillingAddressId={addresses.find((a) => a.default)?.id}\n renderAddressFormDialog={({ isOpen, onClose, onAddressCreated }) => (\n <AddressFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isOpen}\n onClose={onClose}\n selectedAddress={null}\n t={tFn}\n onSubmit={async (formData) => {\n if (paymentActionsDisabled) return;\n const initiatedSubscriptionToken = subscriptionToken;\n walletMutationSubscriptionTokenRef.current =\n initiatedSubscriptionToken;\n try {\n const created =\n await createAddressMutation.mutateAsync(formData);\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n onAddressCreated(mapToFluidPayAddress(created));\n }\n } catch {\n // onError surfaces the toast.\n }\n }}\n isSubmitting={paymentActionsDisabled}\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n languageIso={locale}\n />\n )}\n />\n\n {cardAdd3DS.modal}\n\n <EditPaymentMethodDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={editingPaymentMethod !== null}\n paymentMethod={editingPaymentMethod}\n billingAddress={editingPaymentMethod?.billing_address ?? null}\n onClose={() => setEditingPaymentMethod(null)}\n onSubmit={async (data) => {\n if (paymentActionsDisabled || !editingPaymentMethod) return;\n const initiatedSubscriptionToken = subscriptionToken;\n walletMutationSubscriptionTokenRef.current =\n initiatedSubscriptionToken;\n try {\n await updatePaymentMethodMutation.mutateAsync({\n paymentMethodId: editingPaymentMethod.id,\n data,\n });\n if (isCurrentPaymentAttempt(initiatedSubscriptionToken)) {\n setEditingPaymentMethod(null);\n }\n } catch {\n // onError surfaces the toast.\n }\n }}\n isSubmitting={paymentActionsDisabled}\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n languageIso={locale}\n />\n\n <ConfirmActionDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={profileT(\"delete_credit_card\")}\n description={profileT(\"delete_credit_card_message\")}\n actionText={profileT(\"delete\")}\n openDialog={deletingPaymentMethod !== null}\n setOpenDialog={(open) => {\n if (!open) {\n setDeletingPaymentMethod(null);\n setDeleteError(undefined);\n }\n }}\n onAction={handleConfirmDelete}\n errorMsg={deleteError}\n isLoading={paymentActionsDisabled}\n />\n </FluidPayCoreProvider>\n );\n}\n","import { useId, useState, type JSX } from \"react\";\nimport { cn, Skeleton } from \"@fluid-app/ui-primitives\";\nimport { ChevronDown } from \"lucide-react\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { EllipsesDropdown } from \"@fluid-app/profile-ui\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport type { ResponsiveDialogPresentation } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\n\ninterface SelectableAddressDropdownProps {\n title: string;\n displayAddress: fluidPay.CustomerAddress | null;\n addressList: fluidPay.CustomerAddress[];\n selectedAddressId: number;\n onSelectAddress: (address: fluidPay.CustomerAddress) => void;\n onAddAddressClick: () => void;\n onEditAddress?: (address: fluidPay.CustomerAddress) => void;\n onDeleteAddress?: (address: fluidPay.CustomerAddress) => void;\n onMakeDefaultAddress?: (address: fluidPay.CustomerAddress) => void;\n addAddressLabel?: string;\n showAddButton?: boolean;\n isLoading?: boolean;\n /** Disable selection while a parent mutation is in flight. */\n isPending?: boolean;\n /** Start expanded (list visible) instead of collapsed to the summary. */\n defaultOpen?: boolean;\n className?: string;\n presentation?: ResponsiveDialogPresentation;\n}\n\nfunction formatLine1(address: fluidPay.CustomerAddress): string {\n return [address.address1, address.address2].filter(Boolean).join(\", \");\n}\n\nfunction formatCityStateZip(address: fluidPay.CustomerAddress): string {\n const cityState = [address.city, address.state].filter(Boolean).join(\", \");\n return [cityState, address.postal_code].filter(Boolean).join(\" \");\n}\n\n/**\n * Selectable variant of profile-ui's AddressDropdown, mirroring\n * SelectablePaymentMethodDropdown. Flat layout (no Card wrapper) so it\n * sits inline next to the payment method dropdown in the subscription\n * detail's Payment & Shipping section.\n */\nexport function SelectableAddressDropdown({\n title,\n displayAddress,\n addressList,\n selectedAddressId,\n onSelectAddress,\n onAddAddressClick,\n onEditAddress,\n onDeleteAddress,\n onMakeDefaultAddress,\n addAddressLabel: addAddressLabelProp,\n showAddButton = true,\n isLoading = false,\n isPending = false,\n defaultOpen = false,\n className = \"\",\n presentation = \"dialog\",\n}: SelectableAddressDropdownProps): JSX.Element {\n const { t } = useProfileTranslation();\n const addAddressLabel = addAddressLabelProp ?? t(\"add_an_address\");\n const [isOpen, setIsOpen] = useState(defaultOpen);\n const sectionId = useId();\n\n return (\n <div className={cn(\"border-border mb-6 border-b pb-4\", className)}>\n <button\n type=\"button\"\n aria-expanded={isOpen}\n aria-controls={sectionId}\n onClick={() => setIsOpen((prev) => !prev)}\n className=\"flex w-full flex-row items-center justify-between\"\n >\n <span className=\"text-muted-foreground text-sm\">{title}</span>\n <ChevronDown\n className={cn(\n \"text-muted-foreground h-4 w-4 transition-transform duration-200\",\n isOpen && \"rotate-180\",\n )}\n />\n </button>\n\n {/* Collapsed summary — shows the subscription's current address inline.\n Clicking expands. Mirrors checkout's address-dropdown collapse\n behavior. */}\n {!isOpen && displayAddress && (\n <button\n type=\"button\"\n onClick={() => setIsOpen(true)}\n className=\"mt-1 mb-2 flex w-full cursor-pointer flex-col text-left\"\n >\n <span className=\"text-foreground text-sm font-medium\">\n {displayAddress.name}\n {displayAddress.name && displayAddress.address1 ? \", \" : \"\"}\n {displayAddress.address1}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n {formatCityStateZip(displayAddress)}\n </span>\n {displayAddress.phone && (\n <span className=\"text-muted-foreground text-sm\">\n {displayAddress.phone}\n </span>\n )}\n </button>\n )}\n\n {isOpen && (\n <div\n id={sectionId}\n role=\"listbox\"\n aria-label={title}\n className=\"mt-5 flex max-h-[400px] flex-col gap-y-4 overflow-y-auto pr-0.5\"\n >\n {isLoading ? (\n <>\n {[1, 2].map((i) => (\n <div key={`skeleton-${i}`} className=\"bg-muted rounded-sm p-3\">\n <Skeleton className=\"mb-1 h-4 w-32\" />\n <Skeleton className=\"mb-1 h-4 w-48\" />\n <Skeleton className=\"h-4 w-40\" />\n </div>\n ))}\n </>\n ) : (\n addressList.map((address) => {\n const isSelected = selectedAddressId === address.id;\n const handleSelect = () => {\n if (isPending) return;\n onSelectAddress(address);\n };\n return (\n <div\n key={address.id}\n role=\"option\"\n tabIndex={isPending ? -1 : 0}\n aria-selected={isSelected}\n aria-disabled={isPending}\n onClick={handleSelect}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleSelect();\n }\n }}\n className={cn(\n \"text-foreground flex w-full flex-row items-center justify-between gap-3 rounded-sm p-3 text-left transition-colors\",\n \"not-aria-disabled:cursor-pointer aria-disabled:cursor-not-allowed aria-disabled:opacity-60\",\n isSelected\n ? \"bg-background border-border border\"\n : \"bg-muted hover:bg-muted/80 border border-transparent\",\n )}\n >\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"text-foreground text-sm font-medium\">\n {address.name}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n {formatLine1(address)}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n {formatCityStateZip(address)}\n </span>\n {address.phone && (\n <span className=\"text-muted-foreground text-sm\">\n {address.phone}\n </span>\n )}\n </div>\n <div className=\"flex shrink-0 flex-row items-center gap-2\">\n {address.default && (\n <span className=\"bg-primary text-primary-foreground rounded px-2 py-0.5 text-xs font-medium\">\n {t(\"default\")}\n </span>\n )}\n {(onEditAddress ||\n onDeleteAddress ||\n onMakeDefaultAddress) && (\n <span\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <EllipsesDropdown\n presentation={presentation}\n onEdit={\n onEditAddress\n ? () => onEditAddress(address)\n : undefined\n }\n onDelete={\n onDeleteAddress\n ? () => onDeleteAddress(address)\n : undefined\n }\n onMakeDefault={\n !address.default && onMakeDefaultAddress\n ? () => onMakeDefaultAddress(address)\n : undefined\n }\n />\n </span>\n )}\n </div>\n </div>\n );\n })\n )}\n </div>\n )}\n\n {showAddButton && (\n <button\n type=\"button\"\n disabled={isPending}\n className=\"text-foreground mt-3 text-left text-sm disabled:cursor-not-allowed disabled:opacity-60\"\n onClick={onAddAddressClick}\n >\n {addAddressLabel}\n </button>\n )}\n </div>\n );\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type JSX,\n} from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport {\n FluidPayCoreProvider,\n type fluidPay,\n type State,\n} from \"@fluid-app/fluid-pay-core\";\nimport { AddressFormDialog, ConfirmActionDialog } from \"@fluid-app/profile-ui\";\nimport { useActiveLocale } from \"@fluid-app/i18n/locale-context\";\nimport { useProfileTranslation } from \"@fluid-app/profile-core/translation-api-context\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { useUpdateSubscriptionInfo } from \"@fluid-app/subscriptions-core\";\nimport type { ShippingAddressSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport type { PayAddress } from \"@fluid-app/portal-core/pay-types\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { useCountriesApi } from \"@fluid-app/store-core/countries-api-context\";\nimport { payKeys, storeKeys } from \"../account/query-keys\";\nimport { createFluidPayApiAdapter } from \"../adapters/fluid-pay-api-adapter\";\nimport { useFluidContext } from \"../providers/FluidProvider\";\nimport { ProfileTranslationBridge } from \"../providers/ProfileTranslationBridge\";\nimport { SelectableAddressDropdown } from \"./SelectableAddressDropdown\";\nimport { isCurrentSubscriptionPaymentAttempt } from \"./subscription-payment-recovery\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n phone: raw.phone,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\n// Fall back when the customer's saved-address list doesn't contain the\n// subscription's current address (initial load before fetch, or address\n// removed in another session). Without this the collapsed accordion\n// header would render blank.\n//\n// `id` may be null when the BE serves the snapshot rather than the live\n// row; this fallback is display-only (identity comparisons use the\n// addressId prop instead), so 0 is a safe sentinel matching the\n// `addressId ?? 0` pattern elsewhere in this component.\nfunction subscriptionAddressToFluidPay(\n raw: ShippingAddressSlotContext[\"address\"],\n): fluidPay.CustomerAddress | null {\n if (!raw) return null;\n return {\n id: raw.id ?? 0,\n address1: raw.address1,\n address2: raw.address2,\n city: raw.city,\n country_code: raw.country_code,\n default: raw.default,\n name: raw.name,\n postal_code: raw.postal_code,\n phone: raw.phone ?? null,\n state: raw.state,\n subdivision_code: raw.subdivision_code,\n };\n}\n\ntype ShippingAddressSectionProps = ShippingAddressSlotContext & {\n // `severity` is omitted for normal success and set to \"warning\" when the\n // backend deduped an address create (existing record returned). Callers that\n // ignore the second argument default to a success toast.\n onSuccess?: (message: string, severity?: \"success\" | \"warning\") => void;\n onError?: (message: string, error: unknown) => void;\n};\n\nexport function PortalSubscriptionShippingAddressSection(\n props: ShippingAddressSectionProps,\n): JSX.Element {\n return (\n <ProfileTranslationBridge>\n <PortalSubscriptionShippingAddressSectionInner {...props} />\n </ProfileTranslationBridge>\n );\n}\n\nfunction PortalSubscriptionShippingAddressSectionInner({\n addressId,\n address: currentAddress,\n subscriptionToken,\n disabled,\n onSuccess,\n onError,\n}: ShippingAddressSectionProps): JSX.Element {\n const { isMobile } = useSidebar();\n const { t: profileT } = useProfileTranslation();\n const { t: subsT } = useSubscriptionsTranslation();\n const { config } = useFluidContext();\n const { locale } = useActiveLocale();\n const latestSubscriptionTokenRef = useRef(subscriptionToken);\n latestSubscriptionTokenRef.current = subscriptionToken;\n const isCurrentAddressAttempt = (attemptSubscriptionToken: string) =>\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n attemptSubscriptionToken,\n );\n\n // Bridge for fluid-pay-ui dialogs that accept `t: (key: string) => string`.\n // The underlying adapter falls back to `key` for unknown keys, so widening\n // the key type is safe at runtime.\n const tFn = useCallback(\n (key: string): string => profileT(key as never),\n [profileT],\n );\n\n const payApi = usePayApi();\n const queryClient = useQueryClient();\n const fluidPayShim = useMemo(\n () => createFluidPayApiAdapter(payApi),\n [payApi],\n );\n\n const [isFormDialogOpen, setIsFormDialogOpen] = useState(false);\n const [editingAddress, setEditingAddress] =\n useState<fluidPay.CustomerAddress | null>(null);\n const [deletingAddress, setDeletingAddress] =\n useState<fluidPay.CustomerAddress | null>(null);\n const [deleteError, setDeleteError] = useState<string | undefined>(undefined);\n const previousDialogSubscriptionTokenRef = useRef(subscriptionToken);\n\n useEffect(() => {\n if (previousDialogSubscriptionTokenRef.current === subscriptionToken) {\n return;\n }\n\n previousDialogSubscriptionTokenRef.current = subscriptionToken;\n setIsFormDialogOpen(false);\n setEditingAddress(null);\n setDeletingAddress(null);\n setDeleteError(undefined);\n }, [subscriptionToken]);\n\n const { data: addresses = [], isLoading } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n });\n\n const countriesApi = useCountriesApi();\n const { data: countriesData } = useQuery({\n queryKey: storeKeys.countries(locale),\n queryFn: () => countriesApi.listCountries({ languageIso: locale }),\n enabled: isFormDialogOpen,\n });\n const countryOptions = useMemo(\n () =>\n [...(countriesData?.countries ?? [])]\n .map((c) => ({ iso: c.code, name: c.name }))\n .sort((a, b) => a.name.localeCompare(b.name)),\n [countriesData],\n );\n const statesByCountry = useMemo(() => {\n const map = new Map<string, State[]>();\n for (const c of countriesData?.countries ?? []) {\n map.set(\n c.code,\n c.states.map((s) => ({ name: s.name, isoCode: s.code })),\n );\n }\n return map;\n }, [countriesData]);\n const fetchStatesFromCountries = useCallback(\n (countryCode: string): Promise<State[]> =>\n Promise.resolve(statesByCountry.get(countryCode) ?? []),\n [statesByCountry],\n );\n\n const updateSubscription = useUpdateSubscriptionInfo({\n onSuccess: ({ subscriptionToken: updatedSubscriptionToken }) => {\n if (latestSubscriptionTokenRef.current !== updatedSubscriptionToken) {\n return;\n }\n onSuccess?.(profileT(\"shipping_address_updated\"));\n },\n onError: (err, { subscriptionToken: failedSubscriptionToken }) => {\n if (latestSubscriptionTokenRef.current === failedSubscriptionToken) {\n onError?.(profileT(\"failed_to_update_shipping_address\"), err);\n }\n },\n });\n\n const createAddressMutation = useMutation({\n // Detect a server-side dedupe (POST /api/pay/addresses returns the existing\n // record when an identical address already exists, ignoring `name`). Snapshot\n // the current id set before the request and compare against the returned id.\n mutationFn: async ({\n body,\n }: {\n subscriptionToken: string;\n body: fluidPay.CreateAddressBody;\n }) => {\n const existingIds = new Set(addresses.map((a) => a.id));\n const address = await payApi.createAddress({\n address: {\n name: body.address.name,\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n phone: body.address.phone,\n default: body.address.default,\n },\n });\n return { address, deduped: existingIds.has(address.id) };\n },\n onSuccess: ({ deduped }, { subscriptionToken }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (!isCurrentAddressAttempt(subscriptionToken)) return;\n if (deduped) {\n onSuccess?.(profileT(\"address_already_exists\"), \"warning\");\n } else {\n onSuccess?.(profileT(\"address_created\"), \"success\");\n }\n },\n onError: (err, { subscriptionToken }) => {\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onError?.(profileT(\"failed_to_create_address\"), err);\n }\n },\n });\n\n const updateAddressMutation = useMutation({\n mutationFn: ({\n addressId,\n body,\n }: {\n subscriptionToken: string;\n addressId: number;\n body: fluidPay.CreateAddressBody;\n }) =>\n payApi.updateAddress(addressId, {\n address: {\n name: body.address.name,\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n phone: body.address.phone,\n default: body.address.default,\n },\n }),\n onSuccess: (_address, { subscriptionToken }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onSuccess?.(profileT(\"address_updated\"));\n }\n },\n onError: (err, { subscriptionToken }) => {\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onError?.(profileT(\"failed_to_update_address\"), err);\n }\n },\n });\n\n const deleteAddressMutation = useMutation({\n mutationFn: ({\n addressId,\n }: {\n subscriptionToken: string;\n addressId: number;\n }) => payApi.deleteAddress(addressId),\n onSuccess: (_address, { subscriptionToken }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onSuccess?.(profileT(\"address_deleted\"));\n }\n },\n });\n\n const makeDefaultAddressMutation = useMutation({\n mutationFn: ({\n address,\n }: {\n subscriptionToken: string;\n address: fluidPay.CustomerAddress;\n }) =>\n payApi.updateAddress(address.id, {\n address: {\n name: address.name ?? null,\n street1: address.address1 ?? \"\",\n street2: address.address2,\n city: address.city ?? \"\",\n state: address.state ?? \"\",\n zip: address.postal_code ?? \"\",\n country: address.country_code ?? \"\",\n phone: address.phone,\n default: true,\n },\n }),\n onSuccess: (_address, { subscriptionToken }) => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onSuccess?.(profileT(\"default_address_updated\"));\n }\n },\n onError: (err, { subscriptionToken }) => {\n if (isCurrentAddressAttempt(subscriptionToken)) {\n onError?.(profileT(\"failed_to_update_default_address\"), err);\n }\n },\n });\n\n // Match against the stable FK (addressId), not currentAddress.id — the\n // latter is null when the subscription resolved through the snapshot path.\n // Fall back to content matching when subscription and pay address ID spaces\n // differ so omitted fields such as `phone` still come from the saved record.\n const displayed =\n (addressId !== null\n ? addresses.find((a) => a.id === addressId)\n : undefined) ??\n (currentAddress\n ? addresses.find(\n (a) =>\n a.address1 === currentAddress.address1 &&\n a.postal_code === currentAddress.postal_code &&\n a.city === currentAddress.city,\n )\n : undefined) ??\n subscriptionAddressToFluidPay(currentAddress);\n\n const handleCloseFormDialog = () => {\n setIsFormDialogOpen(false);\n setEditingAddress(null);\n };\n\n const handleConfirmDelete = async () => {\n if (!deletingAddress) return;\n const initiatedSubscriptionToken = subscriptionToken;\n setDeleteError(undefined);\n try {\n await deleteAddressMutation.mutateAsync({\n subscriptionToken: initiatedSubscriptionToken,\n addressId: deletingAddress.id,\n });\n if (isCurrentAddressAttempt(initiatedSubscriptionToken)) {\n setDeletingAddress(null);\n }\n } catch (err) {\n if (isCurrentAddressAttempt(initiatedSubscriptionToken)) {\n setDeleteError(\n err instanceof Error\n ? err.message\n : profileT(\"unable_to_delete_address\"),\n );\n }\n }\n };\n\n return (\n <FluidPayCoreProvider api={fluidPayShim}>\n <SelectableAddressDropdown\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={subsT(\"shipping_address\")}\n displayAddress={displayed}\n addressList={addresses}\n selectedAddressId={addressId ?? 0}\n onSelectAddress={(addr) => {\n if (addr.id === addressId) return;\n updateSubscription.mutate({\n subscriptionToken,\n body: { address_id: addr.id },\n });\n }}\n onAddAddressClick={() => {\n setEditingAddress(null);\n setIsFormDialogOpen(true);\n }}\n onEditAddress={\n disabled\n ? undefined\n : (addr) => {\n setEditingAddress(addr);\n setIsFormDialogOpen(true);\n }\n }\n onDeleteAddress={\n disabled\n ? undefined\n : (addr) => {\n setDeleteError(undefined);\n setDeletingAddress(addr);\n }\n }\n onMakeDefaultAddress={\n disabled\n ? undefined\n : (addr) =>\n makeDefaultAddressMutation.mutate({\n subscriptionToken,\n address: addr,\n })\n }\n addAddressLabel={profileT(\"add_an_address_action\")}\n showAddButton={!disabled}\n isLoading={isLoading}\n isPending={\n disabled ||\n updateSubscription.isPending ||\n createAddressMutation.isPending ||\n updateAddressMutation.isPending ||\n deleteAddressMutation.isPending ||\n makeDefaultAddressMutation.isPending\n }\n />\n\n <AddressFormDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n isOpen={isFormDialogOpen}\n onClose={handleCloseFormDialog}\n selectedAddress={editingAddress}\n defaultCountry={\n addresses.find((a) => a.default)?.country_code ??\n currentAddress?.country_code ??\n config.countryIso ??\n \"US\"\n }\n languageIso={locale}\n t={tFn}\n onSubmit={async (data: fluidPay.CreateAddressBody) => {\n const initiatedSubscriptionToken = subscriptionToken;\n try {\n if (editingAddress) {\n await updateAddressMutation.mutateAsync({\n subscriptionToken: initiatedSubscriptionToken,\n addressId: editingAddress.id,\n body: data,\n });\n } else {\n await createAddressMutation.mutateAsync({\n subscriptionToken: initiatedSubscriptionToken,\n body: data,\n });\n }\n if (isCurrentAddressAttempt(initiatedSubscriptionToken)) {\n handleCloseFormDialog();\n }\n } catch {\n // onError surfaces the toast; swallow here so AddressFormDialog\n // doesn't see an unhandled rejection from its onSubmit handler.\n }\n }}\n isSubmitting={\n createAddressMutation.isPending || updateAddressMutation.isPending\n }\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n />\n\n <ConfirmActionDialog\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={profileT(\"delete_address\")}\n description={profileT(\"delete_address_message\")}\n actionText={profileT(\"delete\")}\n openDialog={deletingAddress !== null}\n setOpenDialog={(open) => {\n if (!open) {\n setDeletingAddress(null);\n setDeleteError(undefined);\n }\n }}\n onAction={handleConfirmDelete}\n errorMsg={deleteError}\n isLoading={deleteAddressMutation.isPending}\n />\n </FluidPayCoreProvider>\n );\n}\n","import { useRef } from \"react\";\nimport {\n useMutation,\n useQueryClient,\n type UseMutationResult,\n} from \"@tanstack/react-query\";\nimport { useAutoApplyPointsApi } from \"../auto-apply-points-api-context\";\nimport { subscriptionsKeys } from \"../query-keys\";\nimport type {\n AutoApplyPointsScope,\n AutoApplyPointsWriteResult,\n} from \"../auto-apply-points-api\";\nimport type { subscriptions } from \"../types\";\n\nexport type UpdateAutoApplyPointsVariables = {\n subscriptionToken: string;\n autoApplyPoints: boolean;\n scope: AutoApplyPointsScope;\n /**\n * Every token the caller believes belongs to this bundle at the moment it\n * fires the write, independent of what the server ends up resolving.\n * Never crosses the AutoApplyPointsApi port - mutationFn below forwards\n * only the three fields above. Purely client-side bookkeeping: a\n * subscription-scoped write reports only the target as resolved, but\n * every sibling's cached renewal_bundle embeds this subscription's\n * contribution to the aggregate auto_apply_points_state, so a sibling the\n * server never mentions can still be showing a stale aggregate. Also\n * widens writeInFlight below so a second write reaching a sibling that\n * isn't the target can still disable that sibling's own control.\n */\n bundleTokens?: string[];\n};\n\nexport type UpdateAutoApplyPointsOutcome = {\n result: AutoApplyPointsWriteResult;\n /**\n * Whether the refetched payload confirms the value that was written. False\n * means the write landed and the read did not, which the caller reports\n * differently from a clean success.\n */\n refreshed: boolean;\n variables: UpdateAutoApplyPointsVariables;\n};\n\n/**\n * Writes the points opt-in through the AutoApplyPointsApi port.\n *\n * The first four guarantees below came from useUpdateSubscriptionInfo, which\n * this replaces for the portal's control. Restated rather than inherited,\n * because invalidating the same keys does not reproduce them: the mutation\n * can settle while the switch still shows the old value, and the\n * partial-success path can vanish silently. The last two are specific to\n * this hook's bundle-aware writes, which useUpdateSubscriptionInfo never had\n * to consider.\n *\n * 1. Awaits the target detail refetch before leaving pending.\n * 2. Keeps the list invalidation, unconditionally on success.\n * 3. Retains the stale-token guard, scoped to the consumer callback only.\n * 4. Surfaces the partial outcome via `refreshed: false`.\n * 5. Invalidates the union of the server's resolved tokens and the caller's\n * own `bundleTokens`, not the server's set alone -- a subscription-scoped\n * write only resolves its target, but every sibling's cached bundle\n * aggregate still shifts.\n * 6. Never lets a stalled sibling invalidation hold up the target's own\n * awaited refetch.\n */\nexport function useUpdateAutoApplyPoints({\n currentSubscriptionToken,\n onSuccess,\n onError,\n}: {\n /**\n * The token on screen right now. A response for anything else is discarded,\n * so an outcome never lands on a sibling the customer navigated to.\n */\n currentSubscriptionToken?: string;\n onSuccess?: (outcome: UpdateAutoApplyPointsOutcome) => void;\n onError?: (error: unknown, variables: UpdateAutoApplyPointsVariables) => void;\n} = {}): UseMutationResult<\n AutoApplyPointsWriteResult,\n unknown,\n UpdateAutoApplyPointsVariables\n> {\n const api = useAutoApplyPointsApi();\n const queryClient = useQueryClient();\n\n // A ref rather than the prop directly: the callbacks below close over the\n // render in which the mutation started, so reading the prop would compare\n // against a stale token.\n const latestTokenRef = useRef(currentSubscriptionToken);\n latestTokenRef.current = currentSubscriptionToken;\n\n return useMutation({\n mutationFn: ({\n subscriptionToken,\n autoApplyPoints,\n scope,\n }: UpdateAutoApplyPointsVariables) =>\n api.updateAutoApplyPoints({ subscriptionToken, autoApplyPoints, scope }),\n onSuccess: async (result, variables) => {\n // Cache work runs unconditionally, regardless of which subscription is\n // on screen right now: the write already landed, so skipping the\n // refresh would leave the cache wrong with nothing left to correct it.\n // A customer who navigates away mid-write and back within the\n // library's staleTime window would otherwise see the pre-write value.\n // Only the consumer-facing callback below is guarded.\n\n // Every sibling the write could have moved: what the server actually\n // resolved, unioned with what the caller already knew was in the\n // bundle when it fired (bundleTokens). The union matters because a\n // subscription-scoped write reports only the target as resolved, yet\n // every other member's cached renewal_bundle still embeds this\n // subscription's contribution to the aggregate auto_apply_points_state\n // -- a sibling the server never mentions can still be showing a stale\n // aggregate. The target itself is excluded: it gets the explicit,\n // awaited refetch below rather than an invalidate, and\n // invalidateQueries internally calls refetchQueries on the same\n // instance, so leaving it in this set would race a second,\n // unawaited refetch against the one awaited next.\n const siblingTokens = [\n ...new Set([\n ...result.resolvedSubscriptionTokens,\n ...(variables.bundleTokens ?? []),\n ]),\n ].filter((token) => token !== variables.subscriptionToken);\n\n // Not awaited: the target refetch just below is the one thing the\n // caller is actually waiting on, and an actively-observed sibling GET\n // that hangs must not hold that up. Each invalidation swallows its own\n // rejection so a failed sibling fetch can't surface as an unhandled\n // rejection now that nothing awaits this Promise.all.\n void Promise.all(\n siblingTokens.map((token) =>\n queryClient\n .invalidateQueries({\n queryKey: subscriptionsKeys.detail(token),\n exact: true,\n })\n .catch(() => {}),\n ),\n );\n\n // Bare prefixes, not the parameterized list()/infiniteList() calls:\n // those are genuine wildcards, matching every cached query under them.\n // list() with no arguments carries an `undefined` params slot, which\n // never matches a real cached query (every caller passes concrete\n // params), so it silently invalidates nothing.\n queryClient.invalidateQueries({ queryKey: subscriptionsKeys.lists });\n queryClient.invalidateQueries({\n queryKey: subscriptionsKeys.infiniteLists,\n });\n\n // Awaited on purpose: leaving pending before the server's answer is in\n // hand would report success next to a control still showing the old\n // value. `exact` matters, since key filters match by prefix and the\n // failed-cycle-waiver key is a child of detail(token).\n await queryClient.refetchQueries({\n queryKey: subscriptionsKeys.detail(variables.subscriptionToken),\n exact: true,\n });\n\n // Guards only the outcome reported to the caller: a response that\n // settles after the screen moved to a sibling must not land there.\n if (\n latestTokenRef.current &&\n latestTokenRef.current !== variables.subscriptionToken\n ) {\n return;\n }\n\n const refreshedDetail =\n queryClient.getQueryData<subscriptions.SubscriptionDetail>(\n subscriptionsKeys.detail(variables.subscriptionToken),\n );\n\n onSuccess?.({\n result,\n refreshed:\n refreshedDetail?.subscription.auto_apply_points ===\n variables.autoApplyPoints,\n variables,\n });\n },\n onError: (error, variables) => {\n if (\n latestTokenRef.current &&\n latestTokenRef.current !== variables.subscriptionToken\n ) {\n return;\n }\n onError?.(error, variables);\n },\n });\n}\n","import type { AutoApplyPointsSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport type {\n subscriptions,\n AutoApplyPointsScope,\n} from \"@fluid-app/subscriptions-core\";\n\nexport interface AutoApplyPointsControlState {\n /** Whether the control belongs on this subscription at all. */\n visible: boolean;\n checked: boolean;\n disabled: boolean;\n}\n\n/**\n * Resolve what the auto-apply-points switch shows, from server state alone.\n *\n * Three rules, each written against a specific way this can go wrong:\n *\n * - A company that does not run a points program never sees the control. An\n * absent `pointsEnabled` counts as off rather than on: the field is\n * additive, so an older payload, or a read path that quietly drops it,\n * must hide a setting that could not act instead of offering it.\n * - `checked` comes from the payload and never from a default. Defaulting to\n * off would render the switch unset while the server held the customer's\n * opt-in, which reads as \"their choice was lost\".\n * - An in-flight write disables the control and leaves it showing the last\n * value the server confirmed. Because there is no optimistic state, a\n * failed write has nothing to roll back and cannot leave the switch\n * misreporting what is stored.\n */\nexport function autoApplyPointsControlState(input: {\n autoApplyPoints: AutoApplyPointsSlotContext[\"autoApplyPoints\"];\n pointsEnabled: AutoApplyPointsSlotContext[\"pointsEnabled\"];\n subscriptionDisabled: boolean;\n writeInFlight: boolean;\n}): AutoApplyPointsControlState {\n return {\n visible: input.pointsEnabled === true,\n checked: input.autoApplyPoints === true,\n disabled: input.subscriptionDisabled || input.writeInFlight,\n };\n}\n\n/** Which write path a toggle should take. */\nexport type AutoApplyPointsWriteRoute = \"fallback\" | \"write\" | \"confirm\";\n\n/**\n * Decide how a toggle is written, from the payload alone.\n *\n * Three rules, each against a specific way this can go wrong:\n *\n * - No renewal bundle means the server did not populate it, so the\n * bundle-aware port cannot be used: it requires a scope and both token\n * arrays, and such a server sends neither. The shared write handles it.\n * - One member, or none, is not a group. Asking a customer to confirm a\n * fan-out that reaches nothing but the subscription in front of them is a\n * dialog with no decision in it.\n * - More than one member means the write reaches subscriptions the customer\n * is not looking at, so they are asked first.\n *\n * Returns \"fallback\", \"write\" or \"confirm\".\n */\nexport function autoApplyPointsWriteRoute(input: {\n renewalBundle?: subscriptions.SubscriptionRenewalBundle | null;\n}): AutoApplyPointsWriteRoute {\n if (!input.renewalBundle) return \"fallback\";\n\n return input.renewalBundle.members.length > 1 ? \"confirm\" : \"write\";\n}\n\n/**\n * Whether the server resolved a different set than the customer agreed to.\n *\n * The expected set is scope-specific, and that is the whole point. After\n * \"Just this one\" the server deliberately returns the target alone while the\n * dialog rendered every member, so comparing the response against the\n * rendered set would report drift on the most common path. The comparison is\n * order-insensitive because neither side promises an order.\n *\n * Returns true when the customer should be told the group changed.\n */\nexport function autoApplyPointsMembershipDrifted(input: {\n confirmedScope: AutoApplyPointsScope;\n renderedTokens: string[];\n targetToken: string;\n resolvedTokens: string[];\n}): boolean {\n const expected =\n input.confirmedScope === \"bundle\"\n ? input.renderedTokens\n : [input.targetToken];\n\n return (\n [...input.resolvedTokens].sort().join(\"\\u0000\") !==\n [...expected].sort().join(\"\\u0000\")\n );\n}\n","import type { JSX } from \"react\";\nimport { Button, DialogFooter } from \"@fluid-app/ui-primitives\";\nimport { ResponsiveDialog } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\n\n/**\n * Asks whether a points opt-in applies to the whole renewal group.\n *\n * Names every member, because the customer is agreeing to a change on\n * subscriptions other than the one on screen. Paused members are named and\n * labelled: they bill, so they are affected. Built on ResponsiveDialog, the\n * same primitive PortalReactivateSubscriptionDialog uses one file over, so\n * this gets a focus trap, escape-to-close and backdrop dismissal for free\n * rather than reimplementing dialog semantics by hand.\n */\nexport function BundleFanOutDialog({\n bundle,\n pointsLabel,\n nextValue,\n onConfirmAll,\n onConfirmOne,\n onCancel,\n}: {\n bundle: subscriptions.SubscriptionRenewalBundle;\n pointsLabel: string;\n /**\n * The value the switch is being set to. The title and the \"Apply to all\"\n * button read as an instruction to turn the setting on, which is backwards\n * when the customer just turned an enabled subscription off -- this picks\n * the matching copy so the confirmation describes what the button\n * actually does.\n */\n nextValue: boolean;\n onConfirmAll: () => void;\n onConfirmOne: () => void;\n onCancel: () => void;\n}): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const { isMobile } = useSidebar();\n\n return (\n <ResponsiveDialog\n open\n onOpenChange={(next) => {\n if (!next) onCancel();\n }}\n title={t(\n nextValue\n ? \"auto_apply_points_bundle_title\"\n : \"auto_apply_points_bundle_title_off\",\n { label: pointsLabel },\n )}\n description={t(\"auto_apply_points_bundle_body\")}\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n >\n <ul className=\"space-y-1 text-sm\">\n {bundle.members.map((bundleMember) => (\n <li key={bundleMember.subscription_token} className=\"text-foreground\">\n {bundleMember.status === \"paused\"\n ? t(\"auto_apply_points_bundle_member_paused\", {\n name: bundleMember.label,\n })\n : bundleMember.label}\n </li>\n ))}\n </ul>\n <DialogFooter>\n <Button\n type=\"button\"\n className=\"bg-muted text-foreground ring-border hover:bg-muted/80 h-10 min-w-[70px] rounded p-3 ring-1\"\n onClick={onCancel}\n >\n {t(\"auto_apply_points_bundle_cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"bg-muted text-foreground ring-border hover:bg-muted/80 h-10 min-w-[70px] rounded p-3 ring-1\"\n onClick={onConfirmOne}\n >\n {t(\"auto_apply_points_bundle_confirm_one\")}\n </Button>\n <Button\n type=\"button\"\n className=\"bg-primary text-primary-foreground h-10 min-w-[70px] rounded p-3 hover:opacity-90\"\n onClick={onConfirmAll}\n >\n {t(\n nextValue\n ? \"auto_apply_points_bundle_confirm_all\"\n : \"auto_apply_points_bundle_confirm_all_off\",\n )}\n </Button>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import { useId, useRef, useState, type JSX } from \"react\";\nimport { useIsFetching, useQueryClient } from \"@tanstack/react-query\";\nimport { Switch } from \"@fluid-app/ui-primitives\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport {\n subscriptionsKeys,\n useUpdateSubscriptionInfo,\n BundleMembershipConflictError,\n type subscriptions,\n type AutoApplyPointsScope,\n} from \"@fluid-app/subscriptions-core\";\nimport { useUpdateAutoApplyPoints } from \"@fluid-app/subscriptions-core/hooks\";\nimport type { AutoApplyPointsSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport { useOptionalStore } from \"@fluid-app/portal-react/hooks/use-optional-store\";\nimport {\n autoApplyPointsControlState,\n autoApplyPointsWriteRoute,\n autoApplyPointsMembershipDrifted,\n} from \"./subscription-auto-apply-points\";\nimport { isCurrentSubscriptionPaymentAttempt } from \"./subscription-payment-recovery\";\nimport { BundleFanOutDialog } from \"./BundleFanOutDialog\";\n\ntype AutoApplyPointsSectionProps = AutoApplyPointsSlotContext & {\n // `severity` is \"warning\" when the write landed but the refreshed payload\n // did not come back, matching how the shipping section reports a partial\n // outcome. Callers that ignore it default to a success toast.\n onSuccess?: (message: string, severity?: \"success\" | \"warning\") => void;\n // Optional: the bundle-conflict branch below has already fully translated\n // the failure into customer-facing copy, so it calls onError with nothing\n // else to append.\n onError?: (message: string, error?: unknown) => void;\n};\n\n/**\n * Lets a customer turn automatic points redemption on or off for one\n * subscription. The switch reads the stored choice from the payload and writes\n * through the subscription update the portal already owns, so an explicit\n * \"off\" is a real write rather than a locally remembered preference.\n */\nexport function PortalSubscriptionAutoApplyPointsSection({\n autoApplyPoints,\n pointsEnabled,\n subscriptionToken,\n disabled,\n renewalBundle,\n onSuccess,\n onError,\n}: AutoApplyPointsSectionProps): JSX.Element | null {\n const { t } = useSubscriptionsTranslation();\n const labelId = useId();\n const queryClient = useQueryClient();\n // Tolerates a host that mounts this screen without a StoreApiProvider, and\n // shares its cache entry with the profile screen's own store query.\n const { data: store } = useOptionalStore();\n const pointsLabel = store?.reward_points_label_plural || \"points\";\n\n // The detail screen can move to a sibling subscription while a write is\n // still open. Compare the settling write's token against the one on screen\n // now so a toast never lands on the wrong subscription.\n const latestSubscriptionTokenRef = useRef(subscriptionToken);\n latestSubscriptionTokenRef.current = subscriptionToken;\n\n // Set once the customer picks a value on a multi-member bundle, while the\n // fan-out dialog waits for \"Apply to all\" / \"Just this one\" / cancel.\n const [pendingValue, setPendingValue] = useState<boolean | null>(null);\n // Guards a confirm() call that lands after the dialog has already been\n // settled: two rapid clicks on the same button, or one on each button, can\n // both fire before React re-renders and removes them, since pendingValue\n // alone can't distinguish \"first click\" from \"second click racing it\" -\n // both read the same value from the same render. Reset whenever a fresh\n // dialog opens, in requestChange below.\n const confirmedRef = useRef(false);\n\n // Resets the dialog if the detail screen moves to a different subscription\n // while it is open. The section does not unmount across that move (see the\n // comment above), so without this a stale pendingValue would keep A's\n // dialog open, listing A's members, over B's underlying bundle - and a\n // confirm there would compare B's resolved set against A's renderedTokens.\n // Adjusted during rendering rather than in an effect: this reacts to a\n // prop change with a state reset, not a side effect, matching the house\n // rule against useEffect for syncing state.\n const [dialogSubscriptionToken, setDialogSubscriptionToken] =\n useState(subscriptionToken);\n if (subscriptionToken !== dialogSubscriptionToken) {\n setDialogSubscriptionToken(subscriptionToken);\n setPendingValue(null);\n confirmedRef.current = false;\n }\n\n const updateSubscription = useUpdateSubscriptionInfo({\n // Async on purpose: the hook returns this promise from its own onSuccess,\n // so awaiting the refreshed payload keeps the mutation pending until the\n // server's answer is in hand. Reporting success before then would put a\n // toast next to a control still showing the pre-write value.\n onSuccess: async ({\n subscriptionToken: updatedSubscriptionToken,\n body,\n }) => {\n if (\n !isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n updatedSubscriptionToken,\n )\n ) {\n return;\n }\n\n // Refetching an already-fetching query joins the in-flight request\n // rather than issuing a second one, so this does not double the round\n // trip the hook's own invalidation already started.\n await queryClient.refetchQueries({\n queryKey: subscriptionsKeys.detail(updatedSubscriptionToken),\n exact: true,\n });\n\n if (\n !isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n updatedSubscriptionToken,\n )\n ) {\n return;\n }\n\n const refreshed =\n queryClient.getQueryData<subscriptions.SubscriptionDetail>(\n subscriptionsKeys.detail(updatedSubscriptionToken),\n );\n\n // The write landed and the read did not, so the switch is about to show\n // a value the server no longer holds. Say that plainly instead of\n // claiming success next to a control that contradicts it. Same case and\n // same wording as the checkout's own auto-apply control.\n if (\n refreshed?.subscription.auto_apply_points !== body.auto_apply_points\n ) {\n onSuccess?.(\n t(\"auto_apply_points_saved_but_not_refreshed\", {\n label: pointsLabel,\n }),\n \"warning\",\n );\n return;\n }\n\n onSuccess?.(t(\"auto_apply_points_updated\", { label: pointsLabel }));\n },\n onError: (error, { subscriptionToken: failedSubscriptionToken }) => {\n if (\n isCurrentSubscriptionPaymentAttempt(\n latestSubscriptionTokenRef.current,\n failedSubscriptionToken,\n )\n ) {\n onError?.(\n t(\"failed_to_update_auto_apply_points\", { label: pointsLabel }),\n error,\n );\n }\n },\n });\n\n // Bundle-aware write for a renewal group of more than one member. The hook\n // already scopes its own consumer callbacks to the current subscription\n // token, so no isCurrentSubscriptionPaymentAttempt guard is needed here.\n const fanOut = useUpdateAutoApplyPoints({\n currentSubscriptionToken: subscriptionToken,\n onSuccess: ({ result, refreshed, variables }) => {\n if (\n autoApplyPointsMembershipDrifted({\n confirmedScope: variables.scope,\n // The set this write was fired with, not the ref. The ref tracks\n // whichever dialog opened most recently, so a write on A that\n // settles after the customer opened B's dialog and navigated back\n // to A would be judged against B's members and warn about a drift\n // that never happened. The variables travel with their own\n // mutation, so they cannot be overwritten by a later one.\n renderedTokens: variables.bundleTokens ?? [],\n targetToken: variables.subscriptionToken,\n resolvedTokens: result.resolvedSubscriptionTokens,\n })\n ) {\n onSuccess?.(\n t(\"auto_apply_points_bundle_membership_changed\"),\n \"warning\",\n );\n return;\n }\n if (!refreshed) {\n onSuccess?.(\n t(\"auto_apply_points_saved_but_not_refreshed\", {\n label: pointsLabel,\n }),\n \"warning\",\n );\n return;\n }\n onSuccess?.(t(\"auto_apply_points_updated\", { label: pointsLabel }));\n },\n onError: (error) => {\n if (error instanceof BundleMembershipConflictError) {\n // No second argument: this message is already fully translated\n // customer-facing copy, not raw error detail for the screen to\n // append.\n onError?.(t(\"auto_apply_points_bundle_conflict_retry\"));\n return;\n }\n onError?.(\n t(\"failed_to_update_auto_apply_points\", { label: pointsLabel }),\n error,\n );\n },\n });\n\n // The update hook invalidates the detail query without awaiting the refetch,\n // so the mutation stops being pending while the switch still holds the value\n // it had before the write. Counting that refetch as in-flight keeps the\n // switch disabled until the server's answer arrives, rather than briefly\n // offering a control that reports the old setting under a success toast.\n // `exact` matters: query-key filters match by prefix by default, and\n // subscriptionsKeys.failedCycleWaiver(token) is a child of detail(token).\n // Without it, a past-due subscription fetching its waiver preview would\n // disable this switch for a query that has nothing to do with points.\n const detailRefetching =\n useIsFetching({\n queryKey: subscriptionsKeys.detail(subscriptionToken),\n exact: true,\n }) > 0;\n\n const control = autoApplyPointsControlState({\n autoApplyPoints,\n pointsEnabled,\n subscriptionDisabled: disabled,\n // Scoped to the write's own subscription, matching\n // PortalSubscriptionPaymentMethodSection. The detail screen preserves this\n // mutation across a move to a sibling subscription, so an unscoped\n // isPending would disable B's switch for a request belonging to A. The\n // fanOut branch also checks bundleTokens, not just the target: a\n // bundle-scoped write in flight for A also writes B, so without this a\n // customer who navigates to B mid-write would find its switch enabled\n // and could fire a second, overlapping write that races the first --\n // whichever commits last silently wins, possibly undoing the customer's\n // more recent choice.\n writeInFlight:\n (updateSubscription.isPending &&\n updateSubscription.variables?.subscriptionToken ===\n subscriptionToken) ||\n (fanOut.isPending &&\n (fanOut.variables?.subscriptionToken === subscriptionToken ||\n fanOut.variables?.bundleTokens?.includes(subscriptionToken))) ||\n detailRefetching,\n });\n\n // Routes a toggle to the write it needs: the shared subscription update on\n // a server that sent no renewal bundle, a direct bundle-aware write when\n // the bundle has nothing else in it, or the fan-out dialog when the write\n // would reach subscriptions the customer isn't looking at.\n function requestChange(next: boolean): void {\n const route = autoApplyPointsWriteRoute({ renewalBundle });\n\n if (route === \"fallback\") {\n updateSubscription.mutate({\n subscriptionToken,\n body: { auto_apply_points: next },\n });\n return;\n }\n if (route === \"write\") {\n fanOut.mutate({\n subscriptionToken,\n autoApplyPoints: next,\n scope: \"subscription\",\n bundleTokens: [subscriptionToken],\n });\n return;\n }\n confirmedRef.current = false;\n setPendingValue(next);\n }\n\n // Settles the dialog: writes at the confirmed scope. confirmedRef is the\n // real guard against a second call racing the first - the dialog only\n // mounts while pendingValue is set, so a `pendingValue === null` check\n // alone can't tell \"first click\" from \"second click before the re-render\n // that removes the buttons\"; both would read the same pendingValue.\n function confirm(scope: AutoApplyPointsScope): void {\n if (confirmedRef.current) return;\n confirmedRef.current = true;\n\n const next = pendingValue;\n setPendingValue(null);\n if (next === null) return;\n\n // Read off the same `renewalBundle` the dialog rendered in this very\n // render, so the drift baseline is whatever the customer had on screen\n // when they clicked. A snapshot frozen at dialog-open would disagree\n // with the list they were looking at as soon as the detail refetched\n // mid-dialog, and drift would then fire against a set nobody saw.\n fanOut.mutate({\n subscriptionToken,\n autoApplyPoints: next,\n scope,\n bundleTokens:\n renewalBundle?.members.map((member) => member.subscription_token) ?? [],\n });\n }\n\n if (!control.visible) return null;\n\n return (\n <div className=\"border-border mb-6 border-b pb-4\">\n <div className=\"flex items-start justify-between gap-4\">\n <div>\n <p id={labelId} className=\"text-foreground text-sm font-medium\">\n {t(\"auto_apply_points_each_renewal\", { label: pointsLabel })}\n </p>\n <p className=\"text-muted-foreground mt-1 text-sm\">\n {t(\"auto_apply_points_partial_balance\")}\n </p>\n </div>\n <Switch\n aria-labelledby={labelId}\n checked={control.checked}\n disabled={control.disabled}\n onCheckedChange={requestChange}\n />\n </div>\n {pendingValue !== null && renewalBundle ? (\n <BundleFanOutDialog\n bundle={renewalBundle}\n pointsLabel={pointsLabel}\n nextValue={pendingValue}\n onConfirmAll={() => confirm(\"bundle\")}\n onConfirmOne={() => confirm(\"subscription\")}\n onCancel={() => setPendingValue(null)}\n />\n ) : null}\n </div>\n );\n}\n","import { useEffect, useMemo, useState, type JSX } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { Button, DialogFooter } from \"@fluid-app/ui-primitives\";\nimport { ResponsiveDialog } from \"@fluid-app/ui-components/components/ResponsiveDialog\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport type { fluidPay } from \"@fluid-app/fluid-pay-core\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport type { ReactivateDialogSlotContext } from \"@fluid-app/subscriptions-ui\";\nimport type { PayAddress } from \"@fluid-app/portal-core/pay-types\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { payKeys } from \"../account/query-keys\";\nimport { ProfileTranslationBridge } from \"../providers/ProfileTranslationBridge\";\nimport { SelectableAddressDropdown } from \"./SelectableAddressDropdown\";\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n phone: raw.phone,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\n/**\n * Portal reactivation dialog. Confirms the shipping address before a rep\n * reactivates a cancelled subscription so it can't silently ship to an\n * address the customer has since removed (CURRENT-2204). Passing no\n * address_id keeps the subscription's current address — used only when the\n * customer has no saved addresses to choose from.\n */\nexport function PortalReactivateSubscriptionDialog(\n props: ReactivateDialogSlotContext,\n): JSX.Element {\n return (\n <ProfileTranslationBridge>\n <PortalReactivateSubscriptionDialogInner {...props} />\n </ProfileTranslationBridge>\n );\n}\n\nfunction PortalReactivateSubscriptionDialogInner({\n open,\n onOpenChange,\n onConfirm,\n isLoading,\n isError,\n}: ReactivateDialogSlotContext): JSX.Element {\n const { t } = useSubscriptionsTranslation();\n const { isMobile } = useSidebar();\n const payApi = usePayApi();\n\n const { data: addresses = [], isLoading: addressesLoading } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n enabled: open,\n });\n\n const [selectedAddressId, setSelectedAddressId] = useState<number | null>(\n null,\n );\n\n // No pre-selection: reactivation must be an explicit address confirmation\n // (CURRENT-2204), so the rep picks an address before Reactivate enables.\n // Reset each time the dialog opens so a prior pick doesn't leak across opens.\n useEffect(() => {\n if (open) setSelectedAddressId(null);\n }, [open]);\n\n // Ignore a selection that is no longer in the list (e.g. removed by a\n // refetch while the dialog is open) so a stale address_id can't be sent.\n const effectiveAddressId =\n selectedAddressId != null &&\n addresses.some((a) => a.id === selectedAddressId)\n ? selectedAddressId\n : null;\n\n const displayAddress = useMemo(\n () => addresses.find((a) => a.id === effectiveAddressId) ?? null,\n [addresses, effectiveAddressId],\n );\n\n const addressesReady = !addressesLoading;\n const emptyBook = addressesReady && addresses.length === 0;\n const canSubmit = (effectiveAddressId != null || emptyBook) && !isLoading;\n\n const handleOpenChange = (next: boolean) => {\n if (!next) setSelectedAddressId(null);\n onOpenChange(next);\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={t(\"reactivate_subscription\")}\n description={t(\"reactivate_dialog_description\")}\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n >\n <div className=\"space-y-4\">\n {!emptyBook && (\n <div>\n <SelectableAddressDropdown\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n title={t(\"shipping_address\")}\n displayAddress={displayAddress}\n addressList={addresses}\n selectedAddressId={effectiveAddressId ?? 0}\n onSelectAddress={(addr) => setSelectedAddressId(addr.id)}\n onAddAddressClick={() => {}}\n showAddButton={false}\n isLoading={addressesLoading}\n isPending={isLoading}\n defaultOpen\n />\n {effectiveAddressId == null && (\n <p className=\"text-destructive mt-1 text-xs\">\n {t(\"reactivate_select_address\")}\n </p>\n )}\n </div>\n )}\n </div>\n\n {isError && (\n <p className=\"text-destructive text-left text-sm\">\n {t(\"failed_to_reactivate\")}\n </p>\n )}\n\n <DialogFooter>\n <div className=\"flex w-full flex-row justify-between gap-x-2\">\n <Button\n className=\"bg-muted text-foreground ring-border hover:bg-muted/80 h-10 min-w-[70px] rounded p-3 ring-1\"\n onClick={() => handleOpenChange(false)}\n >\n {t(\"cancel\")}\n </Button>\n <Button\n type=\"button\"\n className=\"bg-primary text-primary-foreground h-10 min-w-[70px] rounded p-3 hover:opacity-90 disabled:opacity-50\"\n onClick={() => onConfirm({ addressId: effectiveAddressId })}\n disabled={!canSubmit}\n >\n {isLoading ? (\n <div className=\"border-primary-foreground size-5 animate-spin rounded-full border-4 border-t-4 border-t-transparent\" />\n ) : (\n t(\"reactivate\")\n )}\n </Button>\n </div>\n </DialogFooter>\n </ResponsiveDialog>\n );\n}\n","import { useCallback, useState } from \"react\";\nimport { SubscriptionDetailScreen as SubscriptionDetailScreenContent } from \"@fluid-app/subscriptions-ui/screens/SubscriptionDetailScreen\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { useSidebar } from \"@fluid-app/portal-react/shell/sidebar\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\nimport { PortalSubscriptionPaymentMethodSection } from \"../subscriptions/PortalSubscriptionPaymentMethodSection\";\nimport { PortalSubscriptionShippingAddressSection } from \"../subscriptions/PortalSubscriptionShippingAddressSection\";\nimport { PortalSubscriptionAutoApplyPointsSection } from \"../subscriptions/PortalSubscriptionAutoApplyPointsSection\";\nimport { PortalReactivateSubscriptionDialog } from \"../subscriptions/PortalReactivateSubscriptionDialog\";\n\ninterface SubscriptionDetailScreenProps {\n token: string;\n onToast: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n}\n\nexport function SubscriptionDetailScreen({\n token,\n onToast,\n}: SubscriptionDetailScreenProps): React.JSX.Element {\n const { navigate } = useAppNavigation();\n const { t } = useSubscriptionsTranslation();\n const { isMobile } = useSidebar();\n // Lift the Add Payment Method dialog state so the past-due banner's\n // \"Update your card\" CTA and the in-section payment-method dropdown\n // open the same dialog. Without this, the banner would have to\n // duplicate the \"Add Payment Method\" mounting logic, or scroll\n // (which the subscriptions-ui fallback does for non-portal hosts).\n const [addPaymentDialogOpen, setAddPaymentDialogOpen] = useState(false);\n\n const handleNavigateToList = useCallback(\n () => navigate(\"subscriptions\"),\n [navigate],\n );\n\n const handleNavigateToSubscription = useCallback(\n (nextToken: string) => navigate(`subscriptions/${nextToken}`),\n [navigate],\n );\n\n const handleNotFound = useCallback(() => {\n onToast(t(\"subscription_not_found\"), \"warning\");\n navigate(\"subscriptions\");\n }, [onToast, navigate, t]);\n\n const handleError = useCallback(\n (err: unknown) => {\n const message = err instanceof Error ? err.message : t(\"error_occurred\");\n onToast(t(\"failed_to_load_subscription\", { message }), \"error\");\n },\n [onToast, t],\n );\n\n const handleSuccess = useCallback(\n (\n message: string,\n severity: \"success\" | \"error\" | \"warning\" = \"success\",\n ) => {\n onToast(message, severity);\n },\n [onToast],\n );\n\n const handleMutationError = useCallback(\n (message: string, err: unknown) => {\n const detail = err instanceof Error ? err.message : t(\"error_occurred\");\n onToast(`${message}: ${detail}`, \"error\");\n },\n [onToast, t],\n );\n\n return (\n <SubscriptionDetailScreenContent\n token={token}\n presentation={isMobile ? \"bottom-sheet\" : \"dialog\"}\n onNavigateToList={handleNavigateToList}\n onNavigateToSubscription={handleNavigateToSubscription}\n onNotFound={handleNotFound}\n onError={handleError}\n onSuccess={handleSuccess}\n onMutationError={handleMutationError}\n onUpdatePaymentClick={() => setAddPaymentDialogOpen(true)}\n renderPaymentMethod={(ctx) => (\n <PortalSubscriptionPaymentMethodSection\n {...ctx}\n onSuccess={(msg, severity) => onToast(msg, severity ?? \"success\")}\n onError={(msg, err) => {\n const detail =\n err instanceof Error ? err.message : t(\"error_occurred\");\n onToast(`${msg}: ${detail}`, \"error\");\n }}\n addDialogOpen={addPaymentDialogOpen}\n onAddDialogOpenChange={setAddPaymentDialogOpen}\n />\n )}\n renderShippingAddress={(ctx) => (\n <PortalSubscriptionShippingAddressSection\n {...ctx}\n onSuccess={(msg, severity) => onToast(msg, severity ?? \"success\")}\n onError={(msg, err) => {\n const detail =\n err instanceof Error ? err.message : t(\"error_occurred\");\n onToast(`${msg}: ${detail}`, \"error\");\n }}\n />\n )}\n renderAutoApplyPoints={(ctx) => (\n <PortalSubscriptionAutoApplyPointsSection\n {...ctx}\n onSuccess={(msg, severity) => onToast(msg, severity ?? \"success\")}\n onError={(msg, err) => {\n // Unlike the payment-method and shipping-address handlers above,\n // err can be genuinely absent here: the bundle-conflict path\n // calls onError with only the (already fully translated)\n // message, so appending a fallback string on top of it would\n // read as untranslated debug detail glued onto real copy.\n const detail = err instanceof Error ? err.message : undefined;\n onToast(detail ? `${msg}: ${detail}` : msg, \"error\");\n }}\n />\n )}\n renderReactivateDialog={(ctx) => (\n <PortalReactivateSubscriptionDialog {...ctx} />\n )}\n />\n );\n}\n","import type { ComponentProps } from \"react\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n PaddingOptions,\n} from \"../types\";\nimport type { WidgetPropertySchema } from \"../registries/property-schema-types\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\nimport { useAccount } from \"../hooks/use-account\";\nimport { PortalSubscriptionsApiProvider } from \"../subscriptions/PortalSubscriptionsApiProvider\";\nimport { PortalBundlesApiProvider } from \"../subscriptions/PortalBundlesApiProvider\";\nimport { useSubscriptionsTranslation } from \"@fluid-app/subscriptions-core/translation-api-context\";\nimport { SubscriptionsTranslationBridge } from \"../providers/SubscriptionsTranslationBridge\";\nimport { SubscriptionsListScreen } from \"./SubscriptionsListScreen\";\nimport { SubscriptionDetailScreen } from \"./SubscriptionDetailScreen\";\n\nfunction AccountErrorFallback(): React.JSX.Element {\n const { t } = useSubscriptionsTranslation();\n return (\n <div className=\"text-muted-foreground px-4 py-8 text-center text-sm\">\n {t(\"account_load_error\")}\n </div>\n );\n}\n\ntype SubscriptionsScreenProps = ComponentProps<\"div\"> & {\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n onToast?: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n};\n\nfunction defaultToast(message: string, type: \"success\" | \"error\" | \"warning\") {\n fluidToast({ title: message, type });\n}\n\nexport function SubscriptionsScreen({\n onToast,\n /* eslint-disable @typescript-eslint/no-unused-vars -- destructured to exclude from divProps spread */\n background,\n textColor,\n accentColor,\n padding,\n borderRadius,\n /* eslint-enable @typescript-eslint/no-unused-vars */\n ...divProps\n}: SubscriptionsScreenProps): React.JSX.Element {\n const { currentSlug } = useAppNavigation();\n const effectiveToast = onToast ?? defaultToast;\n\n // Parse slug: \"subscriptions\" → list, \"subscriptions/{token}\" → detail\n const detailToken = currentSlug.split(\"/\")[1];\n const isDetailView = detailToken !== undefined;\n\n const { data: account } = useAccount();\n const customerId = account?.id;\n const isLoadingCustomer = account === undefined;\n const isCustomerError = false;\n\n return (\n <div {...divProps}>\n <SubscriptionsTranslationBridge>\n <PortalSubscriptionsApiProvider>\n <PortalBundlesApiProvider>\n {isDetailView ? (\n <SubscriptionDetailScreen\n token={detailToken}\n onToast={effectiveToast}\n />\n ) : isCustomerError && !isLoadingCustomer ? (\n <AccountErrorFallback />\n ) : (\n <SubscriptionsListScreen\n customerId={customerId}\n isLoadingCustomer={isLoadingCustomer}\n onToast={effectiveToast}\n />\n )}\n </PortalBundlesApiProvider>\n </PortalSubscriptionsApiProvider>\n </SubscriptionsTranslationBridge>\n </div>\n );\n}\n\nexport const subscriptionsScreenPropertySchema: WidgetPropertySchema = {\n widgetType: \"SubscriptionsScreen\",\n displayName: \"Subscriptions Screen\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [],\n} as const satisfies WidgetPropertySchema;\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"mappings":"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"}
|