Portal/rsconcept/frontend/src/features/library/dialogs/DlgChangeLocation.tsx

102 lines
3.4 KiB
TypeScript
Raw Normal View History

2024-06-07 20:17:03 +03:00
'use client';
2025-02-12 21:36:03 +03:00
import { Controller, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
2024-06-07 20:17:03 +03:00
import clsx from 'clsx';
import { z } from 'zod';
2024-06-07 20:17:03 +03:00
2025-02-12 21:36:03 +03:00
import { useAuthSuspense } from '@/features/auth';
import { Label, TextArea } from '@/components/Input';
import { ModalForm } from '@/components/Modal';
import { useDialogsStore } from '@/stores/dialogs';
2024-06-07 20:17:03 +03:00
import { limits } from '@/utils/constants';
import { errorMsg } from '@/utils/labels';
2024-06-07 20:17:03 +03:00
2025-02-12 15:12:59 +03:00
import { SelectLocationContext } from '../components/SelectLocationContext';
import { SelectLocationHead } from '../components/SelectLocationHead';
import { LocationHead } from '../models/library';
import { combineLocation, validateLocation } from '../models/libraryAPI';
const schemaLocation = z.object({
location: z.string().refine(data => validateLocation(data), { message: errorMsg.invalidLocation })
});
type ILocationType = z.infer<typeof schemaLocation>;
export interface DlgChangeLocationProps {
2024-06-07 20:17:03 +03:00
initial: string;
onChangeLocation: (newLocation: string) => void;
}
function DlgChangeLocation() {
const { initial, onChangeLocation } = useDialogsStore(state => state.props as DlgChangeLocationProps);
const { user } = useAuthSuspense();
2024-06-07 20:17:03 +03:00
const {
handleSubmit,
control,
formState: { errors, isValid, isDirty }
} = useForm<ILocationType>({
resolver: zodResolver(schemaLocation),
defaultValues: {
location: initial
},
mode: 'onChange'
});
2024-06-26 18:59:49 +03:00
function onSubmit(data: ILocationType) {
onChangeLocation(data.location);
2025-02-06 14:09:20 +03:00
}
2024-06-07 20:17:03 +03:00
return (
2025-02-06 20:27:56 +03:00
<ModalForm
2024-06-07 20:17:03 +03:00
overflowVisible
header='Изменение расположения'
submitText='Переместить'
submitInvalidTooltip={`Допустимы буквы, цифры, подчерк, пробел и "!". Сегмент пути не может начинаться и заканчиваться пробелом. Общая длина (с корнем) не должна превышать ${limits.location_len}`}
canSubmit={isValid && isDirty}
onSubmit={event => void handleSubmit(onSubmit)(event)}
2024-09-19 20:52:17 +03:00
className={clsx('w-[35rem]', 'pb-3 px-6 flex gap-3 h-[9rem]')}
2024-06-07 20:17:03 +03:00
>
<div className='flex flex-col gap-2 min-w-[7rem] h-min'>
2024-06-26 18:59:49 +03:00
<Label className='select-none' text='Корень' />
<Controller
control={control}
name='location'
render={({ field }) => (
<SelectLocationHead
value={field.value.substring(0, 2) as LocationHead}
onChange={newValue => field.onChange(combineLocation(newValue, field.value.substring(3)))}
excluded={!user.is_staff ? [LocationHead.LIBRARY] : []}
/>
)}
2024-06-07 20:17:03 +03:00
/>
</div>
<Controller
control={control}
name='location'
render={({ field }) => (
<SelectLocationContext className='max-h-[9.2rem]' value={field.value} onChange={field.onChange} />
)}
/>
<Controller
control={control} //
name='location'
render={({ field }) => (
<TextArea
id='dlg_location'
label='Путь'
rows={3}
value={field.value.substring(3)}
onChange={event => field.onChange(combineLocation(field.value.substring(0, 2), event.target.value))}
error={errors.location}
/>
)}
/>
2025-02-06 20:27:56 +03:00
</ModalForm>
2024-06-07 20:17:03 +03:00
);
}
export default DlgChangeLocation;