feat(tasarim): şehir sayfasına hero dilinde piksel harita; üniversite konum kartı da aynı harita
All checks were successful
Deploy / deploy (push) Successful in 4m39s

- scripts/il-izgara-uret.ts → src/lib/il-izgara-verisi.ts: 81 il ve 7 ülke
  kontürü hero'nun dot-matrix ızgarasına (72×31) rasterize; küçük iller 2×2 garanti.
- SehirPikselHaritasi: iri kareler, altı opaklık, kıyı serpintisi, usePixelHeat
  ısı fırçası; bulunulan il iri turuncu karelerle sırayla belirir (kt-piksel-belir)
  ve nabız atar; KKTC/yurt dışında şehir merkezinde 2×2 iri kare.
- Şehir sayfası başlığı beyaz piksel dokulu yüzeyde (SehirYuzeyi), harita sağda/altta.
- UniversiteKonumHaritasi düz SVG yerine aynı piksel haritayı kullanır.
- DESIGN.md §4.12/§4.17/§10.8 güncellendi.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-24 14:56:11 +03:00
parent 259534fa9c
commit eefac56659
8 changed files with 671 additions and 108 deletions

View File

@@ -1,20 +1,20 @@
import { normalizeIlAdi } from "@/lib/harita";
import { uniUlkeKonum, yurtdisiUniKonum } from "@/lib/harita-ulkeler";
import { cities } from "turkey-map-react/lib/data";
import {
HARITA_GENISLIK,
HARITA_UST_KIRPMA,
HARITA_YUKSEKLIK,
normalizeIlAdi,
} from "@/lib/harita";
import {
ULKE_HARITA_GENISLIK,
ULKE_HARITA_YUKSEKLIK,
uniUlkeKonum,
type UlkeKonum,
} from "@/lib/harita-ulkeler";
TurkiyePikselHaritasi,
UlkePikselHaritasi,
} from "./sehir-piksel-haritasi";
const SECILI_DOLGU = "oklch(0.809 0.105 251.8)";
const ZEMIN_DOLGU = "oklch(0.929 0.013 255.5)";
// Harita il adları modül yükünde bir kez DB biçimine çevrilir.
const HARITA_ILLERI = new Set(cities.map((c) => normalizeIlAdi(c.name)));
/**
* Üniversite sayfasındaki konum kartı: şehir sayfasıyla aynı dot-matrix
* harita (DESIGN.md §4.17; Bilal, 24 Eyl 2026: "bu kart kısmına piksel
* dokuları ekle"). Türkiye'de il turuncu noktalarla yanar; KKTC/yurt dışında
* ülke kontürü + kampüs şehrinde iri turuncu piksel.
*/
export function UniversiteKonumHaritasi({
universite,
il,
@@ -24,9 +24,15 @@ export function UniversiteKonumHaritasi({
}) {
const yurtdisi = uniUlkeKonum(universite, il);
if (yurtdisi) {
const konum = yurtdisiUniKonum(universite, il);
return (
<KonumBolumu universite={universite}>
<UlkeHaritasi universite={universite} konum={yurtdisi} />
<UlkePikselHaritasi
ulke={yurtdisi.ulke}
sehir={konum ? { x: konum.x, y: konum.y } : null}
etiket={`${universite} konumunun ${yurtdisi.ulkeAd} haritasındaki görünümü${yurtdisi.sehir ? ` (${yurtdisi.sehir})` : ""}`}
className="absolute inset-0 h-full w-full"
/>
<p className="pointer-events-none absolute bottom-0 left-0 text-xs font-medium text-slate-500">
{yurtdisi.ulkeAd}
{yurtdisi.sehir ? ` · ${yurtdisi.sehir}` : ""}
@@ -35,31 +41,15 @@ export function UniversiteKonumHaritasi({
);
}
if (!il) return null;
if (!il || !HARITA_ILLERI.has(il)) return null;
return (
<KonumBolumu universite={universite}>
<svg
viewBox={`0 ${HARITA_UST_KIRPMA} ${HARITA_GENISLIK} ${HARITA_YUKSEKLIK - HARITA_UST_KIRPMA}`}
<TurkiyePikselHaritasi
il={il}
etiket={`${universite} konumunun Türkiye haritasındaki görünümü`}
className="absolute inset-0 h-full w-full"
role="img"
aria-label={`${universite} konumunun Türkiye haritasındaki görünümü`}
>
{cities.map((city) => {
const secili = il ? normalizeIlAdi(city.name) === il : false;
return (
<path
key={city.id}
d={city.path}
fill={secili ? SECILI_DOLGU : ZEMIN_DOLGU}
stroke="white"
strokeWidth={secili ? 1.8 : 1}
>
<title>{city.name}</title>
</path>
);
})}
</svg>
/>
</KonumBolumu>
);
}
@@ -83,30 +73,3 @@ function KonumBolumu({
</section>
);
}
function UlkeHaritasi({
universite,
konum,
}: {
universite: string;
konum: UlkeKonum;
}) {
const { harita, ulkeAd, sehir } = konum;
return (
<svg
viewBox={`0 0 ${ULKE_HARITA_GENISLIK} ${ULKE_HARITA_YUKSEKLIK}`}
className="absolute inset-0 h-full w-full"
role="img"
aria-label={`${universite} konumunun ${ulkeAd} haritasındaki görünümü${sehir ? ` (${sehir})` : ""}`}
>
{harita.baglam.map((d, i) => (
<path key={`b${i}`} d={d} fill={ZEMIN_DOLGU} stroke="white" strokeWidth={1} />
))}
{harita.ulke.map((d, i) => (
<path key={`u${i}`} d={d} fill={SECILI_DOLGU} stroke="white" strokeWidth={1.8}>
<title>{ulkeAd}</title>
</path>
))}
</svg>
);
}