FormPayment Forms
Betaalformulier met methode-keuze (iDEAL/creditcard/SEPA), kaartvelden en ordersamenvatting.
src/components/forms/FormPayment.astro
---
/**
* FormPayment — betaalformulier met methode-keuze (iDEAL/creditcard/SEPA),
* kaartvelden en een ordersamenvatting bovenaan. Velden zijn visueel (demo).
*
* Props:
* - summaryLabel?: string
* - amount?: string
* - summaryDesc?: string
* - heading?: string
* - methods?: { value: string; label: string }[]
* - securityNote?: string
* - submitLabel?: string
*/
interface Props {
summaryLabel?: string;
amount?: string;
summaryDesc?: string;
heading?: string;
methods?: { value: string; label: string }[];
securityNote?: string;
submitLabel?: string;
}
const {
summaryLabel = 'Totaal te betalen',
amount = '€ 750 / maand',
summaryDesc = 'Growth pakket, maand 1',
heading = 'Betalingsgegevens',
methods = [
{ value: 'ideal', label: 'iDEAL' },
{ value: 'card', label: 'Creditcard' },
{ value: 'sepa', label: 'SEPA Bankoverschrijving' },
],
securityNote = 'Betalingen worden verwerkt via een beveiligde SSL-verbinding',
submitLabel = 'Betaling bevestigen',
} = Astro.props;
---
<section class="bl-section fpm">
<div class="bl-inner fpm-inner">
<div class="fpm-card">
<div class="fpm-order-summary">
<div class="fpm-order-label">{summaryLabel}</div>
<div class="fpm-order-amount">{amount}</div>
<div class="fpm-order-desc">{summaryDesc}</div>
</div>
<h2 class="fpm-heading">{heading}</h2>
<form class="fpm-form" novalidate aria-label="Betalingsformulier (demo)">
<div class="fpm-methods" role="group" aria-label="Betaalmethode">
{methods.map((m, i) => (
<label class="fpm-method">
<input class="fpm-method-input" type="radio" name="payment_method" value={m.value} checked={i === 0} />
<span class="fpm-method-box">{m.label}</span>
</label>
))}
</div>
<div class="fpm-card-fields">
<div class="fpm-field">
<label class="fpm-label" for="fpm-holder">Naam kaarthouder</label>
<input class="fpm-input" type="text" id="fpm-holder" name="card_holder" placeholder="Naam kaarthouder" autocomplete="cc-name" />
</div>
<div class="fpm-field">
<label class="fpm-label" for="fpm-number">Kaartnummer</label>
<input class="fpm-input fpm-input--card" type="text" id="fpm-number" name="card_number" placeholder="1234 5678 9012 3456" maxlength="19" autocomplete="cc-number" inputmode="numeric" />
</div>
<div class="fpm-row">
<div class="fpm-field">
<label class="fpm-label" for="fpm-expiry">Vervaldatum</label>
<input class="fpm-input" type="text" id="fpm-expiry" name="expiry" placeholder="MM / JJ" maxlength="7" autocomplete="cc-exp" inputmode="numeric" />
</div>
<div class="fpm-field">
<label class="fpm-label" for="fpm-cvv">CVV<span class="fpm-tooltip" title="3-cijferige code op de achterkant van je kaart">?</span></label>
<input class="fpm-input" type="text" id="fpm-cvv" name="cvv" placeholder="•••" maxlength="4" autocomplete="cc-csc" inputmode="numeric" />
</div>
</div>
</div>
<div class="fpm-security">
<span class="fpm-security-icon" aria-hidden="true">→</span>
<span>{securityNote}</span>
</div>
<button class="fpm-submit" type="submit">{submitLabel}</button>
</form>
</div>
</div>
</section>
<style>
.fpm-inner{display:flex;justify-content:center}
.fpm-card{width:100%;max-width:520px}
.fpm-order-summary{background:var(--color-primary, #0a0a0a);color:#fff;padding:1.5rem;border-radius:12px;margin-bottom:2rem;text-align:center}
.fpm-order-label{font-size:.8rem;color:#aaa;text-transform:uppercase;letter-spacing:.1em;margin-bottom:.25rem}
.fpm-order-amount{font-size:2rem;font-weight:800;margin-bottom:.25rem}
.fpm-order-desc{font-size:1rem;color:#e8e8e8}
.fpm-heading{font-size:1.4rem;font-weight:800;color:var(--color-primary, #0a0a0a);margin:0 0 1.5rem}
.fpm-form{display:flex;flex-direction:column;gap:1.25rem}
.fpm-methods{display:flex;gap:.75rem;flex-wrap:wrap}
.fpm-method{cursor:pointer;flex:1;min-width:120px}
.fpm-method-input{display:none}
.fpm-method-box{display:flex;align-items:center;justify-content:center;gap:.5rem;padding:.75rem;background:#f5f5f5;border:1.5px solid transparent;border-radius:8px;font-size:1rem;font-weight:500;color:#374151;transition:border-color .15s,background-color .15s,color .15s}
.fpm-method-input:checked+.fpm-method-box{border-color:var(--color-accent, #6366f1);background:#eef2ff;color:var(--color-accent, #6366f1);font-weight:600}
.fpm-card-fields{display:flex;flex-direction:column;gap:1rem;background:#f9f9f9;padding:1.25rem;border-radius:10px}
.fpm-row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
.fpm-field{display:flex;flex-direction:column;gap:.35rem}
.fpm-label{font-size:.95rem;font-weight:600;color:var(--color-primary, #0a0a0a);display:flex;align-items:center;gap:.35rem}
.fpm-tooltip{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:50%;background:#ddd;color:#555;font-size:.7rem;font-weight:700;cursor:help}
.fpm-input{padding:.7rem .9rem;border:1.5px solid #ddd;border-radius:8px;font-size:1rem;color:var(--color-primary, #0a0a0a);background:#fff;transition:border-color .2s;font-family:inherit;box-sizing:border-box;width:100%}
.fpm-input:focus{outline:none;border-color:var(--color-accent, #6366f1);box-shadow:0 0 0 3px #6366f11f}
.fpm-security{display:flex;align-items:center;gap:.5rem;font-size:.875rem;color:#555}
.fpm-security-icon{font-size:1rem}
.fpm-submit{padding:.95rem;background:var(--color-accent, #6366f1);color:#fff;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer;transition:opacity .2s}
.fpm-submit:hover{opacity:.88}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
summaryLabel | string | 'Totaal te betalen' | Label boven het bedrag |
amount | string | - | Te betalen bedrag |
summaryDesc | string | - | Omschrijving onder het bedrag |
heading | string | 'Betalingsgegevens' | Kop boven het formulier |
methods | { value: string; label: string }[] | - | Betaalmethoden; eerste staat standaard aan |
securityNote | string | - | Beveiligingsmelding onderaan |
submitLabel | string | 'Betaling bevestigen' | Tekst op de submit-knop |
* = verplicht