Phase 1 (Foundation): - Project restructure (presenton-main → backend/ + frontend/) - Database schema (8 new models, Alembic config, seed script) - Auth (Azure AD SSO + dev bypass, JWT sessions, AuthMiddleware) - RBAC (access_service, rbac_middleware, admin routers) - Audit logging (fire-and-forget, AuditMiddleware, admin router) - i18n (react-i18next with 5 namespace files) Phase 2 (Admin Panel & Client Management): - Admin panel shell (sidebar layout, role guard, 12 pages) - Redux admin slice with 18 async thunks - User management (role changes, deactivation) - Client management (CRUD, brand config, team management) - Brand config editor (colors, fonts, logos, voice rules) - Master deck upload & parser (PPTX → HTML → React pipeline) - Audit log viewer with filters and CSV/JSON export Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
91 lines
2.5 KiB
TypeScript
91 lines
2.5 KiB
TypeScript
"use client";
|
|
import React, { useEffect, useState } from "react";
|
|
import { useSearchParams } from "next/navigation";
|
|
import { validate as uuidValidate } from 'uuid';
|
|
import { getCustomTemplateDetails } from "../hooks/useCustomTemplates";
|
|
import { getSchemaByTemplateId, getSettingsByTemplateId } from "../presentation-templates";
|
|
const page = () => {
|
|
const searchParams = useSearchParams();
|
|
const templateID = searchParams.get("group");
|
|
if (!templateID) {
|
|
return <div>No templateID provided</div>;
|
|
}
|
|
const [loading, setLoading] = useState(true);
|
|
const [layout, setLayout] = useState<any[]>([]);
|
|
const [settings, setSettings] = useState<any>({
|
|
description: "",
|
|
ordered: false,
|
|
default: false,
|
|
});
|
|
const isCustomTemplate = templateID.startsWith("custom-") || uuidValidate(templateID);
|
|
|
|
useEffect(() => {
|
|
const fetchLayoutsAndSettings = async () => {
|
|
if (isCustomTemplate) {
|
|
const customTemplateDetails = await getCustomTemplateDetails(
|
|
isCustomTemplate ? templateID.startsWith("custom-") ? templateID.split("custom-")[1] : templateID : "",
|
|
isCustomTemplate ? templateID : "",
|
|
"",
|
|
);
|
|
|
|
if (customTemplateDetails) {
|
|
|
|
setLayout(customTemplateDetails.layouts.map(layout => {
|
|
return {
|
|
id: `custom-${customTemplateDetails.id}:${layout.layoutId}`,
|
|
name: layout.layoutName,
|
|
description: layout.layoutDescription,
|
|
json_schema: layout.schemaJSON,
|
|
}
|
|
}));
|
|
setSettings({
|
|
...customTemplateDetails.template,
|
|
ordered: false,
|
|
default: false,
|
|
});
|
|
}
|
|
} else {
|
|
const layoutsData = getSchemaByTemplateId(templateID || "");
|
|
const settingsData = getSettingsByTemplateId(templateID || "");
|
|
setLayout(layoutsData);
|
|
setSettings(settingsData || {
|
|
description: "",
|
|
ordered: false,
|
|
default: true,
|
|
});
|
|
|
|
}
|
|
setLoading(false);
|
|
|
|
};
|
|
fetchLayoutsAndSettings();
|
|
|
|
|
|
}, [isCustomTemplate]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
<div>
|
|
{loading ? (
|
|
<div>Loading...</div>
|
|
) : (
|
|
<div>
|
|
<div data-layouts={JSON.stringify(layout)}>
|
|
<pre>{JSON.stringify(layout, null, 2)}</pre>\
|
|
</div>
|
|
<div data-settings={JSON.stringify(settings)}>
|
|
<pre>{JSON.stringify(settings, null, 2)}</pre>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default page;
|