diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json
index c17c938..0a1c31b 100644
--- a/public/locales/fa/app.json
+++ b/public/locales/fa/app.json
@@ -250,5 +250,15 @@
"delete_tooltip": "حذف",
"update_tooltip": "ویرایش",
"update_expert": "ویرایش کارشناس"
+ },
+ "CallHistory": {
+ "category_name": "موضوع",
+ "subcategory_name": "زیر موضوع",
+ "operator": "اپراتور",
+ "date": "تاریخ",
+ "call_history_of": "تاریخچه تماس های",
+ "call_history_not_found": "تاریخچه ای برای تماس دریافتی یافت نشد",
+ "call_history_error_fetching": "خطا در دریافت تاریخچه تماس دریافتی",
+ "show_more": "نمایش موارد بیشتر"
}
}
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty/__tests__/index.test.js b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty/__tests__/index.test.js
new file mode 100644
index 0000000..91d5651
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty/__tests__/index.test.js
@@ -0,0 +1,19 @@
+import {render, screen} from "@testing-library/react";
+import ErrorOrEmpty from "../../ErrorOrEmpty";
+import MockAppWithProviders from "../../../../../../../../../../../mocks/AppWithProvider";
+
+describe("ErrorOrEmpty Component From call history", () => {
+ describe("Rendering", () => {
+ it("error fetching history of call text rendered", () => {
+ render();
+ const errorText = screen.queryByText('خطا در دریافت تاریخچه تماس دریافتی');
+ expect(errorText).toBeInTheDocument();
+ });
+ it("empty fetching history of call text rendered", () => {
+ render();
+ const emptyText = screen.queryByText('تاریخچه ای برای تماس دریافتی یافت نشد');
+ expect(emptyText).toBeInTheDocument();
+
+ });
+ });
+});
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty/index.jsx
new file mode 100644
index 0000000..bb0f818
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty/index.jsx
@@ -0,0 +1,33 @@
+import {useTranslations} from "next-intl";
+import {Typography} from "@mui/material";
+
+const ErrorOrEmpty = ({isErrorOrEmpty}) => {
+ const t = useTranslations();
+ return (
+ <>
+ {isErrorOrEmpty === "error" ?
+
+ {t("CallHistory.call_history_error_fetching")}
+
+ : isErrorOrEmpty === "empty" ?
+
+ {t("CallHistory.call_history_not_found")}
+ : <>>
+ }
+ >
+ )
+}
+
+export default ErrorOrEmpty
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/HistoryHeader/__tests__/index.test.js b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/HistoryHeader/__tests__/index.test.js
new file mode 100644
index 0000000..51d700e
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/HistoryHeader/__tests__/index.test.js
@@ -0,0 +1,21 @@
+import {render, screen} from "@testing-library/react";
+import HistoryHeader from "../../HistoryHeader";
+import MockAppWithProviders from "../../../../../../../../../../../mocks/AppWithProvider";
+
+describe("HistoryHeader Component From call history", () => {
+ describe("Rendering", () => {
+ const tab = {
+ phone_number: "09111111111"
+ }
+ it("text of header rendered", () => {
+ render();
+ const textHeader = screen.queryByText(/تاریخچه تماس های/i);
+ expect(textHeader).toBeInTheDocument();
+ });
+ it("caller number in header rendered", () => {
+ render();
+ const callerNumber = screen.queryByText(/09111111111/i);
+ expect(callerNumber).toBeInTheDocument();
+ });
+ });
+});
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/HistoryHeader/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/HistoryHeader/index.jsx
new file mode 100644
index 0000000..21a3270
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/HistoryHeader/index.jsx
@@ -0,0 +1,25 @@
+import {useTranslations} from "next-intl";
+import {Stack, Typography} from "@mui/material";
+
+const HistoryHeader = ({tab}) => {
+ const t = useTranslations();
+ return (
+
+
+ .... {t("CallHistory.call_history_of")}:
+
+
+ {tab.phone_number} ....
+
+
+ )
+}
+
+export default HistoryHeader
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData/__tests__/index.test.js b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData/__tests__/index.test.js
new file mode 100644
index 0000000..4fd4519
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData/__tests__/index.test.js
@@ -0,0 +1,22 @@
+import {render, screen} from "@testing-library/react";
+import MockAppWithProviders from "../../../../../../../../../../../../mocks/AppWithProvider";
+import PreviousOperatorData from "../../PreviousOperatorData";
+
+describe("PreviousOperatorData Component From call history", () => {
+ describe("Rendering", () => {
+ const historyItem = {
+ operator_name: "test name",
+ answer_date: "test date"
+ }
+ it("operator name rendered", () => {
+ render();
+ const operatorName = screen.queryByText("test name");
+ expect(operatorName).toBeInTheDocument();
+ });
+ it("operator answer date rendered", () => {
+ render();
+ const operatorAnswerDate = screen.queryByText("test date");
+ expect(operatorAnswerDate).toBeInTheDocument();
+ });
+ });
+});
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData/index.jsx
new file mode 100644
index 0000000..afd2ad7
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData/index.jsx
@@ -0,0 +1,28 @@
+import {useTranslations} from "next-intl";
+import {Avatar, Box, ListItem, ListItemAvatar, ListItemText, Typography} from "@mui/material";
+import HeadsetMicIcon from '@mui/icons-material/HeadsetMic';
+
+const PreviousOperatorData = ({historyItem}) => {
+ const t = useTranslations();
+ return (
+
+
+
+
+
+
+
+
+ {historyItem.operator_name}
+
+
+ ({t("CallHistory.operator")})
+
+
+ } secondary={historyItem.answer_date}/>
+
+ )
+}
+
+export default PreviousOperatorData
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics/__tests__/index.test.js b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics/__tests__/index.test.js
new file mode 100644
index 0000000..d9d77e4
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics/__tests__/index.test.js
@@ -0,0 +1,22 @@
+import {render, screen} from "@testing-library/react";
+import MockAppWithProviders from "../../../../../../../../../../../../mocks/AppWithProvider";
+import Topics from "../../Topics";
+
+describe("Topics Component From call history", () => {
+ describe("Rendering", () => {
+ const historyItem = {
+ category_name: "test category",
+ subcategory_name: "test sub category"
+ }
+ it("operator name rendered", () => {
+ render();
+ const operatorName = screen.queryByText("test category");
+ expect(operatorName).toBeInTheDocument();
+ });
+ it("operator answer date rendered", () => {
+ render();
+ const operatorAnswerDate = screen.queryByText("test sub category");
+ expect(operatorAnswerDate).toBeInTheDocument();
+ });
+ });
+});
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics/index.jsx
new file mode 100644
index 0000000..3b57744
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics/index.jsx
@@ -0,0 +1,43 @@
+import {useTranslations} from "next-intl";
+import {Box, List, ListItem, Typography} from "@mui/material";
+
+const Topics = ({historyItem}) => {
+ const t = useTranslations();
+ return (
+
+
+
+
+
+ {t("CallHistory.category_name")}:
+
+
+ {historyItem.category_name}
+
+
+
+
+
+
+
+
+ {t("CallHistory.subcategory_name")}:
+
+
+ {historyItem.subcategory_name}
+
+
+
+
+
+ )
+}
+
+export default Topics
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/index.jsx
new file mode 100644
index 0000000..7af4fd5
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/index.jsx
@@ -0,0 +1,21 @@
+import {useTranslations} from "next-intl";
+import {Grow, List} from "@mui/material";
+import PreviousOperatorData from "./PreviousOperatorData";
+import Topics from "./Topics";
+
+const ListItemOfCalls = ({historyItem}) => {
+ const t = useTranslations();
+
+ // console.log(historyItem)
+
+ return (
+
+
+
+
+
+
+ )
+}
+
+export default ListItemOfCalls
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/LoadingHistory/__tests__/intex.test.js b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/LoadingHistory/__tests__/intex.test.js
new file mode 100644
index 0000000..1592a02
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/LoadingHistory/__tests__/intex.test.js
@@ -0,0 +1,68 @@
+import {render, screen} from "@testing-library/react";
+import LoadingHistory from "../../LoadingHistory";
+import MockAppWithProviders from "../../../../../../../../../../../mocks/AppWithProvider";
+
+describe("LoadingHistory Component From call history", () => {
+ describe("Rendering", () => {
+ it("loading list rendered", () => {
+ render();
+ const loadingList = screen.queryByTestId("loading-list");
+ expect(loadingList).toBeInTheDocument();
+ });
+ it("loading list item avatar rendered", () => {
+ render();
+ const loadingListItemAvatar = screen.queryByTestId("loading-listItemAvatar");
+ expect(loadingListItemAvatar).toBeInTheDocument();
+ });
+ it("loading list item text rendered", () => {
+ render();
+ const loadingListItemText = screen.queryByTestId("loading-listItemText");
+ expect(loadingListItemText).toBeInTheDocument();
+ });
+ it("loading list item category rendered", () => {
+ render();
+ const loadingListItemCat = screen.queryByTestId("loading-listItem-cat");
+ expect(loadingListItemCat).toBeInTheDocument();
+ });
+ it("loading list item sub category rendered", () => {
+ render();
+ const loadingListItemSubCat = screen.queryByTestId("loading-listItem-subCat");
+ expect(loadingListItemSubCat).toBeInTheDocument();
+ });
+ it("operator avatar skeleton rendered", () => {
+ render();
+ const operatorAvatarSkeleton = screen.queryByTestId("operator-avatar-skeleton");
+ expect(operatorAvatarSkeleton).toBeInTheDocument();
+ });
+ it("operator name skeleton rendered", () => {
+ render();
+ const operatorNameSkeleton = screen.queryByTestId("operator-name-skeleton");
+ expect(operatorNameSkeleton).toBeInTheDocument();
+ });
+ it("operator answer date skeleton rendered", () => {
+ render();
+ const operatorAnswerDateSkeleton = screen.queryByTestId("operator-answer-date-skeleton");
+ expect(operatorAnswerDateSkeleton).toBeInTheDocument();
+ });
+ it("operator category header skeleton rendered", () => {
+ render();
+ const operatorCategoryHeaderSkeleton = screen.queryByTestId("operator-category-header-skeleton");
+ expect(operatorCategoryHeaderSkeleton).toBeInTheDocument();
+ });
+ it("operator category value skeleton rendered", () => {
+ render();
+ const operatorCategoryValueSkeleton = screen.queryByTestId("operator-category-value-skeleton");
+ expect(operatorCategoryValueSkeleton).toBeInTheDocument();
+ });
+ it("operator subCategory header skeleton rendered", () => {
+ render();
+ const operatorSubCategoryHeaderSkeleton = screen.queryByTestId("operator-subCategory-header-skeleton");
+ expect(operatorSubCategoryHeaderSkeleton).toBeInTheDocument();
+ });
+ it("operator subCategory value skeleton rendered", () => {
+ render();
+ const operatorSubCategoryValueSkeleton = screen.queryByTestId("operator-subCategory-value-skeleton");
+ expect(operatorSubCategoryValueSkeleton).toBeInTheDocument();
+ });
+ });
+});
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/LoadingHistory/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/LoadingHistory/index.jsx
new file mode 100644
index 0000000..2c9900e
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/LoadingHistory/index.jsx
@@ -0,0 +1,86 @@
+import {useTranslations} from "next-intl";
+import {Box, List, ListItem, ListItemAvatar, ListItemText, Skeleton} from "@mui/material";
+
+const LoadingHistory = () => {
+ const t = useTranslations();
+ return (
+ <>
+
+
+
+
+
+
+
+
+ } secondary={
+
+ }/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+
+ )
+}
+
+export default LoadingHistory
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/index.jsx
index 048c091..c83bc49 100644
--- a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/index.jsx
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/index.jsx
@@ -1,6 +1,64 @@
+import {useTranslations} from "next-intl";
+import {Box, Chip, Divider, Stack} from "@mui/material";
+import HeadphonesIcon from '@mui/icons-material/Headphones';
+import LoadingHistory from "./LoadingHistory";
+import HistoryHeader from "./HistoryHeader";
+import ErrorOrEmpty from "./ErrorOrEmpty";
+import useCallerHistory from "@/lib/callWidget/hooks/useCallerHistory";
+import ListItemOfCalls from "./ListItemOfCalls";
+import {useState} from "react";
+
+const max_size = 10;
const CallHistory = ({tab}) => {
+ const t = useTranslations();
+ const {
+ firstItemOfHistory,
+ historyList,
+ isLoadingHistoryList,
+ errorHistoryList
+ } = useCallerHistory(tab.id, tab.phone_number, max_size);
+ const [showRestOfHistory, setShowRestOfHistory] = useState(false);
+
return (
- <>CallHistory - {tab.id}>
+
+
+
+ {errorHistoryList ? (
+
+ ) : isLoadingHistoryList ? (
+
+ ) : !firstItemOfHistory ? (
+
+ ) : (
+
+
+ {historyList && (
+
+ }
+ onClick={() => setShowRestOfHistory(true)}
+ label={t("show_more")}
+ disabled={showRestOfHistory}
+ />
+
+ )}
+ {showRestOfHistory && (
+ <>
+ {historyList.map((historyItem, index) => (
+ <>
+
+
+ >
+ ))}
+ >)
+ }
+
+ )}
+
+
)
}
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/index.jsx
index 79dc736..8fc1d87 100644
--- a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/index.jsx
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/index.jsx
@@ -1,15 +1,19 @@
-import {Grid} from "@mui/material";
+import {Divider, Grid} from "@mui/material";
import CallActions from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallActions";
import CallHistory from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory";
const CallTabPanel = ({tab}) => {
return (
-
-
+
+
+
+
diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js
index 19534ca..127d1df 100644
--- a/src/core/data/apiRoutes.js
+++ b/src/core/data/apiRoutes.js
@@ -16,6 +16,10 @@ export const GET_ROLE_LIST = BASE_URL + "/api/roles/list";
export const GET_PROVINCE_LIST = BASE_URL + "/api/provinces";
// province list
+// province list
+export const GET_CALLER_HISTORY = BASE_URL + "/api/calls/list";
+// province list
+
//change password
export const SET_USER_PASSWORD = BASE_URL + "/api/profile/change_password";
//end change password
diff --git a/src/lib/callWidget/hooks/useCallerHistory.jsx b/src/lib/callWidget/hooks/useCallerHistory.jsx
new file mode 100644
index 0000000..68ee6d0
--- /dev/null
+++ b/src/lib/callWidget/hooks/useCallerHistory.jsx
@@ -0,0 +1,37 @@
+import useRequest from "@/lib/app/hooks/useRequest";
+import {useEffect, useState} from "react";
+import useSWR from "swr";
+import {GET_CALLER_HISTORY} from "@/core/data/apiRoutes";
+
+const useCallerHistory = (call_id, phone_number, max_size) => {
+ const requestServer = useRequest({auth: true, notification: false});
+ const [validData, setValidData] = useState([]);
+
+ //swr config
+ const fetcher = (...args) => {
+ return requestServer(args, 'get').then(({data}) => {
+ return data.data;
+ }).catch(() => {
+ })
+ };
+
+ const {data, isLoading} = useSWR(`${GET_CALLER_HISTORY}?phone_number=${phone_number}&size=${max_size}`, fetcher, {
+ revalidateIfStale: false,
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false,
+ keepPreviousData: true
+ });
+
+ useEffect(() => {
+ data && setValidData(data.filter((item) => item.id != call_id));
+ }, [data, call_id]);
+
+ return {
+ firstItemOfHistory: validData.length === 0 ? false : validData[0],
+ historyList: validData.length < 2 ? false : validData.slice(1),
+ isLoadingHistoryList: true,
+ errorHistoryList: false
+ }
+};
+
+export default useCallerHistory;
\ No newline at end of file