116 lines
3.6 KiB
Plaintext
116 lines
3.6 KiB
Plaintext
---
|
|
import type { Form as Props } from '~/types';
|
|
import Button from '~/components/ui/Button.astro';
|
|
|
|
const { inputs, textarea, disclaimer, button = 'Contact us', description = '' } = Astro.props;
|
|
---
|
|
|
|
<style>
|
|
/* Checkbox error styling */
|
|
.checkbox-error {
|
|
border: 2px solid #ef4444;
|
|
border-radius: 0.5rem;
|
|
padding: 0.5rem;
|
|
background-color: rgba(239, 68, 68, 0.05);
|
|
}
|
|
</style>
|
|
|
|
<form id="contact-form" action="/api/contact" method="POST" class="needs-validation" novalidate>
|
|
|
|
<!-- Form status messages -->
|
|
<div id="form-success" class="hidden mb-6 p-4 bg-green-100 border border-green-200 text-green-700 rounded-lg">
|
|
Your message has been sent successfully. We will get back to you soon!
|
|
</div>
|
|
|
|
<div id="form-error" class="hidden mb-6 p-4 bg-red-100 border border-red-200 text-red-700 rounded-lg">
|
|
There was an error sending your message. Please check all fields and try again.
|
|
</div>
|
|
|
|
<!-- CSRF Token - Will be populated via JavaScript -->
|
|
<input type="hidden" name="csrf_token" id="csrf_token" value="" />
|
|
{
|
|
inputs &&
|
|
inputs.map(
|
|
({ type = 'text', name, label = '', autocomplete = 'on', placeholder = '', required = true }) =>
|
|
name && (
|
|
<div class="mb-6">
|
|
{label && (
|
|
<label for={name} class="block text-sm font-medium">
|
|
{label}{required && <span class="text-red-600">*</span>}
|
|
</label>
|
|
)}
|
|
<input
|
|
type={type}
|
|
name={name}
|
|
id={name}
|
|
autocomplete={autocomplete}
|
|
placeholder={placeholder}
|
|
class="py-3 px-4 block w-full text-md rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-slate-900"
|
|
required={required}
|
|
/>
|
|
<div class="invalid-feedback hidden text-red-600 text-sm mt-1"></div>
|
|
</div>
|
|
)
|
|
)
|
|
}
|
|
|
|
{
|
|
textarea && (
|
|
<div class="mb-6">
|
|
<label for="textarea" class="block text-sm font-medium">
|
|
{textarea.label}<span class="text-red-600">*</span>
|
|
</label>
|
|
<textarea
|
|
id="textarea"
|
|
name={textarea.name ? textarea.name : 'message'}
|
|
rows={textarea.rows ? textarea.rows : 4}
|
|
placeholder={textarea.placeholder}
|
|
class="py-3 px-4 block w-full text-md rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-slate-900"
|
|
required
|
|
/>
|
|
<div class="invalid-feedback hidden text-red-600 text-sm mt-1"></div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
{
|
|
disclaimer && (
|
|
<div class="mt-3 flex items-start mb-6">
|
|
<div class="flex mt-0.5">
|
|
<input
|
|
id="disclaimer"
|
|
name="disclaimer"
|
|
type="checkbox"
|
|
class="cursor-pointer mt-1 py-3 px-4 block w-full text-md rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-slate-900"
|
|
required
|
|
/>
|
|
</div>
|
|
<div class="ml-3">
|
|
<label for="disclaimer" class="cursor-pointer select-none text-sm text-gray-600 dark:text-gray-400">
|
|
{disclaimer.label}<span class="text-red-600">*</span>
|
|
</label>
|
|
<div class="invalid-feedback hidden text-red-600 text-sm mt-1"></div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
{
|
|
button && (
|
|
<div class="mt-10 grid">
|
|
<Button variant="primary" type="submit">
|
|
{button}
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
{
|
|
description && (
|
|
<div class="mt-3 text-center">
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">{description}</p>
|
|
</div>
|
|
)
|
|
}
|
|
</form>
|