production: docker + nginx config for rf-flux.com
Deploy to VPS / deploy (push) Has been cancelled

This commit is contained in:
2026-03-20 13:46:05 -05:00
parent b275b19f08
commit fc24313f15
187 changed files with 20977 additions and 767 deletions
@@ -0,0 +1,163 @@
//src/app/hq-command/dashboard/applications/actions.ts
"use server";
import { prisma } from "@/lib/prisma";
import { revalidatePath } from "next/cache";
import { unstable_noStore as noStore } from "next/cache"; // 🔥 ANTI-CACHÉ
// 🔥 IMPORTAMOS EL TRADUCTOR DE IA
import { translateContentForCMS } from "@/lib/aiTranslator";
const generateSlug = (title: string) => {
return title.toLowerCase().trim().replace(/[^\w\s-]/g, '').replace(/[\s_-]+/g, '-').replace(/^-+|-+$/g, '');
};
// 1. OBTENER LA LISTA DE APLICACIONES
export async function getApplications() {
noStore();
try {
const apps = await prisma.application.findMany({
orderBy: { createdAt: "asc" }
});
return { success: true, apps };
} catch (error) {
return { error: "Failed to fetch applications." };
}
}
// 2. OBTENER UNA APLICACIÓN ESPECÍFICA
export async function getApplicationBySlug(slug: string) {
try {
const app = await prisma.application.findUnique({
where: { slug }
});
if (!app) return { error: "Application not found." };
return { success: true, app };
} catch (error) {
return { error: "Failed to fetch application details." };
}
}
// 3. CREAR NUEVA APLICACIÓN (¡Ahora con IA!)
export async function createApplication(formData: FormData) {
try {
const title = formData.get("title") as string;
const subtitle = formData.get("subtitle") as string;
const category = formData.get("category") as string;
// Capturamos el switch de IA
const autoTranslate = formData.get("autoTranslate") === "on";
const shortDescription = "New application ready to be configured.";
const slug = generateSlug(title);
let translationsJson = "{}";
// 🔥 LA MAGIA DE LA IA EN LA CREACIÓN 🔥
if (autoTranslate) {
const aiResult = await translateContentForCMS({
title, subtitle, category, shortDescription
});
if (aiResult) translationsJson = JSON.stringify(aiResult);
}
await prisma.application.create({
data: {
slug, title, subtitle, category,
shortDescription,
heroDescription: "", sectionsJson: "[]", advantagesJson: "[]", datasheetJson: "{}", dashboardMetricsJson: "[]",
isActive: true,
translationsJson
}
});
revalidatePath("/hq-command/dashboard/applications");
revalidatePath("/[locale]", "layout");
return { success: true };
} catch (error) {
return { error: "Failed to create application. Title might already exist." };
}
}
// 4. ACTUALIZAR TODA LA INFORMACIÓN (¡Traduciendo JSONs completos!)
export async function updateApplicationData(formData: FormData) {
try {
const slug = formData.get("slug") as string;
const title = formData.get("title") as string;
const subtitle = formData.get("subtitle") as string;
const category = formData.get("category") as string;
const shortDescription = formData.get("shortDescription") as string;
const heroDescription = formData.get("heroDescription") as string;
const sectionsJson = formData.get("sectionsJson") as string;
const advantagesJson = formData.get("advantagesJson") as string;
const datasheetJson = formData.get("datasheetJson") as string || "{}";
const dashboardMetricsJson = formData.get("dashboardMetricsJson") as string || "[]";
const autoTranslate = formData.get("autoTranslate") === "on";
let updateData: any = {
title, subtitle, category, shortDescription, heroDescription,
sectionsJson, advantagesJson, datasheetJson, dashboardMetricsJson
};
// 🔥 LA MAGIA DE LA IA PARA EL CONTENIDO PROFUNDO 🔥
// Nota: Le mandamos los JSON stringificados. GPT-4o los traducirá y nos los devolverá con la misma estructura.
if (autoTranslate) {
const aiResult = await translateContentForCMS({
title, subtitle, category, shortDescription, heroDescription,
sectionsJson, advantagesJson, dashboardMetricsJson
});
if (aiResult) {
updateData.translationsJson = JSON.stringify(aiResult);
}
}
await prisma.application.update({
where: { slug },
data: updateData
});
revalidatePath(`/applications/${slug}`);
revalidatePath("/hq-command/dashboard/applications");
revalidatePath("/[locale]", "layout");
return { success: true };
} catch (error) {
console.error("Update Error:", error);
return { error: "Failed to update application data." };
}
}
// 5. OCULTAR / MOSTRAR APLICACIÓN
export async function toggleApplication(slug: string, currentStatus: boolean) {
try {
await prisma.application.update({
where: { slug },
data: { isActive: !currentStatus }
});
revalidatePath("/hq-command/dashboard/applications");
revalidatePath("/[locale]", "layout");
return { success: true };
} catch (e) {
return { error: "Failed to toggle status." };
}
}
// 6. ELIMINAR APLICACIÓN
export async function deleteApplication(slug: string) {
try {
await prisma.application.delete({ where: { slug } });
revalidatePath("/hq-command/dashboard/applications");
revalidatePath("/[locale]", "layout");
return { success: true };
} catch (e) {
return { error: "Failed to delete application." };
}
}
// 7. LA SEMILLA: AUTO-POBLAR LA BASE DE DATOS (Intacto)
export async function seedInitialApplications() {
// ... Tu código actual de la semilla se queda exactamente igual ...
// (Para mantener este mensaje limpio, asume que la función de seedInitialApplications() que ya tienes va aquí)
}