{"version":3,"file":"CreditCardForm.mjs","names":["React","useEffect","useMemo","useState","useTranslation","UdpFlexbox","UdpRadioGroup","UdpSpinner","usePaymentProviderForm","PaymentDetails","PaymentMethodData","PaymentTenderTypeEnum","PaymentVendorFactoryEnum","useApiQuery","HostedPaymentError","NewCreditCardForm","ConfigService","OTHER_RADIO_VALUE","CreditCardFormProps","isFormDisabled","paymentDetails","externalId","tenantId","providerType","providerProps","isHostedPaymentPage","hasReadPropertiesError","readPropertiesMessageError","enabled","data","actionLabel","allowSaveMethod","setSelectedPaymentAccount","paymentAccount","onStatusChange","paymentFormResult","s2sToken","s2sTenantId","CreditCardForm","t","paymentAccounts","isLoading","loadingPaymentAccounts","pgV1ApiUrl","Boolean","savedMethods","hasSavedMethods","length","selected","setSelected","paymentTokenID","sel","find","s","showOtherForm","isValid","paymentProviderForm","CreditCard","items","savedItems","map","m","nickname","paymentToken","defaultValue","exp","expirationDate","Date","toLocaleDateString","month","year","label","value","String","e","target"],"sources":["../../../../src/utilities/form/paymentForm/CreditCardForm.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { UdpFlexbox } from '../../../UI/fluent-web-components/UdpFlexbox';\nimport { UdpRadioGroup } from '../../../UI/fluent-web-components/UdpRadioGroup';\nimport { UdpSpinner } from '../../../UI/fluent-web-components/UdpSpinner';\nimport { usePaymentProviderForm } from './usePaymentProviderForm';\nimport { PaymentDetails, PaymentMethodData } from './AccountPayment.model';\nimport { PaymentTenderTypeEnum } from '../../../enums/paymentTenderTypeEnum';\nimport { PaymentVendorFactoryEnum } from '../../../enums/paymentVendorFactoryEnum';\nimport { useApiQuery } from '../../useApiQuery';\nimport { HostedPaymentError } from './HostedPaymentError';\nimport { NewCreditCardForm } from './NewCreditCardForm';\nimport { ConfigService } from '../../../configService';\n\nconst OTHER_RADIO_VALUE = '__other__';\n\ninterface CreditCardFormProps {\n  isFormDisabled?: boolean;\n  paymentDetails: PaymentDetails;\n  externalId?: string;\n  tenantId?: string;\n  providerType?: PaymentVendorFactoryEnum | null;\n  providerProps?: any;\n  isHostedPaymentPage?: boolean | null;\n  hasReadPropertiesError?: boolean | null;\n  readPropertiesMessageError?: string | null;\n  enabled?: boolean | null;\n  data?: PaymentMethodData;\n  actionLabel?: string;\n  /** When false, the manual card form hides its \"save this card\" checkbox. */\n  allowSaveMethod?: boolean;\n  setSelectedPaymentAccount?: (paymentAccount: any) => void;\n  onStatusChange?: (paymentFormResult: any) => void;\n  /** S2S bearer token; forwarded to the hosted payment provider form. */\n  s2sToken?: string;\n  /** Tenant ID required alongside `s2sToken` for S2S mode API calls. */\n  s2sTenantId?: string;\n}\n\n/**\n * Credit-card branch of the payment form. Shows:\n *   - A radio list of saved cards (when any exist) + an \"Other / new card\"\n *     option, per D3 of REFACTOR_PLAN.md\n *   - Either the hosted-payment iframe (when `isHostedPaymentPage`) or the\n *     manual `NewCreditCardForm` once the user picks \"Other\".\n */\nexport const CreditCardForm = ({\n  isFormDisabled = false,\n  data,\n  externalId,\n  paymentDetails,\n  providerType = null,\n  providerProps = null,\n  isHostedPaymentPage,\n  hasReadPropertiesError,\n  readPropertiesMessageError,\n  actionLabel,\n  allowSaveMethod = true,\n  onStatusChange,\n  setSelectedPaymentAccount,\n  s2sToken,\n  s2sTenantId,\n}: CreditCardFormProps) => {\n  const { t } = useTranslation();\n\n  const { data: paymentAccounts, isLoading: loadingPaymentAccounts } = useApiQuery<any[]>(\n    ConfigService.pgV1ApiUrl,\n    `PaymentTokenCreditCard/${externalId}`,\n    {},\n    { enabled: Boolean(externalId) },\n  );\n\n  const savedMethods = paymentAccounts ?? [];\n  const hasSavedMethods = savedMethods.length > 0;\n\n  const [selected, setSelected] = useState<string>(OTHER_RADIO_VALUE);\n\n  // Default to the first saved method, or \"Other\" if none on file.\n  useEffect(() => {\n    setSelected(savedMethods[0]?.paymentTokenID || OTHER_RADIO_VALUE);\n  }, [savedMethods]);\n\n  // Push the selected saved token up so the submit flow can include it.\n  useEffect(() => {\n    if (selected && selected !== OTHER_RADIO_VALUE) {\n      const sel = savedMethods.find((s: any) => s?.paymentTokenID === selected);\n      setSelectedPaymentAccount?.(sel || null);\n    } else {\n      setSelectedPaymentAccount?.(null);\n    }\n  }, [selected, savedMethods, setSelectedPaymentAccount]);\n\n  const showOtherForm = selected === OTHER_RADIO_VALUE;\n\n  // Report validity to the parent picker so submit can be enabled. The hosted\n  // iframe component reports its own granular status; we only set a coarse\n  // \"ready to submit\" signal here.\n  useEffect(() => {\n    if (!showOtherForm) {\n      onStatusChange?.({ isValid: true });\n      return;\n    }\n    if (isHostedPaymentPage === false) {\n      // Manual entry — RFF blocks invalid submits at submit time.\n      onStatusChange?.({ isValid: true });\n    } else {\n      // Hosted iframe — wait for the iframe to report a token.\n      onStatusChange?.({ isValid: false });\n    }\n    // onStatusChange is intentionally omitted from deps; consumers may pass\n    // unstable references and we only want to fire when the selection / mode\n    // changes.\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [showOtherForm, isHostedPaymentPage]);\n\n  const paymentProviderForm = usePaymentProviderForm(\n    PaymentTenderTypeEnum.CreditCard,\n    providerType,\n    providerProps,\n    onStatusChange,\n    paymentDetails,\n    data,\n    s2sToken,\n    s2sTenantId,\n  );\n\n  const items = useMemo(() => {\n    const savedItems = savedMethods.map((m: any) => {\n      const nickname =\n        m?.paymentToken?.nickname ??\n        t('payments.card.savedCard', { defaultValue: 'Saved card' });\n      const exp = m?.expirationDate\n        ? new Date(m.expirationDate).toLocaleDateString('en-US', {\n            month: '2-digit',\n            year: '2-digit',\n          })\n        : null;\n      return {\n        label: exp ? `${nickname} (${exp})` : nickname,\n        value: String(m?.paymentTokenID ?? ''),\n      };\n    });\n    return [\n      ...savedItems,\n      {\n        label:\n          actionLabel ||\n          t('payments.card.useDifferentCard', { defaultValue: 'Use a different card' }),\n        value: OTHER_RADIO_VALUE,\n      },\n    ];\n  }, [savedMethods, actionLabel, t]);\n\n  if (loadingPaymentAccounts) {\n    return (\n      <UdpFlexbox direction=\"row\" justify=\"center\" align=\"center\">\n        <UdpSpinner size=\"medium\" />\n      </UdpFlexbox>\n    );\n  }\n\n  if (hasReadPropertiesError) {\n    return (\n      <HostedPaymentError\n        error={t('payments.form.configurationError', { defaultValue: 'Configuration error' })}\n        message={\n          readPropertiesMessageError ||\n          t('payments.form.unknownError', { defaultValue: 'Unknown error' })\n        }\n      />\n    );\n  }\n\n  return (\n    <UdpFlexbox direction=\"column\" gap=\"sm\" wrap=\"nowrap\">\n      {hasSavedMethods && (\n        <UdpRadioGroup\n          label={t('payments.card.savedCards', { defaultValue: 'Saved cards' })}\n          name=\"savedCreditCard\"\n          orientation=\"vertical\"\n          disabled={isFormDisabled}\n          value={selected}\n          items={items}\n          onChange={(e) => setSelected(String(e.target.value))}\n        />\n      )}\n\n      {showOtherForm &&\n        (isHostedPaymentPage ? (\n          paymentProviderForm\n        ) : (\n          <NewCreditCardForm\n            isFormDisabled={isFormDisabled}\n            paymentDetails={paymentDetails}\n            allowSaveMethod={allowSaveMethod}\n          />\n        ))}\n    </UdpFlexbox>\n  );\n};\n"],"mappings":"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"}