FormSurvey Forms
Klanttevredenheidsformulier met 1-10 schaal, meerkeuzevragen en open tekstvelden.
src/components/forms/FormSurvey.astro
---
/**
* FormSurvey — klanttevredenheidsformulier: 1-10 schaal, meerkeuze en open velden.
*
* Props:
* - heading?: string
* - sub?: string
* - scaleQuestion?: string
* - scaleLow?: string
* - scaleHigh?: string
* - communicationOptions?: string[]
* - recommendQuestion?: string
* - recommendOptions?: string[]
* - submitLabel?: string
*/
interface Props {
heading?: string;
sub?: string;
scaleQuestion?: string;
scaleLow?: string;
scaleHigh?: string;
communicationOptions?: string[];
recommendQuestion?: string;
recommendOptions?: string[];
submitLabel?: string;
}
const {
heading = 'Klantfeedback formulier',
sub = 'Je feedback helpt ons om onze dienstverlening continu te verbeteren. Invullen duurt minder dan 2 minuten.',
scaleQuestion = 'Hoe tevreden ben je over onze samenwerking?',
scaleLow = 'Heel ontevreden',
scaleHigh = 'Heel tevreden',
communicationOptions = ['Uitstekend', 'Goed', 'Voldoende', 'Matig', 'Slecht'],
recommendQuestion = 'Zou je ons aanbevelen aan anderen?',
recommendOptions = ['Zeker wel', 'Waarschijnlijk wel', 'Misschien', 'Waarschijnlijk niet'],
submitLabel = 'Feedback versturen',
} = Astro.props;
const scale = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
---
<section class="bl-section fsv">
<div class="bl-inner bl-inner--narrow fsv-inner">
<div class="fsv-header">
<h2 class="fsv-heading">{heading}</h2>
<p class="fsv-subtext">{sub}</p>
</div>
<form class="fsv-form" novalidate>
<fieldset class="fsv-fieldset">
<legend class="fsv-legend">{scaleQuestion}</legend>
<div class="fsv-scale">
{scale.map((n) => (
<label class="fsv-scale-item">
<input class="fsv-scale-input" type="radio" name="overall_score" value={String(n)} required />
<span class="fsv-scale-num">{n}</span>
</label>
))}
</div>
<div class="fsv-scale-labels"><span>{scaleLow}</span><span>{scaleHigh}</span></div>
</fieldset>
<fieldset class="fsv-fieldset">
<legend class="fsv-legend">Hoe beoordeel je de communicatie?</legend>
<div class="fsv-radios">
{communicationOptions.map((o) => (
<label class="fsv-radio-item"><input class="fsv-radio" type="radio" name="communication" value={o} required /> {o}</label>
))}
</div>
</fieldset>
<div class="fsv-field">
<label class="fsv-label" for="fsv-best">Wat gaat er goed?</label>
<textarea class="fsv-textarea" id="fsv-best" name="positive" rows="3" placeholder="Bijv. snelle responstijden, goede rapportages..."></textarea>
</div>
<div class="fsv-field">
<label class="fsv-label" for="fsv-improve">Wat kan er beter?</label>
<textarea class="fsv-textarea" id="fsv-improve" name="improvement" rows="3" placeholder="Wees gerust eerlijk, we leren graag van je feedback."></textarea>
</div>
<fieldset class="fsv-fieldset">
<legend class="fsv-legend">{recommendQuestion}</legend>
<div class="fsv-radios fsv-radios--inline">
{recommendOptions.map((o) => (
<label class="fsv-radio-item"><input class="fsv-radio" type="radio" name="recommend" value={o} required /> {o}</label>
))}
</div>
</fieldset>
<div class="fsv-field">
<label class="fsv-label" for="fsv-name">Naam (optioneel)</label>
<input class="fsv-input" type="text" id="fsv-name" name="name" placeholder="Jouw naam" autocomplete="name" />
</div>
<button class="fsv-submit" type="submit">{submitLabel}</button>
</form>
</div>
</section>
<style>
.fsv-header{margin-bottom:2rem}
.fsv-heading{font-size:1.75rem;font-weight:800;color:var(--color-primary, #0a0a0a);margin:0 0 .5rem}
.fsv-subtext{font-size:1rem;color:#555;margin:0;line-height:1.6}
.fsv-form{display:flex;flex-direction:column;gap:1.75rem}
.fsv-fieldset{border:none;padding:0;margin:0}
.fsv-legend{font-size:1.05rem;font-weight:700;color:var(--color-primary, #0a0a0a);margin-bottom:1rem}
.fsv-scale{display:flex;gap:.4rem;flex-wrap:wrap}
.fsv-scale-item{cursor:pointer}
.fsv-scale-input{display:none}
.fsv-scale-num{display:flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:8px;background:#f5f5f5;font-size:.9375rem;font-weight:600;color:#374151;border:1.5px solid transparent;transition:border-color .15s,background-color .15s,color .15s}
.fsv-scale-input:checked+.fsv-scale-num{background:var(--color-accent, #6366f1);color:#fff;border-color:var(--color-accent, #6366f1)}
.fsv-scale-labels{display:flex;justify-content:space-between;font-size:.8125rem;color:#555;margin-top:.5rem}
.fsv-radios{display:flex;flex-direction:column;gap:.5rem}
.fsv-radios--inline{flex-direction:row;flex-wrap:wrap;gap:.5rem}
.fsv-radio-item{display:flex;align-items:center;gap:.5rem;font-size:1rem;color:#374151;cursor:pointer;padding:.55rem 1rem;background:#f9f9f9;border-radius:8px;border:1.5px solid transparent}
.fsv-radio-item:has(input:checked){border-color:var(--color-accent, #6366f1);background:#eef2ff;color:var(--color-accent, #6366f1)}
.fsv-radio{accent-color:var(--color-accent, #6366f1)}
.fsv-field{display:flex;flex-direction:column;gap:.4rem}
.fsv-label{font-size:.95rem;font-weight:600;color:var(--color-primary, #0a0a0a)}
.fsv-input,.fsv-textarea{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%}
.fsv-input:focus,.fsv-textarea:focus{outline:none;border-color:var(--color-accent, #6366f1);box-shadow:0 0 0 3px #6366f11f}
.fsv-textarea{resize:vertical;min-height:90px}
.fsv-submit{padding:.9rem 2rem;background:var(--color-accent, #6366f1);color:#fff;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer;transition:opacity .2s;align-self:flex-start}
.fsv-submit:hover{opacity:.88}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
heading | string | 'Klantfeedback formulier' | Kop boven het formulier |
sub | string | - | Toelichtende tekst onder de kop |
scaleQuestion | string | - | Vraag boven de 1-10 schaal |
scaleLow | string | - | Label aan de lage kant van de schaal |
scaleHigh | string | - | Label aan de hoge kant van de schaal |
communicationOptions | string[] | - | Antwoordopties communicatie-vraag |
recommendQuestion | string | - | Aanbevelings-vraag |
recommendOptions | string[] | - | Antwoordopties aanbevelings-vraag |
submitLabel | string | 'Feedback versturen' | Tekst op de submit-knop |
* = verplicht