fix: update callback handling and user profile management in list components
All checks were successful
Deploy / deploy (push) Successful in 7m23s

Enhanced the handling of user profiles and callback URLs in various components. Updated the `GirisKarti` to support multiple callback scenarios, ensuring seamless user experience. Improved the `ListeUretici` and `ListemIcerik` components to manage profile data more effectively, including handling cases where the profile is stored in cookies. Additionally, refined the logic for redirecting users based on their profile status, ensuring they are directed to the appropriate pages without losing context. Updated the database file to reflect these changes.
This commit is contained in:
bilalgursen
2026-08-09 04:15:53 +03:00
parent 696dc69763
commit 437e2bc96a
13 changed files with 603 additions and 70 deletions

View File

@@ -0,0 +1,134 @@
// Kayıtlı listenin üretildiği tercihler (rapor params) ile kullanıcının şu
// anki tercih profilini karşılaştırır. /listem'deki "tercihlerin değişti"
// uyarısı ve güncelleme CTA'sı bu farktan doğar.
//
// İzomorfik: yalnızca tip ve etiket sabitlerine bağlı — hem client bileşeni
// hem sunucu tarafı tüketebilir.
//
// Eski akışla üretilmiş raporlarda sihirbaz alanları (kategoriler/iller/
// universiteTipi/oncelikler) hiç yok. Olmayan alan "değişmiş" sayılmaz:
// kıyaslanacak bir değer yokken kullanıcıyı 3 kredilik güncellemeye
// çağırmak dürüst olmaz. Sıralama ve puan türü her raporda dolu olduğundan
// onlar her zaman kıyaslanır.
import {
PUAN_TURU_ETIKET,
UNIVERSITE_TIPI_ETIKET,
type TercihProfili,
} from "@/features/sihirbaz/sihirbaz-sabitler";
import type { RaporParams } from "./types/rapor";
export type FarkAlani =
| "sira"
| "tur"
| "kategoriler"
| "iller"
| "universiteTipi"
| "oncelikler";
export const FARK_ETIKET: Record<FarkAlani, string> = {
sira: "başarı sıralaman",
tur: "puan türün",
kategoriler: "ilgi alanların",
iller: "şehir tercihlerin",
universiteTipi: "devlet/vakıf tercihin",
oncelikler: "önceliklerin",
};
/** Sıra/tür/seçim üçlüsünün kararlı imzası — uyarının "bu değişikliği
* gizle" kaydı bu imzaya bağlanır (tercih yine değişirse uyarı geri gelir). */
export function profilImzasi(profil: TercihProfili): string {
const s = profil.secimler;
return JSON.stringify([
Math.round(profil.sira),
profil.tur,
[...s.kategoriler].sort(),
[...s.iller].sort(),
s.universiteTipi,
[...s.oncelikler].sort(),
]);
}
// Sıra bağımsız küme kıyası: sihirbaz seçimleri tekrarsız olarak doğrulanır
// (bkz. sihirbazDogrula), aynı seçimlerin farklı sırayla kaydedilmesi
// "değişiklik" değildir.
function kumeFarkli(
eski: readonly string[] | undefined,
yeni: readonly string[],
): boolean {
if (!eski) return false;
if (eski.length !== yeni.length) return true;
const kume = new Set(eski);
return yeni.some((x) => !kume.has(x));
}
function liste(degerler: readonly string[] | undefined): string {
return degerler && degerler.length > 0 ? degerler.join(", ") : "—";
}
export function tercihFarki(
params: RaporParams,
profil: TercihProfili,
): FarkAlani[] {
const farklar: FarkAlani[] = [];
const s = profil.secimler;
if (Math.round(params.sira) !== Math.round(profil.sira)) farklar.push("sira");
if (params.tur !== profil.tur) farklar.push("tur");
if (kumeFarkli(params.kategoriler, s.kategoriler)) farklar.push("kategoriler");
if (kumeFarkli(params.iller, s.iller)) farklar.push("iller");
if (
params.universiteTipi !== undefined &&
params.universiteTipi !== s.universiteTipi
) {
farklar.push("universiteTipi");
}
if (kumeFarkli(params.oncelikler, s.oncelikler)) farklar.push("oncelikler");
return farklar;
}
/** "başarı sıralaman ve ilgi alanların" — uyarı cümlesinin ortası. */
export function farkCumlesi(farklar: FarkAlani[]): string {
const etiketler = farklar.map((f) => FARK_ETIKET[f]);
if (etiketler.length <= 1) return etiketler[0] ?? "";
return `${etiketler.slice(0, -1).join(", ")} ve ${etiketler[etiketler.length - 1]}`;
}
export type FarkSatiri = { alan: FarkAlani; etiket: string; eski: string; yeni: string };
/** Değişen her alanın eski → yeni değeri; uyarıda tek tek gösterilir. */
export function farkSatirlari(
params: RaporParams,
profil: TercihProfili,
farklar: FarkAlani[],
): FarkSatiri[] {
const s = profil.secimler;
const sayi = (n: number) => Math.round(n).toLocaleString("tr-TR");
return farklar.map((alan) => {
const ortak = { alan, etiket: FARK_ETIKET[alan] };
switch (alan) {
case "sira":
return { ...ortak, eski: `${sayi(params.sira)}.`, yeni: `${sayi(profil.sira)}.` };
case "tur":
return {
...ortak,
eski: PUAN_TURU_ETIKET[params.tur] ?? params.tur,
yeni: PUAN_TURU_ETIKET[profil.tur] ?? profil.tur,
};
case "kategoriler":
return { ...ortak, eski: liste(params.kategoriler), yeni: liste(s.kategoriler) };
case "iller":
return { ...ortak, eski: liste(params.iller), yeni: liste(s.iller) };
case "universiteTipi":
return {
...ortak,
eski: UNIVERSITE_TIPI_ETIKET[params.universiteTipi ?? "farketmez"],
yeni: UNIVERSITE_TIPI_ETIKET[s.universiteTipi],
};
case "oncelikler":
return { ...ortak, eski: liste(params.oncelikler), yeni: liste(s.oncelikler) };
}
});
}