Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | 33x 33x 33x 33x 33x 33x 8x 8x 8x 8x 8x 4x 4x 4x 4x 4x 2x 2x 2x 4x | import React, { useState } from 'react';
import { useAppDispatch } from '@/store/hooks';
import { projectSchema } from '@/shared/schema';
import { PROJECT_MESSAGES } from '@/shared/constants';
import {
ModalActions,
ModalContainer,
ModalForm,
ModalInputs,
} from '@/entities/project/ui/modal';
import type { ErrorMessage } from '@/shared/types';
interface ProjectModalBaseProps<TArgs extends Record<string, unknown>> {
title: string;
buttonLabel: string;
onClose: () => void;
onSubmitAction: (
dispatch: ReturnType<typeof useAppDispatch>,
args: TArgs,
) => Promise<void>;
initialValue?: string;
buildArgs: (name: string, width: number, height: number) => TArgs;
disableAutoClose?: boolean;
showInput?: boolean;
showCanvasInputs?: boolean;
customContent?: React.ReactNode;
'data-testid'?: string;
}
/**
* Base modal layout for project operations (Create / Update / Delete)
* Handles validation, async dispatching, error feedback and visuals.
*/
export function ProjectModalBase<TArgs extends Record<string, unknown>>({
title,
buttonLabel,
onClose,
onSubmitAction,
initialValue = '',
buildArgs,
showInput = true,
showCanvasInputs = false,
customContent,
'data-testid': testId,
}: ProjectModalBaseProps<TArgs>) {
const dispatch = useAppDispatch();
const [name, setName] = useState(initialValue);
const [width, setWidth] = useState(800);
const [height, setHeight] = useState(600);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<ErrorMessage>(null);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setError(null);
Eif (showInput || showCanvasInputs) {
const validation = projectSchema.safeParse({ name, width, height });
if (!validation.success) {
setError(
validation.error.issues[0]?.message ??
PROJECT_MESSAGES.ERROR_VALIDATION,
);
return;
}
}
try {
setLoading(true);
await onSubmitAction(dispatch, buildArgs(name, width, height));
onClose();
} catch (err) {
const message = (err instanceof Error ? err.message : '') || '';
setError(
message.includes('exists')
? PROJECT_MESSAGES.NAME_DUPLICATE
: PROJECT_MESSAGES.UNEXPECTED_SERVER_ERROR,
);
} finally {
setLoading(false);
}
}
return (
<ModalContainer data-testid={testId}>
<ModalForm onSubmit={handleSubmit} data-testid="project-form" title={title}>
<ModalInputs
showInput={showInput}
showCanvasInputs={showCanvasInputs}
customContent={customContent}
name={name}
width={width}
height={height}
error={error}
setName={setName}
setWidth={setWidth}
setHeight={setHeight}
/>
<ModalActions
onClose={onClose}
buttonLabel={buttonLabel}
loading={loading}
showInput={showInput}
/>
</ModalForm>
</ModalContainer>
);
}
|