@fluid-app/portal-sdk 0.1.155 → 0.1.157

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.
Files changed (92) hide show
  1. package/dist/{ContactsScreen-Dy9coizh.cjs → ContactsScreen-BKQk5wU5.cjs} +2 -2
  2. package/dist/{ContactsScreen-Djvyn4Rq.cjs → ContactsScreen-Ck5NCh9d.cjs} +3 -3
  3. package/dist/{ContactsScreen-Djvyn4Rq.cjs.map → ContactsScreen-Ck5NCh9d.cjs.map} +1 -1
  4. package/dist/{ContactsScreen-BKT7Ohfe.mjs → ContactsScreen-CmnKU--w.mjs} +3 -3
  5. package/dist/{ContactsScreen-BKT7Ohfe.mjs.map → ContactsScreen-CmnKU--w.mjs.map} +1 -1
  6. package/dist/{FluidProvider-CRMe-Enf.cjs → FluidProvider-Bc-3uN7M.cjs} +151 -19
  7. package/dist/FluidProvider-Bc-3uN7M.cjs.map +1 -0
  8. package/dist/{FluidProvider-DpET43hN.mjs → FluidProvider-Cqf2kmUc.mjs} +137 -5
  9. package/dist/FluidProvider-Cqf2kmUc.mjs.map +1 -0
  10. package/dist/{MessagingScreen-DXgDrzlG.mjs → MessagingScreen-B1MbKdSO.mjs} +2 -2
  11. package/dist/{MessagingScreen-DXgDrzlG.mjs.map → MessagingScreen-B1MbKdSO.mjs.map} +1 -1
  12. package/dist/{MessagingScreen-cxQADd91.cjs → MessagingScreen-lAO4PVqi.cjs} +2 -2
  13. package/dist/{MessagingScreen-cxQADd91.cjs.map → MessagingScreen-lAO4PVqi.cjs.map} +1 -1
  14. package/dist/{MessagingScreen-ChCBVO4U.cjs → MessagingScreen-s9HaMQGR.cjs} +4 -3
  15. package/dist/{MySiteScreen-gl8KGOrU.mjs → MySiteScreen-BEbj9K8U.mjs} +262 -602
  16. package/dist/MySiteScreen-BEbj9K8U.mjs.map +1 -0
  17. package/dist/{MySiteScreen-CdsAyh7a.cjs → MySiteScreen-D8YvEYwH.cjs} +262 -611
  18. package/dist/MySiteScreen-D8YvEYwH.cjs.map +1 -0
  19. package/dist/{MySiteScreen-efkpTcUh.cjs → MySiteScreen-DIbwHNbV.cjs} +2 -1
  20. package/dist/{OrdersScreen-C0HGsjwv.mjs → OrdersScreen-CSbbQw2L.mjs} +2 -2
  21. package/dist/{OrdersScreen-C0HGsjwv.mjs.map → OrdersScreen-CSbbQw2L.mjs.map} +1 -1
  22. package/dist/{OrdersScreen-Dbmbf9g_.cjs → OrdersScreen-DLjDPnqI.cjs} +2 -2
  23. package/dist/{OrdersScreen-Dbmbf9g_.cjs.map → OrdersScreen-DLjDPnqI.cjs.map} +1 -1
  24. package/dist/{OrdersScreen-dNALJLm3.cjs → OrdersScreen-Dxv6ZQlu.cjs} +1 -1
  25. package/dist/{ProductsScreen-H-8HShV5.mjs → ProductsScreen-CcRQhx0c.mjs} +2 -2
  26. package/dist/{ProductsScreen-H-8HShV5.mjs.map → ProductsScreen-CcRQhx0c.mjs.map} +1 -1
  27. package/dist/{ProductsScreen-CfcVBUZ8.cjs → ProductsScreen-DTBg7Bm3.cjs} +2 -2
  28. package/dist/{ProductsScreen-CfcVBUZ8.cjs.map → ProductsScreen-DTBg7Bm3.cjs.map} +1 -1
  29. package/dist/{ProductsScreen-Dcnp0MG-.mjs → ProductsScreen-MADYD0MH.mjs} +5 -4
  30. package/dist/{ProductsScreen-BJ2ZUaPi.cjs → ProductsScreen-NmOdT82w.cjs} +5 -4
  31. package/dist/{ProfileScreen-CaNQYd_F.mjs → ProfileScreen-BcCYQt5U.mjs} +4 -4
  32. package/dist/{ProfileScreen-CaNQYd_F.mjs.map → ProfileScreen-BcCYQt5U.mjs.map} +1 -1
  33. package/dist/{ProfileScreen-BRPBvvI7.cjs → ProfileScreen-C01vRpm3.cjs} +4 -3
  34. package/dist/{ProfileScreen-D4OJk9F0.cjs → ProfileScreen-fmUckcMP.cjs} +4 -4
  35. package/dist/{ProfileScreen-D4OJk9F0.cjs.map → ProfileScreen-fmUckcMP.cjs.map} +1 -1
  36. package/dist/{ShareablesScreen-CL6A1m_P.cjs → ShareablesScreen-BMxugV_y.cjs} +5 -4
  37. package/dist/{ShareablesScreen-FDOtQ67f.mjs → ShareablesScreen-BkVWntLq.mjs} +5 -4
  38. package/dist/{ShareablesScreen-DLz5tvRS.cjs → ShareablesScreen-DmtFkpDO.cjs} +2 -2
  39. package/dist/{ShareablesScreen-DLz5tvRS.cjs.map → ShareablesScreen-DmtFkpDO.cjs.map} +1 -1
  40. package/dist/{ShareablesScreen-CtK4S7FT.mjs → ShareablesScreen-WW2uw8wV.mjs} +2 -2
  41. package/dist/{ShareablesScreen-CtK4S7FT.mjs.map → ShareablesScreen-WW2uw8wV.mjs.map} +1 -1
  42. package/dist/{ShopScreen-Bj3PjrVi.cjs → ShopScreen-BeBh8oUd.cjs} +3 -3
  43. package/dist/{ShopScreen-Bj3PjrVi.cjs.map → ShopScreen-BeBh8oUd.cjs.map} +1 -1
  44. package/dist/{ShopScreen-CKidhX9F.cjs → ShopScreen-D2DmHW7P.cjs} +4 -3
  45. package/dist/{ShopScreen-DDscuexZ.mjs → ShopScreen-DQDOi7Xn.mjs} +3 -3
  46. package/dist/{ShopScreen-DDscuexZ.mjs.map → ShopScreen-DQDOi7Xn.mjs.map} +1 -1
  47. package/dist/{SubscriptionsScreen-DHg2Y0Vk.cjs → SubscriptionsScreen-BBKc60-g.cjs} +1 -1
  48. package/dist/{SubscriptionsScreen-Cu9Fc98m.mjs → SubscriptionsScreen-Bh6hyLOm.mjs} +231 -9
  49. package/dist/SubscriptionsScreen-Bh6hyLOm.mjs.map +1 -0
  50. package/dist/{SubscriptionsScreen-RaocKuQG.cjs → SubscriptionsScreen-CwglxGt2.cjs} +231 -9
  51. package/dist/SubscriptionsScreen-CwglxGt2.cjs.map +1 -0
  52. package/dist/{countries-api-context-EEnpUpp2.cjs → countries-api-context-CwUkJTdy.cjs} +1 -1
  53. package/dist/{countries-api-context-EEnpUpp2.cjs.map → countries-api-context-CwUkJTdy.cjs.map} +1 -1
  54. package/dist/{countries-api-context-esV7AdsB.mjs → countries-api-context-D0dubtHy.mjs} +1 -1
  55. package/dist/{countries-api-context-esV7AdsB.mjs.map → countries-api-context-D0dubtHy.mjs.map} +1 -1
  56. package/dist/index.cjs +31 -30
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.cts.map +1 -1
  59. package/dist/index.d.mts.map +1 -1
  60. package/dist/index.mjs +31 -30
  61. package/dist/index.mjs.map +1 -1
  62. package/dist/mysite-api-context-BTt-_urb.cjs +25 -0
  63. package/dist/mysite-api-context-BTt-_urb.cjs.map +1 -0
  64. package/dist/mysite-api-context-C7eiw7TO.mjs +13 -0
  65. package/dist/mysite-api-context-C7eiw7TO.mjs.map +1 -0
  66. package/dist/{parse-api-errors-DLWVAkAd.mjs → parse-api-errors-D8PITFLg.mjs} +1 -1
  67. package/dist/{parse-api-errors-DLWVAkAd.mjs.map → parse-api-errors-D8PITFLg.mjs.map} +1 -1
  68. package/dist/{parse-api-errors-J6VflWm8.cjs → parse-api-errors-pw_TZf_b.cjs} +1 -1
  69. package/dist/{parse-api-errors-J6VflWm8.cjs.map → parse-api-errors-pw_TZf_b.cjs.map} +1 -1
  70. package/dist/{portal_tenant-DTIfG6m4.cjs → portal_tenant-CSxWYAH-.cjs} +1 -1
  71. package/dist/{portal_tenant-DTIfG6m4.cjs.map → portal_tenant-CSxWYAH-.cjs.map} +1 -1
  72. package/dist/{portal_tenant-S57LBMo6.mjs → portal_tenant-Taa7uJwV.mjs} +1 -1
  73. package/dist/{portal_tenant-S57LBMo6.mjs.map → portal_tenant-Taa7uJwV.mjs.map} +1 -1
  74. package/dist/{use-portal-products-client-DGYbhJLC.mjs → use-portal-products-client-CChGsvZI.mjs} +2 -2
  75. package/dist/{use-portal-products-client-DGYbhJLC.mjs.map → use-portal-products-client-CChGsvZI.mjs.map} +1 -1
  76. package/dist/{use-portal-products-client-CkehVVCL.cjs → use-portal-products-client-mpdZuZyu.cjs} +2 -2
  77. package/dist/{use-portal-products-client-CkehVVCL.cjs.map → use-portal-products-client-mpdZuZyu.cjs.map} +1 -1
  78. package/dist/{use-portal-shareables-api-BpQpcPcx.cjs → use-portal-shareables-api-CZ4ELYei.cjs} +3 -3
  79. package/dist/{use-portal-shareables-api-BpQpcPcx.cjs.map → use-portal-shareables-api-CZ4ELYei.cjs.map} +1 -1
  80. package/dist/{use-portal-shareables-api-kcUnux8J.mjs → use-portal-shareables-api-DXuaX66a.mjs} +3 -3
  81. package/dist/{use-portal-shareables-api-kcUnux8J.mjs.map → use-portal-shareables-api-DXuaX66a.mjs.map} +1 -1
  82. package/package.json +20 -20
  83. package/dist/FluidProvider-CRMe-Enf.cjs.map +0 -1
  84. package/dist/FluidProvider-DpET43hN.mjs.map +0 -1
  85. package/dist/MySiteScreen-CdsAyh7a.cjs.map +0 -1
  86. package/dist/MySiteScreen-gl8KGOrU.mjs.map +0 -1
  87. package/dist/SubscriptionsScreen-Cu9Fc98m.mjs.map +0 -1
  88. package/dist/SubscriptionsScreen-RaocKuQG.cjs.map +0 -1
  89. package/dist/portal_tenant_mysite-NSJTd8ff.mjs +0 -136
  90. package/dist/portal_tenant_mysite-NSJTd8ff.mjs.map +0 -1
  91. package/dist/portal_tenant_mysite-PDI1nxcm.cjs +0 -213
  92. package/dist/portal_tenant_mysite-PDI1nxcm.cjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"MySiteScreen-gl8KGOrU.mjs","names":["portalTenantMysite.mysite_profile_show","portalTenantMysite.mysite_themes_list","portalTenantMysite.mysite_links_list","portalTenantMysite.mysite_favorites_list","portalTenantMysite.mysite_links_create","portalTenantMysite.mysite_favorites_create","portalTenantMysite.mysite_profile_update","portalTenantMysite.mysite_settings_update","portalTenantMysite.mysite_links_update","portalTenantMysite.mysite_links_bulk_reorder","portalTenantMysite.mysite_favorites_bulk_reorder","portalTenantMysite.mysite_links_destroy","portalTenantMysite.mysite_favorites_destroy","updateMySiteApi","updateProfileApi","defaultToast"],"sources":["../src/mysite/create-portal-mysite-adapter.ts","../src/mysite/use-portal-mysite-client.ts","../../../mysite/ui/src/shared/query-keys.ts","../../../mysite/ui/src/shared/schemas/mysite.schema.ts","../../../mysite/ui/src/admin/networking/mysite.api.ts","../../../mysite/ui/src/shared/schemas/mysite-theme.schema.ts","../../../mysite/ui/src/admin/networking/mysite-theme.api.ts","../../../mysite/ui/src/admin/hooks/use-mysite.ts","../../../mysite/ui/src/portal/components/animation-utils.ts","../../../mysite/ui/src/portal/components/VisitorDetailsCard.tsx","../../../mysite/ui/src/portal/components/MySiteLinkCard.tsx","../../../mysite/ui/src/portal/components/PhonePreview.tsx","../../../mysite/ui/src/portal/components/ThemeEditor.tsx","../../../mysite/ui/src/shared/utils.ts","../../../mysite/ui/src/portal/components/ButtonsEditor.tsx","../../../mysite/ui/src/portal/components/FavoritesEditor.tsx","../../../mysite/ui/src/portal/components/MySiteProfileForm.tsx","../src/screens/MySiteScreen/MySiteMainView.tsx","../src/screens/MySiteScreen/MySiteProfileView.tsx","../src/screens/MySiteScreen/index.tsx"],"sourcesContent":["/**\n * Portal MySite Adapter — FetchClient that translates old mysite API calls\n * to the portal-tenant MySite BFF endpoints.\n *\n * The existing mysite-ui hooks and networking functions call endpoints like\n * `/me.json`, `/users/{id}/links.json`, `/mysite/themes`, etc. This adapter\n * intercepts those calls and routes them to the BFF at `/api/mysite/...`,\n * mapping request bodies and response shapes so the UI layer works unchanged.\n */\n\nimport type { FetchClient, RequestOptions } from \"@fluid-app/api-client-core\";\nimport { portalTenantMysite } from \"@fluid-app/portal-tenant-mysite-api-client\";\n\n// ---------------------------------------------------------------------------\n// Response mappers — BFF shapes → old API shapes\n// ---------------------------------------------------------------------------\n\n/**\n * BFF MySiteProfile → old /me.json MeProfile shape.\n * Fields not available in the BFF (views, leads, affiliate_id) are zeroed out.\n */\nfunction mapProfileToMe(\n profile: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n id: profile.id,\n affiliate_id: null,\n company: null,\n mysite_url: profile.mysite_url ?? null,\n mysite_views: 0,\n mysite_leads: 0,\n mysite_theme_id: profile.theme_id ?? null,\n mysite_theme: null,\n bio: profile.bio ?? null,\n // Social links not exposed by BFF — null them out\n facebook: null,\n instagram: null,\n twitter: null,\n youtube: null,\n pinterest: null,\n tiktok: null,\n linkedin: null,\n whatsapp: null,\n wechat: null,\n };\n}\n\n/** BFF Link → old MySiteLink shape (must pass Zod: { id, url, text, order, clicks? }) */\nfunction mapBffLink(link: Record<string, unknown>): Record<string, unknown> {\n return {\n id: link.id,\n url: link.url ?? \"\",\n text: link.title ?? \"\",\n order: link.position ?? 0,\n clicks: 0,\n };\n}\n\n/** BFF Favorite → old MySiteFavorite shape (must pass Zod favoriteSchema) */\nfunction mapBffFavorite(fav: Record<string, unknown>): Record<string, unknown> {\n return {\n id: fav.id,\n favoriteable_id: fav.product_id,\n favoriteable_type: \"Product\",\n order: fav.position ?? 0,\n user_company_id: undefined,\n created_at: fav.created_at,\n favoriteable: {\n id: fav.product_id,\n title: fav.product_name ?? null,\n name: fav.product_name ?? null,\n image_url: fav.product_image_url ?? null,\n type: \"Product\",\n },\n };\n}\n\n/** BFF Theme → old MysiteTheme shape (must pass Zod themeSchema) */\nfunction mapBffTheme(theme: Record<string, unknown>): Record<string, unknown> {\n const now = new Date().toISOString();\n return {\n id: theme.id,\n name: theme.name ?? \"Untitled\",\n description: null,\n public: true,\n company_id: null,\n created_at: now,\n updated_at: now,\n image_url: theme.preview_url ?? null,\n application_theme_template_id: null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// URL matchers\n// ---------------------------------------------------------------------------\n\nconst LINKS_LIST = /^\\/users\\/\\d+\\/links\\.json$/;\nconst LINK_SINGLE = /^\\/users\\/\\d+\\/links\\/(\\d+)\\.json$/;\nconst LINKS_REORDER = /^\\/users\\/\\d+\\/links\\/bulk_reorder\\.json$/;\n\nconst FAVORITES_LIST = /^\\/user_companies\\/\\d+\\/favorites\\.json$/;\nconst FAVORITE_SINGLE = /^\\/user_companies\\/\\d+\\/favorites\\/(\\d+)\\.json$/;\nconst FAVORITES_REORDER =\n /^\\/user_companies\\/\\d+\\/favorites\\/bulk_reorder\\.json$/;\n\n// ---------------------------------------------------------------------------\n// Adapter factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a FetchClient adapter that translates legacy mysite API calls\n * to portal-tenant MySite BFF endpoints.\n *\n * @param bffClient - A FetchClient pointed at the tenant BFF origin\n * (e.g. https://acme.portal.fluid.app, **without** /api suffix — the\n * generated namespace functions already include /api/mysite/... paths).\n */\nexport function createPortalMySiteAdapter(bffClient: FetchClient): FetchClient {\n // ----- GET -----\n async function get<T>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: Omit<RequestOptions, \"method\" | \"params\">,\n ): Promise<T> {\n // GET /me.json → profile\n if (endpoint === \"/me.json\") {\n const res = await portalTenantMysite.mysite_profile_show(bffClient);\n return mapProfileToMe(\n (res.profile ?? {}) as Record<string, unknown>,\n ) as T;\n }\n\n // GET /mysite/themes → themes list\n if (endpoint === \"/mysite/themes\") {\n const res = await portalTenantMysite.mysite_themes_list(bffClient);\n const themes = (res.themes ?? []) as Record<string, unknown>[];\n return themes.map(mapBffTheme) as T;\n }\n\n // GET /users/:id/links.json → links list\n if (LINKS_LIST.test(endpoint)) {\n const res = await portalTenantMysite.mysite_links_list(bffClient);\n const links = (res.links ?? []) as Record<string, unknown>[];\n return links.map(mapBffLink) as T;\n }\n\n // GET /user_companies/:id/favorites.json → favorites list\n if (FAVORITES_LIST.test(endpoint)) {\n const res = await portalTenantMysite.mysite_favorites_list(bffClient);\n const favs = (res.favorites ?? []) as Record<string, unknown>[];\n return favs.map(mapBffFavorite) as T;\n }\n\n // Fallthrough — pass to BFF client as-is\n return bffClient.get<T>(endpoint, params, options);\n }\n\n // ----- POST -----\n async function post<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ): Promise<T> {\n // POST /users/:id/links.json → create link\n if (LINKS_LIST.test(endpoint)) {\n const b = body as { url?: string; text?: string } | undefined;\n const res = await portalTenantMysite.mysite_links_create(bffClient, {\n link: { title: b?.text ?? \"\", url: b?.url ?? \"\" },\n });\n const link = (res.link ?? {}) as Record<string, unknown>;\n return mapBffLink(link) as T;\n }\n\n // POST /user_companies/:id/favorites.json → add favorite\n if (FAVORITES_LIST.test(endpoint)) {\n const b = body as\n | {\n favorite?: { favoriteable_id?: number };\n country_id?: number;\n }\n | undefined;\n const res = await portalTenantMysite.mysite_favorites_create(bffClient, {\n favorite: { product_id: b?.favorite?.favoriteable_id ?? 0 },\n });\n const fav = (res.favorite ?? {}) as Record<string, unknown>;\n return mapBffFavorite(fav) as T;\n }\n\n // Fallthrough\n return bffClient.post<T>(endpoint, body, options);\n }\n\n // ----- PUT -----\n async function put<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ): Promise<T> {\n // PUT /me.json → update profile\n if (endpoint === \"/me.json\") {\n const b = body as Record<string, unknown> | undefined;\n const res = await portalTenantMysite.mysite_profile_update(bffClient, {\n profile: {\n display_name: (b?.display_name as string) ?? undefined,\n bio: (b?.bio as string) ?? undefined,\n avatar_url:\n (b?.image_url as string) ?? (b?.avatar_url as string) ?? undefined,\n },\n });\n const profile = (res.profile ?? {}) as Record<string, unknown>;\n return mapProfileToMe(profile) as T;\n }\n\n // PUT /mysite.json → update settings (theme_id) or profile (username→slug)\n if (endpoint === \"/mysite.json\") {\n const b = body as\n | {\n user_company?: { theme_id?: number; username?: string };\n }\n | undefined;\n const uc = b?.user_company;\n if (uc?.theme_id !== undefined) {\n const res = await portalTenantMysite.mysite_settings_update(bffClient, {\n settings: { theme_id: uc.theme_id },\n });\n return { id: 0, ...(res.settings ?? {}) } as T;\n }\n if (uc?.username !== undefined) {\n const res = await portalTenantMysite.mysite_profile_update(bffClient, {\n profile: { slug: uc.username },\n });\n const profile = (res.profile ?? {}) as Record<string, unknown>;\n return { id: profile.id ?? 0, ...profile } as T;\n }\n return { id: 0 } as T;\n }\n\n // PUT /users/:id/links/:linkId.json → update link\n const linkMatch = endpoint.match(LINK_SINGLE);\n if (linkMatch) {\n const linkId = Number(linkMatch[1]);\n const b = body as { url?: string; text?: string } | undefined;\n const res = await portalTenantMysite.mysite_links_update(\n bffClient,\n linkId,\n { link: { title: b?.text, url: b?.url } },\n );\n const link = (res.link ?? {}) as Record<string, unknown>;\n return mapBffLink(link) as T;\n }\n\n // Fallthrough\n return bffClient.put<T>(endpoint, body, options);\n }\n\n // ----- PATCH -----\n async function patch<T>(\n endpoint: string,\n body?: unknown,\n options?: Omit<RequestOptions, \"method\" | \"body\">,\n ): Promise<T> {\n // PATCH /users/:id/links/bulk_reorder.json → reorder links\n if (LINKS_REORDER.test(endpoint)) {\n const b = body as\n | {\n links?: Array<{ id: number; order: number }>;\n }\n | undefined;\n const items = b?.links ?? [];\n if (items.length === 0) return [] as unknown as T;\n const sortedIds = [...items]\n .sort((a, b2) => a.order - b2.order)\n .map((l) => l.id);\n const res = await portalTenantMysite.mysite_links_bulk_reorder(\n bffClient,\n { ordered_ids: sortedIds },\n );\n const links = (res.links ?? []) as Record<string, unknown>[];\n return links.map(mapBffLink) as T;\n }\n\n // PATCH /user_companies/:id/favorites/bulk_reorder.json → reorder favorites\n if (FAVORITES_REORDER.test(endpoint)) {\n const b = body as\n | {\n favorites?: Array<{ id: number; order: number }>;\n }\n | undefined;\n const items = b?.favorites ?? [];\n if (items.length === 0) return [] as unknown as T;\n const sortedIds = [...items]\n .sort((a, b2) => a.order - b2.order)\n .map((f) => f.id);\n const res = await portalTenantMysite.mysite_favorites_bulk_reorder(\n bffClient,\n { ordered_ids: sortedIds },\n );\n const favs = (res.favorites ?? []) as Record<string, unknown>[];\n return favs.map(mapBffFavorite) as T;\n }\n\n // Fallthrough\n return bffClient.patch<T>(endpoint, body, options);\n }\n\n // ----- DELETE -----\n async function del<T>(\n endpoint: string,\n options?: Omit<RequestOptions, \"method\">,\n ): Promise<T> {\n // DELETE /users/:id/links/:linkId.json → delete link\n const linkMatch = endpoint.match(LINK_SINGLE);\n if (linkMatch) {\n const linkId = Number(linkMatch[1]);\n return portalTenantMysite.mysite_links_destroy(\n bffClient,\n linkId,\n ) as Promise<T>;\n }\n\n // DELETE /user_companies/:id/favorites/:favId.json → delete favorite\n const favMatch = endpoint.match(FAVORITE_SINGLE);\n if (favMatch) {\n const favId = Number(favMatch[1]);\n return portalTenantMysite.mysite_favorites_destroy(\n bffClient,\n favId,\n ) as Promise<T>;\n }\n\n // Fallthrough\n return bffClient.delete<T>(endpoint, options);\n }\n\n // ----- Assemble -----\n return {\n request: bffClient.request,\n requestWithFormData: bffClient.requestWithFormData,\n get,\n post,\n put,\n patch,\n delete: del,\n };\n}\n","/**\n * Hook that returns a FetchClient adapter translating legacy mysite API\n * calls to the portal-tenant MySite BFF.\n *\n * The adapter wraps the shared portal-tenant FetchClient so that existing\n * mysite-ui hooks and components (which call `/me.json`, `/users/{id}/links.json`,\n * etc.) work transparently against the BFF endpoints.\n */\n\nimport { useMemo } from \"react\";\nimport type { FetchClient } from \"@fluid-app/api-client-core\";\nimport { usePortalTenantClient } from \"../providers/PortalTenantClientProvider\";\nimport { createPortalMySiteAdapter } from \"./create-portal-mysite-adapter\";\n\nexport function usePortalMySiteClient(): FetchClient {\n const bffClient = usePortalTenantClient();\n\n return useMemo(() => createPortalMySiteAdapter(bffClient), [bffClient]);\n}\n","export const MYSITE_KEYS = {\n links: (userId: number) => [\"mysite\", \"links\", userId] as const,\n favorites: (affiliateId: number) =>\n [\"mysite\", \"favorites\", affiliateId] as const,\n themes: () => [\"mysite\", \"themes\"] as const,\n defaultMySite: () => [\"mysite\", \"default\"] as const,\n defaultMySiteFavorites: () => [\"mysite\", \"default\", \"favorites\"] as const,\n};\n","import { z } from \"zod\";\n\n// User Links (Buttons)\nexport const linkSchema = z.object({\n id: z.number(),\n url: z.string(),\n text: z.string(),\n order: z.number(),\n clicks: z.number().optional().default(0),\n});\n\nexport const linksResponseSchema = z.array(linkSchema);\n\nexport type MySiteLink = z.infer<typeof linkSchema>;\n\n// Favorites\nexport const favoriteableSchema = z\n .object({\n id: z.number(),\n title: z.string().nullable().optional(),\n name: z.string().nullable().optional(),\n image_url: z.string().nullable().optional(),\n type: z.string().optional(),\n })\n .passthrough();\n\nexport const favoriteSchema = z\n .object({\n id: z.number(),\n favoriteable_id: z.number().optional(),\n favoriteable_type: z.string(),\n order: z.number(),\n user_company_id: z.number().optional(),\n created_at: z.string().optional(),\n favoriteable: favoriteableSchema.nullable(),\n })\n .passthrough();\n\nexport const favoritesResponseSchema = z.array(favoriteSchema);\n\nexport type MySiteFavorite = z.infer<typeof favoriteSchema>;\n\n// MySite Update\nexport const mysiteUpdateResponseSchema = z\n .object({\n id: z.number(),\n })\n .passthrough();\n\n// User Profile Update\nexport const profileUpdateResponseSchema = z.object({\n id: z.number(),\n bio: z.string().nullable(),\n facebook: z.string().nullable(),\n twitter: z.string().nullable(),\n instagram: z.string().nullable(),\n youtube: z.string().nullable(),\n pinterest: z.string().nullable(),\n tiktok: z.string().nullable(),\n linkedin: z.string().nullable(),\n whatsapp: z.string().nullable(),\n wechat: z.string().nullable(),\n image_url: z.string().nullable(),\n});\n\nexport type ProfileUpdateResponse = z.infer<typeof profileUpdateResponseSchema>;\n","import type { FetchClient } from \"./types\";\nimport {\n linksResponseSchema,\n linkSchema,\n favoritesResponseSchema,\n favoriteSchema,\n mysiteUpdateResponseSchema,\n profileUpdateResponseSchema,\n} from \"../../shared/schemas/mysite.schema\";\n\nexport async function getUserLinks(client: FetchClient, userId: number) {\n const response = await client.get(`/users/${userId}/links.json`);\n return linksResponseSchema.parse(response);\n}\n\nexport async function createUserLink(\n client: FetchClient,\n userId: number,\n data: { url: string; text: string },\n) {\n const response = await client.post(`/users/${userId}/links.json`, data);\n const result = linkSchema.safeParse(response);\n return result.success ? result.data : response;\n}\n\nexport async function updateUserLink(\n client: FetchClient,\n userId: number,\n linkId: number,\n data: { url: string; text: string },\n) {\n const response = await client.put(\n `/users/${userId}/links/${linkId}.json`,\n data,\n );\n const result = linkSchema.safeParse(response);\n return result.success ? result.data : response;\n}\n\nexport async function deleteUserLink(\n client: FetchClient,\n userId: number,\n linkId: number,\n) {\n return client.delete(`/users/${userId}/links/${linkId}.json`);\n}\n\nexport async function reorderUserLinks(\n client: FetchClient,\n userId: number,\n links: Array<{ id: number; order: number }>,\n) {\n const response = await client.patch(\n `/users/${userId}/links/bulk_reorder.json`,\n { links },\n );\n const reorderResult = linksResponseSchema.safeParse(response);\n return reorderResult.success ? reorderResult.data : response;\n}\n\nexport async function getUserFavorites(\n client: FetchClient,\n affiliateId: number,\n) {\n const response = await client.get(\n `/user_companies/${affiliateId}/favorites.json`,\n );\n return favoritesResponseSchema.parse(response);\n}\n\nexport async function deleteFavorite(\n client: FetchClient,\n affiliateId: number,\n favoriteId: number,\n) {\n return client.delete(\n `/user_companies/${affiliateId}/favorites/${favoriteId}.json`,\n );\n}\n\nexport async function reorderFavorites(\n client: FetchClient,\n affiliateId: number,\n favorites: Array<{ id: number; order: number }>,\n countryId?: number,\n languageIso?: string,\n) {\n const response = await client.patch(\n `/user_companies/${affiliateId}/favorites/bulk_reorder.json`,\n {\n favorites,\n country_id: countryId,\n language_iso: languageIso,\n },\n );\n const reorderFavResult = favoritesResponseSchema.safeParse(response);\n return reorderFavResult.success ? reorderFavResult.data : response;\n}\n\nexport async function updateMySite(\n client: FetchClient,\n data: {\n theme_id?: number;\n username?: string;\n },\n) {\n const response = await client.put(\"/mysite.json\", { user_company: data });\n const mysiteResult = mysiteUpdateResponseSchema.safeParse(response);\n return mysiteResult.success ? mysiteResult.data : response;\n}\n\nexport async function updateProfile(\n client: FetchClient,\n data: {\n bio?: string;\n facebook?: string;\n twitter?: string;\n instagram?: string;\n youtube?: string;\n pinterest?: string;\n tiktok?: string;\n linkedin?: string;\n whatsapp?: string;\n wechat?: string;\n image_url?: string;\n },\n) {\n const response = await client.put(\"/me.json\", data);\n const profileResult = profileUpdateResponseSchema.safeParse(response);\n return profileResult.success ? profileResult.data : response;\n}\n\nexport async function addFavorite(\n client: FetchClient,\n affiliateId: number,\n data: {\n favoriteable_id: number;\n favoriteable_type: string;\n },\n countryId?: number,\n) {\n const response = await client.post(\n `/user_companies/${affiliateId}/favorites.json`,\n {\n favorite: data,\n country_id: countryId,\n },\n );\n const favResult = favoriteSchema.safeParse(response);\n return favResult.success ? favResult.data : response;\n}\n","import { z } from \"zod\";\n\nexport interface MysiteTheme {\n id: number;\n name: string;\n description: string | null;\n public: boolean;\n company_id: number | null;\n created_at: string;\n updated_at: string;\n image_url: string | null;\n application_theme_template_id: number | null;\n}\n\nexport const themeSchema: z.ZodType<MysiteTheme> = z.object({\n id: z.number(),\n name: z.string(),\n description: z.string().nullable(),\n public: z.boolean(),\n company_id: z.number().nullable(),\n created_at: z.string().datetime(),\n updated_at: z.string().datetime(),\n image_url: z.string().nullable(),\n application_theme_template_id: z.number().nullable(),\n});\n\nexport const mysiteThemesSchema: z.ZodType<MysiteTheme[]> =\n z.array(themeSchema);\n\n// --- Legacy Theme (for creating themes via /legacy_themes endpoint) ---\n\ninterface LegacyThemeTemplate {\n id: number;\n name: string;\n content: string | null;\n stylesheet: string | null;\n head: string | null;\n status: string;\n}\n\nconst legacyThemeTemplateSchema: z.ZodType<LegacyThemeTemplate> = z.object({\n id: z.number(),\n name: z.string(),\n content: z.string().nullable(),\n stylesheet: z.string().nullable(),\n head: z.string().nullable(),\n status: z.string(),\n});\n\nexport interface LegacyThemeResponse {\n data: {\n legacy_theme: {\n id: number;\n name: string;\n description: string | null;\n image_url: string | null;\n public: boolean;\n company_id: number | null;\n template: LegacyThemeTemplate;\n };\n };\n}\n\nconst legacyThemeResponseSchema: z.ZodType<LegacyThemeResponse> = z.object({\n data: z.object({\n legacy_theme: z.object({\n id: z.number(),\n name: z.string(),\n description: z.string().nullable(),\n image_url: z.string().nullable(),\n public: z.boolean(),\n company_id: z.number().nullable(),\n template: legacyThemeTemplateSchema,\n }),\n }),\n});\n\nexport { legacyThemeResponseSchema };\n\nexport interface CreateLegacyThemeInput {\n name: string;\n description?: string;\n image_url?: string;\n public?: boolean;\n template?: {\n content?: string;\n stylesheet?: string;\n head?: string;\n };\n}\n","import type { FetchClient } from \"./types\";\nimport {\n mysiteThemesSchema,\n legacyThemeResponseSchema,\n type MysiteTheme,\n type CreateLegacyThemeInput,\n} from \"../../shared/schemas/mysite-theme.schema\";\n\nexport async function getMysiteThemes(\n client: FetchClient,\n): Promise<MysiteTheme[]> {\n const response = await client.get(\"/mysite/themes\");\n return mysiteThemesSchema.parse(response);\n}\n\nexport async function createLegacyTheme(\n client: FetchClient,\n input: CreateLegacyThemeInput,\n) {\n const response = await client.post(\"/legacy_themes\", {\n legacy_theme: input,\n });\n const result = legacyThemeResponseSchema.safeParse(response);\n return result.success ? result.data : response;\n}\n","\"use client\";\nimport { useQuery, useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { MYSITE_KEYS } from \"../../shared/query-keys\";\nimport {\n getUserLinks,\n createUserLink,\n updateUserLink,\n deleteUserLink,\n reorderUserLinks,\n getUserFavorites,\n addFavorite,\n deleteFavorite,\n reorderFavorites,\n updateMySite as updateMySiteApi,\n updateProfile as updateProfileApi,\n} from \"../networking/mysite.api\";\nimport {\n getMysiteThemes,\n createLegacyTheme,\n} from \"../networking/mysite-theme.api\";\nimport type { CreateLegacyThemeInput } from \"../../shared/schemas/mysite-theme.schema\";\nimport type {\n MySiteLink,\n MySiteFavorite,\n} from \"../../shared/schemas/mysite.schema\";\nimport type { FetchClient } from \"../networking/types\";\n\n// === LINKS HOOKS ===\n\nexport function useUserLinks(\n client: FetchClient,\n userId: number | null | undefined,\n) {\n return useQuery({\n queryKey: MYSITE_KEYS.links(userId ?? 0),\n queryFn: () => getUserLinks(client, userId!),\n enabled: !!userId,\n });\n}\n\nexport function useCreateLink(\n client: FetchClient,\n userId: number | null | undefined,\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (data: { url: string; text: string }) => {\n if (!userId) return Promise.reject(new Error(\"User not loaded\"));\n return createUserLink(client, userId, data);\n },\n onSuccess: () => {\n if (userId)\n queryClient.invalidateQueries({ queryKey: MYSITE_KEYS.links(userId) });\n },\n });\n}\n\nexport function useUpdateLink(\n client: FetchClient,\n userId: number | null | undefined,\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({\n linkId,\n data,\n }: {\n linkId: number;\n data: { url: string; text: string };\n }) => {\n if (!userId) return Promise.reject(new Error(\"User not loaded\"));\n return updateUserLink(client, userId, linkId, data);\n },\n onSuccess: () => {\n if (userId)\n queryClient.invalidateQueries({ queryKey: MYSITE_KEYS.links(userId) });\n },\n });\n}\n\nexport function useDeleteLink(\n client: FetchClient,\n userId: number | null | undefined,\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (linkId: number) => {\n if (!userId) return Promise.reject(new Error(\"User not loaded\"));\n return deleteUserLink(client, userId, linkId);\n },\n onSuccess: () => {\n if (userId)\n queryClient.invalidateQueries({ queryKey: MYSITE_KEYS.links(userId) });\n },\n });\n}\n\nexport function useReorderLinks(\n client: FetchClient,\n userId: number | null | undefined,\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({\n payload,\n }: {\n payload: Array<{ id: number; order: number }>;\n optimisticItems: MySiteLink[];\n }) => {\n if (!userId) return Promise.reject(new Error(\"User not loaded\"));\n return reorderUserLinks(client, userId, payload);\n },\n onMutate: async ({ optimisticItems }) => {\n if (!userId) return;\n await queryClient.cancelQueries({\n queryKey: MYSITE_KEYS.links(userId),\n });\n const previousData = queryClient.getQueryData<MySiteLink[]>(\n MYSITE_KEYS.links(userId),\n );\n queryClient.setQueryData(MYSITE_KEYS.links(userId), optimisticItems);\n return { previousData };\n },\n onError: (_err, _vars, context) => {\n if (userId && context?.previousData) {\n queryClient.setQueryData(\n MYSITE_KEYS.links(userId),\n context.previousData,\n );\n }\n },\n onSettled: () => {\n if (userId)\n queryClient.invalidateQueries({ queryKey: MYSITE_KEYS.links(userId) });\n },\n });\n}\n\n// === FAVORITES HOOKS ===\n\nexport function useUserFavorites(\n client: FetchClient,\n affiliateId: number | null | undefined,\n) {\n return useQuery({\n queryKey: MYSITE_KEYS.favorites(affiliateId ?? 0),\n queryFn: () => getUserFavorites(client, affiliateId!),\n enabled: !!affiliateId,\n });\n}\n\nexport function useAddFavorite(\n client: FetchClient,\n affiliateId: number | null | undefined,\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (data: {\n favoriteable_id: number;\n favoriteable_type: string;\n country_id?: number;\n }) => {\n if (!affiliateId) return Promise.reject(new Error(\"User not loaded\"));\n return addFavorite(\n client,\n affiliateId,\n {\n favoriteable_id: data.favoriteable_id,\n favoriteable_type: data.favoriteable_type,\n },\n data.country_id,\n );\n },\n onSuccess: () => {\n if (affiliateId)\n queryClient.invalidateQueries({\n queryKey: MYSITE_KEYS.favorites(affiliateId),\n });\n },\n });\n}\n\nexport function useDeleteFavorite(\n client: FetchClient,\n affiliateId: number | null | undefined,\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (favoriteId: number) => {\n if (!affiliateId) return Promise.reject(new Error(\"User not loaded\"));\n return deleteFavorite(client, affiliateId, favoriteId);\n },\n onSuccess: () => {\n if (affiliateId)\n queryClient.invalidateQueries({\n queryKey: MYSITE_KEYS.favorites(affiliateId),\n });\n },\n });\n}\n\nexport function useReorderFavorites(\n client: FetchClient,\n affiliateId: number | null | undefined,\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({\n payload,\n }: {\n payload: Array<{ id: number; order: number }>;\n optimisticItems: MySiteFavorite[];\n }) => {\n if (!affiliateId) return Promise.reject(new Error(\"User not loaded\"));\n return reorderFavorites(client, affiliateId, payload);\n },\n onMutate: async ({ optimisticItems }) => {\n if (!affiliateId) return;\n await queryClient.cancelQueries({\n queryKey: MYSITE_KEYS.favorites(affiliateId),\n });\n const previousData = queryClient.getQueryData<MySiteFavorite[]>(\n MYSITE_KEYS.favorites(affiliateId),\n );\n queryClient.setQueryData(\n MYSITE_KEYS.favorites(affiliateId),\n optimisticItems,\n );\n return { previousData };\n },\n onError: (_err, _vars, context) => {\n if (affiliateId && context?.previousData) {\n queryClient.setQueryData(\n MYSITE_KEYS.favorites(affiliateId),\n context.previousData,\n );\n }\n },\n onSettled: () => {\n if (affiliateId)\n queryClient.invalidateQueries({\n queryKey: MYSITE_KEYS.favorites(affiliateId),\n });\n },\n });\n}\n\n// === THEMES HOOK ===\n\nexport function useMySiteThemes(client: FetchClient) {\n return useQuery({\n queryKey: MYSITE_KEYS.themes(),\n queryFn: () => getMysiteThemes(client),\n });\n}\n\n// === CREATE LEGACY THEME HOOK ===\n\nexport function useCreateLegacyTheme(client: FetchClient) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (data: CreateLegacyThemeInput) =>\n createLegacyTheme(client, data),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: MYSITE_KEYS.themes() });\n },\n });\n}\n\n// === MYSITE SETTINGS HOOK ===\n\nexport function useUpdateMySite(\n client: FetchClient,\n options?: { onProfileRefetch?: () => void },\n) {\n return useMutation({\n mutationFn: (data: Parameters<typeof updateMySiteApi>[1]) =>\n updateMySiteApi(client, data),\n onSuccess: () => options?.onProfileRefetch?.(),\n });\n}\n\n// === PROFILE HOOK ===\n\nexport function useUpdateProfile(\n client: FetchClient,\n options?: { onProfileRefetch?: () => void },\n) {\n return useMutation({\n mutationFn: (data: Parameters<typeof updateProfileApi>[1]) =>\n updateProfileApi(client, data),\n onSuccess: () => options?.onProfileRefetch?.(),\n });\n}\n","import { FADE_MS, SLIDE_MS, type AnimPhase } from \"./types\";\n\nexport function getContentStyle(phase: AnimPhase): React.CSSProperties {\n switch (phase) {\n case \"idle\":\n return { transform: \"translateX(0)\", opacity: 1, transition: \"none\" };\n case \"fade-out\":\n return {\n transform: \"translateX(0)\",\n opacity: 0,\n transition: `opacity ${FADE_MS}ms ease-in-out`,\n };\n case \"slide\":\n return {\n transform: \"translateX(50%)\",\n opacity: 0,\n transition: `transform ${SLIDE_MS}ms ease-in-out`,\n };\n case \"fade-in\":\n return {\n transform: \"translateX(50%)\",\n opacity: 1,\n transition: `opacity ${FADE_MS}ms ease-in-out`,\n };\n case \"editing\":\n return { transform: \"translateX(50%)\", opacity: 1, transition: \"none\" };\n case \"exit-fade-out\":\n return {\n transform: \"translateX(50%)\",\n opacity: 0,\n transition: `opacity ${FADE_MS}ms ease-in-out`,\n };\n case \"exit-slide\":\n return {\n transform: \"translateX(0)\",\n opacity: 0,\n transition: `transform ${SLIDE_MS}ms ease-in-out`,\n };\n case \"exit-fade-in\":\n return {\n transform: \"translateX(0)\",\n opacity: 1,\n transition: `opacity ${FADE_MS}ms ease-in-out`,\n };\n }\n}\n\nexport function getPreviewStyle(phase: AnimPhase): React.CSSProperties {\n switch (phase) {\n case \"idle\":\n case \"fade-out\":\n case \"exit-fade-in\":\n return { transform: \"translateX(0)\", transition: \"none\" };\n case \"slide\":\n return {\n transform: \"translateX(-200%)\",\n transition: `transform ${SLIDE_MS}ms ease-in-out`,\n };\n case \"fade-in\":\n case \"editing\":\n case \"exit-fade-out\":\n return { transform: \"translateX(-200%)\", transition: \"none\" };\n case \"exit-slide\":\n return {\n transform: \"translateX(0)\",\n transition: `transform ${SLIDE_MS}ms ease-in-out`,\n };\n }\n}\n","import { Eye, Users } from \"lucide-react\";\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Separator,\n} from \"@fluid-app/ui-primitives\";\n\nexport function MySiteVisitorDetailsCard({\n views,\n leads,\n}: {\n views: number;\n leads: number;\n}): React.JSX.Element {\n return (\n <Card className=\"h-auto gap-0 py-0 shadow-none\">\n <CardHeader className=\"p-4 pb-3\">\n <CardTitle className=\"text-sm\">Visitor Details</CardTitle>\n </CardHeader>\n <CardContent className=\"flex px-4 pb-4\">\n <div className=\"flex-1\">\n <div className=\"mb-2 flex items-center gap-1.5\">\n <Eye className=\"text-muted-foreground h-3.5 w-3.5\" />\n <span className=\"text-muted-foreground text-sm\">Views</span>\n </div>\n <p className=\"text-foreground text-2xl font-bold\">\n {views.toLocaleString()}\n </p>\n </div>\n <Separator orientation=\"vertical\" className=\"bg-border mx-4 h-auto\" />\n <div className=\"flex-1\">\n <div className=\"mb-2 flex items-center gap-1.5\">\n <Users className=\"text-muted-foreground h-3.5 w-3.5\" />\n <span className=\"text-muted-foreground text-sm\">Leads</span>\n </div>\n <p className=\"text-foreground text-2xl font-bold\">\n {leads.toLocaleString()}\n </p>\n </div>\n </CardContent>\n </Card>\n );\n}\n","import { useCallback, useState } from \"react\";\nimport { Copy } from \"lucide-react\";\nimport {\n Button,\n Card,\n CardAction,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"@fluid-app/ui-primitives\";\n\nexport function MySiteLinkCard({\n mysiteUrl,\n displayUrl,\n onUpdateSlug,\n onToast,\n}: {\n mysiteUrl: string;\n displayUrl: string;\n onUpdateSlug?: (slug: string) => Promise<void>;\n onToast?: (message: string, type: \"success\" | \"error\") => void;\n}): React.JSX.Element {\n const lastSlashIndex = displayUrl.lastIndexOf(\"/\");\n const urlPrefix =\n lastSlashIndex >= 0 ? displayUrl.slice(0, lastSlashIndex + 1) : \"\";\n const currentSlug =\n lastSlashIndex >= 0 ? displayUrl.slice(lastSlashIndex + 1) : displayUrl;\n\n const [isEditingLink, setIsEditingLink] = useState(false);\n const [linkSlugInput, setLinkSlugInput] = useState(currentSlug);\n const [isSaving, setIsSaving] = useState(false);\n\n const handleEditLink = useCallback(() => {\n setLinkSlugInput(currentSlug);\n setIsEditingLink(true);\n }, [currentSlug]);\n\n const handleCancelEditLink = useCallback(() => {\n setIsEditingLink(false);\n setLinkSlugInput(currentSlug);\n }, [currentSlug]);\n\n const handleSaveLink = useCallback(async () => {\n const trimmed = linkSlugInput.trim();\n if (!trimmed) {\n onToast?.(\"Slug cannot be empty\", \"error\");\n return;\n }\n if (trimmed === currentSlug) {\n setIsEditingLink(false);\n return;\n }\n if (!onUpdateSlug) return;\n setIsSaving(true);\n try {\n await onUpdateSlug(trimmed);\n onToast?.(\"MySite link updated\", \"success\");\n setIsEditingLink(false);\n } catch {\n onToast?.(\"Failed to update link\", \"error\");\n } finally {\n setIsSaving(false);\n }\n }, [linkSlugInput, currentSlug, onUpdateSlug, onToast]);\n\n const handleCopyLink = useCallback(async () => {\n if (!mysiteUrl) return;\n try {\n await navigator.clipboard.writeText(mysiteUrl);\n onToast?.(\"Link copied to clipboard\", \"success\");\n } catch {\n onToast?.(\"Failed to copy link\", \"error\");\n }\n }, [mysiteUrl, onToast]);\n\n return (\n <Card className=\"h-auto gap-0 py-0 shadow-none\">\n <CardHeader className=\"items-center p-4\">\n <CardTitle className=\"text-sm\">Your MySite Link</CardTitle>\n {!isEditingLink && onUpdateSlug && (\n <CardAction>\n <Button variant=\"link\" size=\"sm\" onClick={handleEditLink}>\n Edit Link\n </Button>\n </CardAction>\n )}\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div\n className=\"flex items-center gap-2 rounded-lg border px-3 py-2.5\"\n style={{\n background:\n \"linear-gradient(90deg, #d4edda 0%, #fce4ec 50%, #fff3e0 100%)\",\n }}\n >\n {isEditingLink ? (\n <>\n <span className=\"text-foreground shrink-0 text-sm\">\n {urlPrefix}\n </span>\n <input\n type=\"text\"\n value={linkSlugInput}\n onChange={(e) => setLinkSlugInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !isSaving) handleSaveLink();\n if (e.key === \"Escape\") handleCancelEditLink();\n }}\n className=\"text-foreground border-input focus:ring-primary min-w-0 flex-1 rounded-md border bg-white/60 px-2 py-1 text-sm font-medium outline-none focus:ring-1\"\n autoFocus\n />\n </>\n ) : (\n <span\n className=\"min-w-0 flex-1 truncate text-sm\"\n style={{ color: \"black\" }}\n >\n {displayUrl || \"Not configured\"}\n </span>\n )}\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={handleCopyLink}\n disabled={!mysiteUrl}\n >\n <Copy className=\"h-4 w-4\" />\n </Button>\n </div>\n\n <div\n className=\"grid transition-all duration-300 ease-in-out\"\n style={{\n gridTemplateRows: isEditingLink ? \"1fr\" : \"0fr\",\n opacity: isEditingLink ? 1 : 0,\n marginTop: isEditingLink ? 12 : 0,\n }}\n >\n <div className=\"overflow-hidden\">\n <div className=\"flex justify-end gap-2\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleCancelEditLink}\n >\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleSaveLink} disabled={isSaving}>\n {isSaving ? \"Saving...\" : \"Save\"}\n </Button>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n );\n}\n","import { LoaderCircle } from \"lucide-react\";\nimport {\n Button,\n Card,\n CardContent,\n CardHeader,\n} from \"@fluid-app/ui-primitives\";\n\nexport function MySitePhonePreview({\n mysiteUrl,\n themeName,\n previewKey,\n isUpdating,\n onPreview,\n}: {\n mysiteUrl: string;\n themeName: string;\n previewKey: number;\n isUpdating: boolean;\n onPreview: () => void;\n}): React.JSX.Element {\n return (\n <Card className=\"items-center gap-4 py-5\">\n <CardHeader className=\"w-full items-center px-5\">\n <div>\n <p className=\"text-muted-foreground text-xs\">Current Theme</p>\n <p className=\"text-foreground text-sm font-semibold\">{themeName}</p>\n </div>\n <Button\n className=\"col-start-2 row-span-2 row-start-1 self-center justify-self-end\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={onPreview}\n disabled={!mysiteUrl}\n >\n Preview\n </Button>\n </CardHeader>\n\n <CardContent className=\"relative mx-auto my-auto w-[320px] px-0\">\n <div className=\"overflow-hidden rounded-[40px] border-[8px] border-[#1e2939] bg-[#1e2939] shadow-xl\">\n <div className=\"flex items-center justify-between bg-[#101828] px-6 py-1.5\">\n <span className=\"text-[11px] font-medium text-[#ffffff]\">9:41</span>\n <div className=\"flex items-center gap-1\">\n <div className=\"h-2.5 w-2.5 rounded-full bg-[#ffffff60]\" />\n <div className=\"h-2.5 w-4 rounded-sm bg-[#ffffff60]\" />\n </div>\n </div>\n\n <div\n className=\"relative h-[600px] overflow-y-auto bg-[#ffffff]\"\n style={{ scrollbarWidth: \"none\" }}\n aria-busy={isUpdating}\n >\n {mysiteUrl ? (\n <>\n <iframe\n key={previewKey}\n className=\"h-full w-full origin-top-left bg-[#ffffff]\"\n src={`${mysiteUrl}?preview=true`}\n title=\"MySite Preview\"\n />\n {isUpdating && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/60\">\n <LoaderCircle className=\"text-muted-foreground h-6 w-6 animate-spin\" />\n </div>\n )}\n </>\n ) : (\n <div className=\"flex h-full items-center justify-center\">\n <p className=\"text-muted-foreground text-sm\">\n No site configured\n </p>\n </div>\n )}\n </div>\n </div>\n\n <div className=\"absolute bottom-2 left-1/2 h-1 w-28 -translate-x-1/2 rounded-full bg-white\" />\n </CardContent>\n </Card>\n );\n}\n","import { ArrowLeft, Check, Palette } from \"lucide-react\";\nimport { Button, Card, CardContent, cn } from \"@fluid-app/ui-primitives\";\nimport type { MysiteTheme } from \"../../shared/schemas/mysite-theme.schema\";\n\nexport function MySiteThemeEditor({\n themes,\n selectedThemeId,\n onSelectTheme,\n isPending,\n onBack,\n}: {\n themes: MysiteTheme[];\n selectedThemeId: number | null;\n onSelectTheme: (theme: MysiteTheme) => void;\n isPending: boolean;\n onBack: () => void;\n}): React.JSX.Element {\n return (\n <>\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={onBack}>\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <h1 className=\"text-foreground text-xl font-bold\">Choose a Theme</h1>\n </div>\n\n {themes.length === 0 ? (\n <Card>\n <CardContent className=\"py-8 text-center\">\n <p className=\"text-muted-foreground\">No themes available</p>\n </CardContent>\n </Card>\n ) : (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3\">\n {themes.map((theme) => {\n const isSelected = theme.id === selectedThemeId;\n return (\n <button\n key={theme.id}\n type=\"button\"\n onClick={() => onSelectTheme(theme)}\n className={cn(\n \"group focus:ring-primary relative overflow-hidden rounded-lg border-2 transition-all focus:ring-2 focus:ring-offset-2 focus:outline-none\",\n isSelected\n ? \"border-primary ring-primary ring-2\"\n : \"border-border hover:border-muted-foreground/50\",\n )}\n aria-pressed={isSelected}\n disabled={isPending}\n >\n <div className=\"bg-muted relative aspect-[4/3] w-full\">\n {theme.image_url ? (\n <img\n src={theme.image_url}\n alt={theme.name}\n loading=\"lazy\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n ) : (\n <div className=\"text-muted-foreground/50 flex h-full w-full items-center justify-center\">\n <Palette className=\"h-8 w-8\" />\n </div>\n )}\n {isSelected && (\n <div className=\"bg-primary/20 absolute inset-0 flex items-center justify-center\">\n <div className=\"bg-primary text-primary-foreground flex h-8 w-8 items-center justify-center rounded-full\">\n <Check className=\"h-5 w-5\" />\n </div>\n </div>\n )}\n {!isSelected && (\n <div className=\"absolute inset-0 bg-black/0 transition-colors group-hover:bg-black/10 dark:group-hover:bg-white/10\" />\n )}\n </div>\n <div className=\"bg-card p-2\">\n <p\n className={cn(\n \"truncate text-sm font-medium\",\n isSelected ? \"text-primary\" : \"text-foreground\",\n )}\n >\n {theme.name}\n </p>\n </div>\n </button>\n );\n })}\n </div>\n )}\n </>\n );\n}\n","export const sortByOrder = <T extends { order: number }>(items: T[]): T[] => {\n return [...items].sort((a, b) => a.order - b.order);\n};\n\nexport const updateOrders = <T extends { id: number | string; order: number }>(\n items: T[],\n): T[] => {\n return items.map((item, index) => ({\n ...item,\n order: index + 1,\n }));\n};\n\nexport const generateTempId = (): string => {\n return `temp_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n};\n\nexport function normalizeUrl(value: string): string {\n const trimmed = value.trim();\n if (!trimmed) return \"\";\n if (/^https?:\\/\\//i.test(trimmed)) return trimmed;\n return `https://${trimmed}`;\n}\n","\"use client\";\nimport { useCallback, useState } from \"react\";\nimport { ArrowLeft, Plus, GripVertical, Pencil, Trash2 } from \"lucide-react\";\nimport {\n Button,\n Badge,\n Card,\n Dialog,\n Skeleton,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n Input,\n Label,\n useZodForm,\n} from \"@fluid-app/ui-primitives\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { z } from \"zod\";\nimport {\n useUserLinks,\n useCreateLink,\n useUpdateLink,\n useDeleteLink,\n useReorderLinks,\n} from \"../../admin/hooks/use-mysite\";\nimport type { FetchClient } from \"@fluid-app/api-client-core\";\nimport type { MySiteLink } from \"../../shared/schemas/mysite.schema\";\nimport { normalizeUrl } from \"../../shared/utils\";\n\nconst buttonSchema = z.object({\n text: z.string().min(1, \"Button text is required\"),\n url: z\n .string()\n .transform(normalizeUrl)\n .pipe(z.string().url(\"Must be a valid URL\")),\n});\n\ntype ButtonFormData = z.infer<typeof buttonSchema>;\n\nfunction SortableButtonCard({\n link,\n onEdit,\n onDelete,\n}: {\n link: MySiteLink;\n onEdit: (link: MySiteLink) => void;\n onDelete: (link: MySiteLink) => void;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: link.id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n };\n\n const truncatedUrl =\n link.url.length > 40 ? `${link.url.substring(0, 40)}...` : link.url;\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n className={`border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4 ${\n isDragging ? \"opacity-50 shadow-lg\" : \"\"\n }`}\n >\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground cursor-grab touch-none\"\n aria-label=\"Drag to reorder\"\n {...attributes}\n {...listeners}\n >\n <GripVertical className=\"h-5 w-5\" />\n </button>\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-foreground truncate font-medium\">{link.text}</p>\n <p className=\"text-muted-foreground truncate text-sm\">{truncatedUrl}</p>\n </div>\n\n <Badge variant=\"secondary\" className=\"hidden shrink-0 sm:inline-flex\">\n {link.clicks ?? 0} clicks\n </Badge>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground hover:text-foreground\"\n onClick={() => onEdit(link)}\n aria-label=\"Edit button\"\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground hover:text-destructive\"\n onClick={() => onDelete(link)}\n aria-label=\"Delete button\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n\nexport function MySiteButtonsEditor({\n onBack,\n onRefreshPreview,\n client,\n userId,\n onToast,\n}: {\n onBack: () => void;\n onRefreshPreview?: () => void;\n client: FetchClient;\n userId: number | null | undefined;\n onToast?: (message: string, type: \"success\" | \"error\") => void;\n}): React.JSX.Element {\n \"use no memo\";\n const { data: links = [], isLoading } = useUserLinks(client, userId);\n const createLinkMutation = useCreateLink(client, userId);\n const updateLinkMutation = useUpdateLink(client, userId);\n const deleteLinkMutation = useDeleteLink(client, userId);\n const reorderLinksMutation = useReorderLinks(client, userId);\n\n const [isAddEditDialogOpen, setIsAddEditDialogOpen] = useState(false);\n const [editingLink, setEditingLink] = useState<MySiteLink | null>(null);\n const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);\n const [deletingLink, setDeletingLink] = useState<MySiteLink | null>(null);\n\n const {\n register,\n handleSubmit: handleButtonSubmit,\n reset: resetButtonForm,\n formState: { errors: buttonErrors, isSubmitting: isButtonSubmitting },\n } = useZodForm<ButtonFormData>(buttonSchema, {\n defaultValues: { text: \"\", url: \"\" },\n });\n\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n }),\n );\n\n const handleOpenAddDialog = useCallback(() => {\n setEditingLink(null);\n resetButtonForm({ text: \"\", url: \"\" });\n setIsAddEditDialogOpen(true);\n }, [resetButtonForm]);\n\n const handleOpenEditDialog = useCallback(\n (link: MySiteLink) => {\n setEditingLink(link);\n resetButtonForm({ text: link.text, url: link.url });\n setIsAddEditDialogOpen(true);\n },\n [resetButtonForm],\n );\n\n const handleCloseAddEditDialog = useCallback(() => {\n setIsAddEditDialogOpen(false);\n setEditingLink(null);\n resetButtonForm({ text: \"\", url: \"\" });\n }, [resetButtonForm]);\n\n const onButtonSubmit = useCallback(\n (data: ButtonFormData) => {\n if (editingLink) {\n updateLinkMutation.mutate(\n { linkId: editingLink.id, data },\n {\n onSuccess: () => {\n onToast?.(\"Button updated\", \"success\");\n handleCloseAddEditDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to update button\", \"error\");\n },\n },\n );\n } else {\n createLinkMutation.mutate(data, {\n onSuccess: () => {\n onToast?.(\"Button created\", \"success\");\n handleCloseAddEditDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to create button\", \"error\");\n },\n });\n }\n },\n [\n editingLink,\n createLinkMutation,\n updateLinkMutation,\n handleCloseAddEditDialog,\n onRefreshPreview,\n onToast,\n ],\n );\n\n const handleOpenDeleteDialog = useCallback((link: MySiteLink) => {\n setDeletingLink(link);\n setIsDeleteDialogOpen(true);\n }, []);\n\n const handleCloseDeleteDialog = useCallback(() => {\n setIsDeleteDialogOpen(false);\n setDeletingLink(null);\n }, []);\n\n const handleConfirmDelete = useCallback(() => {\n if (deletingLink) {\n deleteLinkMutation.mutate(deletingLink.id, {\n onSuccess: () => {\n onToast?.(\"Button deleted\", \"success\");\n handleCloseDeleteDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to delete button\", \"error\");\n },\n });\n }\n }, [\n deletingLink,\n deleteLinkMutation,\n handleCloseDeleteDialog,\n onRefreshPreview,\n onToast,\n ]);\n\n const handleDragEnd = useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n if (over && active.id !== over.id) {\n const oldIndex = links.findIndex((l) => l.id === active.id);\n const newIndex = links.findIndex((l) => l.id === over.id);\n const reordered = arrayMove(links, oldIndex, newIndex);\n const payload = reordered.map((link, index) => ({\n id: link.id,\n order: index + 1,\n }));\n reorderLinksMutation.mutate(\n { payload, optimisticItems: reordered },\n {\n onSuccess: () => {\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to reorder buttons\", \"error\");\n },\n },\n );\n }\n },\n [links, reorderLinksMutation, onRefreshPreview, onToast],\n );\n\n return (\n <>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={onBack}>\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <h1 className=\"text-foreground text-xl font-bold\">Buttons</h1>\n </div>\n <Button size=\"sm\" onClick={handleOpenAddDialog}>\n <Plus className=\"mr-1 h-4 w-4\" />\n Add Button\n </Button>\n </div>\n\n {isLoading ? (\n <div className=\"space-y-2\">\n {Array.from({ length: 3 }).map((_, i) => (\n <div\n key={i}\n className=\"border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4\"\n >\n <Skeleton className=\"h-5 w-5\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-48\" />\n </div>\n <Skeleton className=\"hidden h-5 w-16 sm:block\" />\n <div className=\"flex gap-1\">\n <Skeleton className=\"h-8 w-8\" />\n <Skeleton className=\"h-8 w-8\" />\n </div>\n </div>\n ))}\n </div>\n ) : links.length === 0 ? (\n <Card className=\"p-6 text-center sm:p-8\">\n <p className=\"text-muted-foreground mb-4\">\n No buttons yet. Add custom link buttons to display on your MySite.\n </p>\n <Button size=\"sm\" onClick={handleOpenAddDialog}>\n <Plus className=\"mr-1 h-4 w-4\" />\n Add Button\n </Button>\n </Card>\n ) : (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext\n items={links.map((l) => l.id)}\n strategy={verticalListSortingStrategy}\n >\n <div className=\"space-y-2\">\n {links.map((link) => (\n <SortableButtonCard\n key={link.id}\n link={link}\n onEdit={handleOpenEditDialog}\n onDelete={handleOpenDeleteDialog}\n />\n ))}\n </div>\n </SortableContext>\n </DndContext>\n )}\n\n {/* Add/Edit Dialog */}\n <Dialog open={isAddEditDialogOpen} onOpenChange={setIsAddEditDialogOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {editingLink ? \"Edit Button\" : \"Add Button\"}\n </DialogTitle>\n </DialogHeader>\n <form\n onSubmit={handleButtonSubmit(onButtonSubmit)}\n className=\"space-y-4\"\n >\n <div className=\"space-y-2\">\n <Label htmlFor=\"text\">Button Text</Label>\n <Input\n id=\"text\"\n placeholder=\"Enter button text...\"\n {...register(\"text\")}\n className={buttonErrors.text ? \"border-destructive\" : \"\"}\n />\n {buttonErrors.text && (\n <p className=\"text-destructive text-sm\">\n {buttonErrors.text.message}\n </p>\n )}\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"url\">URL</Label>\n <Input\n id=\"url\"\n placeholder=\"https://example.com\"\n {...register(\"url\")}\n className={buttonErrors.url ? \"border-destructive\" : \"\"}\n />\n {buttonErrors.url && (\n <p className=\"text-destructive text-sm\">\n {buttonErrors.url.message}\n </p>\n )}\n </div>\n <DialogFooter className=\"flex justify-between\">\n {editingLink ? (\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={() => {\n handleCloseAddEditDialog();\n handleOpenDeleteDialog(editingLink);\n }}\n >\n <Trash2 className=\"mr-1 h-4 w-4\" />\n Delete\n </Button>\n ) : (\n <div />\n )}\n <div className=\"flex gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleCloseAddEditDialog}\n >\n Cancel\n </Button>\n <Button\n type=\"submit\"\n disabled={\n isButtonSubmitting ||\n createLinkMutation.isPending ||\n updateLinkMutation.isPending\n }\n >\n {isButtonSubmitting ||\n createLinkMutation.isPending ||\n updateLinkMutation.isPending\n ? \"Saving...\"\n : \"Save\"}\n </Button>\n </div>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n\n {/* Delete Confirmation Dialog */}\n <Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Delete Button</DialogTitle>\n </DialogHeader>\n <p className=\"text-muted-foreground\">\n Are you sure you want to delete the button &quot;\n {deletingLink?.text}&quot;? This action cannot be undone.\n </p>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleCloseDeleteDialog}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={handleConfirmDelete}\n disabled={deleteLinkMutation.isPending}\n >\n {deleteLinkMutation.isPending ? \"Deleting...\" : \"Delete\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","\"use client\";\nimport { useCallback, useState } from \"react\";\nimport { ArrowLeft, GripVertical, Trash2 } from \"lucide-react\";\nimport {\n Button,\n Card,\n Dialog,\n Skeleton,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n} from \"@fluid-app/ui-primitives\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport {\n useUserFavorites,\n useDeleteFavorite,\n useReorderFavorites,\n} from \"../../admin/hooks/use-mysite\";\nimport type { FetchClient } from \"@fluid-app/api-client-core\";\nimport type { MySiteFavorite } from \"../../shared/schemas/mysite.schema\";\n\nfunction SortableFavoriteCard({\n favorite,\n onDelete,\n}: {\n favorite: MySiteFavorite;\n onDelete: (favorite: MySiteFavorite) => void;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: favorite.id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n };\n\n const title =\n favorite.favoriteable?.title ?? favorite.favoriteable?.name ?? \"Untitled\";\n const imageUrl = favorite.favoriteable?.image_url;\n const type = favorite.favoriteable_type.replace(/([A-Z])/g, \" $1\").trim();\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n className={`border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4 ${\n isDragging ? \"opacity-50 shadow-lg\" : \"\"\n }`}\n >\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground cursor-grab touch-none\"\n aria-label=\"Drag to reorder\"\n {...attributes}\n {...listeners}\n >\n <GripVertical className=\"h-5 w-5\" />\n </button>\n\n <div className=\"bg-muted h-10 w-10 shrink-0 overflow-hidden rounded-md\">\n {imageUrl ? (\n <img\n src={imageUrl}\n alt={title}\n loading=\"lazy\"\n width={40}\n height={40}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"text-muted-foreground flex h-full w-full items-center justify-center text-xs\">\n N/A\n </div>\n )}\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-foreground truncate font-medium\">{title}</p>\n <p className=\"text-muted-foreground truncate text-sm\">{type}</p>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground hover:text-destructive\"\n onClick={() => onDelete(favorite)}\n aria-label=\"Remove favorite\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n\nexport function MySiteFavoritesEditor({\n onBack,\n onRefreshPreview,\n client,\n affiliateId,\n onToast,\n}: {\n onBack: () => void;\n onRefreshPreview?: () => void;\n client: FetchClient;\n affiliateId: number | null | undefined;\n onToast?: (message: string, type: \"success\" | \"error\") => void;\n}): React.JSX.Element {\n const { data: favorites = [], isLoading } = useUserFavorites(\n client,\n affiliateId,\n );\n const deleteFavoriteMutation = useDeleteFavorite(client, affiliateId);\n const reorderFavoritesMutation = useReorderFavorites(client, affiliateId);\n\n const [isDeleteFavoriteDialogOpen, setIsDeleteFavoriteDialogOpen] =\n useState(false);\n const [deletingFavorite, setDeletingFavorite] =\n useState<MySiteFavorite | null>(null);\n\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n }),\n );\n\n const handleOpenDeleteFavoriteDialog = useCallback(\n (favorite: MySiteFavorite) => {\n setDeletingFavorite(favorite);\n setIsDeleteFavoriteDialogOpen(true);\n },\n [],\n );\n\n const handleCloseDeleteFavoriteDialog = useCallback(() => {\n setIsDeleteFavoriteDialogOpen(false);\n setDeletingFavorite(null);\n }, []);\n\n const handleConfirmDeleteFavorite = useCallback(() => {\n if (deletingFavorite) {\n deleteFavoriteMutation.mutate(deletingFavorite.id, {\n onSuccess: () => {\n onToast?.(\"Content removed\", \"success\");\n handleCloseDeleteFavoriteDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to remove content\", \"error\");\n },\n });\n }\n }, [\n deletingFavorite,\n deleteFavoriteMutation,\n handleCloseDeleteFavoriteDialog,\n onRefreshPreview,\n onToast,\n ]);\n\n const handleFavoriteDragEnd = useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n if (over && active.id !== over.id) {\n const oldIndex = favorites.findIndex((f) => f.id === active.id);\n const newIndex = favorites.findIndex((f) => f.id === over.id);\n const reordered = arrayMove(favorites, oldIndex, newIndex);\n const payload = reordered.map((fav, index) => ({\n id: fav.id,\n order: index + 1,\n }));\n reorderFavoritesMutation.mutate(\n { payload, optimisticItems: reordered },\n {\n onSuccess: () => {\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to reorder content\", \"error\");\n },\n },\n );\n }\n },\n [favorites, reorderFavoritesMutation, onRefreshPreview, onToast],\n );\n\n return (\n <>\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={onBack}>\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <h1 className=\"text-foreground text-xl font-bold\">MySite Content</h1>\n </div>\n\n {isLoading ? (\n <div className=\"space-y-2\">\n {Array.from({ length: 3 }).map((_, i) => (\n <div\n key={i}\n className=\"border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4\"\n >\n <Skeleton className=\"h-5 w-5\" />\n <Skeleton className=\"h-10 w-10 rounded-md\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-20\" />\n </div>\n <Skeleton className=\"h-8 w-8\" />\n </div>\n ))}\n </div>\n ) : favorites.length === 0 ? (\n <Card className=\"p-6 text-center sm:p-8\">\n <p className=\"text-muted-foreground\">\n No featured content yet. Favorite products, media, or pages to\n display on your MySite.\n </p>\n </Card>\n ) : (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleFavoriteDragEnd}\n >\n <SortableContext\n items={favorites.map((f) => f.id)}\n strategy={verticalListSortingStrategy}\n >\n <div className=\"space-y-2\">\n {favorites.map((fav) => (\n <SortableFavoriteCard\n key={fav.id}\n favorite={fav}\n onDelete={handleOpenDeleteFavoriteDialog}\n />\n ))}\n </div>\n </SortableContext>\n </DndContext>\n )}\n\n {/* Delete Favorite Confirmation Dialog */}\n <Dialog\n open={isDeleteFavoriteDialogOpen}\n onOpenChange={setIsDeleteFavoriteDialogOpen}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Remove Content</DialogTitle>\n </DialogHeader>\n <p className=\"text-muted-foreground\">\n Are you sure you want to remove &quot;\n {deletingFavorite?.favoriteable?.title ??\n deletingFavorite?.favoriteable?.name ??\n \"this item\"}\n &quot; from your MySite? This action cannot be undone.\n </p>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleCloseDeleteFavoriteDialog}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={handleConfirmDeleteFavorite}\n disabled={deleteFavoriteMutation.isPending}\n >\n {deleteFavoriteMutation.isPending ? \"Removing...\" : \"Remove\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","\"use client\";\nimport { useState, useCallback, useMemo, useEffect, useRef } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { FetchClient } from \"@fluid-app/api-client-core\";\nimport { ArrowLeft, Camera } from \"lucide-react\";\nimport { Button, Card, Input, Label, Textarea } from \"@fluid-app/ui-primitives\";\nimport { useUpdateProfile } from \"../../admin/hooks/use-mysite\";\nimport type { MeProfile } from \"./types\";\n\nconst socialFields = [\n {\n name: \"linkedin\" as const,\n label: \"LinkedIn\",\n placeholder: \"https://linkedin.com/in/username\",\n },\n {\n name: \"facebook\" as const,\n label: \"Facebook\",\n placeholder: \"https://facebook.com/username\",\n },\n {\n name: \"twitter\" as const,\n label: \"X (Twitter)\",\n placeholder: \"https://x.com/username\",\n },\n {\n name: \"instagram\" as const,\n label: \"Instagram\",\n placeholder: \"https://instagram.com/username\",\n },\n {\n name: \"youtube\" as const,\n label: \"YouTube\",\n placeholder: \"https://youtube.com/@channel\",\n },\n {\n name: \"pinterest\" as const,\n label: \"Pinterest\",\n placeholder: \"https://pinterest.com/username\",\n },\n {\n name: \"tiktok\" as const,\n label: \"TikTok\",\n placeholder: \"https://tiktok.com/@username\",\n },\n {\n name: \"whatsapp\" as const,\n label: \"WhatsApp\",\n placeholder: \"Phone number or link\",\n },\n { name: \"wechat\" as const, label: \"WeChat\", placeholder: \"WeChat ID\" },\n] as const;\n\ntype SocialFieldName = (typeof socialFields)[number][\"name\"];\n\ntype ProfileFormState = {\n bio: string;\n} & Record<SocialFieldName, string>;\n\nexport function MySiteProfileForm({\n client,\n onBack,\n onToast,\n onUploadPhoto,\n avatarUrl,\n userName,\n userInitial,\n}: {\n client: FetchClient;\n onBack: () => void;\n onToast?: (message: string, type: \"success\" | \"error\") => void;\n onUploadPhoto?: (file: File) => Promise<string>;\n avatarUrl?: string | null;\n userName?: string | null;\n userInitial?: string | null;\n}): React.JSX.Element {\n const queryClient = useQueryClient();\n const { data: meProfile, isLoading: isProfileLoading } = useQuery<MeProfile>({\n queryKey: [\"sdk-mysite\", \"me\"],\n queryFn: () => client.get<MeProfile>(\"/me.json\"),\n });\n\n const updateProfileMutation = useUpdateProfile(client);\n\n const initialFormState = useMemo<ProfileFormState>(\n () => ({\n bio: meProfile?.bio ?? \"\",\n linkedin: meProfile?.linkedin ?? \"\",\n facebook: meProfile?.facebook ?? \"\",\n twitter: meProfile?.twitter ?? \"\",\n instagram: meProfile?.instagram ?? \"\",\n youtube: meProfile?.youtube ?? \"\",\n pinterest: meProfile?.pinterest ?? \"\",\n tiktok: meProfile?.tiktok ?? \"\",\n whatsapp: meProfile?.whatsapp ?? \"\",\n wechat: meProfile?.wechat ?? \"\",\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [meProfile?.id],\n );\n\n const [formState, setFormState] = useState<ProfileFormState>(\n () => initialFormState,\n );\n\n const profileSyncedRef = useRef(false);\n useEffect(() => {\n if (meProfile && !profileSyncedRef.current) {\n profileSyncedRef.current = true;\n setFormState({\n bio: meProfile.bio ?? \"\",\n linkedin: meProfile.linkedin ?? \"\",\n facebook: meProfile.facebook ?? \"\",\n twitter: meProfile.twitter ?? \"\",\n instagram: meProfile.instagram ?? \"\",\n youtube: meProfile.youtube ?? \"\",\n pinterest: meProfile.pinterest ?? \"\",\n tiktok: meProfile.tiktok ?? \"\",\n whatsapp: meProfile.whatsapp ?? \"\",\n wechat: meProfile.wechat ?? \"\",\n });\n }\n }, [meProfile]);\n\n const isDirty =\n formState.bio !== initialFormState.bio ||\n formState.linkedin !== initialFormState.linkedin ||\n formState.facebook !== initialFormState.facebook ||\n formState.twitter !== initialFormState.twitter ||\n formState.instagram !== initialFormState.instagram ||\n formState.youtube !== initialFormState.youtube ||\n formState.pinterest !== initialFormState.pinterest ||\n formState.tiktok !== initialFormState.tiktok ||\n formState.whatsapp !== initialFormState.whatsapp ||\n formState.wechat !== initialFormState.wechat;\n\n const handleFieldChange = useCallback(\n (field: keyof ProfileFormState, value: string) => {\n setFormState((s) => ({ ...s, [field]: value }));\n },\n [],\n );\n\n const handleSave = useCallback(() => {\n updateProfileMutation.mutate(\n {\n bio: formState.bio,\n linkedin: formState.linkedin,\n facebook: formState.facebook,\n twitter: formState.twitter,\n instagram: formState.instagram,\n youtube: formState.youtube,\n pinterest: formState.pinterest,\n tiktok: formState.tiktok,\n whatsapp: formState.whatsapp,\n wechat: formState.wechat,\n },\n {\n onSuccess: () => {\n profileSyncedRef.current = false;\n queryClient.invalidateQueries({ queryKey: [\"sdk-mysite\", \"me\"] });\n onToast?.(\"Profile updated successfully\", \"success\");\n },\n onError: () => {\n onToast?.(\"Failed to update profile\", \"error\");\n },\n },\n );\n }, [formState, updateProfileMutation, queryClient, onToast]);\n\n // Avatar upload handling\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isUploadingPhoto, setIsUploadingPhoto] = useState(false);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n\n useEffect(() => {\n return () => {\n if (previewUrl) URL.revokeObjectURL(previewUrl);\n };\n }, [previewUrl]);\n\n const handleFileSelected = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file || !onUploadPhoto) return;\n\n if (!file.type.startsWith(\"image/\")) {\n onToast?.(\"Please select an image file\", \"error\");\n return;\n }\n\n setPreviewUrl(URL.createObjectURL(file));\n setIsUploadingPhoto(true);\n\n try {\n const imageUrl = await onUploadPhoto(file);\n updateProfileMutation.mutate(\n { image_url: imageUrl },\n {\n onSuccess: () => {\n onToast?.(\"Profile photo updated\", \"success\");\n },\n onError: () => {\n setPreviewUrl(null);\n onToast?.(\"Failed to save profile photo\", \"error\");\n },\n },\n );\n } catch {\n setPreviewUrl(null);\n onToast?.(\"Failed to upload photo\", \"error\");\n } finally {\n setIsUploadingPhoto(false);\n if (fileInputRef.current) fileInputRef.current.value = \"\";\n }\n },\n [onUploadPhoto, updateProfileMutation, onToast],\n );\n\n if (isProfileLoading) {\n return (\n <div className=\"flex h-full items-center justify-center\">\n <div className=\"text-muted-foreground animate-pulse\">Loading...</div>\n </div>\n );\n }\n\n const displayAvatarUrl = previewUrl || avatarUrl;\n\n return (\n <div className=\"space-y-4 p-4 sm:space-y-6 sm:p-6\">\n {/* Header */}\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={onBack}\n className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex h-10 w-10 items-center justify-center rounded-full transition-colors\"\n aria-label=\"Go back\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n <h1 className=\"text-foreground text-xl font-bold sm:text-2xl\">\n Profile\n </h1>\n </div>\n\n {/* Avatar Section (optional) */}\n {onUploadPhoto && (\n <Card className=\"p-4 sm:p-6\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handleFileSelected}\n />\n <div className=\"flex flex-col items-center gap-3 sm:flex-row sm:gap-4\">\n <div className=\"relative h-[120px] w-[120px] shrink-0 overflow-hidden rounded-full bg-gray-200\">\n {displayAvatarUrl ? (\n <img\n src={displayAvatarUrl}\n alt={userName || \"Profile\"}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"bg-background text-foreground flex h-full w-full items-center justify-center text-xl font-semibold\">\n {userInitial || \"U\"}\n </div>\n )}\n {isUploadingPhoto && (\n <div className=\"absolute inset-0 flex items-center justify-center rounded-full bg-black/40\">\n <div className=\"border-t-primary h-6 w-6 animate-spin rounded-full border-2 border-white\" />\n </div>\n )}\n </div>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => fileInputRef.current?.click()}\n disabled={isUploadingPhoto}\n >\n <Camera className=\"mr-1 h-4 w-4\" />\n {isUploadingPhoto ? \"Uploading...\" : \"Change Photo\"}\n </Button>\n </div>\n </Card>\n )}\n\n {/* Bio Section */}\n <Card className=\"p-4 sm:p-6\">\n <h2 className=\"text-foreground mb-4 text-base font-semibold sm:text-lg\">\n Bio\n </h2>\n <div className=\"space-y-2\">\n <Label htmlFor=\"profile-bio\">About you</Label>\n <Textarea\n id=\"profile-bio\"\n rows={4}\n value={formState.bio}\n onChange={(e) => handleFieldChange(\"bio\", e.target.value)}\n placeholder=\"Tell people a little about yourself...\"\n />\n </div>\n </Card>\n\n {/* Social Media Links Section */}\n <Card className=\"p-4 sm:p-6\">\n <h2 className=\"text-foreground mb-4 text-base font-semibold sm:text-lg\">\n Social Media Links\n </h2>\n <div className=\"space-y-4\">\n {socialFields.map((field) => (\n <div key={field.name} className=\"space-y-2\">\n <Label htmlFor={`profile-${field.name}`}>{field.label}</Label>\n <Input\n id={`profile-${field.name}`}\n type=\"text\"\n value={formState[field.name]}\n onChange={(e) => handleFieldChange(field.name, e.target.value)}\n placeholder={field.placeholder}\n />\n </div>\n ))}\n </div>\n </Card>\n\n {/* Save Button */}\n <div className=\"flex justify-end\">\n <Button\n onClick={handleSave}\n disabled={!isDirty || updateProfileMutation.isPending}\n className=\"w-full sm:w-auto\"\n >\n {updateProfileMutation.isPending ? \"Saving...\" : \"Save Changes\"}\n </Button>\n </div>\n </div>\n );\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { FetchClient } from \"@fluid-app/api-client-core\";\nimport {\n useMySiteThemes,\n useUpdateMySite,\n} from \"@fluid-app/mysite-ui/admin/hooks/use-mysite\";\nimport type { MysiteTheme } from \"@fluid-app/mysite-ui/shared/schemas/mysite-theme.schema\";\nimport {\n type AnimPhase,\n type EditingSection,\n FADE_MS,\n SLIDE_MS,\n getContentStyle,\n getPreviewStyle,\n MySiteVisitorDetailsCard,\n MySitePhonePreview,\n MySiteLinkCard,\n MySiteThemeEditor,\n MySiteButtonsEditor,\n MySiteFavoritesEditor,\n} from \"@fluid-app/mysite-ui/portal/components\";\nimport type { MeProfile } from \"@fluid-app/mysite-ui/portal/components\";\nimport { ChevronRight, User, Link2, Palette, LayoutGrid } from \"lucide-react\";\nimport { useAppNavigation } from \"../../shell/AppNavigationContext\";\n\ntype NavLinkItem = {\n label: string;\n slug: string;\n icon: typeof User;\n};\ntype NavActionItem = {\n label: string;\n key: \"theme\" | \"buttons\" | \"content\";\n icon: typeof User;\n};\ntype NavItem = NavLinkItem | NavActionItem;\n\nconst navigationItems: NavItem[] = [\n { label: \"Profile\", slug: \"my-site/profile\", icon: User },\n { label: \"Theme\", key: \"theme\", icon: Palette },\n { label: \"MySite Content\", key: \"content\", icon: LayoutGrid },\n { label: \"Buttons\", key: \"buttons\", icon: Link2 },\n];\n\nfunction defaultToast(message: string, type: \"success\" | \"error\") {\n if (type === \"error\") console.warn(\"[MySite]\", message);\n else console.info(\"[MySite]\", message);\n}\n\nexport function MySiteMainView({\n client,\n}: {\n client: FetchClient;\n}): React.JSX.Element {\n const { navigate } = useAppNavigation();\n\n const [animPhase, setAnimPhase] = useState<AnimPhase>(\"idle\");\n const [editingSection, setEditingSection] = useState<EditingSection>(null);\n const timeoutsRef = useRef<ReturnType<typeof setTimeout>[]>([]);\n\n useEffect(() => {\n const ref = timeoutsRef;\n return () => ref.current.forEach(clearTimeout);\n }, []);\n\n const cancelScheduled = useCallback(() => {\n timeoutsRef.current.forEach(clearTimeout);\n timeoutsRef.current = [];\n }, []);\n\n const schedule = useCallback((phase: AnimPhase, delay: number) => {\n const id = setTimeout(() => setAnimPhase(phase), delay);\n timeoutsRef.current.push(id);\n }, []);\n\n const showEditContent = [\n \"slide\",\n \"fade-in\",\n \"editing\",\n \"exit-fade-out\",\n \"exit-slide\",\n ].includes(animPhase);\n\n // Data fetching\n const { data: meProfile, isLoading: isUserLoading } = useQuery<MeProfile>({\n queryKey: [\"sdk-mysite\", \"me\"],\n queryFn: () => client.get<MeProfile>(\"/me.json\"),\n });\n\n const queryClient = useQueryClient();\n const { data: themes = [] } = useMySiteThemes(client);\n const updateMySiteMutation = useUpdateMySite(client);\n\n const [previewKey, setPreviewKey] = useState(0);\n const refreshPreview = useCallback(() => setPreviewKey((k) => k + 1), []);\n\n const [selectedThemeId, setSelectedThemeId] = useState<number | null>(null);\n\n const resolvedThemeId =\n selectedThemeId ??\n meProfile?.mysite_theme_id ??\n meProfile?.mysite_theme?.id ??\n themes.find((t) => t.name === \"Default\")?.id ??\n themes[0]?.id ??\n null;\n\n const currentTheme = themes.find((t) => t.id === resolvedThemeId);\n const themeName = currentTheme?.name ?? \"Default\";\n\n const mysiteUrl = meProfile?.mysite_url ?? \"\";\n const displayUrl = mysiteUrl ? mysiteUrl.replace(/^https?:\\/\\//, \"\") : \"\";\n const views = meProfile?.mysite_views ?? 0;\n const leads = meProfile?.mysite_leads ?? 0;\n\n const handleSelectTheme = useCallback(\n (theme: MysiteTheme) => {\n if (theme.id === resolvedThemeId) return;\n const previousThemeId = selectedThemeId;\n setSelectedThemeId(theme.id);\n updateMySiteMutation.mutate(\n { theme_id: theme.id },\n {\n onSuccess: () => {\n defaultToast(`Theme changed to \"${theme.name}\"`, \"success\");\n refreshPreview();\n },\n onError: () => {\n setSelectedThemeId(previousThemeId);\n defaultToast(\"Failed to update theme\", \"error\");\n },\n },\n );\n },\n [resolvedThemeId, selectedThemeId, updateMySiteMutation, refreshPreview],\n );\n\n const handleUpdateSlug = useCallback(\n async (slug: string) => {\n await new Promise<void>((resolve, reject) => {\n updateMySiteMutation.mutate(\n { username: slug },\n {\n onSuccess: () => resolve(),\n onError: () => reject(new Error(\"Failed\")),\n },\n );\n });\n await queryClient.refetchQueries({ queryKey: [\"sdk-mysite\", \"me\"] });\n },\n [updateMySiteMutation, queryClient],\n );\n\n const handleEditSection = useCallback(\n (section: EditingSection) => {\n cancelScheduled();\n setEditingSection(section);\n setAnimPhase(\"fade-out\");\n schedule(\"slide\", FADE_MS);\n schedule(\"fade-in\", FADE_MS + SLIDE_MS);\n schedule(\"editing\", FADE_MS + SLIDE_MS + FADE_MS);\n },\n [cancelScheduled, schedule],\n );\n\n const handleBackClick = useCallback(() => {\n cancelScheduled();\n setAnimPhase(\"exit-fade-out\");\n schedule(\"exit-slide\", FADE_MS);\n schedule(\"exit-fade-in\", FADE_MS + SLIDE_MS);\n const id = setTimeout(\n () => {\n setAnimPhase(\"idle\");\n setEditingSection(null);\n },\n FADE_MS + SLIDE_MS + FADE_MS,\n );\n timeoutsRef.current.push(id);\n }, [cancelScheduled, schedule]);\n\n const handlePreview = useCallback(() => {\n if (mysiteUrl) window.open(`${mysiteUrl}?preview=true`, \"_blank\");\n }, [mysiteUrl]);\n\n const sectionLabel = useMemo(() => {\n if (editingSection === \"theme\") return \"Theme\";\n if (editingSection === \"buttons\") return \"Buttons\";\n if (editingSection === \"content\") return \"MySite Content\";\n return \"\";\n }, [editingSection]);\n\n if (isUserLoading) {\n return (\n <div className=\"flex h-full overflow-hidden px-2 py-6\">\n <div className=\"w-full px-4 2xl:w-2/3 2xl:shrink-0\">\n <div className=\"flex flex-col gap-5\">\n <div className=\"bg-muted h-7 w-32 animate-pulse rounded-md\" />\n <div className=\"bg-muted h-20 w-full animate-pulse rounded-lg\" />\n <div className=\"bg-muted h-16 w-full animate-pulse rounded-lg\" />\n <div className=\"bg-muted h-40 w-full animate-pulse rounded-lg\" />\n </div>\n </div>\n <div className=\"hidden w-1/3 shrink-0 overflow-y-hidden px-4 2xl:block\">\n <div className=\"bg-muted flex h-full flex-col items-center gap-4 rounded-xl p-5\">\n <div className=\"flex w-full items-center justify-between\">\n <div className=\"space-y-1\">\n <div className=\"bg-background/50 h-3 w-24 animate-pulse rounded\" />\n <div className=\"bg-background/50 h-4 w-28 animate-pulse rounded\" />\n </div>\n <div className=\"bg-background/50 h-8 w-20 animate-pulse rounded-md\" />\n </div>\n <div className=\"bg-background/50 h-[580px] w-[280px] animate-pulse rounded-[36px]\" />\n </div>\n </div>\n </div>\n );\n }\n\n const contentStyle = getContentStyle(animPhase);\n const previewStyle = getPreviewStyle(animPhase);\n\n return (\n <div className=\"flex h-full overflow-hidden px-2 py-6\">\n {/* Content column */}\n <div className=\"w-full px-4 2xl:w-2/3 2xl:shrink-0\" style={contentStyle}>\n <div className=\"flex h-full min-w-0 flex-col gap-5 overflow-y-auto\">\n {showEditContent && editingSection === \"theme\" ? (\n <MySiteThemeEditor\n themes={themes}\n selectedThemeId={resolvedThemeId}\n onSelectTheme={handleSelectTheme}\n isPending={updateMySiteMutation.isPending}\n onBack={handleBackClick}\n />\n ) : showEditContent && editingSection === \"buttons\" ? (\n <MySiteButtonsEditor\n onBack={handleBackClick}\n onRefreshPreview={refreshPreview}\n client={client}\n userId={meProfile?.id}\n onToast={defaultToast}\n />\n ) : showEditContent && editingSection === \"content\" ? (\n <MySiteFavoritesEditor\n onBack={handleBackClick}\n onRefreshPreview={refreshPreview}\n client={client}\n affiliateId={meProfile?.affiliate_id}\n onToast={defaultToast}\n />\n ) : (\n <>\n {/* Header with optional back-to-section label */}\n <div className=\"flex items-center gap-2\">\n <h1 className=\"text-foreground text-xl font-bold\">MySite</h1>\n {animPhase !== \"idle\" && sectionLabel && (\n <>\n <ChevronRight className=\"text-muted-foreground h-4 w-4\" />\n <span className=\"text-foreground text-xl font-bold\">\n {sectionLabel}\n </span>\n </>\n )}\n </div>\n\n <MySiteVisitorDetailsCard views={views} leads={leads} />\n\n <MySiteLinkCard\n mysiteUrl={mysiteUrl}\n displayUrl={displayUrl}\n onUpdateSlug={handleUpdateSlug}\n onToast={defaultToast}\n />\n\n <div className=\"border-border bg-card divide-border divide-y overflow-hidden rounded-lg border\">\n {navigationItems.map((item) => {\n const Icon = item.icon;\n const rowClassName =\n \"group hover:bg-muted flex w-full items-center gap-2.5 px-3 py-2.5 transition-colors text-left cursor-pointer\";\n\n return (\n <button\n key={item.label}\n type=\"button\"\n onClick={() => {\n if (\"key\" in item) handleEditSection(item.key);\n else navigate(item.slug);\n }}\n className={rowClassName}\n >\n <div className=\"bg-muted text-foreground flex h-7 w-7 shrink-0 items-center justify-center rounded-full\">\n <Icon className=\"h-3.5 w-3.5\" />\n </div>\n <span className=\"text-foreground flex-1 text-sm font-medium\">\n {item.label}\n </span>\n <ChevronRight className=\"text-muted-foreground h-3 w-3 shrink-0 transition-transform group-hover:translate-x-0.5\" />\n </button>\n );\n })}\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* Preview column */}\n <div\n className=\"hidden w-1/3 shrink-0 overflow-y-hidden px-4 2xl:block\"\n style={previewStyle}\n >\n <MySitePhonePreview\n mysiteUrl={mysiteUrl}\n themeName={themeName}\n previewKey={previewKey}\n isUpdating={updateMySiteMutation.isPending}\n onPreview={handlePreview}\n />\n </div>\n </div>\n );\n}\n","import type { FetchClient } from \"@fluid-app/api-client-core\";\nimport { MySiteProfileForm } from \"@fluid-app/mysite-ui/portal/components\";\nimport { useAppNavigation } from \"../../shell/AppNavigationContext\";\n\nfunction defaultToast(message: string, type: \"success\" | \"error\") {\n if (type === \"error\") console.warn(\"[MySite]\", message);\n else console.info(\"[MySite]\", message);\n}\n\nexport function MySiteProfileView({\n client,\n}: {\n client: FetchClient;\n}): React.JSX.Element {\n const { navigate } = useAppNavigation();\n return (\n <MySiteProfileForm\n client={client}\n onBack={() => navigate(\"my-site\")}\n onToast={defaultToast}\n />\n );\n}\n","import React, { useMemo } from \"react\";\nimport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@fluid-app/ui-primitives\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport type { WidgetPropertySchema } from \"../../registries/property-schema-types\";\nimport { usePortalMySiteClient } from \"../../mysite/use-portal-mysite-client\";\nimport { useAppNavigation } from \"../../shell/AppNavigationContext\";\nimport { MySiteMainView } from \"./MySiteMainView\";\nimport { MySiteProfileView } from \"./MySiteProfileView\";\nimport type { MySiteScreenProps } from \"./types\";\n\nexport type { MySiteScreenProps } from \"./types\";\nexport type { MeProfile } from \"./types\";\n\nexport function MySiteScreen({\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}: MySiteScreenProps): React.JSX.Element {\n const client = usePortalMySiteClient();\n const { currentSlug, navigate } = useAppNavigation();\n const subRoute = currentSlug.split(\"/\")[1] ?? null;\n const isProfileView = subRoute === \"profile\";\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n {isProfileView ? (\n <BreadcrumbLink\n href=\"#\"\n onClick={(e: React.MouseEvent) => {\n e.preventDefault();\n navigate(\"my-site\");\n }}\n >\n My Site\n </BreadcrumbLink>\n ) : (\n <BreadcrumbPage className=\"font-semibold\">My Site</BreadcrumbPage>\n )}\n </BreadcrumbItem>\n {isProfileView && (\n <>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n Profile\n </BreadcrumbPage>\n </BreadcrumbItem>\n </>\n )}\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [isProfileView, navigate],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n return (\n <div {...divProps} className={`h-full ${divProps.className ?? \"\"}`}>\n {isProfileView ? (\n <MySiteProfileView client={client} />\n ) : (\n <MySiteMainView client={client} />\n )}\n </div>\n );\n}\n\nexport const mySiteScreenPropertySchema: WidgetPropertySchema = {\n widgetType: \"MySiteScreen\",\n displayName: \"My Site Screen\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"SubscriptionsScreen-Cu9Fc98m.mjs","names":["Table","SubscriptionsListScreen","portalTenant.subscriptions_list","portalTenant.subscriptions_show","portalTenant.subscriptions_pause","portalTenant.subscriptions_resume","portalTenant.subscriptions_skip","portalTenant.subscriptions_cancel","portalTenant.subscriptions_reactivate","portalTenant.subscriptions_update","SubscriptionsListScreenContent","SubscriptionDetailScreen","SubscriptionDetailScreenContent"],"sources":["../../../subscriptions/core/src/subscriptions-api-context.ts","../../../subscriptions/core/src/provider.tsx","../../../subscriptions/core/src/query-keys.ts","../../../subscriptions/core/src/hooks/use-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/utils/subscription-helpers.ts","../../../subscriptions/ui/src/lib/format.ts","../../../subscriptions/ui/src/lib/cn.ts","../../../subscriptions/ui/src/components/status-pill.tsx","../../../subscriptions/ui/src/components/subscriptions-list.tsx","../../../subscriptions/ui/src/screens/SubscriptionsListScreen.tsx","../../../subscriptions/api-client/src/portal-tenant-adapter.ts","../src/screens/SubscriptionsListScreen.tsx","../../../subscriptions/ui/src/components/confirm-dialog.tsx","../../../subscriptions/ui/src/components/subscription-detail.tsx","../../../subscriptions/ui/src/screens/SubscriptionDetailScreen.tsx","../src/screens/SubscriptionDetailScreen.tsx","../src/screens/SubscriptionsScreen.tsx"],"sourcesContent":["import { createContext, useContext } 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 = useContext(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 list: (params?: subscriptions.FetchSubscriptionsParams) =>\n [...subscriptionsKeys.all, \"list\", params] as const,\n detail: (token: string) =>\n [...subscriptionsKeys.all, \"detail\", token] as const,\n} as const;\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 { 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: 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\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 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 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\nexport function formatDate(\n dateString: string,\n isCancelled: boolean = false,\n): string {\n if (isCancelled) return \"Cancelled\";\n if (!dateString) return \"Paused\";\n\n const datePortion = dateString.split(\"T\")[0] ?? dateString;\n const parts = datePortion.split(\"-\");\n if (parts.length !== 3) return \"Invalid date\";\n\n const [year, month, day] = parts.map(Number);\n if (!year || !month || !day) return \"Invalid date\";\n const date = new Date(year, month - 1, day);\n\n const monthNames = [\n \"January\",\n \"February\",\n \"March\",\n \"April\",\n \"May\",\n \"June\",\n \"July\",\n \"August\",\n \"September\",\n \"October\",\n \"November\",\n \"December\",\n ];\n\n const dayNum = date.getDate();\n const monthName = monthNames[date.getMonth()];\n const yearNum = date.getFullYear();\n\n const ordinalSuffix = (d: number) => {\n if (d > 3 && d < 21) return \"th\";\n switch (d % 10) {\n case 1:\n return \"st\";\n case 2:\n return \"nd\";\n case 3:\n return \"rd\";\n default:\n return \"th\";\n }\n };\n\n return `${monthName} ${dayNum}${ordinalSuffix(dayNum)}, ${yearNum}`;\n}\n\nexport function getNextBillDisplay<\n T extends { status?: string; next_bill_date?: string | null },\n>(subscription: T | null | undefined): string {\n if (subscription?.status === \"cancelled\") return \"Cancelled\";\n if (subscription?.next_bill_date)\n return formatDate(subscription.next_bill_date);\n if (subscription?.status === \"paused\") return \"Paused\";\n return \"N/A\";\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","/**\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 * 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 next bill date string to M/D/YYYY (UTC).\n */\nexport function formatNextBillDate(nextBillDate: string): string {\n if (!nextBillDate) return \"N/A\";\n const date = new Date(nextBillDate);\n if (isNaN(date.getTime())) return \"N/A\";\n const month = date.getUTCMonth() + 1;\n const day = date.getUTCDate();\n const year = date.getUTCFullYear();\n return `${month}/${day}/${year}`;\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 { useState, useEffect, type JSX } from \"react\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport { useSubscriptions } from \"@fluid-app/subscriptions-core\";\nimport { TableColumn, PaginationFooter } from \"@fluid-app/orders-ui\";\nimport {\n Skeleton,\n Table,\n TableBody,\n TableCell,\n TableHeader,\n TableRow,\n ToggleGroup,\n ToggleGroupItem,\n} from \"@fluid-app/ui-primitives\";\nimport { SearchSort } from \"@fluid-app/ui-components/components/SearchSort\";\nimport { formatCurrency, startCase, formatNextBillDate } from \"../lib/format\";\nimport { StatusPill } from \"./status-pill\";\n\nexport interface SubscriptionsListProps {\n customerId: number | undefined;\n onSubscriptionClick: (subscriptionToken: string) => void;\n t: (key: string) => string;\n pageSize?: number;\n}\n\nexport function SubscriptionsList({\n customerId,\n onSubscriptionClick,\n t,\n pageSize = 10,\n}: SubscriptionsListProps): JSX.Element {\n const [currentPage, setCurrentPage] = useState(1);\n const [statusFilter, setStatusFilter] = useState<string | null>(null);\n const [search, setSearch] = useState<string | null>(null);\n const [sortBy, setSortBy] = useState<{\n column: string;\n direction: \"asc\" | \"desc\";\n }>({\n column: \"next_bill_date\",\n direction: \"desc\",\n });\n\n const params: subscriptions.FetchSubscriptionsParams = {\n customerId: customerId ?? 0,\n page: currentPage,\n perPage: pageSize,\n status: statusFilter,\n search,\n sortBy: sortBy.column,\n sortDirection: sortBy.direction,\n };\n\n const { data, isLoading } = useSubscriptions(params, {\n enabled: !!customerId,\n });\n\n // Reset page when filters change\n useEffect(() => {\n setCurrentPage(1);\n }, [statusFilter, search, sortBy]);\n\n const items = data?.subscriptions ?? [];\n const totalItems = data?.meta?.pagination?.total_count ?? 0;\n const totalPages = data?.meta?.pagination?.total_pages ?? 1;\n\n const handleSubscriptionClick = (token: string) => {\n if (token) {\n onSubscriptionClick(token);\n }\n };\n\n return (\n <div className=\"border-border overflow-hidden rounded-lg border shadow-sm\">\n {/* header: filter tabs + search */}\n <div className=\"flex flex-col gap-2 p-3 sm:flex-row sm:items-center sm:justify-between\">\n <ToggleGroup\n type=\"single\"\n value={statusFilter ?? \"all\"}\n onValueChange={(v) => {\n if (v) setStatusFilter(v === \"all\" ? null : v);\n }}\n variant=\"ghost\"\n >\n <ToggleGroupItem value=\"all\">{t(\"all\")}</ToggleGroupItem>\n <ToggleGroupItem value=\"active\">{t(\"active\")}</ToggleGroupItem>\n <ToggleGroupItem value=\"inactive\">{t(\"inactive\")}</ToggleGroupItem>\n </ToggleGroup>\n <div className=\"w-full max-w-sm\">\n <SearchSort\n searchValue={search ?? \"\"}\n onSearchChange={(v) => setSearch(v || null)}\n placeholder={t(\"search_subscriptions\")}\n />\n </div>\n </div>\n\n {/* mobile view */}\n <div className=\"block md:hidden\">\n {isLoading ? (\n Array(5)\n .fill(0)\n .map((_, index) => (\n <div\n key={`skeleton-${index}`}\n className=\"border-border border-b p-4\"\n >\n <div className=\"flex space-x-3\">\n <Skeleton className=\"h-12 w-12 rounded-md\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n </div>\n </div>\n ))\n ) : items.length === 0 ? (\n <div className=\"text-muted-foreground px-3 py-8 text-center text-sm\">\n {t(\"no_subscriptions_found\")}\n </div>\n ) : (\n items.map((subscription) => (\n <div\n key={subscription.subscription_token}\n className=\"border-border hover:bg-accent cursor-pointer border-b p-4 transition-colors duration-200 ease-in-out last:border-b-0\"\n onClick={() =>\n handleSubscriptionClick(subscription.subscription_token)\n }\n >\n <div className=\"flex items-start space-x-3\">\n <img\n src={subscription.variant?.product?.image_url}\n alt={subscription.variant?.product?.title}\n width={48}\n height={48}\n className=\"h-12 w-12 flex-shrink-0 rounded-md object-cover\"\n />\n <div className=\"w-0 min-w-0 flex-1\">\n <p className=\"text-foreground truncate text-sm font-medium\">\n {subscription.variant?.product?.title}\n </p>\n <div className=\"mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-sm\">\n <div>\n <span className=\"text-muted-foreground block text-xs\">\n {t(\"next_bill_date\")}\n </span>\n <span className=\"text-muted-foreground\">\n {formatNextBillDate(subscription.next_bill_date ?? \"\")}\n </span>\n </div>\n <div>\n <span className=\"text-muted-foreground block text-xs\">\n {t(\"price\")}\n </span>\n <span className=\"text-foreground font-medium\">\n {formatCurrency(\n subscription.price * subscription.quantity,\n )}\n </span>\n </div>\n </div>\n <div className=\"mt-2\">\n <span className=\"text-muted-foreground block text-xs\">\n {t(\"status\")}\n </span>\n <StatusPill status={subscription.status}>\n {startCase(subscription.status) || t(\"unknown_status\")}\n </StatusPill>\n </div>\n </div>\n </div>\n </div>\n ))\n )}\n </div>\n\n {/* desktop view */}\n <div className=\"hidden md:block\">\n <Table className=\"min-w-full table-fixed\">\n <colgroup>\n <col className=\"w-[45%] min-w-[240px]\" />\n <col className=\"w-[20%] min-w-[100px]\" />\n <col className=\"w-[15%] min-w-[100px]\" />\n <col className=\"w-[20%] min-w-[100px]\" />\n </colgroup>\n <TableHeader className=\"bg-muted\">\n <TableRow className=\"hover:bg-muted h-10\">\n <TableColumn label={t(\"product\")} sortable={false} />\n <TableColumn\n label={t(\"next_bill_date\")}\n sortBy=\"next_bill_date\"\n sortData={sortBy}\n onSortClick={(value: string) =>\n setSortBy({\n column: value,\n direction: sortBy.direction === \"asc\" ? \"desc\" : \"asc\",\n })\n }\n />\n <TableColumn label={t(\"price\")} sortable={false} />\n <TableColumn label={t(\"status\")} sortable={false} />\n </TableRow>\n </TableHeader>\n <TableBody className=\"bg-background\">\n {isLoading ? (\n Array(5)\n .fill(0)\n .map((_, index) => (\n <TableRow key={`skeleton-${index}`}>\n <TableCell className=\"px-3 py-4\">\n <div className=\"flex items-center space-x-2\">\n <Skeleton className=\"h-9 w-9 rounded-md\" />\n <Skeleton className=\"h-4 w-32\" />\n </div>\n </TableCell>\n <TableCell className=\"px-3 py-4\">\n <Skeleton className=\"h-4 w-24\" />\n </TableCell>\n <TableCell className=\"px-3 py-4\">\n <Skeleton className=\"h-4 w-24\" />\n </TableCell>\n <TableCell className=\"px-3 py-4\">\n <Skeleton className=\"h-4 w-16\" />\n </TableCell>\n </TableRow>\n ))\n ) : items.length === 0 ? (\n <TableRow>\n <TableCell\n colSpan={4}\n className=\"text-muted-foreground px-3 py-8 text-center text-sm\"\n >\n {t(\"no_subscriptions_found\")}\n </TableCell>\n </TableRow>\n ) : (\n items.map((subscription) => (\n <TableRow\n key={subscription.subscription_token}\n className=\"cursor-pointer\"\n onClick={() =>\n handleSubscriptionClick(subscription.subscription_token)\n }\n >\n <TableCell className=\"text-muted-foreground flex max-w-[280px] items-center space-x-3 py-4 pr-3 pl-3 text-sm\">\n <img\n src={subscription.variant?.product?.image_url}\n alt={subscription.variant?.product?.title}\n width={48}\n height={48}\n className=\"h-12 w-12 flex-shrink-0 rounded-md object-cover\"\n />\n <span className=\"text-foreground truncate text-sm font-medium\">\n {subscription.variant?.product?.title}\n </span>\n </TableCell>\n <TableCell className=\"text-muted-foreground px-3 py-4 text-sm whitespace-nowrap\">\n {formatNextBillDate(subscription.next_bill_date ?? \"\")}\n </TableCell>\n <TableCell className=\"px-3 py-4 text-sm whitespace-nowrap\">\n <span className=\"text-muted-foreground\">\n {formatCurrency(\n subscription.price * subscription.quantity,\n )}\n </span>\n </TableCell>\n <TableCell className=\"px-3 py-4 text-sm whitespace-nowrap\">\n <StatusPill status={subscription.status}>\n {startCase(subscription.status) || t(\"unknown_status\")}\n </StatusPill>\n </TableCell>\n </TableRow>\n ))\n )}\n </TableBody>\n </Table>\n </div>\n\n <PaginationFooter\n currentPage={currentPage}\n totalPages={totalPages}\n pageSize={pageSize}\n totalItems={totalItems}\n onPageChange={setCurrentPage}\n t={t}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbPage,\n} from \"@fluid-app/ui-primitives\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { SubscriptionsList } from \"../components/subscriptions-list\";\n\nexport interface SubscriptionsListScreenProps {\n customerId: number | undefined;\n onSubscriptionClick: (subscriptionToken: string) => void;\n t: (key: string) => string;\n isLoadingCustomer?: boolean;\n}\n\nexport function SubscriptionsListScreen({\n customerId,\n onSubscriptionClick,\n t,\n isLoadingCustomer,\n}: SubscriptionsListScreenProps) {\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n Subscriptions\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n if (isLoadingCustomer) {\n return (\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 <div className=\"space-y-3\">\n <div className=\"bg-muted h-10 animate-pulse rounded\" />\n <div className=\"bg-muted h-64 animate-pulse rounded\" />\n </div>\n </div>\n );\n }\n\n return (\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 <SubscriptionsList\n customerId={customerId}\n onSubscriptionClick={onSubscriptionClick}\n t={t}\n />\n </div>\n );\n}\n","import type { SubscriptionsApi } from \"@fluid-app/subscriptions-core\";\nimport type { FetchClient } from \"./lib/fetch-client\";\nimport type { subscriptions } from \"./custom/subscriptions\";\nimport { portalTenant } from \"@fluid-app/portal-tenant-api-client\";\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 = Awaited<\n ReturnType<typeof portalTenant.subscriptions_show>\n>;\n\ntype BffListResponse = Awaited<\n ReturnType<typeof portalTenant.subscriptions_list>\n>;\n\n/**\n * Maps a BFF subscription detail response to the port's SubscriptionDetail.\n *\n * The BFF returns a flat Subscription schema while the port expects a richly\n * nested SubscriptionDetailSubscription. Both represent the same underlying\n * data — the consuming portal UI only accesses the subset of fields the BFF\n * provides. The explicit field mapping ensures the envelope structure is\n * correct, while the subscription data passes through at runtime.\n */\nfunction mapSubscriptionDetail(\n response: BffSubscriptionResponse,\n): subscriptions.SubscriptionDetail {\n return {\n subscription: (response.subscription ??\n {}) as unknown as subscriptions.SubscriptionDetailSubscription,\n meta: response.meta ? mapMeta(response.meta) : undefined,\n };\n}\n\nfunction mapSubscriptionList(\n response: BffListResponse,\n): subscriptions.SubscriptionsResponse {\n return {\n subscriptions: (response.subscriptions ??\n []) as unknown as subscriptions.SubscriptionListItem[],\n meta: mapMeta(response.meta ?? {}),\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: FetchClient,\n): SubscriptionsApi {\n return {\n fetchCustomerSubscriptions: async (\n params: subscriptions.FetchSubscriptionsParams,\n ) => {\n const response = await portalTenant.subscriptions_list(client, {\n \"page[cursor]\": params.cursor,\n \"page[limit]\": params.limit ?? params.perPage,\n });\n return mapSubscriptionList(response);\n },\n\n fetchSubscription: async (subscriptionToken: string) => {\n const response = await portalTenant.subscriptions_show(\n client,\n subscriptionToken,\n );\n return mapSubscriptionDetail(response);\n },\n\n pauseSubscription: async (\n subscriptionToken: string,\n _params: subscriptions.PauseSubscriptionParams,\n ) => {\n const response = await portalTenant.subscriptions_pause(\n client,\n subscriptionToken,\n );\n return mapSubscriptionDetail(response);\n },\n\n resumeSubscription: async (\n subscriptionToken: string,\n _params: subscriptions.ResumeSubscriptionParams,\n ) => {\n const response = await portalTenant.subscriptions_resume(\n client,\n subscriptionToken,\n );\n return mapSubscriptionDetail(response);\n },\n\n skipSubscription: async (\n subscriptionToken: string,\n _params: subscriptions.SkipSubscriptionParams,\n ) => {\n const response = await portalTenant.subscriptions_skip(\n client,\n subscriptionToken,\n );\n return mapSubscriptionDetail(response);\n },\n\n cancelSubscription: async (\n subscriptionToken: string,\n _customerId?: number,\n ) => {\n const response = await portalTenant.subscriptions_cancel(\n client,\n subscriptionToken,\n );\n return mapSubscriptionDetail(response);\n },\n\n reactivateSubscription: async (\n subscriptionToken: string,\n _params: subscriptions.ReactivateSubscriptionParams,\n ) => {\n const response = await portalTenant.subscriptions_reactivate(\n client,\n subscriptionToken,\n );\n return mapSubscriptionDetail(response);\n },\n\n updateSubscriptionInfo: async (\n subscriptionToken: string,\n body: Pick<subscriptions.UpdateSubscriptionInfoBody, \"payment_method_id\">,\n ) => {\n const response = await portalTenant.subscriptions_update(\n client,\n subscriptionToken,\n { subscription: { payment_method_id: body.payment_method_id } },\n );\n return mapSubscriptionDetail(response);\n },\n };\n}\n","import { useMemo } from \"react\";\nimport { SubscriptionsCoreProvider } from \"@fluid-app/subscriptions-core\";\nimport { SubscriptionsListScreen as SubscriptionsListScreenContent } from \"@fluid-app/subscriptions-ui/screens/SubscriptionsListScreen\";\nimport { createPortalSubscriptionsAdapter } from \"@fluid-app/subscriptions-api-client\";\nimport { usePortalTenantClient } from \"../providers/PortalTenantClientProvider\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\n\nconst translations: Record<string, string> = {\n all: \"All\",\n active: \"Active\",\n inactive: \"Inactive\",\n search: \"Search\",\n subscriptions: \"Search subscriptions...\",\n product: \"Product\",\n next_bill_date: \"Next Bill Date\",\n price: \"Price\",\n status: \"Status\",\n no_subscriptions_found: \"No subscriptions found\",\n unknown_status: \"Unknown\",\n total: \"Total\",\n results: \"results\",\n previous: \"Previous\",\n next: \"Next\",\n pagination: \"Pagination\",\n};\n\ninterface SubscriptionsListScreenProps {\n customerId: number | undefined;\n isLoadingCustomer: boolean;\n}\n\nexport function SubscriptionsListScreen({\n customerId,\n isLoadingCustomer,\n}: SubscriptionsListScreenProps): React.JSX.Element {\n const client = usePortalTenantClient();\n const subscriptionsApi = useMemo(\n () => createPortalSubscriptionsAdapter(client),\n [client],\n );\n const { navigate } = useAppNavigation();\n\n return (\n <SubscriptionsCoreProvider api={subscriptionsApi}>\n <SubscriptionsListScreenContent\n customerId={customerId}\n isLoadingCustomer={isLoadingCustomer}\n onSubscriptionClick={(subscriptionToken) =>\n navigate(`subscriptions/${subscriptionToken}`)\n }\n t={(key) => translations[key] ?? key}\n />\n </SubscriptionsCoreProvider>\n );\n}\n","import { useState } from \"react\";\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogCancel,\n AlertDialogAction,\n} from \"@fluid-app/ui-primitives\";\n\ninterface ConfirmDialogProps {\n title: string;\n description: string;\n actionButtonText?: string;\n cancelButtonText?: string;\n open: boolean;\n setOpen: (open: boolean) => void;\n onConfirm: () => void | Promise<unknown>;\n}\n\nexport function ConfirmDialog({\n title,\n description,\n actionButtonText = \"Delete\",\n cancelButtonText = \"Cancel\",\n open,\n setOpen,\n onConfirm,\n}: ConfirmDialogProps) {\n const [isPending, setIsPending] = useState(false);\n\n const handleConfirm = async () => {\n try {\n const result = onConfirm();\n if (result instanceof Promise) {\n setIsPending(true);\n await result;\n }\n } catch (error) {\n console.error(\"ConfirmDialog: action rejected\", error);\n } finally {\n setIsPending(false);\n setOpen(false);\n }\n };\n\n return (\n <AlertDialog open={open} onOpenChange={(v) => !isPending && setOpen(v)}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>{title}</AlertDialogTitle>\n <AlertDialogDescription>{description}</AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={isPending}>\n {cancelButtonText}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={handleConfirm}\n disabled={isPending}\n className=\"bg-red-600 text-white hover:bg-red-500\"\n >\n {isPending ? \"...\" : actionButtonText}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n","import { useState, useEffect, useRef, type JSX } from \"react\";\nimport type { subscriptions } from \"@fluid-app/subscriptions-core\";\nimport {\n useSubscription,\n usePauseSubscription,\n useResumeSubscription,\n useSkipSubscription,\n useCancelSubscription,\n useReactivateSubscription,\n formatSubscriptionFrequency,\n formatDate,\n getNextBillDisplay,\n calculateNextBillDate,\n} from \"@fluid-app/subscriptions-core\";\nimport { SkipForward, Pause, Play, XCircle, RotateCcw } from \"lucide-react\";\nimport { Skeleton, Button } from \"@fluid-app/ui-primitives\";\nimport { ConfirmDialog } from \"./confirm-dialog\";\nimport { StatusPill } from \"./status-pill\";\nimport { startCase, formatCurrency } from \"../lib/format\";\n\nexport interface SubscriptionDetailProps {\n token: string;\n onNotFound?: () => void;\n onError?: (error: Error) => void;\n onSuccess?: (message: string) => void;\n onMutationError?: (message: string, error: unknown) => void;\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 space-x-4\">\n <Skeleton className=\"h-24 w-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\nfunction SubscriptionItemsSection({\n subscription,\n}: {\n subscription: subscriptions.SubscriptionDetailSubscription;\n}) {\n const variant = subscription.variant;\n const product = variant?.product;\n const quantity = subscription.quantity;\n const totalPrice = formatCurrency(subscription.price * quantity);\n const discount =\n subscription.original_price != null\n ? subscription.original_price - subscription.price\n : 0;\n const subtotal =\n discount > 0\n ? formatCurrency(subscription.original_price * quantity)\n : totalPrice;\n\n return (\n <section className=\"bg-muted flex w-full flex-col items-center px-8 lg:col-span-4\">\n <div className=\"flex w-full max-w-lg flex-col\">\n {/* Upcoming order summary */}\n <div className=\"mt-4\">\n <h2 className=\"text-foreground mb-2 text-lg font-medium\">\n 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 Next Order Date\n </div>\n <div className=\"text-foreground text-2xl font-bold\">\n {getNextBillDisplay(subscription)}\n </div>\n </div>\n <div className=\"pl-4\">\n <div className=\"text-muted-foreground mb-1 text-sm\">\n Next Bill Amount\n </div>\n <div className=\"text-foreground text-2xl font-bold\">\n {formatCurrency(subscription.price * quantity)}\n </div>\n </div>\n </div>\n <hr className=\"border-border mt-4\" />\n </div>\n </div>\n\n {/* Product row */}\n <div className=\"py-6\">\n <div className=\"flex flex-row items-center space-x-4\">\n <div className=\"flex min-w-0 flex-1 flex-row space-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 || \"Product image\"}\n width={96}\n height={96}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"text-muted-foreground flex h-full w-full items-center justify-center\">\n 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 space-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 </div>\n </div>\n\n {/* Pricing summary */}\n <div className=\"mb-4\">\n {discount > 0 && (\n <>\n <div className=\"flex justify-between text-sm\">\n <p className=\"text-muted-foreground text-sm font-medium\">\n Subtotal\n </p>\n <p className=\"text-muted-foreground text-sm font-medium\">\n {subtotal}\n </p>\n </div>\n <div className=\"mt-2 flex justify-between text-sm\">\n <p className=\"text-muted-foreground text-sm font-medium\">\n Discount\n </p>\n <p className=\"text-muted-foreground text-sm font-medium\">\n -{formatCurrency(discount * quantity)}\n </p>\n </div>\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\">Total</p>\n <p className=\"text-foreground text-base font-bold\">\n {formatCurrency(subscription.price * quantity)}\n </p>\n </div>\n <span className=\"text-muted-foreground text-xs\">\n *Tax and shipping calculated at checkout\n </span>\n </div>\n </div>\n </section>\n );\n}\n\n/* ── Right column: actions & details ───────────────────────────────── */\n\nfunction SubscriptionManagementSection({\n subscription,\n isActive,\n isPaused,\n isCancelled,\n isMutating,\n onSkip,\n onPause,\n onResume,\n onCancel,\n onReactivate,\n}: {\n subscription: subscriptions.SubscriptionDetailSubscription;\n isActive: boolean;\n isPaused: boolean;\n isCancelled: boolean;\n isMutating: boolean;\n onSkip: () => void;\n onPause: () => void;\n onResume: () => void;\n onCancel: () => void;\n onReactivate: () => void;\n}) {\n const plan = subscription.subscription_plan;\n const quantity = subscription.quantity;\n const totalPrice = formatCurrency(subscription.price * quantity);\n\n const paymentMethod = subscription.payment_method;\n const paymentDetails = paymentMethod?.details as {\n last4?: string;\n card_type?: string;\n logo_url?: string;\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 {/* Action Buttons */}\n <div className=\"border-border mb-6 border-b pb-6\">\n <h2 className=\"text-foreground mb-3 text-sm/6 font-semibold\">\n Order Actions\n </h2>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {isActive && plan.allow_skipping && (\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\">Skip Next Order</span>\n </Button>\n )}\n {isActive && (\n <Button\n variant=\"outline\"\n onClick={onPause}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <Pause className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">Pause Subscription</span>\n </Button>\n )}\n {isPaused && (\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\">Resume Subscription</span>\n </Button>\n )}\n <Button\n variant=\"outline\"\n onClick={onCancel}\n disabled={isMutating || isCancelled}\n className={actionButtonClass}\n >\n <XCircle className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">\n {isCancelled ? \"Cancelled\" : \"Cancel Subscription\"}\n </span>\n </Button>\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\">Reactivate Subscription</span>\n </Button>\n )}\n </div>\n </div>\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 Subscription Details\n </h3>\n <StatusPill status={subscription.status}>\n {startCase(subscription.status)}\n </StatusPill>\n </div>\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 Order Frequency\n </div>\n <div className=\"text-foreground font-medium\">\n {formatSubscriptionFrequency(plan.billing_interval_unit)}\n </div>\n </div>\n <div className=\"flex-1 px-4\">\n <div className=\"text-muted-foreground text-sm\">Next Payment</div>\n <div className=\"text-foreground font-medium\">{totalPrice}</div>\n </div>\n {subscription.last_bill_date && (\n <div className=\"flex-1 pl-4 text-right\">\n <div className=\"text-muted-foreground text-sm\">Last Billed</div>\n <div className=\"text-foreground font-medium\">\n {formatDate(subscription.last_bill_date)}\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Payment & Shipping */}\n <div className=\"pt-2\">\n <h3 className=\"text-foreground text-sm/6 font-semibold\">\n Payment & Shipping\n </h3>\n <div className=\"flex flex-col\">\n {/* Shipping Address */}\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 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 </div>\n </div>\n )}\n\n {/* Payment Method */}\n {paymentMethod && (\n <div className=\"border-border mb-6 border-b pb-4\">\n <div className=\"text-muted-foreground mb-1 text-sm\">\n Payment Method\n </div>\n <div className=\"text-foreground flex items-center gap-2 text-sm\">\n {paymentDetails?.logo_url && (\n <img\n src={paymentDetails.logo_url}\n alt={paymentDetails.card_type ?? \"Card\"}\n className=\"h-6\"\n />\n )}\n <span className=\"font-medium\">\n {paymentDetails?.card_type\n ? startCase(paymentDetails.card_type)\n : paymentMethod.payment_type}\n {paymentDetails?.last4\n ? ` ending in ${paymentDetails.last4}`\n : \"\"}\n </span>\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Order History */}\n {subscription.orders.length > 0 && (\n <div className=\"border-border mb-4 border-b pb-4\">\n <h3 className=\"text-foreground mb-3 text-sm/6 font-semibold\">\n Order History\n </h3>\n <div className=\"overflow-x-auto\">\n <table className=\"divide-border min-w-full divide-y text-sm\">\n <thead>\n <tr>\n <th className=\"text-muted-foreground py-2 pr-3 text-left font-medium\">\n Order\n </th>\n <th className=\"text-muted-foreground px-3 py-2 text-left font-medium\">\n Date\n </th>\n <th className=\"text-muted-foreground px-3 py-2 text-left font-medium\">\n Status\n </th>\n <th className=\"text-muted-foreground py-2 pl-3 text-right font-medium\">\n 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 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] ?? \"\")}\n </td>\n <td className=\"px-3 py-2\">\n <StatusPill status={order.status}>\n {startCase(order.status)}\n </StatusPill>\n </td>\n <td className=\"text-foreground py-2 pl-3 text-right\">\n {order.amount != null\n ? formatCurrency(Number(order.amount))\n : \"N/A\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n\n/* ── Main component ────────────────────────────────────────────────── */\n\nexport function SubscriptionDetail({\n token,\n onNotFound,\n onError,\n onSuccess,\n onMutationError,\n}: SubscriptionDetailProps): JSX.Element | null {\n const [showCancelModal, setShowCancelModal] = useState(false);\n\n const { data, isLoading, error } = useSubscription(token);\n const subscription = data?.subscription;\n const customerId = subscription?.customer?.id ?? 0;\n\n const pauseMutation = usePauseSubscription({\n onSuccess: () => onSuccess?.(\"Subscription paused\"),\n onError: (err: unknown) =>\n onMutationError?.(\"Failed to pause subscription\", err),\n });\n\n const resumeMutation = useResumeSubscription({\n onSuccess: () => onSuccess?.(\"Subscription resumed\"),\n onError: (err: unknown) =>\n onMutationError?.(\"Failed to resume subscription\", err),\n });\n\n const skipMutation = useSkipSubscription({\n onSuccess: () => onSuccess?.(\"Next billing skipped\"),\n onError: (err: unknown) => onMutationError?.(\"Failed to skip billing\", err),\n });\n\n const cancelMutation = useCancelSubscription({\n onSuccess: () => {\n onSuccess?.(\"Subscription cancelled\");\n setShowCancelModal(false);\n },\n onError: (err: unknown) =>\n onMutationError?.(\"Failed to cancel subscription\", err),\n });\n\n const reactivateMutation = useReactivateSubscription({\n onSuccess: () => onSuccess?.(\"Subscription reactivated\"),\n onError: (err: unknown) =>\n onMutationError?.(\"Failed to reactivate subscription\", err),\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 isActive = subscription.status === \"active\";\n const isPaused = subscription.status === \"paused\";\n const isCancelled = subscription.status === \"cancelled\";\n const isMutating =\n pauseMutation.isPending ||\n resumeMutation.isPending ||\n skipMutation.isPending ||\n cancelMutation.isPending ||\n reactivateMutation.isPending;\n\n const handlePause = () => {\n pauseMutation.mutate({\n subscriptionToken: token,\n pauseParams: { customerId },\n });\n };\n\n const handleResume = () => {\n const nextBillDate = calculateNextBillDate(\n plan.billing_interval,\n plan.billing_interval_unit,\n );\n resumeMutation.mutate({\n subscriptionToken: token,\n resumeParams: { customerId, nextBillDate },\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 reactivateMutation.mutate({\n subscriptionToken: token,\n reactivateParams: {},\n });\n };\n\n return (\n <>\n <div className=\"flex flex-col lg:grid lg:grid-cols-8\">\n <SubscriptionItemsSection subscription={subscription} />\n <SubscriptionManagementSection\n subscription={subscription}\n isActive={isActive}\n isPaused={isPaused}\n isCancelled={isCancelled}\n isMutating={isMutating}\n onSkip={handleSkip}\n onPause={handlePause}\n onResume={handleResume}\n onCancel={() => setShowCancelModal(true)}\n onReactivate={handleReactivate}\n />\n </div>\n <ConfirmDialog\n title=\"Cancel Subscription\"\n actionButtonText=\"Cancel Subscription\"\n description=\"Are you sure you want to cancel this subscription? You can reactivate it later.\"\n open={showCancelModal}\n setOpen={setShowCancelModal}\n onConfirm={handleCancel}\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) {\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\">Skip Next</span>\n </Button>\n )}\n <Button\n variant=\"outline\"\n onClick={onPause}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <Pause className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">Pause</span>\n </Button>\n <Button\n variant=\"outline\"\n onClick={onCancel}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <XCircle className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">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\">Resume</span>\n </Button>\n <Button\n variant=\"outline\"\n onClick={onCancel}\n disabled={isMutating}\n className={actionButtonClass}\n >\n <XCircle className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">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\">Reactivate</span>\n </Button>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@fluid-app/ui-primitives\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { SubscriptionDetail } from \"../components/subscription-detail\";\n\nexport interface SubscriptionDetailScreenProps {\n token: string;\n onNavigateToList: () => void;\n onNotFound?: () => void;\n onError?: (error: Error) => void;\n onSuccess?: (message: string) => void;\n onMutationError?: (message: string, error: unknown) => void;\n}\n\nexport function SubscriptionDetailScreen({\n token,\n onNavigateToList,\n onNotFound,\n onError,\n onSuccess,\n onMutationError,\n}: SubscriptionDetailScreenProps) {\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbLink\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n onNavigateToList();\n }}\n >\n Subscriptions\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n Subscription #{token}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [token, onNavigateToList],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n return (\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 />\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { SubscriptionsCoreProvider } from \"@fluid-app/subscriptions-core\";\nimport { SubscriptionDetailScreen as SubscriptionDetailScreenContent } from \"@fluid-app/subscriptions-ui/screens/SubscriptionDetailScreen\";\nimport { createPortalSubscriptionsAdapter } from \"@fluid-app/subscriptions-api-client\";\nimport { usePortalTenantClient } from \"../providers/PortalTenantClientProvider\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\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 client = usePortalTenantClient();\n const subscriptionsApi = useMemo(\n () => createPortalSubscriptionsAdapter(client),\n [client],\n );\n const { navigate } = useAppNavigation();\n\n return (\n <SubscriptionsCoreProvider api={subscriptionsApi}>\n <SubscriptionDetailScreenContent\n token={token}\n onNavigateToList={() => navigate(\"subscriptions\")}\n onNotFound={() => {\n onToast(\"Subscription not found\", \"warning\");\n navigate(\"subscriptions\");\n }}\n onError={(err) => {\n const message =\n err instanceof Error ? err.message : \"An error occurred\";\n onToast(`Failed to load subscription: ${message}`, \"error\");\n }}\n onSuccess={(message) => {\n onToast(message, \"success\");\n }}\n onMutationError={(message, err) => {\n const detail =\n err instanceof Error ? err.message : \"An error occurred\";\n onToast(`${message}: ${detail}`, \"error\");\n }}\n />\n </SubscriptionsCoreProvider>\n );\n}\n","import type { ComponentProps } from \"react\";\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 { SubscriptionsListScreen } from \"./SubscriptionsListScreen\";\nimport { SubscriptionDetailScreen } from \"./SubscriptionDetailScreen\";\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 if (type === \"error\" || type === \"warning\") {\n console.warn(\"[Subscriptions]\", message);\n } else {\n console.info(\"[Subscriptions]\", message);\n }\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 if (isDetailView) {\n return (\n <div {...divProps}>\n <SubscriptionDetailScreen\n token={detailToken}\n onToast={effectiveToast}\n />\n </div>\n );\n }\n\n if (isCustomerError && !isLoadingCustomer) {\n return (\n <div {...divProps}>\n <div className=\"text-muted-foreground px-4 py-8 text-center text-sm\">\n Unable to load account data. Please try again later.\n </div>\n </div>\n );\n }\n\n return (\n <div {...divProps}>\n <SubscriptionsListScreen\n customerId={customerId}\n isLoadingCustomer={isLoadingCustomer}\n />\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"],"mappings":"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"}