JezK
Edit File: sc-payment-methods-list.entry.js.map
{"file":"sc-payment-methods-list.entry.js","mappings":";;;;;;;AAAA,MAAM,uBAAuB,GAAG,kVAAkV,CAAC;AACnX,mCAAe,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wECyEX,UAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;8EAwBI,UAAE;;;;;;;;;;;;;;;8EAcF,UAAE;;;;;;;;;;;;;;;;;;;;;;;8EAuBF,UAAE;;;;;;;;;;qJAyBK,UAAE;;;;;;;;;;mTAmBmF,UAAE,gHAC3C,UAAE;;;;;uRAgBrE,UAAE;;8aAQ0F,UAAE,yEAC5D,UAAE;;;;;;;;;;;;;;;;;;;;;gUAsCL,UAAE;;;oHAanC,UAAE;;;mHAUF,UAAE,uJAOyC,UAAE,qdAM7C,UAAE,4TAGF,UAAE,8HACuB,UAAE,kSAK3B,UAAE,gJAGF,UAAE,+OAM2C,UAAE,2RAI1C,UAAE,0RAGP,UAAE,kJAGF,UAAE;;;;;;;;;;;","names":[],"sources":["src/components/controllers/dashboard/payment-methods-list/sc-payment-methods-list.scss?tag=sc-payment-methods-list&encapsulation=shadow","src/components/controllers/dashboard/payment-methods-list/sc-payment-methods-list.tsx"],"sourcesContent":[":host {\n display: block;\n position: relative;\n}\n\n.payment-methods-list {\n display: grid;\n gap: 0.5em;\n\n sc-heading a {\n text-decoration: none;\n font-weight: var(--sc-font-weight-semibold);\n display: inline-flex;\n align-items: center;\n gap: 0.25em;\n color: var(--sc-color-primary-500);\n }\n}\n\n.payment-id {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n","import { Component, Element, h, Prop, State, Watch } from '@stencil/core';\nimport { __ } from '@wordpress/i18n';\nimport { addQueryArgs } from '@wordpress/url';\nimport apiFetch from '../../../../functions/fetch';\nimport { Customer, PaymentMethod } from '../../../../types';\nimport { onFirstVisible } from '../../../../functions/lazy';\n\n@Component({\n tag: 'sc-payment-methods-list',\n styleUrl: 'sc-payment-methods-list.scss',\n shadow: true,\n})\nexport class ScPaymentMethodsList {\n @Element() el: HTMLScPaymentMethodsListElement;\n\n /** Query to fetch paymentMethods */\n @Prop() query: object;\n\n /** The heading */\n @Prop() heading: string;\n\n /** Is this a customer */\n @Prop() isCustomer: boolean;\n\n /** Whether default payment method can be detached */\n @Prop() canDetachDefaultPaymentMethod: boolean = false;\n\n /** Loaded payment methods */\n @State() paymentMethods: Array<PaymentMethod> = [];\n\n /** Loading state */\n @State() loading: boolean;\n @State() busy: boolean;\n\n /** Error message */\n @State() error: string;\n\n /** Does this have a title slot */\n @State() hasTitleSlot: boolean;\n\n /** Stores the currently selected payment method for editing */\n @State() editPaymentMethod: PaymentMethod | false = false;\n\n /** Stores the currently selected payment method for editing */\n @State() deletePaymentMethod: PaymentMethod | false = false;\n\n /** Whether to cascade default payment method */\n @State() cascadeDefaultPaymentMethod: boolean = false;\n\n /** Only fetch if visible */\n componentWillLoad() {\n onFirstVisible(this.el, () => this.getPaymentMethods());\n this.handleSlotChange();\n }\n\n handleSlotChange() {\n this.hasTitleSlot = !!this.el.querySelector('[slot=\"title\"]');\n }\n\n /**\n * Delete the payment method.\n */\n async deleteMethod() {\n if (!this.deletePaymentMethod) return;\n try {\n this.busy = true;\n (await apiFetch({\n path: `surecart/v1/payment_methods/${this.deletePaymentMethod?.id}/detach`,\n method: 'PATCH',\n })) as PaymentMethod;\n // remove from view.\n this.paymentMethods = this.paymentMethods.filter(m => m.id !== (this.deletePaymentMethod as PaymentMethod)?.id);\n this.deletePaymentMethod = false;\n } catch (e) {\n alert(e?.messsage || __('Something went wrong', 'surecart'));\n } finally {\n this.busy = false;\n }\n }\n\n /**\n * Set the default payment method.\n */\n async setDefault() {\n if (!this.editPaymentMethod) return;\n try {\n this.error = '';\n this.busy = true;\n (await apiFetch({\n path: `surecart/v1/customers/${(this.editPaymentMethod?.customer as Customer)?.id}`,\n method: 'PATCH',\n data: {\n default_payment_method: this.editPaymentMethod?.id,\n cascade_default_payment_method: this.cascadeDefaultPaymentMethod,\n },\n })) as PaymentMethod;\n this.editPaymentMethod = false;\n } catch (e) {\n this.error = e?.message || __('Something went wrong', 'surecart');\n } finally {\n this.busy = false;\n }\n\n try {\n this.busy = true;\n this.paymentMethods = (await apiFetch({\n path: addQueryArgs(`surecart/v1/payment_methods/`, {\n expand: ['card', 'customer', 'billing_agreement', 'paypal_account', 'payment_instrument', 'bank_account'],\n ...this.query,\n }),\n })) as PaymentMethod[];\n } catch (e) {\n this.error = e?.message || __('Something went wrong', 'surecart');\n } finally {\n this.busy = false;\n }\n }\n\n /** Get all paymentMethods */\n async getPaymentMethods() {\n if (!this.isCustomer) {\n return;\n }\n\n try {\n this.loading = true;\n this.paymentMethods = (await apiFetch({\n path: addQueryArgs(`surecart/v1/payment_methods/`, {\n expand: ['card', 'customer', 'billing_agreement', 'paypal_account', 'payment_instrument', 'bank_account'],\n ...this.query,\n per_page: 100,\n }),\n })) as PaymentMethod[];\n } catch (e) {\n console.error(this.error);\n this.error = e?.message || __('Something went wrong', 'surecart');\n } finally {\n this.loading = false;\n }\n }\n\n renderLoading() {\n return (\n <sc-card noPadding>\n <sc-stacked-list>\n <sc-stacked-list-row style={{ '--columns': '4' }} mobile-size={500}>\n {[...Array(4)].map(() => (\n <sc-skeleton style={{ width: '100px', display: 'inline-block' }}></sc-skeleton>\n ))}\n </sc-stacked-list-row>\n </sc-stacked-list>\n </sc-card>\n );\n }\n\n renderEmpty() {\n return (\n <div>\n <sc-divider style={{ '--spacing': '0' }}></sc-divider>\n <slot name=\"empty\">\n <sc-empty icon=\"credit-card\">{__(\"You don't have any saved payment methods.\", 'surecart')}</sc-empty>\n </slot>\n </div>\n );\n }\n\n renderPaymentMethodActions(paymentMethod: PaymentMethod) {\n const { id, customer } = paymentMethod;\n\n // If this is a string, don't show the actions.\n if (typeof customer === 'string') return;\n\n // If this is the default payment method and it cannot be detached, don't show the actions.\n if (customer.default_payment_method === id && !this.canDetachDefaultPaymentMethod) return;\n\n return (\n <sc-dropdown placement=\"bottom-end\" slot=\"suffix\">\n <sc-icon role=\"button\" tabIndex={0} name=\"more-horizontal\" slot=\"trigger\"></sc-icon>\n <sc-menu>\n {customer.default_payment_method !== id && <sc-menu-item onClick={() => (this.editPaymentMethod = paymentMethod)}>{__('Make Default', 'surecart')}</sc-menu-item>}\n <sc-menu-item onClick={() => (this.deletePaymentMethod = paymentMethod)}>{__('Delete', 'surecart')}</sc-menu-item>\n </sc-menu>\n </sc-dropdown>\n );\n }\n\n renderList() {\n return this.paymentMethods.map(paymentMethod => {\n const { id, card, customer, live_mode, billing_agreement, paypal_account } = paymentMethod;\n return (\n <sc-stacked-list-row style={{ '--columns': billing_agreement ? '2' : '3' }}>\n <sc-payment-method paymentMethod={paymentMethod} />\n\n <div class=\"payment-id\">\n {!!card?.exp_month && (\n <span>\n {__('Exp.', 'surecart')}\n {card?.exp_month}/{card?.exp_year}\n </span>\n )}\n {!!paypal_account && paypal_account?.email}\n </div>\n\n <sc-flex justify-content=\"flex-start\" align-items=\"center\" style={{ '--spacing': '0.5em', 'marginLeft': 'auto' }}>\n {typeof customer !== 'string' && customer?.default_payment_method === id && <sc-tag type=\"info\">{__('Default', 'surecart')}</sc-tag>}\n {!live_mode && <sc-tag type=\"warning\">{__('Test', 'surecart')}</sc-tag>}\n </sc-flex>\n {this.renderPaymentMethodActions(paymentMethod)}\n </sc-stacked-list-row>\n );\n });\n }\n\n renderContent() {\n if (!this.isCustomer) {\n return this.renderEmpty();\n }\n\n if (this.loading) {\n return this.renderLoading();\n }\n\n if (this.paymentMethods?.length === 0) {\n return this.renderEmpty();\n }\n\n return (\n <sc-card no-padding>\n <sc-stacked-list>{this.renderList()}</sc-stacked-list>\n </sc-card>\n );\n }\n\n @Watch('editPaymentMethod')\n handleEditPaymentMethodChange() {\n // reset when payment method edit changes\n this.cascadeDefaultPaymentMethod = false;\n }\n\n render() {\n return (\n <sc-dashboard-module class=\"payment-methods-list\" error={this.error}>\n <span slot=\"heading\">\n <slot name=\"heading\">{this.heading || __('Payment Methods', 'surecart')}</slot>\n </span>\n\n {this.isCustomer && (\n <sc-flex slot=\"end\">\n <sc-button\n type=\"link\"\n href={addQueryArgs(window.location.href, {\n action: 'index',\n model: 'charge',\n })}\n >\n <sc-icon name=\"clock\" slot=\"prefix\"></sc-icon>\n {__('Payment History', 'surecart')}\n </sc-button>\n <sc-button\n type=\"link\"\n href={addQueryArgs(window.location.href, {\n action: 'create',\n model: 'payment_method',\n })}\n >\n <sc-icon name=\"plus\" slot=\"prefix\"></sc-icon>\n {__('Add', 'surecart')}\n </sc-button>\n </sc-flex>\n )}\n\n {this.renderContent()}\n\n <sc-dialog open={!!this.editPaymentMethod} label={__('Update Default Payment Method', 'surecart')} onScRequestClose={() => (this.editPaymentMethod = false)}>\n <sc-alert type=\"danger\" open={!!this.error}>\n {this.error}\n </sc-alert>\n <sc-flex flexDirection=\"column\" style={{ '--sc-flex-column-gap': 'var(--sc-spacing-small)' }}>\n <sc-alert type=\"info\" open>\n {__('A default payment method will be used as a fallback in case other payment methods get removed from a subscription.', 'surecart')}\n </sc-alert>\n <sc-switch checked={this.cascadeDefaultPaymentMethod} onScChange={e => (this.cascadeDefaultPaymentMethod = e.target.checked)}>\n {__('Update All Subscriptions', 'surecart')}\n <span slot=\"description\">{__('Update all existing subscriptions to use this payment method', 'surecart')}</span>\n </sc-switch>\n </sc-flex>\n <div slot=\"footer\">\n <sc-button type=\"text\" onClick={() => (this.editPaymentMethod = false)}>\n {__('Cancel', 'surecart')}\n </sc-button>\n <sc-button type=\"primary\" onClick={() => this.setDefault()}>\n {__('Make Default', 'surecart')}\n </sc-button>\n </div>\n {this.busy && <sc-block-ui spinner></sc-block-ui>}\n </sc-dialog>\n\n <sc-dialog open={!!this.deletePaymentMethod} label={__('Delete Payment Method', 'surecart')} onScRequestClose={() => (this.deletePaymentMethod = false)}>\n <sc-alert type=\"danger\" open={!!this.error}>\n {this.error}\n </sc-alert>\n <sc-text>{__('Are you sure you want to remove this payment method?', 'surecart')}</sc-text>\n <div slot=\"footer\">\n <sc-button type=\"text\" onClick={() => (this.deletePaymentMethod = false)}>\n {__('Cancel', 'surecart')}\n </sc-button>\n <sc-button type=\"primary\" onClick={() => this.deleteMethod()}>\n {__('Delete', 'surecart')}\n </sc-button>\n </div>\n {this.busy && <sc-block-ui spinner></sc-block-ui>}\n </sc-dialog>\n\n {this.busy && <sc-block-ui spinner></sc-block-ui>}\n </sc-dashboard-module>\n );\n }\n}\n"],"version":3}