refactor: migrate to common eslint+prettier configs (#4168)

* refactor: migrate to common eslint+prettier configs

* fix: prettier frontend

* feat: config changes

* fix: lint issues

* fix: lint

* fix: type imports

* fix: cyclical import issue

* fix: lockfile

* fix: missing dep

* fix: switch to tabs

* fix: continue switch to tabs

* fix: rustfmt parity

* fix: moderation lint issue

* fix: lint issues

* fix: ui intl

* fix: lint issues

* Revert "fix: rustfmt parity"

This reverts commit cb99d2376c321d813d4b7fc7e2a213bb30a54711.

* feat: revert last rs
This commit is contained in:
Cal H.
2025-08-14 21:48:38 +01:00
committed by GitHub
parent 82697278dc
commit 2aabcf36ee
702 changed files with 101360 additions and 102020 deletions

View File

@@ -1,41 +1,41 @@
import { computed, onMounted, onUnmounted, type Ref } from 'vue'
import { useElementSize } from '@vueuse/core'
import { computed, onMounted, onUnmounted, type Ref } from 'vue'
export interface DynamicFontSizeOptions {
containerElement: Ref<HTMLElement | null>
text: Ref<string | undefined>
baseFontSize?: number
minFontSize?: number
maxFontSize?: number
availableWidthRatio?: number
maxContainerWidth?: number
padding?: number
fontFamily?: string
fontWeight?: string | number
containerElement: Ref<HTMLElement | null>
text: Ref<string | undefined>
baseFontSize?: number
minFontSize?: number
maxFontSize?: number
availableWidthRatio?: number
maxContainerWidth?: number
padding?: number
fontFamily?: string
fontWeight?: string | number
}
export function useDynamicFontSize(options: DynamicFontSizeOptions) {
const {
containerElement,
text,
baseFontSize = 1.25,
minFontSize = 0.75,
maxFontSize = 2,
availableWidthRatio = 0.9,
maxContainerWidth = 400,
padding = 24,
fontFamily = 'inherit',
fontWeight = 'inherit',
} = options
const {
containerElement,
text,
baseFontSize = 1.25,
minFontSize = 0.75,
maxFontSize = 2,
availableWidthRatio = 0.9,
maxContainerWidth = 400,
padding = 24,
fontFamily = 'inherit',
fontWeight = 'inherit',
} = options
const { width: containerWidth } = useElementSize(containerElement)
let measurementElement: HTMLElement | null = null
const { width: containerWidth } = useElementSize(containerElement)
let measurementElement: HTMLElement | null = null
const createMeasurementElement = () => {
if (measurementElement) return measurementElement
const createMeasurementElement = () => {
if (measurementElement) return measurementElement
measurementElement = document.createElement('div')
measurementElement.style.cssText = `
measurementElement = document.createElement('div')
measurementElement.style.cssText = `
position: absolute;
top: -9999px;
left: -9999px;
@@ -45,73 +45,73 @@ export function useDynamicFontSize(options: DynamicFontSizeOptions) {
font-family: ${fontFamily};
font-weight: ${fontWeight};
`
measurementElement.setAttribute('aria-hidden', 'true')
document.body.appendChild(measurementElement)
measurementElement.setAttribute('aria-hidden', 'true')
document.body.appendChild(measurementElement)
return measurementElement
}
return measurementElement
}
const cleanupMeasurementElement = () => {
if (measurementElement?.parentNode) {
measurementElement.parentNode.removeChild(measurementElement)
measurementElement = null
}
}
const cleanupMeasurementElement = () => {
if (measurementElement?.parentNode) {
measurementElement.parentNode.removeChild(measurementElement)
measurementElement = null
}
}
const measureTextWidth = (textContent: string, fontSize: number): number => {
if (!textContent) return 0
const measureTextWidth = (textContent: string, fontSize: number): number => {
if (!textContent) return 0
const element = createMeasurementElement()
element.style.fontSize = `${fontSize}rem`
element.textContent = textContent
const element = createMeasurementElement()
element.style.fontSize = `${fontSize}rem`
element.textContent = textContent
return element.getBoundingClientRect().width
}
return element.getBoundingClientRect().width
}
const findOptimalFontSize = (textContent: string, availableWidth: number): number => {
let low = minFontSize
let high = maxFontSize
let bestSize = minFontSize
const findOptimalFontSize = (textContent: string, availableWidth: number): number => {
let low = minFontSize
let high = maxFontSize
let bestSize = minFontSize
const maxWidth = measureTextWidth(textContent, maxFontSize)
if (maxWidth <= availableWidth) return maxFontSize
const maxWidth = measureTextWidth(textContent, maxFontSize)
if (maxWidth <= availableWidth) return maxFontSize
for (let i = 0; i < 8; i++) {
const mid = (low + high) / 2
const width = measureTextWidth(textContent, mid)
for (let i = 0; i < 8; i++) {
const mid = (low + high) / 2
const width = measureTextWidth(textContent, mid)
if (width <= availableWidth) {
bestSize = mid
low = mid
} else {
high = mid
}
if (width <= availableWidth) {
bestSize = mid
low = mid
} else {
high = mid
}
if (high - low < 0.01) break
}
if (high - low < 0.01) break
}
return Math.max(bestSize, minFontSize)
}
return Math.max(bestSize, minFontSize)
}
const fontSize = computed(() => {
if (!text.value || !containerWidth.value) return `${baseFontSize}rem`
const fontSize = computed(() => {
if (!text.value || !containerWidth.value) return `${baseFontSize}rem`
const availableWidth =
Math.min(containerWidth.value * availableWidthRatio, maxContainerWidth) - padding
const availableWidth =
Math.min(containerWidth.value * availableWidthRatio, maxContainerWidth) - padding
const baseWidth = measureTextWidth(text.value, baseFontSize)
if (baseWidth <= availableWidth) return `${baseFontSize}rem`
const baseWidth = measureTextWidth(text.value, baseFontSize)
if (baseWidth <= availableWidth) return `${baseFontSize}rem`
const optimalSize = findOptimalFontSize(text.value, availableWidth)
return `${optimalSize}rem`
})
const optimalSize = findOptimalFontSize(text.value, availableWidth)
return `${optimalSize}rem`
})
onMounted(createMeasurementElement)
onUnmounted(cleanupMeasurementElement)
onMounted(createMeasurementElement)
onUnmounted(cleanupMeasurementElement)
return {
fontSize,
containerWidth,
cleanup: cleanupMeasurementElement,
}
return {
fontSize,
containerWidth,
cleanup: cleanupMeasurementElement,
}
}

View File

@@ -1,23 +1,23 @@
import { createFormatter, type FormatOptions, type Formatter } from '@vintl/how-ago'
import type { IntlController } from '@vintl/vintl/controller'
import { useVIntl } from '@vintl/vintl'
import type { IntlController } from '@vintl/vintl/controller'
import { computed } from 'vue'
/* eslint-disable @typescript-eslint/no-explicit-any */
const formatters = new WeakMap<IntlController<any>, Formatter>()
export function useRelativeTime(): Formatter {
const vintl = useVIntl()
const vintl = useVIntl()
let formatter = formatters.get(vintl)
let formatter = formatters.get(vintl)
if (formatter == null) {
const formatterRef = computed(() => createFormatter(vintl.intl))
const defaultOptions: FormatOptions = { roundingMode: 'halfExpand' as const }
if (formatter == null) {
const formatterRef = computed(() => createFormatter(vintl.intl))
const defaultOptions: FormatOptions = { roundingMode: 'halfExpand' as const }
formatter = (value, options) => formatterRef.value(value, { ...options, ...defaultOptions })
formatters.set(vintl, formatter)
}
formatter = (value, options) => formatterRef.value(value, { ...options, ...defaultOptions })
formatters.set(vintl, formatter)
}
return formatter
return formatter
}

View File

@@ -1,2 +1,2 @@
export * from './how-ago'
export * from './dynamic-font-size'
export * from './how-ago'

View File

@@ -1,17 +1,18 @@
import type Stripe from 'stripe'
import { type Stripe as StripeJs, loadStripe, type StripeElements } from '@stripe/stripe-js'
import { computed, ref, type Ref } from 'vue'
import { loadStripe, type Stripe as StripeJs, type StripeElements } from '@stripe/stripe-js'
import type { ContactOption } from '@stripe/stripe-js/dist/stripe-js/elements/address'
import type Stripe from 'stripe'
import { computed, type Ref, ref } from 'vue'
import type {
ServerPlan,
BasePaymentIntentResponse,
ChargeRequestType,
CreatePaymentIntentRequest,
CreatePaymentIntentResponse,
PaymentRequestType,
ServerBillingInterval,
UpdatePaymentIntentRequest,
UpdatePaymentIntentResponse,
BasePaymentIntentResponse,
ChargeRequestType,
CreatePaymentIntentRequest,
CreatePaymentIntentResponse,
PaymentRequestType,
ServerBillingInterval,
ServerPlan,
UpdatePaymentIntentRequest,
UpdatePaymentIntentResponse,
} from '../utils/billing.ts'
// export type CreateElements = (
@@ -24,383 +25,386 @@ import type {
// }
export const useStripe = (
publishableKey: string,
customer: Stripe.Customer,
paymentMethods: Stripe.PaymentMethod[],
currency: string,
product: Ref<ServerPlan | undefined>,
interval: Ref<ServerBillingInterval>,
region: Ref<string | undefined>,
project: Ref<string | undefined>,
initiatePayment: (
body: CreatePaymentIntentRequest | UpdatePaymentIntentRequest,
) => Promise<CreatePaymentIntentResponse | UpdatePaymentIntentResponse>,
onError: (err: Error) => void,
publishableKey: string,
customer: Stripe.Customer,
paymentMethods: Stripe.PaymentMethod[],
currency: string,
product: Ref<ServerPlan | undefined>,
interval: Ref<ServerBillingInterval>,
region: Ref<string | undefined>,
project: Ref<string | undefined>,
initiatePayment: (
body: CreatePaymentIntentRequest | UpdatePaymentIntentRequest,
) => Promise<CreatePaymentIntentResponse | UpdatePaymentIntentResponse>,
onError: (err: Error) => void,
) => {
const stripe = ref<StripeJs | null>(null)
const stripe = ref<StripeJs | null>(null)
let elements: StripeElements | undefined = undefined
const elementsLoaded = ref<0 | 1 | 2>(0)
const loadingElementsFailed = ref<boolean>(false)
let elements: StripeElements | undefined = undefined
const elementsLoaded = ref<0 | 1 | 2>(0)
const loadingElementsFailed = ref<boolean>(false)
const paymentMethodLoading = ref(false)
const loadingFailed = ref<string>()
const paymentIntentId = ref<string>()
const tax = ref<number>()
const total = ref<number>()
const confirmationToken = ref<string>()
const submittingPayment = ref(false)
const selectedPaymentMethod = ref<Stripe.PaymentMethod>()
const inputtedPaymentMethod = ref<Stripe.PaymentMethod>()
const clientSecret = ref<string>()
const completingPurchase = ref<boolean>(false)
const paymentMethodLoading = ref(false)
const loadingFailed = ref<string>()
const paymentIntentId = ref<string>()
const tax = ref<number>()
const total = ref<number>()
const confirmationToken = ref<string>()
const submittingPayment = ref(false)
const selectedPaymentMethod = ref<Stripe.PaymentMethod>()
const inputtedPaymentMethod = ref<Stripe.PaymentMethod>()
const clientSecret = ref<string>()
const completingPurchase = ref<boolean>(false)
async function initialize() {
stripe.value = await loadStripe(publishableKey)
}
async function initialize() {
stripe.value = await loadStripe(publishableKey)
}
function createIntent(body: CreatePaymentIntentRequest): Promise<CreatePaymentIntentResponse> {
return initiatePayment(body) as Promise<CreatePaymentIntentResponse>
}
function createIntent(body: CreatePaymentIntentRequest): Promise<CreatePaymentIntentResponse> {
return initiatePayment(body) as Promise<CreatePaymentIntentResponse>
}
function updateIntent(body: UpdatePaymentIntentRequest): Promise<UpdatePaymentIntentResponse> {
return initiatePayment(body) as Promise<UpdatePaymentIntentResponse>
}
function updateIntent(body: UpdatePaymentIntentRequest): Promise<UpdatePaymentIntentResponse> {
return initiatePayment(body) as Promise<UpdatePaymentIntentResponse>
}
const planPrices = computed(() => {
return product.value?.prices.find((x) => x.currency_code === currency)
})
const planPrices = computed(() => {
return product.value?.prices.find((x) => x.currency_code === currency)
})
const createElements = (options) => {
const styles = getComputedStyle(document.body)
const createElements = (options) => {
const styles = getComputedStyle(document.body)
if (!stripe.value) {
throw new Error('Stripe API not yet loaded')
}
if (!stripe.value) {
throw new Error('Stripe API not yet loaded')
}
elements = stripe.value.elements({
appearance: {
variables: {
colorPrimary: styles.getPropertyValue('--color-brand'),
colorBackground: styles.getPropertyValue('--experimental-color-button-bg'),
colorText: styles.getPropertyValue('--color-base'),
colorTextPlaceholder: styles.getPropertyValue('--color-secondary'),
colorDanger: styles.getPropertyValue('--color-red'),
fontFamily: styles.getPropertyValue('--font-standard'),
spacingUnit: '0.25rem',
borderRadius: '0.75rem',
},
},
loader: 'never',
...options,
})
elements = stripe.value.elements({
appearance: {
variables: {
colorPrimary: styles.getPropertyValue('--color-brand'),
colorBackground: styles.getPropertyValue('--experimental-color-button-bg'),
colorText: styles.getPropertyValue('--color-base'),
colorTextPlaceholder: styles.getPropertyValue('--color-secondary'),
colorDanger: styles.getPropertyValue('--color-red'),
fontFamily: styles.getPropertyValue('--font-standard'),
spacingUnit: '0.25rem',
borderRadius: '0.75rem',
},
},
loader: 'never',
...options,
})
const paymentElement = elements.create('payment', {
layout: {
type: 'tabs',
defaultCollapsed: false,
},
})
paymentElement.mount('#payment-element')
const paymentElement = elements.create('payment', {
layout: {
type: 'tabs',
defaultCollapsed: false,
},
})
paymentElement.mount('#payment-element')
const contacts: ContactOption[] = []
const contacts: ContactOption[] = []
paymentMethods.forEach((method) => {
const addr = method.billing_details?.address
if (
addr &&
addr.line1 &&
addr.city &&
addr.postal_code &&
addr.country &&
addr.state &&
method.billing_details.name
) {
contacts.push({
address: {
line1: addr.line1,
line2: addr.line2 ?? undefined,
city: addr.city,
state: addr.state,
postal_code: addr.postal_code,
country: addr.country,
},
name: method.billing_details.name,
})
}
})
paymentMethods.forEach((method) => {
const addr = method.billing_details?.address
if (
addr &&
addr.line1 &&
addr.city &&
addr.postal_code &&
addr.country &&
addr.state &&
method.billing_details.name
) {
contacts.push({
address: {
line1: addr.line1,
line2: addr.line2 ?? undefined,
city: addr.city,
state: addr.state,
postal_code: addr.postal_code,
country: addr.country,
},
name: method.billing_details.name,
})
}
})
const addressElement = elements.create('address', {
mode: 'billing',
contacts: contacts.length > 0 ? contacts : undefined,
})
addressElement.mount('#address-element')
const addressElement = elements.create('address', {
mode: 'billing',
contacts: contacts.length > 0 ? contacts : undefined,
})
addressElement.mount('#address-element')
return { elements, paymentElement, addressElement }
}
return { elements, paymentElement, addressElement }
}
const primaryPaymentMethodId = computed<string | null>(() => {
if (customer && customer.invoice_settings && customer.invoice_settings.default_payment_method) {
const method = customer.invoice_settings.default_payment_method
if (typeof method === 'string') {
return method
} else {
return method.id
}
} else if (paymentMethods && paymentMethods[0] && paymentMethods[0].id) {
return paymentMethods[0].id
} else {
return null
}
})
const primaryPaymentMethodId = computed<string | null>(() => {
if (customer && customer.invoice_settings && customer.invoice_settings.default_payment_method) {
const method = customer.invoice_settings.default_payment_method
if (typeof method === 'string') {
return method
} else {
return method.id
}
} else if (paymentMethods && paymentMethods[0] && paymentMethods[0].id) {
return paymentMethods[0].id
} else {
return null
}
})
const loadStripeElements = async () => {
loadingFailed.value = undefined
try {
if (!customer && primaryPaymentMethodId.value) {
paymentMethodLoading.value = true
await refreshPaymentIntent(primaryPaymentMethodId.value, false)
paymentMethodLoading.value = false
}
const loadStripeElements = async () => {
loadingFailed.value = undefined
try {
if (!customer && primaryPaymentMethodId.value) {
paymentMethodLoading.value = true
await refreshPaymentIntent(primaryPaymentMethodId.value, false)
paymentMethodLoading.value = false
}
if (!selectedPaymentMethod.value) {
elementsLoaded.value = 0
if (!selectedPaymentMethod.value) {
elementsLoaded.value = 0
const {
elements: newElements,
addressElement,
paymentElement,
} = createElements({
mode: 'payment',
currency: currency.toLowerCase(),
amount: product.value?.prices.find((x) => x.currency_code === currency)?.prices.intervals[
interval.value
],
paymentMethodCreation: 'manual',
setupFutureUsage: 'off_session',
})
const {
elements: newElements,
addressElement,
paymentElement,
} = createElements({
mode: 'payment',
currency: currency.toLowerCase(),
amount: product.value?.prices.find((x) => x.currency_code === currency)?.prices.intervals[
interval.value
],
paymentMethodCreation: 'manual',
setupFutureUsage: 'off_session',
})
elements = newElements
paymentElement.on('ready', () => {
elementsLoaded.value += 1
})
addressElement.on('ready', () => {
elementsLoaded.value += 1
})
}
} catch (err) {
loadingFailed.value = String(err)
console.log(err)
}
}
elements = newElements
paymentElement.on('ready', () => {
elementsLoaded.value += 1
})
addressElement.on('ready', () => {
elementsLoaded.value += 1
})
}
} catch (err) {
loadingFailed.value = String(err)
console.log(err)
}
}
async function refreshPaymentIntent(id: string, confirmation: boolean) {
try {
paymentMethodLoading.value = true
if (!confirmation) {
selectedPaymentMethod.value = paymentMethods.find((x) => x.id === id)
}
async function refreshPaymentIntent(id: string, confirmation: boolean) {
try {
paymentMethodLoading.value = true
if (!confirmation) {
selectedPaymentMethod.value = paymentMethods.find((x) => x.id === id)
}
const requestType: PaymentRequestType = confirmation
? {
type: 'confirmation_token',
token: id,
}
: {
type: 'payment_method',
id: id,
}
const requestType: PaymentRequestType = confirmation
? {
type: 'confirmation_token',
token: id,
}
: {
type: 'payment_method',
id: id,
}
if (!product.value) {
return handlePaymentError('No product selected')
}
if (!product.value) {
return handlePaymentError('No product selected')
}
const charge: ChargeRequestType = {
type: 'new',
product_id: product.value?.id,
interval: interval.value,
}
const charge: ChargeRequestType = {
type: 'new',
product_id: product.value?.id,
interval: interval.value,
}
let result: BasePaymentIntentResponse
let result: BasePaymentIntentResponse
const metadata: CreatePaymentIntentRequest['metadata'] = {
type: 'pyro',
server_region: region.value,
source: project.value
? {
project_id: project.value,
}
: {},
}
const metadata: CreatePaymentIntentRequest['metadata'] = {
type: 'pyro',
server_region: region.value,
source: project.value
? {
project_id: project.value,
}
: {},
}
if (paymentIntentId.value) {
result = await updateIntent({
...requestType,
charge,
existing_payment_intent: paymentIntentId.value,
metadata,
})
console.log(`Updated payment intent: ${interval.value} for ${result.total}`)
} else {
;({
payment_intent_id: paymentIntentId.value,
client_secret: clientSecret.value,
...result
} = await createIntent({
...requestType,
charge,
metadata: metadata,
}))
console.log(`Created payment intent: ${interval.value} for ${result.total}`)
}
if (paymentIntentId.value) {
result = await updateIntent({
...requestType,
charge,
existing_payment_intent: paymentIntentId.value,
metadata,
})
console.log(`Updated payment intent: ${interval.value} for ${result.total}`)
} else {
;({
payment_intent_id: paymentIntentId.value,
client_secret: clientSecret.value,
...result
} = await createIntent({
...requestType,
charge,
metadata: metadata,
}))
console.log(`Created payment intent: ${interval.value} for ${result.total}`)
}
tax.value = result.tax
total.value = result.total
tax.value = result.tax
total.value = result.total
if (confirmation) {
confirmationToken.value = id
if (result.payment_method) {
inputtedPaymentMethod.value = result.payment_method
}
}
} catch (err) {
handlePaymentError(err as string)
}
paymentMethodLoading.value = false
}
if (confirmation) {
confirmationToken.value = id
if (result.payment_method) {
inputtedPaymentMethod.value = result.payment_method
}
}
} catch (err) {
handlePaymentError(err as string)
}
paymentMethodLoading.value = false
}
async function createConfirmationToken() {
if (!elements) {
return handlePaymentError('No elements')
}
if (!stripe.value) {
return handlePaymentError('No stripe')
}
async function createConfirmationToken() {
if (!elements) {
return handlePaymentError('No elements')
}
if (!stripe.value) {
return handlePaymentError('No stripe')
}
const { error, confirmationToken: confirmation } = await stripe.value.createConfirmationToken({
elements,
})
const { error, confirmationToken: confirmation } = await stripe.value.createConfirmationToken({
elements,
})
if (error) {
handlePaymentError(error.message ?? 'Unknown error creating confirmation token')
return
}
if (error) {
handlePaymentError(error.message ?? 'Unknown error creating confirmation token')
return
}
return confirmation.id
}
return confirmation.id
}
function handlePaymentError(err: string | Error) {
paymentMethodLoading.value = false
completingPurchase.value = false
onError(typeof err === 'string' ? new Error(err) : err)
}
function handlePaymentError(err: string | Error) {
paymentMethodLoading.value = false
completingPurchase.value = false
onError(typeof err === 'string' ? new Error(err) : err)
}
async function createNewPaymentMethod() {
paymentMethodLoading.value = true
async function createNewPaymentMethod() {
paymentMethodLoading.value = true
if (!elements) {
return handlePaymentError('No elements')
}
if (!elements) {
return handlePaymentError('No elements')
}
const { error: submitError } = await elements.submit()
const { error: submitError } = await elements.submit()
if (submitError) {
return handlePaymentError(submitError.message ?? 'Unknown error creating payment method')
}
if (submitError) {
return handlePaymentError(submitError.message ?? 'Unknown error creating payment method')
}
const token = await createConfirmationToken()
if (!token) {
return handlePaymentError('Failed to create confirmation token')
}
await refreshPaymentIntent(token, true)
const token = await createConfirmationToken()
if (!token) {
return handlePaymentError('Failed to create confirmation token')
}
await refreshPaymentIntent(token, true)
if (!planPrices.value) {
return handlePaymentError('No plan prices')
}
if (!total.value) {
return handlePaymentError('No total amount')
}
if (!planPrices.value) {
return handlePaymentError('No plan prices')
}
if (!total.value) {
return handlePaymentError('No total amount')
}
elements.update({ currency: planPrices.value.currency_code.toLowerCase(), amount: total.value })
elements.update({
currency: planPrices.value.currency_code.toLowerCase(),
amount: total.value,
})
elementsLoaded.value = 0
confirmationToken.value = token
paymentMethodLoading.value = false
elementsLoaded.value = 0
confirmationToken.value = token
paymentMethodLoading.value = false
return token
}
return token
}
async function selectPaymentMethod(paymentMethod: Stripe.PaymentMethod | undefined) {
selectedPaymentMethod.value = paymentMethod
if (paymentMethod === undefined) {
await loadStripeElements()
} else {
refreshPaymentIntent(paymentMethod.id, false)
}
}
async function selectPaymentMethod(paymentMethod: Stripe.PaymentMethod | undefined) {
selectedPaymentMethod.value = paymentMethod
if (paymentMethod === undefined) {
await loadStripeElements()
} else {
refreshPaymentIntent(paymentMethod.id, false)
}
}
const loadingElements = computed(() => elementsLoaded.value < 2)
const loadingElements = computed(() => elementsLoaded.value < 2)
async function submitPayment(returnUrl: string) {
completingPurchase.value = true
const secert = clientSecret.value
async function submitPayment(returnUrl: string) {
completingPurchase.value = true
const secert = clientSecret.value
if (!secert) {
return handlePaymentError('No client secret')
}
if (!secert) {
return handlePaymentError('No client secret')
}
if (!stripe.value) {
return handlePaymentError('No stripe')
}
if (!stripe.value) {
return handlePaymentError('No stripe')
}
submittingPayment.value = true
const { error } = await stripe.value.confirmPayment({
clientSecret: secert,
confirmParams: {
confirmation_token: confirmationToken.value,
return_url: `${returnUrl}?priceId=${product.value?.prices.find((x) => x.currency_code === currency)?.id}&plan=${interval.value}`,
},
})
submittingPayment.value = true
const { error } = await stripe.value.confirmPayment({
clientSecret: secert,
confirmParams: {
confirmation_token: confirmationToken.value,
return_url: `${returnUrl}?priceId=${product.value?.prices.find((x) => x.currency_code === currency)?.id}&plan=${interval.value}`,
},
})
if (error) {
handlePaymentError(error.message ?? 'Unknown error submitting payment')
return false
}
submittingPayment.value = false
completingPurchase.value = false
return true
}
if (error) {
handlePaymentError(error.message ?? 'Unknown error submitting payment')
return false
}
submittingPayment.value = false
completingPurchase.value = false
return true
}
async function reloadPaymentIntent() {
console.log('selected:', selectedPaymentMethod.value)
console.log('token:', confirmationToken.value)
if (selectedPaymentMethod.value) {
await refreshPaymentIntent(selectedPaymentMethod.value.id, false)
} else if (confirmationToken.value) {
await refreshPaymentIntent(confirmationToken.value, true)
} else {
throw new Error('No payment method selected')
}
}
async function reloadPaymentIntent() {
console.log('selected:', selectedPaymentMethod.value)
console.log('token:', confirmationToken.value)
if (selectedPaymentMethod.value) {
await refreshPaymentIntent(selectedPaymentMethod.value.id, false)
} else if (confirmationToken.value) {
await refreshPaymentIntent(confirmationToken.value, true)
} else {
throw new Error('No payment method selected')
}
}
const hasPaymentMethod = computed(() => selectedPaymentMethod.value || confirmationToken.value)
const hasPaymentMethod = computed(() => selectedPaymentMethod.value || confirmationToken.value)
return {
initializeStripe: initialize,
selectPaymentMethod,
reloadPaymentIntent,
primaryPaymentMethodId,
selectedPaymentMethod,
inputtedPaymentMethod,
hasPaymentMethod,
createNewPaymentMethod,
loadingElements,
loadingElementsFailed,
paymentMethodLoading,
loadStripeElements,
tax,
total,
submitPayment,
completingPurchase,
}
return {
initializeStripe: initialize,
selectPaymentMethod,
reloadPaymentIntent,
primaryPaymentMethodId,
selectedPaymentMethod,
inputtedPaymentMethod,
hasPaymentMethod,
createNewPaymentMethod,
loadingElements,
loadingElementsFailed,
paymentMethodLoading,
loadStripeElements,
tax,
total,
submitPayment,
completingPurchase,
}
}