Skip to content

Instantly share code, notes, and snippets.

@jonshipman
Last active December 15, 2023 23:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonshipman/3d1864084394577a587389be7520b43a to your computer and use it in GitHub Desktop.
Save jonshipman/3d1864084394577a587389be7520b43a to your computer and use it in GitHub Desktop.
<script lang="ts">
import { applyAction, enhance } from '$app/forms';
import { page } from '$app/stores';
import { RoofGraphic } from '$lib/graphics';
import { fade } from 'svelte/transition';
import type { ActionUpdate, Result } from './form.svelte.d';
import Button from './button.svelte';
import Field from './field.svelte';
import { EmailIcon, MessageIcon, NameIcon, PhoneIcon } from './icons';
import { FormStore, type FormDataInterface } from './store';
export let action = '/contact/';
$: error = $page.form?.error || '';
$: success = $page.form?.success || '';
let className = '';
function handleCloseError() {
error = '';
}
function handleSubmit({ formData }: { formData: FormData }) {
const data = Object.fromEntries(formData) as unknown;
FormStore.set(data as FormDataInterface);
return ({ update, result }: { update: ActionUpdate; result: Result }) => {
return update().then(() => applyAction(result));
};
}
export { className as class };
</script>
<form {action} method="POST" class={className} use:enhance={handleSubmit}>
<div class="px-4 pb-4 pt-8 rounded-lg border-gray-300 border bg-white relative">
{#if error || success}
<div transition:fade class="flex items-center justify-center relative text-center">
<div class="z-10 absolute bottom-16 max-w-5xl mx-auto w-full">
{#if error}
<div
class="mb-4 last:mb-0 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded"
role="alert"
>
{@html error}
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
<svg
on:click|stopPropagation={handleCloseError}
on:keydown|stopPropagation={handleCloseError}
tabindex={0}
class="fill-current h-6 w-6 text-red-500"
role="button"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
>
<title>Close</title>
<path
d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"
/>
</svg>
</span>
</div>
{/if}
{#if success}
<div
class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded"
role="alert"
>
{@html success}
</div>
{/if}
</div>
</div>
{/if}
<slot>
<div class="flex flex-col md:grid gap-4 grid-cols-4">
<Field tabindex={2} name="name" placeholder="Name" required>
<svelte:fragment slot="icon">
<NameIcon />
</svelte:fragment>
</Field>
<Field tabindex={2} name="phone" type="tel" placeholder="Phone">
<svelte:fragment slot="icon">
<PhoneIcon />
</svelte:fragment>
</Field>
<Field tabindex={2} name="email" type="email" placeholder="Email" required>
<svelte:fragment slot="icon">
<EmailIcon />
</svelte:fragment>
</Field>
<div class="order-last md:order-none">
<Button class="w-full" tabindex={3}>Get a Free Quote</Button>
</div>
<div class="spanning-message">
<Field tabindex={2} name="message" placeholder="Message">
<svelte:fragment slot="icon">
<MessageIcon />
</svelte:fragment>
</Field>
</div>
</div>
</slot>
</div>
</form>
<style>
.spanning-message {
grid-area: 2 / 1 / 3 / 4;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment