Files
new-api/web/default/src/features/models/components/dialogs/vendor-mutate-dialog.tsx
T
CaIon 337169e0a4 revert: undo t0ng7u UI design-system refactor
Revert the following commits:
- 308e3e347 feat(web): polish themed data views and add task log details
- b2a890e75 fix: Fontsource asset resolution across workspace layouts
- 9d1ca545e refactor(web): refine data-table cards and pricing page layout
- 0918bdb49 refactor(web): consolidate design-system primitives and responsive data views
- 262ab9312 style(web): unify design system across default frontend
2026-07-11 14:51:54 +08:00

222 lines
6.3 KiB
TypeScript
Vendored

/*
Copyright (C) 2023-2026 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import { zodResolver } from '@hookform/resolvers/zod'
import { useQueryClient } from '@tanstack/react-query'
import { Loader2 } from 'lucide-react'
import { useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'
import { Dialog } from '@/components/dialog'
import { Button } from '@/components/ui/button'
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import { createVendor, updateVendor } from '../../api'
import { vendorsQueryKeys, modelsQueryKeys } from '../../lib'
import { vendorFormSchema, type Vendor } from '../../types'
type VendorMutateDialogProps = {
open: boolean
onOpenChange: (open: boolean) => void
currentVendor?: Vendor | null
}
const VENDOR_MUTATE_FORM_ID = 'vendor-mutate-form'
export function VendorMutateDialog({
open,
onOpenChange,
currentVendor,
}: VendorMutateDialogProps) {
const { t } = useTranslation()
const queryClient = useQueryClient()
const isEdit = Boolean(currentVendor?.id)
const [isSaving, setIsSaving] = useState(false)
const form = useForm({
resolver: zodResolver(vendorFormSchema),
defaultValues: {
name: '',
description: '',
icon: '',
status: 1,
},
})
// Load vendor data for editing
useEffect(() => {
if (open && isEdit && currentVendor) {
form.reset({
id: currentVendor.id,
name: currentVendor.name,
description: currentVendor.description || '',
icon: currentVendor.icon || '',
status: currentVendor.status || 1,
})
} else if (open && !isEdit) {
form.reset({
name: '',
description: '',
icon: '',
status: 1,
})
}
}, [open, isEdit, currentVendor, form])
const onSubmit = async (values: Record<string, unknown>) => {
setIsSaving(true)
try {
const response = isEdit
? await updateVendor({ ...values, id: currentVendor!.id })
: await createVendor(values)
if (response.success) {
toast.success(
isEdit ? 'Vendor updated successfully' : 'Vendor created successfully'
)
queryClient.invalidateQueries({ queryKey: vendorsQueryKeys.lists() })
queryClient.invalidateQueries({ queryKey: modelsQueryKeys.lists() })
onOpenChange(false)
} else {
toast.error(response.message || 'Operation failed')
}
} catch (error: unknown) {
toast.error((error as Error)?.message || 'Operation failed')
} finally {
setIsSaving(false)
}
}
return (
<Dialog
open={open}
onOpenChange={onOpenChange}
title={isEdit ? t('Edit Vendor') : t('Create Vendor')}
description={
isEdit
? t('Update vendor information for {{name}}', {
name: currentVendor?.name,
})
: t('Add a new vendor to the system')
}
contentHeight='auto'
bodyClassName='space-y-4'
footer={
<>
<Button
type='button'
variant='outline'
onClick={() => onOpenChange(false)}
disabled={isSaving}
>
{t('Cancel')}
</Button>
<Button
type='submit'
form={VENDOR_MUTATE_FORM_ID}
disabled={isSaving}
>
{isSaving ? (
<Loader2 className='mr-2 h-4 w-4 animate-spin' />
) : null}
{isSaving ? t('Saving...') : isEdit ? t('Update') : t('Create')}
</Button>
</>
}
>
<Form {...form}>
<form
id={VENDOR_MUTATE_FORM_ID}
onSubmit={form.handleSubmit(onSubmit)}
className='space-y-4'
>
<FormField
control={form.control}
name='name'
render={({ field }) => (
<FormItem>
<FormLabel>{t('Vendor Name *')}</FormLabel>
<FormControl>
<Input
placeholder={t('OpenAI, Anthropic, etc.')}
{...field}
/>
</FormControl>
<FormDescription>
{t('The unique name for this vendor')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='description'
render={({ field }) => (
<FormItem>
<FormLabel>{t('Description')}</FormLabel>
<FormControl>
<Textarea
placeholder={t('Describe this vendor...')}
rows={3}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='icon'
render={({ field }) => (
<FormItem>
<FormLabel>{t('Icon')}</FormLabel>
<FormControl>
<Input
placeholder={t('OpenAI, Anthropic, Google, etc.')}
{...field}
/>
</FormControl>
<FormDescription>
{t('@lobehub/icons key name')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
</Dialog>
)
}