fix(icerik): üst bant sezon dışında "sona erdi" demez, hazırlık çerçevesi kurar

2027 takvimi açıklanmadığı için bant artık "takvim-belirsiz" aşamasında:
geri sayım ve `role="timer"` hiç render edilmiyor (boş "--" sayaçları yok),
metin `BANT_METNI` üzerinden "2027 tercihine hazırlık · 2026 yerleştirme
verisi yüklü" oluyor. Yıl ve aralık `TERCIH_YILI`/`VERI_ARALIGI`'ndan
geliyor; takvim bilinmiyorsa `<time>` aralığı yerine veri penceresini
söyleyen düz satır duruyor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-22 01:19:43 +03:00
parent 54fb72d18c
commit 46efc7f86c

View File

@@ -3,7 +3,17 @@
import { startTransition, useEffect, useState } from "react"; import { startTransition, useEffect, useState } from "react";
import NumberFlow, { NumberFlowGroup } from "@number-flow/react"; import NumberFlow, { NumberFlowGroup } from "@number-flow/react";
import { CalendarDays, Clock3 } from "lucide-react"; import { CalendarDays, Clock3 } from "lucide-react";
import { sezonAsamasi, sezonHedefi, type SezonAsamasi } from "@/lib/sezon"; import {
BANT_ARIA,
BANT_METNI,
SEZON_TAKVIMI,
sezonAsamasi,
sezonHedefi,
type SezonAraligi,
type SezonAsamasi,
} from "@/lib/sezon";
import { trTarih } from "@/lib/tarih";
import { TERCIH_YILI, VERI_ARALIGI } from "@/lib/veri-yillari";
type GeriSayim = { type GeriSayim = {
asama: SezonAsamasi; asama: SezonAsamasi;
@@ -27,6 +37,27 @@ function geriSayimiHesapla(simdi: number): GeriSayim {
}; };
} }
/**
* "29 Temmuz – 10 Ağustos 2026": aralık aynı yıl içindeyse yıl yalnızca sonda
* yazılır. `trTarih` bilinçli olarak `Date`/`toLocale*` kullanmaz; sunucu ile
* tarayıcı saat dilimi farklı olsa da aynı metni üretir.
*/
function araligiBicimlendir(takvim: SezonAraligi) {
const baslangicIso = takvim.baslangic.slice(0, 10);
const bitisIso = takvim.bitis.slice(0, 10);
const yil = bitisIso.slice(0, 4);
const baslangic = trTarih(baslangicIso);
return {
baslangicIso,
bitisIso,
baslangicMetni: baslangicIso.startsWith(yil)
? baslangic.replace(` ${yil}`, "")
: baslangic,
bitisMetni: trTarih(bitisIso),
};
}
const BIRIMLER = [ const BIRIMLER = [
{ anahtar: "gun", etiket: "gün" }, { anahtar: "gun", etiket: "gün" },
{ anahtar: "saat", etiket: "sa" }, { anahtar: "saat", etiket: "sa" },
@@ -48,36 +79,50 @@ export function SiteTopBanner() {
return () => window.clearInterval(zamanlayici); return () => window.clearInterval(zamanlayici);
}, []); }, []);
const asamaMetni = // Takvim açıklanmamışsa aşama zamandan bağımsızdır; mount öncesinde de
geriSayim?.asama === "baslamadi" // bilinir, böylece boş sayaç bir an görünüp kaybolmaz. Takvim varsa sunucu
? "Başlamasına" // çıktısı eskisi gibi "devam-ediyor" varsayar, ilk tikte gerçeğine döner.
: geriSayim?.asama === "sona-erdi" const takvim = SEZON_TAKVIMI[TERCIH_YILI] ?? null;
? "Tercih dönemi sona erdi" const asama: SezonAsamasi =
: "Sona ermesine"; geriSayim?.asama ?? (takvim ? "devam-ediyor" : "takvim-belirsiz");
const hedef = sezonHedefi(asama);
const aralik = takvim ? araligiBicimlendir(takvim) : null;
return ( return (
<section <section
aria-label="2026 YKS tercih dönemi" aria-label={BANT_ARIA}
className="relative z-50 border-b border-primary-foreground/15 bg-primary text-primary-foreground print:hidden" className="relative z-50 border-b border-primary-foreground/15 bg-primary text-primary-foreground print:hidden"
> >
<div className="mx-auto flex min-h-12 max-w-6xl flex-wrap items-center justify-center gap-x-5 gap-y-1.5 px-4 py-2 sm:justify-between"> <div className="mx-auto flex min-h-12 max-w-6xl flex-wrap items-center justify-center gap-x-5 gap-y-1.5 px-4 py-2 sm:justify-between">
<div className="flex min-w-0 items-center gap-2.5"> <div className="flex min-w-0 items-center gap-2.5">
<CalendarDays className="size-4 shrink-0 opacity-80" aria-hidden /> <CalendarDays className="size-4 shrink-0 opacity-80" aria-hidden />
<p className="truncate text-sm font-semibold tracking-[-0.01em]"> <p className="truncate text-sm font-semibold tracking-[-0.01em]">
<span className="hidden sm:inline">2026 YKS tercih dönemi · </span> <span className="hidden sm:inline">{BANT_ARIA} · </span>
<time dateTime="2026-07-29">29 Temmuz</time> {aralik ? (
<span aria-hidden> – </span> <>
<time dateTime="2026-08-10">10 Ağustos 2026</time> <time dateTime={aralik.baslangicIso}>
{aralik.baslangicMetni}
</time>
<span aria-hidden> – </span>
<time dateTime={aralik.bitisIso}>{aralik.bitisMetni}</time>
</>
) : (
// Takvim yok: uydurma tarih yerine elimizdeki veriyi söyle.
<span>{VERI_ARALIGI} verisi</span>
)}
</p> </p>
</div> </div>
<div className="flex items-center gap-2.5" role="timer"> <div
className="flex items-center gap-2.5"
role={hedef !== null ? "timer" : undefined}
>
<div className="flex items-center gap-1.5 text-xs font-medium opacity-85"> <div className="flex items-center gap-1.5 text-xs font-medium opacity-85">
<Clock3 className="size-3.5" aria-hidden /> <Clock3 className="size-3.5" aria-hidden />
<span>{asamaMetni}</span> <span>{BANT_METNI[asama]}</span>
</div> </div>
{geriSayim?.asama !== "sona-erdi" ? ( {hedef !== null ? (
<dl <dl
className="flex items-baseline gap-1 font-mono text-xs tabular-nums" className="flex items-baseline gap-1 font-mono text-xs tabular-nums"
aria-label={ aria-label={