humam kerdiah 4bfd8c84a9 feat: add template checkpoint edit dialog and vendor management components
- Implemented TemplateCheckpointEditDialog for creating and editing inspection checkpoints.
- Added VendorActions component for managing vendor actions including edit, activate/deactivate, and delete.
- Created VendorContext for managing vendor state across components.
- Developed VendorGeneralInfo component to display detailed vendor information.
- Introduced AedSymbol and Money components for consistent currency representation.
- Added PromptDialog for user input prompts throughout the application.
- Implemented RelationLink component for unified related-data display in CRUD tables.
- Created InspectionTemplatesClient for API interactions related to inspection templates.
2026-05-18 12:08:42 +04:00

79 lines
2.3 KiB
TypeScript

"use client"
import Link from "next/link"
import type { ComponentType, MouseEvent, ReactNode } from "react"
import { Button, buttonVariants } from "@/shared/components/ui/button"
import { cn } from "@/shared/lib/utils"
type IconComponent = ComponentType<{ className?: string }>
export type RelationLinkProps = {
/** Destination href. When falsy the chip renders as a non-interactive button-styled span. */
href?: string | null
/** Primary label rendered inside the button. */
label?: ReactNode
/** Optional icon shown before the label. */
icon?: IconComponent
/** Rendered when label is empty (with or without href). Defaults to "—". */
fallback?: ReactNode
/** Optional secondary text rendered after the label (e.g. phone, plate). */
meta?: ReactNode
className?: string
}
/**
* Unified cell for related-data columns across every CRUD table.
* Renders an outlined button-style chip either way:
* - With href: clickable next/link wrapped by a Button (asChild).
* - Without href: same outline styling on a plain span so visual columns
* stay consistent across resources that don't have detail routes.
*/
export function RelationLink({
href,
label,
icon: Icon,
fallback = "—",
meta,
className,
}: RelationLinkProps) {
const hasLabel = label != null && label !== ""
if (!hasLabel && !href) {
return <span className="text-muted-foreground">{fallback}</span>
}
const body = (
<>
{Icon ? <Icon /> : null}
<span>{hasLabel ? label : fallback}</span>
{meta ? <span className="ms-1 text-muted-foreground">· {meta}</span> : null}
</>
)
if (!href) {
return (
<span
className={cn(
buttonVariants({ variant: "outline", size: "sm" }),
"cursor-default pointer-events-none",
className,
)}
>
{body}
</span>
)
}
return (
<Button
variant="outline"
size="sm"
asChild
className={className}
onClick={(event: MouseEvent<HTMLButtonElement>) => event.stopPropagation()}
>
<Link href={href}>{body}</Link>
</Button>
)
}