refactor: remove unused netler API and program-netleri component
- Deleted the netler API route and the associated program-netleri component as they are no longer needed in the application. This cleanup helps streamline the codebase and improve maintainability.
This commit is contained in:
@@ -1,19 +0,0 @@
|
|||||||
import { NextResponse, type NextRequest } from "next/server";
|
|
||||||
import { netlerGetir } from "@/lib/db";
|
|
||||||
|
|
||||||
// Program satırındaki "netler" butonunun verisi: programa yerleşen son
|
|
||||||
// kişinin yıl bazlı netleri (bkz. components/program-netleri.tsx). Veri
|
|
||||||
// yılda bir değiştiği için istemci tarafında gönül rahatlığıyla cache'lenir.
|
|
||||||
export function GET(request: NextRequest) {
|
|
||||||
const id = request.nextUrl.searchParams.get("id") ?? "";
|
|
||||||
if (!/^\d{1,12}$/.test(id)) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: "Geçerli bir program kimliği gerekli." },
|
|
||||||
{ status: 400 },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return NextResponse.json(
|
|
||||||
{ netler: netlerGetir(id) },
|
|
||||||
{ headers: { "Cache-Control": "public, max-age=86400" } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
// Program satırındaki "netler" butonu: YÖK Atlas'ın "yerleşen son kişinin
|
|
||||||
// netleri" verisini (data/yokatlas.db → netler tablosu, /api/netler) yıl
|
|
||||||
// sütunlu tabloyla alttan açılan sayfada gösterir (DESIGN.md §4.10: ayrıntı
|
|
||||||
// her zaman Drawer, ortada modal değil; §4.19 netler paneli). Kadın-erkek
|
|
||||||
// dağılımı bilinçli olarak yok: YÖK Atlas 2026 SPA'sına geçerken cinsiyet
|
|
||||||
// panelini yayından kaldırdı (bkz. scripts/detay.ts).
|
|
||||||
|
|
||||||
import { SATIR_BASLIK, SATIR_DUGME_BOYU } from "@/components/liste-satiri";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { ListChecks, X } from "lucide-react";
|
|
||||||
import type { ProgramNetSatiri } from "@/types/yokatlas";
|
|
||||||
import { olay } from "@/lib/analitik";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import {
|
|
||||||
Drawer,
|
|
||||||
DrawerClose,
|
|
||||||
DrawerContent,
|
|
||||||
DrawerDescription,
|
|
||||||
DrawerTitle,
|
|
||||||
DrawerTrigger,
|
|
||||||
} from "@/components/ui/drawer";
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from "@/components/ui/table";
|
|
||||||
|
|
||||||
// Ders sırası ÖSYM oturum sırasıyla; max = testteki soru sayısı.
|
|
||||||
const DERSLER: {
|
|
||||||
alan: keyof Omit<ProgramNetSatiri, "yil" | "puanTuru" | "tabanPuan" | "obp">;
|
|
||||||
etiket: string;
|
|
||||||
max: number;
|
|
||||||
}[] = [
|
|
||||||
{ alan: "tytTrkNet", etiket: "TYT Türkçe", max: 40 },
|
|
||||||
{ alan: "tytSosNet", etiket: "TYT Sosyal Bilimler", max: 20 },
|
|
||||||
{ alan: "tytMatNet", etiket: "TYT Matematik", max: 40 },
|
|
||||||
{ alan: "tytFenNet", etiket: "TYT Fen Bilimleri", max: 20 },
|
|
||||||
{ alan: "aytMatNet", etiket: "AYT Matematik", max: 40 },
|
|
||||||
{ alan: "aytFizNet", etiket: "AYT Fizik", max: 14 },
|
|
||||||
{ alan: "aytKimNet", etiket: "AYT Kimya", max: 13 },
|
|
||||||
{ alan: "aytBioNet", etiket: "AYT Biyoloji", max: 13 },
|
|
||||||
{ alan: "aytTdeNet", etiket: "AYT Türk Dili ve Edebiyatı", max: 24 },
|
|
||||||
{ alan: "aytTrh1Net", etiket: "AYT Tarih-1", max: 10 },
|
|
||||||
{ alan: "aytCog1Net", etiket: "AYT Coğrafya-1", max: 6 },
|
|
||||||
{ alan: "aytTrh2Net", etiket: "AYT Tarih-2", max: 11 },
|
|
||||||
{ alan: "aytCog2Net", etiket: "AYT Coğrafya-2", max: 11 },
|
|
||||||
{ alan: "aytDinNet", etiket: "AYT Din Kültürü", max: 6 },
|
|
||||||
{ alan: "aytFelNet", etiket: "AYT Felsefe Grubu", max: 12 },
|
|
||||||
{ alan: "ydtYdilNet", etiket: "YDT Yabancı Dil", max: 80 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const net = (n: number) =>
|
|
||||||
n.toLocaleString("tr-TR", { maximumFractionDigits: 2 });
|
|
||||||
|
|
||||||
type Durum = "bekliyor" | "yukleniyor" | "hazir" | "hata";
|
|
||||||
|
|
||||||
export function ProgramNetleriButonu({
|
|
||||||
programId,
|
|
||||||
isim,
|
|
||||||
universite,
|
|
||||||
className = "",
|
|
||||||
}: {
|
|
||||||
programId: string;
|
|
||||||
isim: string;
|
|
||||||
universite?: string;
|
|
||||||
className?: string;
|
|
||||||
}) {
|
|
||||||
const [durum, setDurum] = useState<Durum>("bekliyor");
|
|
||||||
const [netler, setNetler] = useState<ProgramNetSatiri[]>([]);
|
|
||||||
|
|
||||||
async function yukle() {
|
|
||||||
setDurum("yukleniyor");
|
|
||||||
try {
|
|
||||||
const res = await fetch(`/api/netler?id=${programId}`);
|
|
||||||
if (!res.ok) throw new Error(String(res.status));
|
|
||||||
const veri = (await res.json()) as { netler: ProgramNetSatiri[] };
|
|
||||||
setNetler(veri.netler);
|
|
||||||
setDurum("hazir");
|
|
||||||
} catch {
|
|
||||||
setDurum("hata");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function acildi(acik: boolean) {
|
|
||||||
if (!acik) return;
|
|
||||||
olay("netler_goruntulendi");
|
|
||||||
if (durum === "bekliyor" || durum === "hata") yukle();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Drawer onOpenChange={acildi} handleOnly>
|
|
||||||
<DrawerTrigger asChild>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
title="Son yerleşenin netleri"
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
className={`inline-flex ${SATIR_DUGME_BOYU} cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-card text-slate-500 transition-[background-color,border-color,color,transform] duration-150 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.92] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${className}`}
|
|
||||||
>
|
|
||||||
<ListChecks className="size-4" aria-hidden />
|
|
||||||
<span className="sr-only">{isim} — son yerleşenin netleri</span>
|
|
||||||
</button>
|
|
||||||
</DrawerTrigger>
|
|
||||||
{/* Çekmece kabı ve çarpı cta-sira-form.tsx'teki çekmeceyle birebir (§4.10, §4.3) */}
|
|
||||||
<DrawerContent
|
|
||||||
className="max-h-[92dvh] bg-card sm:mx-auto sm:max-w-2xl sm:border-x sm:border-slate-200 sm:shadow-2xl"
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<DrawerClose className="absolute top-3 right-3 z-10 flex size-9 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-popover text-slate-500 transition-[background-color,transform] duration-150 hover:bg-slate-100 hover:text-slate-800 active:scale-[0.96]">
|
|
||||||
<X className="size-4" aria-hidden />
|
|
||||||
<span className="sr-only">Kapat</span>
|
|
||||||
</DrawerClose>
|
|
||||||
<div className="min-h-0 flex-1 overflow-y-auto px-4 pt-5 pb-[max(1.25rem,env(safe-area-inset-bottom))] sm:px-6">
|
|
||||||
<DrawerTitle className="px-10 text-center font-heading text-2xl font-bold text-slate-900">
|
|
||||||
Son yerleşenin netleri
|
|
||||||
</DrawerTitle>
|
|
||||||
<DrawerDescription className="mx-auto mt-1 max-w-md px-4 text-center text-sm text-slate-500">
|
|
||||||
{isim}
|
|
||||||
{universite ? ` · ${universite}` : ""} — bölüme en düşük puanla
|
|
||||||
yerleşen adayın sınav netleri (YÖK Atlas).
|
|
||||||
</DrawerDescription>
|
|
||||||
<div className="mt-5">
|
|
||||||
<NetlerIcerik durum={durum} netler={netler} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</DrawerContent>
|
|
||||||
</Drawer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function NetlerIcerik({
|
|
||||||
durum,
|
|
||||||
netler,
|
|
||||||
}: {
|
|
||||||
durum: Durum;
|
|
||||||
netler: ProgramNetSatiri[];
|
|
||||||
}) {
|
|
||||||
if (durum === "yukleniyor" || durum === "bekliyor") {
|
|
||||||
return (
|
|
||||||
<div className="space-y-2" aria-hidden>
|
|
||||||
{[0, 1, 2, 3, 4].map((i) => (
|
|
||||||
<div key={i} className="h-10 animate-pulse rounded-lg bg-slate-100" />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (durum === "hata") {
|
|
||||||
return (
|
|
||||||
<p className="py-4 text-center text-base text-slate-500">
|
|
||||||
Netler yüklenemedi. Paneli kapatıp yeniden açmayı dene.
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (netler.length === 0) {
|
|
||||||
return (
|
|
||||||
<p className="py-4 text-center text-base text-slate-500">
|
|
||||||
Bu program için YÖK Atlas'ta net verisi yayınlanmamış.
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dersler = DERSLER.filter((d) =>
|
|
||||||
netler.some((y) => y[d.alan] != null),
|
|
||||||
);
|
|
||||||
// En yeni yıl vurgulu (§1.1 "sık bakılan önde"); eski yıllar bağlam.
|
|
||||||
const sonYil = Math.max(...netler.map((y) => y.yil));
|
|
||||||
const hucre = (yil: number, vurgu = false) =>
|
|
||||||
cn(
|
|
||||||
"py-2.5 text-right text-sm tabular-nums",
|
|
||||||
yil === sonYil
|
|
||||||
? vurgu
|
|
||||||
? "font-semibold text-slate-900"
|
|
||||||
: "font-semibold text-slate-800"
|
|
||||||
: "text-slate-500",
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Table>
|
|
||||||
<TableHeader>
|
|
||||||
<TableRow>
|
|
||||||
<TableHead className={cn(SATIR_BASLIK, "pl-0")}>Ders</TableHead>
|
|
||||||
{netler.map((y) => (
|
|
||||||
<TableHead
|
|
||||||
key={y.yil}
|
|
||||||
className={cn(
|
|
||||||
SATIR_BASLIK,
|
|
||||||
"text-right tabular-nums",
|
|
||||||
y.yil === sonYil && "text-slate-900",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{y.yil}
|
|
||||||
</TableHead>
|
|
||||||
))}
|
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{dersler.map((d) => (
|
|
||||||
<TableRow key={d.alan}>
|
|
||||||
<TableCell className="py-2.5 pl-0 text-sm text-slate-700">
|
|
||||||
{d.etiket}
|
|
||||||
<span className="text-slate-400"> / {d.max}</span>
|
|
||||||
</TableCell>
|
|
||||||
{netler.map((y) => {
|
|
||||||
const deger = y[d.alan];
|
|
||||||
return (
|
|
||||||
<TableCell key={y.yil} className={hucre(y.yil)}>
|
|
||||||
{deger != null ? net(deger) : "—"}
|
|
||||||
</TableCell>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
<TableRow>
|
|
||||||
<TableCell className="py-2.5 pl-0 text-sm text-slate-500">OBP</TableCell>
|
|
||||||
{netler.map((y) => (
|
|
||||||
<TableCell
|
|
||||||
key={y.yil}
|
|
||||||
className="py-2.5 text-right text-sm tabular-nums text-slate-500"
|
|
||||||
>
|
|
||||||
{y.obp != null ? net(y.obp) : "—"}
|
|
||||||
</TableCell>
|
|
||||||
))}
|
|
||||||
</TableRow>
|
|
||||||
<TableRow className="border-t border-slate-200">
|
|
||||||
<TableCell className="py-3 pl-0 text-sm font-semibold text-slate-900">
|
|
||||||
Yerleşme puanı
|
|
||||||
</TableCell>
|
|
||||||
{netler.map((y) => (
|
|
||||||
<TableCell key={y.yil} className={hucre(y.yil, true)}>
|
|
||||||
{y.tabanPuan != null ? net(y.tabanPuan) : "—"}
|
|
||||||
</TableCell>
|
|
||||||
))}
|
|
||||||
</TableRow>
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user