Browse Source

feat(web): implement received sms tab in dashboard

pull/8/head
isra el 2 years ago
parent
commit
47bd11ae08
  1. 170
      web/components/dashboard/ReceiveSMS.tsx
  2. 2
      web/pages/dashboard.tsx
  3. 5
      web/services/gatewayService.ts
  4. 35
      web/store/deviceSlice.ts

170
web/components/dashboard/ReceiveSMS.tsx

@ -0,0 +1,170 @@
import {
Alert,
AlertIcon,
Grid,
GridItem,
Spinner,
Stack,
Tab,
TabList,
TabPanel,
TabPanels,
Table,
TableContainer,
Tabs,
Tbody,
Td,
Th,
Thead,
Tr,
} from '@chakra-ui/react'
import { useEffect, useMemo, useState } from 'react'
import { useSelector } from 'react-redux'
import {
fetchReceivedSMSList,
selectDeviceList,
selectReceivedSMSList,
} from '../../store/deviceSlice'
import { useAppDispatch } from '../../store/hooks'
import { selectAuthUser } from '../../store/authSlice'
export default function ReceiveSMS() {
return (
<>
<Grid
templateColumns={{ base: 'repeat(1, 1fr)', md: 'repeat(3, 1fr)' }}
gap={6}
>
<GridItem colSpan={2}>
<ReceivedSMSList />
</GridItem>
<GridItem colSpan={1}>
<ReceiveSMSNotifications />
</GridItem>
</Grid>
</>
)
}
const ReceiveSMSNotifications = () => {
return (
<Stack spacing={3}>
<Alert status='success'>
<AlertIcon />
You can now receive SMS and view them in the dashboard, or retreive them
via the API
</Alert>
<Alert status='warning'>
<AlertIcon />
To receive SMS, you need to have an active device that has receive SMS
option enabled <small>(Turn on the switch in the app)</small>
</Alert>
<Alert status='info'>
<AlertIcon />
Webhooks will be available soon 😉
</Alert>
</Stack>
)
}
const ReceivedSMSList = () => {
const dispatch = useAppDispatch()
const [tabIndex, setTabIndex] = useState(0)
const { loading: receivedSMSListLoading, data: receivedSMSListData } =
useSelector(selectReceivedSMSList)
const deviceList = useSelector(selectDeviceList)
const authUser = useSelector(selectAuthUser)
const activeDeviceId = useMemo(() => {
return deviceList[tabIndex]?._id
}, [tabIndex, deviceList])
useEffect(() => {
if (authUser) {
dispatch(fetchReceivedSMSList(activeDeviceId))
}
}, [dispatch, authUser, activeDeviceId])
if (!receivedSMSListLoading && (!deviceList || deviceList.length == 0)) {
return (
<Alert status='warning'>
<AlertIcon />
You dont have any devices yet. Please register a device to receive SMS
</Alert>
)
}
return (
<>
<Tabs isLazy={false} index={tabIndex} onChange={setTabIndex}>
<TabList>
{deviceList.map(({ _id, brand, model }) => (
<Tab key={_id}>{`${brand} ${model}`}</Tab>
))}
</TabList>
<TabPanels>
{deviceList.map(({ _id, brand, model }) => (
<TabPanel key={_id}>
<TableContainer>
<Table variant='striped'>
<Thead>
<Tr>
<Th>sender</Th>
<Th>message</Th>
<Th>received at</Th>
</Tr>
</Thead>
<Tbody>
{receivedSMSListLoading && (
<Tr>
<Td colSpan={3} textAlign='center'>
<Spinner size='lg' />
</Td>
</Tr>
)}
{!receivedSMSListLoading &&
receivedSMSListData.length == 0 && (
<Td colSpan={3} textAlign='center'>
No SMS received
</Td>
)}
{!receivedSMSListLoading &&
receivedSMSListData.length > 0 &&
receivedSMSListData.map(
({ _id, sender, message, receivedAt }) => (
<Tr key={_id}>
<Td>{sender}</Td>
<Td whiteSpace='pre-wrap' maxW='300px'>
{message}
</Td>
<Td>
{new Date(receivedAt).toLocaleString('en-US', {
month: 'long',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true,
})}
</Td>
<Td></Td>
</Tr>
)
)}
</Tbody>
</Table>
</TableContainer>
</TabPanel>
))}
</TabPanels>
</Tabs>
</>
)
}

