Browse Source

feat(web): improve dashboard stats

pull/4/head
isra el 2 years ago
parent
commit
ff63cdca8b
  1. 31
      web/components/dashboard/UserStats.tsx
  2. 10
      web/services/statsService.ts
  3. 56
      web/store/statsSlice.ts
  4. 2
      web/store/store.ts

31
web/components/dashboard/UserStats.tsx

@ -1,15 +1,27 @@
import { Box, SimpleGrid, chakra } from '@chakra-ui/react' import { Box, SimpleGrid, chakra } from '@chakra-ui/react'
import React from 'react'
import React, { useEffect } from 'react'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import { selectApiKeyList } from '../../store/apiKeySlice'
import { selectAuthUser } from '../../store/authSlice' import { selectAuthUser } from '../../store/authSlice'
import { selectDeviceList } from '../../store/deviceSlice'
import UserStatsCard from './UserStatsCard' import UserStatsCard from './UserStatsCard'
import {
fetchStats,
selectStatsData,
selectStatsLoading,
} from '../../store/statsSlice'
import { useAppDispatch, useAppSelector } from '../../store/hooks'
const UserStats = () => { const UserStats = () => {
const authUser = useSelector(selectAuthUser) const authUser = useSelector(selectAuthUser)
const deviceList = useSelector(selectDeviceList)
const apiKeyList = useSelector(selectApiKeyList)
const { totalApiKeyCount, totalDeviceCount, totalSMSCount } =
useAppSelector(selectStatsData)
const statsLoading = useAppSelector(selectStatsLoading)
const dispatch = useAppDispatch()
useEffect(() => {
dispatch(fetchStats())
}, [dispatch])
return ( return (
<> <>
@ -26,13 +38,16 @@ const UserStats = () => {
<SimpleGrid columns={{ base: 3 }} spacing={{ base: 5, lg: 8 }}> <SimpleGrid columns={{ base: 3 }} spacing={{ base: 5, lg: 8 }}>
<UserStatsCard <UserStatsCard
title={'Registered '} title={'Registered '}
stat={`${deviceList?.length || '-:-'} Devices`}
stat={`${statsLoading ? '-:-' : totalDeviceCount} Devices`}
/> />
<UserStatsCard <UserStatsCard
title={'Generated'} title={'Generated'}
stat={`${apiKeyList?.length || '-:-'} API Keys`}
stat={`${statsLoading ? '-:-' : totalApiKeyCount} API Keys`}
/>
<UserStatsCard
title={'Sent'}
stat={`${statsLoading ? '-:-' : totalSMSCount} SMS Sent`}
/> />
<UserStatsCard title={'Sent'} stat={'-:- SMS'} />
</SimpleGrid> </SimpleGrid>
</SimpleGrid> </SimpleGrid>
</Box> </Box>

10
web/services/statsService.ts

@ -0,0 +1,10 @@
import httpClient from '../lib/httpClient'
class StatsService {
async getStats() {
const res = await httpClient.get(`/gateway/stats`)
return res.data.data
}
}
export const statsService = new StatsService()

56
web/store/statsSlice.ts

@ -0,0 +1,56 @@
import { createAsyncThunk, createSlice, isAnyOf } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import { createStandaloneToast } from '@chakra-ui/react'
import { RootState } from './store'
import { statsService } from '../services/statsService'
const { toast } = createStandaloneToast()
const initialState = {
loading: false,
data: {
totalApiKeyCount: 0,
totalDeviceCount: 0,
totalSMSCount: 0,
},
}
export const fetchStats = createAsyncThunk(
'gateway/fetchStats',
async (_, { rejectWithValue }) => {
try {
const res = await statsService.getStats()
return res
} catch (e) {
toast({
title: e.response.data.error || 'Failed to Fetch stats',
status: 'error',
})
return rejectWithValue(e.response.data)
}
}
)
export const statsSlice = createSlice({
name: 'stats',
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchStats.fulfilled, (state, action: PayloadAction<any>) => {
state.loading = false
state.data = action.payload
})
.addCase(fetchStats.rejected, (state) => {
state.loading = false
})
.addMatcher(isAnyOf(fetchStats.pending), (state) => {
state.loading = true
})
},
})
export const selectStatsLoading = (state: RootState) => state.stats.loading
export const selectStatsData = (state: RootState) => state.stats.data
export default statsSlice.reducer

2
web/store/store.ts

@ -2,12 +2,14 @@ import { configureStore } from '@reduxjs/toolkit'
import apiKeyReducer from './apiKeySlice' import apiKeyReducer from './apiKeySlice'
import authReducer from './authSlice' import authReducer from './authSlice'
import deviceReducer from './deviceSlice' import deviceReducer from './deviceSlice'
import statsReducer from './statsSlice'
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
auth: authReducer, auth: authReducer,
apiKey: apiKeyReducer, apiKey: apiKeyReducer,
device: deviceReducer, device: deviceReducer,
stats: statsReducer,
}, },
}) })

Loading…
Cancel
Save