Browse Source

chore(web): upgrade dependencies

pull/4/head v2.0.1
isra el 2 years ago
parent
commit
7d68b74b25
  1. 133
      web/components/Navbar.tsx
  2. 7
      web/components/dashboard/ApiKeyList.tsx
  3. 17
      web/components/dashboard/DeviceList.tsx
  4. 4
      web/components/dashboard/GenerateApiKey.tsx
  5. 6
      web/components/dashboard/SendSMS.tsx
  6. 5
      web/next.config.js
  7. 43
      web/package.json
  8. 9
      web/pages/_app.tsx
  9. 15
      web/pages/dashboard.tsx
  10. 1
      web/pages/index.tsx
  11. 5
      web/pages/login.tsx
  12. 5
      web/pages/register.tsx
  13. 3704
      web/pnpm-lock.yaml
  14. 5
      web/services/gatewayService.ts
  15. 2
      web/store/apiKeySlice.ts
  16. 2
      web/store/authSlice.ts
  17. 23
      web/store/deviceSlice.ts
  18. 5
      web/store/hooks.ts
  19. 1
      web/store/store.ts

133
web/components/Navbar.tsx

@ -11,7 +11,6 @@ import {
useColorModeValue,
Stack,
useColorMode,
Image,
SimpleGrid,
} from '@chakra-ui/react'
import Link from 'next/link'
@ -19,6 +18,7 @@ import { MoonIcon, SunIcon } from '@chakra-ui/icons'
import Router from 'next/router'
import { useDispatch, useSelector } from 'react-redux'
import { logout, selectAuthUser } from '../store/authSlice'
import Image from 'next/image'
export default function Navbar() {
const dispatch = useDispatch()
@ -38,11 +38,10 @@ export default function Navbar() {
<Flex alignItems={'center'}>
<Image
alt={'Hero Image'}
fit={'cover'}
w={'30px'}
h={'30px'}
width={30}
height={30}
src={'/images/sms-gateway-logo.png'}
borderRadius='full'
style={{ borderRadius: '50%' }}
/>
<Box style={{ cursor: 'pointer', marginLeft: '5px' }}>
TextBee
@ -50,76 +49,74 @@ export default function Navbar() {
</Flex>
</Link>
<Flex alignItems={'center'}>
<Stack direction={'row'} spacing={7}>
<Button onClick={toggleColorMode}>
{colorMode === 'light' ? <MoonIcon /> : <SunIcon />}
</Button>
<Stack alignItems='center' direction='row' spacing={5}>
<Button onClick={toggleColorMode} aria-label={'Toggle Color Mode'}>
{colorMode === 'light' ? <MoonIcon /> : <SunIcon />}
</Button>
<Menu>
<Link href='https://github.com/vernu/textbee' passHref>
<MenuButton>Github</MenuButton>
</Link>
</Menu>
{!authUser && (
<Menu>
<Link href='https://github.com/vernu/textbee' passHref>
<MenuButton>Github</MenuButton>
<Link href='/login' passHref>
<MenuButton>Login</MenuButton>
</Link>
<Link href='/register' passHref>
<MenuButton>Register</MenuButton>
</Link>
</Menu>
)}
{!authUser && (
<Menu>
<Link href='/login' passHref>
<MenuButton>Login</MenuButton>
</Link>
<Link href='/register' passHref>
<MenuButton>Register</MenuButton>
</Link>
</Menu>
)}
{authUser && (
<Menu>
<MenuButton
as={Button}
rounded={'full'}
variant={'link'}
cursor={'pointer'}
minW={0}
>
<Avatar
size={'sm'}
name={authUser.name}
src={authUser?.avatar}
/>
</MenuButton>
<MenuList alignItems={'center'}>
<MenuItem>
<SimpleGrid columns={2} spacing={3}>
<Avatar
size={'sm'}
name={authUser.name}
src={authUser?.avatar}
/>
{authUser?.name}
</SimpleGrid>
</MenuItem>
{authUser && (
<Menu>
<MenuButton
as={Button}
rounded={'full'}
variant={'link'}
cursor={'pointer'}
minW={0}
<MenuDivider />
<MenuItem
onClick={() => {
Router.push('/dashboard')
}}
>
<Avatar
size={'sm'}
name={authUser.name}
src={authUser?.avatar}
/>
</MenuButton>
<MenuList alignItems={'center'}>
<MenuItem>
<SimpleGrid columns={2} spacing={3}>
<Avatar
size={'sm'}
name={authUser.name}
src={authUser?.avatar}
/>
{authUser?.name}
</SimpleGrid>
</MenuItem>
<MenuDivider />
<MenuItem
onClick={() => {
Router.push('/dashboard')
}}
>
Dashboard
</MenuItem>
<MenuItem
onClick={() => {
dispatch(logout())
}}
>
Logout
</MenuItem>
</MenuList>
</Menu>
)}
</Stack>
</Flex>
Dashboard
</MenuItem>
<MenuItem
onClick={() => {
dispatch(logout())
}}
>
Logout
</MenuItem>
</MenuList>
</Menu>
)}
</Stack>
</Flex>
</Box>
</>

7
web/components/dashboard/ApiKeyList.tsx

@ -11,7 +11,7 @@ import {
Tr,
} from '@chakra-ui/react'
import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { useSelector } from 'react-redux'
import {
deleteApiKey,
fetchApiKeys,
@ -19,9 +19,10 @@ import {
selectApiKeyLoading,
} from '../../store/apiKeySlice'
import { selectAuthUser } from '../../store/authSlice'
import { useAppDispatch } from '../../store/hooks'
const ApiKeyRow = ({ apiKey }: any) => {
const dispatch = useDispatch()
const dispatch = useAppDispatch()
const handleDelete = async () => {
dispatch(deleteApiKey(apiKey._id))
@ -41,7 +42,7 @@ const ApiKeyRow = ({ apiKey }: any) => {
}
const ApiKeyList = () => {
const dispatch = useDispatch()
const dispatch = useAppDispatch()
const loading = useSelector(selectApiKeyLoading)
const apiKeyList = useSelector(selectApiKeyList)

17
web/components/dashboard/DeviceList.tsx

@ -12,11 +12,12 @@ import {
Tr,
} from '@chakra-ui/react'
import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { useSelector } from 'react-redux'
import { selectAuthUser } from '../../store/authSlice'
import { fetchDevices, selectDeviceList, selectDeviceLoading } from '../../store/deviceSlice'
import { deleteDevice, fetchDevices, selectDeviceList, selectDeviceLoading } from '../../store/deviceSlice'
import { useAppDispatch } from '../../store/hooks'
const DeviceRow = ({ device }: any) => {
const DeviceRow = ({ device, onDelete }: any) => {
const { enabled, model, brand, _id, createdAt } = device
return (
<Tr>
@ -28,7 +29,7 @@ const DeviceRow = ({ device }: any) => {
<IconButton
aria-label='Delete'
icon={<DeleteIcon />}
onDoubleClick={(e) => {}}
onDoubleClick={onDelete}
/>
</Tooltip>
</Td>
@ -37,7 +38,7 @@ const DeviceRow = ({ device }: any) => {
}
const DeviceList = () => {
const dispatch = useDispatch()
const dispatch = useAppDispatch()
const authUser = useSelector(selectAuthUser)
useEffect(() => {
@ -49,7 +50,9 @@ const DeviceList = () => {
const deviceList = useSelector(selectDeviceList)
const loading = useSelector(selectDeviceLoading)
const onDelete = (apiKeyId: string) => {}
const onDelete = (apiKeyId: string) => {
dispatch(deleteDevice(apiKeyId))
}
return (
<TableContainer>
@ -81,7 +84,7 @@ const DeviceList = () => {
{!loading &&
deviceList.length > 0 &&
deviceList.map((device) => (
<DeviceRow key={device._id} device={device} />
<DeviceRow key={device._id} device={device} onDelete={() => onDelete(device._id)} />
))}
</Tbody>
</Table>

4
web/components/dashboard/GenerateApiKey.tsx

@ -14,10 +14,10 @@ import {
useToast,
} from '@chakra-ui/react'
import { useState } from 'react'
import { useDispatch } from 'react-redux'
import QRCode from 'react-qr-code'
import { fetchApiKeys } from '../../store/apiKeySlice'
import { gatewayService } from '../../services/gatewayService'
import { useAppDispatch } from '../../store/hooks'
const NewApiKeyGeneratedModal = ({
isOpen = false,
@ -105,7 +105,7 @@ export default function GenerateApiKey() {
const [showGeneratedApiKeyModal, setShowGeneratedApiKeyModal] =
useState(false)
const dispatch = useDispatch()
const dispatch = useAppDispatch()
const generateApiKey = async () => {
setGeneratingApiKey(true)

6
web/components/dashboard/SendSMS.tsx

@ -18,12 +18,13 @@ import {
useToast,
} from '@chakra-ui/react'
import { useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { useSelector } from 'react-redux'
import {
selectDeviceList,
selectSendingSMS,
sendSMS,
} from '../../store/deviceSlice'
import { useAppDispatch } from '../../store/hooks'
export const SendSMSForm = ({ deviceList, formData, handleChange }) => {
return (
@ -71,7 +72,7 @@ export default function SendSMS() {
const { isOpen, onOpen, onClose } = useDisclosure()
const deviceList = useSelector(selectDeviceList)
const toast = useToast()
const dispatch = useDispatch()
const dispatch = useAppDispatch()
const sendingSMS = useSelector(selectSendingSMS)
@ -98,6 +99,7 @@ export default function SendSMS() {
// TODO: validate phone numbers
}
dispatch(
sendSMS({
deviceId,

5
web/next.config.js

@ -1,6 +1,11 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
i18n: {
locales: ['en-US'],
defaultLocale: 'en-US',
},
async redirects() {
return [
{

43
web/package.json

@ -9,26 +9,31 @@
"lint": "next lint"
},
"dependencies": {
"@chakra-ui/icons": "^1.1.7",
"@chakra-ui/react": "^1.8.7",
"@emotion/react": "^11.8.2",
"@emotion/styled": "^11.8.1",
"@react-oauth/google": "^0.11.1",
"@reduxjs/toolkit": "^1.9.3",
"axios": "^0.26.1",
"framer-motion": "^6.2.8",
"next": "12.1.4",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-qr-code": "^2.0.5",
"react-redux": "^7.2.8"
"@chakra-ui/icons": "^2.1.1",
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"@react-oauth/google": "^0.12.1",
"@reduxjs/toolkit": "^2.0.1",
"axios": "^1.6.5",
"framer-motion": "^10.18.0",
"next": "14.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-qr-code": "^2.0.12",
"react-redux": "^9.1.0"
},
"engines": {
"node": ">=18.17.0"
},
"devDependencies": {
"@types/node": "17.0.23",
"@types/react": "17.0.43",
"@types/react-dom": "17.0.14",
"eslint": "8.12.0",
"eslint-config-next": "12.1.4",
"typescript": "4.6.3"
"@types/node": "20.11.5",
"@types/react": "18.2.48",
"@types/react-dom": "18.2.18",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"eslint": "8.56.0",
"eslint-config-next": "14.1.0",
"typescript": "5.3.3"
}
}

9
web/pages/_app.tsx

@ -2,14 +2,19 @@ import type { AppProps } from 'next/app'
import { Provider } from 'react-redux'
import { store } from '../store/store'
import { Box, ChakraProvider } from '@chakra-ui/react'
import Navbar from '../components/Navbar'
import Meta from '../components/meta/Meta'
import { GoogleOAuthProvider } from '@react-oauth/google'
import ErrorBoundary from '../components/ErrorBoundary'
import Footer from '../components/Footer'
import Analytics from '../components/analytics/Analytics'
import dynamic from 'next/dynamic'
function MyApp({ Component, pageProps }: AppProps) {
const NoSSRNavbar = dynamic(() => import('../components/Navbar'), {
ssr: false,
})
return (
<ErrorBoundary>
<Provider store={store}>
@ -19,7 +24,7 @@ function MyApp({ Component, pageProps }: AppProps) {
>
<ChakraProvider>
<Meta />
<Navbar />
<NoSSRNavbar />
<Wrapper>
<Component {...pageProps} />
</Wrapper>

15
web/pages/dashboard.tsx

@ -1,5 +1,4 @@
import { Box, Flex, SimpleGrid, useToast } from '@chakra-ui/react'
import { Box, SimpleGrid, useToast } from '@chakra-ui/react'
import ApiKeyList from '../components/dashboard/ApiKeyList'
import UserStats from '../components/dashboard/UserStats'
import GenerateApiKey from '../components/dashboard/GenerateApiKey'
@ -10,8 +9,16 @@ import Router from 'next/router'
import { useEffect } from 'react'
import SendSMS from '../components/dashboard/SendSMS'
import ErrorBoundary from '../components/ErrorBoundary'
import dynamic from 'next/dynamic'
export default function Dashboard() {
const NoSSRAnimatedWrapper = dynamic(
() => import('../components/AnimatedScrollWrapper'),
{
ssr: false,
}
)
const authUser = useSelector(selectAuthUser)
const toast = useToast()
useEffect(() => {
@ -25,7 +32,7 @@ export default function Dashboard() {
}
}, [authUser, toast])
return (
<>
<NoSSRAnimatedWrapper>
<UserStats />
<Box maxW='7xl' mx={'auto'} pt={5} px={{ base: 2, sm: 12, md: 17 }}>
<SimpleGrid columns={{ base: 1, md: 2 }} spacing={{ base: 5, lg: 8 }}>
@ -43,6 +50,6 @@ export default function Dashboard() {
</Box>
</SimpleGrid>
</Box>
</>
</NoSSRAnimatedWrapper>
)
}

1
web/pages/index.tsx

@ -18,6 +18,7 @@ export default function HomePage() {
useGoogleOneTapLogin({
onSuccess: ({ credential: idToken }) => {
dispatch(
// @ts-ignore
loginWithGoogle({
idToken,
})

5
web/pages/login.tsx

@ -18,9 +18,10 @@ import Link from 'next/link'
import { useState } from 'react'
import { ViewIcon, ViewOffIcon } from '@chakra-ui/icons'
import { login, loginWithGoogle, selectAuthLoading, selectAuthUser } from '../store/authSlice'
import { useDispatch, useSelector } from 'react-redux'
import { useSelector } from 'react-redux'
import { LoginRequestPayload } from '../services/types'
import { GoogleLogin } from '@react-oauth/google'
import { useAppDispatch } from '../store/hooks'
export default function LoginPage() {
const [showPassword, setShowPassword] = useState<boolean>(false)
@ -30,7 +31,7 @@ export default function LoginPage() {
password: '',
})
const dispatch = useDispatch()
const dispatch = useAppDispatch()
const toast = useToast()
const authUser = useSelector(selectAuthUser)
const loading = useSelector(selectAuthLoading)

5
web/pages/register.tsx

@ -22,9 +22,10 @@ import {
selectAuthUser,
selectAuthLoading,
} from '../store/authSlice'
import { useDispatch, useSelector } from 'react-redux'
import { useSelector } from 'react-redux'
import { RegisterRequestPayload } from '../services/types'
import { GoogleLogin } from '@react-oauth/google'
import { useAppDispatch } from '../store/hooks'
export default function RegisterPage() {
const [showPassword, setShowPassword] = useState(false)
@ -34,7 +35,7 @@ export default function RegisterPage() {
password: '',
})
const toast = useToast()
const dispatch = useDispatch()
const dispatch = useAppDispatch()
const authUser = useSelector(selectAuthUser)
const loading = useSelector(selectAuthLoading)

3704
web/pnpm-lock.yaml
File diff suppressed because it is too large
View File

5
web/services/gatewayService.ts

@ -22,6 +22,11 @@ class GatewayService {
return res.data.data
}
async deleteDevice(id: string) {
const res = await httpClient.delete(`/gateway/devices/${id}`)
return res.data.data
}
async sendSMS(deviceId: string, payload: SendSMSRequestPayload) {
const res = await httpClient.post(
`/gateway/devices/${deviceId}/sendSMS`,

2
web/store/apiKeySlice.ts

@ -4,7 +4,7 @@ import { createStandaloneToast } from '@chakra-ui/react'
import { RootState } from './store'
import { gatewayService } from '../services/gatewayService'
const toast = createStandaloneToast()
const { toast } = createStandaloneToast()
const initialState = {
loading: false,

2
web/store/authSlice.ts

@ -13,7 +13,7 @@ import { removeUserAndToken, saveUserAndToken } from '../shared/utils'
import { LOCAL_STORAGE_KEY } from '../shared/constants'
import { googleLogout } from '@react-oauth/google'
import { authService } from '../services/authService'
const toast = createStandaloneToast()
const { toast } = createStandaloneToast()
const initialState: AuthState = {
loading: false,

23
web/store/deviceSlice.ts

@ -4,7 +4,7 @@ import { createStandaloneToast } from '@chakra-ui/react'
import { RootState } from './store'
import { gatewayService } from '../services/gatewayService'
const toast = createStandaloneToast()
const { toast } = createStandaloneToast()
const initialState = {
loading: false,
@ -29,6 +29,27 @@ export const fetchDevices = createAsyncThunk(
}
)
export const deleteDevice = createAsyncThunk(
'device/deleteDevice',
async (id: string, { rejectWithValue, dispatch }) => {
try {
const res = await gatewayService.deleteDevice(id)
dispatch(fetchDevices())
toast({
title: 'Device deleted successfully',
status: 'success',
})
return res
} catch (e) {
toast({
title: e.response?.data?.error || 'Failed to delete device',
status: 'error',
})
return rejectWithValue(e.response?.data)
}
}
)
export const sendSMS = createAsyncThunk(
'device/sendSMS',
async ({ deviceId, payload }: any, { rejectWithValue }) => {

5
web/store/hooks.ts

@ -0,0 +1,5 @@
import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux'
import type { RootState, AppDispatch } from './store'
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

1
web/store/store.ts

@ -9,7 +9,6 @@ export const store = configureStore({
apiKey: apiKeyReducer,
device: deviceReducer,
},
enhancers: [],
})
export type RootState = ReturnType<typeof store.getState>

Loading…
Cancel
Save