2025-02-07 15:30:47 +03:00
|
|
|
'use no memo'; // TODO: remove when react hook forms are compliant with react compiler
|
2024-03-08 18:39:08 +03:00
|
|
|
'use client';
|
|
|
|
|
2025-02-07 15:30:47 +03:00
|
|
|
import { useMemo } from 'react';
|
|
|
|
import { useForm, useWatch } from 'react-hook-form';
|
2025-02-12 21:36:25 +03:00
|
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
|
|
|
|
|
import { useRSFormSuspense } from '@/features/rsform';
|
2024-03-08 18:39:08 +03:00
|
|
|
|
2025-02-10 01:32:55 +03:00
|
|
|
import { MiniButton } from '@/components/Control';
|
2024-04-03 21:05:53 +03:00
|
|
|
import { IconReset, IconSave } from '@/components/Icons';
|
2025-02-10 01:32:55 +03:00
|
|
|
import { TextArea, TextInput } from '@/components/Input';
|
|
|
|
import { ModalView } from '@/components/Modal';
|
2025-01-16 16:31:32 +03:00
|
|
|
import { useDialogsStore } from '@/stores/dialogs';
|
2025-02-12 01:35:41 +03:00
|
|
|
import { errorMsg } from '@/utils/labels';
|
2024-03-08 18:39:08 +03:00
|
|
|
|
2025-02-21 21:15:05 +03:00
|
|
|
import { type IVersionUpdateDTO, schemaVersionUpdate } from '../../backend/types';
|
2025-02-12 15:13:37 +03:00
|
|
|
import { useMutatingLibrary } from '../../backend/useMutatingLibrary';
|
|
|
|
import { useVersionDelete } from '../../backend/useVersionDelete';
|
|
|
|
import { useVersionUpdate } from '../../backend/useVersionUpdate';
|
2025-02-12 21:36:25 +03:00
|
|
|
|
2025-02-19 23:30:35 +03:00
|
|
|
import { TableVersions } from './TableVersions';
|
2024-03-08 18:39:08 +03:00
|
|
|
|
2025-01-16 16:31:32 +03:00
|
|
|
export interface DlgEditVersionsProps {
|
2025-02-12 15:13:37 +03:00
|
|
|
itemID: number;
|
|
|
|
afterDelete: (targetVersion: number) => void;
|
2024-03-08 18:39:08 +03:00
|
|
|
}
|
|
|
|
|
2025-02-19 23:30:35 +03:00
|
|
|
export function DlgEditVersions() {
|
2025-02-07 15:30:47 +03:00
|
|
|
const { itemID, afterDelete } = useDialogsStore(state => state.props as DlgEditVersionsProps);
|
|
|
|
const hideDialog = useDialogsStore(state => state.hideDialog);
|
|
|
|
const { schema } = useRSFormSuspense({ itemID });
|
|
|
|
const isProcessing = useMutatingLibrary();
|
2025-01-27 15:03:48 +03:00
|
|
|
const { versionDelete } = useVersionDelete();
|
|
|
|
const { versionUpdate } = useVersionUpdate();
|
2024-03-08 18:39:08 +03:00
|
|
|
|
2025-02-07 15:30:47 +03:00
|
|
|
const {
|
|
|
|
register,
|
|
|
|
handleSubmit,
|
|
|
|
control,
|
|
|
|
reset,
|
2025-02-07 20:45:32 +03:00
|
|
|
formState: { isDirty, errors: formErrors }
|
2025-02-07 15:30:47 +03:00
|
|
|
} = useForm<IVersionUpdateDTO>({
|
2025-02-10 14:11:28 +03:00
|
|
|
resolver: zodResolver(schemaVersionUpdate),
|
2025-02-07 15:30:47 +03:00
|
|
|
defaultValues: {
|
2025-02-15 15:37:19 +03:00
|
|
|
id: schema.versions[schema.versions.length - 1].id,
|
|
|
|
version: schema.versions[schema.versions.length - 1].version,
|
|
|
|
description: schema.versions[schema.versions.length - 1].description
|
2025-02-07 20:45:32 +03:00
|
|
|
},
|
|
|
|
context: { schema: schema }
|
2025-02-07 15:30:47 +03:00
|
|
|
});
|
|
|
|
const versionID = useWatch({ control, name: 'id' });
|
|
|
|
const versionName = useWatch({ control, name: 'version' });
|
2024-03-08 18:39:08 +03:00
|
|
|
|
2025-02-07 15:30:47 +03:00
|
|
|
const isValid = useMemo(
|
|
|
|
() => schema.versions.every(ver => ver.id === versionID || ver.version != versionName),
|
|
|
|
[schema, versionID, versionName]
|
|
|
|
);
|
2025-01-27 15:03:48 +03:00
|
|
|
|
2025-02-12 15:13:37 +03:00
|
|
|
function handleSelectVersion(targetVersion: number) {
|
2025-02-07 15:30:47 +03:00
|
|
|
const ver = schema.versions.find(ver => ver.id === targetVersion);
|
|
|
|
if (!ver) {
|
2024-03-08 18:39:08 +03:00
|
|
|
return;
|
|
|
|
}
|
2025-02-07 15:30:47 +03:00
|
|
|
reset({ ...ver });
|
|
|
|
}
|
|
|
|
|
2025-02-12 15:13:37 +03:00
|
|
|
function handleDeleteVersion(targetVersion: number) {
|
2025-02-07 15:30:47 +03:00
|
|
|
const nextVer = schema.versions.find(ver => ver.id !== targetVersion);
|
2025-02-11 20:16:11 +03:00
|
|
|
void versionDelete({ itemID: itemID, versionID: targetVersion }).then(() => {
|
2025-02-07 15:30:47 +03:00
|
|
|
if (!nextVer) {
|
|
|
|
hideDialog();
|
|
|
|
} else if (targetVersion === versionID) {
|
|
|
|
reset({ id: nextVer.id, version: nextVer.version, description: nextVer.description });
|
2025-01-28 19:47:24 +03:00
|
|
|
}
|
2025-02-07 15:30:47 +03:00
|
|
|
afterDelete(targetVersion);
|
2025-01-28 19:47:24 +03:00
|
|
|
});
|
2024-03-08 18:39:08 +03:00
|
|
|
}
|
|
|
|
|
2025-02-07 15:30:47 +03:00
|
|
|
function onUpdate(data: IVersionUpdateDTO) {
|
|
|
|
if (!isDirty || isProcessing || !isValid) {
|
|
|
|
return;
|
2024-03-08 18:39:08 +03:00
|
|
|
}
|
2025-02-17 14:40:18 +03:00
|
|
|
void versionUpdate({ itemID: itemID, version: data }).then(() => reset({ ...data }));
|
2024-03-08 18:39:08 +03:00
|
|
|
}
|
|
|
|
|
2024-12-13 21:31:09 +03:00
|
|
|
return (
|
2025-02-06 20:28:23 +03:00
|
|
|
<ModalView header='Редактирование версий' className='flex flex-col w-[40rem] px-6 gap-3 pb-6'>
|
2024-06-26 19:47:31 +03:00
|
|
|
<TableVersions
|
2025-02-07 15:30:47 +03:00
|
|
|
processing={isProcessing}
|
2025-02-15 15:37:19 +03:00
|
|
|
items={schema.versions.reverse()}
|
2025-01-27 15:03:48 +03:00
|
|
|
onDelete={handleDeleteVersion}
|
2025-02-07 15:30:47 +03:00
|
|
|
onSelect={handleSelectVersion}
|
|
|
|
selected={versionID}
|
2024-03-08 18:39:08 +03:00
|
|
|
/>
|
2024-04-30 16:06:25 +03:00
|
|
|
|
2025-02-18 23:39:11 +03:00
|
|
|
<form className='flex items-center ' onSubmit={event => void handleSubmit(onUpdate)(event)}>
|
2025-02-07 20:45:32 +03:00
|
|
|
<TextInput
|
|
|
|
id='dlg_version'
|
|
|
|
{...register('version')}
|
|
|
|
dense
|
|
|
|
label='Версия'
|
|
|
|
className='w-[16rem] mr-3'
|
|
|
|
error={formErrors.version}
|
|
|
|
/>
|
2025-02-18 23:39:11 +03:00
|
|
|
<div className='cc-icons h-fit'>
|
2024-04-03 18:48:56 +03:00
|
|
|
<MiniButton
|
2025-02-07 15:30:47 +03:00
|
|
|
type='submit'
|
2025-02-12 01:35:41 +03:00
|
|
|
title={isValid ? 'Сохранить изменения' : errorMsg.versionTaken}
|
2025-02-07 15:30:47 +03:00
|
|
|
disabled={!isDirty || !isValid || isProcessing}
|
2024-04-03 21:05:53 +03:00
|
|
|
icon={<IconSave size='1.25rem' className='icon-primary' />}
|
2024-04-03 18:48:56 +03:00
|
|
|
/>
|
|
|
|
<MiniButton
|
|
|
|
title='Сбросить несохраненные изменения'
|
2025-02-07 15:30:47 +03:00
|
|
|
disabled={!isDirty}
|
|
|
|
onClick={() => reset()}
|
2024-04-03 21:05:53 +03:00
|
|
|
icon={<IconReset size='1.25rem' className='icon-primary' />}
|
2024-04-03 18:48:56 +03:00
|
|
|
/>
|
|
|
|
</div>
|
2025-02-07 15:30:47 +03:00
|
|
|
</form>
|
2024-03-08 18:39:08 +03:00
|
|
|
<TextArea
|
2025-02-07 15:30:47 +03:00
|
|
|
id='dlg_description' //
|
|
|
|
{...register('description')}
|
2024-03-08 18:39:08 +03:00
|
|
|
spellCheck
|
|
|
|
label='Описание'
|
|
|
|
rows={3}
|
|
|
|
/>
|
2025-02-06 20:28:23 +03:00
|
|
|
</ModalView>
|
2024-03-08 18:39:08 +03:00
|
|
|
);
|
|
|
|
}
|