feat(katalog): şehre göre üniversiteler — /universiteler/[il] sayfaları ve şehir çipleri
- Veri: getAllIller/getIlBySlug (üniversite en çok programının olduğu ile sayılır; ili boş olan hiçbir şehre girmez; tireli yurt dışı adlar baş harfli). - /universiteler: "Şehre göre" çip satırı (2+ üniversiteli 28 şehir) + "Tüm şehirler" A–Z üç sütunlu liste (#tum-sehirler). - /universiteler/[il]: 92 statik şehir sayfası — katalog detay düzeni, il ve üniversite sayısı hapları, kompakt sıra satırı, devlet/vakıf/KKTC-yurt dışı öbekleri, diğer şehir çipleri, CTA bandı; metadata + breadcrumb JSON-LD. - SehirCipleri: sihirbaz il çipiyle aynı kalıp, aktif şehir mavi dolu. - Sitemap'e şehir sayfaları eklendi. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -62,6 +62,8 @@ const globalKatalog = globalThis as unknown as {
|
||||
bolumOzetler?: BolumOzet[];
|
||||
uniMap?: Map<string, UniKayit>;
|
||||
uniOzetler?: UniOzet[];
|
||||
iller?: IlOzet[];
|
||||
ilMap?: Map<string, IlOzet>;
|
||||
};
|
||||
|
||||
function bolumMapGetir(): Map<string, BolumKayit> {
|
||||
@@ -369,6 +371,68 @@ export function getAllUniversiteSlugs(): string[] {
|
||||
return [...uniMapGetir().keys()];
|
||||
}
|
||||
|
||||
// ---------- İl (şehir) tarafı: /universiteler/[il] ----------
|
||||
|
||||
export type IlOzet = {
|
||||
/** turkishSlugify(il): "istanbul", "saraybosna-bosna-hersek" */
|
||||
slug: string;
|
||||
/** Görünen ad: İstanbul, Bakü-Azerbaycan */
|
||||
ad: string;
|
||||
/** Bu ilde yer alan üniversiteler (UniOzet.il esas; ad sırasıyla) */
|
||||
uniler: UniOzet[];
|
||||
programSayisi: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* "BAKÜ-AZERBAYCAN" → "Bakü-Azerbaycan": trBaslikDuzeni yalnız boşlukta
|
||||
* böler; yurt dışı şehirlerin tireli ülke eki de baş harfli yazılır.
|
||||
*/
|
||||
function ilGorunenAd(il: string): string {
|
||||
return trBaslikDuzeni(il).replace(/-(\p{L})/gu, (_, harf: string) =>
|
||||
`-${harf.toLocaleUpperCase("tr-TR")}`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Üniversiteleri iline göre kümeler; sıralama üniversite sayısına göre
|
||||
* azalan, eşitlikte ad. Her üniversite tek ilde sayılır (UniOzet.il: en çok
|
||||
* programının bulunduğu il). İli olmayan (NULL/boş) üniversite hiçbir ile
|
||||
* girmez. KKTC ve yurt dışı şehirler de birer ildir (LEFKOŞA, BAKÜ-…).
|
||||
*/
|
||||
export function getAllIller(): IlOzet[] {
|
||||
if (!globalKatalog.iller) {
|
||||
const bySlug = new Map<string, IlOzet>();
|
||||
for (const u of getAllUniversiteler()) {
|
||||
const il = u.il?.trim();
|
||||
if (!il) continue;
|
||||
const slug = turkishSlugify(il);
|
||||
if (!slug) continue;
|
||||
let kayit = bySlug.get(slug);
|
||||
if (!kayit) {
|
||||
kayit = { slug, ad: ilGorunenAd(il), uniler: [], programSayisi: 0 };
|
||||
bySlug.set(slug, kayit);
|
||||
}
|
||||
kayit.uniler.push(u);
|
||||
kayit.programSayisi += u.programSayisi;
|
||||
}
|
||||
globalKatalog.ilMap = bySlug;
|
||||
globalKatalog.iller = [...bySlug.values()].sort(
|
||||
(a, b) =>
|
||||
b.uniler.length - a.uniler.length || a.ad.localeCompare(b.ad, "tr-TR"),
|
||||
);
|
||||
}
|
||||
return globalKatalog.iller;
|
||||
}
|
||||
|
||||
export function getAllIlSlugs(): string[] {
|
||||
return getAllIller().map((il) => il.slug);
|
||||
}
|
||||
|
||||
export function getIlBySlug(slug: string): IlOzet | null {
|
||||
getAllIller();
|
||||
return globalKatalog.ilMap!.get(slug) ?? null;
|
||||
}
|
||||
|
||||
export function getUniversiteBySlug(slug: string): UniDetay | null {
|
||||
const kayit = uniMapGetir().get(slug);
|
||||
if (!kayit) return null;
|
||||
|
||||
Reference in New Issue
Block a user