diff --git a/client/package-lock.json b/client/package-lock.json index b08413fa1ea4936c7eef606822511df8882cdf81..7e73859f4e13b504ee814cde74ed293dd53e33ed 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1125,6 +1125,49 @@ "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz", "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==" }, + "@devexpress/dx-chart-core": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/@devexpress/dx-chart-core/-/dx-chart-core-2.7.5.tgz", + "integrity": "sha512-ZSpBN7SjnOhBOcvmuYZ5U+XyUYKlsTrYXCYMfFH2qXwvqh0e0UbhzW1FPfDXdWqx0Y52MtPX0HJrBC4QqH7Bcg==", + "requires": { + "d3-array": "^2.4.0", + "d3-scale": "^3.2.0", + "d3-shape": "^1.3.7" + } + }, + "@devexpress/dx-core": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/@devexpress/dx-core/-/dx-core-2.7.5.tgz", + "integrity": "sha512-VQQkz0uUqQ7YuVZeBEx1JFqpSSe5Bz9Qy2T0XAbilBQ8IItj74xjzaFMCNjuASAKXOJGtG0RUh+BOKrMGV7jlg==" + }, + "@devexpress/dx-react-chart": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/@devexpress/dx-react-chart/-/dx-react-chart-2.7.5.tgz", + "integrity": "sha512-j3nPsHrMiCbgm6olZCykxHOxxJ2XXG0CVihMYGOoyenM74Ed+NIaLi1bk2VtxKZdEPB5UrWgU10rd9SLH45BsQ==", + "requires": { + "@devexpress/dx-chart-core": "2.7.5", + "d3-scale": "^3.2.0", + "d3-shape": "^1.3.7" + } + }, + "@devexpress/dx-react-chart-material-ui": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/@devexpress/dx-react-chart-material-ui/-/dx-react-chart-material-ui-2.7.5.tgz", + "integrity": "sha512-uS450uSP1D6mZ2jgtueShqaATNRVqJEwqhgyRQUXL/gQyTrTCvM61TC5NLyEYCOW6RkiHK1BabWbhJlVATZbeg==", + "requires": { + "clsx": "^1.0.4", + "prop-types": "^15.7.2" + } + }, + "@devexpress/dx-react-core": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/@devexpress/dx-react-core/-/dx-react-core-2.7.5.tgz", + "integrity": "sha512-YwJ4l8nnMs/vghqamo8OzirDnrbT1ZNIcMP5xJFJJQIyfYAXvGGDS4yLeYI4cwitBg/d2O4jMOReXDB8tUaDDQ==", + "requires": { + "@devexpress/dx-core": "2.7.5", + "prop-types": "^15.7.2" + } + }, "@emotion/hash": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", @@ -5416,6 +5459,73 @@ "type": "^1.0.1" } }, + "d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "requires": { + "internmap": "^1.0.0" + } + }, + "d3-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz", + "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==" + }, + "d3-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz", + "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==" + }, + "d3-interpolate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz", + "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==", + "requires": { + "d3-color": "1 - 2" + } + }, + "d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, + "d3-scale": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.2.4.tgz", + "integrity": "sha512-PG6gtpbPCFqKbvdBEswQcJcTzHC8VEd/XzezF5e68KlkT4/ggELw/nR1tv863jY6ufKTvDlzCMZvhe06codbbA==", + "requires": { + "d3-array": "^2.3.0", + "d3-format": "1 - 2", + "d3-interpolate": "1.2.0 - 2", + "d3-time": "1 - 2", + "d3-time-format": "2 - 3" + } + }, + "d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "requires": { + "d3-path": "1" + } + }, + "d3-time": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz", + "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==", + "requires": { + "d3-array": "2" + } + }, + "d3-time-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", + "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", + "requires": { + "d3-time": "1 - 2" + } + }, "damerau-levenshtein": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", @@ -8492,6 +8602,11 @@ "side-channel": "^1.0.4" } }, + "internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", diff --git a/client/package.json b/client/package.json index f41350a6740cde52afbbaa3d6de2cf77ac48d032..2d393d3d80ce5126841f980c77e830355be56960 100644 --- a/client/package.json +++ b/client/package.json @@ -3,6 +3,9 @@ "version": "0.1.0", "private": true, "dependencies": { + "@devexpress/dx-react-chart": "^2.7.5", + "@devexpress/dx-react-chart-material-ui": "^2.7.5", + "@devexpress/dx-react-core": "^2.7.5", "@material-ui/core": "^4.11.3", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.57", diff --git a/client/src/pages/admin/dashboard/Dashboard.tsx b/client/src/pages/admin/dashboard/Dashboard.tsx index e3139d722ee897d50469ba508d3222734bfafef8..07426279010a358e1b0e118150010b34d338476e 100644 --- a/client/src/pages/admin/dashboard/Dashboard.tsx +++ b/client/src/pages/admin/dashboard/Dashboard.tsx @@ -3,6 +3,9 @@ import Paper from '@material-ui/core/Paper' import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' import React from 'react' import CurrentUser from './widgets/CurrentUser' +import NumberOfRegions from './widgets/NumberOfRegions' +import NumberOfRoles from './widgets/NumberOfRoles' +import NumberOfUsers from './widgets/NumberOfUsers' const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -25,25 +28,36 @@ const Dashboard: React.FC = () => { <div> <Grid container spacing={3}> <Grid item xs={12}> - <Paper className={classes.paper}>Dashboard Header</Paper> + <Paper className={classes.paper}> + <h1>Dashboard Header</h1> + </Paper> </Grid> <Grid item xs={6}> - <Paper className={classes.paper}>Widget 1</Paper> + <Paper className={classes.paper}> + <h1>Du är inloggad som:</h1> + <CurrentUser /> + </Paper> </Grid> <Grid item xs={6}> <Paper className={classes.paper}>Widget 2</Paper> </Grid> <Grid item xs={3}> - <Paper className={classes.paper}>Widget 3</Paper> + <Paper className={classes.paper}> + <h1>Antal Användare:</h1> + <NumberOfUsers /> + </Paper> </Grid> <Grid item xs={3}> <Paper className={classes.paper}> - Widget 4 - <CurrentUser /> + <h1>Antal Regioner:</h1> + <NumberOfRegions /> </Paper> </Grid> <Grid item xs={3}> - <Paper className={classes.paper}>Widget 5</Paper> + <Paper className={classes.paper}> + <h1>Antal Roller:</h1> + <NumberOfRoles /> + </Paper> </Grid> <Grid item xs={3}> <Paper className={classes.paper}>Widget 6</Paper> diff --git a/client/src/pages/admin/dashboard/widgets/CurrentUser.tsx b/client/src/pages/admin/dashboard/widgets/CurrentUser.tsx index b197e7b0b3f4e45f1221c04b5a985c743172cf55..1c61a80869d0f5b7d2972967b53aa234cbb62d53 100644 --- a/client/src/pages/admin/dashboard/widgets/CurrentUser.tsx +++ b/client/src/pages/admin/dashboard/widgets/CurrentUser.tsx @@ -1,14 +1,16 @@ -import { Box } from '@material-ui/core' import React from 'react' +import { useAppSelector } from '../../../../hooks' // import * from '@material-ui/core' const CurrentUser: React.FC = () => { + const currentUser = useAppSelector((state: { user: { userInfo: any } }) => state.user.userInfo) return ( <div> - <Box color="text.primary" bgcolor="secondary.main" fontFamily="h3.fontFamily" width="100%" height="100%"> - Current user info - </Box> + <div>Namn: {currentUser.name}</div> + <div>Email: {currentUser.email}</div> + <div>Region: {currentUser.city.name}</div> + <div>Roll: {currentUser.role.name}</div> </div> ) } diff --git a/client/src/pages/admin/dashboard/widgets/NumberOfRegions.tsx b/client/src/pages/admin/dashboard/widgets/NumberOfRegions.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f8757762711d9de891d6b462a2f02b0c2dfb3a1e --- /dev/null +++ b/client/src/pages/admin/dashboard/widgets/NumberOfRegions.tsx @@ -0,0 +1,26 @@ +import { Box } from '@material-ui/core' +import React, { useEffect } from 'react' +import { getSearchUsers } from '../../../../actions/searchUser' +import { useAppDispatch, useAppSelector } from '../../../../hooks' + +// import * from '@material-ui/core' + +const NumberOfRegions: React.FC = () => { + const cities = useAppSelector((state) => state.cities.cities) + const dispatch = useAppDispatch() + + useEffect(() => { + dispatch(getSearchUsers()) + }, []) + return ( + <div> + <Box color="text.primary" bgcolor="" fontFamily="h3.fontFamily" width="100%" height="100%"> + <div> + <h2>{cities.length} </h2> + </div> + </Box> + </div> + ) +} + +export default NumberOfRegions diff --git a/client/src/pages/admin/dashboard/widgets/NumberOfRoles.tsx b/client/src/pages/admin/dashboard/widgets/NumberOfRoles.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b94dcc0522f2f9e27d302471047d16c1df69c9ea --- /dev/null +++ b/client/src/pages/admin/dashboard/widgets/NumberOfRoles.tsx @@ -0,0 +1,26 @@ +import { Box } from '@material-ui/core' +import React, { useEffect } from 'react' +import { getSearchUsers } from '../../../../actions/searchUser' +import { useAppDispatch, useAppSelector } from '../../../../hooks' + +// import * from '@material-ui/core' + +const NumberOfRoles: React.FC = () => { + const roles = useAppSelector((state) => state.roles.roles) + const dispatch = useAppDispatch() + + useEffect(() => { + dispatch(getSearchUsers()) + }, []) + return ( + <div> + <Box color="text.primary" bgcolor="" fontFamily="h3.fontFamily" width="100%" height="100%"> + <div> + <h2>{roles.length} </h2> + </div> + </Box> + </div> + ) +} + +export default NumberOfRoles diff --git a/client/src/pages/admin/dashboard/widgets/NumberOfUsers.tsx b/client/src/pages/admin/dashboard/widgets/NumberOfUsers.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2989c2fb67b2b07e56d65f7278ff6404057ec9c4 --- /dev/null +++ b/client/src/pages/admin/dashboard/widgets/NumberOfUsers.tsx @@ -0,0 +1,27 @@ +import { Box } from '@material-ui/core' +import React, { useEffect } from 'react' +import { getSearchUsers } from '../../../../actions/searchUser' +import { useAppDispatch, useAppSelector } from '../../../../hooks' + +// import * from '@material-ui/core' + +const NumberOfUsers: React.FC = () => { + const users = useAppSelector((state) => state.searchUsers.users) + const usersTotal = useAppSelector((state) => state.searchUsers.total) + const dispatch = useAppDispatch() + + useEffect(() => { + dispatch(getSearchUsers()) + }, []) + return ( + <div> + <Box color="text.primary" bgcolor="" fontFamily="h3.fontFamily" width="100%" height="100%"> + <div> + <h2>{usersTotal}</h2> + </div> + </Box> + </div> + ) +} + +export default NumberOfUsers