Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Akctarus committed Jan 24, 2024
1 parent 8ac0c0c commit a196492
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 158 deletions.
22 changes: 1 addition & 21 deletions front/src/common/BootstrapSNCF/ModalSNCF/ModalProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import React, {
} from 'react';
import { Outlet, useLocation } from 'react-router-dom';
import cx from 'classnames';
import ConfirmModal from './ConfirmModal';

/**
* Type of the modal context
Expand Down Expand Up @@ -48,11 +47,7 @@ export const ModalContext = createContext(initialModalContext);
export const ModalSNCF: FC = () => {
const modalRef = useRef<HTMLDivElement | null>(null);
const { isOpen, content, closeModal, size, className } = useContext(ModalContext);
const [isConfirmModalOpen, setConfirmModalOpen] = useState(false);

/**
* Register click outside event to close the modal.
*/
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
Expand All @@ -62,12 +57,7 @@ export const ModalSNCF: FC = () => {
!(event.target as HTMLElement).classList.contains('no-close-modal') &&
!modalRef.current.contains(event.target as HTMLElement)
) {
const isXlModal = modalRef.current.classList.contains('modal-xl');
if (isXlModal) {
setConfirmModalOpen(true);
} else if (!isXlModal) {
closeModal();
}
closeModal();
}
};

Expand All @@ -77,15 +67,6 @@ export const ModalSNCF: FC = () => {
};
}, [isOpen, closeModal]);

const handleConfirm = () => {
setConfirmModalOpen(false);
closeModal();
};

const handleCancel = () => {
setConfirmModalOpen(false);
};

