Update package.json scripts, enhance layout with new components, and improve API error handling
Some checks failed
Deploy / deploy (push) Failing after 1h28m6s
Some checks failed
Deploy / deploy (push) Failing after 1h28m6s
- Added new scripts for database operations and temporary production in package.json. - Integrated KaydetBannerLazy component into the layout for improved user notifications. - Enhanced API error handling in the soru route to mark credit exhaustion. - Updated the IletisimPage for better button styling and user experience. - Refactored ListemPage to streamline user flow and improve session handling. - Removed unused ListePaneli component to clean up the codebase.
This commit is contained in:
83
src/lib/tadimlik-havuzu.ts
Normal file
83
src/lib/tadimlik-havuzu.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
// Girişsiz yapay zekâ tadımlığının sunucu katmanı: batch üretilmiş
|
||||
// (scripts/tadimlik-uret.ts) satırlar app.db'deki tadimlik_havuzu'ndan
|
||||
// SEÇİLİR — anonim istek LLM'e asla gitmez, seçim her zaman sunucuda.
|
||||
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { appDb, schema } from "./appdb";
|
||||
import { turkishSlugify } from "./slug";
|
||||
import type { PuanTuruKey } from "./db";
|
||||
import type { Dilim } from "./rapor-havuzu";
|
||||
import type { RaporSonuc } from "./ai/rapor";
|
||||
|
||||
/** Sihirbaz kategorisi seçilmemiş kullanıcı için kova×tür başına fallback satır. */
|
||||
export const GENEL_KATEGORI = "genel";
|
||||
|
||||
/**
|
||||
* Havuz anahtarındaki sıra kovaları. Eşikler analitik.ts'teki siraKovasi()
|
||||
* ile birebir aynı tutulmalı (oradaki Türkçe etiketler DB anahtarı olamaz).
|
||||
* temsiliSira: batch üretimde "bu kovadaki tipik aday" olarak kullanılan sıra.
|
||||
*/
|
||||
export const KOVALAR = [
|
||||
{ slug: "0-10k", temsiliSira: 5_000, max: 10_000 },
|
||||
{ slug: "10-50k", temsiliSira: 30_000, max: 50_000 },
|
||||
{ slug: "50-100k", temsiliSira: 75_000, max: 100_000 },
|
||||
{ slug: "100-250k", temsiliSira: 175_000, max: 250_000 },
|
||||
{ slug: "250-500k", temsiliSira: 375_000, max: 500_000 },
|
||||
{ slug: "500k-plus", temsiliSira: 750_000, max: Number.POSITIVE_INFINITY },
|
||||
] as const;
|
||||
|
||||
export type Kova = (typeof KOVALAR)[number];
|
||||
|
||||
export function kovaBul(sira: number): Kova {
|
||||
return KOVALAR.find((k) => sira <= k.max) ?? KOVALAR[KOVALAR.length - 1];
|
||||
}
|
||||
|
||||
/** "Mühendislik & Teknoloji" → "muhendislik-teknoloji" (havuz anahtarı). */
|
||||
export function kategoriSlugBul(kategori: string): string {
|
||||
return turkishSlugify(kategori);
|
||||
}
|
||||
|
||||
export interface TadimlikSatir {
|
||||
programId: string;
|
||||
dilim: Dilim;
|
||||
gerekce: string;
|
||||
riskNotu: string;
|
||||
trendOzeti: string;
|
||||
program: RaporSonuc["programlar"][string];
|
||||
}
|
||||
|
||||
/**
|
||||
* Kova × tür × kategori anahtarıyla tadımlık satırı seçer. Kategoriye özel
|
||||
* satır yoksa "genel"e düşer; o da yoksa null — çağıran taraf bileşeni hiç
|
||||
* render etmez (boş/generic tadımlık gösterilmez, PRD kuralı).
|
||||
*/
|
||||
export async function tadimlikSec(
|
||||
sira: number,
|
||||
tur: PuanTuruKey,
|
||||
kategoriSlug?: string,
|
||||
): Promise<TadimlikSatir | null> {
|
||||
const kova = kovaBul(sira);
|
||||
const sluglar = [
|
||||
...new Set([kategoriSlug ?? GENEL_KATEGORI, GENEL_KATEGORI]),
|
||||
];
|
||||
for (const slug of sluglar) {
|
||||
const satir = await appDb.query.tadimlikHavuzu.findFirst({
|
||||
where: and(
|
||||
eq(schema.tadimlikHavuzu.kovaSlug, kova.slug),
|
||||
eq(schema.tadimlikHavuzu.tur, tur),
|
||||
eq(schema.tadimlikHavuzu.kategoriSlug, slug),
|
||||
),
|
||||
});
|
||||
if (satir) {
|
||||
return {
|
||||
programId: satir.programId,
|
||||
dilim: satir.dilim,
|
||||
gerekce: satir.gerekce,
|
||||
riskNotu: satir.riskNotu,
|
||||
trendOzeti: satir.trendOzeti,
|
||||
program: satir.program as RaporSonuc["programlar"][string],
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user