perf(web): improve dialog sizing and footer layout

- migrate frontend dialogs to the shared footer API so actions stay separated from scrollable body content.
- tune dialog dimensions for model analytics, prefill groups, billing history, channel model sync, and related workflows.
- update channel terminology and dialog action translations across supported locales.
This commit is contained in:
QuentinHsu
2026-06-06 21:49:33 +08:00
parent 7a5348caa3
commit 2eaa943d9f
80 changed files with 8137 additions and 8517 deletions
@@ -22,14 +22,6 @@ import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { useTranslation } from 'react-i18next'
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog'
import {
Form,
FormControl,
@@ -40,6 +32,7 @@ import {
FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { Dialog } from '@/components/dialog'
const rateLimitDialogSchema = z.object({
groupName: z.string().min(1, 'Group name is required'),
@@ -55,6 +48,8 @@ const rateLimitDialogSchema = z.object({
type RateLimitDialogFormValues = z.infer<typeof rateLimitDialogSchema>
const RATE_LIMIT_FORM_ID = 'rate-limit-form'
export type RateLimitEntryData = {
groupName: string
maxRequests: number
@@ -105,126 +100,125 @@ export function RateLimitDialog({
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className='sm:max-w-[500px]'>
<DialogHeader>
<DialogTitle>
{isEditMode
? t('Edit group rate limit')
: t('Add group rate limit')}
</DialogTitle>
<DialogDescription>
{t('Configure rate limiting rules for a specific user group.')}
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form
onSubmit={form.handleSubmit(handleSubmit)}
className='space-y-4'
<Dialog
open={open}
onOpenChange={onOpenChange}
title={
isEditMode ? t('Edit group rate limit') : t('Add group rate limit')
}
description={t(
'Configure rate limiting rules for a specific user group.'
)}
contentClassName='sm:max-w-[500px]'
contentHeight='auto'
bodyClassName='space-y-4'
footer={
<>
<Button
type='button'
variant='outline'
onClick={() => onOpenChange(false)}
>
<FormField
control={form.control}
name='groupName'
render={({ field }) => (
<FormItem>
<FormLabel>{t('Group Name')}</FormLabel>
<FormControl>
{t('Cancel')}
</Button>
<Button type='submit' form={RATE_LIMIT_FORM_ID}>
{isEditMode ? t('Update') : t('Add')}
</Button>
</>
}
>
<Form {...form}>
<form
id={RATE_LIMIT_FORM_ID}
onSubmit={form.handleSubmit(handleSubmit)}
className='space-y-4'
>
<FormField
control={form.control}
name='groupName'
render={({ field }) => (
<FormItem>
<FormLabel>{t('Group Name')}</FormLabel>
<FormControl>
<Input
placeholder={t('e.g., default, vip, premium')}
{...field}
disabled={isEditMode}
/>
</FormControl>
<FormDescription>
{isEditMode
? t('Group name cannot be changed when editing.')
: t('Unique identifier for this group.')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='maxRequests'
render={({ field }) => (
<FormItem>
<FormLabel>{t('Max Requests (including failures)')}</FormLabel>
<FormControl>
<div className='flex items-center gap-2'>
<Input
placeholder={t('e.g., default, vip, premium')}
type='number'
min={0}
max={2147483647}
step={1}
{...field}
disabled={isEditMode}
onChange={(e) =>
field.onChange(parseInt(e.target.value) || 0)
}
/>
</FormControl>
<FormDescription>
{isEditMode
? t('Group name cannot be changed when editing.')
: t('Unique identifier for this group.')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<span className='text-muted-foreground text-sm'>
{t('times')}
</span>
</div>
</FormControl>
<FormDescription>
{t('Total requests allowed per period. 0 = unlimited.')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='maxRequests'
render={({ field }) => (
<FormItem>
<FormLabel>
{t('Max Requests (including failures)')}
</FormLabel>
<FormControl>
<div className='flex items-center gap-2'>
<Input
type='number'
min={0}
max={2147483647}
step={1}
{...field}
onChange={(e) =>
field.onChange(parseInt(e.target.value) || 0)
}
/>
<span className='text-muted-foreground text-sm'>
{t('times')}
</span>
</div>
</FormControl>
<FormDescription>
{t('Total requests allowed per period. 0 = unlimited.')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='maxSuccess'
render={({ field }) => (
<FormItem>
<FormLabel>{t('Max Successful Requests')}</FormLabel>
<FormControl>
<div className='flex items-center gap-2'>
<Input
type='number'
min={1}
max={2147483647}
step={1}
{...field}
onChange={(e) =>
field.onChange(parseInt(e.target.value) || 1)
}
/>
<span className='text-muted-foreground text-sm'>
{t('times')}
</span>
</div>
</FormControl>
<FormDescription>
{t('Only successful requests count toward this limit.')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter>
<Button
type='button'
variant='outline'
onClick={() => onOpenChange(false)}
>
{t('Cancel')}
</Button>
<Button type='submit'>
{isEditMode ? t('Update') : t('Add')}
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
<FormField
control={form.control}
name='maxSuccess'
render={({ field }) => (
<FormItem>
<FormLabel>{t('Max Successful Requests')}</FormLabel>
<FormControl>
<div className='flex items-center gap-2'>
<Input
type='number'
min={1}
max={2147483647}
step={1}
{...field}
onChange={(e) =>
field.onChange(parseInt(e.target.value) || 1)
}
/>
<span className='text-muted-foreground text-sm'>
{t('times')}
</span>
</div>
</FormControl>
<FormDescription>
{t('Only successful requests count toward this limit.')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
</Dialog>
)
}