From 3c995402c69d7b56ba32d358a2b14ed2aadaddf0 Mon Sep 17 00:00:00 2001 From: bilalgursen Date: Wed, 7 Oct 2026 17:12:53 +0300 Subject: [PATCH] =?UTF-8?q?feat(ui):=20Arc=20bile=C5=9Fenleri,=20landing?= =?UTF-8?q?=20b=C3=B6l=C3=BCmleri=20ve=20bildirim=20y=C4=B1=C4=9F=C4=B1n?= =?UTF-8?q?=C4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sonner/vaul yerine kendi bildirim yığını ve alt sayfa; çip grubu, kart destesi, kaydırma eylemi, yazı dönüşümü, bölme tutamacı; landing'e program duvarı, süzülen haplar ve veri akışı; yaylar tek dosyada (lib/hareket.ts). Co-Authored-By: Claude Fable 5.1 --- data/app.db | Bin 823296 -> 880640 bytes .../2026-10-07-booking-pill-sekil-hapi.md | 1026 +++++++++++++++++ docs/ekip/BACKLOG.md | 1 + scripts/tasarim-denetim.ts | 2 +- src/app/globals.css | 54 +- src/app/layout.tsx | 4 +- src/app/page.tsx | 287 +++-- src/components/dev/dev-panel.tsx | 2 +- src/components/pixel-decor.tsx | 105 ++ src/components/ui/alt-sayfa.tsx | 686 +++++++++++ src/components/ui/bildirim.tsx | 696 +++++++++++ src/components/ui/bolme-tutamaci.tsx | 177 +++ src/components/ui/cip-grubu.tsx | 139 +++ src/components/ui/drawer.tsx | 154 --- src/components/ui/kart-destesi.tsx | 615 ++++++++++ src/components/ui/kaydirma-eylemi.tsx | 528 +++++++++ src/components/ui/sonner.tsx | 54 - src/components/ui/yazi-donusumu.tsx | 149 +++ .../katalog/components/akademik-ayrinti.tsx | 43 +- .../katalog/components/bolum-icerik.tsx | 44 +- .../katalog/components/program-ayrinti.tsx | 50 +- .../katalog/components/taban-karti.tsx | 39 +- .../katalog/components/universite-icerik.tsx | 47 +- .../kullanici/components/giris-form.tsx | 2 +- .../liste/components/liste-cekmecesi.tsx | 220 ++-- .../liste/components/program-ekle-butonu.tsx | 2 +- .../components/tercih-profili-kapisi.tsx | 2 +- .../odeme/components/satin-al-form.tsx | 2 +- .../pazarlama/components/deste-demosu.tsx | 109 ++ .../pazarlama/components/program-duvari.tsx | 245 ++++ .../pazarlama/components/suzulen-haplar.tsx | 208 ++++ .../pazarlama/components/veri-akisi.tsx | 157 +++ src/features/pazarlama/landing-verisi.ts | 129 +++ .../components/tercih-degisti-modali.tsx | 2 +- .../sihirbaz/components/cta-sira-form.tsx | 41 +- .../sihirbaz/components/hero-form.tsx | 24 +- .../sihirbaz/components/sihirbaz-adimlar.tsx | 78 +- src/lib/hareket.ts | 48 + 38 files changed, 5474 insertions(+), 697 deletions(-) create mode 100644 docs/arastirma/2026-10-07-booking-pill-sekil-hapi.md create mode 100644 src/components/ui/alt-sayfa.tsx create mode 100644 src/components/ui/bildirim.tsx create mode 100644 src/components/ui/bolme-tutamaci.tsx create mode 100644 src/components/ui/cip-grubu.tsx delete mode 100644 src/components/ui/drawer.tsx create mode 100644 src/components/ui/kart-destesi.tsx create mode 100644 src/components/ui/kaydirma-eylemi.tsx delete mode 100644 src/components/ui/sonner.tsx create mode 100644 src/components/ui/yazi-donusumu.tsx create mode 100644 src/features/pazarlama/components/deste-demosu.tsx create mode 100644 src/features/pazarlama/components/program-duvari.tsx create mode 100644 src/features/pazarlama/components/suzulen-haplar.tsx create mode 100644 src/features/pazarlama/components/veri-akisi.tsx create mode 100644 src/features/pazarlama/landing-verisi.ts create mode 100644 src/lib/hareket.ts diff --git a/data/app.db b/data/app.db index 9c154e88bb4a5ef3b58f142ab32c62ab23329492..43b41cf4f2f2045f87d544ecb4a138588c430c3a 100644 GIT binary patch delta 44749 zcmb?^34B}CmA>}HlC3z-P8P-4oM0ty)00FX!AYFWah%0joC3*{^c2gMY{yFyn?-Th zx>=sctHG03RGu`MOfTYR8GfwzslKOHHlI9m;B!95udMFPmS3H% z^dGlm@1ERJ_R#~D%Er*l#@n3Pk5BH-^fYYhuWvXirIo%d4IArw)^Fa+|#m7YE`=$)+jv(Gkdmd z+mnp$NVo56N!RaLFE*`R+bY%{?T|O^T`PBY)}^9#M|)b6{nEkizIa_zI-(!eHpJF! zh^NB`x7LN~dpotY2U{BI5_LQ4cEonB-@b9fUa2wJ)4HLjVfUe6PvhpseZhvK`;RoF zdbSIapz8gbTcaCd$)@Dyox29IGq3QS?V9qh<~bc*JL2n7V&jH=hvH&abMu}^ON-d0 zZ10F~)b^e|FwJbv3^c8)7q&Jx_H0V;R$^;6sg2FCU}JNmvbDKRY?OuNZ9D7h8#;DG zJG-_w?dWT5-kgYTYUo!2yTa?6yVk8~YT0x6$e#X?bTGDS{TB6bI;b5L>i6lp_cW<% z#f?pCgY7Nrv@J?cU!&CAw5wjwj`VGbZ48B4rC47&no%|<^n>l)Yo$<3>)FtuL5S?$-nS>bYj;fB8R|;52<_>8hqv^vX%DX7RbSVpZVC>p>sz;7b)paixZk>Wd>JNx#C{p(s9 z+cxy1c5SRnMh~uO>^|BZYdh4mX`i%K+}e6LAhd2e65JGR?LSnP45b>5^sn8&?TFCZ z+_|x3PyLZi?E`C$v^94f-4Ye+l(vIy&tCs>Yj5_Rc}ueYG0$nP&7PPSbhV{_?rD3r z>7UPTp83SI84lm;Sofy8egEV8qwgKx+rD4(QKvv+OyXQcla{+_J=ii`Tjz@ zJTVV1r)J~jQpW!@tI9X}9;-N6eyDt?{C@9J?+(xHo)^o$?){_p#nKl6>)gKaK$ z`ca!L6NyCPp{NoGL^UZKP!g&hh=${0K$W8SDk>!eSrttt%Qs{-BB*jA9teqvARY`w z0-B^n1EL-aCNwpo$WcMSgD1nWu&nCQP(T!^#&}2yM6{p~hzCQOuBvfSQxYri;K7Ix z3uPj@5)Fi8NeL*D7!5>(h#Zh2cvOt&K~2+^RweLfat}iH4(5 zS&yO(Ie-VJ;-OGHAqfFFETEGrnvF=Ict8xs!jggy#bBt`WHP_4iE%L+6V*&0q@Y

