Make initial version of userpage; remove deprecated user routes, services and api calls (replaced by person queries)

This commit is contained in:
ShootingStar91
2024-07-12 16:48:21 +03:00
parent a10bf9f7fe
commit e1e01501d3
7 changed files with 66 additions and 50 deletions
+10 -1
View File
@@ -26,7 +26,16 @@ router.post('/login', async (req, res) => {
expiresIn: LOGIN_VALID_MS,
})
return res.status(200).send({ token, username: result.user_name, role: getRole(result.now_user_group ?? '') })
const personResult = await nowDb.com_people.findFirst({ where: { user_id: result.user_id } })
if (!personResult) throw new Error('User found but not person; this should not happen.')
return res.status(200).send({
token,
username: result.user_name,
role: getRole(result.now_user_group ?? ''),
initials: personResult.initials,
})
})
router.get('/all', async (_req, res) => {
-16
View File
@@ -70,19 +70,3 @@ export const createTestUsers = async () => {
}
}
}
export const getAllUsers = async () => {
const result = await nowDb.com_users.findMany({})
return result
}
export const getUserDetails = async (id: number) => {
// TODO: Check if user has access
const result = await nowDb.com_users.findUnique({
where: {
user_id: id,
},
})
return result
}
+3 -1
View File
@@ -13,6 +13,7 @@ import {
timeBoundPage,
timeUnitPage,
} from './components/pages'
import { UserPage } from './components/UserPage'
const App = () => {
return (
@@ -34,8 +35,9 @@ const App = () => {
<Route element={regionPage} path="/region/:id?" />
<Route element={personPage} path="/person/:id?" />
<Route element={projectPage} path="/project/:id?" />
<Route element={<FrontPage />} path="/" />
<Route element={<Login />} path="/login" />
<Route element={<UserPage />} path="/userpage" />
<Route element={<FrontPage />} path="/" />
<Route element={<div>Page not found.</div>} path="*" />
</Routes>
</Grid>
+1 -1
View File
@@ -34,7 +34,7 @@ export const Login = () => {
useEffect(() => {
if (data && data.token) {
dispatch(setUser({ username: data.username, token: data.token, role: data.role || Role.ReadOnly }))
dispatch(setUser(data))
// Reset api cache, so that we won't show guest data to logged user
dispatch(api.util.resetApiState())
navigate('/')
+6 -12
View File
@@ -42,6 +42,8 @@ export const NavBar = () => {
},
]
if (user.username) pages.push({ title: 'User', url: '/userpage' })
const logout = () => {
dispatch(clearUser())
// Reset api, so that we won't show cached private data to guest user
@@ -52,9 +54,7 @@ export const NavBar = () => {
const logoutButton = (
<MenuItem onClick={logout} style={{ display: 'inline-block' }}>
<Typography component="h4" textAlign="center">
Logout
</Typography>
<Typography textAlign="center">Logout</Typography>
</MenuItem>
)
@@ -70,9 +70,7 @@ export const NavBar = () => {
onClick={handleClick}
sx={{ color: 'white', paddingTop: '6px', paddingBottom: '6px', paddingLeft: '16px', paddingRight: '16px' }}
>
<Typography component="h4" textAlign="center">
{link.title}
</Typography>
<Typography textAlign="center">{link.title}</Typography>
</Box>
<Menu
id={`${link.url}-menu`}
@@ -102,9 +100,7 @@ export const NavBar = () => {
}
return (
<MenuItem key={`${link.url}-menuitem`} component={Link} to={link.url} style={{ display: 'inline-block' }}>
<Typography component="h4" textAlign="center">
{link.title}
</Typography>
<Typography textAlign="center">{link.title}</Typography>
</MenuItem>
)
}
@@ -118,9 +114,7 @@ export const NavBar = () => {
<AppBar position="static">
<Stack spacing={10} direction="row" marginLeft={2} justifyContent="space-between">
<MenuItem component={Link} to="/">
<Typography component="h1" fontSize={'2.2em'}>
Now Database {getModeText()}
</Typography>
<Typography fontSize={'2.2em'}>Now Database {getModeText()}</Typography>
</MenuItem>
<MenuList style={{ alignContent: 'center' }}>
{pages
+38
View File
@@ -0,0 +1,38 @@
import { useUser } from '@/hooks/user'
import { useGetPersonDetailsQuery } from '@/redux/personReducer'
import { Box, CircularProgress, Divider, Stack, Typography } from '@mui/material'
import { skipToken } from '@reduxjs/toolkit/query'
import { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
export const UserPage = () => {
const user = useUser()
const navigate = useNavigate()
const { data: userDetails, isError } = useGetPersonDetailsQuery(user?.initials ?? skipToken)
useEffect(() => {
if (!user.username) navigate('/login')
}, [user, navigate])
if (!userDetails) return <CircularProgress />
if (isError || !userDetails.user) return <Box>Error fetching user</Box>
return (
<Box sx={{ maxWidth: '30em', marginLeft: 'auto', marginRight: 'auto' }}>
<Typography variant="h4">User</Typography>
<Divider sx={{ marginBottom: '1em' }} />
<Stack gap={2}>
<Box>
<b>Username:</b> {user.username}
</Box>
<Box>
<b>Initials:</b> {user.initials}
</Box>
<Box>
<b>Last login:</b> {userDetails.user.last_login?.toString() || 'No data'}
</Box>
</Stack>
</Box>
)
}
+8 -19
View File
@@ -1,12 +1,12 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { api } from '@/redux/api'
import { PersonDetailsType } from '@/backendTypes'
import { Role } from '@/types'
export type FrontendUser = {
token: string
username: string
role: Role
initials: string
}
type LoginData = { username: string; password: string }
@@ -23,16 +23,6 @@ const userApi = api.injectEndpoints({
method: 'POST',
}),
}),
getAllUsers: builder.query<PersonDetailsType[], void>({
query: () => ({
url: `/user/all`,
}),
}),
getUserDetails: builder.query<PersonDetailsType, string>({
query: id => ({
url: `/user/${id}`,
}),
}),
}),
})
@@ -40,30 +30,29 @@ export interface UserState {
token: string | null
username: string | null
role: Role
initials: string | null
}
const initialState: UserState = {
token: null,
username: null,
role: Role.ReadOnly,
initials: null,
}
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
setUser(state, action: PayloadAction<{ token: string; username: string; role: Role }>) {
const { token, username, role } = action.payload
return { ...state, token, username, role }
setUser(_state, action: PayloadAction<UserState>) {
return { ...action.payload }
},
clearUser(state) {
state.token = null
state.username = null
state.role = Role.ReadOnly
clearUser() {
return { ...initialState }
},
},
})
export const { setUser, clearUser } = userSlice.actions
export const userReducer = userSlice.reducer
export const { useTryLoginMutation, useGetAllUsersQuery, useGetUserDetailsQuery } = userApi
export const { useTryLoginMutation } = userApi