import { Head, Link } from '@inertiajs/react'; import { useState } from 'react'; import Heading from '@/components/heading'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { useTranslation } from '@/hooks/use-translation'; import AppLayout from '@/layouts/app-layout'; import { type BreadcrumbItem } from '@/types'; interface Endpoint { method: string; path: string; summary: string; abilities: string[]; } type Tab = 'guide' | 'zapier' | 'endpoints'; interface Props { guide_html: string; zapier_html: string; endpoints: Endpoint[]; spec_url: string; version: string | null; } const METHOD_TONE: Record = { GET: 'text-emerald-700 dark:text-emerald-400', POST: 'text-violet-700 dark:text-violet-400', PATCH: 'text-amber-700 dark:text-amber-400', PUT: 'text-amber-700 dark:text-amber-400', DELETE: 'text-red-700 dark:text-red-400', }; export default function ApiDocs({ guide_html, zapier_html, endpoints, spec_url, version }: Props) { const { t } = useTranslation(); const [tab, setTab] = useState('guide'); const breadcrumbs: BreadcrumbItem[] = [{ title: t('API'), href: '/api/docs' }]; return (
{version && v{version}}
{/* * Three views of the same API, one at a time. The endpoint * table is generated from the committed OpenAPI document; * the other two are markdown files that ship with the * application, converted server-side with HTML input * escaped — see ApiDocsController. * * The guide and the Zapier page are separate because they * are for different readers: one is writing code against * the API, the other is filling in a form in Zapier and * will read nothing else. */}
{(['guide', 'zapier', 'endpoints'] as const).map((key) => ( ))}
{tab === 'endpoints' && (
{endpoints.map((endpoint) => ( ))}
{t('Method')} {t('Path')} {t('Description')} {t('Permissions')}
{endpoint.method} {endpoint.path} {endpoint.summary} {endpoint.abilities.join(', ') || '—'}
)} {tab !== 'endpoints' && (
)}
); }