Initial commit of Descrybe v2 without local scratch artifacts.

Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
2026-08-09 22:47:43 +02:00
commit 8580c996c3
1285 changed files with 325780 additions and 0 deletions
@@ -0,0 +1,155 @@
<script lang="ts">
import { i18n } from "$lib/i18n";
import { page } from "$app/state";
import { failureMessage } from "$lib/api";
import { DEMO_BOOKING_URL } from "$lib/site";
import { submitSalesContact } from "$lib/sales-contact";
import { notifySuccess, notifyApiError } from "$lib/notify";
import PageShell from "$lib/components/PageShell.svelte";
import Alert from "$lib/components/Alert.svelte";
import {
Button,
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
Input,
Label,
Textarea
} from "$lib/components/ui";
let name = $state("");
let email = $state("");
let companyName = $state("");
let phone = $state("");
let message = $state("");
let estimatedSkus = $state("");
let submitting = $state(false);
let error = $state("");
let done = $state(false);
const source = $derived(page.url.searchParams.get("source")?.trim() || "pricing");
const canSubmit = $derived(
name.trim().length > 0 &&
email.trim().length > 3 &&
message.trim().length > 0 &&
!submitting
);
async function handleSubmit(event: Event) {
event.preventDefault();
if (!canSubmit) return;
submitting = true;
error = "";
try {
const skusRaw = estimatedSkus.trim();
const skus = skusRaw ? Number.parseInt(skusRaw, 10) : undefined;
await submitSalesContact({
name: name.trim(),
email: email.trim(),
company_name: companyName.trim() || undefined,
phone: phone.trim() || undefined,
message: message.trim(),
estimated_skus: skus != null && Number.isFinite(skus) ? skus : undefined,
source
});
done = true;
notifySuccess(i18n.t("sales.contact.toast.success"));
} catch (err) {
error = failureMessage(err, i18n.t("sales.contact.error"));
notifyApiError(err, i18n.t("sales.contact.error"));
} finally {
submitting = false;
}
}
</script>
<PageShell title={i18n.t("sales.contact.title")} description={i18n.t("sales.contact.lead")}>
{#if done}
<Card>
<CardHeader>
<CardTitle>{i18n.t("sales.contact.thanksTitle")}</CardTitle>
<CardDescription>{i18n.t("sales.contact.thanksBody")}</CardDescription>
</CardHeader>
<CardContent class="flex flex-wrap gap-3">
<a
href={DEMO_BOOKING_URL}
target="_blank"
rel="noopener noreferrer"
class="inline-flex h-10 items-center justify-center rounded-md border border-border px-4 text-sm font-medium text-text transition-colors hover:bg-surface-muted"
>
{i18n.t("sales.contact.bookDemo")}
</a>
<a
href="/pricing"
class="inline-flex h-10 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground"
>
{i18n.t("sales.contact.backPricing")}
</a>
</CardContent>
</Card>
{:else}
<Card class="max-w-2xl">
<CardHeader>
<CardTitle>{i18n.t("sales.contact.formTitle")}</CardTitle>
<CardDescription>{i18n.t("sales.contact.formLead")}</CardDescription>
</CardHeader>
<CardContent>
{#if error}
<Alert message={error} />
{/if}
<form class="space-y-4" onsubmit={handleSubmit}>
<div class="grid gap-4 sm:grid-cols-2">
<div class="space-y-2">
<Label for="sales-name">{i18n.t("sales.contact.name")}</Label>
<Input id="sales-name" bind:value={name} required autocomplete="name" maxlength={200} />
</div>
<div class="space-y-2">
<Label for="sales-email">{i18n.t("sales.contact.email")}</Label>
<Input
id="sales-email"
type="email"
bind:value={email}
required
autocomplete="email"
maxlength={320}
/>
</div>
</div>
<div class="grid gap-4 sm:grid-cols-2">
<div class="space-y-2">
<Label for="sales-company">{i18n.t("sales.contact.company")}</Label>
<Input id="sales-company" bind:value={companyName} autocomplete="organization" maxlength={200} />
</div>
<div class="space-y-2">
<Label for="sales-phone">{i18n.t("sales.contact.phone")}</Label>
<Input id="sales-phone" bind:value={phone} autocomplete="tel" maxlength={40} />
</div>
</div>
<div class="space-y-2">
<Label for="sales-skus">{i18n.t("sales.contact.estimatedSkus")}</Label>
<Input id="sales-skus" inputmode="numeric" bind:value={estimatedSkus} />
</div>
<div class="space-y-2">
<Label for="sales-message">{i18n.t("sales.contact.message")}</Label>
<Textarea id="sales-message" bind:value={message} required rows={6} maxlength={10000} />
</div>
<div class="flex flex-wrap items-center gap-3">
<Button type="submit" disabled={!canSubmit}>
{submitting ? i18n.t("sales.contact.submitting") : i18n.t("sales.contact.submit")}
</Button>
<a
href={DEMO_BOOKING_URL}
target="_blank"
rel="noopener noreferrer"
class="text-sm text-text-muted underline-offset-4 hover:text-link hover:underline"
>
{i18n.t("sales.contact.orBookDemo")}
</a>
</div>
</form>
</CardContent>
</Card>
{/if}
</PageShell>