feat(veri): bileşenler yılsız Program'a ve veri-yillari sözlüğüne geçti (P-B b)

- SiraSerisi = { siraGecmisi, ilkYil? }; yardımcılar dizinin kendi son iki
  elemanıyla çalışır, yıl ilkYil + indeks. raporSiraSerisi diziyi doldurmaz:
  5 elemanlı eski raporlar 2024→2025 trendini göstermeye devam eder.
- Tablo başlıkları "Son ${VERI_YIL_SAYISI} yıl"; rapor listesi başlığı kaydın
  kendi pencere uzunluğunu söyler (eski rapor: 5).
- siraYiliEtiketi SON_YIL/ONCEKI_YIL'dan; bölüm/üniversite sayfa metinleri ve
  metadata SON_YIL, TERCIH_YILI, BASLIK_YILI sözlüğünden.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-21 17:00:39 +03:00
parent ce40b7c5b3
commit ceeb70375d
10 changed files with 127 additions and 89 deletions

View File

@@ -1,30 +1,37 @@
import { TrendingDown, TrendingUp } from "lucide-react";
import type { Program } from "@/types/yokatlas";
import { ILK_YIL } from "@/lib/veri-yillari";
/** Taban sıra sütunlarının yapısal alt kümesi: hem DB programı hem de
* rapordaki kaydedilmiş sıra geçmişi (bkz. raporSiraSerisi) bu tipe uyar. */
export type SiraSerisi = Pick<
Program,
"sira2021" | "sira2022" | "sira2023" | "sira2024" | "sira2025"
>;
/** Taban sıra geçmişinin yapısal alt kümesi: hem DB programı hem de rapordaki
* kaydedilmiş sıra geçmişi (bkz. raporSiraSerisi) bu tipe uyar. Dizi `ilkYil`'a
* (yoksa veri penceresinin ilk yılına) demirlidir: eleman yılı
* `ilkYil + indeks`. Uzunluk sabit DEĞİL — eski kayıtlı raporlar daha kısa
* dizi taşır; yardımcılar dizinin kendi son iki elemanıyla çalışır. */
export type SiraSerisi = {
siraGecmisi: readonly (number | null)[];
ilkYil?: number;
};
/** Rapordaki [2021..2025] dizisini sütunlu seriye çevirir. */
export function raporSiraSerisi(gecmis?: (number | null)[]): SiraSerisi {
const g = gecmis ?? [];
return {
sira2021: g[0] ?? null,
sira2022: g[1] ?? null,
sira2023: g[2] ?? null,
sira2024: g[3] ?? null,
sira2025: g[4] ?? null,
};
/** Rapordaki kayıtlı diziyi seriye çevirir. Dizi DOLDURULMAZ: 5 elemanlı eski
* kayıt 5 elemanlı kalır, "son iki yıl" kaydın kendi son iki yılıdır. */
export function raporSiraSerisi(
gecmis?: (number | null)[],
ilkYil?: number,
): SiraSerisi {
return { siraGecmisi: gecmis ?? [], ilkYil };
}
/** Serinin son iki yılı: [bir önceki, son]. */
function sonIkiSira(program: SiraSerisi): [number | null, number | null] {
const g = program.siraGecmisi;
return [g[g.length - 2] ?? null, g[g.length - 1] ?? null];
}
export function programEtkinSira(program: SiraSerisi): number | null {
return program.sira2025 ?? program.sira2024;
const [onceki, son] = sonIkiSira(program);
return son ?? onceki;
}
/** 2021–2025 taban sıralamasını sonuç listesindeki kompakt çizgiyle gösterir. */
/** Taban sıralaması geçmişini sonuç listesindeki kompakt çizgiyle gösterir. */
export function ProgramSiraGecmisi({ program }: { program: SiraSerisi }) {
// Satır başına render edilen bileşen: filter/map/min/max/map/map'in 6 ayrı
// geçişi tek döngüde toplanır (js-combine-iterations, js-min-max-loop)
@@ -32,14 +39,10 @@ export function ProgramSiraGecmisi({ program }: { program: SiraSerisi }) {
let min = Infinity;
let max = -Infinity;
const ozetParcalari: string[] = [];
for (const [yil, sira] of [
[2021, program.sira2021],
[2022, program.sira2022],
[2023, program.sira2023],
[2024, program.sira2024],
[2025, program.sira2025],
] as const) {
const ilkYil = program.ilkYil ?? ILK_YIL;
for (const [indeks, sira] of program.siraGecmisi.entries()) {
if (sira == null) continue;
const yil = ilkYil + indeks;
yillar.push([yil, sira]);
if (sira < min) min = sira;
if (sira > max) max = sira;
@@ -89,12 +92,13 @@ export function ProgramSiraGecmisi({ program }: { program: SiraSerisi }) {
/** Son iki yılın tabanı %10'dan fazla değiştiğinde yönü işaretler. */
export function ProgramTabanTrendi({ program }: { program: SiraSerisi }) {
if (program.sira2025 == null || program.sira2024 == null) return null;
const [onceki, son] = sonIkiSira(program);
if (son == null || onceki == null) return null;
const oran = (program.sira2024 - program.sira2025) / program.sira2024;
const oran = (onceki - son) / onceki;
if (Math.abs(oran) < 0.1) return null;
const gecis = `${program.sira2024.toLocaleString("tr-TR")} → ${program.sira2025.toLocaleString("tr-TR")}`;
const gecis = `${onceki.toLocaleString("tr-TR")} → ${son.toLocaleString("tr-TR")}`;
if (oran > 0) {
return (
<TrendingUp