Sihirbaz akışı ana sayfaya taşındı: sıralama girilince modal orada açılır
Some checks failed
Deploy / deploy (push) Failing after 1m30s
Some checks failed
Deploy / deploy (push) Failing after 1m30s
- Ortak SihirbazAdimlar bileşeni (3 adımlık seçim UI'ı) çıkarıldı; hem hero modalı hem /sonuc modalı kullanıyor - /api/facetler: sıraya göre kategori/il/üniversite tipi facet'leri - HeroForm: "Listemi oluştur" artık modalı açar; seçimler tamamlanınca localStorage'a (SIHIRBAZ_STORAGE_KEY) yazılıp /sonuc'a yönlendirilir - /sonuc: modal yalnızca giriş dönüşünde (?sihirbaz=1) otomatik açılır; kayıtlı seçimler prefill olarak kullanılır Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,49 +2,112 @@
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
import { ArrowRight, Loader2 } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { SihirbazAdimlar } from "@/components/sihirbaz-adimlar";
|
||||
import type { SihirbazFacetleri } from "@/lib/db";
|
||||
import { SIHIRBAZ_STORAGE_KEY, type SihirbazSecimleri } from "@/lib/sihirbaz";
|
||||
|
||||
const TUR: string = "say";
|
||||
|
||||
export function HeroForm() {
|
||||
const [siralama, setSiralama] = useState("");
|
||||
const [sira, setSira] = useState<number | null>(null);
|
||||
const [facetler, setFacetler] = useState<SihirbazFacetleri | null>(null);
|
||||
const [yukleniyor, setYukleniyor] = useState(false);
|
||||
const [modalAcik, setModalAcik] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
function handleSubmit(e: React.FormEvent) {
|
||||
async function handleSubmit(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
const value = Number(siralama.replace(/\./g, ""));
|
||||
if (!value || value < 1 || value > 4_000_000) {
|
||||
toast.error("Geçerli bir başarı sıralaması gir (ör. 85.000).");
|
||||
return;
|
||||
}
|
||||
router.push(`/sonuc?sira=${value}`);
|
||||
setYukleniyor(true);
|
||||
try {
|
||||
const res = await fetch(`/api/facetler?sira=${value}&tur=${TUR}`);
|
||||
if (!res.ok) throw new Error();
|
||||
const veri = (await res.json()) as { facetler: SihirbazFacetleri };
|
||||
setSira(value);
|
||||
setFacetler(veri.facetler);
|
||||
setModalAcik(true);
|
||||
} catch {
|
||||
toast.error("Bir şeyler ters gitti, tekrar dener misin?");
|
||||
} finally {
|
||||
setYukleniyor(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Seçimler tamam: sonuç sayfası (ve sonrası) kullanabilsin diye sakla, yönlendir.
|
||||
function secimleriTamamla(secimler: SihirbazSecimleri) {
|
||||
if (!sira) return;
|
||||
try {
|
||||
localStorage.setItem(
|
||||
SIHIRBAZ_STORAGE_KEY,
|
||||
JSON.stringify({ sira, tur: TUR, secimler }),
|
||||
);
|
||||
} catch {}
|
||||
setModalAcik(false);
|
||||
router.push(`/sonuc?sira=${sira}&tur=${TUR}`);
|
||||
}
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="flex w-full max-w-md flex-col gap-3 sm:flex-row"
|
||||
>
|
||||
<label htmlFor="siralama" className="sr-only">
|
||||
YKS başarı sıralaması
|
||||
</label>
|
||||
<Input
|
||||
id="siralama"
|
||||
inputMode="numeric"
|
||||
placeholder="YKS başarı sıralaman (ör. 85.000)"
|
||||
value={siralama}
|
||||
onChange={(e) => setSiralama(e.target.value)}
|
||||
className="h-12 flex-1 bg-white text-base"
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
size="lg"
|
||||
className="h-12 cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"
|
||||
<>
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="flex w-full max-w-md flex-col gap-3 sm:flex-row"
|
||||
>
|
||||
Listemi oluştur
|
||||
<ArrowRight className="size-4" aria-hidden />
|
||||
</Button>
|
||||
</form>
|
||||
<label htmlFor="siralama" className="sr-only">
|
||||
YKS başarı sıralaması
|
||||
</label>
|
||||
<Input
|
||||
id="siralama"
|
||||
inputMode="numeric"
|
||||
placeholder="YKS başarı sıralaman (ör. 85.000)"
|
||||
value={siralama}
|
||||
onChange={(e) => setSiralama(e.target.value)}
|
||||
className="h-12 flex-1 bg-white text-base"
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
size="lg"
|
||||
disabled={yukleniyor}
|
||||
className="h-12 cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"
|
||||
>
|
||||
{yukleniyor ? (
|
||||
<Loader2 className="size-4 animate-spin" aria-hidden />
|
||||
) : null}
|
||||
Listemi oluştur
|
||||
{yukleniyor ? null : <ArrowRight className="size-4" aria-hidden />}
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<Dialog open={modalAcik} onOpenChange={setModalAcik}>
|
||||
<DialogContent className="max-h-[92dvh] gap-0 overflow-y-auto p-6 text-left sm:max-w-3xl">
|
||||
<DialogTitle className="sr-only">Tercih listesi sihirbazı</DialogTitle>
|
||||
<DialogDescription className="sr-only">
|
||||
Sıralamana uygun seçimlerini yap, tercih planına geç.
|
||||
</DialogDescription>
|
||||
{facetler ? (
|
||||
<SihirbazAdimlar
|
||||
key={sira}
|
||||
facetler={facetler}
|
||||
sonButonEtiketi="Tercih planıma geç"
|
||||
onTamamla={secimleriTamamla}
|
||||
/>
|
||||
) : null}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user