2
web/pages/dashboard.tsx

@ -54,13 +54,11 @@ const DashboardTabView = () => {
<Box maxW='7xl' mx={'auto'} pt={5} px={{ base: 2, sm: 12, md: 17 }}> <Box maxW='7xl' mx={'auto'} pt={5} px={{ base: 2, sm: 12, md: 17 }}>
<Tabs isLazy={false} index={tabIndex} onChange={setTabIndex}> <Tabs isLazy={false} index={tabIndex} onChange={setTabIndex}>
<TabList> <TabList>
{/* <Tab>Get Started</Tab> */}
<Tab>API Key and Devices</Tab> <Tab>API Key and Devices</Tab>
<Tab>Send SMS</Tab> <Tab>Send SMS</Tab>
<Tab>Receive SMS</Tab> <Tab>Receive SMS</Tab>
</TabList> </TabList>
<TabPanels> <TabPanels>
{/* <TabPanel>Get Started</TabPanel> */}
<TabPanel> <TabPanel>
<APIKeyAndDevices /> <APIKeyAndDevices />
</TabPanel> </TabPanel>

5
web/services/gatewayService.ts

@ -34,6 +34,11 @@ class GatewayService {
) )
return res.data.data return res.data.data
} }
async getReceivedSMSList(deviceId: string) {
const res = await httpClient.get(`/gateway/devices/${deviceId}/getReceivedSMS`)
return res.data.data
}
} }
export const gatewayService = new GatewayService() export const gatewayService = new GatewayService()

35
web/store/deviceSlice.ts

@ -11,6 +11,10 @@ const initialState = {
item: null, item: null,
list: [], list: [],
sendingSMS: false, sendingSMS: false,
receivedSMSList: {
loading: false,
data: [],
},
} }
export const fetchDevices = createAsyncThunk( export const fetchDevices = createAsyncThunk(
@ -29,6 +33,22 @@ export const fetchDevices = createAsyncThunk(
} }
) )
export const fetchReceivedSMSList = createAsyncThunk(
'device/fetchReceivedSMSList',
async (id: string, { rejectWithValue }) => {
try {
const res = await gatewayService.getReceivedSMSList(id)
return res
} catch (e) {
toast({
title: e.response.data.error || 'Failed to Fetch received sms list',
status: 'error',
})
return rejectWithValue(e.response.data)
}
}
)
export const deleteDevice = createAsyncThunk( export const deleteDevice = createAsyncThunk(
'device/deleteDevice', 'device/deleteDevice',
async (id: string, { rejectWithValue, dispatch }) => { async (id: string, { rejectWithValue, dispatch }) => {
@ -100,6 +120,19 @@ export const deviceSlice = createSlice({
.addCase(sendSMS.rejected, (state) => { .addCase(sendSMS.rejected, (state) => {
state.sendingSMS = false state.sendingSMS = false
}) })
.addCase(fetchReceivedSMSList.pending, (state) => {
state.receivedSMSList.loading = true
})
.addCase(
fetchReceivedSMSList.fulfilled,
(state, action: PayloadAction<any>) => {
state.receivedSMSList.loading = false
state.receivedSMSList.data = action.payload
}
)
.addCase(fetchReceivedSMSList.rejected, (state) => {
state.receivedSMSList.loading = false
})
}, },
}) })
@ -109,5 +142,7 @@ export const selectDeviceList = (state: RootState) => state.device.list
export const selectDeviceItem = (state: RootState) => state.device.item export const selectDeviceItem = (state: RootState) => state.device.item
export const selectDeviceLoading = (state: RootState) => state.device.loading export const selectDeviceLoading = (state: RootState) => state.device.loading
export const selectSendingSMS = (state: RootState) => state.device.sendingSMS export const selectSendingSMS = (state: RootState) => state.device.sendingSMS
export const selectReceivedSMSList = (state: RootState) =>
state.device.receivedSMSList
export default deviceSlice.reducer export default deviceSlice.reducer
Loading…
Cancel
Save