customer feedback
parent
bd4385e452
commit
cdd2192274
File diff suppressed because it is too large
Load Diff
|
@ -16,6 +16,7 @@
|
|||
"i18next-browser-languagedetector": "^7.1.0",
|
||||
"i18next-http-backend": "^2.2.1",
|
||||
"react": "^18.2.0",
|
||||
"react-countup": "^6.5.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-highlight-words": "^0.20.0",
|
||||
"react-i18next": "^13.0.1",
|
||||
|
@ -26,6 +27,7 @@
|
|||
"react-stl-viewer": "^2.2.5",
|
||||
"react-virtuoso": "^4.5.1",
|
||||
"react-webcam": "^7.1.1",
|
||||
"recharts": "^2.12.7",
|
||||
"uuid": "^9.0.0",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
"dashboard": "Dashboard",
|
||||
"equipmentDocumentation": "Gerätedokumentation",
|
||||
"consoles": "Konsolen",
|
||||
"customerFeedback": "Bewertungen",
|
||||
"groupTasks": {
|
||||
"menuCategory": "Gruppenaufgaben",
|
||||
"overview": "Kategorien",
|
||||
|
@ -705,5 +706,12 @@
|
|||
"noLogTypesFound": "Keine Log-Typen gefunden",
|
||||
"noLogManagerServerSpecified": "Kein Log-Manager-Server angegeben",
|
||||
"couldntReachlogManagerServer": "Verbindung zum Log-Manager-Server konnte nicht hergestellt werden"
|
||||
},
|
||||
"customerFeedback": {
|
||||
"origin": "Herkunft:",
|
||||
"feedbacks": "Bewertungen",
|
||||
"table": {
|
||||
"createdAt":"Erstellt am"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
"dashboard": "Dashboard",
|
||||
"equipmentDocumentation": "Equipment Documentation",
|
||||
"consoles": "Consoles",
|
||||
"customerFeedback": "Feedbacks",
|
||||
"groupTasks": {
|
||||
"menuCategory": "Group Tasks",
|
||||
"overview": "Categories",
|
||||
|
@ -709,5 +710,12 @@
|
|||
"noLogTypesFound": "No log types found",
|
||||
"noLogManagerServerSpecified": "No log manager specified",
|
||||
"couldntReachlogManagerServer": "Connection to log manager server failed"
|
||||
},
|
||||
"customerFeedback": {
|
||||
"origin": "Origin:",
|
||||
"feedbacks": "Feedbacks",
|
||||
"table": {
|
||||
"createdAt":"Created at"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
31
src/App.js
31
src/App.js
|
@ -16,6 +16,7 @@ import HeaderProvider from "./Contexts/HeaderContext";
|
|||
import ConsolesProvider from "./Contexts/ConsolesContext";
|
||||
import ScannerProvider from "./Contexts/ScannerContext";
|
||||
import { CrmProvider } from "./Contexts/CrmContext";
|
||||
import { CustomerFeedbackProvider } from "./Contexts/CustomerFeedbackContext";
|
||||
|
||||
export default function App() {
|
||||
const [notificationApi, notificationContextHolder] =
|
||||
|
@ -49,22 +50,24 @@ export default function App() {
|
|||
<ConsolesProvider>
|
||||
<ScannerProvider>
|
||||
<CrmProvider>
|
||||
<WebSocketProvider
|
||||
userSession={userSession}
|
||||
setUserSession={setUserSession}
|
||||
isWebSocketReady={isWebSocketReady}
|
||||
setIsWebSocketReady={setIsWebSocketReady}
|
||||
notificationApi={notificationApi}
|
||||
>
|
||||
<ReconnectingView
|
||||
isWebSocketReady={isWebSocketReady}
|
||||
/>
|
||||
|
||||
<DashboardLayout
|
||||
<CustomerFeedbackProvider>
|
||||
<WebSocketProvider
|
||||
userSession={userSession}
|
||||
setUserSession={setUserSession}
|
||||
/>
|
||||
</WebSocketProvider>
|
||||
isWebSocketReady={isWebSocketReady}
|
||||
setIsWebSocketReady={setIsWebSocketReady}
|
||||
notificationApi={notificationApi}
|
||||
>
|
||||
<ReconnectingView
|
||||
isWebSocketReady={isWebSocketReady}
|
||||
/>
|
||||
|
||||
<DashboardLayout
|
||||
userSession={userSession}
|
||||
setUserSession={setUserSession}
|
||||
/>
|
||||
</WebSocketProvider>
|
||||
</CustomerFeedbackProvider>
|
||||
</CrmProvider>
|
||||
</ScannerProvider>
|
||||
</ConsolesProvider>
|
||||
|
|
|
@ -23,8 +23,9 @@ const ViewEquipmentDocumentations = lazy(() =>
|
|||
);
|
||||
const Consoles = lazy(() => import("../../Pages/Consoles"));
|
||||
const RoboticsRobots = lazy(() => import("../../Pages/Robotics/Robots"));
|
||||
const Crm = lazy(() => import("../../Pages/Crm"));
|
||||
// const Crm = lazy(() => import("../../Pages/Crm"));
|
||||
const CrmTest = lazy(() => import("../../Pages/CrmTest/CrmTest"));
|
||||
const CustomerFeedback = lazy(() => import("../../Pages/CustomerFeedback"));
|
||||
|
||||
export default function AppRoutes({ userSession, setUserSession }) {
|
||||
const appContext = useAppContext();
|
||||
|
@ -258,6 +259,34 @@ export default function AppRoutes({ userSession, setUserSession }) {
|
|||
/>
|
||||
)}
|
||||
|
||||
{hasPermission(
|
||||
appContext.userPermissions,
|
||||
Constants.PERMISSIONS.CUSTOMERFEEDBACK.VIEW
|
||||
) && (
|
||||
<Route
|
||||
path={Constants.ROUTE_PATHS.CUSTOMERFEEDBACK_VIEW}
|
||||
element={
|
||||
<MySupsenseFallback>
|
||||
<CustomerFeedback />
|
||||
</MySupsenseFallback>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{hasPermission(
|
||||
appContext.userPermissions,
|
||||
Constants.PERMISSIONS.CUSTOMERFEEDBACK.VIEW
|
||||
) && (
|
||||
<Route
|
||||
path={`${Constants.ROUTE_PATHS.CUSTOMERFEEDBACK_VIEW}/:paramOrigin`}
|
||||
element={
|
||||
<MySupsenseFallback>
|
||||
<CustomerFeedback />
|
||||
</MySupsenseFallback>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Route
|
||||
path="*"
|
||||
element={
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export const RequestState = {
|
||||
INIT: -1,
|
||||
NOTHING: 0,
|
||||
REQUESTING: 1,
|
||||
SUCCESS: 2,
|
||||
FAILED: 3,
|
||||
};
|
|
@ -82,6 +82,20 @@ export function SideMenuContent({
|
|||
});
|
||||
}
|
||||
|
||||
// customer feedback
|
||||
if (
|
||||
hasPermission(
|
||||
appContext.userPermissions,
|
||||
Constants.PERMISSIONS.CUSTOMERFEEDBACK.VIEW
|
||||
)
|
||||
) {
|
||||
items.push({
|
||||
label: t("sideMenu.customerFeedback"),
|
||||
icon: <SnippetsOutlined />,
|
||||
key: Constants.ROUTE_PATHS.CUSTOMERFEEDBACK_VIEW,
|
||||
});
|
||||
}
|
||||
|
||||
// group tasks
|
||||
let groupTasksGroup = {
|
||||
label: t("sideMenu.groupTasks.menuCategory"),
|
||||
|
@ -149,6 +163,7 @@ export function SideMenuContent({
|
|||
label: t("sideMenu.robotics.robots"),
|
||||
icon: <RobotOutlined />,
|
||||
key: Constants.ROUTE_PATHS.ROBOTICS_ROBOTS,
|
||||
disabled: true,
|
||||
});
|
||||
|
||||
items.push(roboticsGroup);
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
import { createContext, useContext, useState } from "react";
|
||||
|
||||
const preview = {
|
||||
origins: [],
|
||||
setOrigins: () => {},
|
||||
customerFeedbacks: [],
|
||||
setCustomerFeedbacks: () => {},
|
||||
};
|
||||
|
||||
const CustomerFeedbackContext = createContext(preview);
|
||||
|
||||
export const useCustomerFeedbackContext = () =>
|
||||
useContext(CustomerFeedbackContext);
|
||||
|
||||
export function CustomerFeedbackProvider({ children }) {
|
||||
const [origins, setOrigins] = useState([]);
|
||||
const [customerFeedbacks, setCustomerFeedbacks] = useState([]);
|
||||
|
||||
return (
|
||||
<CustomerFeedbackContext.Provider
|
||||
value={{
|
||||
origins,
|
||||
setOrigins,
|
||||
customerFeedbacks,
|
||||
setCustomerFeedbacks,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CustomerFeedbackContext.Provider>
|
||||
);
|
||||
}
|
|
@ -17,6 +17,7 @@ import { useHeaderContext } from "./HeaderContext";
|
|||
import { useConsolesContext } from "./ConsolesContext";
|
||||
import { useScannerContext } from "./ScannerContext";
|
||||
import { useCrmContext } from "./CrmContext";
|
||||
import { useCustomerFeedbackContext } from "./CustomerFeedbackContext";
|
||||
|
||||
const WebSocketContext = createContext(null);
|
||||
|
||||
|
@ -46,6 +47,7 @@ export default function WebSocketProvider({
|
|||
const consolesContext = useConsolesContext();
|
||||
const scannerContext = useScannerContext();
|
||||
const crmContext = useCrmContext();
|
||||
const customerFeedbackContext = useCustomerFeedbackContext();
|
||||
|
||||
if (wsConnectionEvent === null) {
|
||||
wsConnectionEvent = new CustomEvent(wsConnectionCustomEventName, {
|
||||
|
@ -106,7 +108,8 @@ export default function WebSocketProvider({
|
|||
usersContext,
|
||||
consolesContext,
|
||||
scannerContext,
|
||||
crmContext
|
||||
crmContext,
|
||||
customerFeedbackContext
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ export const ReceivedMessagesCommands = {
|
|||
CrmLinkCreated: 51,
|
||||
CrmLinkUsed: 52,
|
||||
CrmLinkDeleted: 53,
|
||||
CustomerFeedbackAddFeedback: 54,
|
||||
};
|
||||
|
||||
// commands sent to the backend server
|
||||
|
@ -100,7 +101,8 @@ export function handleWebSocketMessage(
|
|||
usersContext,
|
||||
consolesContext,
|
||||
scannerContext,
|
||||
crmContext
|
||||
crmContext,
|
||||
customerFeedbackContext
|
||||
) {
|
||||
const data = JSON.parse(event.data);
|
||||
|
||||
|
@ -1120,6 +1122,9 @@ export function handleWebSocketMessage(
|
|||
arr.filter((link) => link.Id !== body)
|
||||
);
|
||||
break;
|
||||
case ReceivedMessagesCommands.CustomerFeedbackAddFeedback:
|
||||
customerFeedbackContext.setCustomerFeedbacks((arr) => [...arr, body]);
|
||||
break;
|
||||
default:
|
||||
console.error("unknown command", cmd);
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,436 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
Constants,
|
||||
FormatDatetime,
|
||||
myFetch,
|
||||
wsConnectionCustomEventName,
|
||||
} from "../../utils";
|
||||
import { useCustomerFeedbackContext } from "../../Contexts/CustomerFeedbackContext";
|
||||
import { Card, Col, Result, Row, Select, Spin, Statistic, Table } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { RequestState } from "../../Components/MyRequestState";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import CountUp from "react-countup";
|
||||
import {
|
||||
LineChart,
|
||||
Line,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
Legend,
|
||||
ResponsiveContainer,
|
||||
} from "recharts";
|
||||
|
||||
function calculateAverage(arr) {
|
||||
if (arr.length === 0) return 0;
|
||||
const sum = arr.reduce(
|
||||
(accumulator, currentValue) => accumulator + currentValue,
|
||||
0
|
||||
);
|
||||
const average = sum / arr.length;
|
||||
|
||||
return average.toFixed(1);
|
||||
}
|
||||
|
||||
export default function CustomerFeedback() {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const customerFeedbackContext = useCustomerFeedbackContext();
|
||||
const { paramOrigin } = useParams();
|
||||
|
||||
const [isRequesting, setIsRequesting] = useState(RequestState.INIT);
|
||||
const [selectedOrigin, setSelectedOrigin] = useState("");
|
||||
|
||||
const getTableContent = () => {
|
||||
const feedbackColumns = [];
|
||||
const columns = [];
|
||||
|
||||
for (const feedback of customerFeedbackContext.customerFeedbacks) {
|
||||
if (feedback.Data === null) continue;
|
||||
|
||||
for (const key in feedback.Data) {
|
||||
if (!columns.includes(key)) {
|
||||
feedbackColumns.push({
|
||||
title: key,
|
||||
dataIndex: key,
|
||||
key: key,
|
||||
});
|
||||
|
||||
columns.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
...feedbackColumns,
|
||||
{
|
||||
title: t("customerFeedback.table.createdAt"),
|
||||
dataIndex: "createdAt",
|
||||
key: "createdAt",
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
const getTableItems = () => {
|
||||
const items = [];
|
||||
|
||||
customerFeedbackContext.customerFeedbacks.sort(
|
||||
(a, b) => new Date(b.CreatedAt) - new Date(a.CreatedAt)
|
||||
);
|
||||
|
||||
customerFeedbackContext.customerFeedbacks.forEach((customerFeedback) => {
|
||||
let dynamicItems = {};
|
||||
|
||||
if (customerFeedback.Data !== null) {
|
||||
for (const key in customerFeedback.Data) {
|
||||
dynamicItems[key] = customerFeedback.Data[key];
|
||||
}
|
||||
}
|
||||
|
||||
items.push({
|
||||
key: customerFeedback.Id,
|
||||
...dynamicItems,
|
||||
createdAt: FormatDatetime(customerFeedback.CreatedAt),
|
||||
});
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
const navigateToOrigin = (origin) =>
|
||||
navigate(`${Constants.ROUTE_PATHS.CUSTOMERFEEDBACK_VIEW}/${origin}`);
|
||||
|
||||
const StatisticCard = () => {
|
||||
const data = {};
|
||||
|
||||
for (const customerFeedback of customerFeedbackContext.customerFeedbacks) {
|
||||
if (customerFeedback.Data === null) continue;
|
||||
|
||||
for (const feedbackDataKey in customerFeedback.Data) {
|
||||
if (typeof customerFeedback.Data[feedbackDataKey] !== "number")
|
||||
continue;
|
||||
|
||||
if (!data.hasOwnProperty(feedbackDataKey)) {
|
||||
data[feedbackDataKey] = [];
|
||||
}
|
||||
|
||||
data[feedbackDataKey].push(customerFeedback.Data[feedbackDataKey]);
|
||||
}
|
||||
}
|
||||
|
||||
const elements = [
|
||||
<Statistic
|
||||
title={t("customerFeedback.feedbacks")}
|
||||
value={customerFeedbackContext.customerFeedbacks.length}
|
||||
formatter={(value) => <CountUp end={value} />}
|
||||
/>,
|
||||
];
|
||||
|
||||
for (const statistic in data) {
|
||||
elements.push(
|
||||
<Statistic
|
||||
key={statistic}
|
||||
title={statistic}
|
||||
value={calculateAverage(data[statistic])}
|
||||
formatter={(value) => (
|
||||
<span>
|
||||
<CountUp end={value} prefix="Ø " decimals={1} /> / ∑{" "}
|
||||
{data[statistic].length}
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const chunkedElements = elements.reduce((acc, element, index) => {
|
||||
const chunkIndex = Math.floor(index / 8);
|
||||
if (!acc[chunkIndex]) {
|
||||
acc[chunkIndex] = [];
|
||||
}
|
||||
acc[chunkIndex].push(element);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Card style={{ marginTop: 20 }}>
|
||||
{chunkedElements.map((chunk, chunkIndex) => (
|
||||
<Row gutter={16} key={chunkIndex}>
|
||||
{chunk.map((element, elementIndex) => (
|
||||
<Col xs={24} sm={12} md={4} key={elementIndex}>
|
||||
{element}
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
))}
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
const Graphs = () => {
|
||||
if (
|
||||
!customerFeedbackContext.customerFeedbacks ||
|
||||
customerFeedbackContext.customerFeedbacks.length === 0
|
||||
) {
|
||||
return <div>No data available</div>;
|
||||
}
|
||||
|
||||
// Function to count number of feedbacks for each date
|
||||
const countFeedbacksByDate = (feedbacks) => {
|
||||
const dateCounts = {};
|
||||
|
||||
// Iterate through feedbacks
|
||||
feedbacks.forEach((feedback) => {
|
||||
const date = new Date(feedback.CreatedAt).toISOString().split("T")[0];
|
||||
|
||||
// Increment count for date or initialize it with 1
|
||||
dateCounts[date] = (dateCounts[date] || 0) + 1;
|
||||
});
|
||||
|
||||
// Convert date-counts map to array of objects and sort by date ascending
|
||||
return Object.keys(dateCounts)
|
||||
.map((date) => ({
|
||||
date,
|
||||
count: dateCounts[date],
|
||||
}))
|
||||
.sort((a, b) => new Date(a.date) - new Date(b.date));
|
||||
};
|
||||
|
||||
const data = countFeedbacksByDate(
|
||||
customerFeedbackContext.customerFeedbacks
|
||||
);
|
||||
|
||||
// Function to extract data for each key in Data
|
||||
const getDataByKey = (feedbacks, key) => {
|
||||
const dateValuesMap = {};
|
||||
|
||||
// Iterate through feedbacks
|
||||
feedbacks.forEach((feedback) => {
|
||||
if (feedback.Data && typeof feedback.Data === "object") {
|
||||
const date = new Date(feedback.CreatedAt).toISOString().split("T")[0];
|
||||
const value = feedback.Data[key];
|
||||
|
||||
// Increment count for date or initialize it with value
|
||||
dateValuesMap[date] =
|
||||
(dateValuesMap[date] || 0) + (typeof value === "number" ? 1 : 0);
|
||||
}
|
||||
});
|
||||
|
||||
// Convert date-values map to array of objects and sort by date ascending
|
||||
return Object.keys(dateValuesMap)
|
||||
.map((date) => ({
|
||||
date,
|
||||
value: dateValuesMap[date],
|
||||
}))
|
||||
.sort((a, b) => new Date(a.date) - new Date(b.date));
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Card style={{ marginTop: 20 }}>
|
||||
<h2>Feedback Count</h2>
|
||||
<ResponsiveContainer width="100%" height={400}>
|
||||
<LineChart data={data}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="date" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="count"
|
||||
stroke="#8884d8"
|
||||
activeDot={{ r: 8 }}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
|
||||
/*
|
||||
{Object.keys(customerFeedbackContext.customerFeedbacks[0]?.Data || {})
|
||||
.filter(
|
||||
(key) =>
|
||||
typeof customerFeedbackContext.customerFeedbacks[0]?.Data[key] ===
|
||||
"number"
|
||||
)
|
||||
.map((key) => (
|
||||
<Card key={key} style={{ marginTop: 20 }}>
|
||||
<h2>{key}</h2>
|
||||
<ResponsiveContainer width="100%" height={400}>
|
||||
<LineChart
|
||||
data={getDataByKey(
|
||||
customerFeedbackContext.customerFeedbacks,
|
||||
key
|
||||
)}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="date" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="value"
|
||||
stroke="#8884d8"
|
||||
activeDot={{ r: 8 }}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
))}
|
||||
*/
|
||||
};
|
||||
|
||||
// Function to group data by date and count occurrences
|
||||
/*const getDataByDate = (feedbacks) => {
|
||||
const dateCounts = feedbacks.reduce((acc, feedback) => {
|
||||
const date = new Date(feedback.CreatedAt).toISOString().split("T")[0]; // Extract date part
|
||||
acc[date] = (acc[date] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const sortedDates = Object.keys(dateCounts).sort(
|
||||
(a, b) => new Date(a) - new Date(b)
|
||||
);
|
||||
|
||||
return sortedDates.map((date) => ({
|
||||
date,
|
||||
count: dateCounts[date],
|
||||
}));
|
||||
};
|
||||
|
||||
const data = getDataByDate(customerFeedbackContext.customerFeedbacks);
|
||||
|
||||
return (
|
||||
<Card style={{ marginTop: 20 }}>
|
||||
<ResponsiveContainer width="100%" height={400}>
|
||||
<LineChart data={data}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="date" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="count"
|
||||
stroke="#8884d8"
|
||||
activeDot={{ r: 8 }}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
);
|
||||
}; */
|
||||
|
||||
useEffect(() => {
|
||||
const customersRequest = () => {
|
||||
setIsRequesting(RequestState.REQUESTING);
|
||||
|
||||
myFetch(`/customerfeedback/origins`, "GET").then((data) => {
|
||||
if (data === undefined || data === null) return;
|
||||
|
||||
customerFeedbackContext.setOrigins(data);
|
||||
|
||||
if (data.length === 0) {
|
||||
setIsRequesting(RequestState.NOTHING);
|
||||
} else if (paramOrigin === undefined || !data.includes(paramOrigin)) {
|
||||
navigateToOrigin(data[0]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
customersRequest();
|
||||
|
||||
const handleCustomersRequest = () => customersRequest();
|
||||
|
||||
document.addEventListener(
|
||||
wsConnectionCustomEventName,
|
||||
handleCustomersRequest
|
||||
);
|
||||
|
||||
return () =>
|
||||
document.removeEventListener(
|
||||
wsConnectionCustomEventName,
|
||||
handleCustomersRequest
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (paramOrigin === undefined) return;
|
||||
|
||||
setIsRequesting(RequestState.REQUESTING);
|
||||
setSelectedOrigin(paramOrigin);
|
||||
|
||||
myFetch(`/customerfeedback/origin/${paramOrigin}`, "GET").then((data) => {
|
||||
if (data === undefined || data === null) return;
|
||||
|
||||
customerFeedbackContext.setCustomerFeedbacks(data);
|
||||
setIsRequesting(RequestState.SUCCESS);
|
||||
});
|
||||
}, [paramOrigin]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: 10,
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<span>{t("customerFeedback.origin")}</span>
|
||||
|
||||
<Select
|
||||
style={{
|
||||
width: "100%",
|
||||
}}
|
||||
value={selectedOrigin}
|
||||
onSelect={(value) => navigateToOrigin(value)}
|
||||
options={customerFeedbackContext.origins.map((origin) => {
|
||||
return {
|
||||
value: origin,
|
||||
label: origin,
|
||||
};
|
||||
})}
|
||||
></Select>
|
||||
</div>
|
||||
|
||||
{isRequesting === RequestState.INIT ? (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: "80vh",
|
||||
}}
|
||||
>
|
||||
<Spin size="large"></Spin>
|
||||
</div>
|
||||
) : isRequesting === RequestState.NOTHING ? (
|
||||
<Result
|
||||
status="404"
|
||||
title="404"
|
||||
subTitle="Sorry, the page you visited does not exist."
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<StatisticCard />
|
||||
|
||||
<Graphs />
|
||||
|
||||
<Table
|
||||
style={{ paddingTop: 20 }}
|
||||
scroll={{ x: "max-content" }}
|
||||
columns={getTableContent()}
|
||||
dataSource={getTableItems()}
|
||||
loading={isRequesting === RequestState.REQUESTING}
|
||||
pagination
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -97,6 +97,7 @@ export const Constants = {
|
|||
ROBOTICS_ROBOTS: "/robotics/robots",
|
||||
CRM: "/crm/",
|
||||
CRM_TEST: "/crm/test",
|
||||
CUSTOMERFEEDBACK_VIEW: "/customer-feedback",
|
||||
},
|
||||
CRM_TYPE: {
|
||||
TEST_CUSTOMERS: "test-customers",
|
||||
|
@ -224,6 +225,9 @@ export const Constants = {
|
|||
VIEW: "crm.setter_closer.view",
|
||||
},
|
||||
},
|
||||
CUSTOMERFEEDBACK: {
|
||||
VIEW: "customerfeedback.view",
|
||||
},
|
||||
},
|
||||
SYSTEM_LOG_TYPE: {
|
||||
INFO: 0,
|
||||
|
|
Loading…
Reference in New Issue