2024-10-23 15:18:46 +03:00
|
|
|
'use client';
|
|
|
|
|
|
|
|
import clsx from 'clsx';
|
2024-12-13 21:30:49 +03:00
|
|
|
import { useState } from 'react';
|
2024-10-23 15:18:46 +03:00
|
|
|
|
2024-10-28 23:55:12 +03:00
|
|
|
import { RelocateUpIcon } from '@/components/DomainIcons';
|
2024-10-23 15:18:46 +03:00
|
|
|
import PickMultiConstituenta from '@/components/select/PickMultiConstituenta';
|
|
|
|
import SelectLibraryItem from '@/components/select/SelectLibraryItem';
|
2024-10-28 23:55:12 +03:00
|
|
|
import MiniButton from '@/components/ui/MiniButton';
|
2025-01-16 16:31:03 +03:00
|
|
|
import Modal from '@/components/ui/Modal';
|
2024-10-23 15:18:46 +03:00
|
|
|
import DataLoader from '@/components/wrap/DataLoader';
|
|
|
|
import { useLibrary } from '@/context/LibraryContext';
|
|
|
|
import useRSFormDetails from '@/hooks/useRSFormDetails';
|
|
|
|
import { ILibraryItem, LibraryItemID } from '@/models/library';
|
2024-10-29 12:05:23 +03:00
|
|
|
import { HelpTopic } from '@/models/miscellaneous';
|
2024-10-23 15:18:46 +03:00
|
|
|
import { ICstRelocateData, IOperation, IOperationSchema } from '@/models/oss';
|
|
|
|
import { getRelocateCandidates } from '@/models/ossAPI';
|
|
|
|
import { ConstituentaID } from '@/models/rsform';
|
2025-01-16 16:31:03 +03:00
|
|
|
import { useDialogsStore } from '@/stores/dialogs';
|
2024-10-23 15:18:46 +03:00
|
|
|
import { prefixes } from '@/utils/constants';
|
|
|
|
|
2025-01-16 16:31:03 +03:00
|
|
|
export interface DlgRelocateConstituentsProps {
|
2024-10-23 15:18:46 +03:00
|
|
|
oss: IOperationSchema;
|
2024-10-28 23:55:12 +03:00
|
|
|
initialTarget?: IOperation;
|
2024-10-23 15:18:46 +03:00
|
|
|
onSubmit: (data: ICstRelocateData) => void;
|
|
|
|
}
|
|
|
|
|
2025-01-16 16:31:03 +03:00
|
|
|
function DlgRelocateConstituents() {
|
|
|
|
const { oss, initialTarget, onSubmit } = useDialogsStore(state => state.props as DlgRelocateConstituentsProps);
|
2024-10-23 15:18:46 +03:00
|
|
|
const library = useLibrary();
|
|
|
|
|
2024-10-28 23:55:12 +03:00
|
|
|
const [directionUp, setDirectionUp] = useState(true);
|
2024-10-23 15:18:46 +03:00
|
|
|
const [destination, setDestination] = useState<ILibraryItem | undefined>(undefined);
|
|
|
|
const [selected, setSelected] = useState<ConstituentaID[]>([]);
|
2024-10-28 23:55:12 +03:00
|
|
|
const [source, setSource] = useState<ILibraryItem | undefined>(
|
|
|
|
library.items.find(item => item.id === initialTarget?.result)
|
|
|
|
);
|
2024-12-13 21:30:49 +03:00
|
|
|
const isValid = !!destination && selected.length > 0;
|
2024-10-28 23:55:12 +03:00
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
const operation = oss.items.find(item => item.result === source?.id);
|
|
|
|
const sourceSchemas = library.items.filter(item => oss.schemas.includes(item.id));
|
|
|
|
const destinationSchemas = (() => {
|
2024-10-28 23:55:12 +03:00
|
|
|
if (!operation) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
const node = oss.graph.at(operation.id)!;
|
|
|
|
const ids: LibraryItemID[] = directionUp
|
|
|
|
? node.inputs.map(id => oss.operationByID.get(id)!.result).filter(id => id !== null)
|
|
|
|
: node.outputs.map(id => oss.operationByID.get(id)!.result).filter(id => id !== null);
|
|
|
|
return ids.map(id => library.items.find(item => item.id === id)).filter(item => item !== undefined);
|
2024-12-13 21:30:49 +03:00
|
|
|
})();
|
2024-10-23 15:18:46 +03:00
|
|
|
|
2024-10-28 23:55:12 +03:00
|
|
|
const sourceData = useRSFormDetails({ target: source ? String(source.id) : undefined });
|
2024-12-13 21:30:49 +03:00
|
|
|
const filteredConstituents = (() => {
|
2024-10-28 23:55:12 +03:00
|
|
|
if (!sourceData.schema || !destination || !operation) {
|
2024-10-23 15:18:46 +03:00
|
|
|
return [];
|
|
|
|
}
|
|
|
|
const destinationOperation = oss.items.find(item => item.result === destination.id);
|
2024-10-28 23:55:12 +03:00
|
|
|
return getRelocateCandidates(operation.id, destinationOperation!.id, sourceData.schema, oss);
|
2024-12-13 21:30:49 +03:00
|
|
|
})();
|
2024-10-23 15:18:46 +03:00
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
function toggleDirection() {
|
2024-10-28 23:55:12 +03:00
|
|
|
setDirectionUp(prev => !prev);
|
|
|
|
setDestination(undefined);
|
2024-12-13 21:30:49 +03:00
|
|
|
}
|
2024-10-23 15:18:46 +03:00
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
function handleSelectSource(newValue: ILibraryItem | undefined) {
|
2024-10-28 23:55:12 +03:00
|
|
|
setSource(newValue);
|
|
|
|
setDestination(undefined);
|
2024-10-23 15:18:46 +03:00
|
|
|
setSelected([]);
|
2024-12-13 21:30:49 +03:00
|
|
|
}
|
2024-10-23 15:18:46 +03:00
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
function handleSelectDestination(newValue: ILibraryItem | undefined) {
|
2024-10-23 15:18:46 +03:00
|
|
|
setDestination(newValue);
|
2024-10-28 23:55:12 +03:00
|
|
|
setSelected([]);
|
2024-12-13 21:30:49 +03:00
|
|
|
}
|
2024-10-23 15:18:46 +03:00
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
function handleSubmit() {
|
2024-10-28 14:52:30 +03:00
|
|
|
if (!destination) {
|
|
|
|
return;
|
|
|
|
}
|
2024-10-23 15:18:46 +03:00
|
|
|
const data: ICstRelocateData = {
|
2024-10-28 14:52:30 +03:00
|
|
|
destination: destination.id,
|
|
|
|
items: selected
|
2024-10-23 15:18:46 +03:00
|
|
|
};
|
|
|
|
onSubmit(data);
|
2024-12-13 21:30:49 +03:00
|
|
|
}
|
2024-10-23 15:18:46 +03:00
|
|
|
|
|
|
|
return (
|
|
|
|
<Modal
|
2024-10-29 12:05:23 +03:00
|
|
|
header='Перенос конституент'
|
2024-10-23 15:18:46 +03:00
|
|
|
submitText='Переместить'
|
|
|
|
canSubmit={isValid}
|
|
|
|
onSubmit={handleSubmit}
|
|
|
|
className={clsx('w-[40rem] h-[33rem]', 'py-3 px-6')}
|
2024-10-29 12:05:23 +03:00
|
|
|
helpTopic={HelpTopic.UI_RELOCATE_CST}
|
2024-10-23 15:18:46 +03:00
|
|
|
>
|
2024-10-28 23:55:12 +03:00
|
|
|
<div className='flex flex-col border'>
|
|
|
|
<div className='flex gap-1 items-center clr-input border-b rounded-t-md'>
|
|
|
|
<SelectLibraryItem
|
|
|
|
noBorder
|
|
|
|
className='w-1/2'
|
|
|
|
placeholder='Выберите исходную схему'
|
|
|
|
items={sourceSchemas}
|
|
|
|
value={source}
|
|
|
|
onSelectValue={handleSelectSource}
|
|
|
|
/>
|
|
|
|
<MiniButton
|
|
|
|
title='Направление перемещения'
|
|
|
|
icon={<RelocateUpIcon value={directionUp} />}
|
|
|
|
onClick={toggleDirection}
|
|
|
|
/>
|
|
|
|
<SelectLibraryItem
|
|
|
|
noBorder
|
|
|
|
className='w-1/2'
|
|
|
|
placeholder='Выберите целевую схему'
|
|
|
|
items={destinationSchemas}
|
|
|
|
value={destination}
|
|
|
|
onSelectValue={handleSelectDestination}
|
2024-10-23 15:18:46 +03:00
|
|
|
/>
|
2024-10-28 23:55:12 +03:00
|
|
|
</div>
|
2024-12-12 13:17:24 +03:00
|
|
|
<DataLoader isLoading={sourceData.loading} error={sourceData.error}>
|
2024-10-28 23:55:12 +03:00
|
|
|
{sourceData.schema ? (
|
|
|
|
<PickMultiConstituenta
|
|
|
|
noBorder
|
|
|
|
schema={sourceData.schema}
|
|
|
|
data={filteredConstituents}
|
|
|
|
rows={12}
|
|
|
|
prefixID={prefixes.dlg_cst_constituents_list}
|
|
|
|
selected={selected}
|
|
|
|
setSelected={setSelected}
|
|
|
|
/>
|
|
|
|
) : null}
|
|
|
|
</DataLoader>
|
|
|
|
</div>
|
2024-10-23 15:18:46 +03:00
|
|
|
</Modal>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default DlgRelocateConstituents;
|