dev #78

Merged
root merged 4 commits from dev into main 2026-06-02 01:41:52 +03:00
4 changed files with 43 additions and 88 deletions
Showing only changes of commit c7527e4845 - Show all commits

View File

@@ -0,0 +1,39 @@
import { capture } from "@/lib/posthog";
import { Button } from "@sase/ui";
import { Link } from "@tanstack/react-router";
import { ArrowRight } from "lucide-react";
interface DemoFooterCtaProps {
/** Analytics surface tag — e.g. "footer", "category_footer". */
source: string;
}
/**
* Footer conversion card on /demo pages — anti-gimmick B2B trust strip +
* single "Hesap Aç" primary button routed to /register (no VIN carried;
* visitors who want to query their own VIN can use the hero on /, or paste
* it on the register page itself). Mobile-friendly: full-width button below
* the headline; `mb-20` clears the Chatwoot widget in the bottom-right.
*/
export function DemoFooterCta({ source }: DemoFooterCtaProps) {
return (
<div className="mb-20 mt-8 flex flex-col items-start gap-3 rounded-lg border border-border bg-muted/30 p-5 sm:mb-0 sm:flex-row sm:items-center sm:justify-between">
<div>
<p className="text-sm font-semibold">Sınırsız şase sorgulamak için ücretsiz hesap </p>
<p className="mt-0.5 text-xs text-muted-foreground">
Kart bilgisi gerekmez · 30 gün ücretsiz · istediğin an iptal
</p>
</div>
<Button
asChild
className="w-full shrink-0 sm:w-auto"
data-faro-user-action-name={`demo-footer-cta-${source}`}
>
<Link to="/register" onClick={() => capture("demo_to_register_click", { source })}>
Hesap
<ArrowRight className="ml-1 h-4 w-4" />
</Link>
</Button>
</div>
);
}

View File

@@ -1,77 +0,0 @@
import { capture } from "@/lib/posthog";
import { Button, Input } from "@sase/ui";
import { useNavigate } from "@tanstack/react-router";
import { ArrowRight } from "lucide-react";
import { type FormEvent, useState } from "react";
interface DemoVinCtaProps {
/** Analytics surface tag — e.g. "footer", "category_footer". */
source: string;
}
/**
* Conversion card shown at the bottom of /demo pages: B2B trust strip + a
* VIN input the visitor can paste their OWN VIN into. Submitting the form
* (or clicking the empty-input button) routes to /register with the VIN
* carried via `?vin=` so the register teaser can lift off where this leaves
* off. The "Yeni VIN sorgula" gate from the 1C spec lives here rather than
* in the sticky DemoBanner so the banner stays a single-CTA conversion
* anchor without crowding mobile widths.
*/
export function DemoVinCta({ source }: DemoVinCtaProps) {
const navigate = useNavigate();
const [vin, setVin] = useState("");
const trimmed = vin.trim().toUpperCase();
const hasVin = trimmed.length > 0;
const submitLabel = hasVin ? "Bu VIN için Hesap Aç" : "Hesap Aç";
const handleSubmit = (e?: FormEvent) => {
e?.preventDefault();
capture("demo_to_register_click", {
source,
has_vin: hasVin,
vin_length: trimmed.length,
});
navigate({
to: "/register",
search: hasVin ? { vin: trimmed } : {},
});
};
return (
<div className="mb-20 mt-8 rounded-lg border border-border bg-muted/30 p-5 sm:mb-0">
<div className="mb-3 flex flex-col gap-1">
<p className="text-sm font-semibold">Sınırsız şase sorgulamak için ücretsiz hesap </p>
<p className="text-xs text-muted-foreground">
Kart bilgisi gerekmez · 30 gün ücretsiz · istediğin an iptal
</p>
</div>
<form onSubmit={handleSubmit} className="flex flex-col gap-2 sm:flex-row">
<Input
value={vin}
onChange={(e) => setVin(e.target.value.toUpperCase())}
placeholder="Müşterinizin şase numarası (17 karakter)"
maxLength={17}
inputMode="text"
autoCapitalize="characters"
autoCorrect="off"
autoComplete="off"
spellCheck={false}
enterKeyHint="go"
aria-label="Müşterinizin şase numarası"
className="font-mono"
/>
<Button
type="submit"
className="w-full shrink-0 sm:w-auto"
data-faro-user-action-name={`demo-vin-cta-${source}`}
>
{submitLabel}
<ArrowRight className="ml-1 h-4 w-4" />
</Button>
</form>
</div>
);
}

View File

@@ -1,5 +1,5 @@
import { DemoBanner } from "@/components/demo/demo-banner";
import { DemoVinCta } from "@/components/demo/demo-vin-cta";
import { DemoFooterCta } from "@/components/demo/demo-footer-cta";
import { usePageMeta } from "@/hooks/use-page-meta";
import { ApiError, api } from "@/lib/api-client";
import { KEYS_8 } from "@/lib/keys";
@@ -134,11 +134,7 @@ function DemoVehiclePage() {
</CardContent>
</Card>
{/* Footer conversion card — VIN input lets the visitor jump straight
from the demo into a signup pre-filled with THEIR vehicle, instead
of having to bounce back to the hero. Empty submit = same as
plain "Hesap Aç". */}
<DemoVinCta source="footer" />
<DemoFooterCta source="footer" />
</main>
</div>
);

View File

@@ -1,5 +1,5 @@
import { DemoBanner } from "@/components/demo/demo-banner";
import { DemoVinCta } from "@/components/demo/demo-vin-cta";
import { DemoFooterCta } from "@/components/demo/demo-footer-cta";
import { SchemaViewer } from "@/components/schema/schema-viewer";
import { usePageMeta } from "@/hooks/use-page-meta";
import type { CategorySchema } from "@/hooks/use-parts";
@@ -190,10 +190,7 @@ function DemoCategoryPage() {
</Suspense>
))}
{/* Footer conversion card — VIN input at the "aha moment" lets the
visitor pivot straight from browsing the demo to signing up with
their own vehicle pre-filled. */}
{data && !data.loadError && <DemoVinCta source="category_footer" />}
{data && !data.loadError && <DemoFooterCta source="category_footer" />}
</main>
</div>
);