CFE-2 Merge branch 'feature/CFE-2_widget_call_action' into 'develop'
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
import {userHandler} from "./handlers/user";
|
||||
import {permissionsHandler} from "./handlers/permissions";
|
||||
import {rolesHandler} from "./handlers/roles";
|
||||
import {provincesHandler} from "./handlers/provinces";
|
||||
import {expertsHandler} from "./handlers/experts";
|
||||
import { userHandler } from "./handlers/user";
|
||||
import { permissionsHandler } from "./handlers/permissions";
|
||||
import { rolesHandler } from "./handlers/roles";
|
||||
import { provincesHandler } from "./handlers/provinces";
|
||||
import { expertsHandler } from "./handlers/experts";
|
||||
import { categoriesHandler } from "./handlers/categories";
|
||||
|
||||
export const handler = [
|
||||
...userHandler,
|
||||
...permissionsHandler,
|
||||
...rolesHandler,
|
||||
...provincesHandler,
|
||||
...expertsHandler
|
||||
]
|
||||
...expertsHandler,
|
||||
...categoriesHandler,
|
||||
];
|
||||
|
||||
25
mocks/handlers/categories.js
Normal file
25
mocks/handlers/categories.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import { rest } from "msw";
|
||||
import { GET_CATEGORY } from "@/core/data/apiRoutes";
|
||||
|
||||
export const categoriesHandler = [
|
||||
rest.get(GET_CATEGORY, (req, res, ctx) => {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: [
|
||||
{
|
||||
category_id: 1,
|
||||
category_name: "اطلاعات راه",
|
||||
subcategory_id: 1,
|
||||
subcategory_name: "اطلاعات باز و بسته",
|
||||
},
|
||||
{
|
||||
category_id: 3,
|
||||
category_name: "سایر",
|
||||
subcategory_id: 2,
|
||||
subcategory_name: "مزاحم",
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
}),
|
||||
];
|
||||
@@ -260,5 +260,13 @@
|
||||
"call_history_not_found": "تاریخچه ای برای تماس دریافتی یافت نشد",
|
||||
"call_history_error_fetching": "خطا در دریافت تاریخچه تماس دریافتی",
|
||||
"show_more": "نمایش موارد بیشتر"
|
||||
},
|
||||
"CallAction": {
|
||||
"call_history_of": "عملیات های مربوط به تماس",
|
||||
"categories" : "موضوع ها",
|
||||
"subcategories" : "زیر موضوع ها",
|
||||
"description" : "توضیحات تماس (اختیاری)",
|
||||
"text_field_label" : "توضیحات",
|
||||
"text_field_palacholder" : "لطفا توضیحات خود را وارد نمایید"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import {render, screen, waitFor} from "@testing-library/react";
|
||||
import MockAppWithProviders from "../../../../../../../../../../../mocks/AppWithProvider";
|
||||
import {AnswersProvider} from "@/lib/callWidget/contexts/answers";
|
||||
import ActionHeader from "..";
|
||||
|
||||
const tab = {
|
||||
active: true,
|
||||
active_category_id: 1,
|
||||
phone_number : "09134849737"
|
||||
}
|
||||
|
||||
describe('Action Header Button from Call Actions Categories', () => {
|
||||
describe('Rendering', () => {
|
||||
it('should see header text', async () => {
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<ActionHeader tab={tab} />
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
)
|
||||
const headingElement = screen.getByRole('heading', {
|
||||
name: /\.\.\.\. عملیات های مربوط به تماس:/i
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(headingElement).toBeInTheDocument()
|
||||
})
|
||||
});
|
||||
it('should see phone number', async () => {
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<ActionHeader tab={tab} />
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
)
|
||||
const phone_numberElement = screen.queryByText(/09134849737/i)
|
||||
await waitFor(() => {
|
||||
expect(phone_numberElement).toBeInTheDocument()
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
import {useTranslations} from "next-intl";
|
||||
import {Stack, Typography} from "@mui/material";
|
||||
|
||||
const ActionHeader = ({tab}) => {
|
||||
const t = useTranslations();
|
||||
return (
|
||||
<Stack sx={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
py: 2,
|
||||
backgroundColor: "primary.main",
|
||||
overflow: "hidden"
|
||||
}}>
|
||||
<Typography variant="subtitle1" sx={{marginRight: 1, color: "#fff"}}>
|
||||
.... {t("CallAction.call_history_of")}:
|
||||
</Typography>
|
||||
<Typography data-testid="phone_number" variant="subtitle1" sx={{color: "#fff"}}>
|
||||
{tab.phone_number} ....
|
||||
</Typography>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
export default ActionHeader
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Button, Grid } from "@mui/material";
|
||||
import useCategories from "@/lib/callWidget/hooks/useCategories";
|
||||
|
||||
const CallActionCategoriesButton = ({ category, tab }) => {
|
||||
const { setActiveCategoryID } = useCategories();
|
||||
|
||||
return (
|
||||
|
||||
<Grid item xs={4}>
|
||||
<Button
|
||||
sx={{py : 1.5}}
|
||||
fullWidth
|
||||
variant={"contained"}
|
||||
color={tab.active_category_id === category.category_id ? "primary" : "inherit"}
|
||||
onClick={() => {
|
||||
setActiveCategoryID(tab.id, category.category_id);
|
||||
}}
|
||||
>
|
||||
{category.category_name}
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
);
|
||||
};
|
||||
export default CallActionCategoriesButton;
|
||||
@@ -0,0 +1,51 @@
|
||||
import {fireEvent, render, screen, waitFor} from "@testing-library/react";
|
||||
import MockAppWithProviders from "../../../../../../../../../../../mocks/AppWithProvider";
|
||||
import {AnswersProvider} from "@/lib/callWidget/contexts/answers";
|
||||
import CallActionCategoriesButton from "../CallActionCategoriesButton";
|
||||
|
||||
const category = {
|
||||
category_id: 1,
|
||||
category_name: "اطلاعات راه ها",
|
||||
}
|
||||
const tab = {
|
||||
active: true,
|
||||
active_category_id: 1,
|
||||
}
|
||||
|
||||
describe('Call Action Categories Button from Call Actions Categories', () => {
|
||||
describe('Rendering', () => {
|
||||
it('should categories names', async () => {
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<CallActionCategoriesButton tab={tab} category={category}/>
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
)
|
||||
const categoryElement = screen.queryByText("اطلاعات راه ها")
|
||||
await waitFor(() => {
|
||||
expect(categoryElement).toBeInTheDocument()
|
||||
})
|
||||
});
|
||||
});
|
||||
describe("Behavior", ()=>{
|
||||
it("Should change the color when button clecked",async()=>{
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<CallActionCategoriesButton tab={tab} category={category}/>
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
)
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: /اطلاعات راه ها/i
|
||||
})
|
||||
|
||||
fireEvent.click(buttonElement);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(buttonElement).toHaveStyle('background-color: rgb(12, 31, 23)');
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
import { AnswersProvider } from "@/lib/callWidget/contexts/answers";
|
||||
import CallActionsCategories from "..";
|
||||
import MockAppWithProviders from "../../../../../../../../../../../mocks/AppWithProvider";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
|
||||
const tab = {
|
||||
active: true,
|
||||
active_category_id: 1,
|
||||
id : 1,
|
||||
phone_number : "09134849737"
|
||||
}
|
||||
|
||||
describe('Call Action Categories Button from Call Actions Categories', () => {
|
||||
describe('Rendering', () => {
|
||||
it('should see divider text', async () => {
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<CallActionsCategories tab={tab}/>
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
)
|
||||
const divider_textElement = screen.queryByText("موضوع ها")
|
||||
await waitFor(() => {
|
||||
expect(divider_textElement).toBeInTheDocument()
|
||||
})
|
||||
});
|
||||
});
|
||||
})
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Chip, Divider, Grid, Stack } from "@mui/material";
|
||||
import useCategories from "@/lib/callWidget/hooks/useCategories";
|
||||
import CallActionCategoriesButton from "./CallActionCategoriesButton";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const CallActionsCategories = ({ tab }) => {
|
||||
const { categoryLists } = useCategories();
|
||||
const t = useTranslations();
|
||||
return (
|
||||
<>
|
||||
<Divider sx={{margin : 2}}><Chip label={t("CallAction.categories")} variant="outlined"/></Divider>
|
||||
<Stack sx={{m : 1, p : 1}} direction={"row"}>
|
||||
<Grid container spacing={2}>
|
||||
{categoryLists.map((category) => {
|
||||
return <CallActionCategoriesButton tab={tab} key={category.category_id} category={category} />;
|
||||
})}
|
||||
</Grid>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default CallActionsCategories;
|
||||
@@ -0,0 +1,54 @@
|
||||
import {fireEvent, render, screen, waitFor} from "@testing-library/react";
|
||||
import MockAppWithProviders from "../../../../../../../../../../../mocks/AppWithProvider";
|
||||
import {AnswersProvider} from "@/lib/callWidget/contexts/answers";
|
||||
import CallActionDescription from "..";
|
||||
|
||||
describe('Action Header Button from Call Actions Categories', () => {
|
||||
describe('Rendering', () => {
|
||||
it('should see placeholder text', async () => {
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<CallActionDescription />
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
)
|
||||
const textElement = screen.getByPlaceholderText('لطفا توضیحات خود را وارد نمایید')
|
||||
await waitFor(() => {
|
||||
expect(textElement).toBeInTheDocument()
|
||||
})
|
||||
});
|
||||
it('should see header text', async () => {
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<CallActionDescription />
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
)
|
||||
const textElement = screen.getByText('توضیحات تماس (اختیاری)')
|
||||
await waitFor(() => {
|
||||
expect(textElement).toBeInTheDocument()
|
||||
})
|
||||
});
|
||||
});
|
||||
describe("Behavior", ()=>{
|
||||
it("Should see what write in input", async()=>{
|
||||
const setDescription = jest.fn();
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<CallActionDescription setDescription={setDescription} />
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
)
|
||||
const textElement = screen.getByPlaceholderText('لطفا توضیحات خود را وارد نمایید')
|
||||
|
||||
fireEvent.change(textElement, {target : {value : "امین"}})
|
||||
|
||||
await waitFor(() => {
|
||||
expect(textElement).toHaveValue("امین")
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Box, Chip, Divider, TextField } from "@mui/material"
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const CallActionDescription = ({setDescription}) => {
|
||||
const t = useTranslations();
|
||||
return(
|
||||
<>
|
||||
<Divider sx={{margin : 2}}><Chip label={t("CallAction.description")} variant="outlined"/></Divider>
|
||||
<Box sx={{m : 2}}>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
placeholder={t(
|
||||
"CallAction.text_field_palacholder"
|
||||
)}
|
||||
type={"text"}
|
||||
fullWidth
|
||||
multiline
|
||||
rows={8}
|
||||
onChange={(e)=>{
|
||||
setDescription(e.target.value)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default CallActionDescription
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Button, Grid } from "@mui/material";
|
||||
|
||||
const CallActionSubcategoriesButton = ({ sub_category, tab, handleSubcategoryButton }) => {
|
||||
|
||||
return sub_category.category_id === tab.active_category_id ? (
|
||||
<Grid item xs={3}>
|
||||
<Button sx={{py : 1.5}} fullWidth color="inherit"
|
||||
onClick={()=>{handleSubcategoryButton(sub_category.category_id, sub_category.subcategory_id)}} variant={"contained"}>
|
||||
{sub_category.subcategory_name}
|
||||
</Button>
|
||||
</Grid>
|
||||
) : null;
|
||||
};
|
||||
export default CallActionSubcategoriesButton;
|
||||
@@ -0,0 +1,37 @@
|
||||
import {render, screen, waitFor} from "@testing-library/react";
|
||||
import MockAppWithProviders from "../../../../../../../../../../../mocks/AppWithProvider";
|
||||
import {AnswersProvider} from "@/lib/callWidget/contexts/answers";
|
||||
import CallActionSubcategoriesButton from "../CallActionSubcategoriesButton";
|
||||
|
||||
const sub_category = {
|
||||
category_id: 1,
|
||||
category_name: "اطلاعات راه",
|
||||
subcategory_id: 1,
|
||||
subcategory_name: "اطلاعات باز و بسته"
|
||||
};
|
||||
|
||||
const tab = {
|
||||
active: true,
|
||||
active_category_id: 1,
|
||||
date: new Date(),
|
||||
id: 1,
|
||||
phone_number: "09134849737"
|
||||
};
|
||||
|
||||
describe('Call Action Subcategories Button from Call Actions Categories', () => {
|
||||
describe('Rendering', () => {
|
||||
it('should render subcategory name', async () => {
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<CallActionSubcategoriesButton sub_category={sub_category} tab={tab} />
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
);
|
||||
const subCategoryElement = screen.queryByText(/اطلاعات باز و بسته/i);
|
||||
await waitFor(() => {
|
||||
expect(subCategoryElement).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import { AnswersProvider } from "@/lib/callWidget/contexts/answers";
|
||||
import CallActionsSubcategories from "..";
|
||||
import MockAppWithProviders from "../../../../../../../../../../../mocks/AppWithProvider";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
|
||||
const tab = {
|
||||
active: true,
|
||||
active_category_id: 1,
|
||||
id : 1,
|
||||
phone_number : "09134849737"
|
||||
}
|
||||
|
||||
describe('Call Action Categories Button from Call Actions Categories', () => {
|
||||
describe('Rendering', () => {
|
||||
it('should see divider text', async () => {
|
||||
render(
|
||||
<MockAppWithProviders>
|
||||
<AnswersProvider>
|
||||
<CallActionsSubcategories tab={tab}/>
|
||||
</AnswersProvider>
|
||||
</MockAppWithProviders>
|
||||
)
|
||||
const divider_textElement = screen.queryByText("زیر موضوع ها")
|
||||
await waitFor(() => {
|
||||
expect(divider_textElement).toBeInTheDocument()
|
||||
})
|
||||
});
|
||||
});
|
||||
})
|
||||
@@ -0,0 +1,22 @@
|
||||
import useCategories from "@/lib/callWidget/hooks/useCategories";
|
||||
import { Chip, Divider, Grid, Stack } from "@mui/material";
|
||||
import CallActionSubcategoriesButton from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallActions/CallActionSubcategories/CallActionSubcategoriesButton";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const CallActionsSubcategories = ({ tab, handleSubcategoryButton }) => {
|
||||
const { subCategoryLists } = useCategories();
|
||||
const t = useTranslations();
|
||||
return (
|
||||
<>
|
||||
<Divider sx={{margin : 2}}><Chip label={t("CallAction.subcategories")} variant="outlined"/></Divider>
|
||||
<Stack sx={{m : 1, p : 1 }} direction={"row"}>
|
||||
<Grid container spacing={2}>
|
||||
{subCategoryLists.map((sub_category, index) => {
|
||||
return <CallActionSubcategoriesButton key={index} tab={tab} sub_category={sub_category} handleSubcategoryButton={handleSubcategoryButton}/>;
|
||||
})}
|
||||
</Grid>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default CallActionsSubcategories;
|
||||
@@ -1,7 +1,43 @@
|
||||
const CallActions = ({tab}) => {
|
||||
import CallActionsCategories from "./CallActionCategories";
|
||||
import CallActionsSubcategories from "./CallActionSubcategories";
|
||||
import ActionHeader from "./ActionHeader";
|
||||
import CallActionDescription from "./CallActionDescription";
|
||||
import { CALL_ACTION } from "@/core/data/apiRoutes";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import useAnswers from "@/lib/callWidget/hooks/useAnswers";
|
||||
import { useState } from "react";
|
||||
|
||||
function CallActions({ tab }) {
|
||||
const [description, setDescription] = useState('')
|
||||
const requestServer = useRequest({ auth: true });
|
||||
const { closeAnswerTab } = useAnswers();
|
||||
|
||||
const handleSubcategoryButton = (category_id, subcategory_id) => {
|
||||
requestServer(`${CALL_ACTION}/${tab.id}`, "post", {
|
||||
data: {
|
||||
category_id,
|
||||
subcategory_id,
|
||||
description
|
||||
},
|
||||
success: {
|
||||
notification: { show: false },
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
closeAnswerTab(tab.id);
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>CallActions - {tab.id}</>
|
||||
)
|
||||
<>
|
||||
<ActionHeader tab={tab} />
|
||||
<CallActionDescription setDescription={setDescription} />
|
||||
<CallActionsCategories tab={tab} />
|
||||
<CallActionsSubcategories handleSubcategoryButton={handleSubcategoryButton} tab={tab} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default CallActions
|
||||
export default CallActions;
|
||||
|
||||
@@ -29,21 +29,16 @@ export const GET_USER = BASE_URL + "/api/profile/info";
|
||||
//user data
|
||||
|
||||
//sidebar notification
|
||||
export const GET_SIDEBAR_NOTIFICATION = BASE_URL + "/dashboard/notification"
|
||||
export const GET_SIDEBAR_NOTIFICATION = BASE_URL + "/dashboard/notification";
|
||||
//sidebar notification
|
||||
|
||||
// role management
|
||||
export const GET_ROLES =
|
||||
BASE_URL + "/api/roles"
|
||||
export const ADD_ROLE =
|
||||
BASE_URL + "/api/roles"
|
||||
export const UPDATE_ROLE =
|
||||
BASE_URL + "/api/roles"
|
||||
export const DELETE_ROLE =
|
||||
BASE_URL + "/api/roles"
|
||||
export const GET_ROLES = BASE_URL + "/api/roles";
|
||||
export const ADD_ROLE = BASE_URL + "/api/roles";
|
||||
export const UPDATE_ROLE = BASE_URL + "/api/roles";
|
||||
export const DELETE_ROLE = BASE_URL + "/api/roles";
|
||||
|
||||
export const GET_PERMISSIONS_LIST =
|
||||
BASE_URL + "/api/permissions/list"
|
||||
export const GET_PERMISSIONS_LIST = BASE_URL + "/api/permissions/list";
|
||||
//role management
|
||||
|
||||
//expert management
|
||||
@@ -51,4 +46,9 @@ export const GET_EXPERTS = BASE_URL + "/api/users";
|
||||
export const ADD_EXPERT = BASE_URL + "/api/users";
|
||||
export const UPDATE_EXPERT = BASE_URL + "/api/users";
|
||||
export const DELETE_EXPERT = BASE_URL + "/api/users";
|
||||
//expert management
|
||||
//expert management
|
||||
|
||||
//call action history
|
||||
export const GET_CATEGORY = BASE_URL + "/api/categories";
|
||||
export const CALL_ACTION = BASE_URL + "/api/calls";
|
||||
//call action history
|
||||
|
||||
@@ -1,31 +1,86 @@
|
||||
import {createContext, useReducer, useState} from "react";
|
||||
import { createContext, useEffect, useReducer, useState } from "react";
|
||||
import { GET_CATEGORY } from "@/core/data/apiRoutes";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
|
||||
const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case "CHANGE_ACTIVE_TAB":
|
||||
return state.map((answer, index) => action.newValue === index ? {...answer, active: true} : {
|
||||
...answer,
|
||||
active: false
|
||||
});
|
||||
return state.map((answer, index) =>
|
||||
action.newValue === index
|
||||
? { ...answer, active: true }
|
||||
: {
|
||||
...answer,
|
||||
active: false,
|
||||
}
|
||||
);
|
||||
case "CHANGE_LIST":
|
||||
return [...action.newList]
|
||||
return [...action.newList];
|
||||
case "CHANGE_ACTIVE_ID":
|
||||
return state.map((answer, index) =>
|
||||
action.tab_id === answer.id
|
||||
? {
|
||||
...answer,
|
||||
active_category_id: action.category_id,
|
||||
}
|
||||
: { ...answer }
|
||||
);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export const AnswersContext = createContext()
|
||||
export const AnswersProvider = ({children}) => {
|
||||
const [openCallDialog, setOpenCallDialog] = useState(false)
|
||||
const [activeTab, setActiveTab] = useState(0)
|
||||
};
|
||||
|
||||
const submission = (handleCategories, operation) => {
|
||||
switch (operation.type) {
|
||||
case "SET_CATEGORIES":
|
||||
return { ...handleCategories, categoryLists: operation.categoriesByAPI };
|
||||
case "SET_SUBCATEGORIES":
|
||||
return { ...handleCategories, subCategoryLists: operation.subCategoriesByAPI };
|
||||
default:
|
||||
return handleCategories;
|
||||
}
|
||||
};
|
||||
|
||||
export const AnswersContext = createContext();
|
||||
export const AnswersProvider = ({ children }) => {
|
||||
const requestServer = useRequest({ auth: true, notification: false });
|
||||
const [openCallDialog, setOpenCallDialog] = useState(false);
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
const [handleCategories, operation] = useReducer(submission, {
|
||||
categoryLists: [],
|
||||
subCategoryLists: [],
|
||||
});
|
||||
const [state, dispatch] = useReducer(reducer, []);
|
||||
|
||||
return <AnswersContext.Provider
|
||||
value = {{
|
||||
openCallDialog,
|
||||
setOpenCallDialog,
|
||||
state,
|
||||
dispatch,
|
||||
activeTab,
|
||||
setActiveTab
|
||||
}}>{children}</AnswersContext.Provider>
|
||||
}
|
||||
useEffect(() => {
|
||||
requestServer(GET_CATEGORY, "get")
|
||||
.then(({ data }) => {
|
||||
const subCategoriesByAPI = data.data;
|
||||
const categoriesByAPI = subCategoriesByAPI.reduce((accumulator, currentValue) => {
|
||||
if (!accumulator.find((item) => item.category_id === currentValue.category_id)) {
|
||||
accumulator.push(currentValue);
|
||||
}
|
||||
return accumulator;
|
||||
}, []);
|
||||
operation({ type: "SET_CATEGORIES", categoriesByAPI });
|
||||
operation({ type: "SET_SUBCATEGORIES", subCategoriesByAPI });
|
||||
})
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AnswersContext.Provider
|
||||
value={{
|
||||
openCallDialog,
|
||||
setOpenCallDialog,
|
||||
state,
|
||||
dispatch,
|
||||
activeTab,
|
||||
setActiveTab,
|
||||
categoryLists: handleCategories.categoryLists,
|
||||
subCategoryLists: handleCategories.subCategoryLists,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AnswersContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
59
src/lib/callWidget/contexts/categories.jsx
Normal file
59
src/lib/callWidget/contexts/categories.jsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { createContext, useCallback, useEffect, useReducer } from "react";
|
||||
import useRequest from "@/lib/app/hooks/useRequest";
|
||||
import { GET_CATEGORY } from "@/core/data/apiRoutes";
|
||||
|
||||
const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case "CHANGE_ACTIVE_ID":
|
||||
return { ...state, active_id: action.id };
|
||||
case "SET_CATEGORIES":
|
||||
return { ...state, categoryLists: action.cat };
|
||||
case "SET_SUBCATEGORIES":
|
||||
return { ...state, subCategoryLists: action.subCat };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
export const CategoriesContext = createContext();
|
||||
|
||||
export const CategoriesProvider = ({ children }) => {
|
||||
const requestServer = useRequest({ auth: true, notification: false });
|
||||
const [state, dispatch] = useReducer(reducer, {
|
||||
categoryLists: [],
|
||||
subCategoryLists: [],
|
||||
active_id: null,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
requestServer(GET_CATEGORY, "get")
|
||||
.then(({ data }) => {
|
||||
const subCat = data.data;
|
||||
const cat = subCat.reduce((accumulator, currentValue) => {
|
||||
if (!accumulator.find((item) => item.category_id === currentValue.category_id)) {
|
||||
accumulator.push(currentValue);
|
||||
}
|
||||
return accumulator;
|
||||
}, []);
|
||||
dispatch({ type: "SET_CATEGORIES", cat });
|
||||
dispatch({ type: "SET_SUBCATEGORIES", subCat });
|
||||
})
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
const setCategoryID = useCallback((id) => {
|
||||
dispatch({ type: "CHANGE_ACTIVE_ID", id });
|
||||
});
|
||||
|
||||
return (
|
||||
<CategoriesContext.Provider
|
||||
value={{
|
||||
categoryLists: state.categoryLists,
|
||||
subCategoryLists: state.subCategoryLists,
|
||||
active_id: state.active_id,
|
||||
setCategoryID,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CategoriesContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -1,38 +1,46 @@
|
||||
import {useContext} from "react";
|
||||
import {AnswersContext} from "@/lib/callWidget/contexts/answers";
|
||||
import { useContext } from "react";
|
||||
import { AnswersContext } from "@/lib/callWidget/contexts/answers";
|
||||
|
||||
const useAnswers = () => {
|
||||
const {state, dispatch, activeTab, setActiveTab} = useContext(AnswersContext)
|
||||
const { state, dispatch, activeTab, setActiveTab } = useContext(AnswersContext);
|
||||
|
||||
const changeActiveTabAnswers = (newValue) => {
|
||||
dispatch({type: 'CHANGE_ACTIVE_TAB', newValue})
|
||||
setActiveTab(newValue)
|
||||
}
|
||||
dispatch({ type: "CHANGE_ACTIVE_TAB", newValue });
|
||||
setActiveTab(newValue);
|
||||
};
|
||||
const newAnswerTab = (data) => {
|
||||
const newAnswer = {
|
||||
id: data.id,
|
||||
phone_number: data.phone_number,
|
||||
date: new Date(),
|
||||
active: true
|
||||
}
|
||||
const newList = [...state, newAnswer]
|
||||
dispatch({type: 'CHANGE_LIST', newList})
|
||||
changeActiveTabAnswers(newList.length - 1)
|
||||
}
|
||||
active: true,
|
||||
active_category_id: null,
|
||||
};
|
||||
const newList = [...state, newAnswer];
|
||||
dispatch({ type: "CHANGE_LIST", newList });
|
||||
changeActiveTabAnswers(newList.length - 1);
|
||||
};
|
||||
|
||||
const closeAnswerTab = (id) => {
|
||||
const index = state.findIndex(answer => answer.id === id)
|
||||
const newIndex = index === 0 ? 0 : index - 1
|
||||
const newList = [...state]
|
||||
const index = state.findIndex((answer) => answer.id === id);
|
||||
const newIndex = index === 0 ? 0 : index - 1;
|
||||
const newList = [...state];
|
||||
newList.splice(index, 1);
|
||||
if (newList.length !== 0) {
|
||||
newList[newIndex].active = true
|
||||
setActiveTab(newIndex)
|
||||
newList[newIndex].active = true;
|
||||
setActiveTab(newIndex);
|
||||
}
|
||||
dispatch({type: 'CHANGE_LIST', newList})
|
||||
}
|
||||
dispatch({ type: "CHANGE_LIST", newList });
|
||||
};
|
||||
|
||||
return {answersList: state, activeTab, setActiveTab, changeActiveTabAnswers, closeAnswerTab, newAnswerTab}
|
||||
}
|
||||
return {
|
||||
answersList: state,
|
||||
activeTab,
|
||||
setActiveTab,
|
||||
changeActiveTabAnswers,
|
||||
closeAnswerTab,
|
||||
newAnswerTab,
|
||||
};
|
||||
};
|
||||
|
||||
export default useAnswers
|
||||
export default useAnswers;
|
||||
|
||||
@@ -29,8 +29,8 @@ const useCallerHistory = (call_id, phone_number, max_size) => {
|
||||
return {
|
||||
firstItemOfHistory: validData.length === 0 ? false : validData[0],
|
||||
historyList: validData.length < 2 ? false : validData.slice(1),
|
||||
isLoadingHistoryList: true,
|
||||
errorHistoryList: false
|
||||
isLoadingHistoryList: isLoading,
|
||||
errorHistoryList: !data
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
17
src/lib/callWidget/hooks/useCategories.jsx
Normal file
17
src/lib/callWidget/hooks/useCategories.jsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { useContext } from "react";
|
||||
import { AnswersContext } from "@/lib/callWidget/contexts/answers";
|
||||
|
||||
const useCategories = () => {
|
||||
const { categoryLists, subCategoryLists, active_category_id, dispatch } = useContext(AnswersContext);
|
||||
|
||||
const setActiveCategoryID = (tab_id, category_id) => {
|
||||
dispatch({ type: "CHANGE_ACTIVE_ID", tab_id, category_id });
|
||||
};
|
||||
return {
|
||||
categoryLists,
|
||||
subCategoryLists,
|
||||
active_category_id,
|
||||
setActiveCategoryID,
|
||||
};
|
||||
};
|
||||
export default useCategories;
|
||||
Reference in New Issue
Block a user