@fluid-app/portal-sdk 0.1.236 → 0.1.238
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{FluidProvider-BazvsIwu.mjs → FluidProvider-B3DjYoUW.mjs} +3 -3
- package/dist/{FluidProvider-BazvsIwu.mjs.map → FluidProvider-B3DjYoUW.mjs.map} +1 -1
- package/dist/{FluidProvider-Dxn7Ehiz.cjs → FluidProvider-DcpUKHrn.cjs} +3 -3
- package/dist/{FluidProvider-Dxn7Ehiz.cjs.map → FluidProvider-DcpUKHrn.cjs.map} +1 -1
- package/dist/{MessagingScreen-RItZgONw.mjs → MessagingScreen-BBqwXPZB.mjs} +2 -2
- package/dist/{MessagingScreen-RItZgONw.mjs.map → MessagingScreen-BBqwXPZB.mjs.map} +1 -1
- package/dist/{MessagingScreen-40YCQbX9.cjs → MessagingScreen-BzWV22JZ.cjs} +2 -2
- package/dist/{MessagingScreen-40YCQbX9.cjs.map → MessagingScreen-BzWV22JZ.cjs.map} +1 -1
- package/dist/{MessagingScreen-CrdiB4M3.cjs → MessagingScreen-CPBUg-32.cjs} +3 -3
- package/dist/{MySiteWidget-B0dc_7Dc.mjs → MySiteWidget-COj7yYQF.mjs} +22 -29
- package/dist/MySiteWidget-COj7yYQF.mjs.map +1 -0
- package/dist/{MySiteWidget-BkqAS0aY.cjs → MySiteWidget-DRH4q_YV.cjs} +22 -29
- package/dist/MySiteWidget-DRH4q_YV.cjs.map +1 -0
- package/dist/{ProfileScreen-CEKbhSRz.cjs → ProfileScreen-C0nmvuW1.cjs} +2 -2
- package/dist/{ProfileScreen-CEKbhSRz.cjs.map → ProfileScreen-C0nmvuW1.cjs.map} +1 -1
- package/dist/{ProfileScreen-CeD1jq89.mjs → ProfileScreen-CwQr_Km7.mjs} +2 -2
- package/dist/{ProfileScreen-CeD1jq89.mjs.map → ProfileScreen-CwQr_Km7.mjs.map} +1 -1
- package/dist/{ProfileScreen-Dex8VHSB.cjs → ProfileScreen-MCfnv8eT.cjs} +3 -3
- package/dist/{ShareablesScreen-Bt0E1aya.cjs → ShareablesScreen-A69L0Nok.cjs} +136 -108
- package/dist/ShareablesScreen-A69L0Nok.cjs.map +1 -0
- package/dist/{ShareablesScreen-LSyiDa6q.cjs → ShareablesScreen-BUYG-mjj.cjs} +1 -1
- package/dist/{ShareablesScreen-D3Hfqg9-.mjs → ShareablesScreen-sieWBlAl.mjs} +136 -108
- package/dist/ShareablesScreen-sieWBlAl.mjs.map +1 -0
- package/dist/{ShopScreen-Cgro0M1d.cjs → ShopScreen-Brw7gNMu.cjs} +3 -3
- package/dist/{ShopScreen-BiqZPyiB.cjs → ShopScreen-CiGozvW4.cjs} +2 -2
- package/dist/{ShopScreen-BiqZPyiB.cjs.map → ShopScreen-CiGozvW4.cjs.map} +1 -1
- package/dist/{ShopScreen-dAe71cdL.mjs → ShopScreen-D39WpS6j.mjs} +2 -2
- package/dist/{ShopScreen-dAe71cdL.mjs.map → ShopScreen-D39WpS6j.mjs.map} +1 -1
- package/dist/index.cjs +25 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +25 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -13
- package/dist/MySiteWidget-B0dc_7Dc.mjs.map +0 -1
- package/dist/MySiteWidget-BkqAS0aY.cjs.map +0 -1
- package/dist/ShareablesScreen-Bt0E1aya.cjs.map +0 -1
- package/dist/ShareablesScreen-D3Hfqg9-.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProfileScreen-CeD1jq89.mjs","names":[],"sources":["../src/screens/ProfileContentScreen.tsx","../src/screens/ProfileScreen.tsx"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport { useController } from \"react-hook-form\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { ProfileUIProvider } from \"@fluid-app/profile-core\";\nimport type { Language, PointsLedger } from \"@fluid-app/profile-core\";\nimport {\n Profile,\n AddressFormDialog,\n CreditCardFormDialog,\n} from \"@fluid-app/profile-ui\";\nimport type {\n UserFormData,\n EditPaymentMethodFormData,\n BillingAddressAutocompleteRenderProps,\n} from \"@fluid-app/profile-ui\";\nimport {\n FluidPayCoreProvider,\n type fluidPay,\n type State,\n} from \"@fluid-app/fluid-pay-core\";\nimport type { PayAddress } from \"@fluid-app/portal-core/pay-types\";\nimport {\n createFluidPayApiAdapter,\n mapToFluidPayPaymentMethod,\n} from \"../adapters/fluid-pay-api-adapter\";\nimport type { AccountRep } from \"@fluid-app/portal-core/account-types\";\nimport { useAccountApi } from \"@fluid-app/portal-core/account-api-context\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { useCountriesApi } from \"@fluid-app/store-core/countries-api-context\";\nimport { useLanguagesApi } from \"@fluid-app/store-core/languages-api-context\";\nimport { accountKeys, payKeys, storeKeys } from \"../account/query-keys\";\nimport { useAccount } from \"../hooks/use-account\";\n\ninterface ProfileContentScreenProps {\n onToast: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n countryIso: string;\n}\n\nconst translations: Record<string, string> = {\n edit_profile: \"Edit Profile\",\n first_name: \"First Name\",\n last_name: \"Last Name\",\n phone_number: \"Phone Number\",\n language: \"Language\",\n first_name_is_required: \"First name is required\",\n last_name_is_required: \"Last name is required\",\n language_is_required: \"Language is required\",\n saving: \"Saving...\",\n save_changes: \"Save Changes\",\n select_an_option: \"Select an option\",\n points_history: \"Points History\",\n points_available: \"Points Available\",\n points_awarded: \"Points Awarded\",\n points_redeemed: \"Points Redeemed\",\n transaction: \"Transaction\",\n no_points_history_found: \"No points history found\",\n shipping_addresses: \"Shipping Addresses\",\n add_an_address: \"Add an Address\",\n delete_address: \"Delete Address\",\n delete_address_message:\n \"Are you sure you want to delete this address? This action cannot be undone.\",\n delete: \"Delete\",\n add_address: \"Add Address\",\n edit_address: \"Edit Address\",\n set_as_default_address: \"Set as default address\",\n save_address: \"Save Address\",\n card_number: \"Card Number\",\n expiration_date: \"Expiration (MM / YY)\",\n cvc: \"CVC\",\n cardholder_name: \"Cardholder Name\",\n add_credit_card: \"Add Credit Card\",\n save_card: \"Save Card\",\n securing: \"Loading secure form...\",\n payment_methods: \"Payment Methods\",\n add_payment_method: \"Add Payment Method\",\n delete_credit_card: \"Delete Credit Card\",\n delete_credit_card_message:\n \"Are you sure you want to delete this payment method? This action cannot be undone.\",\n edit_card: \"Card Details\",\n billing_address: \"Billing Address\",\n country: \"Country\",\n name: \"Name\",\n address_line_1: \"Address Line 1\",\n address_line_2: \"Address Line 2\",\n city: \"City\",\n state: \"State\",\n province: \"Province\",\n zip_code: \"Zip Code\",\n postal_code: \"Postal Code\",\n select_state: \"Select state\",\n set_as_default_payment_method: \"Set as default payment method\",\n cancel: \"Cancel\",\n save: \"Save\",\n close: \"Close\",\n edit: \"Edit\",\n default: \"Default\",\n card_expires: \"Expires\",\n no_billing_address: \"No billing address on file\",\n default_payment_method_updated: \"Payment method updated\",\n failed_to_set_default_payment_method: \"Failed to update payment method\",\n};\n\nfunction t(key: string): string {\n if (translations[key]) return translations[key];\n return key\n .split(\"_\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\nfunction adaptPointsLedger(\n entry: import(\"@fluid-app/portal-core/pay-types\").PointsLedgerEntry,\n): PointsLedger {\n const meta = entry.metadata as {\n transaction_type?: string | null;\n source?: {\n name: string;\n email?: string;\n reason?: string;\n user_id?: number;\n } | null;\n } | null;\n return {\n id: entry.id,\n amount: entry.amount,\n company_id: 0,\n created_at: entry.created_at,\n customer_id: 0,\n metadata: {\n transaction_type: meta?.transaction_type ?? undefined,\n source: meta?.source ?? undefined,\n },\n total_balance: entry.total_balance,\n updated_at: entry.created_at,\n };\n}\n\n// ---------------------------------------------------------------------------\n// PayApi → fluidPay type mappers (bridge for Profile UI)\n// ---------------------------------------------------------------------------\n\nfunction mapAccountToCustomerAccount(\n raw: AccountRep,\n): fluidPay.CustomerAccount {\n return {\n fluid_pay_account: {\n id: raw.id,\n email: raw.email,\n address_count: 0,\n payment_methods_count: 0,\n language_iso: null,\n },\n customer: {\n id: raw.id,\n active: true,\n active_subscriptions_count: 0,\n display_total_spent: \"0\",\n email: raw.email,\n first_name: raw.first_name,\n full_name: `${raw.first_name} ${raw.last_name}`.trim(),\n inactive_subscriptions_count: 0,\n is_rep: raw.member_type === \"rep\",\n phone: raw.phone,\n orders_count: 0,\n },\n };\n}\n\nfunction composeAddressName(\n firstName: string,\n lastName: string,\n): string | null {\n const combined = `${firstName} ${lastName}`.trim();\n return combined.length > 0 ? combined : null;\n}\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Screen component\n// ---------------------------------------------------------------------------\n\nexport function ProfileContentScreen({\n onToast,\n countryIso: _countryIso,\n}: ProfileContentScreenProps): React.JSX.Element {\n const payApi = usePayApi();\n const accountApi = useAccountApi();\n const queryClient = useQueryClient();\n const fluidPayShim = useMemo(\n () => createFluidPayApiAdapter(payApi),\n [payApi],\n );\n\n // -- Data fetching --\n\n // Share the same cache entry as the app-wide useAccount() hook (used in\n // AppShell, PageRouter, etc.) rather than writing a different shape under\n // the same query key, which caused `customer` to be undefined here.\n const {\n data: accountRep,\n isLoading: isLoadingAccount,\n isError: isAccountError,\n } = useAccount();\n const accountData = useMemo(\n () => (accountRep ? mapAccountToCustomerAccount(accountRep) : undefined),\n [accountRep],\n );\n\n const { data: addressesData, isLoading: isLoadingAddresses } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n enabled: true,\n });\n\n const { data: paymentMethodsData, isLoading: isLoadingPaymentMethods } =\n useQuery({\n queryKey: payKeys.paymentMethods.list(),\n queryFn: async () => {\n const response = await payApi.fetchPaymentMethods();\n return response.payment_methods.map(mapToFluidPayPaymentMethod);\n },\n enabled: true,\n });\n\n const countriesAdapter = useCountriesApi();\n const languagesAdapter = useLanguagesApi();\n\n const { data: countriesData } = useQuery({\n queryKey: storeKeys.countries(),\n queryFn: () => countriesAdapter.listCountries(),\n enabled: true,\n });\n\n const { data: languagesData } = useQuery({\n queryKey: storeKeys.languages(),\n queryFn: () => languagesAdapter.listLanguages(),\n enabled: true,\n });\n\n const {\n data: pointsLedgerData,\n isLoading: isLoadingPointsLedger,\n isError: isPointsLedgerError,\n } = useQuery({\n queryKey: payKeys.pointsLedgers.list(),\n queryFn: () => payApi.fetchPointsLedgers(),\n enabled: true,\n // BFF returns 403 when reward points are not enabled for the company.\n // Don't retry on 403 so the UI simply hides the points section.\n retry: (failureCount, error) => {\n if (\n error instanceof Error &&\n \"status\" in error &&\n (error as { status: number }).status === 403\n ) {\n return false;\n }\n return failureCount < 1;\n },\n });\n\n // Points are enabled if the fetch succeeded (non-403)\n const rewardPointsEnabled = !isPointsLedgerError && pointsLedgerData != null;\n\n // -- Mutations --\n\n const updateCustomerMutation = useMutation({\n mutationFn: async (data: UserFormData) => {\n await accountApi.updateAccount({\n account: {\n first_name: data.first_name,\n last_name: data.last_name,\n phone: data.phone_number,\n },\n });\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: accountKeys.all });\n onToast(\"Profile updated\", \"success\");\n },\n onError: () => {\n onToast(\"Failed to update profile\", \"error\");\n },\n });\n\n const deleteAddressMutation = useMutation({\n mutationFn: (addressId: number) => payApi.deleteAddress(addressId),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n },\n onError: () => {\n onToast(\"Failed to delete address\", \"error\");\n },\n });\n\n const deletePaymentMethodMutation = useMutation({\n mutationFn: (paymentMethodId: number) =>\n payApi.deletePaymentMethod(paymentMethodId),\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n },\n onError: () => {\n onToast(\"Failed to delete payment method\", \"error\");\n },\n });\n\n const updatePaymentMethodMutation = useMutation({\n mutationFn: ({\n paymentMethodId,\n data,\n }: {\n paymentMethodId: number;\n data: EditPaymentMethodFormData;\n }) =>\n payApi.updatePaymentMethod(paymentMethodId, {\n payment_method: {\n default: data.set_as_default,\n billing_address: {\n name: data.billing_address.name,\n street1: data.billing_address.address1,\n street2: data.billing_address.address2 ?? null,\n city: data.billing_address.city,\n state: data.billing_address.state,\n zip: data.billing_address.zip,\n country: data.billing_address.country_code,\n },\n },\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n },\n onError: () => {\n onToast(\"Failed to update payment method\", \"error\");\n },\n });\n\n const createAddressMutation = useMutation({\n mutationFn: (body: fluidPay.CreateAddressBody) =>\n payApi.createAddress({\n address: {\n name: composeAddressName(\n body.address.first_name,\n body.address.last_name,\n ),\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n },\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n onToast(\"Address created\", \"success\");\n },\n onError: () => {\n onToast(\"Failed to create address\", \"error\");\n },\n });\n\n const updateAddressMutation = useMutation({\n mutationFn: ({\n addressId,\n body,\n }: {\n addressId: number;\n body: fluidPay.CreateAddressBody;\n }) =>\n payApi.updateAddress(addressId, {\n address: {\n name: composeAddressName(\n body.address.first_name,\n body.address.last_name,\n ),\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n },\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n onToast(\"Address updated\", \"success\");\n },\n onError: () => {\n onToast(\"Failed to update address\", \"error\");\n },\n });\n\n const addCreditCardMutation = useMutation({\n mutationFn: (data: fluidPay.AddCreditCardData) =>\n payApi.createPaymentMethod({\n payment_method: {\n type: \"card\",\n token: data.payment_method.token,\n default: data.default_payment_method,\n },\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n onToast(\"Payment method added\", \"success\");\n },\n onError: () => {\n onToast(\"Failed to add payment method\", \"error\");\n },\n });\n\n // -- Derived data --\n\n const addresses = addressesData ?? [];\n const paymentMethods = paymentMethodsData ?? [];\n\n const adaptedPointsLedger: PointsLedger[] =\n pointsLedgerData?.points_ledgers?.map(adaptPointsLedger) ?? [];\n\n const adaptedLanguages: Language[] = (languagesData?.languages ?? []).map(\n (l, i) => ({ id: i, name: l.name, iso: l.code }),\n );\n\n const countries = countriesData?.countries;\n\n const countryOptions = useMemo(\n () =>\n [...(countries ?? [])]\n .map((c) => ({ iso: c.code, name: c.name }))\n .sort((a, b) => a.name.localeCompare(b.name)),\n [countries],\n );\n\n const statesByCountry = useMemo(() => {\n const map = new Map<string, State[]>();\n for (const c of countries ?? []) {\n map.set(\n c.code,\n c.states.map((s) => ({ name: s.name, isoCode: s.code })),\n );\n }\n return map;\n }, [countries]);\n\n const fetchStatesFromCountries = useCallback(\n (countryCode: string): Promise<State[]> =>\n Promise.resolve(statesByCountry.get(countryCode) ?? []),\n [statesByCountry],\n );\n\n // -- Loading state --\n\n if (isAccountError && !isLoadingAccount) {\n return (\n <div className=\"px-4 py-8 sm:px-9\">\n <div className=\"text-muted-foreground text-center text-sm\">\n Unable to load account data. Please try again later.\n </div>\n </div>\n );\n }\n\n if (isLoadingAccount || !accountData) {\n return (\n <div className=\"px-4 pt-4 sm:px-9 md:pt-8\">\n <div className=\"space-y-4\">\n <div className=\"bg-muted h-16 animate-pulse rounded\" />\n <div className=\"bg-muted h-32 animate-pulse rounded\" />\n <div className=\"bg-muted h-32 animate-pulse rounded\" />\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"px-4 pt-4 sm:px-9 md:pt-8\">\n <FluidPayCoreProvider api={fluidPayShim}>\n <ProfileUIProvider t={t}>\n <Profile\n customerAccount={accountData}\n languages={adaptedLanguages}\n onUpdateCustomer={async (data) => {\n await updateCustomerMutation.mutateAsync(data);\n }}\n isUpdatingCustomer={updateCustomerMutation.isPending}\n // TODO: wire onChangeEmail to PATCH /v202506/users/:id/change_email\n // once portal self-service email change is designed\n // onChangeEmail={...}\n // pendingEmail={pendingEmail}\n rewardsPointsEnabled={rewardPointsEnabled}\n pointsLedger={adaptedPointsLedger}\n isLoadingPointsLedger={isLoadingPointsLedger}\n addresses={addresses}\n isLoadingAddresses={isLoadingAddresses}\n onDeleteAddress={async (addressId) => {\n await deleteAddressMutation.mutateAsync(addressId);\n }}\n isDeletingAddress={deleteAddressMutation.isPending}\n paymentMethods={paymentMethods}\n isLoadingPaymentMethods={isLoadingPaymentMethods}\n onDeletePaymentMethod={async (paymentMethodId) => {\n await deletePaymentMethodMutation.mutateAsync(paymentMethodId);\n }}\n isDeletingPaymentMethod={deletePaymentMethodMutation.isPending}\n onUpdatePaymentMethod={async (paymentMethodId, data) => {\n await updatePaymentMethodMutation.mutateAsync({\n paymentMethodId,\n data,\n });\n }}\n isUpdatingPaymentMethod={updatePaymentMethodMutation.isPending}\n getBillingAddress={(paymentMethod) =>\n paymentMethod.billing_address ?? null\n }\n countries={countryOptions}\n renderAddressDialog={({ isOpen, onClose, selectedAddress }) => (\n <AddressFormDialog\n isOpen={isOpen}\n onClose={onClose}\n selectedAddress={selectedAddress}\n t={t}\n onSubmit={async (formData) => {\n if (selectedAddress) {\n await updateAddressMutation.mutateAsync({\n addressId: selectedAddress.id,\n body: formData,\n });\n } else {\n await createAddressMutation.mutateAsync(formData);\n }\n onClose();\n }}\n isSubmitting={\n createAddressMutation.isPending ||\n updateAddressMutation.isPending\n }\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n renderAddressAutocomplete={({\n control,\n setValue: _setValue,\n }: {\n control: Parameters<\n NonNullable<\n Parameters<\n typeof AddressFormDialog\n >[0][\"renderAddressAutocomplete\"]\n >\n >[0][\"control\"];\n setValue: Parameters<\n NonNullable<\n Parameters<\n typeof AddressFormDialog\n >[0][\"renderAddressAutocomplete\"]\n >\n >[0][\"setValue\"];\n }) => <PlainAddressInput control={control} name=\"address1\" />}\n />\n )}\n renderCreditCardDialog={({ isOpen, onClose }) => (\n <CreditCardFormDialog\n isOpen={isOpen}\n onClose={onClose}\n t={t}\n onSubmit={async (data) => {\n try {\n await addCreditCardMutation.mutateAsync(data);\n onClose();\n } catch {\n // onError surfaces the toast; swallow here so the dialog\n // doesn't see an unhandled rejection.\n }\n }}\n isSubmitting={addCreditCardMutation.isPending}\n countries={countryOptions}\n jwt=\"\"\n renderAddressAutocomplete={({\n control,\n setValue: _setValue,\n }: BillingAddressAutocompleteRenderProps) => (\n <PlainAddressInput control={control} name=\"address1\" />\n )}\n />\n )}\n />\n </ProfileUIProvider>\n </FluidPayCoreProvider>\n </div>\n );\n}\n\n/**\n * Plain text input fallback for address autocomplete.\n * The SDK doesn't have Google Places integration.\n */\nfunction PlainAddressInput({\n control,\n name,\n}: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n control: any;\n name: string;\n}): React.JSX.Element {\n const { field } = useController({ control, name: name as string });\n return (\n <input\n type=\"text\"\n ref={field.ref}\n value={(field.value as string) ?? \"\"}\n placeholder=\"Address Line 1\"\n className=\"border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50\"\n onChange={field.onChange}\n onBlur={field.onBlur}\n />\n );\n}\n","import { type ComponentProps, useMemo } from \"react\";\nimport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbPage,\n fluidToast,\n} from \"@fluid-app/ui-primitives\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n PaddingOptions,\n} from \"../types\";\nimport type { WidgetPropertySchema } from \"../registries/property-schema-types\";\nimport { useFluidContext } from \"../providers/FluidProvider\";\nimport { ProfileContentScreen } from \"./ProfileContentScreen\";\n\ntype ProfileScreenProps = ComponentProps<\"div\"> & {\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n onToast?: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n};\n\nfunction defaultToast(message: string, type: \"success\" | \"error\" | \"warning\") {\n fluidToast({ title: message, type });\n}\n\nexport function ProfileScreen({\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}: ProfileScreenProps): React.JSX.Element {\n const { config } = useFluidContext();\n const effectiveToast = onToast ?? defaultToast;\n const countryIso = config.countryIso ?? \"US\";\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">Profile</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n return (\n <div {...divProps}>\n <ProfileContentScreen onToast={effectiveToast} countryIso={countryIso} />\n </div>\n );\n}\n\nexport const profileScreenPropertySchema: WidgetPropertySchema = {\n widgetType: \"ProfileScreen\",\n displayName: \"Profile Screen\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProfileScreen-CwQr_Km7.mjs","names":[],"sources":["../src/screens/ProfileContentScreen.tsx","../src/screens/ProfileScreen.tsx"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport { useController } from \"react-hook-form\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { ProfileUIProvider } from \"@fluid-app/profile-core\";\nimport type { Language, PointsLedger } from \"@fluid-app/profile-core\";\nimport {\n Profile,\n AddressFormDialog,\n CreditCardFormDialog,\n} from \"@fluid-app/profile-ui\";\nimport type {\n UserFormData,\n EditPaymentMethodFormData,\n BillingAddressAutocompleteRenderProps,\n} from \"@fluid-app/profile-ui\";\nimport {\n FluidPayCoreProvider,\n type fluidPay,\n type State,\n} from \"@fluid-app/fluid-pay-core\";\nimport type { PayAddress } from \"@fluid-app/portal-core/pay-types\";\nimport {\n createFluidPayApiAdapter,\n mapToFluidPayPaymentMethod,\n} from \"../adapters/fluid-pay-api-adapter\";\nimport type { AccountRep } from \"@fluid-app/portal-core/account-types\";\nimport { useAccountApi } from \"@fluid-app/portal-core/account-api-context\";\nimport { usePayApi } from \"@fluid-app/portal-core/pay-api-context\";\nimport { useCountriesApi } from \"@fluid-app/store-core/countries-api-context\";\nimport { useLanguagesApi } from \"@fluid-app/store-core/languages-api-context\";\nimport { accountKeys, payKeys, storeKeys } from \"../account/query-keys\";\nimport { useAccount } from \"../hooks/use-account\";\n\ninterface ProfileContentScreenProps {\n onToast: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n countryIso: string;\n}\n\nconst translations: Record<string, string> = {\n edit_profile: \"Edit Profile\",\n first_name: \"First Name\",\n last_name: \"Last Name\",\n phone_number: \"Phone Number\",\n language: \"Language\",\n first_name_is_required: \"First name is required\",\n last_name_is_required: \"Last name is required\",\n language_is_required: \"Language is required\",\n saving: \"Saving...\",\n save_changes: \"Save Changes\",\n select_an_option: \"Select an option\",\n points_history: \"Points History\",\n points_available: \"Points Available\",\n points_awarded: \"Points Awarded\",\n points_redeemed: \"Points Redeemed\",\n transaction: \"Transaction\",\n no_points_history_found: \"No points history found\",\n shipping_addresses: \"Shipping Addresses\",\n add_an_address: \"Add an Address\",\n delete_address: \"Delete Address\",\n delete_address_message:\n \"Are you sure you want to delete this address? This action cannot be undone.\",\n delete: \"Delete\",\n add_address: \"Add Address\",\n edit_address: \"Edit Address\",\n set_as_default_address: \"Set as default address\",\n save_address: \"Save Address\",\n card_number: \"Card Number\",\n expiration_date: \"Expiration (MM / YY)\",\n cvc: \"CVC\",\n cardholder_name: \"Cardholder Name\",\n add_credit_card: \"Add Credit Card\",\n save_card: \"Save Card\",\n securing: \"Loading secure form...\",\n payment_methods: \"Payment Methods\",\n add_payment_method: \"Add Payment Method\",\n delete_credit_card: \"Delete Credit Card\",\n delete_credit_card_message:\n \"Are you sure you want to delete this payment method? This action cannot be undone.\",\n edit_card: \"Card Details\",\n billing_address: \"Billing Address\",\n country: \"Country\",\n name: \"Name\",\n address_line_1: \"Address Line 1\",\n address_line_2: \"Address Line 2\",\n city: \"City\",\n state: \"State\",\n province: \"Province\",\n zip_code: \"Zip Code\",\n postal_code: \"Postal Code\",\n select_state: \"Select state\",\n set_as_default_payment_method: \"Set as default payment method\",\n cancel: \"Cancel\",\n save: \"Save\",\n close: \"Close\",\n edit: \"Edit\",\n default: \"Default\",\n card_expires: \"Expires\",\n no_billing_address: \"No billing address on file\",\n default_payment_method_updated: \"Payment method updated\",\n failed_to_set_default_payment_method: \"Failed to update payment method\",\n};\n\nfunction t(key: string): string {\n if (translations[key]) return translations[key];\n return key\n .split(\"_\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\nfunction adaptPointsLedger(\n entry: import(\"@fluid-app/portal-core/pay-types\").PointsLedgerEntry,\n): PointsLedger {\n const meta = entry.metadata as {\n transaction_type?: string | null;\n source?: {\n name: string;\n email?: string;\n reason?: string;\n user_id?: number;\n } | null;\n } | null;\n return {\n id: entry.id,\n amount: entry.amount,\n company_id: 0,\n created_at: entry.created_at,\n customer_id: 0,\n metadata: {\n transaction_type: meta?.transaction_type ?? undefined,\n source: meta?.source ?? undefined,\n },\n total_balance: entry.total_balance,\n updated_at: entry.created_at,\n };\n}\n\n// ---------------------------------------------------------------------------\n// PayApi → fluidPay type mappers (bridge for Profile UI)\n// ---------------------------------------------------------------------------\n\nfunction mapAccountToCustomerAccount(\n raw: AccountRep,\n): fluidPay.CustomerAccount {\n return {\n fluid_pay_account: {\n id: raw.id,\n email: raw.email,\n address_count: 0,\n payment_methods_count: 0,\n language_iso: null,\n },\n customer: {\n id: raw.id,\n active: true,\n active_subscriptions_count: 0,\n display_total_spent: \"0\",\n email: raw.email,\n first_name: raw.first_name,\n full_name: `${raw.first_name} ${raw.last_name}`.trim(),\n inactive_subscriptions_count: 0,\n is_rep: raw.member_type === \"rep\",\n phone: raw.phone,\n orders_count: 0,\n },\n };\n}\n\nfunction composeAddressName(\n firstName: string,\n lastName: string,\n): string | null {\n const combined = `${firstName} ${lastName}`.trim();\n return combined.length > 0 ? combined : null;\n}\n\nfunction mapToFluidPayAddress(raw: PayAddress): fluidPay.CustomerAddress {\n return {\n id: raw.id,\n address1: raw.street1,\n address2: raw.street2,\n city: raw.city,\n country_code: raw.country,\n default: raw.default,\n name: raw.name,\n postal_code: raw.zip,\n state: raw.state,\n subdivision_code: null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Screen component\n// ---------------------------------------------------------------------------\n\nexport function ProfileContentScreen({\n onToast,\n countryIso: _countryIso,\n}: ProfileContentScreenProps): React.JSX.Element {\n const payApi = usePayApi();\n const accountApi = useAccountApi();\n const queryClient = useQueryClient();\n const fluidPayShim = useMemo(\n () => createFluidPayApiAdapter(payApi),\n [payApi],\n );\n\n // -- Data fetching --\n\n // Share the same cache entry as the app-wide useAccount() hook (used in\n // AppShell, PageRouter, etc.) rather than writing a different shape under\n // the same query key, which caused `customer` to be undefined here.\n const {\n data: accountRep,\n isLoading: isLoadingAccount,\n isError: isAccountError,\n } = useAccount();\n const accountData = useMemo(\n () => (accountRep ? mapAccountToCustomerAccount(accountRep) : undefined),\n [accountRep],\n );\n\n const { data: addressesData, isLoading: isLoadingAddresses } = useQuery({\n queryKey: payKeys.addresses.list(),\n queryFn: async () => {\n const response = await payApi.fetchAddresses();\n return response.addresses.map(mapToFluidPayAddress);\n },\n enabled: true,\n });\n\n const { data: paymentMethodsData, isLoading: isLoadingPaymentMethods } =\n useQuery({\n queryKey: payKeys.paymentMethods.list(),\n queryFn: async () => {\n const response = await payApi.fetchPaymentMethods();\n return response.payment_methods.map(mapToFluidPayPaymentMethod);\n },\n enabled: true,\n });\n\n const countriesAdapter = useCountriesApi();\n const languagesAdapter = useLanguagesApi();\n\n const { data: countriesData } = useQuery({\n queryKey: storeKeys.countries(),\n queryFn: () => countriesAdapter.listCountries(),\n enabled: true,\n });\n\n const { data: languagesData } = useQuery({\n queryKey: storeKeys.languages(),\n queryFn: () => languagesAdapter.listLanguages(),\n enabled: true,\n });\n\n const {\n data: pointsLedgerData,\n isLoading: isLoadingPointsLedger,\n isError: isPointsLedgerError,\n } = useQuery({\n queryKey: payKeys.pointsLedgers.list(),\n queryFn: () => payApi.fetchPointsLedgers(),\n enabled: true,\n // BFF returns 403 when reward points are not enabled for the company.\n // Don't retry on 403 so the UI simply hides the points section.\n retry: (failureCount, error) => {\n if (\n error instanceof Error &&\n \"status\" in error &&\n (error as { status: number }).status === 403\n ) {\n return false;\n }\n return failureCount < 1;\n },\n });\n\n // Points are enabled if the fetch succeeded (non-403)\n const rewardPointsEnabled = !isPointsLedgerError && pointsLedgerData != null;\n\n // -- Mutations --\n\n const updateCustomerMutation = useMutation({\n mutationFn: async (data: UserFormData) => {\n await accountApi.updateAccount({\n account: {\n first_name: data.first_name,\n last_name: data.last_name,\n phone: data.phone_number,\n },\n });\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: accountKeys.all });\n onToast(\"Profile updated\", \"success\");\n },\n onError: () => {\n onToast(\"Failed to update profile\", \"error\");\n },\n });\n\n const deleteAddressMutation = useMutation({\n mutationFn: (addressId: number) => payApi.deleteAddress(addressId),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n },\n onError: () => {\n onToast(\"Failed to delete address\", \"error\");\n },\n });\n\n const deletePaymentMethodMutation = useMutation({\n mutationFn: (paymentMethodId: number) =>\n payApi.deletePaymentMethod(paymentMethodId),\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n },\n onError: () => {\n onToast(\"Failed to delete payment method\", \"error\");\n },\n });\n\n const updatePaymentMethodMutation = useMutation({\n mutationFn: ({\n paymentMethodId,\n data,\n }: {\n paymentMethodId: number;\n data: EditPaymentMethodFormData;\n }) =>\n payApi.updatePaymentMethod(paymentMethodId, {\n payment_method: {\n default: data.set_as_default,\n billing_address: {\n name: data.billing_address.name,\n street1: data.billing_address.address1,\n street2: data.billing_address.address2 ?? null,\n city: data.billing_address.city,\n state: data.billing_address.state,\n zip: data.billing_address.zip,\n country: data.billing_address.country_code,\n },\n },\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n },\n onError: () => {\n onToast(\"Failed to update payment method\", \"error\");\n },\n });\n\n const createAddressMutation = useMutation({\n mutationFn: (body: fluidPay.CreateAddressBody) =>\n payApi.createAddress({\n address: {\n name: composeAddressName(\n body.address.first_name,\n body.address.last_name,\n ),\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n },\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n onToast(\"Address created\", \"success\");\n },\n onError: () => {\n onToast(\"Failed to create address\", \"error\");\n },\n });\n\n const updateAddressMutation = useMutation({\n mutationFn: ({\n addressId,\n body,\n }: {\n addressId: number;\n body: fluidPay.CreateAddressBody;\n }) =>\n payApi.updateAddress(addressId, {\n address: {\n name: composeAddressName(\n body.address.first_name,\n body.address.last_name,\n ),\n street1: body.address.address1,\n street2: body.address.address2,\n city: body.address.city,\n state: body.address.state,\n zip: body.address.postal_code,\n country: body.address.country_code,\n },\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: payKeys.addresses.all });\n onToast(\"Address updated\", \"success\");\n },\n onError: () => {\n onToast(\"Failed to update address\", \"error\");\n },\n });\n\n const addCreditCardMutation = useMutation({\n mutationFn: (data: fluidPay.AddCreditCardData) =>\n payApi.createPaymentMethod({\n payment_method: {\n type: \"card\",\n token: data.payment_method.token,\n default: data.default_payment_method,\n },\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: payKeys.paymentMethods.all,\n });\n onToast(\"Payment method added\", \"success\");\n },\n onError: () => {\n onToast(\"Failed to add payment method\", \"error\");\n },\n });\n\n // -- Derived data --\n\n const addresses = addressesData ?? [];\n const paymentMethods = paymentMethodsData ?? [];\n\n const adaptedPointsLedger: PointsLedger[] =\n pointsLedgerData?.points_ledgers?.map(adaptPointsLedger) ?? [];\n\n const adaptedLanguages: Language[] = (languagesData?.languages ?? []).map(\n (l, i) => ({ id: i, name: l.name, iso: l.code }),\n );\n\n const countries = countriesData?.countries;\n\n const countryOptions = useMemo(\n () =>\n [...(countries ?? [])]\n .map((c) => ({ iso: c.code, name: c.name }))\n .sort((a, b) => a.name.localeCompare(b.name)),\n [countries],\n );\n\n const statesByCountry = useMemo(() => {\n const map = new Map<string, State[]>();\n for (const c of countries ?? []) {\n map.set(\n c.code,\n c.states.map((s) => ({ name: s.name, isoCode: s.code })),\n );\n }\n return map;\n }, [countries]);\n\n const fetchStatesFromCountries = useCallback(\n (countryCode: string): Promise<State[]> =>\n Promise.resolve(statesByCountry.get(countryCode) ?? []),\n [statesByCountry],\n );\n\n // -- Loading state --\n\n if (isAccountError && !isLoadingAccount) {\n return (\n <div className=\"px-4 py-8 sm:px-9\">\n <div className=\"text-muted-foreground text-center text-sm\">\n Unable to load account data. Please try again later.\n </div>\n </div>\n );\n }\n\n if (isLoadingAccount || !accountData) {\n return (\n <div className=\"px-4 pt-4 sm:px-9 md:pt-8\">\n <div className=\"space-y-4\">\n <div className=\"bg-muted h-16 animate-pulse rounded\" />\n <div className=\"bg-muted h-32 animate-pulse rounded\" />\n <div className=\"bg-muted h-32 animate-pulse rounded\" />\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"px-4 pt-4 sm:px-9 md:pt-8\">\n <FluidPayCoreProvider api={fluidPayShim}>\n <ProfileUIProvider t={t}>\n <Profile\n customerAccount={accountData}\n languages={adaptedLanguages}\n onUpdateCustomer={async (data) => {\n await updateCustomerMutation.mutateAsync(data);\n }}\n isUpdatingCustomer={updateCustomerMutation.isPending}\n // TODO: wire onChangeEmail to PATCH /v202506/users/:id/change_email\n // once portal self-service email change is designed\n // onChangeEmail={...}\n // pendingEmail={pendingEmail}\n rewardsPointsEnabled={rewardPointsEnabled}\n pointsLedger={adaptedPointsLedger}\n isLoadingPointsLedger={isLoadingPointsLedger}\n addresses={addresses}\n isLoadingAddresses={isLoadingAddresses}\n onDeleteAddress={async (addressId) => {\n await deleteAddressMutation.mutateAsync(addressId);\n }}\n isDeletingAddress={deleteAddressMutation.isPending}\n paymentMethods={paymentMethods}\n isLoadingPaymentMethods={isLoadingPaymentMethods}\n onDeletePaymentMethod={async (paymentMethodId) => {\n await deletePaymentMethodMutation.mutateAsync(paymentMethodId);\n }}\n isDeletingPaymentMethod={deletePaymentMethodMutation.isPending}\n onUpdatePaymentMethod={async (paymentMethodId, data) => {\n await updatePaymentMethodMutation.mutateAsync({\n paymentMethodId,\n data,\n });\n }}\n isUpdatingPaymentMethod={updatePaymentMethodMutation.isPending}\n getBillingAddress={(paymentMethod) =>\n paymentMethod.billing_address ?? null\n }\n countries={countryOptions}\n renderAddressDialog={({ isOpen, onClose, selectedAddress }) => (\n <AddressFormDialog\n isOpen={isOpen}\n onClose={onClose}\n selectedAddress={selectedAddress}\n t={t}\n onSubmit={async (formData) => {\n if (selectedAddress) {\n await updateAddressMutation.mutateAsync({\n addressId: selectedAddress.id,\n body: formData,\n });\n } else {\n await createAddressMutation.mutateAsync(formData);\n }\n onClose();\n }}\n isSubmitting={\n createAddressMutation.isPending ||\n updateAddressMutation.isPending\n }\n countries={countryOptions}\n fetchStates={fetchStatesFromCountries}\n renderAddressAutocomplete={({\n control,\n setValue: _setValue,\n }: {\n control: Parameters<\n NonNullable<\n Parameters<\n typeof AddressFormDialog\n >[0][\"renderAddressAutocomplete\"]\n >\n >[0][\"control\"];\n setValue: Parameters<\n NonNullable<\n Parameters<\n typeof AddressFormDialog\n >[0][\"renderAddressAutocomplete\"]\n >\n >[0][\"setValue\"];\n }) => <PlainAddressInput control={control} name=\"address1\" />}\n />\n )}\n renderCreditCardDialog={({ isOpen, onClose }) => (\n <CreditCardFormDialog\n isOpen={isOpen}\n onClose={onClose}\n t={t}\n onSubmit={async (data) => {\n try {\n await addCreditCardMutation.mutateAsync(data);\n onClose();\n } catch {\n // onError surfaces the toast; swallow here so the dialog\n // doesn't see an unhandled rejection.\n }\n }}\n isSubmitting={addCreditCardMutation.isPending}\n countries={countryOptions}\n jwt=\"\"\n renderAddressAutocomplete={({\n control,\n setValue: _setValue,\n }: BillingAddressAutocompleteRenderProps) => (\n <PlainAddressInput control={control} name=\"address1\" />\n )}\n />\n )}\n />\n </ProfileUIProvider>\n </FluidPayCoreProvider>\n </div>\n );\n}\n\n/**\n * Plain text input fallback for address autocomplete.\n * The SDK doesn't have Google Places integration.\n */\nfunction PlainAddressInput({\n control,\n name,\n}: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n control: any;\n name: string;\n}): React.JSX.Element {\n const { field } = useController({ control, name: name as string });\n return (\n <input\n type=\"text\"\n ref={field.ref}\n value={(field.value as string) ?? \"\"}\n placeholder=\"Address Line 1\"\n className=\"border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50\"\n onChange={field.onChange}\n onBlur={field.onBlur}\n />\n );\n}\n","import { type ComponentProps, useMemo } from \"react\";\nimport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbPage,\n fluidToast,\n} from \"@fluid-app/ui-primitives\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n PaddingOptions,\n} from \"../types\";\nimport type { WidgetPropertySchema } from \"../registries/property-schema-types\";\nimport { useFluidContext } from \"../providers/FluidProvider\";\nimport { ProfileContentScreen } from \"./ProfileContentScreen\";\n\ntype ProfileScreenProps = ComponentProps<\"div\"> & {\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n onToast?: (message: string, type: \"success\" | \"error\" | \"warning\") => void;\n};\n\nfunction defaultToast(message: string, type: \"success\" | \"error\" | \"warning\") {\n fluidToast({ title: message, type });\n}\n\nexport function ProfileScreen({\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}: ProfileScreenProps): React.JSX.Element {\n const { config } = useFluidContext();\n const effectiveToast = onToast ?? defaultToast;\n const countryIso = config.countryIso ?? \"US\";\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">Profile</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n return (\n <div {...divProps}>\n <ProfileContentScreen onToast={effectiveToast} countryIso={countryIso} />\n </div>\n );\n}\n\nexport const profileScreenPropertySchema: WidgetPropertySchema = {\n widgetType: \"ProfileScreen\",\n displayName: \"Profile Screen\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":";;;;;;;;;;;;;;;AAsCA,MAAM,eAAuC;CAC3C,cAAc;CACd,YAAY;CACZ,WAAW;CACX,cAAc;CACd,UAAU;CACV,wBAAwB;CACxB,uBAAuB;CACvB,sBAAsB;CACtB,QAAQ;CACR,cAAc;CACd,kBAAkB;CAClB,gBAAgB;CAChB,kBAAkB;CAClB,gBAAgB;CAChB,iBAAiB;CACjB,aAAa;CACb,yBAAyB;CACzB,oBAAoB;CACpB,gBAAgB;CAChB,gBAAgB;CAChB,wBACE;CACF,QAAQ;CACR,aAAa;CACb,cAAc;CACd,wBAAwB;CACxB,cAAc;CACd,aAAa;CACb,iBAAiB;CACjB,KAAK;CACL,iBAAiB;CACjB,iBAAiB;CACjB,WAAW;CACX,UAAU;CACV,iBAAiB;CACjB,oBAAoB;CACpB,oBAAoB;CACpB,4BACE;CACF,WAAW;CACX,iBAAiB;CACjB,SAAS;CACT,MAAM;CACN,gBAAgB;CAChB,gBAAgB;CAChB,MAAM;CACN,OAAO;CACP,UAAU;CACV,UAAU;CACV,aAAa;CACb,cAAc;CACd,+BAA+B;CAC/B,QAAQ;CACR,MAAM;CACN,OAAO;CACP,MAAM;CACN,SAAS;CACT,cAAc;CACd,oBAAoB;CACpB,gCAAgC;CAChC,sCAAsC;CACvC;AAED,SAAS,EAAE,KAAqB;AAC9B,KAAI,aAAa,KAAM,QAAO,aAAa;AAC3C,QAAO,IACJ,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,CAC3D,KAAK,IAAI;;AAGd,SAAS,kBACP,OACc;CACd,MAAM,OAAO,MAAM;AASnB,QAAO;EACL,IAAI,MAAM;EACV,QAAQ,MAAM;EACd,YAAY;EACZ,YAAY,MAAM;EAClB,aAAa;EACb,UAAU;GACR,kBAAkB,MAAM,oBAAoB,KAAA;GAC5C,QAAQ,MAAM,UAAU,KAAA;GACzB;EACD,eAAe,MAAM;EACrB,YAAY,MAAM;EACnB;;AAOH,SAAS,4BACP,KAC0B;AAC1B,QAAO;EACL,mBAAmB;GACjB,IAAI,IAAI;GACR,OAAO,IAAI;GACX,eAAe;GACf,uBAAuB;GACvB,cAAc;GACf;EACD,UAAU;GACR,IAAI,IAAI;GACR,QAAQ;GACR,4BAA4B;GAC5B,qBAAqB;GACrB,OAAO,IAAI;GACX,YAAY,IAAI;GAChB,WAAW,GAAG,IAAI,WAAW,GAAG,IAAI,YAAY,MAAM;GACtD,8BAA8B;GAC9B,QAAQ,IAAI,gBAAgB;GAC5B,OAAO,IAAI;GACX,cAAc;GACf;EACF;;AAGH,SAAS,mBACP,WACA,UACe;CACf,MAAM,WAAW,GAAG,UAAU,GAAG,WAAW,MAAM;AAClD,QAAO,SAAS,SAAS,IAAI,WAAW;;AAG1C,SAAS,qBAAqB,KAA2C;AACvE,QAAO;EACL,IAAI,IAAI;EACR,UAAU,IAAI;EACd,UAAU,IAAI;EACd,MAAM,IAAI;EACV,cAAc,IAAI;EAClB,SAAS,IAAI;EACb,MAAM,IAAI;EACV,aAAa,IAAI;EACjB,OAAO,IAAI;EACX,kBAAkB;EACnB;;AAOH,SAAgB,qBAAqB,EACnC,SACA,YAAY,eACmC;CAC/C,MAAM,SAAS,WAAW;CAC1B,MAAM,aAAa,eAAe;CAClC,MAAM,cAAc,gBAAgB;CACpC,MAAM,eAAe,cACb,yBAAyB,OAAO,EACtC,CAAC,OAAO,CACT;CAOD,MAAM,EACJ,MAAM,YACN,WAAW,kBACX,SAAS,mBACP,YAAY;CAChB,MAAM,cAAc,cACX,aAAa,4BAA4B,WAAW,GAAG,KAAA,GAC9D,CAAC,WAAW,CACb;CAED,MAAM,EAAE,MAAM,eAAe,WAAW,uBAAuB,SAAS;EACtE,UAAU,QAAQ,UAAU,MAAM;EAClC,SAAS,YAAY;AAEnB,WADiB,MAAM,OAAO,gBAAgB,EAC9B,UAAU,IAAI,qBAAqB;;EAErD,SAAS;EACV,CAAC;CAEF,MAAM,EAAE,MAAM,oBAAoB,WAAW,4BAC3C,SAAS;EACP,UAAU,QAAQ,eAAe,MAAM;EACvC,SAAS,YAAY;AAEnB,WADiB,MAAM,OAAO,qBAAqB,EACnC,gBAAgB,IAAI,2BAA2B;;EAEjE,SAAS;EACV,CAAC;CAEJ,MAAM,mBAAmB,iBAAiB;CAC1C,MAAM,mBAAmB,iBAAiB;CAE1C,MAAM,EAAE,MAAM,kBAAkB,SAAS;EACvC,UAAU,UAAU,WAAW;EAC/B,eAAe,iBAAiB,eAAe;EAC/C,SAAS;EACV,CAAC;CAEF,MAAM,EAAE,MAAM,kBAAkB,SAAS;EACvC,UAAU,UAAU,WAAW;EAC/B,eAAe,iBAAiB,eAAe;EAC/C,SAAS;EACV,CAAC;CAEF,MAAM,EACJ,MAAM,kBACN,WAAW,uBACX,SAAS,wBACP,SAAS;EACX,UAAU,QAAQ,cAAc,MAAM;EACtC,eAAe,OAAO,oBAAoB;EAC1C,SAAS;EAGT,QAAQ,cAAc,UAAU;AAC9B,OACE,iBAAiB,SACjB,YAAY,SACX,MAA6B,WAAW,IAEzC,QAAO;AAET,UAAO,eAAe;;EAEzB,CAAC;CAGF,MAAM,sBAAsB,CAAC,uBAAuB,oBAAoB;CAIxE,MAAM,yBAAyB,YAAY;EACzC,YAAY,OAAO,SAAuB;AACxC,SAAM,WAAW,cAAc,EAC7B,SAAS;IACP,YAAY,KAAK;IACjB,WAAW,KAAK;IAChB,OAAO,KAAK;IACb,EACF,CAAC;;EAEJ,iBAAiB;AACf,eAAY,kBAAkB,EAAE,UAAU,YAAY,KAAK,CAAC;AAC5D,WAAQ,mBAAmB,UAAU;;EAEvC,eAAe;AACb,WAAQ,4BAA4B,QAAQ;;EAE/C,CAAC;CAEF,MAAM,wBAAwB,YAAY;EACxC,aAAa,cAAsB,OAAO,cAAc,UAAU;EAClE,iBAAiB;AACf,eAAY,kBAAkB,EAAE,UAAU,QAAQ,UAAU,KAAK,CAAC;;EAEpE,eAAe;AACb,WAAQ,4BAA4B,QAAQ;;EAE/C,CAAC;CAEF,MAAM,8BAA8B,YAAY;EAC9C,aAAa,oBACX,OAAO,oBAAoB,gBAAgB;EAC7C,iBAAiB;AACf,eAAY,kBAAkB,EAC5B,UAAU,QAAQ,eAAe,KAClC,CAAC;;EAEJ,eAAe;AACb,WAAQ,mCAAmC,QAAQ;;EAEtD,CAAC;CAEF,MAAM,8BAA8B,YAAY;EAC9C,aAAa,EACX,iBACA,WAKA,OAAO,oBAAoB,iBAAiB,EAC1C,gBAAgB;GACd,SAAS,KAAK;GACd,iBAAiB;IACf,MAAM,KAAK,gBAAgB;IAC3B,SAAS,KAAK,gBAAgB;IAC9B,SAAS,KAAK,gBAAgB,YAAY;IAC1C,MAAM,KAAK,gBAAgB;IAC3B,OAAO,KAAK,gBAAgB;IAC5B,KAAK,KAAK,gBAAgB;IAC1B,SAAS,KAAK,gBAAgB;IAC/B;GACF,EACF,CAAC;EACJ,iBAAiB;AACf,eAAY,kBAAkB,EAC5B,UAAU,QAAQ,eAAe,KAClC,CAAC;;EAEJ,eAAe;AACb,WAAQ,mCAAmC,QAAQ;;EAEtD,CAAC;CAEF,MAAM,wBAAwB,YAAY;EACxC,aAAa,SACX,OAAO,cAAc,EACnB,SAAS;GACP,MAAM,mBACJ,KAAK,QAAQ,YACb,KAAK,QAAQ,UACd;GACD,SAAS,KAAK,QAAQ;GACtB,SAAS,KAAK,QAAQ;GACtB,MAAM,KAAK,QAAQ;GACnB,OAAO,KAAK,QAAQ;GACpB,KAAK,KAAK,QAAQ;GAClB,SAAS,KAAK,QAAQ;GACvB,EACF,CAAC;EACJ,iBAAiB;AACf,eAAY,kBAAkB,EAAE,UAAU,QAAQ,UAAU,KAAK,CAAC;AAClE,WAAQ,mBAAmB,UAAU;;EAEvC,eAAe;AACb,WAAQ,4BAA4B,QAAQ;;EAE/C,CAAC;CAEF,MAAM,wBAAwB,YAAY;EACxC,aAAa,EACX,WACA,WAKA,OAAO,cAAc,WAAW,EAC9B,SAAS;GACP,MAAM,mBACJ,KAAK,QAAQ,YACb,KAAK,QAAQ,UACd;GACD,SAAS,KAAK,QAAQ;GACtB,SAAS,KAAK,QAAQ;GACtB,MAAM,KAAK,QAAQ;GACnB,OAAO,KAAK,QAAQ;GACpB,KAAK,KAAK,QAAQ;GAClB,SAAS,KAAK,QAAQ;GACvB,EACF,CAAC;EACJ,iBAAiB;AACf,eAAY,kBAAkB,EAAE,UAAU,QAAQ,UAAU,KAAK,CAAC;AAClE,WAAQ,mBAAmB,UAAU;;EAEvC,eAAe;AACb,WAAQ,4BAA4B,QAAQ;;EAE/C,CAAC;CAEF,MAAM,wBAAwB,YAAY;EACxC,aAAa,SACX,OAAO,oBAAoB,EACzB,gBAAgB;GACd,MAAM;GACN,OAAO,KAAK,eAAe;GAC3B,SAAS,KAAK;GACf,EACF,CAAC;EACJ,iBAAiB;AACf,eAAY,kBAAkB,EAC5B,UAAU,QAAQ,eAAe,KAClC,CAAC;AACF,WAAQ,wBAAwB,UAAU;;EAE5C,eAAe;AACb,WAAQ,gCAAgC,QAAQ;;EAEnD,CAAC;CAIF,MAAM,YAAY,iBAAiB,EAAE;CACrC,MAAM,iBAAiB,sBAAsB,EAAE;CAE/C,MAAM,sBACJ,kBAAkB,gBAAgB,IAAI,kBAAkB,IAAI,EAAE;CAEhE,MAAM,oBAAgC,eAAe,aAAa,EAAE,EAAE,KACnE,GAAG,OAAO;EAAE,IAAI;EAAG,MAAM,EAAE;EAAM,KAAK,EAAE;EAAM,EAChD;CAED,MAAM,YAAY,eAAe;CAEjC,MAAM,iBAAiB,cAEnB,CAAC,GAAI,aAAa,EAAE,CAAE,CACnB,KAAK,OAAO;EAAE,KAAK,EAAE;EAAM,MAAM,EAAE;EAAM,EAAE,CAC3C,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,EACjD,CAAC,UAAU,CACZ;CAED,MAAM,kBAAkB,cAAc;EACpC,MAAM,sBAAM,IAAI,KAAsB;AACtC,OAAK,MAAM,KAAK,aAAa,EAAE,CAC7B,KAAI,IACF,EAAE,MACF,EAAE,OAAO,KAAK,OAAO;GAAE,MAAM,EAAE;GAAM,SAAS,EAAE;GAAM,EAAE,CACzD;AAEH,SAAO;IACN,CAAC,UAAU,CAAC;CAEf,MAAM,2BAA2B,aAC9B,gBACC,QAAQ,QAAQ,gBAAgB,IAAI,YAAY,IAAI,EAAE,CAAC,EACzD,CAAC,gBAAgB,CAClB;AAID,KAAI,kBAAkB,CAAC,iBACrB,QACE,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,OAAD;GAAK,WAAU;aAA4C;GAErD,CAAA;EACF,CAAA;AAIV,KAAI,oBAAoB,CAAC,YACvB,QACE,oBAAC,OAAD;EAAK,WAAU;YACb,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,OAAD,EAAK,WAAU,uCAAwC,CAAA;IACvD,oBAAC,OAAD,EAAK,WAAU,uCAAwC,CAAA;IACvD,oBAAC,OAAD,EAAK,WAAU,uCAAwC,CAAA;IACnD;;EACF,CAAA;AAIV,QACE,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,sBAAD;GAAsB,KAAK;aACzB,oBAAC,mBAAD;IAAsB;cACpB,oBAAC,SAAD;KACE,iBAAiB;KACjB,WAAW;KACX,kBAAkB,OAAO,SAAS;AAChC,YAAM,uBAAuB,YAAY,KAAK;;KAEhD,oBAAoB,uBAAuB;KAK3C,sBAAsB;KACtB,cAAc;KACS;KACZ;KACS;KACpB,iBAAiB,OAAO,cAAc;AACpC,YAAM,sBAAsB,YAAY,UAAU;;KAEpD,mBAAmB,sBAAsB;KACzB;KACS;KACzB,uBAAuB,OAAO,oBAAoB;AAChD,YAAM,4BAA4B,YAAY,gBAAgB;;KAEhE,yBAAyB,4BAA4B;KACrD,uBAAuB,OAAO,iBAAiB,SAAS;AACtD,YAAM,4BAA4B,YAAY;OAC5C;OACA;OACD,CAAC;;KAEJ,yBAAyB,4BAA4B;KACrD,oBAAoB,kBAClB,cAAc,mBAAmB;KAEnC,WAAW;KACX,sBAAsB,EAAE,QAAQ,SAAS,sBACvC,oBAAC,mBAAD;MACU;MACC;MACQ;MACd;MACH,UAAU,OAAO,aAAa;AAC5B,WAAI,gBACF,OAAM,sBAAsB,YAAY;QACtC,WAAW,gBAAgB;QAC3B,MAAM;QACP,CAAC;WAEF,OAAM,sBAAsB,YAAY,SAAS;AAEnD,gBAAS;;MAEX,cACE,sBAAsB,aACtB,sBAAsB;MAExB,WAAW;MACX,aAAa;MACb,4BAA4B,EAC1B,SACA,UAAU,gBAgBN,oBAAC,mBAAD;OAA4B;OAAS,MAAK;OAAa,CAAA;MAC7D,CAAA;KAEJ,yBAAyB,EAAE,QAAQ,cACjC,oBAAC,sBAAD;MACU;MACC;MACN;MACH,UAAU,OAAO,SAAS;AACxB,WAAI;AACF,cAAM,sBAAsB,YAAY,KAAK;AAC7C,iBAAS;eACH;;MAKV,cAAc,sBAAsB;MACpC,WAAW;MACX,KAAI;MACJ,4BAA4B,EAC1B,SACA,UAAU,gBAEV,oBAAC,mBAAD;OAA4B;OAAS,MAAK;OAAa,CAAA;MAEzD,CAAA;KAEJ,CAAA;IACgB,CAAA;GACC,CAAA;EACnB,CAAA;;;;;;AAQV,SAAS,kBAAkB,EACzB,SACA,QAKoB;CACpB,MAAM,EAAE,UAAU,cAAc;EAAE;EAAe;EAAgB,CAAC;AAClE,QACE,oBAAC,SAAD;EACE,MAAK;EACL,KAAK,MAAM;EACX,OAAQ,MAAM,SAAoB;EAClC,aAAY;EACZ,WAAU;EACV,UAAU,MAAM;EAChB,QAAQ,MAAM;EACd,CAAA;;;;;;;;AC/lBN,SAAS,aAAa,SAAiB,MAAuC;AAC5E,YAAW;EAAE,OAAO;EAAS;EAAM,CAAC;;AAGtC,SAAgB,cAAc,EAC5B,SAEA,YACA,WACA,aACA,SACA,cAEA,GAAG,YACqC;CACxC,MAAM,EAAE,WAAW,iBAAiB;CACpC,MAAM,iBAAiB,WAAW;CAClC,MAAM,aAAa,OAAO,cAAc;AAcxC,4BAZ0B,cAEtB,oBAAC,YAAD,EAAA,UACE,oBAAC,gBAAD;EAAgB,WAAU;YACxB,oBAAC,gBAAD,EAAA,UACE,oBAAC,gBAAD;GAAgB,WAAU;aAAgB;GAAwB,CAAA,EACnD,CAAA;EACF,CAAA,EACN,CAAA,EAEf,EAAE,CACH,CAC4C;AAE7C,QACE,oBAAC,OAAD;EAAK,GAAI;YACP,oBAAC,sBAAD;GAAsB,SAAS;GAA4B;GAAc,CAAA;EACrE,CAAA;;AAIV,MAAa,8BAAoD;CAC/D,YAAY;CACZ,aAAa;CACb,YAAY,CAAC;EAAE,IAAI;EAAW,OAAO;EAAW,CAAC;CACjD,QAAQ,EAAE;CACX"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
require("./FluidProvider-
|
|
2
|
+
require("./FluidProvider-DcpUKHrn.cjs");
|
|
3
3
|
require("./ScreenRenderer-aYfgv6mR.cjs");
|
|
4
4
|
require("./account-api-context-DZP9IiGg.cjs");
|
|
5
5
|
require("./store-api-context-D1gZn22Z.cjs");
|
|
@@ -29,7 +29,7 @@ require("./ContainerWidget-Cjwrq2MS.cjs");
|
|
|
29
29
|
require("./ImageWidget-xcE0sFf-.cjs");
|
|
30
30
|
require("./LinkWidget-B14FTQP7.cjs");
|
|
31
31
|
require("./ListWidget-wBDnXWxa.cjs");
|
|
32
|
-
require("./MySiteWidget-
|
|
32
|
+
require("./MySiteWidget-DRH4q_YV.cjs");
|
|
33
33
|
require("./scroll-arrows-DhwdUQBY.cjs");
|
|
34
34
|
require("./NestedWidget-C_2XwnW0.cjs");
|
|
35
35
|
require("./PointsWidget-CLUWrFjZ.cjs");
|
|
@@ -43,6 +43,6 @@ require("./ToDoWidget-BbeXt99H.cjs");
|
|
|
43
43
|
require("./VideoWidget-Bc6ZAAaA.cjs");
|
|
44
44
|
require("./ScreenHeaderContext-oIu5Bvhs.cjs");
|
|
45
45
|
require("./fluid-pay-api-adapter-BszgrFL6.cjs");
|
|
46
|
-
const require_ProfileScreen = require("./ProfileScreen-
|
|
46
|
+
const require_ProfileScreen = require("./ProfileScreen-C0nmvuW1.cjs");
|
|
47
47
|
exports.ProfileScreen = require_ProfileScreen.ProfileScreen;
|
|
48
48
|
exports.profileScreenPropertySchema = require_ProfileScreen.profileScreenPropertySchema;
|
|
@@ -105,6 +105,14 @@ const shareablesKeys = {
|
|
|
105
105
|
id
|
|
106
106
|
]
|
|
107
107
|
},
|
|
108
|
+
mediaProducts: {
|
|
109
|
+
all: ["mediaProducts"],
|
|
110
|
+
list: (mediaId) => [
|
|
111
|
+
"mediaProducts",
|
|
112
|
+
"list",
|
|
113
|
+
mediaId
|
|
114
|
+
]
|
|
115
|
+
},
|
|
108
116
|
shareLinks: {
|
|
109
117
|
all: ["shareLinks"],
|
|
110
118
|
link: (type, id, contactId, locale) => [
|
|
@@ -1952,6 +1960,108 @@ function MediaListingScreen(_props) {
|
|
|
1952
1960
|
})] });
|
|
1953
1961
|
}
|
|
1954
1962
|
//#endregion
|
|
1963
|
+
//#region ../../shareables/ui/src/components/SharePage/TaggedProductsList.tsx
|
|
1964
|
+
const DEFAULT_IMAGE$5 = "https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png";
|
|
1965
|
+
function resolvePrice(product) {
|
|
1966
|
+
let price = product.display_price || product.price;
|
|
1967
|
+
if (product.variants && product.variants.length > 0) {
|
|
1968
|
+
const firstVariant = product.variants[0];
|
|
1969
|
+
if (firstVariant?.display_price) price = firstVariant.display_price;
|
|
1970
|
+
else if (firstVariant?.price) price = firstVariant.price;
|
|
1971
|
+
}
|
|
1972
|
+
if (!price) return null;
|
|
1973
|
+
const numPrice = parseFloat(price.replace(/[^0-9.-]/g, ""));
|
|
1974
|
+
if (Number.isNaN(numPrice) || numPrice <= 0) return null;
|
|
1975
|
+
if (price.includes("$")) return price;
|
|
1976
|
+
return `$${numPrice.toFixed(2)}`;
|
|
1977
|
+
}
|
|
1978
|
+
function TaggedProductsList({ products, onProductClick }) {
|
|
1979
|
+
const renderImage = useRenderImage();
|
|
1980
|
+
const handleProductClick = (productId, e) => {
|
|
1981
|
+
e.stopPropagation();
|
|
1982
|
+
if (productId == null) return;
|
|
1983
|
+
onProductClick?.(productId);
|
|
1984
|
+
};
|
|
1985
|
+
if (!products || products.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1986
|
+
className: "mb-6",
|
|
1987
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1988
|
+
className: "mb-4 px-4",
|
|
1989
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
1990
|
+
className: "text-foreground text-[15px] leading-[1.4] font-semibold",
|
|
1991
|
+
children: "Tagged Products (0)"
|
|
1992
|
+
})
|
|
1993
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1994
|
+
className: "flex flex-1 items-center justify-center px-6 py-12",
|
|
1995
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1996
|
+
className: "text-center",
|
|
1997
|
+
children: [
|
|
1998
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1999
|
+
className: "text-muted-foreground mb-2",
|
|
2000
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ShoppingBag, { className: "mx-auto h-12 w-12" })
|
|
2001
|
+
}),
|
|
2002
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2003
|
+
className: "text-foreground mb-1 text-sm",
|
|
2004
|
+
children: "No Tagged Products"
|
|
2005
|
+
}),
|
|
2006
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2007
|
+
className: "text-muted-foreground text-xs",
|
|
2008
|
+
children: "No products are tagged in this playlist"
|
|
2009
|
+
})
|
|
2010
|
+
]
|
|
2011
|
+
})
|
|
2012
|
+
})]
|
|
2013
|
+
});
|
|
2014
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2015
|
+
className: "mb-6",
|
|
2016
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2017
|
+
className: "mb-4 px-4",
|
|
2018
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
|
|
2019
|
+
className: "text-foreground text-[15px] leading-[1.4] font-semibold",
|
|
2020
|
+
children: [
|
|
2021
|
+
"Tagged Products (",
|
|
2022
|
+
products.length,
|
|
2023
|
+
")"
|
|
2024
|
+
]
|
|
2025
|
+
})
|
|
2026
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2027
|
+
className: "px-4",
|
|
2028
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2029
|
+
className: "scrollbar-none flex gap-4 overflow-x-auto pb-2",
|
|
2030
|
+
children: products.map((product, index) => {
|
|
2031
|
+
const imageUrl = product.images?.[0]?.image_url || product.image_url || product.compressed_image_url || DEFAULT_IMAGE$5;
|
|
2032
|
+
const title = product.title || "Untitled";
|
|
2033
|
+
const displayPrice = resolvePrice(product);
|
|
2034
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2035
|
+
onClick: (e) => handleProductClick(product.id, e),
|
|
2036
|
+
className: "group bg-muted hover:bg-muted/60 flex w-[168px] shrink-0 flex-col gap-2 rounded-lg p-3 text-left transition-all",
|
|
2037
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2038
|
+
className: "bg-background relative h-[168px] w-full overflow-hidden rounded-lg",
|
|
2039
|
+
children: renderImage({
|
|
2040
|
+
src: imageUrl,
|
|
2041
|
+
alt: title,
|
|
2042
|
+
fill: true,
|
|
2043
|
+
className: "object-cover"
|
|
2044
|
+
})
|
|
2045
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2046
|
+
className: "flex min-w-0 flex-col gap-1",
|
|
2047
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
|
|
2048
|
+
className: "text-foreground flex items-start gap-1.5 text-[15px] leading-[1.4] font-semibold",
|
|
2049
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2050
|
+
className: "line-clamp-2",
|
|
2051
|
+
children: title
|
|
2052
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ArrowUpRight, { className: "text-foreground mt-0.5 h-3 w-3 shrink-0 opacity-0 transition-opacity group-hover:opacity-100" })]
|
|
2053
|
+
}), displayPrice && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2054
|
+
className: "text-foreground text-[15px] leading-[1.4] font-normal",
|
|
2055
|
+
children: displayPrice
|
|
2056
|
+
})]
|
|
2057
|
+
})]
|
|
2058
|
+
}, product.id ?? index);
|
|
2059
|
+
})
|
|
2060
|
+
})
|
|
2061
|
+
})]
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
2064
|
+
//#endregion
|
|
1955
2065
|
//#region ../../shareables/ui/src/components/screens/MediaDetailScreen.tsx
|
|
1956
2066
|
function getBadgeLabel(kind) {
|
|
1957
2067
|
switch (kind) {
|
|
@@ -1961,15 +2071,28 @@ function getBadgeLabel(kind) {
|
|
|
1961
2071
|
default: return "Media";
|
|
1962
2072
|
}
|
|
1963
2073
|
}
|
|
1964
|
-
function MediaDetailScreen({ mediaId, onNavigate
|
|
2074
|
+
function MediaDetailScreen({ mediaId, onNavigate, onBack }) {
|
|
1965
2075
|
const api = useShareablesApi();
|
|
1966
2076
|
const repContext = useRepContext();
|
|
1967
|
-
const { navigate, readOnly } = useShareablesUI();
|
|
2077
|
+
const { navigate, readOnly, mediaProductsApi } = useShareablesUI();
|
|
1968
2078
|
const { data: mediaResponse, isLoading } = (0, _tanstack_react_query.useQuery)({
|
|
1969
2079
|
queryKey: shareablesKeys.media.detail(Number(mediaId), repContext),
|
|
1970
2080
|
queryFn: () => api.media.getMediaById(Number(mediaId))
|
|
1971
2081
|
});
|
|
1972
2082
|
const { shareLink, loading: shareLinkLoading, error: shareLinkError } = useShareLink({ id: Number(mediaId) }, "Medium");
|
|
2083
|
+
const { data: mediaProductsData } = (0, _tanstack_react_query.useQuery)({
|
|
2084
|
+
queryKey: shareablesKeys.mediaProducts.list(Number(mediaId)),
|
|
2085
|
+
queryFn: () => mediaProductsApi.listMediaProducts(Number(mediaId)),
|
|
2086
|
+
enabled: !!mediaProductsApi
|
|
2087
|
+
});
|
|
2088
|
+
const taggedProducts = (0, react.useMemo)(() => mediaProductsData?.media_products?.map((p) => ({
|
|
2089
|
+
id: p.id,
|
|
2090
|
+
title: p.name ?? null,
|
|
2091
|
+
image_url: p.image_url ?? null,
|
|
2092
|
+
price: p.price ?? null,
|
|
2093
|
+
slug: p.slug ?? null,
|
|
2094
|
+
sku: p.sku ?? null
|
|
2095
|
+
})) ?? [], [mediaProductsData]);
|
|
1973
2096
|
const mediaItem = mediaResponse?.media;
|
|
1974
2097
|
const displayTitle = mediaItem?.title || "";
|
|
1975
2098
|
const displayImage = mediaItem?.image_url || "";
|
|
@@ -2045,7 +2168,14 @@ function MediaDetailScreen({ mediaId, onNavigate: _onNavigate, onBack }) {
|
|
|
2045
2168
|
isVideo,
|
|
2046
2169
|
relateableId: Number(mediaId),
|
|
2047
2170
|
relateableType: "Medium"
|
|
2048
|
-
})
|
|
2171
|
+
}),
|
|
2172
|
+
children: taggedProducts.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Separator, { className: "bg-foreground my-4" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2173
|
+
className: "bg-background rounded-lg",
|
|
2174
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TaggedProductsList, {
|
|
2175
|
+
products: taggedProducts,
|
|
2176
|
+
onProductClick: (productId) => onNavigate?.("product", String(productId))
|
|
2177
|
+
})
|
|
2178
|
+
})] })
|
|
2049
2179
|
});
|
|
2050
2180
|
}
|
|
2051
2181
|
//#endregion
|
|
@@ -9489,7 +9619,7 @@ function MediaCreateScreen({ onNavigate, onBack }) {
|
|
|
9489
9619
|
}
|
|
9490
9620
|
//#endregion
|
|
9491
9621
|
//#region ../../shareables/ui/src/components/playlists/PlaylistCard.tsx
|
|
9492
|
-
const DEFAULT_IMAGE$
|
|
9622
|
+
const DEFAULT_IMAGE$4 = "https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png";
|
|
9493
9623
|
function PlaylistCard({ title, imageUrl, href, itemCount, isFavorited = false, isSelectable = false, isSelected = false, canEdit = false, onSelectionChange, onToggleFavorite, onEdit, onDelete }) {
|
|
9494
9624
|
const { navigate } = useShareablesUI();
|
|
9495
9625
|
const renderImage = useRenderImage();
|
|
@@ -9514,7 +9644,7 @@ function PlaylistCard({ title, imageUrl, href, itemCount, isFavorited = false, i
|
|
|
9514
9644
|
className: "bg-muted relative aspect-square overflow-hidden rounded-lg",
|
|
9515
9645
|
children: [
|
|
9516
9646
|
renderImage({
|
|
9517
|
-
src: imgError ? DEFAULT_IMAGE$
|
|
9647
|
+
src: imgError ? DEFAULT_IMAGE$4 : imageUrl || DEFAULT_IMAGE$4,
|
|
9518
9648
|
alt: title,
|
|
9519
9649
|
fill: true,
|
|
9520
9650
|
className: "object-cover transition-transform group-hover:scale-105",
|
|
@@ -9969,108 +10099,6 @@ const NAVIGABLE_RELATEABLE_TYPES = new Set([
|
|
|
9969
10099
|
"Medium"
|
|
9970
10100
|
]);
|
|
9971
10101
|
//#endregion
|
|
9972
|
-
//#region ../../shareables/ui/src/components/SharePage/TaggedProductsList.tsx
|
|
9973
|
-
const DEFAULT_IMAGE$4 = "https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png";
|
|
9974
|
-
function resolvePrice(product) {
|
|
9975
|
-
let price = product.display_price || product.price;
|
|
9976
|
-
if (product.variants && product.variants.length > 0) {
|
|
9977
|
-
const firstVariant = product.variants[0];
|
|
9978
|
-
if (firstVariant?.display_price) price = firstVariant.display_price;
|
|
9979
|
-
else if (firstVariant?.price) price = firstVariant.price;
|
|
9980
|
-
}
|
|
9981
|
-
if (!price) return null;
|
|
9982
|
-
const numPrice = parseFloat(price.replace(/[^0-9.-]/g, ""));
|
|
9983
|
-
if (Number.isNaN(numPrice) || numPrice <= 0) return null;
|
|
9984
|
-
if (price.includes("$")) return price;
|
|
9985
|
-
return `$${numPrice.toFixed(2)}`;
|
|
9986
|
-
}
|
|
9987
|
-
function TaggedProductsList({ products, onProductClick }) {
|
|
9988
|
-
const renderImage = useRenderImage();
|
|
9989
|
-
const handleProductClick = (productId, e) => {
|
|
9990
|
-
e.stopPropagation();
|
|
9991
|
-
if (productId == null) return;
|
|
9992
|
-
onProductClick?.(productId);
|
|
9993
|
-
};
|
|
9994
|
-
if (!products || products.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9995
|
-
className: "mb-6",
|
|
9996
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9997
|
-
className: "mb-4 px-4",
|
|
9998
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
9999
|
-
className: "text-foreground text-[15px] leading-[1.4] font-semibold",
|
|
10000
|
-
children: "Tagged Products (0)"
|
|
10001
|
-
})
|
|
10002
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10003
|
-
className: "flex flex-1 items-center justify-center px-6 py-12",
|
|
10004
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10005
|
-
className: "text-center",
|
|
10006
|
-
children: [
|
|
10007
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10008
|
-
className: "text-muted-foreground mb-2",
|
|
10009
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ShoppingBag, { className: "mx-auto h-12 w-12" })
|
|
10010
|
-
}),
|
|
10011
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10012
|
-
className: "text-foreground mb-1 text-sm",
|
|
10013
|
-
children: "No Tagged Products"
|
|
10014
|
-
}),
|
|
10015
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10016
|
-
className: "text-muted-foreground text-xs",
|
|
10017
|
-
children: "No products are tagged in this playlist"
|
|
10018
|
-
})
|
|
10019
|
-
]
|
|
10020
|
-
})
|
|
10021
|
-
})]
|
|
10022
|
-
});
|
|
10023
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10024
|
-
className: "mb-6",
|
|
10025
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10026
|
-
className: "mb-4 px-4",
|
|
10027
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
|
|
10028
|
-
className: "text-foreground text-[15px] leading-[1.4] font-semibold",
|
|
10029
|
-
children: [
|
|
10030
|
-
"Tagged Products (",
|
|
10031
|
-
products.length,
|
|
10032
|
-
")"
|
|
10033
|
-
]
|
|
10034
|
-
})
|
|
10035
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10036
|
-
className: "px-4",
|
|
10037
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10038
|
-
className: "scrollbar-none flex gap-4 overflow-x-auto pb-2",
|
|
10039
|
-
children: products.map((product, index) => {
|
|
10040
|
-
const imageUrl = product.images?.[0]?.image_url || product.image_url || product.compressed_image_url || DEFAULT_IMAGE$4;
|
|
10041
|
-
const title = product.title || "Untitled";
|
|
10042
|
-
const displayPrice = resolvePrice(product);
|
|
10043
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
10044
|
-
onClick: (e) => handleProductClick(product.id, e),
|
|
10045
|
-
className: "group bg-muted hover:bg-muted/60 flex w-[168px] shrink-0 flex-col gap-2 rounded-lg p-3 text-left transition-all",
|
|
10046
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10047
|
-
className: "bg-background relative h-[168px] w-full overflow-hidden rounded-lg",
|
|
10048
|
-
children: renderImage({
|
|
10049
|
-
src: imageUrl,
|
|
10050
|
-
alt: title,
|
|
10051
|
-
fill: true,
|
|
10052
|
-
className: "object-cover"
|
|
10053
|
-
})
|
|
10054
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10055
|
-
className: "flex min-w-0 flex-col gap-1",
|
|
10056
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
|
|
10057
|
-
className: "text-foreground flex items-start gap-1.5 text-[15px] leading-[1.4] font-semibold",
|
|
10058
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10059
|
-
className: "line-clamp-2",
|
|
10060
|
-
children: title
|
|
10061
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ArrowUpRight, { className: "text-foreground mt-0.5 h-3 w-3 shrink-0 opacity-0 transition-opacity group-hover:opacity-100" })]
|
|
10062
|
-
}), displayPrice && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10063
|
-
className: "text-foreground text-[15px] leading-[1.4] font-normal",
|
|
10064
|
-
children: displayPrice
|
|
10065
|
-
})]
|
|
10066
|
-
})]
|
|
10067
|
-
}, product.id ?? index);
|
|
10068
|
-
})
|
|
10069
|
-
})
|
|
10070
|
-
})]
|
|
10071
|
-
});
|
|
10072
|
-
}
|
|
10073
|
-
//#endregion
|
|
10074
10102
|
//#region ../../shareables/ui/src/components/SharePage/PlaylistItemsList.tsx
|
|
10075
10103
|
const DEFAULT_IMAGE$3 = "https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png";
|
|
10076
10104
|
function getItemType(type, kind) {
|
|
@@ -13469,4 +13497,4 @@ Object.defineProperty(exports, "shareablesScreenPropertySchema", {
|
|
|
13469
13497
|
}
|
|
13470
13498
|
});
|
|
13471
13499
|
|
|
13472
|
-
//# sourceMappingURL=ShareablesScreen-
|
|
13500
|
+
//# sourceMappingURL=ShareablesScreen-A69L0Nok.cjs.map
|