Skip to content

Commit

Permalink
feat(local-units): add delete modal and refine permissions
Browse files Browse the repository at this point in the history
- Add delete modal in Local Units Form and Local Units Table  
- Separate delete and validate permissions for local units  
- Simplify delete permission logic  

Co-authored-by: samshara <sameerai2736@gmail.com>
  • Loading branch information
shreeyash07 and samshara authored Dec 17, 2024
1 parent cbe00a9 commit 2e3eb63
Show file tree
Hide file tree
Showing 11 changed files with 350 additions and 165 deletions.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"namespace": "localUnitDeleteModal",
"strings": {
"submitLabel": "Submit",
"deleteSuccessMessage": "{localUnitName} has been successfully deleted.",
"deleteFailureMessage": "Unable to delete {localUnitName}. Please try again.",
"chooseDeleteReasonMessage": "Choose the reason to delete local unit.",
"deleteReasonExplanation": "Explain the reason why the local unit is being deleted.",
"deleteLocalUnitHeading": "Are you sure you want to delete \"{localUnitName}\"?"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import {
useCallback,
useMemo,
} from 'react';
import {
Button,
Modal,
RadioInput,
TextArea,
} from '@ifrc-go/ui';
import { useTranslation } from '@ifrc-go/ui/hooks';
import { resolveToString } from '@ifrc-go/ui/utils';
import {
createSubmitHandler,
getErrorObject,
ObjectSchema,
PartialForm,
requiredStringCondition,
useForm,
} from '@togglecorp/toggle-form';

import type { GlobalEnums } from '#contexts/domain';
import useGlobalEnums from '#hooks/domain/useGlobalEnums';
import useAlert from '#hooks/useAlert';
import {
GoApiBody,
useLazyRequest,
} from '#utils/restRequest';

import i18n from './i18n.json';
import styles from './styles.module.css';

type DeprecateReason = NonNullable<GlobalEnums['local_units_deprecate_reason']>[number];

type LocalUnitDeprecateBody = GoApiBody<'/api/v2/local-units/{id}/deprecate/', 'POST'>;

type DeprecateFormType = PartialForm<LocalUnitDeprecateBody>;
type FormSchema = ObjectSchema<DeprecateFormType>;
type FormSchemaFields = ReturnType<FormSchema['fields']>;

const deprecateReasonKeySelector = (
item: DeprecateReason,
) => item.key;

const deprecateReasonLabelSelector = (
item: DeprecateReason,
) => item.value;

const defaultFormValue: DeprecateFormType = {
};

const schema: FormSchema = {
fields: (): FormSchemaFields => ({
deprecated_reason: {
required: true,
},
deprecated_reason_overview: {
required: true,
requiredValidation: requiredStringCondition,
},
}),
};

interface Props {
localUnitId: number;
onDeleteActionSuccess?: () => void;
onClose: () => void;
localUnitName: string;
}

function LocalUnitDeleteModal(props: Props) {
const strings = useTranslation(i18n);
const {
localUnitId,
localUnitName,
onDeleteActionSuccess,
onClose,
} = props;

const {
local_units_deprecate_reason: deprecateReasonOptions,
} = useGlobalEnums();

const {
value,
error: formError,
setFieldValue,
setError,
validate,
} = useForm(schema, { value: defaultFormValue });

const error = useMemo(
() => getErrorObject(formError),
[formError],
);

const alert = useAlert();

const {
pending: deprecateLocalUnitPending,
trigger: deprecateLocalUnit,
} = useLazyRequest({
method: 'POST',
url: '/api/v2/local-units/{id}/deprecate/',
body: (body: LocalUnitDeprecateBody) => body,
pathVariables: { id: localUnitId },
onSuccess: () => {
const validationMessage = resolveToString(
strings.deleteSuccessMessage,
{ localUnitName },
);
alert.show(
validationMessage,
{ variant: 'success' },
);
if (onDeleteActionSuccess) {
onDeleteActionSuccess();
}
},
onFailure: (response) => {
const {
value: { messageForNotification },
} = response;

alert.show(
resolveToString(
strings.deleteFailureMessage,
{ localUnitName },
),
{
variant: 'danger',
description: messageForNotification,
},
);
},
});

const handleFormSubmit = useCallback(
(formValues: DeprecateFormType) => {
deprecateLocalUnit(formValues as LocalUnitDeprecateBody);
},
[deprecateLocalUnit],
);

return (
<Modal
heading={resolveToString(
strings.deleteLocalUnitHeading,
{ localUnitName },
)}
withHeaderBorder
childrenContainerClassName={styles.localUnitDeleteFormContent}
onClose={onClose}
footerActions={(
<Button
name={undefined}
onClick={createSubmitHandler(validate, setError, handleFormSubmit)}
disabled={deprecateLocalUnitPending}
>
{strings.submitLabel}
</Button>
)}
>
<RadioInput
required
name="deprecated_reason"
listContainerClassName={styles.reasonList}
value={value.deprecated_reason}
label={strings.chooseDeleteReasonMessage}
onChange={setFieldValue}
options={deprecateReasonOptions}
keySelector={deprecateReasonKeySelector}
labelSelector={deprecateReasonLabelSelector}
error={error?.deprecated_reason}
/>
<TextArea
required
name="deprecated_reason_overview"
label={strings.deleteReasonExplanation}
value={value.deprecated_reason_overview}
onChange={setFieldValue}
error={error?.deprecated_reason_overview}
/>
</Modal>
);
}

export default LocalUnitDeleteModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.local-unit-delete-form-content {
display: flex;
flex-direction: column;
gap: var(--go-ui-spacing-lg);

.reason-list {
flex-direction: column;
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"otherProfiles": "Other profiles",
"commentsNS": "Comments by the NS",
"submitButtonLabel": "Submit",
"editButtonLabel": "Edit"
"editButtonLabel": "Edit",
"localUnitDeleteButtonLabel": "Delete"
}
}
Loading

0 comments on commit 2e3eb63

Please sign in to comment.