feat(activities): payment-rails pattern + provider-aware checkout #68

Merged
padreug merged 7 commits from payment-rails-pattern into dev 2026-05-23 21:18:54 +00:00
Showing only changes of commit b7b5a08594 - Show all commits

fix(base): FiatToggleField reads form state via useFormContext

The previous version called useField directly with a getter for the
field name. That created a child-local field rather than connecting
to the parent form's allow_fiat / fiat_currency state — so the
Switch's on/off visually toggled but the form never knew, and the
conditional Fiat currency dropdown never appeared.

Rewrite around the proven pattern used elsewhere in the dialog: bind
the inputs through FormField (the shadcn-vue / vee-validate Field
component) and reach for cross-field state via useFormContext.
showCurrencyDropdown now reads form.values[allowFiatField] directly,
which mirrors the parent's actual state, and the denomination-mirror
watch goes through form.setFieldValue.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Padreug 2026-05-23 19:30:03 +02:00

View file

@ -1,9 +1,10 @@
<script setup lang="ts">
import { computed, watch } from 'vue'
import { useField } from 'vee-validate'
import { useFormContext } from 'vee-validate'
import {
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
@ -37,21 +38,19 @@ const props = defineProps<{
disabled?: boolean
}>()
const { value: allowFiat, handleChange: setAllowFiat } = useField<boolean>(
() => props.allowFiatField,
)
const { value: fiatCurrency, setValue: setFiatCurrency } = useField<string>(
() => props.fiatCurrencyField,
)
const form = useFormContext()
const { hasAnyProvider, refresh } = useFiatProviders()
// Refresh once on mount so the disabled-state reflects providers the
// user may have just configured in another tab.
refresh()
const allowFiatValue = computed(() =>
Boolean(form.values[props.allowFiatField as keyof typeof form.values]),
)
const showCurrencyDropdown = computed(
() => allowFiat.value && props.denomination === 'sat',
() => allowFiatValue.value && props.denomination === 'sat',
)
// When the price is denominated in a fiat currency, the rail currency
@ -59,8 +58,8 @@ const showCurrencyDropdown = computed(
watch(
() => props.denomination,
(d) => {
if (d && d !== 'sat' && fiatCurrency.value !== d) {
setFiatCurrency(d)
if (d && d !== 'sat' && form.values[props.fiatCurrencyField as keyof typeof form.values] !== d) {
form.setFieldValue(props.fiatCurrencyField, d)
}
},
{ immediate: true },
@ -69,60 +68,60 @@ watch(
<template>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3 items-end">
<FormItem class="sm:col-span-2 flex flex-row items-center justify-between rounded-md border p-3">
<div class="space-y-0.5">
<FormLabel>Also accept fiat</FormLabel>
<FormDescription class="text-xs">
Buyers can pay with card or bank through your configured provider.
</FormDescription>
</div>
<FormControl>
<TooltipProvider v-if="!hasAnyProvider" :delay-duration="200">
<Tooltip>
<TooltipTrigger as-child>
<span class="inline-flex">
<Switch :model-value="false" disabled />
</span>
</TooltipTrigger>
<TooltipContent class="max-w-xs">
Your LNbits user has no fiat provider configured. Open
LNbits Account Fiat providers and add Stripe, PayPal,
or Square to enable this.
</TooltipContent>
</Tooltip>
</TooltipProvider>
<Switch
v-else
:model-value="allowFiat"
:disabled="disabled"
@update:model-value="setAllowFiat"
/>
</FormControl>
</FormItem>
<FormField v-slot="{ value, handleChange }" :name="allowFiatField">
<FormItem class="sm:col-span-2 flex flex-row items-center justify-between rounded-md border p-3">
<div class="space-y-0.5">
<FormLabel>Also accept fiat</FormLabel>
<FormDescription class="text-xs">
Buyers can pay with card or bank through your configured provider.
</FormDescription>
</div>
<FormControl>
<TooltipProvider v-if="!hasAnyProvider" :delay-duration="200">
<Tooltip>
<TooltipTrigger as-child>
<span class="inline-flex">
<Switch :model-value="false" disabled />
</span>
</TooltipTrigger>
<TooltipContent class="max-w-xs">
Your LNbits user has no fiat provider configured. Open
LNbits Account Fiat providers and add Stripe, PayPal,
or Square to enable this.
</TooltipContent>
</Tooltip>
</TooltipProvider>
<Switch
v-else
:model-value="value as boolean"
:disabled="disabled"
@update:model-value="handleChange"
/>
</FormControl>
</FormItem>
</FormField>
<FormItem v-show="showCurrencyDropdown">
<FormLabel>Fiat currency</FormLabel>
<FormControl>
<Select
:model-value="fiatCurrency"
:disabled="disabled"
@update:model-value="(v) => setFiatCurrency(v as string)"
>
<SelectTrigger>
<SelectValue placeholder="USD" />
</SelectTrigger>
<SelectContent>
<SelectItem
v-for="c in availableFiatCurrencies"
:key="c"
:value="c"
>
{{ c }}
</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
<FormField v-slot="{ componentField }" :name="fiatCurrencyField">
<FormItem v-show="showCurrencyDropdown">
<FormLabel>Fiat currency</FormLabel>
<FormControl>
<Select v-bind="componentField" :disabled="disabled">
<SelectTrigger>
<SelectValue placeholder="USD" />
</SelectTrigger>
<SelectContent>
<SelectItem
v-for="c in availableFiatCurrencies"
:key="c"
:value="c"
>
{{ c }}
</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</div>
</template>