diff --git a/src/api/api-util-functions.ts b/src/api/api-util-functions.ts index 02fa81f..be62960 100644 --- a/src/api/api-util-functions.ts +++ b/src/api/api-util-functions.ts @@ -9,6 +9,7 @@ import { history } from "../utils/history"; import { updateBot } from "./updateBot"; import { mapToSegment } from "./segment-mapping"; + export const onBotCreate = () => { const store: any = useStore.getState(); store.startLoading(); @@ -49,25 +50,27 @@ export const onBotCreate = () => { text: store?.state?.startingMessage, botId: res.data.result.id, }); - onMappingBotToSegment({ - queryParams: { - text: reqObj.startingMessage, - botId: res.data.result.id, - } - }).then((res) => { - if(store?.isBroadcastBot){ - onSegmentCreate() - } - else { - store?.stopLoading(); - store.onReset(); - history.navigate("/success"); - } + if (store?.isBroadcastBot) { + onMappingBotToSegment({ + queryParams: { + text: reqObj.startingMessage, + botId: res.data.result.id, + }, }) - .catch((err) => { - toast.error(err?.message); - store.stopLoading(); - }); + .then((res) => { + if (store?.isBroadcastBot) { + onSegmentCreate(); + } else { + store?.stopLoading(); + store.onReset(); + history.navigate("/success"); + } + }) + .catch((err) => { + toast.error(err?.message); + store.stopLoading(); + }); + } }) .catch((err) => { store?.stopLoading(); @@ -115,13 +118,6 @@ export const onSegmentCreate = () => { }); }; -export const afterBroadcastBotLogic = () => { - const store: any = useStore.getState(); - if (store?.conversationLogic.length <= store?.broadcastBotLogics.length) { - store?.setConversationLogic(store?.broadcastBotLogics); - onBotCreate(); - } -}; export const onStartConversation = (bot) => { const store: any = useStore.getState(); @@ -192,7 +188,7 @@ export const onCreateBroadcastBotLogic = () => { console.log({ store }); console.log({state:store.state}) for (const botLogic of store?.conversationLogic) { - console.log({ botLogic }); + const newBotLogic = { ...botLogic, adapter: process.env.REACT_APP_broadcastAdapterId, @@ -222,11 +218,8 @@ export const onCreateBroadcastBotLogic = () => { ], templateType: "JS_TEMPLATE_LITERALS", }, - }, ], - - }; // eslint-disable-next-line no-loop-func addLogic({ data: newBotLogic }) @@ -305,35 +298,38 @@ export const onBroadcastBotCreate=()=>{ } + + export const onBotUpdate = () => { const store: any = useStore.getState(); store?.startLoading(); const reqObj = { - ...store?.state, - isBroadcastBotEnabled: store?.isBroadcastBot, - users: [], - logic: [], + ...store?.editState, + id: store.state.id, }; - store?.userSegments.forEach((userSegment) => { - reqObj.users.push(userSegment.id); - }); - store?.conversationLogic.forEach((logic) => { - reqObj.logic.push(logic.id); - }); + + if (reqObj.startDate) { reqObj.startDate = moment(reqObj.startDate).format("YYYY-MM-DD"); } if (reqObj.endDate) { reqObj.endDate = moment(reqObj.endDate).format("YYYY-MM-DD"); } - + // const newData = omitBy(reqObj, isNull); + // console.log("bot update:", { reqObj, newData }); store?.startLoading(); updateBot(reqObj) .then((res) => { + console.log("bot update:", { res }); store?.stopLoading(); + toast.success("Bot Updated"); + store.stopLoading(); + store.onReset(); + history.navigate("/success"); }) .catch((err) => { + console.log("bot update:", { err }); store?.stopLoading(); console.log({ err }); }); diff --git a/src/api/getBots.ts b/src/api/getBots.ts index 6cebeca..87ca6c6 100644 --- a/src/api/getBots.ts +++ b/src/api/getBots.ts @@ -1,7 +1,7 @@ import axios from "axios"; import { searchBot } from "./urls"; import { getDefaultHeaders } from "./utils"; -import {omitBy,isNull} from 'lodash'; +import { omitBy, isNull } from "lodash"; export const getBots = (data: any) => { const url = searchBot; @@ -10,10 +10,17 @@ export const getBots = (data: any) => { ...getDefaultHeaders(), asset: "bot", }, - params: omitBy({ perPage: data.perPage, page: data.page ,name: data.name },isNull) , + params: omitBy( + { + perPage: data.perPage, + page: data.page, + name: data.name, + sortBy: data.sortBy, + orderBy: data.orderBy, + }, + isNull + ), }; return axios.get(url, config); }; - - diff --git a/src/api/updateBot.ts b/src/api/updateBot.ts index 638f419..c716b3f 100644 --- a/src/api/updateBot.ts +++ b/src/api/updateBot.ts @@ -1,6 +1,7 @@ import axios from "axios"; import { getUpdateBotUrl } from "./urls"; import { getDefaultHeaders } from "./utils"; +import {omit} from 'lodash' export const updateBot = (data: any) => { const url = getUpdateBotUrl(data?.id); @@ -11,5 +12,5 @@ export const updateBot = (data: any) => { }, }; - return axios.patch(url, data, config); + return axios.patch(url, omit (data,['id','segmentId']), config); }; diff --git a/src/components/addLogicModal/index.tsx b/src/components/addLogicModal/index.tsx index 0a3b2c3..357f809 100644 --- a/src/components/addLogicModal/index.tsx +++ b/src/components/addLogicModal/index.tsx @@ -14,6 +14,7 @@ import { MDBContainer, MDBCol, MDBSpinner, + MDBIcon, } from "mdb-react-ui-kit"; import { toast } from "react-hot-toast"; import { uploadForm } from "../../api/uploadForm"; @@ -21,6 +22,9 @@ import { addLogic } from "../../api/addLogic"; import { omitBy, isNull } from "lodash"; import { getUploadErrorMsg } from "../../utils"; import { useStore } from "../../store"; +import "./style.css"; +import FileModal from "../fileModal"; + const AddLogicModal: FC = ({ open, activeLogic = {}, @@ -31,6 +35,7 @@ const AddLogicModal: FC = ({ const [logics, setLogics] = useState([]); const [form, setForm] = useState(null); const [media, setMedia] = useState(null); + const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [cadencePerPage, setCadencePerPage] = useState(100); const [formId, setFormId] = useState(""); const [modalState, setModalState] = useState({ ...activeLogic }); @@ -81,6 +86,7 @@ const AddLogicModal: FC = ({ adapter: process.env.REACT_APP_adapterId, }; + addLogic({ data }) .then((res) => { const newLogic = [...logics, { ...res.data.result }]; @@ -103,10 +109,11 @@ const AddLogicModal: FC = ({ }, []); const onMediaChange = useCallback((event: any) => { - if (!event.target.files.length) { + const files = Array.from(event.target.files); + if (!files.length) { toast.error("No File Selected"); } - setMedia(event.target.files); + setMedia(files); }, []); const onFormUpload = useCallback( @@ -149,7 +156,36 @@ const AddLogicModal: FC = ({ ), [form, formId, modalState] ); - console.log("perpage_comp:",store?.cadencePerPage) + + // Handle file selection + const handleFileChange = (e) => { + if (!e.target.files.length) { + toast.error("No File Selected"); + } + const files = Array.from(e.target.files); + setMedia(files); + }; + + // Handle file removal + const handleFileRemove = (fileName) => { + //setIsDeleteModalOpen(true) + setMedia((prevSelectedFiles) => + prevSelectedFiles.filter((file) => file.name !== fileName) + ); + }; + + const confirmDelete = (ev, fileName) => { + const shouldDelete = window.confirm( + "Are you sure you want to delete this media?" + ); + if (shouldDelete) { + handleFileRemove(fileName); + } else { + ev.preventDefault(); + } + }; + + console.log({ media }); if (!open) return null; return ( @@ -180,7 +216,7 @@ const AddLogicModal: FC = ({ @@ -196,8 +232,6 @@ const AddLogicModal: FC = ({ > - {/* - */} @@ -210,16 +244,57 @@ const AddLogicModal: FC = ({ onChange={onOdkFormChange} /> + + + + {/* {renderSelectedFiles()} */} +
+
+ {media?.length > 0 ? ( + media.map((file) => ( +
+ + + {file.name} + + + {/* */} + + confirmDelete(ev,file.name)} + > + + +
+ )) + ) : ( +

No files selected.

+ )} +
+
+
@@ -260,6 +335,10 @@ const AddLogicModal: FC = ({ + setIsDeleteModalOpen(false)} + /> ); }; diff --git a/src/components/addLogicModal/style.css b/src/components/addLogicModal/style.css new file mode 100644 index 0000000..311b917 --- /dev/null +++ b/src/components/addLogicModal/style.css @@ -0,0 +1,36 @@ +/* FilePicker.css */ + +.file-picker { + /* width: 300px; */ + margin: auto; + + } + + .selected-files { + border: 1px solid #ccc; + border-radius: 5px; + padding: 10px; + } + + + .file-name { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 70%; + } + + .remove-btn { + background-color: #ff4444; + color: white; + border: none; + border-radius: 5px; + padding: 5px 10px; + cursor: pointer; + } + + .remove-btn:hover { + background-color: #ff0000; + } + \ No newline at end of file diff --git a/src/components/conversationFlow/index.tsx b/src/components/conversationFlow/index.tsx index 433b9c8..5f7d0e3 100644 --- a/src/components/conversationFlow/index.tsx +++ b/src/components/conversationFlow/index.tsx @@ -13,6 +13,7 @@ import emptyList from "../../assets/images/empty.svg"; const ConversationFlow: FC<{ compProps: any }> = ({ compProps }) => { const { conversationLogic, onToggle } = compProps; + return (

Conversation Flow

diff --git a/src/components/conversationSetup/index.tsx b/src/components/conversationSetup/index.tsx index 9873b93..17c0d30 100644 --- a/src/components/conversationSetup/index.tsx +++ b/src/components/conversationSetup/index.tsx @@ -12,15 +12,10 @@ import "react-datepicker/dist/react-datepicker.css"; import { useStore } from "../../store"; import moment from "moment"; - const ConversationSetup: FC<{ compProps: any }> = ({ compProps }) => { const store: any = useStore(); - - const { - onChangeHandler, - errors - } = compProps; - + + const { onChangeHandler, errors, disabled } = compProps; const onDateChangeHandler = useCallback( (data) => { onChangeHandler({ target: data }); @@ -33,15 +28,57 @@ const ConversationSetup: FC<{ compProps: any }> = ({ compProps }) => { {/*

Conversation Setup

*/} +
+

Bot Icon

+ + {store?.state.botImage && ( + +
+ bot-icon +
+
+ )} + store?.setBotIcon(ev.target?.files?.[0])} + /> +
+
{errors.name && (
{errors?.name}
@@ -53,9 +90,9 @@ const ConversationSetup: FC<{ compProps: any }> = ({ compProps }) => { //@ts-ignore onChange={onChangeHandler} name="description" - value={store?.state?.description || ''} + value={store?.state?.description || ""} rows={4} - size='md' + size="md" /> {/*
Name Not Available @@ -67,8 +104,8 @@ const ConversationSetup: FC<{ compProps: any }> = ({ compProps }) => { type="text" onChange={onChangeHandler} name="purpose" - value={store?.state?.purpose || ''} - size='md' + value={store?.state?.purpose || ""} + size="md" /> {/*
Name Not Available @@ -81,7 +118,7 @@ const ConversationSetup: FC<{ compProps: any }> = ({ compProps }) => { onChange={onChangeHandler} name="startingMessage" value={store?.state?.startingMessage} - size='md' + size="md" /> {errors?.startingMessage && (
Message Not Available
@@ -94,65 +131,47 @@ const ConversationSetup: FC<{ compProps: any }> = ({ compProps }) => { checked={store?.isBroadcastBot} onChange={(ev) => store?.setIsBroadcastBot(ev.target.checked)} id="flexCheckDefault" - label="Create Broadcast bot" + label="Create Whatsapp bot" size={5} defaultChecked + disabled={disabled} /> -
- {/*
+
+ {/*
Name Not Available
*/} -
- + - -
+
*/}
- - onDateChangeHandler({ name: "startDate", value }) - } - customInput={} - /> + + onDateChangeHandler({ name: "startDate", value }) + } + customInput={} + />
- - onDateChangeHandler({ name: "endDate", value }) - } - customInput={} - /> -
- - -
-

Bot Icon

- store?.setBotIcon(ev.target?.files?.[0])} + onDateChangeHandler({ name: "endDate", value })} + customInput={} />
- {/* {state.botImage && - bot-icon - } */} ); }; diff --git a/src/components/fileModal/index.tsx b/src/components/fileModal/index.tsx new file mode 100644 index 0000000..b14c29c --- /dev/null +++ b/src/components/fileModal/index.tsx @@ -0,0 +1,47 @@ +import { useState } from "react"; + +import { + MDBBtn, + MDBModal, + MDBModalDialog, + MDBModalContent, + MDBModalHeader, + MDBModalTitle, + MDBModalBody, + MDBModalFooter, +} from "mdb-react-ui-kit"; + +const FileModal = ({open,onClose}) => { + const [basicModal, setBasicModal] = useState(false); + const toggleShow = () => onClose(); + + return ( + + + + + Delete Media + + + + + + + + + + Close + + Save changes + + + + + ); +}; + +export default FileModal; diff --git a/src/components/table/index.tsx b/src/components/table/index.tsx index e8c0283..cf9d19e 100644 --- a/src/components/table/index.tsx +++ b/src/components/table/index.tsx @@ -9,12 +9,14 @@ import { MDBDropdownToggle, MDBDropdownMenu, MDBDropdownItem, + MDBIcon, } from "mdb-react-ui-kit"; import { toast } from "react-hot-toast"; import { getBotUrl } from "../../utils"; import { useNavigate } from "react-router-dom"; import { startConversation } from "../../api/startConversation"; import { useStore } from "../../store"; +import { updateBot } from "../../api/updateBot"; export const Table: FC<{ data: Array }> = ({ data }) => { const navigate = useNavigate(); @@ -31,24 +33,32 @@ export const Table: FC<{ data: Array }> = ({ data }) => { ); const onEdit = useCallback( - (data) => { + (data) => { localStorage.setItem("botToEdit", JSON.stringify(data)); store?.setBotToEdit(data); store?.setConversationLogic(data?.logicIDs); - setTimeout(() => navigate("/add-bot?edit=true", { state: data }), 20); + setTimeout(() => navigate(`/add-bot?bot=${data.id}`, { state: data }), 20); }, [navigate, store] ); const onEnable = useCallback((data) => { - startConversation(data) - .then((res) => { - toast.success("Bot Enabled"); - }) - .catch((err) => { - toast.error(err.message); - }); - }, []); + console.log({data}) + store.startLoading(); + const newValue={id:data.id , status : data.status === 'DISABLED' ? 'ENABLED' : 'DISABLED'} + + updateBot(newValue).then(res=>{ + store.stopLoading(); + const toastMsg= data.status === 'DISABLED' ? 'Bot Enabled Succesfully' : 'Bot Disabled Succesfully' + toast.success(toastMsg); + window.location.reload(); + console.log({res}) + }).catch(err=>{ + store.stopLoading(); + toast.error(`Error occured in updating bot-${err.message}`) + console.log({err}); + }) + }, [store]); return ( @@ -113,7 +123,7 @@ export const Table: FC<{ data: Array }> = ({ data }) => { }) )} > - Copy + @@ -123,34 +133,32 @@ export const Table: FC<{ data: Array }> = ({ data }) => { size="sm" onClick={onCopy(record?.id)} > - Copy + - - - Action + + + { ev.preventDefault(); - // onEdit(record); + onEdit(record); }} - disabled + > Edit - {/* Delete + { ev.preventDefault(); onEnable(record); - }}>Enable */} + }}>{record?.status === 'DISABLED' ? 'Enable' : 'Disable'} diff --git a/src/index.css b/src/index.css index a67c038..cb7932a 100644 --- a/src/index.css +++ b/src/index.css @@ -27,4 +27,22 @@ code { } .form-label { +} + +.fas .fa-ellipsis-v::before { + +} + +.dropend .dropdown-toggle::after { + vertical-align: 0; +} +.no-icon > .dropend .dropdown-toggle::after { + display: none !important; + margin-left: .255em; + vertical-align: .255em; + content: ""; + border-top: .3em solid transparent; + border-right: 0; + border-bottom: .3em solid transparent; + border-left: .3em solid; } \ No newline at end of file diff --git a/src/pages/add/index.jsx b/src/pages/add/index.jsx index e482720..7ce7d72 100644 --- a/src/pages/add/index.jsx +++ b/src/pages/add/index.jsx @@ -19,108 +19,135 @@ import { toast } from "react-hot-toast"; import ConversationSetup from "../../components/conversationSetup"; import ConversationFlow from "../../components/conversationFlow"; -import { useLocation, useSearchParams } from "react-router-dom"; +import { useSearchParams } from "react-router-dom"; import { onBotCreate, onBotUpdate } from "../../api/api-util-functions"; import { useStore } from "../../store"; +import { getBotById } from "../../api/getBotById"; export const Add = () => { const store = useStore(); - const location = useLocation(); - const [isFirstLoad, setIsFirstLoad] = useState(true); - const [searchParams] = useSearchParams(); + const [searchParams] = useSearchParams(); const [isStep1, setIsStep1] = useState(true); + const [errors, setErrors] = useState({}); const [open, setOpen] = useState(false); - const [isEdit, setIsEdit] = useState(false); const onToggle = useCallback(() => setOpen((prev) => !prev), []); + const isEditParamAvailable = useMemo( + () => (searchParams.get("bot") ? true : false), + [searchParams] + ); + const onChangeHandler = useCallback( (ev) => { + if (isEditParamAvailable) { + store.setEditState({ + ...store.editState, + [ev.target.name]: ev.target.value, + }); + } store.setState({ ...store.state, [ev.target.name]: ev.target.value }); }, - [store] + [store, isEditParamAvailable] ); - const isEditParamAvailable = useMemo( - () => searchParams.get("edit") === "true", - [searchParams] + const onSubmitHandler = useCallback( + (ev) => { + ev.preventDefault(); + if (isEditParamAvailable) onBotUpdate(); + else onBotCreate(false, false); + }, + [isEditParamAvailable] ); - const onSubmitHandler = useCallback((ev) => { - ev.preventDefault(); - if(isEditParamAvailable ) - onBotUpdate(); - else onBotCreate(false, false); - }, [isEditParamAvailable]); - - useEffect(() => { - if (isEditParamAvailable && isFirstLoad) { - setIsEdit(true); - var data; - if (location.state) { - data = location.state; - } else if (localStorage.getItem("botToEdit")) { - data = JSON.parse(localStorage.getItem("botToEdit")); - } - store?.setState({ - // ...store?.state, - ...data, - startDate: new Date(data.startDate), - endDate: new Date(data.endDate), - description: data.description || "", - purpose: data.purpose || "", - }); - setIsFirstLoad(false); + if (searchParams.get("bot")) { + getBotById(searchParams.get("bot")) + .then((res) => { + const data = { + // ...store?.state, + ...res.data.result, + startDate: new Date(res?.data?.result?.startDate), + endDate: new Date(res?.data?.result?.endDate), + description: res?.data?.result?.description || "", + purpose: res?.data?.result?.purpose || "", + }; + console.log("venom res vv:", { data }); + store?.setState({ + ...data, + }); + store?.setBotToEdit(data); + store?.setConversationLogic(data?.logicIDs); + store?.setBotIcon(data?.botImage); + }) + .catch((error) => { + console.log("venom", { error }); + }); } - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isEditParamAvailable, location.state, store?.setState,isFirstLoad]); - - - const onCheckDuplicateName = useCallback(({ name }) => { - if (name !== "" && name!==store?.botToEdit?.name) - checkDuplicateName({ - name, - }).then((res) => { - - - if (res?.data?.result?.data?.length > 0) { - setErrors((prev) => ({ ...prev, name: "Name Not Available" })); - } else { - setErrors((prev) => ({ ...prev, name: null })); - } - }); - }, [store?.botToEdit?.name]); - - const onCheckDuplicateStartingMsg = useCallback(({ startingMessage }) => { - if (startingMessage !== "" && startingMessage!==store?.botToEdit?.startingMessage) - checkDuplicateName({ - startingMessage, - }).then((res) => { - if (res?.data?.result?.data?.length > 0) { - setErrors((prev) => ({ - ...prev, - startingMessage: "Staring Message Not Available", - })); - } else { - setErrors((prev) => ({ ...prev, startingMessage: null })); - } - }); - }, [store?.botToEdit?.startingMessage]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + searchParams, + store?.setState, + store?.setBotToEdit, + store?.setConversationLogic, + store?.setBotIcon, + ]); + + const onCheckDuplicateName = useCallback( + ({ name }) => { + if (name !== "" && name !== store?.botToEdit?.name) { + checkDuplicateName({ + name, + }).then((res) => { + if (res?.data?.result?.data?.length > 0) { + setErrors((prev) => ({ ...prev, name: "Name Not Available" })); + } else { + setErrors((prev) => ({ ...prev, name: null })); + } + }); + } + }, + [store?.botToEdit] + ); + + const onCheckDuplicateStartingMsg = useCallback( + ({ startingMessage }) => { + if ( + startingMessage !== "" && + startingMessage !== store?.botToEdit?.startingMessage + ) + checkDuplicateName({ + startingMessage, + }).then((res) => { + if (res?.data?.result?.data?.length > 0) { + setErrors((prev) => ({ + ...prev, + startingMessage: "Staring Message Not Available", + })); + } else { + setErrors((prev) => ({ ...prev, startingMessage: null })); + } + }); + }, + [store?.botToEdit?.startingMessage] + ); useEffect(() => { onCheckDuplicateName({ name: store?.state.name }); onCheckDuplicateStartingMsg({ startingMessage: store?.state.startingMessage, }); + return () => { + setErrors({}); + }; }, [ onCheckDuplicateName, onCheckDuplicateStartingMsg, store?.state?.name, store?.state.startingMessage, + store?.state, ]); useEffect(() => { @@ -134,7 +161,7 @@ export const Add = () => { err.message || "Something went wrong in fetching segment count" ); }); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps }, [store?.state.segmentId, store?.setSegmentCount]); const compProps = useMemo( @@ -142,30 +169,52 @@ export const Add = () => { state: store?.state, onChangeHandler, errors, + disabled: isEditParamAvailable, isBroadcastBot: store?.isBroadcastBot, setIsBroadcastBot: store?.setIsBroadcastBot, setBotIcon: store?.setBotIcon, }), - [errors, onChangeHandler, store] + [ + errors, + isEditParamAvailable, + onChangeHandler, + store?.isBroadcastBot, + store?.setBotIcon, + store?.setIsBroadcastBot, + store?.state, + ] ); const step2CompProps = useMemo( - () => ({ conversationLogic: store?.conversationLogic, onToggle }), - [store?.conversationLogic, onToggle] + () => ({ + conversationLogic: store?.conversationLogic, + onToggle, + disabled: isEditParamAvailable, + }), + [store?.conversationLogic, onToggle, isEditParamAvailable] ); - const isNextDisabled = useMemo( - () => + const isNextDisabled = useMemo(() => { + if (isEditParamAvailable) { + return false; + } + return ( Object.values(errors).some((v) => v !== null) || Object.values( store?.isBroadcastBot ? store?.state : omit(store?.state, ["segmentId"]) ).some((v) => v === "" || v === undefined || v === null) || store?.botIcon === "" || - store?.botIcon === null, - [errors, store?.state, store?.botIcon, store?.isBroadcastBot] - ); + store?.botIcon === null + ); + }, [ + errors, + store?.state, + store?.botIcon, + store?.isBroadcastBot, + isEditParamAvailable, + ]); return ( - + <> @@ -181,9 +230,12 @@ export const Add = () => { -
ev.preventDefault()}> - {isStep1 && } - {!isStep1 && } + ev.preventDefault()}> + {isStep1 ? ( + + ) : ( + + )} @@ -204,7 +256,7 @@ export const Add = () => { onClick={onSubmitHandler} disabled={store?.conversationLogic.length === 0} > - {isEditParamAvailable ? 'Update' : 'Submit'} + {isEditParamAvailable ? "Update" : "Submit"} )} diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index a3e57a0..72cc175 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import { getBots } from "../../api/getBots"; import { toast } from "react-hot-toast"; import { Table } from "../../components/table"; @@ -6,6 +6,10 @@ import { MDBBtn, MDBCol, MDBContainer, + MDBDropdown, + MDBDropdownItem, + MDBDropdownMenu, + MDBDropdownToggle, MDBIcon, MDBRow, } from "mdb-react-ui-kit"; @@ -13,39 +17,66 @@ import Pagination from "../../components/pagination"; import { useNavigate } from "react-router-dom"; import { useStore } from "../../store"; +const getSortTypeLabel = (value: string) => { + switch (value) { + case "status": + return "Status"; + case "createdAt": + return "Date Created"; + case "endDate": + return "Date Expired"; + default: + return "Name"; + } +}; + export const Dashboard = () => { const store: any = useStore(); const [page, setPage] = useState(1); - const [searchText, setSearchText] = useState(''); + const [searchText, setSearchText] = useState(""); const [perPage, setPerPage] = useState(10); + const [sortBy, setSortBy] = useState("createdAt"); + const [orderBy, setOrderBy] = useState("desc"); const [botList, setBotList] = useState([]); const [totalRecords, setTotalRecords] = useState(0); const navigate = useNavigate(); - useEffect(() => { store?.startLoading(); - const data = searchText.length > 0 ? {name:searchText} : {perPage, page}; + const data = + searchText.length > 0 + ? { name: searchText, sortBy, orderBy } + : { perPage, page, sortBy, orderBy }; getBots(data) .then((res) => { store?.stopLoading(); setBotList(res?.data?.result?.data); setTotalRecords(res?.data?.result?.totalCount || 0); - if(searchText.length >0 ){ + if (searchText.length > 0) { setPage(1); - setPerPage(10) + setPerPage(10); } }) .catch((err) => { store?.stopLoading(); toast.error(err.message); }); - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [page, perPage, store.startLoading, store?.stopLoading,searchText]); - - + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [page, perPage, store.startLoading, store?.stopLoading, searchText,orderBy,sortBy]); + + const onSortChange = useCallback( + (sortValue) => () => { + setSortBy(sortValue); + }, + [] + ); + + const sortLabel = useMemo(() => getSortTypeLabel(sortBy), [sortBy]); + const orderByIcon = useMemo( + () => (orderBy === "desc" ? "sort-amount-down" : "sort-amount-up"), + [orderBy] + ); return ( @@ -57,24 +88,82 @@ export const Dashboard = () => { placeholder="Search" aria-label="Search" value={searchText} - onChange={ev=>setSearchText(ev.target.value)} + onChange={(ev) => setSearchText(ev.target.value)} /> Search
- navigate("/add-bot")}> + + + {sortLabel}   + + + + Name + + + Status + + + Date Created + + + Date Expired + + + + + + + +   + + + setOrderBy("desc")} + > + Descending + + setOrderBy("asc")} + > + Ascending + + + + + navigate("/add-bot")} className="mx-2">    Add - {/* null} className="mx-2"> + {/* null} className="mx-2">    Refresh */} -
-
+
({ endDate: null, startingMessage: "", }, + editState:{ + }, + setEditState:(newValue)=>set({editState:newValue}), setState: (newValue) => set({ state: newValue }), setCadencePerPage:(newValue)=>set({cadencePerPage:newValue}), segmentCount: 100,