ppt-tool/frontend/app/api/templates/route.ts
Vadym Samoilenko cf21ba4516 Phase 1-2: Foundation + Admin Panel & Client Management
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>
2026-02-26 15:37:17 +00:00

77 lines
No EOL
3.3 KiB
TypeScript

import { NextResponse } from 'next/server'
import { promises as fs } from 'fs'
import path from 'path'
import { TemplateSetting } from '@/app/(presentation-generator)/template-preview/types'
export async function GET() {
try {
// Get the path to the presentation-templates directory
const templatesDirectory = path.join(process.cwd(), 'presentation-templates')
// Read all directories in the presentation-templates directory
const items = await fs.readdir(templatesDirectory, { withFileTypes: true })
// Filter for directories (layout templates) and exclude files
const templateDirectories = items
.filter(item => item.isDirectory())
.map(dir => dir.name)
const allLayouts: {templateName: string, templateID: string; files: string[]; settings: TemplateSetting | null }[] = []
// Scan each template directory for layout files and settings
for (const templateName of templateDirectories) {
try {
const templatePath = path.join(templatesDirectory, templateName)
const templateFiles = await fs.readdir(templatePath)
// Filter for .tsx files and exclude any non-layout files
const layoutFiles = templateFiles.filter(file =>
file.endsWith('.tsx') &&
!file.startsWith('.') &&
!file.includes('.test.') &&
!file.includes('.spec.') &&
file !== 'settings.json'
)
// Read settings.json if it exists
let settings: TemplateSetting | null = null
const settingsPath = path.join(templatePath, 'settings.json')
try {
const settingsContent = await fs.readFile(settingsPath, 'utf-8')
settings = JSON.parse(settingsContent) as TemplateSetting
} catch (settingsError) {
console.warn(`No settings.json found for template ${templateName} or invalid JSON`)
// Provide default settings if settings.json is missing or invalid
settings = {
description: `${templateName} presentation layouts`,
ordered: false,
default: false
}
}
if (layoutFiles.length > 0) {
allLayouts.push({
templateName: templateName,
templateID: templateName,
files: layoutFiles,
settings: settings
})
}
} catch (error) {
console.error(`Error reading template directory ${templateName}:`, error)
// Continue with other templates even if one fails
}
}
return NextResponse.json(allLayouts)
} catch (error) {
console.error('Error reading presentation-templates directory:', error)
return NextResponse.json(
{ error: 'Failed to read presentation-templates directory' },
{ status: 500 }
)
}
}