Add per-quantity TPago payment links for multi-ticket checkout.

Each ticket quantity (1-5) can have its own TPago link so checkout, emails, and admin config use the correct fixed-amount URL.
This commit is contained in:
Michilis
2026-06-18 23:59:17 +00:00
parent 1b2463f4bc
commit fc4af38e8a
11 changed files with 195 additions and 21 deletions
+25 -8
View File
@@ -1519,15 +1519,32 @@ export default function AdminEventDetailPage() {
<div className="space-y-3 pt-3 border-t">
<div>
<label className="block text-xs font-medium text-gray-700 mb-1">
{locale === 'es' ? 'Enlace de Pago TPago' : 'TPago Payment Link'}
{locale === 'es' ? 'Enlaces de Pago TPago (por cantidad de tickets)' : 'TPago Payment Links (per ticket quantity)'}
</label>
<input
type="url"
value={paymentOverrides.tpagoLink ?? ''}
onChange={(e) => updatePaymentOverride('tpagoLink', e.target.value || null)}
placeholder={globalPaymentOptions?.tpagoLink || 'https://www.tpago.com.py/links?alias=...'}
className="w-full px-3 py-2 text-sm rounded-btn border border-secondary-light-gray focus:outline-none focus:ring-2 focus:ring-primary-yellow"
/>
<p className="text-[10px] text-gray-500 mb-2">
{locale === 'es'
? 'Cada enlace tiene un monto fijo. Un enlace distinto por cantidad de tickets.'
: 'Each link has a fixed amount. One link per ticket quantity.'}
</p>
<div className="space-y-2">
{([1, 2, 3, 4, 5] as const).map((qty) => {
const key = (qty === 1 ? 'tpagoLink' : `tpagoLink${qty}`) as keyof PaymentOptionsConfig;
return (
<div key={qty} className="flex items-center gap-2">
<span className="text-xs font-medium text-gray-600 w-20 flex-shrink-0">
{qty} {qty === 1 ? 'ticket' : 'tickets'}
</span>
<input
type="url"
value={(paymentOverrides[key] as string | null) ?? ''}
onChange={(e) => updatePaymentOverride(key, (e.target.value || null) as any)}
placeholder={(globalPaymentOptions?.[key] as string | null) || 'https://www.tpago.com.py/links?alias=...'}
className="flex-1 px-3 py-2 text-sm rounded-btn border border-secondary-light-gray focus:outline-none focus:ring-2 focus:ring-primary-yellow"
/>
</div>
);
})}
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div>
@@ -26,6 +26,10 @@ export default function PaymentOptionsPage() {
const [options, setOptions] = useState<PaymentOptionsConfig>({
tpagoEnabled: false,
tpagoLink: null,
tpagoLink2: null,
tpagoLink3: null,
tpagoLink4: null,
tpagoLink5: null,
tpagoInstructions: null,
tpagoInstructionsEs: null,
bankTransferEnabled: false,
@@ -140,13 +144,31 @@ export default function PaymentOptionsPage() {
<div className="space-y-4 pt-4 border-t">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
{locale === 'es' ? 'Enlace de Pago TPago' : 'TPago Payment Link'}
{locale === 'es' ? 'Enlaces de Pago TPago (por cantidad de tickets)' : 'TPago Payment Links (per ticket quantity)'}
</label>
<Input
value={options.tpagoLink || ''}
onChange={(e) => updateOption('tpagoLink', e.target.value || null)}
placeholder="https://www.tpago.com.py/links?alias=..."
/>
<p className="text-xs text-gray-500 mb-2">
{locale === 'es'
? 'Cada enlace tiene un monto fijo. Usá un enlace distinto para cada cantidad de tickets.'
: 'Each link has a fixed amount. Use a different link for each ticket quantity.'}
</p>
<div className="space-y-2">
{([1, 2, 3, 4, 5] as const).map((qty) => {
const key = (qty === 1 ? 'tpagoLink' : `tpagoLink${qty}`) as keyof PaymentOptionsConfig;
return (
<div key={qty} className="flex items-center gap-2">
<span className="text-sm font-medium text-gray-600 w-24 flex-shrink-0">
{qty} {locale === 'es' ? (qty === 1 ? 'ticket' : 'tickets') : (qty === 1 ? 'ticket' : 'tickets')}
</span>
<Input
value={(options[key] as string | null) || ''}
onChange={(e) => updateOption(key, (e.target.value || null) as any)}
placeholder="https://www.tpago.com.py/links?alias=..."
className="flex-1"
/>
</div>
);
})}
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>