iwAU3!EmIY8qi{r9tf$RwW14>9*r#F59+EIRAa#asDT<| zLDY!(!%IR2ks=9QR~PdKBf1t+gSinaN=6C>!nz^^#HbVvDH8e~mln~JM1WW<91X<6 zm=Z5TRRl=}L3LpvJs48MatPBH2x8hmAQiocYnX2_5{zh}SR@t~7Z{xk z;R6Np3kn1jk(L@(o)Cy7F#ln^>O!KLS1IaYIf8{FVtO$gT@6HJJra;4fvSs!wPcYABqL10p62vk2OR)uID&_ax|dEFdSXRG8ByIW>0_1z3^;T z<9V|UoL~q0ho8C^+Na{}jajW}=?+!WVqqnW(lG_~V5S0^A}WEnjGl=hEgn@u0ctT4 zRDw}VPe4%Ov5E%V)En(zId$+y+#ulUc3 z^A-11w3fe8e!Bd4d2{(<@1MNitGKGd>wC2PO5bC?MZTToZ&ZBO_fq-S%3CTvS$=25 z|MULU`+P-Z#p;UmrT)>8@5$J#CNnsR`4eI!A%|r2C$5QDFxW+ba6$*G(1mCu8q`BF zsEh}@z$MJ>N-z}02$X;jm85_Y!P3UwCN34ygNd*p#bgOg!n_6yz`915BaK?GyD#L=Q>Wic#=9MOI?88{~iU{5MRbVXCqGgVN+VJ#liMIpG5p5}W= z5X3}0jD;7EVqYk6^d}ONQ7#^hW6cI5U^&(FG~XtwmI(S~9GKX8pp6nqh*&xpC)j5^ zD1ez`Wn>4hKe3nZfhcye5{gFxf(W(<{t?5D4r_sUC@u!0LHx*ZgDSMz;=!O62FC;^ zRfwC#v_Lqbg#!sy1GS=ZA}9(qXIpQWVs>LGFQ@gqhkfp6?u9F+PzU*n6=PTs(U2Oz zT!FG0PVgv(5)i-&L-BY_NGM8e_NDzxt9&bPIIcC7mwVsve#3jh_a)!0*%=4sW>+1U zF{3;*{y(h0Yh2k+CYLymuBWr?d)Y&63!F#S(Q);V@jgN)(qZGhN@va%FUh0O&4pH+8S-Hio;_>})yQmN?pdXmgX+_H5%fmX!MBgNsXiGSk?)sKiGb_b)8<$=M4^ zd~(a~zf_m{=!^49eex-PwlY?b}heB~kAwUcbVx9Q6ZdEpLAYr5s^m9IZjP6FMK9WT#NiI0))lQoy& z)#3A)d@uQ~_uT>hsrWo7^8YHh@U;}jQ!Eiw!vSyvoQN?T^57?GK-ClA($SzG%OMBt zG4^AJcVYIr_dj3Z@GUU;UiPJZ_xd*a7JO}zxzfk{%gwg=6D>4HR{O$2mhzcD?yoSd zGL_%$JyP*oPt^I>vPQ?R-C_H`+P-Q12g@zyou*ay)Xmy{eDbuiMqA?t29Gq_Y-_}Q z(NI@cLw&4syU-J^TYF@$-rEp9x~93VUP@`LZO?zWu{*qHOM8EPTJMEY(9?IYd1L1u zNvrD&4fMo9sWtViZl1ZCJw3~;voB0Dt9v0Ylgxa)W-4#z_yV-k+Q0Y6Kxce=XpNBG z*SLK^*^?H#4#qZbY~8!DzkO$S+w*t49PCYon>HTZl-}Ihxwj>;CVix{_u%Gq*Y16? z(y*y+tIm~nYPf{Xr5?TQ_o=re_{4h+vWe`+gMSL9xOo1 z@A=MEe6`|4`Hy_}qV*qR<$NXA?nKn)?M_50w7UxJ&M5QFwfUa#^_DkQyixI~a!dKo zykGaGymQf>#k+M&nYXcgrQ2k7+pw}HB4@XLI62VY*%9c~dwQ?!?C#Lpm&f(PR~ck( z{0vKNF~8(q)~3JyV%vqI>sVu>dA)mX+y3ADvJE@&+ykJNWqMh~2@{6=RSf^fSnLaE zB0!Qn@jp;e+LABJ&V6{{xtDG**J6x5pUL-G-`BAZ@Ah5ktM~bQeZJrN{vBidL&fYX ztSilz=y@5tveW$IGSeiJ$@>HPcdnw#{IoZ7yw&PzY`iUKv)Ot!#UfjyiH>dc4O%)K z?QU(7#qQWZ`_@#nXG5^3r)5X?j)o)k>%v|82V#BVhTd@Rx~_gb(b>Jdw}11x(2dnG zEtQIDvG!d%wp3qLy&~F~>PxSPCQ}EKJzBrk9Z2`J>K*Z9PbzsZxdI<0w9E>ry0$vj z8P|8~-N{5!??%Dqfg}5yw(bkbjj6C0tKZXhB-yi0ZV;14`?mJwC0;wzcb`Vk)q?uWwIRKn-nAwrGJJ?T1pE zVmq{b{X(j1bGkd4>E3YYaP;V2^pgY7)mK5`5#_KX zD4|G1sIBhQ`g&V;_G-O4x;ha}s&8(4cE>z$h;P#m4%=^o*me+mXF9cI$F81p4Y!!< zIDhYDCo|?=K0#oL_;;@2nE8XgMH9^map+C#A5WO)6T@D}Ud6j|?`~72`3I)*pZdOQ z#!R0yKW#2M-fVSFU$Vq}+rjJs@0$+)0q{7D-SlyD^z3A7oB7;{kD0&iwE6yI-h6J~ z1Lj9%@Mv)S$H4Cu@O{s@NiUfH%o)CYVFYHMC?q@Ri4b!_(2q3*%1tx@=^dgyln=qd zl%Jbl$n*J)SoY_93(ie?^>1MGwCYp8H}@XPil6g8-es}+r(uL93w|X0oS@%YZ%XTC zpJJBd?5RqZkG*`4WhHy)V;1|JZ=JN@$9nFqleQTvGH;veO`kXUzGr>I_c7lMz8dQ) z=m<}mK3{Q1#kPuB<-f3gvHZ*BN6Xigd%ZvMK4k6lws{rLd*;VI-|^fFE5+ini{{N` zPncdQyRB@i)mb*fe9Zm2`-|?w?rYs;u77i#a<#f7=U>cIY_putI!`+HITt$q)A6+9 zq~m}?aG30w7wiw&yX@E6C)r-LowgmbZL^vzFIbr62FoHdKZ-FJ{1>z>+GUQlYQ6i@ zdQXpbP%p(?anqPmWRe(Rk;sf=lDKh9u~N(q17k{+Vp+)ak0}-vAhgSnl@m%dPP%>q zMu8~SR3sdiBe9??B-Ep0NM0&-z>8%GcU__of5L2%nEkn!>b>#Eit1Nqv+Ac*_TBH;R6FlGd-q|t$cDaU+pq|R8WlE@2<#a;*-``;*>pt@ z$RQC15xfZDSP%RDkWIb!QybWs^R`7R#|%HJ2jj3j$}k$~uw{ra1i;ioYf_DgSgDdO zihV}I&t<#&LV7>%;|^zu!VWG_92t~F&3JfLQmJ+Og&@w>J~2CcKJ`h?K5F+G!XSSc0QHRFN` zyGa5XxfUe*R4ks*6j%d7y41;jOQZhcBbe5?-?mN8ZoU5l)5^gho#k(ud}n5w+8!~fTfJOgiuh6iMk$%#sx)*MMP1S$POXG zG8a=KiWZeap_m@k!lGt=c-r(I|KyzXitS&_lbya-OuoPP{-5tZeZTYl+V_U7A2qpCt{0uZ zcg`_?6oVNsiyx^7lAdsF&_2YVsWq>}07{+(KfM≫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%0D%S!Rk+mWZ3uG!ePEk*FWpr-i7F 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 delta 15321 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 M0 void; + /** Açıkken hap dışına basılınca. */ + onDisariTiklama?: () => void; + /** Hapın ekran okuyucu adı. */ + etiket: string; + className?: string; + /** O anki adımın yüzü; `data-odak` taşıyan öğe yüz gelince odaklanır. */ + children: ReactNode; +} + +export function SekilHapi({ + adim, + ilkAdim, + yon, + duyuru, + onGeri, + onDisariTiklama, + etiket, + className, + children, +}: SekilHapiProps) { + const azalt = useReducedMotion(); + const cerceveRef = useRef(null); + // Doğal akış (false) ↔ ölçülü çerçeve (true). Ref, efektlerin bayat + // kapanış okumaması için state'in aynası. + const [olculu, setOlculu] = useState(false); + const olculuRef = useRef(false); + const adimRef = useRef(adim); + useLayoutEffect(() => { + adimRef.current = adim; + }, [adim]); + const genislik = useMotionValue("auto"); + const yukseklik = useMotionValue("auto"); + const acik = adim !== ilkAdim; + + /** Çerçeveyi (kenarlık dâhil) yüz ölçüsüne götürür. */ + const hedefeGit = useCallback( + (w: number, h: number) => { + const cerceve = cerceveRef.current; + if (!cerceve || !olculuRef.current) return; + const ekW = cerceve.offsetWidth - cerceve.clientWidth; + const ekH = cerceve.offsetHeight - cerceve.clientHeight; + const gecis = azalt ? { duration: 0 } : YAY.donusum; + const hareket = Promise.all([ + animate(genislik, w + ekW, gecis), + animate(yukseklik, h + ekH, gecis), + ]); + void hareket.then(() => { + // Kapalı adıma dönüş bitti: doğal akışa geri (duyarlı yerleşim). + if (adimRef.current !== ilkAdim || !olculuRef.current) return; + olculuRef.current = false; + genislik.set("auto"); + yukseklik.set("auto"); + setOlculu(false); + }); + }, + [azalt, genislik, yukseklik, ilkAdim], + ); + + /** Yeni yüz monte oldu: çerçeveyi olduğu ölçüye kilitle, sonra hedefe yaylan. */ + const gecisBaslat = useCallback( + (w: number, h: number) => { + const cerceve = cerceveRef.current; + if (!cerceve) return; + if (!olculuRef.current) { + olculuRef.current = true; + genislik.jump(cerceve.offsetWidth); + yukseklik.jump(cerceve.offsetHeight); + setOlculu(true); + } + hedefeGit(w, h); + }, + [genislik, yukseklik, hedefeGit], + ); + + useEffect(() => { + if (!acik || !onDisariTiklama) return; + function dinle(olay: PointerEvent) { + const cerceve = cerceveRef.current; + if (cerceve && !cerceve.contains(olay.target as Node)) onDisariTiklama?.(); + } + document.addEventListener("pointerdown", dinle); + return () => document.removeEventListener("pointerdown", dinle); + }, [acik, onDisariTiklama]); + + function tusBasildi(olay: KeyboardEvent) { + if (olay.key !== "Escape" || !onGeri || !acik) return; + olay.preventDefault(); + olay.stopPropagation(); + onGeri(); + } + + return ( +

+ + + + {children} + + + +

+ {duyuru} +

+
+ ); +} + +const YUZ_VARYANT: Variants = { + giris: (yon: 1 | -1) => ({ + opacity: 0, + x: KAYMA * yon, + scale: 0.95, + filter: "blur(4px)", + }), + orta: { + opacity: 1, + x: 0, + scale: 1, + filter: "blur(0px)", + transition: { delay: VURUS, duration: SURE.standart, ease: EGRI.giris }, + }, + cikis: (yon: 1 | -1) => ({ + opacity: 0, + x: -KAYMA * yon, + scale: 0.97, + filter: "blur(4px)", + transition: { duration: SURE.anlik, ease: EGRI.standart }, + }), +}; + +const YUZ_VARYANT_AZALT: Variants = { + giris: { opacity: 0 }, + orta: { opacity: 1, transition: { duration: SURE.hizli } }, + cikis: { opacity: 0, transition: { duration: SURE.hizli } }, +}; + +function Yuz({ + dogal, + azalt, + onGecis, + onOlcu, + children, +}: { + /** Doğal akıştaki ilk yüz: çerçeveyi kilitlemez, ölçü bildirmez. */ + dogal: boolean; + azalt: boolean; + onGecis: (w: number, h: number) => void; + onOlcu: (w: number, h: number) => void; + children: ReactNode; +}) { + const ref = useRef(null); + + // Monte: ölç (dönüşümsüz offset ölçüsü), çerçeveyi başlat, odağı ver; + // sonra yüzün kendi boyut değişimlerini izle (hata satırı açılır vb.). + useLayoutEffect(() => { + const el = ref.current; + if (!el) return; + if (!dogal) onGecis(el.offsetWidth, el.offsetHeight); + el.querySelector("[data-odak]")?.focus({ preventScroll: true }); + const gozlemci = new ResizeObserver(() => { + onOlcu(el.offsetWidth, el.offsetHeight); + }); + gozlemci.observe(el); + return () => gozlemci.disconnect(); + // eslint-disable-next-line react-hooks/exhaustive-deps -- yalnız mount + }, []); + + return ( + + {children} + + ); +} +``` + +## 4. Kod — `src/features/sihirbaz/components/siralama-hapi.tsx` + +```tsx +"use client"; + +// Üst çubuğun ortasındaki gezinme hapı (lg+): kapalıyken "Sıralamanı gir" +// (ya da kayıtlı sıra özeti) + "Nasıl çalışır?" + Ara; dokununca AYNI hap +// adım adım yeniden biçimlenir — puan türü → başarı sıralaması → bilet +// (özet) → kaydedildi. Arc UI "Booking pill" akışının (kişi → tarih → saat → +// bilet → rezerve) bizdeki karşılığı; hap mekaniği SekilHapi'de (DESIGN.md +// §4.33), bu dosya yalnız yüzleri ve akışı bilir. +// +// İki yol: +// - Profil yok: bilet "Tercihlere geç" der → hap kapanır, tercih profili +// kapısı (modal) sıra+türü hazır alır, facetleri yükler ve doğrudan alan/il +// adımıyla açılır (`tercihlereGec`). Sıra adımı modalda tekrar sorulmaz. +// - Profil var: bilet "Kaydet" der → profil yerinde yazılır (alan/il +// seçimleri korunur), riskler yenilenir, "kaydedildi" yüzü bir vuruş durup +// kapanır. Alan/il de değişecekse bilet üstündeki bağlantı modalı açar. +// lg altındaki ikinci satır bu hapı kullanmaz (modal yolu, katalog-arama.tsx). + +import { useEffect, useEffectEvent, useState, type ReactNode } from "react"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { + ArrowLeft, + ArrowRight, + Check, + SquarePen, + Trophy, + X, +} from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { SecimHaplari } from "@/components/ui/secim-haplari"; +import { SekilHapi } from "@/components/ui/sekil-hapi"; +import { preloadTercihProfiliKapisi } from "@/features/liste/components/tercih-profili-kapisi-lazy"; +import { + profilDuzenlemeyiAc, + profilTamamlandi, + tercihlereGec, + useTercihProfili, +} from "@/features/liste/hooks/use-tercih-profili"; +import { PUAN_TURU_ETIKET, type TercihProfili } from "@/features/sihirbaz/sihirbaz-sabitler"; +import { tercihProfiliYaz } from "@/features/sihirbaz/sihirbaz-profil"; +import { olay, siraKovasi } from "@/lib/analitik"; +import { cn } from "@/lib/utils"; + +const PUAN_TURLERI_SECENEK = [ + { deger: "say", etiket: "Sayısal" }, + { deger: "ea", etiket: "Eşit Ağırlık" }, + { deger: "soz", etiket: "Sözel" }, + { deger: "dil", etiket: "Dil" }, + { deger: "tyt", etiket: "TYT" }, +] as const; +type PuanTuru = (typeof PUAN_TURLERI_SECENEK)[number]["deger"]; + +function puanTuruMu(deger: string): deger is PuanTuru { + return PUAN_TURLERI_SECENEK.some((s) => s.deger === deger); +} + +type Adim = "kapali" | "tur" | "sira" | "bilet" | "kaydedildi"; +const SIRA: Record = { + kapali: 0, + tur: 1, + sira: 2, + bilet: 3, + kaydedildi: 4, +}; + +/** Kaydedildi yüzünün ekranda kaldığı süre (ms); sonra hap kendiliğinden kapanır. */ +const KAYDEDILDI_BEKLEME = 2000; + +const YUVARLAK = + "flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-full transition-[background-color,transform] duration-150 focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none active:scale-[0.96]"; +const GERI = cn(YUVARLAK, "bg-slate-100 text-slate-700 hover:bg-slate-200"); +const ILERI = cn(YUVARLAK, "bg-slate-900 text-slate-50 hover:bg-slate-700"); + +export function SiralamaHapi({ araButonu }: { araButonu: ReactNode }) { + const router = useRouter(); + const profil = useTercihProfili(); + const [adim, setAdim] = useState("kapali"); + const [yon, setYon] = useState<1 | -1>(1); + const [tur, setTur] = useState("say"); + const [siralama, setSiralama] = useState(""); + const [hata, setHata] = useState(null); + const siraDeger = Number(siralama.replace(/\./g, "")); + const turEtiketi = PUAN_TURU_ETIKET[tur] ?? tur; + + function adimaGec(yeni: Adim) { + setYon(SIRA[yeni] > SIRA[adim] ? 1 : -1); + setAdim(yeni); + } + + function ac() { + preloadTercihProfiliKapisi(); + setHata(null); + setTur(profil && puanTuruMu(profil.tur) ? profil.tur : "say"); + setSiralama(profil ? profil.sira.toLocaleString("tr-TR") : ""); + adimaGec("tur"); + } + + function kapat() { + setHata(null); + adimaGec("kapali"); + } + + function geri() { + if (adim === "sira") adimaGec("tur"); + else if (adim === "bilet") adimaGec("sira"); + else kapat(); + } + + function siralamaDegisti(ham: string) { + setHata(null); + const rakamlar = ham.replace(/\D/g, "").slice(0, 7); + setSiralama(rakamlar ? Number(rakamlar).toLocaleString("tr-TR") : ""); + } + + function siraGonder(e: React.FormEvent) { + e.preventDefault(); + if (!siraDeger || siraDeger < 1 || siraDeger > 4_000_000) { + setHata("Geçerli bir başarı sıralaması gir (ör. 85.000)."); + return; + } + setHata(null); + adimaGec("bilet"); + } + + /** Profil yok: sıra+tür kapıya verilir, kapı facetleri yükleyip alan/il adımıyla açılır. */ + function tercihlereDevam() { + kapat(); + tercihlereGec({ sira: siraDeger, tur }); + } + + /** Profil var: sıra+tür yerinde yazılır, alan/il seçimleri korunur. */ + function kaydet() { + if (!profil) return; + const yeni: TercihProfili = { sira: siraDeger, tur, secimler: profil.secimler }; + tercihProfiliYaz(yeni); + // Depodaki profili tazeler, listedeki riskleri yeni sıraya göre yeniler. + profilTamamlandi(yeni); + olay("sira_girildi", { + kaynak: "duzenle", + tur, + sira_kovasi: siraKovasi(siraDeger), + }); + // /sonuc tablosu profil çerezinden SSR'lanır; URL değişmediği için tazele. + router.refresh(); + adimaGec("kaydedildi"); + } + + function tercihleriDeDegistir() { + kapat(); + profilDuzenlemeyiAc(); + } + + const kendiligindenKapat = useEffectEvent(kapat); + useEffect(() => { + if (adim !== "kaydedildi") return; + const zamanlayici = window.setTimeout(kendiligindenKapat, KAYDEDILDI_BEKLEME); + return () => window.clearTimeout(zamanlayici); + }, [adim]); + + const duyuru: Record = { + kapali: "", + tur: "Puan türünü seç.", + sira: `${turEtiketi} başarı sıralamanı yaz.`, + bilet: `Özet: ${siraDeger.toLocaleString("tr-TR")} · ${turEtiketi}. ${profil ? "Kaydet" : "Tercihlere geç"}.`, + kaydedildi: `Sıralaman güncellendi: ${siraDeger.toLocaleString("tr-TR")} · ${turEtiketi}.`, + }; + + return ( + + {adim === "kapali" ? ( +
+ {profil ? ( + + ) : ( + <> + + + Nasıl çalışır? + + + )} + {araButonu} +
+ ) : null} + + {adim === "tur" ? ( +
+ + + Puan türün + + + +
+ ) : null} + + {adim === "sira" ? ( +
+
+ + {/* Hap kabının içinde kenarlıksız ham alan (DESIGN.md §4.6 istisnası): + hapın kendisi form alanıdır, ikinci bir hap çizilmez. */} + + + · {turEtiketi} + + +
+ {hata ? ( + + ) : null} +
+ ) : null} + + {adim === "bilet" ? ( +
+
+
+
+

+ Başarı sıralaman +

+

+ {siraDeger.toLocaleString("tr-TR")} +

+
+ +
+
+
+
Puan türü
+
{turEtiketi}
+
+
+
Tercihler
+
+ {profil + ? `${profil.secimler.kategoriler.length} alan · ${ + profil.secimler.iller.length + ? `${profil.secimler.iller.length} il` + : "her il" + }` + : "Sıradaki adım"} +
+
+
+ {profil ? ( + + ) : null} +
+
+ + +
+
+ ) : null} + + {adim === "kaydedildi" ? ( +
+ + + + + + Sıralaman güncellendi + + + {siraDeger.toLocaleString("tr-TR")} · {turEtiketi} + + + {/* Kapatma çarpısı DialogContent varsayılanıyla aynı sınıf seti (§4.3). */} + +
+ ) : null} +
+ ); +} +``` + +## 5. Bağlantı yaması (nav, kapı deposu, kapı modalı, DESIGN.md §4.33–4.34) + +`git apply` ile uygulanır (HEAD `bc920f6` tabanlı; çakışırsa hunk'lar elle taşınır). DESIGN.md bölümleri §6'da. + +```diff +diff --git a/src/features/katalog/components/katalog-arama.tsx b/src/features/katalog/components/katalog-arama.tsx +index 35aad40..64265bd 100644 +--- a/src/features/katalog/components/katalog-arama.tsx ++++ b/src/features/katalog/components/katalog-arama.tsx +@@ -25,6 +25,7 @@ import { + } from "@/features/liste/hooks/use-tercih-profili"; + import { preloadTercihProfiliKapisi } from "@/features/liste/components/tercih-profili-kapisi-lazy"; + import { PUAN_TURU_ETIKET } from "@/features/sihirbaz/sihirbaz-sabitler"; ++import { SiralamaHapi } from "@/features/sihirbaz/components/siralama-hapi"; + import { olay } from "@/lib/analitik"; + import { + ArrowRight, +@@ -266,69 +267,31 @@ export function KatalogArama({ rehberler }: { rehberler: RehberAramaKaydi[] }) { + + return ( + <> +- {/* lg altında logo + sağ küme ile çakışır (absolute); o aralıkta gizli */} +-