Files
ai-ticket-platform/frontend/src/components/app/AppCreateDialog.tsx
2026-07-16 17:20:45 +08:00

80 lines
2.7 KiB
TypeScript

import type * as React from 'react'
import { CircleAlert, LoaderCircle, Plus } from 'lucide-react'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle
} from '@/components/ui/dialog'
import { cn } from '@/lib/utils'
type AppCreateDialogProps = {
open: boolean
onOpenChange: (open: boolean) => void
title: string
description: string
submitLabel: string
onSubmit: React.FormEventHandler<HTMLFormElement>
children: React.ReactNode
pending?: boolean
submitDisabled?: boolean
error?: string
className?: string
bodyClassName?: string
}
export function AppCreateDialog({
open,
onOpenChange,
title,
description,
submitLabel,
onSubmit,
children,
pending = false,
submitDisabled = false,
error,
className,
bodyClassName
}: AppCreateDialogProps) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className={cn('overflow-hidden p-0 sm:max-w-lg', className)}>
<DialogHeader className="border-b border-border/70 bg-gradient-to-r from-primary/[0.08] via-card to-secondary/55 px-6 py-5 pr-12">
<div className="mb-1 flex size-10 items-center justify-center rounded-2xl bg-primary/10 text-primary shadow-sm ring-1 ring-primary/10">
<Plus className="size-5" aria-hidden="true" />
</div>
<DialogTitle className="text-lg">{title}</DialogTitle>
<DialogDescription className="leading-relaxed">{description}</DialogDescription>
</DialogHeader>
<form onSubmit={onSubmit}>
<div className={cn('scrollbar-panel max-h-[65vh] overflow-y-auto px-6 py-5', bodyClassName)}>
{children}
{error ? (
<Alert variant="destructive" className="mt-4">
<CircleAlert />
<AlertTitle>创建未完成</AlertTitle>
<AlertDescription>{error}</AlertDescription>
</Alert>
) : null}
</div>
<DialogFooter className="m-0 rounded-none border-t border-border/70 bg-muted/35 px-6 py-4">
<Button type="button" variant="outline" onClick={() => onOpenChange(false)} disabled={pending}>
取消
</Button>
<Button type="submit" disabled={pending || submitDisabled}>
{pending ? <LoaderCircle data-icon="inline-start" className="animate-spin" /> : <Plus data-icon="inline-start" />}
{pending ? '正在创建…' : submitLabel}
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
)
}