redoing frontend

This commit is contained in:
2022-07-28 22:56:28 -04:00
parent 55df431241
commit bd6319b6b1
7 changed files with 1003 additions and 802 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -3,26 +3,32 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@mantine/core": "^4.1.2",
"@mantine/dates": "^4.1.1",
"@mantine/dropzone": "^4.1.2",
"@mantine/form": "^4.1.1",
"@mantine/hooks": "^4.1.2",
"@mantine/notifications": "^4.1.0",
"@testing-library/jest-dom": "^5.16.3",
"@testing-library/react": "^12.1.4",
"@emotion/cache": "^11.9.3",
"@emotion/react": "^11.9.3",
"@emotion/serialize": "^1.0.4",
"@emotion/utils": "^1.1.0",
"@mantine/core": "^5.0.0",
"@mantine/dates": "^5.0.0",
"@mantine/dropzone": "^5.0.0",
"@mantine/form": "^5.0.0",
"@mantine/hooks": "^5.0.0",
"@mantine/notifications": "^5.0.0",
"@tabler/icons": "^1.78.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^12.1.5",
"@testing-library/user-event": "^13.5.0",
"base-64": "^1.0.0",
"dayjs": "^1.11.0",
"jotai": "^1.6.1",
"npm-check-updates": "^12.5.4",
"dayjs": "^1.11.4",
"jotai": "^1.7.6",
"npm-check-updates": "^12.5.12",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-icons": "^4.3.1",
"react-jss": "^10.9.0",
"react-router": "^6.2.2",
"react-router-dom": "^6.2.2",
"react-icons": "^4.4.0",
"react-jss": "^10.9.1",
"react-router": "^6.3.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.0",
"tabler-icons": "^1.35.0",
"web-vitals": "^2.1.4"
},
"scripts": {

View File

@@ -4,7 +4,8 @@ import HomePage from './components/pages/HomePage';
import LocationsPage from './components/pages/LocationsPage';
import RoomsPage from './components/pages/RoomsPage';
import LocationForm from './components/forms/LocationForm'
import { Routes, Route, useNavigate } from "react-router-dom";
import NotFound from './components/pages/NotFound';
import { BrowserRouter as Router, Routes, Route} from 'react-router-dom'
import { Modal, Button, Text, Group, TextInput, Loader, AppShell, MediaQuery } from '@mantine/core';
import { useDebouncedValue, useLocalStorageValue } from '@mantine/hooks';
import { useNotifications } from '@mantine/notifications';
@@ -64,21 +65,27 @@ function App() {
return (
<AppShell
navbarOffsetBreakpoint="sm" // navbarOffsetBreakpoint controls when navbar should no longer be offset with padding-left
fixed // fixed prop on AppShell will be automatically added to Header and Navbar
navbar={<SideBar />}
header={<AppHeader />}
>
<Routes>
<Route exact path="/" element={<HomePage />} />
<Route exact path="locations" element={<LocationsPage />} />
<Route exact path="location/:id" element={<LocationDetailsPage />} />
<Route exact path="rooms" element={<RoomsPage />} />
<Route exact path="locations/new" element={<LocationForm />} />
</Routes>
</AppShell>
<Router>
<AppShell
navbarOffsetBreakpoint="sm" // navbarOffsetBreakpoint controls when navbar should no longer be offset with padding-left
fixed // fixed prop on AppShell will be automatically added to Header and Navbar
navbar={<SideBar />}
header={<AppHeader />}
>
<Routes>
<Route path='*' element={<NotFound />} />
<Route index element={<HomePage />} />
<Route path="locations">
<Route index element={<LocationsPage />} />
<Route path=":id" element={<LocationDetailsPage />} />
<Route path="new" element={<LocationForm />} />
</Route>
<Route path="rooms">
<Route index element={<RoomsPage />} />
</Route>
</Routes>
</AppShell>
</Router>
);
}

View File

@@ -1,123 +1,99 @@
import React, {useState } from 'react';
import { useAtom } from 'jotai';
import { activePageAtom, menuOpenedAtom, roomFilterAtom } from '../state/main';
import { Navbar, Group, ScrollArea, createStyles, MediaQuery } from '@mantine/core';
import { LinksGroup } from './sidebar/SidebarLinksGroup';
// import { UserButton } from './sidebar/UserButton';
import { Link } from 'react-router-dom';
import { Navbar, ScrollArea, createStyles } from '@mantine/core';
import { GoLocation, GoDashboard, GoGear } from 'react-icons/go'
import { BsDoorClosed, BsDiagram2 } from 'react-icons/bs'
import { BiCabinet } from 'react-icons/bi'
import { LinksGroup } from './sidebar/SidebarLinksGroup';
const sideBarData = [
{ label: 'Dashboard', icon: GoDashboard, link: {label: 'Dashboard', link: '/'}},
{
label: 'Locations',
icon: GoLocation,
initiallyOpened: true,
links: [
{ label: 'View Locations', link: '/locations' },
{ label: 'Add New Location', link: '/locations/new' },
{ label: 'Outlook', link: '/' },
{ label: 'Real time', link: '/' },
],
},
{
label: 'Rooms',
icon: BsDoorClosed,
initiallyOpened: true,
links: [
{ label: 'View Rooms', link: '/rooms' },
{ label: 'Add New Room', link: '/rooms/new' },
{ label: 'Releases schedule', link: '/'},
],
},
{ label: 'Cabinets', icon: BiCabinet, link: "/" },
{ label: 'Items', icon: BsDiagram2, link: "/" },
{ label: 'Settings', icon: GoGear, link: '/' },
];
const useStyles = createStyles((theme) => ({
navbar: {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.white,
paddingBottom: 0,
},
header: {
padding: theme.spacing.md,
paddingTop: 0,
marginLeft: -theme.spacing.md,
marginRight: -theme.spacing.md,
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
borderBottom: `1px solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
},
links: {
marginLeft: -theme.spacing.md,
marginRight: -theme.spacing.md,
},
linksInner: {
paddingTop: theme.spacing.xl,
paddingBottom: theme.spacing.xl,
},
footer: {
marginLeft: -theme.spacing.md,
marginRight: -theme.spacing.md,
borderTop: `1px solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
},
navbar: {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.white,
paddingBottom: 0,
},
header: {
padding: theme.spacing.md,
paddingTop: 0,
marginLeft: -theme.spacing.md,
marginRight: -theme.spacing.md,
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
borderBottom: `1px solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
},
links: {
marginLeft: -theme.spacing.md,
marginRight: -theme.spacing.md,
},
linksInner: {
paddingTop: theme.spacing.xl,
paddingBottom: theme.spacing.xl,
},
footer: {
marginLeft: -theme.spacing.md,
marginRight: -theme.spacing.md,
borderTop: `1px solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
},
}));
export function SideBar() {
const { classes } = useStyles();
const links = sideBarData.map((item) => <LinksGroup {...item} key={item.label} />);
return (
<Navbar height={800} width={{ sm: 300 }} p="md" className={classes.navbar}>
{/* <Navbar.Section className={classes.header}>
<Group position="apart">
<Logo width={120} />
<Code sx={{ fontWeight: 700 }}>v3.1.2</Code>
</Group>
</Navbar.Section> */}
const sideBarData = [
{ label: 'Dashboard', icon: GoDashboard, link: {label: 'Dashboard', link: '/'}},
{
label: 'Locations',
icon: GoLocation,
initiallyOpened: true,
links: [
{ label: 'View Locations', link: '/locations' },
{ label: 'Add New Location', link: '/locations/new' },
{ label: 'Outlook', link: '/' },
{ label: 'Real time', link: '/' },
],
},
{
label: 'Rooms',
icon: BsDoorClosed,
initiallyOpened: true,
links: [
{ label: 'View Rooms', link: '/rooms' },
{ label: 'Add New Room', link: '/rooms/new' },
{ label: 'Releases schedule', link: '/' },
],
},
{ label: 'Cabinets', icon: BiCabinet },
{ label: 'Items', icon: BsDiagram2 },
{ label: 'Settings', icon: GoGear },
];
<Navbar.Section grow className={classes.links} component={ScrollArea}>
<div className={classes.linksInner}>{links}</div>
</Navbar.Section>
function SideBar(props) {
const { classes } = useStyles();
const [menuOpened] = useAtom(menuOpenedAtom)
const links = sideBarData.map((item) => <LinksGroup {...item} key={item.label} />);
return (
<>
<MediaQuery smallerThan="md" styles={!menuOpened && { 'display': 'none'}}>
<Navbar height={800} width={{ sm: 300 }} p="md" className={classes.navbar}>
{/* <Navbar.Section className={classes.header}>
<Group position="apart">
<Logo width={120} />
<Code sx={{ fontWeight: 700 }}>v3.1.2</Code>
</Group>
</Navbar.Section> */}
<Navbar.Section grow className={classes.links} component={ScrollArea}>
<div className={classes.linksInner}>{links}</div>
</Navbar.Section>
{/* <Navbar.Section className={classes.footer}>
<UserButton
image="https://images.unsplash.com/photo-1508214751196-bcfd4ca60f91?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=255&q=80"
name="Ann Nullpointer"
email="anullpointer@yahoo.com"
/>
</Navbar.Section> */}
</Navbar>
</MediaQuery>
</>
)
{/* <Navbar.Section className={classes.footer}>
<UserButton
image="https://images.unsplash.com/photo-1508214751196-bcfd4ca60f91?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=255&q=80"
name="Ann Nullpointer"
email="anullpointer@yahoo.com"
/>
</Navbar.Section> */}
</Navbar>
);
}
export default SideBar
export default SideBar

View File

@@ -0,0 +1,20 @@
import { Title, Text, Center } from '@mantine/core';
function NotFound() {
return (
<>
<Center>
<Title>Page Not Found!</Title>
</Center>
<Text>The page you are looking for does not exist!</Text>
</>
);
}
export default NotFound

View File

@@ -1,153 +1,124 @@
import React, { useState } from 'react';
import { Group, Box, Collapse, ThemeIcon, UnstyledButton, createStyles } from '@mantine/core';
import { useMediaQuery } from '@mantine/hooks';
import { useEffect, useState } from 'react';
import { Group, Box, Collapse, ThemeIcon, Text, UnstyledButton, createStyles } from '@mantine/core';
import { BiChevronLeft, BiChevronRight } from 'react-icons/bi';
import { useAtom } from 'jotai';
import { activePageAtom, menuOpenedAtom, roomFilterAtom } from '../../state/main';
import { Link } from 'react-router-dom';
import { NavLink, useLocation } from 'react-router-dom';
const useStyles = createStyles((theme, _params, getRef) => {
const icon = getRef('icon');
return {
control: {
fontWeight: 500,
display: 'block',
width: '100%',
padding: `${theme.spacing.xs}px ${theme.spacing.md}px`,
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.black,
fontSize: theme.fontSizes.sm,
const useStyles = createStyles((theme) => ({
control: {
fontWeight: 500,
display: 'block',
width: '100%',
padding: `${theme.spacing.xs}px ${theme.spacing.md}px`,
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.black,
fontSize: theme.fontSizes.sm,
'&:hover': {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[7] : theme.colors.gray[0],
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
'&:hover': {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[7] : theme.colors.gray[0],
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
},
},
},
link: {
fontWeight: 500,
display: 'block',
textDecoration: 'none',
padding: `${theme.spacing.xs}px ${theme.spacing.md}px`,
paddingLeft: 31,
marginLeft: 30,
fontSize: theme.fontSizes.sm,
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.gray[7],
borderLeft: `1px solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
link: {
fontWeight: 500,
display: 'block',
textDecoration: 'none',
padding: `${theme.spacing.xs}px ${theme.spacing.md}px`,
paddingLeft: 31,
marginLeft: 30,
fontSize: theme.fontSizes.sm,
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.gray[7],
borderLeft: `1px solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
'&:hover': {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[7] : theme.colors.gray[1],
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
'&:hover': {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[7] : theme.colors.gray[0],
color: theme.colorScheme === 'dark' ? theme.white : theme.black,
},
},
},
activeLink: {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[7] : theme.colors.gray[3],
},
linkActive: {
'&, &:hover': {
backgroundColor:
theme.colorScheme === 'dark'
? theme.fn.rgba(theme.colors[theme.primaryColor][8], 0.25)
: theme.colors[theme.primaryColor][0],
color: theme.colorScheme === 'dark' ? theme.white : theme.colors[theme.primaryColor][7],
[`& .${icon}`]: {
color: theme.colors[theme.primaryColor][theme.colorScheme === 'dark' ? 5 : 7],
},
},
},
chevron: {
transition: 'transform 200ms ease',
},
}));
export function LinksGroup(props) {
const { icon: Icon, label, initiallyOpened, links, link } = props
const isMobile = useMediaQuery('(max-width: 768px)')
const hasLinks = Array.isArray(links);
const hasLink = (typeof link === "object")
const [opened, setOpened] = useState(initiallyOpened || false);
// Navigation State
const [activePage, setActivePage] = useAtom(activePageAtom)
const [roomFilter, setRoomFilter] = useAtom(roomFilterAtom)
const [menuOpened, setMenuOpened] = useAtom(menuOpenedAtom)
chevron: {
transition: 'transform 200ms ease',
},
}});
export function LinksGroup({ icon: Icon, label, initiallyOpened, links }) {
const mypath = useLocation()
const { classes, theme, cx } = useStyles();
const hasLinks = Array.isArray(links);
const [opened, setOpened] = useState(initiallyOpened || false);
const ChevronIcon = theme.dir === 'ltr' ? BiChevronRight : BiChevronLeft;
const navigate = (location) => {
// event.preventDefault()
if (location === "rooms") {
setRoomFilter({})
}
console.log("navigate to: ", location)
if (isMobile && menuOpened) {
setMenuOpened(false)
}
setActivePage(location)
}
const items = (hasLinks ? links : []).map((link) => (
<>
<Link
component={Link}
className={activePage === link.label.toLowerCase() ? cx(classes.link, classes.activeLink) : classes.link}
to={link.link}
key={link.label}
onClick={() => {navigate(link.label.toLowerCase())}}
>
{link.label}
</Link>
</>
// <Text>{link.link}</Text>
<NavLink
className={({ isActive}) => (cx(classes.link, {[classes.linkActive]: isActive === true}))}
key={link.label}
to={link.link}
>
{link.label}
</NavLink>
));
const buttonContents = () => {
return (
<Group position="apart" spacing={0}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<ThemeIcon variant="light" size={30}>
<Icon size={18} />
</ThemeIcon>
<Box ml="md">{label}</Box>
</Box>
{hasLinks && (
<ChevronIcon
className={classes.chevron}
size={14}
style={{
transform: opened ? `rotate(${theme.dir === 'rtl' ? -90 : 90}deg)` : 'none',
}}
/>
)}
</Group>
)
}
const myButton = () => {
if (hasLink) {
return (
<UnstyledButton
onClick={hasLinks ? () => setOpened((o) => !o) : () => navigate(link.label.toLowerCase())}
className={activePage === link.label.toLowerCase() ? cx(classes.control, classes.activeLink) : classes.control}
component={Link}
to={link.link}
key={link.label}
>
{buttonContents()}
</UnstyledButton>
)
} else {
return (
<UnstyledButton
onClick={() => setOpened((o) => !o)}
className={classes.control}
>
{buttonContents()}
</UnstyledButton>
)
}
}
useEffect(() => {
console.log("MYPATH: ", mypath)
}, [])
return (
<>
{myButton()}
<UnstyledButton onClick={() => setOpened((o) => !o)} className={classes.control}>
<Group position="apart" spacing={0}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<ThemeIcon variant="light" size={30}>
<Icon size={18} />
</ThemeIcon>
<Box ml="md">{label}</Box>
</Box>
{hasLinks && (
<ChevronIcon
className={classes.chevron}
size={14}
stroke={1.5}
style={{
transform: opened ? `rotate(${theme.dir === 'rtl' ? -90 : 90}deg)` : 'none',
}}
/>
)}
</Group>
</UnstyledButton>
{hasLinks ? <Collapse in={opened}>{items}</Collapse> : null}
</>
);
}
)
export function NavbarLinksGroup(data) {
return (
<Box
sx={(theme) => ({
minHeight: 220,
padding: theme.spacing.md,
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.white,
})}
>
<LinksGroup {...data} />
</Box>
);
}

View File

@@ -3,7 +3,6 @@ import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { NotificationsProvider } from '@mantine/notifications';
import { BrowserRouter } from 'react-router-dom';
//setup api
//const backendPort = process.env.REACT_APP_BACKEND_PORT
@@ -11,10 +10,8 @@ import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<React.StrictMode>
<NotificationsProvider>
<BrowserRouter>
<NotificationsProvider>
<App />
</BrowserRouter>
</NotificationsProvider>
</React.StrictMode>,
document.getElementById('root')