CFE-26 Merge branch 'feature/CFE-26_widget_tabs_details' into 'develop'

This commit is contained in:
AmirHossein Mahmoodi
2023-10-21 10:02:22 +00:00
14 changed files with 171 additions and 58 deletions

View File

@@ -44,17 +44,17 @@ merge:test:lint:
- .env.local - .env.local
- .env.test - .env.test
merge:test:build: #merge:test:build:
stage: test:build # stage: test:build
script: # script:
- npm run build # - npm run build
only: # only:
- merge_requests # - merge_requests
artifacts: # artifacts:
paths: # paths:
- node_modules # - node_modules
- .env.local # - .env.local
- .env.test # - .env.test
build: build:
stage: build stage: build
@@ -97,18 +97,18 @@ test:lint:
- .env.local - .env.local
- .env.test - .env.test
test:build: #test:build:
stage: test:build # stage: test:build
script: # script:
- npm run build # - npm run build
only: # only:
- develop # - develop
- main # - main
artifacts: # artifacts:
paths: # paths:
- node_modules # - node_modules
- .env.local # - .env.local
- .env.test # - .env.test
deploy: deploy:
stage: deploy stage: deploy

View File

@@ -1,51 +1,51 @@
import {act, render, screen} from "@testing-library/react"; import {act, render, screen, waitFor} from "@testing-library/react";
import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider"; import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider";
import DeleteContent from "@/components/dashboard/role-management/Form/DeleteForm/DeleteContent"; import DeleteContent from "@/components/dashboard/role-management/Form/DeleteForm/DeleteContent";
import UpdateContent from "@/components/dashboard/role-management/Form/UpdateForm/UpdateContent"; import UpdateContent from "@/components/dashboard/role-management/Form/UpdateForm/UpdateContent";
describe("Create Content component from Create Form Component in Role Management Component",()=> { describe("Create Content component from Create Form Component in Role Management Component", () => {
describe("Rendering", () => { describe("Rendering", () => {
it('should see DeleteDialog text in the top ', async () => { it('should see DeleteDialog text in the top ', async () => {
render( render(
<MockAppWithProviders> <MockAppWithProviders>
<DeleteContent rowId={1}/> <DeleteContent rowId = {1}/>
</MockAppWithProviders> </MockAppWithProviders>
) )
const textElement = screen.queryByText("حذف") const textElement = screen.queryByText("حذف")
act(()=>{ await waitFor(() => {
expect(textElement).toBeInTheDocument() expect(textElement).toBeInTheDocument()
}) })
}) })
it('should see DeleteDialog text content ', async () => { it('should see DeleteDialog text content ', async () => {
render( render(
<MockAppWithProviders> <MockAppWithProviders>
<DeleteContent rowId={1}/> <DeleteContent rowId = {1}/>
</MockAppWithProviders> </MockAppWithProviders>
) )
const textElement = screen.queryByText("آیا از حدف این مورد اطمینان دارید ؟") const textElement = screen.queryByText("آیا از حدف این مورد اطمینان دارید ؟")
act(()=>{ await waitFor(() => {
expect(textElement).toBeInTheDocument() expect(textElement).toBeInTheDocument()
}) })
}) })
it('should see delete text in the delete button ', () => { it('should see delete text in the delete button ', async () => {
render( render(
<MockAppWithProviders> <MockAppWithProviders>
<DeleteContent rowId={1}/> <DeleteContent rowId = {1}/>
</MockAppWithProviders> </MockAppWithProviders>
) )
const buttonElement = screen.queryByText("حذف کردن") const buttonElement = screen.queryByText("حذف کردن")
act(()=>{ await waitFor(() => {
expect(buttonElement).toBeInTheDocument() expect(buttonElement).toBeInTheDocument()
}) })
}); });
it('should see cancel text in the cancel button ', () => { it('should see cancel text in the cancel button ', async () => {
render( render(
<MockAppWithProviders> <MockAppWithProviders>
<DeleteContent rowId={1}/> <DeleteContent rowId = {1}/>
</MockAppWithProviders> </MockAppWithProviders>
) )
const buttonElement = screen.queryByText("انصراف") const buttonElement = screen.queryByText("انصراف")
act(()=>{ await waitFor(() => {
expect(buttonElement).toBeInTheDocument() expect(buttonElement).toBeInTheDocument()
}) })
}); });

View File

@@ -1,8 +1,8 @@
import RoleManagementComponent from "@/components/dashboard/role-management/RoleManagementComponent"; import RoleManagementComponent from "@/components/dashboard/role-management/RoleManagementComponent";
import DashboardLayout from "@/layouts/DashboardLayout"; import DashboardLayout from "@/layouts/DashboardLayout";
import moment from "jalali-moment";
function DashboardRoleManagementComponent() { function DashboardRoleManagementComponent() {
return ( return (
<DashboardLayout> <DashboardLayout>
<RoleManagementComponent /> <RoleManagementComponent />

View File

@@ -0,0 +1,17 @@
import {Stack, Typography} from "@mui/material";
import CallIcon from '@mui/icons-material/Call';
import CallTabTime from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/CallTabTime";
const CallTabDetails = ({tab}) => {
return (
<Stack direction = "row" justifyContent = "center" alignItems = "center" spacing = {3}>
<CallIcon/>
<Stack alignItems = {"start"}>
<Typography>{tab.phone_number}</Typography>
<CallTabTime realTimeDate = {tab.date}/>
</Stack>
</Stack>
)
}
export default CallTabDetails

View File

@@ -1,19 +1,26 @@
import {IconButton, Stack, Typography, Zoom} from "@mui/material"; import {IconButton, Stack, Zoom} from "@mui/material";
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import useAnswers from "@/lib/callWidget/hooks/useAnswers"; import useAnswers from "@/lib/callWidget/hooks/useAnswers";
import CallTabDetails
from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/CallTabDetails";
const CallTabLabel = ({tab}) => { const CallTabLabel = ({tab, index}) => {
const {closeAnswerTab} = useAnswers() const {closeAnswerTab, activeTab} = useAnswers()
const handleCloseClick = (id) => { const handleCloseClick = (id) => {
closeAnswerTab(id) closeAnswerTab(id)
}; };
return ( return (
<Stack sx={{width: '100%'}} direction={'row'} alignItems={'center'} justifyContent={'space-between'}> <Stack sx = {{
<Typography>{tab.phone_number} - {tab.id}</Typography> width: '100%',
<Zoom in={tab.active}> px: 1,
<IconButton onClick={() => handleCloseClick(tab.id)}> borderRight: activeTab === index ? 0 : activeTab - 1 === index ? 0 : 1,
<CloseIcon/> borderRightColor: 'divider'
}} direction = {'row'} alignItems = {'center'} justifyContent = {'space-between'}>
<CallTabDetails tab = {tab}/>
<Zoom in = {tab.active}>
<IconButton size = "small" onClick = {() => handleCloseClick(tab.id)}>
<CloseIcon fontSize = "small"/>
</IconButton> </IconButton>
</Zoom> </Zoom>
</Stack> </Stack>

View File

@@ -0,0 +1,29 @@
import {Typography} from "@mui/material";
import {useEffect, useState} from "react";
import moment from "jalali-moment";
import useLanguage from "@/lib/app/hooks/useLanguage";
const CallTabTime = ({realTimeDate}) => {
const {languageApp} = useLanguage()
const [date, setDate] = useState('...')
const changeTabTime = (tabTime) => {
moment.relativeTimeThreshold('ss', 1)
return moment(tabTime).locale(languageApp).fromNow()
}
useEffect(() => {
const timer = setInterval(() => {
setDate(changeTabTime(realTimeDate))
}, 1000)
return () => {
clearInterval(timer)
}
}, [realTimeDate]);
return (
<Typography variant = "caption"
color = "gray">{date}</Typography>
)
}
export default CallTabTime

View File

@@ -0,0 +1,28 @@
import {render, screen, waitFor} from "@testing-library/react";
import MockAppWithProviders from "../../../../../../../../../mocks/AppWithProvider";
import CallTabDetails
from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/CallTabDetails";
const tab = {
phone_number: "09134849737",
id: 1,
date: new Date()
}
describe("Call Tab Details from Call Tan List", () => {
describe("Rendering", () => {
it('Should see the phone number on tab detail', async () => {
render(
<MockAppWithProviders>
<CallTabDetails tab = {tab}/>
</MockAppWithProviders>
)
const phoneNumberElement = screen.getByText("09134849737")
await waitFor(() => {
expect(phoneNumberElement).toHaveTextContent("09134849737")
})
});
})
})

View File

@@ -0,0 +1,25 @@
import {render, screen, waitFor} from "@testing-library/react";
import MockAppWithProviders from "../../../../../../../../../mocks/AppWithProvider";
import CallTabTime from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/CallTabTime";
const tab = {
phone_number: "09134849737",
id: 1,
date: new Date()
}
describe("Call Tab Details from Call Tan List", () => {
describe("Rendering", () => {
it('Should see the date on tab detail', async () => {
render(
<MockAppWithProviders>
<CallTabTime realTimeDate = {tab.date}/>
</MockAppWithProviders>
)
await waitFor(() => {
expect(screen.getByText(/ثانیه پیش/i)).toBeInTheDocument()
})
});
})
})

View File

@@ -10,14 +10,20 @@ const CallTabsList = () => {
}; };
return ( return (
<Box sx={{borderBottom: 1, borderColor: 'divider'}}> <Box sx = {{borderBottom: 1, borderColor: 'divider'}}>
<Tabs <Tabs
value={activeTab} value = {activeTab}
onChange={handleChange} onChange = {handleChange}
variant={'fullWidth'} variant = "scrollable"
scrollButtons = "auto"
sx = {{background: "#e0e0e0"}}
> >
{answersList.map((answer) => ( {answersList.map((answer, index) => (
<Tab component={'div'} sx={{py: 0.5, pr: 0}} label={<CallTabLabel tab={answer}/>} key={answer.id}/> <Tab component = {'div'} sx = {{
width: 350, p: 0, py: 0.5, background: answer.active ? "#fff" : null,
borderTopRightRadius: answer.active ? "16px" : 0,
borderTopLeftRadius: answer.active ? "16px" : 0,
}} label = {<CallTabLabel index = {index} tab = {answer}/>} key = {answer.id}/>
))} ))}
</Tabs> </Tabs>
</Box> </Box>

View File

@@ -38,8 +38,8 @@ const CallWidgetDialog = () => {
return ( return (
<Dialog <Dialog
fullScreen fullScreen
open={openCallDialog} open = {openCallDialog}
TransitionComponent={DialogTransition} TransitionComponent = {DialogTransition}
> >
<CallTabs/> <CallTabs/>
</Dialog> </Dialog>

View File

@@ -20,7 +20,7 @@ export const AnswersProvider = ({children}) => {
const [state, dispatch] = useReducer(reducer, []); const [state, dispatch] = useReducer(reducer, []);
return <AnswersContext.Provider return <AnswersContext.Provider
value={{ value = {{
openCallDialog, openCallDialog,
setOpenCallDialog, setOpenCallDialog,
state, state,

View File

@@ -12,6 +12,7 @@ const useAnswers = () => {
const newAnswer = { const newAnswer = {
id: data.id, id: data.id,
phone_number: data.phone_number, phone_number: data.phone_number,
date: new Date(),
active: true active: true
} }
const newList = [...state, newAnswer] const newList = [...state, newAnswer]

View File

@@ -1,4 +1,4 @@
import "&/fontiran.scss"; import "&/fontiran.css";
import AppLayout from "@/layouts/AppLayout"; import AppLayout from "@/layouts/AppLayout";
import MuiLayout from "@/layouts/MuiLayout"; import MuiLayout from "@/layouts/MuiLayout";
import {LanguageProvider} from "@/lib/app/contexts/language"; import {LanguageProvider} from "@/lib/app/contexts/language";
@@ -14,11 +14,11 @@ const App = ({Component, pageProps}) => {
return (<> return (<>
<UserProvider> <UserProvider>
<LanguageProvider> <LanguageProvider>
<NextIntlProvider locale={pageProps.locale} messages={pageProps.messages || {}}> <NextIntlProvider locale = {pageProps.locale} messages = {pageProps.messages || {}}>
<MuiLayout isBot={pageProps.isBot}> <MuiLayout isBot = {pageProps.isBot}>
{pageProps.messages ? <TitlePage text={pageProps.title}/> : ''} {pageProps.messages ? <TitlePage text = {pageProps.title}/> : ''}
<LoadingProvider> <LoadingProvider>
<AppLayout isBot={pageProps.isBot}> <AppLayout isBot = {pageProps.isBot}>
<SocketProvider> <SocketProvider>
<Component {...pageProps} /> <Component {...pageProps} />
</SocketProvider> </SocketProvider>