Add medication Items catalogue, counter POS/QR purchase, profile/login, detail pages, loyalty ledger, Cmd+K nav, KPI strips/charts, avatars, and i18n; document the new APIs and open questions for the shared backend team. Co-authored-by: Cursor <cursoragent@cursor.com>
60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
import type { ReactNode } from 'react'
|
|
import { Link } from 'react-router-dom'
|
|
import { ArrowLeft } from 'lucide-react'
|
|
import { Button } from '@/components/ui/button'
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
/**
|
|
* Shared field grid for create forms. Pages own the <form> element (its id is
|
|
* referenced by the footer submit buttons), so the grid lives here as a class
|
|
* string instead of a wrapper to avoid nesting a grid inside a grid.
|
|
*/
|
|
export const createFormGrid = 'grid gap-5 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4'
|
|
/** Field that reads better at double width (names, addresses). */
|
|
export const createFieldWide = 'md:col-span-2'
|
|
/** Field that should span every column (textareas, checkbox rows). */
|
|
export const createFieldFull = 'md:col-span-2 xl:col-span-3 2xl:col-span-4'
|
|
|
|
export function CreatePageLayout({
|
|
title,
|
|
subtitle,
|
|
backTo,
|
|
backLabel = 'Back to list',
|
|
children,
|
|
footer,
|
|
className,
|
|
}: {
|
|
title: string
|
|
subtitle?: string
|
|
backTo: string
|
|
backLabel?: string
|
|
children: ReactNode
|
|
footer?: ReactNode
|
|
className?: string
|
|
}) {
|
|
return (
|
|
<div className={cn('w-full min-w-0 space-y-5', className)}>
|
|
<div>
|
|
<Button asChild variant="ghost" size="sm" className="-ml-2 mb-3 text-muted-foreground">
|
|
<Link to={backTo}>
|
|
<ArrowLeft className="h-4 w-4" />
|
|
{backLabel}
|
|
</Link>
|
|
</Button>
|
|
<div className="mb-2 h-1 w-12 rounded-full bg-gradient-to-r from-brand-500 to-orange" />
|
|
<h1 className="font-display text-2xl font-bold tracking-tight text-forest">{title}</h1>
|
|
{subtitle ? <p className="mt-1 text-sm text-muted-foreground">{subtitle}</p> : null}
|
|
</div>
|
|
<Card>
|
|
<CardHeader className="pb-2">
|
|
<CardTitle className="text-base">Details</CardTitle>
|
|
{subtitle ? <CardDescription className="sr-only">{subtitle}</CardDescription> : null}
|
|
</CardHeader>
|
|
<CardContent className="space-y-5">{children}</CardContent>
|
|
</Card>
|
|
{footer ? <div className="flex flex-wrap justify-end gap-2">{footer}</div> : null}
|
|
</div>
|
|
)
|
|
}
|