Files
cloudflare-domain-manager/apps/web/src/components/subdomain-edit-sheet.tsx
T
Denozordec 2147782ba6
Build, Test, and Push CFDM Docker Image / test (push) Successful in 3m55s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 2m14s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 7s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped
refactor: Replace legacy UI components with new App components across various files for improved consistency and maintainability
2026-06-25 16:54:21 +07:00

197 lines
6.2 KiB
TypeScript

import { useEffect, useMemo, useState } from 'react'
import type { CertMonitoring } from '@cfdm/shared'
import type { ServiceView, SubdomainRecord } from '@/lib/schemas'
import { certMonitoringOptions } from '@/lib/cert-monitoring'
import { formatServiceGroupLabel } from '@/lib/service-utils'
import { FormFieldSimple } from '@/components/form-field'
import { LoadingButton } from '@/components/loading-button'
import { AppInput } from '@/components/app-input'
import { AppFieldDescription, AppFieldGroup } from '@/components/app-field'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@cfdm/ui/components/select'
import {
Sheet,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
} from '@cfdm/ui/components/sheet'
export interface SubdomainEditValues {
name: string
serviceId: string
certMonitoring: CertMonitoring
}
interface SubdomainEditSheetProps {
mode: 'create' | 'edit'
subdomain: SubdomainRecord | null
zoneName: string
services: ServiceView[]
serviceGroupById: Map<number, string | null>
currentServiceId: string
open: boolean
isSaving: boolean
onOpenChange: (open: boolean) => void
onSubmit: (values: SubdomainEditValues) => void
}
export function SubdomainEditSheet({
mode,
subdomain,
zoneName,
services,
serviceGroupById,
currentServiceId,
open,
isSaving,
onOpenChange,
onSubmit,
}: SubdomainEditSheetProps) {
const [name, setName] = useState('')
const [serviceId, setServiceId] = useState('none')
const [certMonitoring, setCertMonitoring] = useState<CertMonitoring>('auto')
const serviceItems = useMemo(
() => [
{ label: 'Без сервиса', value: 'none' },
...services.map((service) => ({
label: formatServiceGroupLabel(
serviceGroupById.get(service.id),
service.name,
),
value: String(service.id),
})),
],
[services, serviceGroupById],
)
const certMonitoringItems = useMemo(
() =>
certMonitoringOptions.map((option) => ({
label: option.label,
value: option.value,
})),
[],
)
useEffect(() => {
if (!open) return
if (mode === 'edit' && subdomain) {
setName(subdomain.name)
setServiceId(currentServiceId || 'none')
setCertMonitoring(subdomain.cert_monitoring)
return
}
setName('')
setServiceId('none')
setCertMonitoring('auto')
}, [open, mode, subdomain, currentServiceId])
function handleSubmit(event: React.FormEvent) {
event.preventDefault()
const trimmed = name.trim()
if (!trimmed) return
onSubmit({ name: trimmed, serviceId, certMonitoring })
}
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent>
<SheetHeader>
<SheetTitle>
{mode === 'create' ? 'Создать поддомен' : 'Редактировать поддомен'}
</SheetTitle>
<SheetDescription>
{mode === 'create'
? `Имя записи в зоне ${zoneName} (например, www или api)`
: `Изменение поддомена в зоне ${zoneName}`}
</SheetDescription>
</SheetHeader>
<form onSubmit={handleSubmit} className="flex flex-col gap-4 px-4">
<AppFieldGroup>
<FormFieldSimple label="Имя" htmlFor="subdomain_name">
<AppInput
id="subdomain_name"
placeholder="www"
value={name}
onChange={(event) => setName(event.target.value)}
className="font-mono"
aria-invalid={!name.trim() && name.length > 0}
/>
</FormFieldSimple>
{mode === 'edit' && (
<>
<FormFieldSimple label="Сервис" htmlFor="subdomain_service">
<Select
items={serviceItems}
value={serviceId}
onValueChange={(value) => setServiceId(value ?? 'none')}
>
<SelectTrigger id="subdomain_service" className="w-full">
<SelectValue placeholder="Без сервиса" />
</SelectTrigger>
<SelectContent>
{serviceItems.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectContent>
</Select>
</FormFieldSimple>
<FormFieldSimple
label="Мониторинг SSL"
htmlFor="subdomain_cert_monitoring"
>
<Select
items={certMonitoringItems}
value={certMonitoring}
onValueChange={(value) =>
setCertMonitoring((value ?? 'auto') as CertMonitoring)
}
>
<SelectTrigger id="subdomain_cert_monitoring" className="w-full">
<SelectValue />
</SelectTrigger>
<SelectContent>
{certMonitoringOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
<AppFieldDescription>
{
certMonitoringOptions.find((o) => o.value === certMonitoring)
?.description
}
</AppFieldDescription>
</FormFieldSimple>
</>
)}
</AppFieldGroup>
<SheetFooter>
<LoadingButton
type="submit"
className="w-full"
disabled={!name.trim()}
isLoading={isSaving}
loadingLabel="Сохранение…"
>
{mode === 'create' ? 'Создать' : 'Сохранить'}
</LoadingButton>
</SheetFooter>
</form>
</SheetContent>
</Sheet>
)
}