import type { ReactNode } from "react"; import Link from "next/link"; import { ChevronLeft, ChevronRight } from "lucide-react"; import { ONCEKI_YIL, SON_YIL } from "@/lib/veri-yillari"; /** Programatik tablo sayfaları için satır dilimi boyutu. */ export const SAYFA_BOYU = 50; /** * Düz listenin `sayfa` numaralı dilimi. Metadata (title/description) ile sayfa * gövdesi aynı satırları anlatsın diye dilim hesabı tek yerde durur. */ export function sayfaDilimi(liste: readonly T[], sayfa: number): T[] { return liste.slice((sayfa - 1) * SAYFA_BOYU, sayfa * SAYFA_BOYU); } /** * Aralıktaki sıraların hangi yıldan geldiği: hepsi son yıl / hepsi bir önceki * yıl / karışık. `yalnizOnceki`: sırası son yılda olmayıp bir önceki yıldan * gelen satır sayısı; `siraliSayi`: sırası olan toplam satır. */ export function siraYiliEtiketi( yalnizOnceki: number, siraliSayi: number, ): string { if (yalnizOnceki === 0) return String(SON_YIL); return yalnizOnceki === siraliSayi ? String(ONCEKI_YIL) : `${ONCEKI_YIL}–${SON_YIL}`; } /** * Üniversite ve bölüm tablo sayfalarının altındaki CtaSiraForm kartının köprü * cümlesi — iki sayfa birebir aynı metni kullansın diye tek kaynak. Sunucu * bileşenlerinden okunduğu için "use client" olan cta-sira-form.tsx'te * duramaz (istemci modülünün sabitleri sunucuda değer olarak okunamaz). * Vaat içermez: tablo geçmiş veridir, ürün sıralamaya yakın programları * risk seviyesine göre ayırıp listeler. */ export const KATALOG_CTA_ACIKLAMA = "Bu tablodaki tabanlar geçmiş yerleştirmelerin sonucu; bu yıl değişebilir. Sıralamanı gir, tabanı sıralamana yakın programları risk seviyesine göre ayrılmış hâlde listeleyelim. Ücretsiz, üyelik gerekmez."; /** * Statik path tabanlı sayfalama navigasyonu. 1. sayfa taban URL'in * kendisidir (/bolum/x), sonrakiler /bolum/x/sayfa/2 ... — hepsi gerçek * , Google her sayfayı ayrı statik URL olarak tarar. * * `onSayfa` verilirse Link yerine aynı görünümde butonlar render edilir — * istemci tarafında sıralanmış listelerin sayfalaması URL değiştirmeden * bu geri çağrıyla ilerler. */ export function Sayfalama({ tabanYol, sayfa, toplamSayfa, sorgu, onSayfa, }: { tabanYol: string; sayfa: number; toplamSayfa: number; sorgu?: string; onSayfa?: (n: number) => void; }) { if (toplamSayfa <= 1) return null; const yol = (n: number) => { const path = n === 1 ? tabanYol : `${tabanYol}/sayfa/${n}`; return sorgu ? `${path}?${sorgu}` : path; }; const gecis = ( n: number, className: string, icerik: ReactNode, ozellikler?: { rel?: string; aktif?: boolean }, ) => onSayfa ? ( ) : ( {icerik} ); // 7'den çok sayfada pencere: 1 … (c-1) c (c+1) … son. Telefonda // (sm altı) tek satır kalsın diye yalnız Önceki · aktif · Sonraki görünür; // diğer numaralar HTML'de durur (tarayıcı botları tüm sayfaları görür). const numaralar: (number | "...")[] = []; if (toplamSayfa <= 7) { for (let n = 1; n <= toplamSayfa; n++) numaralar.push(n); } else { numaralar.push(1); if (sayfa > 3) numaralar.push("..."); for ( let n = Math.max(2, sayfa - 1); n <= Math.min(toplamSayfa - 1, sayfa + 1); n++ ) { numaralar.push(n); } if (sayfa < toplamSayfa - 2) numaralar.push("..."); numaralar.push(toplamSayfa); } return ( ); }