Files
menulio/apps/web/src/app/api/qr-templates/route.ts
T

143 lines
4.2 KiB
TypeScript

import { NextResponse } from "next/server";
import fs from "fs/promises";
import path from "path";
import { supabase } from "@/lib/supabase";
const DATA_FILE = path.join(process.cwd(), "src/data/qr-templates.json");
function mapFromDb(row: any) {
return {
key: row.key,
name: row.name,
categoryName: row.category_name,
aspectRatio: row.aspect_ratio || "1/1",
bgType: row.bg_type || "gradient",
bgImageUrl: row.bg_image_url || undefined,
bgGradient: row.bg_gradient || undefined,
plaqueColor: row.plaque_color || undefined,
borderAccent: row.border_accent || undefined,
accentText: row.accent_text || undefined,
headerText: row.header_text || undefined,
subText: row.sub_text || undefined,
dividerColor: row.divider_color || undefined,
qrConfig: row.qr_config,
layers: row.layers,
isActive: row.is_active ?? true,
createdAt: row.created_at,
updatedAt: row.updated_at,
};
}
function mapToDb(item: any) {
return {
key: item.key,
name: item.name,
category_name: item.categoryName || null,
aspect_ratio: item.aspectRatio || "1/1",
bg_type: item.bgType || "gradient",
bg_image_url: item.bgImageUrl || null,
bg_gradient: item.bgGradient || null,
plaque_color: item.plaqueColor || null,
border_accent: item.borderAccent || null,
accent_text: item.accentText || null,
header_text: item.headerText || null,
sub_text: item.subText || null,
divider_color: item.dividerColor || null,
qr_config: item.qrConfig || item.defaultQrConfig || null,
layers: item.layers || item.defaultLayers || null,
is_active: item.isActive !== undefined ? item.isActive : true,
updated_at: new Date().toISOString(),
};
}
async function readFromDisk(): Promise<any[]> {
try {
const raw = await fs.readFile(DATA_FILE, "utf-8");
return JSON.parse(raw);
} catch {
return [];
}
}
async function writeToDisk(list: any[]): Promise<void> {
try {
await fs.writeFile(DATA_FILE, JSON.stringify(list, null, 2), "utf-8");
} catch {}
}
export async function GET() {
try {
const { data, error } = await supabase
.from("qr_stand_templates")
.select("*")
.order("created_at", { ascending: false });
if (!error && data && data.length > 0) {
const mapped = data.map(mapFromDb);
await writeToDisk(mapped);
return NextResponse.json({ templates: mapped, source: "supabase_db" });
}
} catch {}
const diskTemplates = await readFromDisk();
return NextResponse.json({ templates: diskTemplates, source: "disk_cache" });
}
export async function POST(req: Request) {
try {
const body = await req.json();
if (!body || !body.key) {
return NextResponse.json({ error: "Şablon key zorunludur" }, { status: 400 });
}
// 1. Supabase'e Upsert et
try {
const dbRow = mapToDb(body);
await supabase.from("qr_stand_templates").upsert(dbRow, { onConflict: "key" });
} catch (dbErr) {
console.warn("Supabase upsert warning:", dbErr);
}
// 2. Diske de yaz (offline / backup)
const diskList = await readFromDisk();
const existingIdx = diskList.findIndex((t: any) => t.key === body.key);
if (existingIdx >= 0) {
diskList[existingIdx] = { ...diskList[existingIdx], ...body };
} else {
diskList.unshift(body);
}
await writeToDisk(diskList);
return NextResponse.json({ success: true, template: body });
} catch (err: any) {
return NextResponse.json({ error: err.message }, { status: 500 });
}
}
export async function DELETE(req: Request) {
try {
const { searchParams } = new URL(req.url);
const key = searchParams.get("key");
if (!key) {
return NextResponse.json({ error: "Şablon key zorunludur" }, { status: 400 });
}
// 1. Supabase'den Sil
try {
await supabase.from("qr_stand_templates").delete().eq("key", key);
} catch (dbErr) {
console.warn("Supabase delete warning:", dbErr);
}
// 2. Diskten de Sil
const diskList = await readFromDisk();
const filtered = diskList.filter((t: any) => t.key !== key);
await writeToDisk(filtered);
return NextResponse.json({ success: true, deletedKey: key });
} catch (err: any) {
return NextResponse.json({ error: err.message }, { status: 500 });
}
}