A fast, high-performance exam scheduling system backed by Z3, with a SvelteKit frontend. Designed for small-medium sized schools. kemisolve.wobbl.in
schools school z3 scheduling exam-scheduling solver
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889<script lang='ts'> import type { IconifyIcon } from '@iconify/types' import type { AnyFieldApi } from '@tanstack/svelte-form'
import type { HTMLInputAttributes } from 'svelte/elements' import { useSelector } from '@tanstack/svelte-form' import { TextField } from 'm3-svelte'
interface Props extends HTMLInputAttributes { label: string field: AnyFieldApi disabled?: boolean required?: boolean helperText?: string | null leadingIcon?: IconifyIcon }
const { field, required = false, label, helperText = null, type, ...extraOptions }: Props = $props()
const isNumeric = $derived( type === 'number' || type === 'range' || type === 'tel', )
const { current: isSubmitting } = $derived( useSelector(field.form.store, state => state.isSubmitting), ) const disabled = $derived(isSubmitting)
const { current: errors } = $derived( useSelector(field.store, state => state.meta.errors), )</script>
<div class='container'> <TextField name={field.name} value={field.state.value} oninput={e => field.handleChange( isNumeric ? e.currentTarget.valueAsNumber : e.currentTarget.value, )} onblur={() => field.handleBlur()} error={errors.length !== 0} {type} {label} {disabled} {required} {...extraOptions} /> <div class='m3-font-body-small' style='padding: 0px 1rem;color: rgb(var(--m3-scheme-on-surface-variant));' > {#if errors.length > 0} <ul class='ma-auto pl-0 text-red'> <!-- eslint-disable-next-line svelte/require-each-key --> {#each errors as error} <li> {#if typeof error === 'string'} {error} {:else} {error?.message ?? JSON.stringify(error)} {/if} </li> {/each} </ul> {:else if helperText !== null} {helperText} {/if} </div></div>
<style> .container { display: flex; flex-direction: column; gap: 0.25rem; }</style>