Files
kolaytercih/src/lib/dev/actions.ts
bilalgursen 7288c926d0 UX/CRO denetimi uygulandı: değer-önce funnel, güven sayfaları, dev paneli
Kritik (K1-K6) sonrası kalan tüm maddeler:
- Değer önce: girişsiz kullanıcı sihirbaz bitince /giris yerine /sonuc'taki
  ücretsiz tabloya gider (?hazir=1); AI CTA'sı "5 deneme kredinle listeni
  kur — giriş yap" paneli + sabit alt karttan verilir, girişte otomatik üretim
- Ö1-Ö10: paywall kopyası, aranabilir il seçimi, "Seçtiklerim" adlandırması,
  gizlilik/koşullar/iletişim sayfaları, danışman özeti + uyarılar, revizyon
  kutusu, dilim özeti + tek şehir uyarısı, eksik veri rozetleri, magic link
  yeniden gönder, mobil sohbet kısayolu
- G1-G5: binlik ayraçlı input + inline hata, adım göstergesi, route-level
  loading/error/not-found, dürüst konumlandırma kartı, dürüst buton etiketleri
- Seçtiklerim butonu liste boşken gizli; ilk eklemede belirir
- Dev süperadmin paneli (yalnızca development): hızlı giriş, kredi/paket/rapor
  senaryoları, sahte ödeme dönüşü

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 15:10:57 +03:00

128 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use server";
// Dev süperadmin aksiyonları: yalnızca geliştirme ortamında çalışır.
// Panelden (src/components/dev/dev-panel.tsx) çağrılır; kullanıcı durumunu
// (kredi, paket, rapor) kurcalayıp tüm sayfaları gerçek akışta gezmeyi sağlar.
import { eq } from "drizzle-orm";
import { headers } from "next/headers";
import { appDb, schema } from "@/lib/appdb";
import { auth } from "@/lib/auth";
import { getCurrentUser } from "@/lib/session";
import { URUNLER } from "@/lib/credits";
function devKontrol() {
if (process.env.NODE_ENV === "production") {
throw new Error("Dev paneli yalnızca geliştirme ortamında çalışır.");
}
}
export type DevDurum =
| { girisli: false }
| {
girisli: true;
email: string;
kredi: number;
hasPaket: boolean;
raporVar: boolean;
sira: number | null;
tur: string | null;
};
export async function devDurum(): Promise<DevDurum> {
devKontrol();
const user = await getCurrentUser();
if (!user) return { girisli: false };
const rapor = await appDb.query.reports.findFirst({
where: eq(schema.reports.userId, user.id),
columns: { params: true },
});
const params = rapor?.params as { sira?: number; tur?: string } | undefined;
return {
girisli: true,
email: user.email,
kredi: user.creditBalance,
hasPaket: user.hasPaket,
raporVar: Boolean(rapor),
sira: params?.sira ?? null,
tur: params?.tur ?? null,
};
}
/** Magic link üretir ve (dev'de auth.ts'in yakaladığı) URL'i döner —
* panel bu URL'e giderek anında oturum açar; yeni e-posta = yeni kullanıcı. */
export async function devAnindaGiris(
email: string,
): Promise<{ ok: true; url: string } | { ok: false; error: string }> {
devKontrol();
const temiz = email.trim().toLowerCase();
if (!/^\S+@\S+\.\S+$/.test(temiz)) {
return { ok: false, error: "Geçerli bir e-posta gir." };
}
const g = globalThis as { __sonMagicLink?: string };
g.__sonMagicLink = undefined;
await auth.api.signInMagicLink({
body: { email: temiz, callbackURL: "/" },
headers: await headers(),
});
if (!g.__sonMagicLink) {
return { ok: false, error: "Magic link üretilemedi (auth.ts yakalayamadı)." };
}
return { ok: true, url: g.__sonMagicLink };
}
export async function devAyarla(ayar: {
kredi?: number;
hasPaket?: boolean;
}): Promise<{ ok: boolean; error?: string }> {
devKontrol();
const user = await getCurrentUser();
if (!user) return { ok: false, error: "Önce giriş yap." };
await appDb
.update(schema.user)
.set({
...(typeof ayar.kredi === "number"
? { creditBalance: Math.max(0, Math.round(ayar.kredi)) }
: {}),
...(typeof ayar.hasPaket === "boolean"
? { hasPaket: ayar.hasPaket }
: {}),
})
.where(eq(schema.user.id, user.id));
return { ok: true };
}
/** Raporu ve sohbet geçmişini siler — boş durumları test etmek için. */
export async function devRaporSil(): Promise<{ ok: boolean; error?: string }> {
devKontrol();
const user = await getCurrentUser();
if (!user) return { ok: false, error: "Önce giriş yap." };
await appDb
.delete(schema.reports)
.where(eq(schema.reports.userId, user.id));
await appDb
.delete(schema.chatMessages)
.where(eq(schema.chatMessages.userId, user.id));
return { ok: true };
}
/** Ödenmiş sahte sipariş oluşturur — /odeme/sonuc başarı ekranı için. */
export async function devSahteOdeme(): Promise<
{ ok: true; siparis: string } | { ok: false; error: string }
> {
devKontrol();
const user = await getCurrentUser();
if (!user) return { ok: false, error: "Önce giriş yap." };
const id = `dev-${crypto.randomUUID()}`;
await appDb.insert(schema.orders).values({
id,
userId: user.id,
product: "paket",
amountKurus: URUNLER.paket.amountKurus,
credits: URUNLER.paket.credits,
status: "paid",
createdAt: new Date(),
});
return { ok: true, siparis: id };
}