fix(ux): /listem telefonda yana taşıyordu; başlık yer söylüyor; kaydet bandı
- /listem ve üretim ekranındaki ızgaranın telefonda sütun tanımı yoktu; en geniş çocuk sayfayı 434 px'e itiyordu (375 px'te yatay kaydırma). grid-cols-[minmax(0,1fr)] ile düzeldi (ölçüldü: 375) - /listem h1: pazarlama cümlesi yerine "Tercih listen" + "24 tercih: 5 hayal · 13 dengeli · 6 güvenli"; paketsizde eski cümle alt satırda - Başlık düğmeleri 44 px, hover tek turuncu - "Listen yalnızca bu tarayıcıda" bandı telefonda başlığı kelime kelime kırıyordu: metin üstte, düğme altta tam genişlik; kanonik çarpı Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -58,18 +58,20 @@ export function KaydetBanner() {
|
|||||||
<div className="pointer-events-none fixed inset-x-0 bottom-4 z-40 px-4">
|
<div className="pointer-events-none fixed inset-x-0 bottom-4 z-40 px-4">
|
||||||
<div
|
<div
|
||||||
ref={gorunumRef}
|
ref={gorunumRef}
|
||||||
className="pointer-events-auto mx-auto flex max-w-xl items-center gap-4 rounded-2xl border border-slate-200 bg-white p-4 shadow-xl"
|
// Telefonda metin kendi satırında, düğme altında tam genişlik:
|
||||||
|
// yan yana dizince başlık kelime kelime kırılıyordu (375 px).
|
||||||
|
className="pointer-events-auto relative mx-auto flex max-w-xl flex-wrap items-center gap-3 rounded-2xl border border-slate-200 bg-white p-4 pr-14 shadow-xl sm:flex-nowrap sm:gap-4"
|
||||||
>
|
>
|
||||||
{/* Kullanıcının o anki işletim sisteminin logosu: "bu tarayıcıda"
|
{/* Kullanıcının o anki işletim sisteminin logosu: "bu tarayıcıda"
|
||||||
mesajını somutlaştırır */}
|
mesajını somutlaştırır */}
|
||||||
<div className="flex size-10 shrink-0 items-center justify-center rounded-xl border border-slate-200 bg-slate-50 text-slate-700">
|
<div className="flex size-10 shrink-0 items-center justify-center rounded-xl border border-slate-200 bg-slate-50 text-slate-700">
|
||||||
<IsletimSistemiLogosu className="size-5" />
|
<IsletimSistemiLogosu className="size-5" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<p className="font-heading text-sm font-bold text-slate-900">
|
<p className="font-heading text-base font-bold text-slate-900">
|
||||||
Listen yalnızca bu tarayıcıda
|
Listen yalnızca bu tarayıcıda
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs text-slate-500">
|
<p className="text-sm leading-snug text-slate-500">
|
||||||
Giriş yap; {liste.length} seçimin hesabında saklansın, her
|
Giriş yap; {liste.length} seçimin hesabında saklansın, her
|
||||||
cihazdan aç{" "}
|
cihazdan aç{" "}
|
||||||
<CihazCifti className="ml-0.5 align-[-3px] text-slate-400" />
|
<CihazCifti className="ml-0.5 align-[-3px] text-slate-400" />
|
||||||
@@ -77,8 +79,7 @@ export function KaydetBanner() {
|
|||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
asChild
|
asChild
|
||||||
size="sm"
|
className="h-11 w-full cursor-pointer bg-orange-500 px-5 text-white transition-[background-color,transform] duration-200 hover:bg-orange-600 active:scale-[0.97] sm:w-auto"
|
||||||
className="cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"
|
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
href={girisUrl}
|
href={girisUrl}
|
||||||
@@ -99,7 +100,7 @@ export function KaydetBanner() {
|
|||||||
sessionStorage.setItem(KAPATMA_KEY, "1");
|
sessionStorage.setItem(KAPATMA_KEY, "1");
|
||||||
} catch {}
|
} catch {}
|
||||||
}}
|
}}
|
||||||
className="cursor-pointer rounded-full p-1 text-slate-400 transition-colors duration-200 hover:bg-slate-100 hover:text-slate-600"
|
className="absolute top-3 right-3 z-10 flex size-9 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-popover text-slate-500 transition-[background-color,transform] duration-150 hover:bg-slate-100 hover:text-slate-800 active:scale-[0.96]"
|
||||||
>
|
>
|
||||||
<X className="size-4" aria-hidden />
|
<X className="size-4" aria-hidden />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -434,7 +434,7 @@ function UretimGovdesi({ uzunSurdu }: { uzunSurdu: boolean }) {
|
|||||||
|
|
||||||
{/* Nihai sayfanın (listem-govde) grid'iyle aynı düzen: liste solda,
|
{/* Nihai sayfanın (listem-govde) grid'iyle aynı düzen: liste solda,
|
||||||
danışman sağda — üretim biter bitmez ekran aynı yerlere oturur. */}
|
danışman sağda — üretim biter bitmez ekran aynı yerlere oturur. */}
|
||||||
<div className="mt-8 grid items-start gap-6 lg:grid-cols-[minmax(0,1fr)_380px] xl:grid-cols-[minmax(0,1fr)_440px]">
|
<div className="mt-8 grid grid-cols-[minmax(0,1fr)] items-start gap-6 lg:grid-cols-[minmax(0,1fr)_380px] xl:grid-cols-[minmax(0,1fr)_440px]">
|
||||||
{/* Gelmekte olan tercih listesinin iskeleti */}
|
{/* Gelmekte olan tercih listesinin iskeleti */}
|
||||||
<div className="flex min-w-0 flex-col gap-2 rounded-2xl border border-slate-200 bg-white p-6 sm:p-8">
|
<div className="flex min-w-0 flex-col gap-2 rounded-2xl border border-slate-200 bg-white p-6 sm:p-8">
|
||||||
<div className="flex items-center justify-between pb-2">
|
<div className="flex items-center justify-between pb-2">
|
||||||
|
|||||||
@@ -39,6 +39,11 @@ import {
|
|||||||
} from "@/features/liste/hooks/use-tercih-profili";
|
} from "@/features/liste/hooks/use-tercih-profili";
|
||||||
import { UNIVERSITE_TIPI_ETIKET } from "@/features/sihirbaz/sihirbaz-sabitler";
|
import { UNIVERSITE_TIPI_ETIKET } from "@/features/sihirbaz/sihirbaz-sabitler";
|
||||||
import { PUAN_TURLERI } from "@/types/yokatlas";
|
import { PUAN_TURLERI } from "@/types/yokatlas";
|
||||||
|
import { DILIM_ETIKET } from "@/lib/risk";
|
||||||
|
|
||||||
|
// Başlık satırındaki ikincil düğmeler: 44 px, hover tek turuncu (§4.1, §2.1)
|
||||||
|
const IKINCIL_BUTON =
|
||||||
|
"h-11 cursor-pointer px-4 transition-[background-color,border-color,color,transform] duration-150 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.97]";
|
||||||
|
|
||||||
export function ListemGovde({
|
export function ListemGovde({
|
||||||
rapor,
|
rapor,
|
||||||
@@ -94,6 +99,10 @@ export function ListemGovde({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const acikSatir = kilitliBaslangic ?? rapor.tercihler.length;
|
const acikSatir = kilitliBaslangic ?? rapor.tercihler.length;
|
||||||
|
const dilimOzeti = useMemo(() => {
|
||||||
|
const say = (d: string) => rapor.tercihler.filter((t) => t.dilim === d).length;
|
||||||
|
return `${rapor.tercihler.length} tercih: ${say("hayal")} ${DILIM_ETIKET.hayal.toLocaleLowerCase("tr-TR")} · ${say("dengeli")} ${DILIM_ETIKET.dengeli.toLocaleLowerCase("tr-TR")} · ${say("garanti")} ${DILIM_ETIKET.garanti.toLocaleLowerCase("tr-TR")}`;
|
||||||
|
}, [rapor]);
|
||||||
|
|
||||||
// Profil client'ta (localStorage) çözülür: ilk render'da null döner, yani
|
// Profil client'ta (localStorage) çözülür: ilk render'da null döner, yani
|
||||||
// SSR ile aynı "Tercihlerimi düzenle" hâli basılır — hidrasyon uyuşmazlığı
|
// SSR ile aynı "Tercihlerimi düzenle" hâli basılır — hidrasyon uyuşmazlığı
|
||||||
@@ -148,7 +157,7 @@ export function ListemGovde({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-8 grid items-start gap-6 lg:grid-cols-[minmax(0,1fr)_380px] xl:grid-cols-[minmax(0,1fr)_440px]">
|
<div className="mt-8 grid grid-cols-[minmax(0,1fr)] items-start gap-6 lg:grid-cols-[minmax(0,1fr)_380px] xl:grid-cols-[minmax(0,1fr)_440px]">
|
||||||
<div className="flex min-w-0 flex-col gap-6">
|
<div className="flex min-w-0 flex-col gap-6">
|
||||||
{/* Harita: listenin coğrafyası — ile dokun, üniversiteleri gör */}
|
{/* Harita: listenin coğrafyası — ile dokun, üniversiteleri gör */}
|
||||||
<section
|
<section
|
||||||
@@ -181,11 +190,21 @@ export function ListemGovde({
|
|||||||
aksiyonları bu kutunun kendi başlık satırında yaşar. */}
|
aksiyonları bu kutunun kendi başlık satırında yaşar. */}
|
||||||
<section className={`min-w-0${kilitAcilisi ? " kt-unblur" : ""}`}>
|
<section className={`min-w-0${kilitAcilisi ? " kt-unblur" : ""}`}>
|
||||||
<div className="flex flex-wrap items-center justify-between gap-3 pb-1">
|
<div className="flex flex-wrap items-center justify-between gap-3 pb-1">
|
||||||
<h1 className="min-w-0 font-heading text-xl font-bold tracking-tight sm:text-2xl">
|
{/* Sayfa nerede olduğunu söyler (DESIGN.md §10.1): başlık yer,
|
||||||
{hasPaket
|
altındaki satır listenin sayılarla özeti. */}
|
||||||
? "Yapay Zeka tercih listen"
|
<div className="min-w-0">
|
||||||
: "Veriyi ücretsiz incele. Kararı Yapay Zeka ile netleştir."}
|
<h1 className="font-heading text-2xl font-bold text-balance text-slate-900 sm:text-3xl">
|
||||||
|
Tercih listen
|
||||||
</h1>
|
</h1>
|
||||||
|
<p className="mt-1 text-base text-slate-600">
|
||||||
|
{dilimOzeti}
|
||||||
|
{hasPaket ? null : (
|
||||||
|
<span className="block text-sm text-slate-500">
|
||||||
|
Veriyi ücretsiz incele, kararı Yapay Zeka ile netleştir.
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div className="flex shrink-0 flex-wrap gap-2">
|
<div className="flex shrink-0 flex-wrap gap-2">
|
||||||
{/* Tercih düzenleme her kullanıcıya açık: kapı (layout'ta monte
|
{/* Tercih düzenleme her kullanıcıya açık: kapı (layout'ta monte
|
||||||
TercihProfiliKapisi) profili günceller, /listem'e döner.
|
TercihProfiliKapisi) profili günceller, /listem'e döner.
|
||||||
@@ -200,9 +219,8 @@ export function ListemGovde({
|
|||||||
{farkVar ? (
|
{farkVar ? (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
|
||||||
onClick={() => setFarkModali(true)}
|
onClick={() => setFarkModali(true)}
|
||||||
className="cursor-pointer transition-[background-color,transform] duration-200 active:scale-[0.97]"
|
className="h-11 cursor-pointer px-4 transition-[background-color,transform] duration-200 active:scale-[0.97]"
|
||||||
>
|
>
|
||||||
<RefreshCcw className="size-4" aria-hidden />
|
<RefreshCcw className="size-4" aria-hidden />
|
||||||
Tercihlerin değişmiş
|
Tercihlerin değişmiş
|
||||||
@@ -211,9 +229,8 @@ export function ListemGovde({
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
|
||||||
onClick={profilDuzenlemeyiAc}
|
onClick={profilDuzenlemeyiAc}
|
||||||
className="cursor-pointer"
|
className={IKINCIL_BUTON}
|
||||||
>
|
>
|
||||||
<SlidersHorizontal className="size-4" aria-hidden />
|
<SlidersHorizontal className="size-4" aria-hidden />
|
||||||
Tercihlerimi düzenle
|
Tercihlerimi düzenle
|
||||||
@@ -224,8 +241,7 @@ export function ListemGovde({
|
|||||||
<Button
|
<Button
|
||||||
asChild
|
asChild
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
className={IKINCIL_BUTON}
|
||||||
className="cursor-pointer"
|
|
||||||
>
|
>
|
||||||
<Link href="#revizyon">
|
<Link href="#revizyon">
|
||||||
<PencilLine className="size-4" aria-hidden />
|
<PencilLine className="size-4" aria-hidden />
|
||||||
@@ -235,8 +251,7 @@ export function ListemGovde({
|
|||||||
<Button
|
<Button
|
||||||
asChild
|
asChild
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
className={IKINCIL_BUTON}
|
||||||
className="cursor-pointer"
|
|
||||||
>
|
>
|
||||||
<Link href="/rapor/yazdir" target="_blank">
|
<Link href="/rapor/yazdir" target="_blank">
|
||||||
<FileText className="size-4" aria-hidden />
|
<FileText className="size-4" aria-hidden />
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ export function ListemIcerikSkeleton() {
|
|||||||
<Skeleton className="h-6 w-40 rounded-full" />
|
<Skeleton className="h-6 w-40 rounded-full" />
|
||||||
<Skeleton className="mt-4 h-9 w-3/4 max-w-xl" />
|
<Skeleton className="mt-4 h-9 w-3/4 max-w-xl" />
|
||||||
<Skeleton className="mt-3 h-5 w-2/3 max-w-lg" />
|
<Skeleton className="mt-3 h-5 w-2/3 max-w-lg" />
|
||||||
<div className="mt-8 grid items-start gap-6 lg:grid-cols-[minmax(0,1fr)_380px] xl:grid-cols-[minmax(0,1fr)_440px]">
|
<div className="mt-8 grid grid-cols-[minmax(0,1fr)] items-start gap-6 lg:grid-cols-[minmax(0,1fr)_380px] xl:grid-cols-[minmax(0,1fr)_440px]">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
{Array.from({ length: 10 }).map((_, i) => (
|
{Array.from({ length: 10 }).map((_, i) => (
|
||||||
<Skeleton key={i} className="h-16 w-full rounded-xl" />
|
<Skeleton key={i} className="h-16 w-full rounded-xl" />
|
||||||
|
|||||||
Reference in New Issue
Block a user