Files
resolutionflow/frontend/src/api/publicTemplates.ts
chihlasm 2b657fc4ac feat(gallery): add public templates gallery frontend (Tasks 4 & 5)
Add types, API client, page component, card components, detail modal,
and /templates route for the public templates gallery. Uses raw fetch()
for unauthenticated access, glass-card design system, and URL-synced
filters with debounced search.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:18:58 +00:00

55 lines
2.0 KiB
TypeScript

import type {
PublicGalleryResponse,
PublicFlowDetail,
PublicScriptDetail,
GalleryCategory,
} from '@/types/public-templates'
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'
export const publicTemplatesApi = {
async listGallery(params?: {
category?: string
type?: string
sort?: string
page?: number
per_page?: number
}): Promise<PublicGalleryResponse> {
const searchParams = new URLSearchParams()
if (params?.category) searchParams.set('category', params.category)
if (params?.type) searchParams.set('type', params.type)
if (params?.sort) searchParams.set('sort', params.sort)
if (params?.page) searchParams.set('page', String(params.page))
if (params?.per_page) searchParams.set('per_page', String(params.per_page))
const qs = searchParams.toString()
const response = await fetch(`${API_URL}/api/v1/public/templates${qs ? `?${qs}` : ''}`)
if (!response.ok) throw new Error('Failed to load gallery')
return response.json()
},
async getFlowDetail(id: string): Promise<PublicFlowDetail> {
const response = await fetch(`${API_URL}/api/v1/public/templates/flows/${id}`)
if (!response.ok) throw new Error('Failed to load flow detail')
return response.json()
},
async getScriptDetail(id: string): Promise<PublicScriptDetail> {
const response = await fetch(`${API_URL}/api/v1/public/templates/scripts/${id}`)
if (!response.ok) throw new Error('Failed to load script detail')
return response.json()
},
async listCategories(): Promise<GalleryCategory[]> {
const response = await fetch(`${API_URL}/api/v1/public/templates/categories`)
if (!response.ok) throw new Error('Failed to load categories')
return response.json()
},
async search(q: string): Promise<PublicGalleryResponse> {
const searchParams = new URLSearchParams({ q })
const response = await fetch(`${API_URL}/api/v1/public/templates/search?${searchParams}`)
if (!response.ok) throw new Error('Search failed')
return response.json()
},
}