Files
vps-tracker/apps/web/src/components/domain/project-edit-sheet.tsx
T
DenozordecandCursor 447d499a8d
Docker / build (push) Failing after 20s
feat(projects): переработать проекты и отчётность по проектам
Добавлены карточка проекта, KPI и фильтры на /projects, отчёты с разрезом по проектам, cascade rename и защита удаления на API.

Co-authored-by: Cursor <[email protected]>
2026-06-29 19:21:04 +07:00

96 lines
3.1 KiB
TypeScript

import { Controller } from 'react-hook-form'
import { FormSheetRhf } from '@/components/form-sheet-rhf'
import { FormField } from '@/components/form-field'
import { Input } from '@cfdm/ui/components/input'
import { Textarea } from '@cfdm/ui/components/textarea'
import { ColorPicker } from '@/components/reui/color-picker'
import { projectSchema, type ProjectFormValues } from '@/lib/schemas'
const EMPTY: ProjectFormValues = { name: '', color: '', notes: '' }
interface ProjectEditSheetProps {
open: boolean
onOpenChange: (open: boolean) => void
defaultValues?: ProjectFormValues
onSubmit: (values: ProjectFormValues) => void
submitting?: boolean
}
export function projectFormDefaults(edit?: Partial<ProjectFormValues> | null): ProjectFormValues {
if (!edit) return { ...EMPTY }
return { ...EMPTY, ...edit, color: edit.color ?? '', notes: edit.notes ?? '' }
}
export function ProjectEditSheet({
open,
onOpenChange,
defaultValues = EMPTY,
onSubmit,
submitting,
}: ProjectEditSheetProps) {
const isEdit = Boolean(defaultValues.id)
return (
<FormSheetRhf
open={open}
onOpenChange={onOpenChange}
title={isEdit ? 'Редактировать проект' : 'Новый проект'}
description="Имя будет доступно в автодополнении на форме VPS"
schema={projectSchema as import('zod').ZodType<ProjectFormValues>}
defaultValues={defaultValues}
onSubmit={onSubmit}
submitting={submitting}
>
{(form) => {
const {
register,
control,
formState: { errors },
} = form
return (
<>
<FormField label="Название" htmlFor="project-name" error={errors.name?.message} invalid={!!errors.name}>
<Input id="project-name" aria-invalid={!!errors.name} {...register('name')} />
</FormField>
<FormField
label="Цвет (hex)"
htmlFor="project-color"
description="Например #3b82f6 — для badge в списке VPS"
error={errors.color?.message}
invalid={!!errors.color}
>
<Controller
control={control}
name="color"
render={({ field }) => (
<ColorPicker
id="project-color"
value={field.value ?? ''}
onChange={field.onChange}
onBlur={field.onBlur}
aria-invalid={!!errors.color}
/>
)}
/>
</FormField>
<FormField
label="Заметки"
htmlFor="project-notes"
error={errors.notes?.message}
invalid={!!errors.notes}
>
<Textarea
id="project-notes"
rows={3}
aria-invalid={!!errors.notes}
{...register('notes')}
/>
</FormField>
</>
)
}}
</FormSheetRhf>
)
}