Created
November 16, 2024 21:10
-
-
Save maietta/cd4ec5e8b02a10d296c4ca49838a737e to your computer and use it in GitHub Desktop.
The secret formula search form.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script lang="ts"> | |
import { goto } from '$app/navigation'; | |
import { page } from '$app/stores'; | |
import { onMount } from 'svelte'; | |
import { queryParameters } from 'sveltekit-search-params'; | |
// Initialize query parameters management | |
const params = queryParameters( | |
{ | |
test: { | |
encode: (value) => (value && value.trim() ? value : undefined), | |
decode: (value) => (value && value.trim() ? value : undefined) | |
} | |
}, | |
{ | |
pushHistory: true, // Enables updating the browser history | |
showDefaults: false, // Don't include default values in the query string | |
debounceHistory: 500 | |
} | |
); | |
let form = $state({ | |
Class: '', | |
Type: '' | |
}); | |
let records = $state(); | |
let initialLoad = true; | |
// Initialize form from URL path and query parameters | |
onMount(() => { | |
const [_, classSegment, typeSegment] = $page.url.pathname.split('/').filter(Boolean); | |
form.Class = classSegment || ''; | |
form.Type = typeSegment || ''; | |
// Load query parameters | |
const urlSearchParams = new URLSearchParams(form); | |
for (const [key, value] of urlSearchParams.entries()) { | |
if (params[key] !== undefined) { | |
params[key] = value; // Initialize query parameters | |
} | |
} | |
initialLoad = false; // Initial load is complete | |
}); | |
// Reactive effect: Update URL and fetch data when form changes | |
$effect(() => { | |
if (initialLoad) return; // Prevent URL update during initial load | |
let url = '/search'; | |
if (form.Class) { | |
url += `/${encodeURIComponent(form.Class)}`; | |
if (form.Type) url += `/${encodeURIComponent(form.Type)}`; | |
} | |
let searchParams = new URLSearchParams($page.url.searchParams); | |
// If Class or Type is present, remove them. | |
if (form.Class) searchParams.delete('Class'); | |
if (form.Type) searchParams.delete('Type'); | |
// Add the query parameters to the URL | |
url += `?` + searchParams.toString(); | |
if (typeof window !== 'undefined' && window.location.href !== url) | |
goto(url, { replaceState: true }); | |
fetchData(form); | |
}); | |
// Fetch data from API | |
async function fetchData(formData: typeof form) { | |
try { | |
const response = await fetch('/search', { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify(formData) | |
}); | |
if (!response.ok) throw new Error('Failed to fetch data'); | |
records = await response.json(); | |
} catch (error) { | |
console.error('Error fetching data:', error); | |
} | |
} | |
</script> | |
<form id="search" class="shadow-inset flex flex-col gap-4 rounded border bg-white p-4"> | |
<label for="procpertyClass"><span class="font-bold">Property Type: </span></label> | |
<select name="procpertyClass" class="border border-red-300" bind:value={form.Class}> | |
<option value="">— choose a property type —</option> | |
<option value="residential">Traditional Residential</option> | |
<option value="multi-family">Multi-family Residential</option> | |
<option value="land">Lots and Land</option> | |
<option value="commercial">Commercial</option> | |
</select> | |
<input name="test" type="text" class="border border-red-300" bind:value={params.test} /> | |
{#if form.Class === 'residential'} | |
<label for="Type"><span class="font-bold">Residence Type: </span></label> | |
<select bind:value={form.Type} name="Type" class="w-full"> | |
<option value="">— any type of residential —</option> | |
<option value="single-family">Single Family Residence</option> | |
<option value="single-family-w-guest">Single Family w/Guest Addition(s)</option> | |
<option value="manufactured-on-land">Manufactured Residence on Land</option> | |
<option value="mobile-only">Mobile Only</option> | |
</select> | |
<!-- Additional fields for Residential --> | |
<!-- <label for="bedrooms"><span class="font-bold">Bedrooms:</span></label> | |
<input type="number" bind:value={form.Bedrooms} placeholder="Number of bedrooms" /> | |
<label for="bathrooms"><span class="font-bold">Bathrooms:</span></label> | |
<input type="number" bind:value={form.Bathrooms} placeholder="Number of bathrooms" /> --> | |
{/if} | |
</form> | |
<pre> | |
{JSON.stringify(params, null, 2)} | |
</pre> | |
<pre> | |
{JSON.stringify(records, null, 2)} | |
</pre> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment