diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 0a8a18b..c63ea15 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -3,5 +3,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/operator-dialogue/operator/page.js b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/operator-dialogue/operator/page.js
new file mode 100644
index 0000000..959a964
--- /dev/null
+++ b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/operator-dialogue/operator/page.js
@@ -0,0 +1,16 @@
+import WithPermission from "@/core/middlewares/withPermission";
+import OperatorDialoguePage from "@/components/dashboard/monitoring/operator/OperatorDialogue";
+
+export const metadata = {
+ title: "پیام های سیستمی",
+};
+
+const Page = () => {
+ return (
+
+
+
+ );
+};
+
+export default Page;
diff --git a/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/operator-dialogue/supervisor/page.js b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/operator-dialogue/supervisor/page.js
new file mode 100644
index 0000000..b295b8a
--- /dev/null
+++ b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/operator-dialogue/supervisor/page.js
@@ -0,0 +1,16 @@
+import WithPermission from "@/core/middlewares/withPermission";
+import OperatorDialoguePage from "@/components/dashboard/monitoring/supervisor/OperatorDialogue";
+
+export const metadata = {
+ title: "ارزیابی پیام های سیستمی",
+};
+
+const Page = () => {
+ return (
+
+
+
+ );
+};
+
+export default Page;
\ No newline at end of file
diff --git a/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/people-messages/operator/page.js b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/people-messages/operator/page.js
new file mode 100644
index 0000000..ec296d5
--- /dev/null
+++ b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/people-messages/operator/page.js
@@ -0,0 +1,16 @@
+import WithPermission from "@/core/middlewares/withPermission";
+import PeopleMessagePage from "@/components/dashboard/monitoring/operator/PeopleMessage";
+
+export const metadata = {
+ title: "پیام های سیستمی",
+};
+
+const Page = () => {
+ return (
+
+
+
+ );
+};
+
+export default Page;
diff --git a/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/people-messages/supervisor/page.js b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/people-messages/supervisor/page.js
new file mode 100644
index 0000000..8589b72
--- /dev/null
+++ b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/people-messages/supervisor/page.js
@@ -0,0 +1,16 @@
+import WithPermission from "@/core/middlewares/withPermission";
+import PeopleMessagePage from "@/components/dashboard/monitoring/supervisor/PeopleMessage";
+
+export const metadata = {
+ title: "پیام های سیستمی",
+};
+
+const Page = () => {
+ return (
+
+
+
+ );
+};
+
+export default Page;
diff --git a/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/system-messages/page.js b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/system-messages/operator/page.js
similarity index 93%
rename from src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/system-messages/page.js
rename to src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/system-messages/operator/page.js
index e298dbe..3d22265 100644
--- a/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/system-messages/page.js
+++ b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/system-messages/operator/page.js
@@ -1,5 +1,5 @@
import WithPermission from "@/core/middlewares/withPermission";
-import SystemMessagesPage from "@/components/dashboard/monitoring/SystemMessages";
+import SystemMessagesPage from "@/components/dashboard/monitoring/operator/SystemMessage";
export const metadata = {
title: "پیام های سیستمی",
diff --git a/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/system-messages/supervisor/page.js b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/system-messages/supervisor/page.js
new file mode 100644
index 0000000..e4ba1cb
--- /dev/null
+++ b/src/app/(withAuth)/(dashboardLayout)/dashboard/monitoring/system-messages/supervisor/page.js
@@ -0,0 +1,16 @@
+import WithPermission from "@/core/middlewares/withPermission";
+import SystemMessagesPage from "@/components/dashboard/monitoring/supervisor/SystemMessages";
+
+export const metadata = {
+ title: "پیام های سیستمی",
+};
+
+const Page = () => {
+ return (
+
+
+
+ );
+};
+
+export default Page;
diff --git a/src/components/dashboard/monitoring/operator/OperatorDialogue/DataTable.jsx b/src/components/dashboard/monitoring/operator/OperatorDialogue/DataTable.jsx
new file mode 100644
index 0000000..4f3b96b
--- /dev/null
+++ b/src/components/dashboard/monitoring/operator/OperatorDialogue/DataTable.jsx
@@ -0,0 +1,140 @@
+"use client";
+
+import DataTableWithAuth from "@/core/components/DataTableWithAuth";
+import { GET_OPERATOR_DIALOGUE_OPERATOR } from "@/core/utils/routes";
+import { Box } from "@mui/material";
+import { useMemo } from "react";
+import moment from "jalali-moment";
+import Player from "./Player";
+import CheckIcon from "@mui/icons-material/Check";
+import CloseIcon from "@mui/icons-material/Close";
+
+const DataTable = () => {
+ const columns = useMemo(
+ () => [
+ {
+ header: "تاریخ",
+ id: "date",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.calldate ? moment(row.original.calldate).locale("fa").format("yyyy/MM/DD") : <>->,
+ },
+ {
+ header: "ساعت",
+ id: "time",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.calldate ? moment(row.original.calldate).locale("fa").format("HH:mm") : <>->,
+ },
+ {
+ accessorKey: "src",
+ header: "شماره تماس گیرنده",
+ id: "src",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ accessorKey: "dst",
+ header: "کارشناس",
+ id: "dst",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "پخش صدا",
+ id: "is_listen",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) => {
+ const isListen = row.original.is_listen;
+ const Icon = isListen ? CheckIcon : CloseIcon;
+ const color = isListen ? "success.main" : "error.main";
+
+ return (
+
+
+
+ );
+ }
+ },
+ {
+ accessorKey: "disposition",
+ header: "وضعیت",
+ id: "disposition",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ accessorKey: "duration",
+ header: "طول تماس ( ثانیه )",
+ id: "duration",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "پخش صدا",
+ id: "player",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) => ,
+ },
+ ],
+ []
+ );
+
+ return (
+
+
+
+ );
+};
+export default DataTable;
diff --git a/src/components/dashboard/monitoring/SystemMessages/Player.jsx b/src/components/dashboard/monitoring/operator/OperatorDialogue/Player.jsx
similarity index 100%
rename from src/components/dashboard/monitoring/SystemMessages/Player.jsx
rename to src/components/dashboard/monitoring/operator/OperatorDialogue/Player.jsx
diff --git a/src/components/dashboard/monitoring/operator/OperatorDialogue/RateMessage.jsx b/src/components/dashboard/monitoring/operator/OperatorDialogue/RateMessage.jsx
new file mode 100644
index 0000000..c2ce7cd
--- /dev/null
+++ b/src/components/dashboard/monitoring/operator/OperatorDialogue/RateMessage.jsx
@@ -0,0 +1,153 @@
+"use client";
+
+import { Button, FormControl, FormHelperText, Grid, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
+import LtrTextField from "@/core/components/LtrTextField";
+import { Controller, useForm } from "react-hook-form";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { object, string, number } from "yup";
+import { GET_SYSTEM_MESSAGES_SUPERVISOR } from "@/core/utils/routes";
+import StyledForm from "@/core/components/StyledForm";
+import useRequest from "@/lib/hooks/useRequest";
+import usePermissionsList from "@/lib/hooks/usePermissionsList";
+import { useEffect } from "react";
+
+const RateMessage = ({ date, messageId, initialValues, mutate }) => {
+ const requestServer = useRequest({ notificationSuccess: true });
+
+ const defaultValues = {
+ supervisor_id: initialValues?.supervisor_id ?? "",
+ is_good: initialValues?.is_good ?? "",
+ description: initialValues?.description ?? "",
+ };
+
+ const validationSchema = object().shape({
+ supervisor_id: string().required("کارشناس بررسی کننده را مشخص کنید"),
+ is_good: string().required("نحوه پاسخگویی را مشخص کنید"),
+ description: string().optional(),
+ });
+
+ const {
+ control,
+ handleSubmit,
+ reset,
+ formState: { isSubmitting, errors, isDirty, isValid },
+ } = useForm({ defaultValues, resolver: yupResolver(validationSchema) });
+
+ const onSubmit = async (data) => {
+ const fixData = {
+ date: date,
+ cdr_unique_id: messageId,
+ supervisor_id: data.supervisor_id,
+ is_good: data.is_good,
+ ...(data.description !== "" && { description: data.description }),
+ };
+ try {
+ await requestServer(`${GET_SYSTEM_MESSAGES_SUPERVISOR}`, "post", {
+ data: fixData,
+ });
+ mutate();
+ reset({
+ supervisor_id: initialValues?.supervisor_id ?? "",
+ is_good: initialValues?.is_good ?? "",
+ description: initialValues?.description ?? "",
+ });
+ } catch (error) {}
+ };
+
+ useEffect(() => {
+ reset({
+ supervisor_id: initialValues?.supervisor_id ?? "",
+ is_good: initialValues?.is_good ?? "",
+ description: initialValues?.description ?? "",
+ });
+ }, [initialValues.supervisor_id, initialValues.is_good, initialValues.description]);
+
+ return (
+
+
+
+ {
+ return (
+
+ );
+ }}
+ name="supervisor_id"
+ />
+
+
+ {
+ return (
+
+ );
+ }}
+ name="is_good"
+ />
+
+
+ {
+ return (
+
+ );
+ }}
+ name="description"
+ />
+
+
+
+
+
+
+ );
+};
+
+export default RateMessage;
diff --git a/src/components/dashboard/monitoring/operator/OperatorDialogue/index.jsx b/src/components/dashboard/monitoring/operator/OperatorDialogue/index.jsx
new file mode 100644
index 0000000..cfbfef1
--- /dev/null
+++ b/src/components/dashboard/monitoring/operator/OperatorDialogue/index.jsx
@@ -0,0 +1,16 @@
+"use client";
+
+import PageTitle from "@/core/components/PageTitle";
+import { Stack } from "@mui/material";
+import DataTable from "./DataTable";
+
+const OperatorDialoguePage = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default OperatorDialoguePage;
diff --git a/src/components/dashboard/monitoring/operator/PeopleMessage/DataTable.jsx b/src/components/dashboard/monitoring/operator/PeopleMessage/DataTable.jsx
new file mode 100644
index 0000000..34dc021
--- /dev/null
+++ b/src/components/dashboard/monitoring/operator/PeopleMessage/DataTable.jsx
@@ -0,0 +1,167 @@
+"use client";
+
+import DataTableWithAuth from "@/core/components/DataTableWithAuth";
+import { GET_OPERATOR_PEOPLE_MESSAGE_OPERATOR } from "@/core/utils/routes";
+import { Box } from "@mui/material";
+import { useMemo } from "react";
+import moment from "jalali-moment";
+import Player from "./Player";
+import CloseIcon from '@mui/icons-material/Close';
+import CheckIcon from '@mui/icons-material/Check';
+import RateMessage from "./RateMessage";
+
+const DataTable = () => {
+ const columns = useMemo(
+ () => [
+ {
+ accessorKey: "id",
+ header: "کد یکتا",
+ id: "id",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "تاریخ",
+ id: "date",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.date ? moment(row.original.date).locale("fa").format("yyyy/MM/DD") : <>->,
+ },
+ {
+ header: "ساعت",
+ id: "time",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.date ? moment(row.original.date).locale("fa").format("HH:mm") : <>->,
+ },
+ {
+ accessorKey: "caller_phone_number",
+ header: "شماره تماس",
+ id: "caller_phone_number",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "پخش صدا",
+ id: "player",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) => ,
+ },
+ {
+ header: "پخش صدا",
+ id: "is_listen",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) => {
+ const isListen = row.original.is_listen;
+ const Icon = isListen ? CheckIcon : CloseIcon;
+ const color = isListen ? "success.main" : "error.main";
+
+ return (
+
+
+
+ );
+ }
+ },
+ {
+ accessorKey: "listen_at",
+ header: "زمان شنیده شدن",
+ id: "listen_at",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ accessorKey: "review_duration",
+ header: "زمان بررسی (دقیقه)",
+ id: "review_duration",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "ارزیابی",
+ id: "rate",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ cell, row, table }) => {
+ const mutate = table.options.meta?.mutate;
+
+ return (
+
+ );
+ },
+ },
+ ],
+ []
+ );
+
+ return (
+
+
+
+ );
+};
+export default DataTable;
diff --git a/src/components/dashboard/monitoring/operator/PeopleMessage/Player.jsx b/src/components/dashboard/monitoring/operator/PeopleMessage/Player.jsx
new file mode 100644
index 0000000..761e11b
--- /dev/null
+++ b/src/components/dashboard/monitoring/operator/PeopleMessage/Player.jsx
@@ -0,0 +1,45 @@
+"use client";
+
+import React from "react";
+import { IconButton, Box, Typography } from "@mui/material";
+import PlayArrowIcon from "@mui/icons-material/PlayArrow";
+import PauseIcon from "@mui/icons-material/Pause";
+import useWaveSurferPlayer from "@/lib/hooks/useWaveSurferPlayer";
+
+function formatTime(seconds) {
+ if (!seconds || isNaN(seconds)) return "0:00";
+ const minutes = Math.floor(seconds / 60);
+ const secs = Math.floor(seconds % 60);
+ return `${minutes}:${secs.toString().padStart(2, "0")}`;
+}
+
+const Player = ({ audioUrl }) => {
+ const { containerRef, isPlaying, playPause, currentTime, duration } =
+ useWaveSurferPlayer(audioUrl);
+
+ return (
+
+
+
+
+ {isPlaying ? (
+
+ ) : (
+
+ )}
+
+
+ {formatTime(currentTime)} / {formatTime(duration)}
+
+
+ );
+};
+
+export default Player;
diff --git a/src/components/dashboard/monitoring/operator/PeopleMessage/RateMessage.jsx b/src/components/dashboard/monitoring/operator/PeopleMessage/RateMessage.jsx
new file mode 100644
index 0000000..1844bad
--- /dev/null
+++ b/src/components/dashboard/monitoring/operator/PeopleMessage/RateMessage.jsx
@@ -0,0 +1,159 @@
+"use client";
+
+import { Button, FormControl, Grid, InputLabel, MenuItem, Select } from "@mui/material";
+import LtrTextField from "@/core/components/LtrTextField";
+import { Controller, useForm } from "react-hook-form";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { object, string } from "yup";
+import { GET_OPERATOR_PEOPLE_MESSAGE_OPERATOR } from "@/core/utils/routes";
+import StyledForm from "@/core/components/StyledForm";
+import useRequest from "@/lib/hooks/useRequest";
+import { useEffect } from "react";
+
+const RateMessage = ({ messageId, initialValues, mutate }) => {
+ const requestServer = useRequest({ notificationSuccess: true });
+
+ const defaultValues = {
+ savaneh_id: initialValues?.savaneh_id ?? "",
+ action_id: initialValues?.action_id ?? "",
+ description: initialValues?.description ?? "",
+ };
+
+ const validationSchema = object().shape({
+ savaneh_id: string().required("وضعیت کیفیت پیام را مشخص کنید"),
+ action_id: string().optional(),
+ description: string().optional(),
+ });
+
+ const {
+ control,
+ handleSubmit,
+ reset,
+ formState: { isSubmitting, errors, isDirty, isValid },
+ } = useForm({ defaultValues, resolver: yupResolver(validationSchema) });
+
+ const onSubmit = async (data) => {
+ const fixData = {
+ savaneh_id: parseInt(data.savaneh_id),
+ ...(data.action_id !== "" && { action_id: data.action_id }),
+ ...(data.description !== "" && { description: data.description }),
+ };
+ try {
+ await requestServer(`${GET_OPERATOR_PEOPLE_MESSAGE_OPERATOR}/${messageId}`, "post", {
+ data: fixData,
+ });
+ mutate();
+ reset({
+ savaneh_id: initialValues?.savaneh_id ?? "",
+ action_id: initialValues?.action_id ?? "",
+ description: initialValues?.description ?? "",
+ });
+ } catch (error) {}
+ };
+
+ useEffect(() => {
+ reset({
+ savaneh_id: initialValues?.savaneh_id ?? "",
+ action_id: initialValues?.action_id ?? "",
+ description: initialValues?.description ?? "",
+ });
+ }, [initialValues.savaneh_id, initialValues.action_id, initialValues.description]);
+
+ return (
+
+
+
+ {
+ return (
+
+
+ پیگیری
+
+
+
+ );
+ }}
+ name="savaneh_id"
+ />
+
+
+ {
+ return (
+
+ );
+ }}
+ name="action_id"
+ />
+
+
+ {
+ return (
+
+ );
+ }}
+ name="description"
+ />
+
+
+
+
+
+
+ );
+};
+
+export default RateMessage;
diff --git a/src/components/dashboard/monitoring/operator/PeopleMessage/index.jsx b/src/components/dashboard/monitoring/operator/PeopleMessage/index.jsx
new file mode 100644
index 0000000..81580e6
--- /dev/null
+++ b/src/components/dashboard/monitoring/operator/PeopleMessage/index.jsx
@@ -0,0 +1,16 @@
+"use client";
+
+import PageTitle from "@/core/components/PageTitle";
+import { Stack } from "@mui/material";
+import DataTable from "./DataTable";
+
+const PeopleMessagePage = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default PeopleMessagePage;
diff --git a/src/components/dashboard/monitoring/operator/SystemMessage/DataTable.jsx b/src/components/dashboard/monitoring/operator/SystemMessage/DataTable.jsx
new file mode 100644
index 0000000..c2eb921
--- /dev/null
+++ b/src/components/dashboard/monitoring/operator/SystemMessage/DataTable.jsx
@@ -0,0 +1,103 @@
+"use client";
+
+import DataTableWithAuth from "@/core/components/DataTableWithAuth";
+import { GET_SYSTEM_MESSAGES_OPERATOR } from "@/core/utils/routes";
+import { Box } from "@mui/material";
+import { useMemo } from "react";
+import moment from "jalali-moment";
+import Player from "./Player";
+const DataTable = () => {
+ const columns = useMemo(
+ () => [
+ {
+ accessorKey: "id",
+ header: "کد یکتا",
+ id: "id",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ accessorKey: "type_name",
+ header: "نوع",
+ id: "type_name",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "تاریخ",
+ id: "date",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.date ? moment(row.original.date).locale("fa").format("yyyy/MM/DD") : <>->,
+ },
+ {
+ header: "ساعت",
+ id: "time",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.date ? moment(row.original.date).locale("fa").format("HH:mm") : <>->,
+ },
+ {
+ accessorKey: "duration",
+ header: "طول تماس ( ثانیه )",
+ id: "duration",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "پخش صدا",
+ id: "player",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) => ,
+ },
+ ],
+ []
+ );
+
+ return (
+
+
+
+ );
+};
+export default DataTable;
diff --git a/src/components/dashboard/monitoring/operator/SystemMessage/Player.jsx b/src/components/dashboard/monitoring/operator/SystemMessage/Player.jsx
new file mode 100644
index 0000000..761e11b
--- /dev/null
+++ b/src/components/dashboard/monitoring/operator/SystemMessage/Player.jsx
@@ -0,0 +1,45 @@
+"use client";
+
+import React from "react";
+import { IconButton, Box, Typography } from "@mui/material";
+import PlayArrowIcon from "@mui/icons-material/PlayArrow";
+import PauseIcon from "@mui/icons-material/Pause";
+import useWaveSurferPlayer from "@/lib/hooks/useWaveSurferPlayer";
+
+function formatTime(seconds) {
+ if (!seconds || isNaN(seconds)) return "0:00";
+ const minutes = Math.floor(seconds / 60);
+ const secs = Math.floor(seconds % 60);
+ return `${minutes}:${secs.toString().padStart(2, "0")}`;
+}
+
+const Player = ({ audioUrl }) => {
+ const { containerRef, isPlaying, playPause, currentTime, duration } =
+ useWaveSurferPlayer(audioUrl);
+
+ return (
+
+
+
+
+ {isPlaying ? (
+
+ ) : (
+
+ )}
+
+
+ {formatTime(currentTime)} / {formatTime(duration)}
+
+
+ );
+};
+
+export default Player;
diff --git a/src/components/dashboard/monitoring/SystemMessages/index.jsx b/src/components/dashboard/monitoring/operator/SystemMessage/index.jsx
similarity index 100%
rename from src/components/dashboard/monitoring/SystemMessages/index.jsx
rename to src/components/dashboard/monitoring/operator/SystemMessage/index.jsx
diff --git a/src/components/dashboard/monitoring/supervisor/OperatorDialogue/DataTable.jsx b/src/components/dashboard/monitoring/supervisor/OperatorDialogue/DataTable.jsx
new file mode 100644
index 0000000..d8ae3ed
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/OperatorDialogue/DataTable.jsx
@@ -0,0 +1,168 @@
+"use client";
+
+import DataTableWithAuth from "@/core/components/DataTableWithAuth";
+import { GET_OPERATOR_DIALOGUE_SUPERVISOR } from "@/core/utils/routes";
+import { Box } from "@mui/material";
+import { useMemo } from "react";
+import moment from "jalali-moment";
+import Player from "./Player";
+import RateMessage from "./RateMessage";
+import CheckIcon from "@mui/icons-material/Check";
+import CloseIcon from "@mui/icons-material/Close";
+
+const DataTable = () => {
+ const columns = useMemo(
+ () => [
+ {
+ header: "تاریخ",
+ id: "date",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.calldate ? moment(row.original.calldate).locale("fa").format("yyyy/MM/DD") : <>->,
+ },
+ {
+ header: "ساعت",
+ id: "time",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.calldate ? moment(row.original.calldate).locale("fa").format("HH:mm") : <>->,
+ },
+ {
+ accessorKey: "src",
+ header: "شماره تماس گیرنده",
+ id: "src",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ accessorKey: "dst",
+ header: "کارشناس",
+ id: "dst",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "پخش صدا",
+ id: "is_listen",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) => {
+ const isListen = row.original.is_listen;
+ const Icon = isListen ? CheckIcon : CloseIcon;
+ const color = isListen ? "success.main" : "error.main";
+
+ return (
+
+
+
+ );
+ }
+ },
+ {
+ accessorKey: "disposition",
+ header: "وضعیت",
+ id: "disposition",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ accessorKey: "duration",
+ header: "طول تماس ( ثانیه )",
+ id: "duration",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "پخش صدا",
+ id: "player",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) => ,
+ },
+ {
+ header: "ارزیابی",
+ id: "rate",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ cell, row, table }) => {
+ const mutate = table.options.meta?.mutate;
+
+ return (
+
+ );
+ },
+ },
+ ],
+ []
+ );
+
+ return (
+
+
+
+ );
+};
+export default DataTable;
diff --git a/src/components/dashboard/monitoring/supervisor/OperatorDialogue/Player.jsx b/src/components/dashboard/monitoring/supervisor/OperatorDialogue/Player.jsx
new file mode 100644
index 0000000..9e2d822
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/OperatorDialogue/Player.jsx
@@ -0,0 +1,22 @@
+"use client";
+
+import React from "react";
+import { IconButton, Box } from "@mui/material";
+import PlayArrowIcon from "@mui/icons-material/PlayArrow";
+import PauseIcon from "@mui/icons-material/Pause";
+import useWaveSurferPlayer from "@/lib/hooks/useWaveSurferPlayer";
+
+const Player = ({ audioUrl }) => {
+ const { containerRef, isPlaying, playPause } = useWaveSurferPlayer(audioUrl);
+
+ return (
+
+
+
+ {isPlaying ? : }
+
+
+ );
+};
+
+export default Player;
diff --git a/src/components/dashboard/monitoring/supervisor/OperatorDialogue/RateMessage.jsx b/src/components/dashboard/monitoring/supervisor/OperatorDialogue/RateMessage.jsx
new file mode 100644
index 0000000..3a1489e
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/OperatorDialogue/RateMessage.jsx
@@ -0,0 +1,158 @@
+"use client";
+
+import { Button, FormControl, Grid, InputLabel, MenuItem, Select } from "@mui/material";
+import LtrTextField from "@/core/components/LtrTextField";
+import { Controller, useForm } from "react-hook-form";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { object, string } from "yup";
+import { GET_OPERATOR_DIALOGUE_SUPERVISOR } from "@/core/utils/routes";
+import StyledForm from "@/core/components/StyledForm";
+import useRequest from "@/lib/hooks/useRequest";
+import { useEffect } from "react";
+
+const RateMessage = ({ date, messageId, initialValues, mutate }) => {
+ const requestServer = useRequest({ notificationSuccess: true });
+
+ const defaultValues = {
+ supervisor_id: initialValues?.supervisor_id ?? "",
+ is_good: initialValues?.is_good ?? "",
+ description: initialValues?.description ?? "",
+ };
+
+ const validationSchema = object().shape({
+ supervisor_id: string().required("کارشناس بررسی کننده را مشخص کنید"),
+ is_good: string().required("نحوه پاسخگویی را مشخص کنید"),
+ description: string().optional(),
+ });
+
+ const {
+ control,
+ handleSubmit,
+ reset,
+ formState: { isSubmitting, errors, isDirty, isValid },
+ } = useForm({ defaultValues, resolver: yupResolver(validationSchema) });
+
+ const onSubmit = async (data) => {
+ const fixData = {
+ date: date,
+ cdr_unique_id: messageId,
+ supervisor_id: data.supervisor_id,
+ is_good: parseInt(data.is_good),
+ ...(data.description !== "" && { description: data.description }),
+ };
+ try {
+ await requestServer(`${GET_OPERATOR_DIALOGUE_SUPERVISOR}/rate`, "post", {
+ data: fixData,
+ });
+ mutate();
+ reset({
+ supervisor_id: initialValues?.supervisor_id ?? "",
+ is_good: initialValues?.is_good ?? "",
+ description: initialValues?.description ?? "",
+ });
+ } catch (error) {}
+ };
+
+ useEffect(() => {
+ reset({
+ supervisor_id: initialValues?.supervisor_id ?? "",
+ is_good: initialValues?.is_good ?? "",
+ description: initialValues?.description ?? "",
+ });
+ }, [initialValues.supervisor_id, initialValues.is_good, initialValues.description]);
+
+ return (
+
+
+
+ {
+ return (
+
+ );
+ }}
+ name="supervisor_id"
+ />
+
+
+ {
+ return (
+
+
+ نحوه پاسخگویی
+
+
+
+ );
+ }}
+ name="is_good"
+ />
+
+
+ {
+ return (
+
+ );
+ }}
+ name="description"
+ />
+
+
+
+
+
+
+ );
+};
+
+export default RateMessage;
diff --git a/src/components/dashboard/monitoring/supervisor/OperatorDialogue/index.jsx b/src/components/dashboard/monitoring/supervisor/OperatorDialogue/index.jsx
new file mode 100644
index 0000000..31d2fea
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/OperatorDialogue/index.jsx
@@ -0,0 +1,16 @@
+"use client";
+
+import PageTitle from "@/core/components/PageTitle";
+import { Stack } from "@mui/material";
+import DataTable from "./DataTable";
+
+const OperatorDialoguePage = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default OperatorDialoguePage;
diff --git a/src/components/dashboard/monitoring/supervisor/PeopleMessage/DataTable.jsx b/src/components/dashboard/monitoring/supervisor/PeopleMessage/DataTable.jsx
new file mode 100644
index 0000000..17c2497
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/PeopleMessage/DataTable.jsx
@@ -0,0 +1,167 @@
+"use client";
+
+import DataTableWithAuth from "@/core/components/DataTableWithAuth";
+import { GET_OPERATOR_PEOPLE_MESSAGE_SUPERVISOR } from "@/core/utils/routes";
+import { Box } from "@mui/material";
+import { useMemo } from "react";
+import moment from "jalali-moment";
+import Player from "./Player";
+import CloseIcon from '@mui/icons-material/Close';
+import CheckIcon from '@mui/icons-material/Check';
+import RateMessage from "./RateMessage";
+
+const DataTable = () => {
+ const columns = useMemo(
+ () => [
+ {
+ accessorKey: "id",
+ header: "کد یکتا",
+ id: "id",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "تاریخ",
+ id: "date",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.date ? moment(row.original.date).locale("fa").format("yyyy/MM/DD") : <>->,
+ },
+ {
+ header: "ساعت",
+ id: "time",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) =>
+ row.original.date ? moment(row.original.date).locale("fa").format("HH:mm") : <>->,
+ },
+ {
+ accessorKey: "caller_phone_number",
+ header: "شماره تماس",
+ id: "caller_phone_number",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "پخش صدا",
+ id: "player",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) => ,
+ },
+ {
+ header: "پخش صدا",
+ id: "is_listen",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ row }) => {
+ const isListen = row.original.is_listen;
+ const Icon = isListen ? CheckIcon : CloseIcon;
+ const color = isListen ? "success.main" : "error.main";
+
+ return (
+
+
+
+ );
+ }
+ },
+ {
+ accessorKey: "listen_at",
+ header: "زمان شنیده شدن",
+ id: "listen_at",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ accessorKey: "review_duration",
+ header: "زمان بررسی (دقیقه)",
+ id: "review_duration",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
+ {
+ header: "ارزیابی",
+ id: "rate",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ Cell: ({ cell, row, table }) => {
+ const mutate = table.options.meta?.mutate;
+
+ return (
+
+ );
+ },
+ },
+ ],
+ []
+ );
+
+ return (
+
+
+
+ );
+};
+export default DataTable;
diff --git a/src/components/dashboard/monitoring/supervisor/PeopleMessage/Player.jsx b/src/components/dashboard/monitoring/supervisor/PeopleMessage/Player.jsx
new file mode 100644
index 0000000..761e11b
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/PeopleMessage/Player.jsx
@@ -0,0 +1,45 @@
+"use client";
+
+import React from "react";
+import { IconButton, Box, Typography } from "@mui/material";
+import PlayArrowIcon from "@mui/icons-material/PlayArrow";
+import PauseIcon from "@mui/icons-material/Pause";
+import useWaveSurferPlayer from "@/lib/hooks/useWaveSurferPlayer";
+
+function formatTime(seconds) {
+ if (!seconds || isNaN(seconds)) return "0:00";
+ const minutes = Math.floor(seconds / 60);
+ const secs = Math.floor(seconds % 60);
+ return `${minutes}:${secs.toString().padStart(2, "0")}`;
+}
+
+const Player = ({ audioUrl }) => {
+ const { containerRef, isPlaying, playPause, currentTime, duration } =
+ useWaveSurferPlayer(audioUrl);
+
+ return (
+
+
+
+
+ {isPlaying ? (
+
+ ) : (
+
+ )}
+
+
+ {formatTime(currentTime)} / {formatTime(duration)}
+
+
+ );
+};
+
+export default Player;
diff --git a/src/components/dashboard/monitoring/supervisor/PeopleMessage/RateMessage.jsx b/src/components/dashboard/monitoring/supervisor/PeopleMessage/RateMessage.jsx
new file mode 100644
index 0000000..33ee936
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/PeopleMessage/RateMessage.jsx
@@ -0,0 +1,160 @@
+"use client";
+
+import { Button, FormControl, FormHelperText, Grid, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
+import LtrTextField from "@/core/components/LtrTextField";
+import { Controller, useForm } from "react-hook-form";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { object, string, number } from "yup";
+import { GET_SYSTEM_MESSAGES_SUPERVISOR } from "@/core/utils/routes";
+import StyledForm from "@/core/components/StyledForm";
+import useRequest from "@/lib/hooks/useRequest";
+import usePermissionsList from "@/lib/hooks/usePermissionsList";
+import { useEffect } from "react";
+
+const RateMessage = ({ messageId, initialValues, mutate }) => {
+ const requestServer = useRequest({ notificationSuccess: true });
+
+ const defaultValues = {
+ savaneh_id: initialValues?.savaneh_id ?? "",
+ action_id: initialValues?.action_id ?? "",
+ description: initialValues?.description ?? "",
+ };
+
+ const validationSchema = object().shape({
+ savaneh_id: string().required("وضعیت کیفیت پیام را مشخص کنید"),
+ action_id: string().optional(),
+ description: string().optional(),
+ });
+
+ const {
+ control,
+ handleSubmit,
+ reset,
+ formState: { isSubmitting, errors, isDirty, isValid },
+ } = useForm({ defaultValues, resolver: yupResolver(validationSchema) });
+
+ const onSubmit = async (data) => {
+ const fixData = {
+ savaneh_id: parseInt(data.savaneh_id),
+ ...(data.action_id !== "" && { action_id: data.action_id }),
+ ...(data.description !== "" && { description: data.description }),
+ };
+ try {
+ await requestServer(`${GET_SYSTEM_MESSAGES_SUPERVISOR}/${messageId}`, "post", {
+ data: fixData,
+ });
+ mutate();
+ reset({
+ savaneh_id: initialValues?.savaneh_id ?? "",
+ action_id: initialValues?.action_id ?? "",
+ description: initialValues?.description ?? "",
+ });
+ } catch (error) {}
+ };
+
+ useEffect(() => {
+ reset({
+ savaneh_id: initialValues?.savaneh_id ?? "",
+ action_id: initialValues?.action_id ?? "",
+ description: initialValues?.description ?? "",
+ });
+ }, [initialValues.savaneh_id, initialValues.action_id, initialValues.description]);
+
+ return (
+
+
+
+ {
+ return (
+
+
+ پیگیری
+
+
+
+ );
+ }}
+ name="savaneh_id"
+ />
+
+
+ {
+ return (
+
+ );
+ }}
+ name="action_id"
+ />
+
+
+ {
+ return (
+
+ );
+ }}
+ name="description"
+ />
+
+
+
+
+
+
+ );
+};
+
+export default RateMessage;
diff --git a/src/components/dashboard/monitoring/supervisor/PeopleMessage/index.jsx b/src/components/dashboard/monitoring/supervisor/PeopleMessage/index.jsx
new file mode 100644
index 0000000..f6c045d
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/PeopleMessage/index.jsx
@@ -0,0 +1,16 @@
+"use client";
+
+import PageTitle from "@/core/components/PageTitle";
+import { Stack } from "@mui/material";
+import DataTable from "./DataTable";
+
+const PeopleMessagePage = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default PeopleMessagePage;
diff --git a/src/components/dashboard/monitoring/SystemMessages/DataTable.jsx b/src/components/dashboard/monitoring/supervisor/SystemMessages/DataTable.jsx
similarity index 90%
rename from src/components/dashboard/monitoring/SystemMessages/DataTable.jsx
rename to src/components/dashboard/monitoring/supervisor/SystemMessages/DataTable.jsx
index 094c20b..9ccc280 100644
--- a/src/components/dashboard/monitoring/SystemMessages/DataTable.jsx
+++ b/src/components/dashboard/monitoring/supervisor/SystemMessages/DataTable.jsx
@@ -23,6 +23,18 @@ const DataTable = () => {
grow: false,
size: 100,
},
+ {
+ accessorKey: "type_name",
+ header: "نوع",
+ id: "type_name",
+ enableColumnFilter: true,
+ datatype: "text",
+ filterMode: "equals",
+ sortDescFirst: false,
+ columnFilterModeOptions: ["equals", "contains"],
+ grow: false,
+ size: 100,
+ },
{
header: "تاریخ",
id: "date",
@@ -50,6 +62,7 @@ const DataTable = () => {
row.original.date ? moment(row.original.date).locale("fa").format("HH:mm") : <>->,
},
{
+ accessorKey: "duration",
header: "طول تماس ( ثانیه )",
id: "duration",
enableColumnFilter: true,
diff --git a/src/components/dashboard/monitoring/supervisor/SystemMessages/Player.jsx b/src/components/dashboard/monitoring/supervisor/SystemMessages/Player.jsx
new file mode 100644
index 0000000..761e11b
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/SystemMessages/Player.jsx
@@ -0,0 +1,45 @@
+"use client";
+
+import React from "react";
+import { IconButton, Box, Typography } from "@mui/material";
+import PlayArrowIcon from "@mui/icons-material/PlayArrow";
+import PauseIcon from "@mui/icons-material/Pause";
+import useWaveSurferPlayer from "@/lib/hooks/useWaveSurferPlayer";
+
+function formatTime(seconds) {
+ if (!seconds || isNaN(seconds)) return "0:00";
+ const minutes = Math.floor(seconds / 60);
+ const secs = Math.floor(seconds % 60);
+ return `${minutes}:${secs.toString().padStart(2, "0")}`;
+}
+
+const Player = ({ audioUrl }) => {
+ const { containerRef, isPlaying, playPause, currentTime, duration } =
+ useWaveSurferPlayer(audioUrl);
+
+ return (
+
+
+
+
+ {isPlaying ? (
+
+ ) : (
+
+ )}
+
+
+ {formatTime(currentTime)} / {formatTime(duration)}
+
+
+ );
+};
+
+export default Player;
diff --git a/src/components/dashboard/monitoring/SystemMessages/RateMessage.jsx b/src/components/dashboard/monitoring/supervisor/SystemMessages/RateMessage.jsx
similarity index 100%
rename from src/components/dashboard/monitoring/SystemMessages/RateMessage.jsx
rename to src/components/dashboard/monitoring/supervisor/SystemMessages/RateMessage.jsx
diff --git a/src/components/dashboard/monitoring/supervisor/SystemMessages/index.jsx b/src/components/dashboard/monitoring/supervisor/SystemMessages/index.jsx
new file mode 100644
index 0000000..28481b2
--- /dev/null
+++ b/src/components/dashboard/monitoring/supervisor/SystemMessages/index.jsx
@@ -0,0 +1,16 @@
+"use client";
+
+import PageTitle from "@/core/components/PageTitle";
+import { Stack } from "@mui/material";
+import DataTable from "./DataTable";
+
+const SystemMessagesPage = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default SystemMessagesPage;
diff --git a/src/core/utils/pageMenu.js b/src/core/utils/pageMenu.js
index 95f99ea..f049c8e 100644
--- a/src/core/utils/pageMenu.js
+++ b/src/core/utils/pageMenu.js
@@ -138,27 +138,51 @@ export const pageMenu = [
hasSubitems: true,
Subitems: [
{
- id: "monitoring-operator-dialogue",
+ id: "monitoring-operator-dialogue-supervisor",
+ label: "ارزیابی صدای کارشناسان",
+ type: "page",
+ icon: ,
+ route: "/dashboard/monitoring/operator-dialogue/supervisor",
+ permissions: ["all"],
+ },
+ {
+ id: "monitoring-operator-dialogue-operator",
label: "صدای کارشناسان",
type: "page",
icon: ,
- route: "/dashboard/monitoring/operator-dialogue",
+ route: "/dashboard/monitoring/operator-dialogue/operator",
permissions: ["all"],
},
{
- id: "monitoring-system-messages",
+ id: "monitoring-system-messages-supervisor",
+ label: "ارزیابی پیام های سیستمی",
+ type: "page",
+ icon: ,
+ route: "/dashboard/monitoring/system-messages/supervisor",
+ permissions: ["all"],
+ },
+ {
+ id: "monitoring-system-messages-operator",
label: "پیام های سیستمی",
type: "page",
icon: ,
- route: "/dashboard/monitoring/system-messages",
+ route: "/dashboard/monitoring/system-messages/operator",
permissions: ["all"],
},
{
- id: "monitoring-people-messages",
+ id: "monitoring-people-messages-supervisor",
+ label: "ارزیابی پیام های مردمی",
+ type: "page",
+ icon: ,
+ route: "/dashboard/monitoring/people-messages/supervisor",
+ permissions: ["all"],
+ },
+ {
+ id: "monitoring-people-messages-operator",
label: "پیام های مردمی",
type: "page",
icon: ,
- route: "/dashboard/monitoring/people-messages",
+ route: "/dashboard/monitoring/people-messages/operator",
permissions: ["all"],
},
],
diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js
index bafc9aa..ba43bad 100644
--- a/src/core/utils/routes.js
+++ b/src/core/utils/routes.js
@@ -26,6 +26,12 @@ export const GET_COUNTRY_KEYPRESS_REPORT = api + "/cumulative_keypress_stats";
export const GET_SYSTEM_MESSAGES_SUPERVISOR = api + "/system_messages/supervisor";
export const GET_SYSTEM_MESSAGES_OPERATOR = api + "/system_messages/operator";
+export const GET_OPERATOR_DIALOGUE_SUPERVISOR = api + "/dialogs/supervisor";
+export const GET_OPERATOR_DIALOGUE_OPERATOR = api + "/dialogs/operator";
+
+export const GET_OPERATOR_PEOPLE_MESSAGE_SUPERVISOR = api + "/people_messages/supervisor";
+export const GET_OPERATOR_PEOPLE_MESSAGE_OPERATOR = api + "/people_messages/operator";
+
// export const GET_PROVINCE_CUMULATIVE_CALLS_TOTAL_REPORT = api + "/report/cumulative_total";
export const GET_PROVINCE_CUMULATIVE_CALLS_DAILY_REPORT = api + "/report/cumulative";
export const GET_PROVINCE_PEOPLE_MESSAGES_REPORT = api + "/report/people_messages";
diff --git a/src/lib/hooks/useWaveSurferPlayer.js b/src/lib/hooks/useWaveSurferPlayer.js
index 929bfaa..f056c2e 100644
--- a/src/lib/hooks/useWaveSurferPlayer.js
+++ b/src/lib/hooks/useWaveSurferPlayer.js
@@ -6,7 +6,11 @@ const playerRegistry = new Set();
export default function useWaveSurferPlayer(audioUrl, options = {}) {
const containerRef = useRef(null);
const wavesurferRef = useRef(null);
+
const [isPlaying, setIsPlaying] = useState(false);
+ const [isLoaded, setIsLoaded] = useState(false);
+ const [currentTime, setCurrentTime] = useState(0);
+ const [duration, setDuration] = useState(0);
useEffect(() => {
if (!containerRef.current) return;
@@ -17,7 +21,6 @@ export default function useWaveSurferPlayer(audioUrl, options = {}) {
progressColor: "#1b4332",
cursorColor: "#d32f2f",
height: 40,
- url: audioUrl,
...options,
});
@@ -26,12 +29,24 @@ export default function useWaveSurferPlayer(audioUrl, options = {}) {
wavesurferRef.current.on("finish", () => setIsPlaying(false));
wavesurferRef.current.on("play", () => setIsPlaying(true));
wavesurferRef.current.on("pause", () => setIsPlaying(false));
+ wavesurferRef.current.on("ready", () => {
+ setIsLoaded(true);
+ setDuration(wavesurferRef.current.getDuration());
+ });
+
+ wavesurferRef.current.on("audioprocess", () => {
+ setCurrentTime(wavesurferRef.current.getCurrentTime());
+ });
+
+ wavesurferRef.current.on("seek", () => {
+ setCurrentTime(wavesurferRef.current.getCurrentTime());
+ });
return () => {
playerRegistry.delete(wavesurferRef.current);
wavesurferRef.current?.destroy();
};
- }, [audioUrl]);
+ }, []);
const playPause = () => {
if (!wavesurferRef.current) return;
@@ -42,7 +57,16 @@ export default function useWaveSurferPlayer(audioUrl, options = {}) {
}
});
- wavesurferRef.current.playPause();
+ if (!isLoaded) {
+ setIsLoaded(true);
+ wavesurferRef.current.load(audioUrl);
+ wavesurferRef.current.once("ready", () => {
+ setDuration(wavesurferRef.current.getDuration());
+ wavesurferRef.current.play();
+ });
+ } else {
+ wavesurferRef.current.playPause();
+ }
};
const stop = () => {
@@ -59,6 +83,8 @@ export default function useWaveSurferPlayer(audioUrl, options = {}) {
playPause,
stop,
seekTo,
+ currentTime,
+ duration,
wavesurfer: wavesurferRef.current,
};
}