From d5daf9eb5a3b81d4abe7e2f150236eac7f421283 Mon Sep 17 00:00:00 2001 From: Silevester Dongmo <58907550+SilverD3@users.noreply.github.com> Date: Tue, 22 Oct 2024 16:57:42 +0100 Subject: [PATCH] OH2-404 | Implement supplier deletion (#677) * chore:update suppliers api * feat:OH2-404 | supplier deletion --- .../accessories/admin/suppliers/Suppliers.tsx | 8 ++ .../suppliersTable/SuppliersTable.tsx | 76 ++++++++++++++----- src/generated/apis/SuppliersApi.ts | 22 ++++++ src/generated/models/GroupPermissionsDTO.ts | 25 ++++++ src/resources/i18n/en.json | 5 +- src/state/suppliers/slice.ts | 17 ++++- src/state/suppliers/thunk.ts | 9 +++ src/state/suppliers/types.ts | 2 +- 8 files changed, 142 insertions(+), 22 deletions(-) create mode 100644 src/generated/models/GroupPermissionsDTO.ts diff --git a/src/components/accessories/admin/suppliers/Suppliers.tsx b/src/components/accessories/admin/suppliers/Suppliers.tsx index 4f7a7efef..98e97f246 100644 --- a/src/components/accessories/admin/suppliers/Suppliers.tsx +++ b/src/components/accessories/admin/suppliers/Suppliers.tsx @@ -1,7 +1,9 @@ import React from "react"; +import { useAppDispatch } from "libraries/hooks/redux"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router"; +import { deleteSupplier } from "state/suppliers"; import { PATHS } from "../../../../consts"; import { SupplierDTO } from "../../../../generated"; import Button from "../../button/Button"; @@ -9,6 +11,7 @@ import SuppliersTable from "./suppliersTable"; export const Suppliers = () => { const navigate = useNavigate(); + const dispatch = useAppDispatch(); const { t } = useTranslation(); const handleEdit = (row: SupplierDTO) => { @@ -17,9 +20,14 @@ export const Suppliers = () => { }); }; + const handleDelete = (row: SupplierDTO) => { + dispatch(deleteSupplier(row.supId)); + }; + return ( { diff --git a/src/components/accessories/admin/suppliers/suppliersTable/SuppliersTable.tsx b/src/components/accessories/admin/suppliers/suppliersTable/SuppliersTable.tsx index 0c367a5ab..5db097190 100644 --- a/src/components/accessories/admin/suppliers/suppliersTable/SuppliersTable.tsx +++ b/src/components/accessories/admin/suppliers/suppliersTable/SuppliersTable.tsx @@ -1,22 +1,34 @@ import { CircularProgress } from "@mui/material"; +import ConfirmationDialog from "components/accessories/confirmationDialog/ConfirmationDialog"; import { useAppDispatch, useAppSelector } from "libraries/hooks/redux"; -import React, { ReactNode, useEffect } from "react"; +import React, { ReactNode, useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; import { SupplierDTO } from "../../../../../generated"; -import { getSuppliers } from "../../../../../state/suppliers"; +import { + deleteSupplierReset, + getSuppliers, +} from "../../../../../state/suppliers"; import InfoBox from "../../../infoBox/InfoBox"; import Table from "../../../table/Table"; import { TFilterField } from "../../../table/filter/types"; import classes from "./SuppliersTable.module.scss"; +import checkIcon from "../../../../../assets/check-icon.png"; + interface IOwnProps { onEdit: (row: any) => void; + onDelete: (row: any) => void; headerActions?: ReactNode; } -export const SuppliersTable = ({ onEdit, headerActions }: IOwnProps) => { +export const SuppliersTable = ({ + onEdit, + onDelete, + headerActions, +}: IOwnProps) => { const dispatch = useAppDispatch(); const { t } = useTranslation(); + const infoBoxRef = useRef(null); useEffect(() => { dispatch(getSuppliers()); @@ -44,6 +56,8 @@ export const SuppliersTable = ({ onEdit, headerActions }: IOwnProps) => { (state) => state.suppliers.supplierList ); + const deleteSupplier = useAppSelector((state) => state.suppliers.delete); + const formatDataToDisplay = (data: SupplierDTO[]) => { return data.map((item) => { return { @@ -78,20 +92,48 @@ export const SuppliersTable = ({ onEdit, headerActions }: IOwnProps) => { case "SUCCESS": return ( - + <> +
+ {deleteSupplier.isLoading && ( +
+ +
+ )} + {deleteSupplier.status === "FAIL" && ( +
+ +
+ )} + { + dispatch(getSuppliers()); + dispatch(deleteSupplierReset()); + }} + handleSecondaryButtonClick={() => ({})} + /> + ); case "SUCCESS_EMPTY": return ; diff --git a/src/generated/apis/SuppliersApi.ts b/src/generated/apis/SuppliersApi.ts index ea55d6a80..07cbb0d47 100644 --- a/src/generated/apis/SuppliersApi.ts +++ b/src/generated/apis/SuppliersApi.ts @@ -17,6 +17,10 @@ import { SupplierDTO, } from '../models'; +export interface DeleteSupplierRequest { + id: number; +} + export interface GetSuppliersRequest { excludeDeleted?: boolean; } @@ -38,6 +42,24 @@ export interface UpdateSupplierRequest { */ export class SuppliersApi extends BaseAPI { + /** + */ + deleteSupplier({ id }: DeleteSupplierRequest): Observable + deleteSupplier({ id }: DeleteSupplierRequest, opts?: OperationOpts): Observable> + deleteSupplier({ id }: DeleteSupplierRequest, opts?: OperationOpts): Observable> { + throwIfNullOrUndefined(id, 'id', 'deleteSupplier'); + + const headers: HttpHeaders = { + ...(this.configuration.username != null && this.configuration.password != null ? { Authorization: `Basic ${btoa(this.configuration.username + ':' + this.configuration.password)}` } : undefined), + }; + + return this.request({ + url: '/suppliers/{id}'.replace('{id}', encodeURI(id)), + method: 'DELETE', + headers, + }, opts?.responseOpts); + }; + /** */ getSuppliers({ excludeDeleted }: GetSuppliersRequest): Observable> diff --git a/src/generated/models/GroupPermissionsDTO.ts b/src/generated/models/GroupPermissionsDTO.ts new file mode 100644 index 000000000..d56bab2a4 --- /dev/null +++ b/src/generated/models/GroupPermissionsDTO.ts @@ -0,0 +1,25 @@ +// tslint:disable +/** + * Open Hospital API Documentation + * Open Hospital API Documentation + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * @export + * @interface GroupPermissionsDTO + */ +export interface GroupPermissionsDTO { + /** + * List of permissions\' ids + * @type {Array} + * @memberof GroupPermissionsDTO + */ + permissions?: Array; +} diff --git a/src/resources/i18n/en.json b/src/resources/i18n/en.json index 872e77d45..39fc5a534 100644 --- a/src/resources/i18n/en.json +++ b/src/resources/i18n/en.json @@ -1040,7 +1040,10 @@ "updated": "Supplier updated", "updateSuccess": "Supplier has been updated successfully!", "created": "Supplier created", - "createSuccess": "Supplier has been created successfully!" + "createSuccess": "Supplier has been created successfully!", + "deleted": "Supplier deleted", + "deleting": "Deleting supplier...", + "deleteSuccess": "Supplier has been deleted successfully!" }, "ward": { "code": "Code", diff --git a/src/state/suppliers/slice.ts b/src/state/suppliers/slice.ts index 80fc69a65..8f8b8cb94 100644 --- a/src/state/suppliers/slice.ts +++ b/src/state/suppliers/slice.ts @@ -1,8 +1,8 @@ import { createSlice } from "@reduxjs/toolkit"; +import { isEmpty } from "lodash"; +import { ApiResponse } from "state/types"; import { initial } from "./initial"; import * as thunks from "./thunk"; -import { ApiResponse } from "state/types"; -import { isEmpty } from "lodash"; export const supplierSlice = createSlice({ name: "suppliers", @@ -26,7 +26,8 @@ export const supplierSlice = createSlice({ }) .addCase(thunks.getSuppliers.fulfilled, (state, action) => { state.supplierList = isEmpty(action.payload) - ? ApiResponse.empty() : ApiResponse.value(action.payload); + ? ApiResponse.empty() + : ApiResponse.value(action.payload); }) .addCase(thunks.getSuppliers.rejected, (state, action) => { state.supplierList = ApiResponse.error(action.payload); @@ -50,6 +51,16 @@ export const supplierSlice = createSlice({ }) .addCase(thunks.updateSupplier.rejected, (state, action) => { state.update = ApiResponse.error(action.payload); + }) + // Delete Supplier + .addCase(thunks.deleteSupplier.pending, (state) => { + state.delete = ApiResponse.loading(); + }) + .addCase(thunks.deleteSupplier.fulfilled, (state, action) => { + state.delete = ApiResponse.value(action.payload); + }) + .addCase(thunks.deleteSupplier.rejected, (state, action) => { + state.delete = ApiResponse.error(action.payload); }), }); diff --git a/src/state/suppliers/thunk.ts b/src/state/suppliers/thunk.ts index 03a3e228a..98a634ca9 100644 --- a/src/state/suppliers/thunk.ts +++ b/src/state/suppliers/thunk.ts @@ -30,3 +30,12 @@ export const updateSupplier = createAsyncThunk( .toPromise() .catch((error) => thunkApi.rejectWithValue(error.response)) ); + +export const deleteSupplier = createAsyncThunk( + "suppliers/deleteSupplier", + async (id: number, thunkApi) => + api + .deleteSupplier({ id }) + .toPromise() + .catch((error) => thunkApi.rejectWithValue(error.response)) +); diff --git a/src/state/suppliers/types.ts b/src/state/suppliers/types.ts index bc9e2ae7a..e894bf571 100644 --- a/src/state/suppliers/types.ts +++ b/src/state/suppliers/types.ts @@ -5,5 +5,5 @@ export type ISupplierState = { supplierList: ApiResponse>; create: ApiResponse; update: ApiResponse; - delete: ApiResponse; + delete: ApiResponse; };