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>
55 lines
2.0 KiB
TypeScript
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()
|
|
},
|
|
}
|