if (!content) {
return null;
}
Expand All @@ -97,7 +78,6 @@ export const ModalSNCF: FC = () => {
role="dialog"
aria-hidden="true"
>
{isConfirmModalOpen && <ConfirmModal onConfirm={handleConfirm} onCancel={handleCancel} />}
<div
ref={modalRef}
className={cx('modal-dialog modal-dialog-centered', className, size && `modal-${size}`)}
Expand Down
309 changes: 172 additions & 137 deletions front/src/modules/scenario/components/AddOrEditScenarioModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cx from 'classnames';
import React, { useContext, useEffect, useMemo, useState } from 'react';
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { GoPencil, GoTrash } from 'react-icons/go';
import { FaPlus } from 'react-icons/fa';
Expand All @@ -25,6 +25,7 @@ import ModalHeaderSNCF from 'common/BootstrapSNCF/ModalSNCF/ModalHeaderSNCF';
import { ModalContext } from 'common/BootstrapSNCF/ModalSNCF/ModalProvider';
import { InfraSelectorModal } from 'modules/infra/components/InfraSelector';
import { setFailure, setSuccess } from 'reducers/main';
import { ConfirmModal } from 'common/BootstrapSNCF/ModalSNCF';

type CreateOrPatchScenarioForm = ScenarioPatchForm & {
id?: number;
Expand All @@ -47,7 +48,7 @@ export default function AddOrEditScenarioModal({
scenario,
}: AddOrEditScenarioModalProps) {
const { t } = useTranslation('operationalStudies/scenario');
const { closeModal } = useContext(ModalContext);
const { closeModal, isOpen } = useContext(ModalContext);
const noElectricalProfileSetOption = {
key: undefined,
value: t('noElectricalProfileSet').toString(),
Expand Down Expand Up @@ -206,146 +207,180 @@ export default function AddOrEditScenarioModal({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [infraID]);

const [clickedOutside, setClickedOutside] = useState(false);
const modalRef = useRef<HTMLDivElement | null>(null);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
event.target &&
isOpen &&
modalRef.current &&
!(event.target as HTMLElement).classList.contains('no-close-modal') &&
!modalRef.current.contains(event.target as HTMLElement)
) {
setClickedOutside(true);
}
};

document.body.addEventListener('mousedown', handleClickOutside);
return function cleanup() {
document.body.removeEventListener('mousedown', handleClickOutside);
};
}, [isOpen, clickedOutside]);

const resetClickedOutside = () => {
setClickedOutside(false);
};

return (
<div className="scenario-edition-modal">
<ModalHeaderSNCF withCloseButton withBorderBottom>
<h1 className="scenario-edition-modal-title">
{editionMode ? t('scenarioModificationTitle') : t('scenarioCreationTitle')}
</h1>
</ModalHeaderSNCF>
<ModalBodySNCF>
<div className="row">
<div className={editionMode ? 'col-lg-12' : 'col-lg-6'}>
<div className="scenario-edition-modal-name">
<InputSNCF
id="scenarioInputName"
type="text"
name="scenarioInputName"
label={
<div className="d-flex align-items-center">
<span className="mr-2">
<MdTitle />
</span>
<span className="font-weight-bold">{t('scenarioName')}</span>
<div className="scenario-edition-modal no-close-modal" ref={modalRef}>
{clickedOutside ? (
<ConfirmModal onConfirm={resetClickedOutside} />
) : (
<>
<ModalHeaderSNCF withCloseButton withBorderBottom>
<h1 className="scenario-edition-modal-title">
{editionMode ? t('scenarioModificationTitle') : t('scenarioCreationTitle')}
</h1>
</ModalHeaderSNCF>
<ModalBodySNCF>
<div className="row">
<div className={editionMode ? 'col-lg-12' : 'col-lg-6'}>
<div className="scenario-edition-modal-name">
<InputSNCF
id="scenarioInputName"
type="text"
name="scenarioInputName"
label={
<div className="d-flex align-items-center">
<span className="mr-2">
<MdTitle />
</span>
<span className="font-weight-bold">{t('scenarioName')}</span>
</div>
}
value={currentScenario.name || ''}
onChange={(e) =>
setCurrentScenario({ ...currentScenario, name: e.target.value })
}
isInvalid={displayErrors && !currentScenario.name}
errorMsg={
displayErrors && !currentScenario.name ? t('scenarioNameMissing') : undefined
}
/>
</div>
<div className="scenario-edition-modal-description">
<TextareaSNCF
id="scenarioDescription"
label={
<div className="d-flex align-items-center">
<span className="mr-2">
<MdDescription />
</span>
{t('scenarioDescription')}
</div>
}
value={currentScenario.description || ''}
onChange={(e) =>
setCurrentScenario({ ...currentScenario, description: e.target.value })
}
/>
</div>
{!editionMode && electricalProfilOptions.length > 1 && (
<div className="scenario-edition-modal-description">
<SelectImprovedSNCF
label={
<div className="d-flex align-items-center">
<span className="mr-2">
<GiElectric />
</span>
{t('electricalProfileSet')}
</div>
}
value={selectedValue}
options={electricalProfilOptions.map((e) => ({
id: `${e.key}`,
label: e.value,
}))}
onChange={(e) =>
setCurrentScenario({
...currentScenario,
electrical_profile_set_id: e?.id ? +e.id : undefined,
})
}
/>
</div>
}
value={currentScenario.name || ''}
onChange={(e) => setCurrentScenario({ ...currentScenario, name: e.target.value })}
isInvalid={displayErrors && !currentScenario.name}
errorMsg={
displayErrors && !currentScenario.name ? t('scenarioNameMissing') : undefined
}
/>
</div>
<div className="scenario-edition-modal-description">
<TextareaSNCF
id="scenarioDescription"
label={
<div className="d-flex align-items-center">
<span className="mr-2">
<MdDescription />
</span>
{t('scenarioDescription')}
</div>
}
value={currentScenario.description || ''}
onChange={(e) =>
setCurrentScenario({ ...currentScenario, description: e.target.value })
}
/>
</div>
{!editionMode && electricalProfilOptions.length > 1 && (
<div className="scenario-edition-modal-description">
<SelectImprovedSNCF
label={
<div className="d-flex align-items-center">
<span className="mr-2">
<GiElectric />
</span>
{t('electricalProfileSet')}
</div>
}
value={selectedValue}
options={electricalProfilOptions.map((e) => ({
id: `${e.key}`,
label: e.value,
}))}
onChange={(e) =>
setCurrentScenario({
...currentScenario,
electrical_profile_set_id: e?.id ? +e.id : undefined,
})
}
)}
<ChipsSNCF
addTag={addTag}
tags={currentScenario.tags || []}
removeTag={removeTag}
title={t('scenarioTags')}
color="teal"
/>
</div>
)}
<ChipsSNCF
addTag={addTag}
tags={currentScenario.tags || []}
removeTag={removeTag}
title={t('scenarioTags')}
color="teal"
/>
</div>
{!editionMode && (
<div className="col-lg-6">
<div
className={cx('scenario-edition-modal-infraselector', {
'scenario-edition-modal-infraselector-missing':
displayErrors && !currentScenario.infra_id,
})}
>
<InfraSelectorModal onlySelectionMode />
</div>
{!editionMode && (
<div className="col-lg-6">
<div
className={cx('scenario-edition-modal-infraselector', {
'scenario-edition-modal-infraselector-missing':
displayErrors && !currentScenario.infra_id,
})}
>
<InfraSelectorModal onlySelectionMode />
</div>
</div>
)}
</div>
</ModalBodySNCF>
<ModalFooterSNCF>
<div className="d-flex justify-content-end w-100 mt-3">
{editionMode && (
<button
data-testid="deleteScenario"
className="btn btn-sm btn-outline-danger mr-auto"
type="button"
onClick={removeScenario}
>
<span className="mr-2">
<GoTrash />
</span>
{t('scenarioDeleteButton')}
</button>
)}
<button className="btn btn-sm btn-secondary mr-2" type="button" onClick={closeModal}>
{t('scenarioCancel')}
</button>
{editionMode ? (
<button
data-testid="updateScenario"
className="btn btn-sm btn-warning"
type="button"
onClick={updateScenario}
>
<span className="mr-2">
<GoPencil />
</span>
{t('scenarioModifyButton')}
</button>
) : (
<button
data-testid="createScenario"
className="btn btn-sm btn-primary"
type="button"
onClick={createScenario}
>
<span className="mr-2">
<FaPlus />
</span>
{t('scenarioCreateButton')}
</button>
)}
</div>
)}
</div>
</ModalBodySNCF>
<ModalFooterSNCF>
<div className="d-flex justify-content-end w-100 mt-3">
{editionMode && (
<button
data-testid="deleteScenario"
className="btn btn-sm btn-outline-danger mr-auto"
type="button"
onClick={removeScenario}
>
<span className="mr-2">
<GoTrash />
</span>
{t('scenarioDeleteButton')}
</button>
)}
<button className="btn btn-sm btn-secondary mr-2" type="button" onClick={closeModal}>
{t('scenarioCancel')}
</button>
{editionMode ? (
<button
data-testid="updateScenario"
className="btn btn-sm btn-warning"
type="button"
onClick={updateScenario}
>
<span className="mr-2">
<GoPencil />
</span>
{t('scenarioModifyButton')}
</button>
) : (
<button
data-testid="createScenario"
className="btn btn-sm btn-primary"
type="button"
onClick={createScenario}
>
<span className="mr-2">
<FaPlus />
</span>
{t('scenarioCreateButton')}
</button>
)}
</div>
</ModalFooterSNCF>
</ModalFooterSNCF>
</>
)}
</div>
);
}

0 comments on commit a196492

Please sign in to comment.