aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordan <[email protected]>2023-08-28 11:40:36 -0400
committerdan <[email protected]>2023-08-28 11:40:36 -0400
commit38217a7101b50e7aa0a0d543cad737a011d5fac0 (patch)
tree730865f5822e6d95f655aa85959ae7086061fb7c
parent7c9345f41d9c86142019cce05ca0495408b01730 (diff)
downloaddraggable-form-demo-38217a7101b50e7aa0a0d543cad737a011d5fac0.tar.gz
draggable-form-demo-38217a7101b50e7aa0a0d543cad737a011d5fac0.tar.bz2
draggable-form-demo-38217a7101b50e7aa0a0d543cad737a011d5fac0.zip
refactor: setup and run eslint+prettier
-rw-r--r--.eslintrc.js34
-rw-r--r--package.json6
-rw-r--r--src/App.js79
-rw-r--r--src/CustomThemeProvider.js33
-rw-r--r--src/components/NavBar/index.js196
-rw-r--r--src/hooks/useLoginState.js16
-rw-r--r--src/index.js14
-rw-r--r--src/pages/Login/index.js36
-rw-r--r--src/pages/Users/index.js7
-rw-r--r--src/reportWebVitals.js4
-rw-r--r--src/setupTests.js2
11 files changed, 240 insertions, 187 deletions
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..56d1c38
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,34 @@
+module.exports = {
+ env: {
+ browser: true,
+ es2021: true,
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended",
+ "plugin:prettier/recommended",
+ ],
+ overrides: [
+ {
+ env: {
+ node: true,
+ },
+ files: [".eslintrc.{js,cjs}"],
+ parserOptions: {
+ sourceType: "script",
+ },
+ },
+ ],
+ parserOptions: {
+ ecmaVersion: "latest",
+ sourceType: "module",
+ },
+ plugins: ["react", "prettier", "react-hooks"],
+ rules: {
+ "linebreak-style": ["error", "unix"],
+ semi: ["error", "always"],
+ "react/react-in-jsx-scope": "off",
+ "react/jsx-filename-extension": [1, { extensions: [".js", ".jsx"] }],
+ "react/prop-types": "off",
+ },
+};
diff --git a/package.json b/package.json
index 6ca7e08..72a5caa 100644
--- a/package.json
+++ b/package.json
@@ -28,12 +28,6 @@
"react-app/jest"
]
},
- "prettier": {
- "singleQuote": true,
- "semi": true,
- "tabWidth": 2,
- "useTabs": false
- },
"browserslist": {
"production": [
">0.2%",
diff --git a/src/App.js b/src/App.js
index 9d9ee58..21ebbf3 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,80 +1,81 @@
-import './App.css';
-import { RouterProvider, createBrowserRouter, Navigate } from 'react-router-dom';
-import Login from './pages/Login';
-import Surveys from './pages/Surveys';
-import NewSurvey from './pages/NewSurvey';
-import SurveyResults from './pages/SurveyResults';
-import SurveyAssignees from './pages/SurveyAssignees';
-import Users from './pages/Users';
-import NavBar from './components/NavBar';
-import useLoginState from './hooks/useLoginState';
-import CssBaseline from '@mui/material/CssBaseline';
-import CustomThemeProvider from './CustomThemeProvider';
+import "./App.css";
+import {
+ RouterProvider,
+ createBrowserRouter,
+ Navigate,
+} from "react-router-dom";
+import Login from "./pages/Login";
+import Surveys from "./pages/Surveys";
+import NewSurvey from "./pages/NewSurvey";
+import SurveyResults from "./pages/SurveyResults";
+import SurveyAssignees from "./pages/SurveyAssignees";
+import Users from "./pages/Users";
+import NavBar from "./components/NavBar";
+import useLoginState from "./hooks/useLoginState";
+import CssBaseline from "@mui/material/CssBaseline";
+import CustomThemeProvider from "./CustomThemeProvider";
function routes({ login, logout, isLoggedIn }) {
-
function withNavBar(component) {
const navbarLinks = [
- { label: 'Surveys', link: '/surveys' },
- { label: 'New Survey', link: '/surveys/new' },
- { label: 'Users', link: '/users' },
+ { label: "Surveys", link: "/surveys" },
+ { label: "New Survey", link: "/surveys/new" },
+ { label: "Users", link: "/users" },
];
- return (<>
- <NavBar isLoggedIn={isLoggedIn} pages={navbarLinks} logout={logout} />
- {component}
- </>);
+ return (
+ <>
+ <NavBar isLoggedIn={isLoggedIn} pages={navbarLinks} logout={logout} />
+ {component}
+ </>
+ );
}
if (!isLoggedIn) {
- return ([
+ return [
{
- path: '*',
- element: <Login login={login}/>,
+ path: "*",
+ element: <Login login={login} />,
},
- ]);
+ ];
} else {
- return ([
+ return [
{
- path: '/',
- element: <Navigate to={{ pathname: '/surveys' }} />,
+ path: "/",
+ element: <Navigate to={{ pathname: "/surveys" }} />,
},
{
- path: '/surveys',
+ path: "/surveys",
element: withNavBar(<Surveys />),
},
{
- path: '/surveys/new',
+ path: "/surveys/new",
element: withNavBar(<NewSurvey />),
},
{
- path: '/surveys/:surveyId/results',
+ path: "/surveys/:surveyId/results",
element: withNavBar(<SurveyResults />),
},
{
- path: '/surveys/:surveyId/assignees',
+ path: "/surveys/:surveyId/assignees",
element: withNavBar(<SurveyAssignees />),
},
{
- path: '/users',
+ path: "/users",
element: withNavBar(<Users />),
},
- ]);
+ ];
}
-
}
export default function App() {
const { login, logout, isLoggedIn } = useLoginState();
- const currentRoutes = routes({isLoggedIn, logout, login});
+ const currentRoutes = routes({ isLoggedIn, logout, login });
return (
<>
<CssBaseline />
<CustomThemeProvider>
- <RouterProvider router={
- createBrowserRouter(currentRoutes)
- }/>
+ <RouterProvider router={createBrowserRouter(currentRoutes)} />
</CustomThemeProvider>
</>
);
}
-
diff --git a/src/CustomThemeProvider.js b/src/CustomThemeProvider.js
index f3f4a26..c4234b6 100644
--- a/src/CustomThemeProvider.js
+++ b/src/CustomThemeProvider.js
@@ -1,45 +1,40 @@
-import {ThemeProvider} from '@mui/material';
-import {createTheme} from '@mui/material';
+import { ThemeProvider } from "@mui/material";
+import { createTheme } from "@mui/material";
-export default function CustomThemeProvider({children}) {
- console.log('theme', theme);
- return <ThemeProvider theme={theme}>
- { children }
- </ThemeProvider>;
+export default function CustomThemeProvider({ children }) {
+ console.log("theme", theme);
+ return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
}
const themeOptions = {
palette: {
- mode: 'light',
+ mode: "light",
primary: {
- main: '#0b0b14',
+ main: "#0b0b14",
},
secondary: {
- main: '#9c27b0',
+ main: "#9c27b0",
},
},
overrides: {
MuiAppBar: {
colorInherit: {
- backgroundColor: '#689f38',
- color: '#fff',
+ backgroundColor: "#689f38",
+ color: "#fff",
},
},
MuiButton: {
root: {
- background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
+ background: "linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)",
border: 0,
borderRadius: 3,
- boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
- color: 'white',
+ boxShadow: "0 3px 5px 2px rgba(255, 105, 135, .3)",
+ color: "white",
height: 48,
- padding: '0 30px',
+ padding: "0 30px",
},
},
},
};
-
const theme = createTheme(themeOptions);
-
-
diff --git a/src/components/NavBar/index.js b/src/components/NavBar/index.js
index 0bbc550..83ae7e9 100644
--- a/src/components/NavBar/index.js
+++ b/src/components/NavBar/index.js
@@ -1,7 +1,18 @@
-import {useState} from 'react';
-import { Link } from 'react-router-dom';
-import {AppBar, Box, Button, Drawer, IconButton, List, ListItem, ListItemButton, ListItemText, Toolbar} from '@mui/material';
-import {Menu} from '@mui/icons-material';
+import { useState } from "react";
+import { Link } from "react-router-dom";
+import {
+ AppBar,
+ Box,
+ Button,
+ Drawer,
+ IconButton,
+ List,
+ ListItem,
+ ListItemButton,
+ ListItemText,
+ Toolbar,
+} from "@mui/material";
+import { Menu } from "@mui/icons-material";
export default function NavBar({ isLoggedIn, pages, logout }) {
const drawerWidth = 200;
@@ -12,89 +23,106 @@ export default function NavBar({ isLoggedIn, pages, logout }) {
setMobileOpen(!mobileOpen);
};
- return isLoggedIn &&
- <Box sx={{ display: 'flex' }}>
- <AppBar
- component='nav'
- sx={{position: 'initial'}}>
- <Toolbar>
- <IconButton
- color="inherit"
- aria-label="open drawer"
- edge="start"
- onClick={handleDrawerToggle}
- sx={{ mr: 2, display: { sm: 'none' } }}
- >
- <Menu />
- </IconButton>
- <Box sx={{ display: { xs: 'none', sm: 'block' } }}>
- {pages.map(p =>
- p.hidden ||
-<Link key={p.link} to={p.link} style={{textDecorationLine:'none'}}>
- <Button key={p.label} sx={{ textDecorationLine:'none', color: '#ffffff' }}>
- {p.label}
- </Button>
-</Link>
- )}
- <Button onClick={logout} sx={{color:'#ffffff'}}>
- Logout
- </Button>
- </Box>
- </Toolbar>
- </AppBar>
-
+ return (
+ isLoggedIn && (
+ <Box sx={{ display: "flex" }}>
+ <AppBar component="nav" sx={{ position: "initial" }}>
+ <Toolbar>
+ <IconButton
+ color="inherit"
+ aria-label="open drawer"
+ edge="start"
+ onClick={handleDrawerToggle}
+ sx={{ mr: 2, display: { sm: "none" } }}
+ >
+ <Menu />
+ </IconButton>
+ <Box sx={{ display: { xs: "none", sm: "block" } }}>
+ {pages.map(
+ (p) =>
+ p.hidden || (
+ <Link
+ key={p.link}
+ to={p.link}
+ style={{ textDecorationLine: "none" }}
+ >
+ <Button
+ key={p.label}
+ sx={{ textDecorationLine: "none", color: "#ffffff" }}
+ >
+ {p.label}
+ </Button>
+ </Link>
+ ),
+ )}
+ <Button onClick={logout} sx={{ color: "#ffffff" }}>
+ Logout
+ </Button>
+ </Box>
+ </Toolbar>
+ </AppBar>
- <Box component="nav">
- <Drawer
- sx={{
- width: drawerWidth,
- flexShrink: 0,
- '& .MuiDrawer-paper': {
+ <Box component="nav">
+ <Drawer
+ sx={{
width: drawerWidth,
- boxSizing: 'border-box',
- },
+ flexShrink: 0,
+ "& .MuiDrawer-paper": {
+ width: drawerWidth,
+ boxSizing: "border-box",
+ },
- display: { xs: 'block', sm: 'none' },
- }}
- variant='temporary'
- anchor='left'
- open={mobileOpen}
- onClose={handleDrawerToggle}
- ModalProps={{
- keepMounted:true,
- }}
- >
- <Box onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}>
- <List>
- {pages.map(({label, link, hidden}) => (
- hidden ? <div key={link}></div> :
- <ListItem key={link} disablePadding>
-
- <Link to={link} style={{textDecorationLine:'none', width: '100%'}}>
- <ListItemButton
- key={label}
- sx={{
- width:'100%',
- color: 'primary.main',
- textAlign: 'left',
- }}
+ display: { xs: "block", sm: "none" },
+ }}
+ variant="temporary"
+ anchor="left"
+ open={mobileOpen}
+ onClose={handleDrawerToggle}
+ ModalProps={{
+ keepMounted: true,
+ }}
+ >
+ <Box onClick={handleDrawerToggle} sx={{ textAlign: "center" }}>
+ <List>
+ {pages.map(({ label, link, hidden }) =>
+ hidden ? (
+ <div key={link}></div>
+ ) : (
+ <ListItem key={link} disablePadding>
+ <Link
+ to={link}
+ style={{ textDecorationLine: "none", width: "100%" }}
>
- <ListItemText primary={label} sx={{ width:'100%'}} />
- </ListItemButton>
- </Link>
- </ListItem>
- ))}
- <ListItem disablePadding>
- <ListItemButton
- onClick={logout}
- sx={{width:'100%', color: 'primary.main' }}
- >
- <ListItemText primary={'Logout'}/>
- </ListItemButton>
- </ListItem>
- </List>
- </Box>
- </Drawer>
+ <ListItemButton
+ key={label}
+ sx={{
+ width: "100%",
+ color: "primary.main",
+ textAlign: "left",
+ }}
+ >
+ <ListItemText
+ primary={label}
+ sx={{ width: "100%" }}
+ />
+ </ListItemButton>
+ </Link>
+ </ListItem>
+ ),
+ )}
+ <ListItem disablePadding>
+ <ListItemButton
+ onClick={logout}
+ sx={{ width: "100%", color: "primary.main" }}
+ >
+ <ListItemText primary={"Logout"} />
+ </ListItemButton>
+ </ListItem>
+ </List>
+ </Box>
+ </Drawer>
+ </Box>
</Box>
- </Box>;
+ )
+ );
}
diff --git a/src/hooks/useLoginState.js b/src/hooks/useLoginState.js
index b7c7221..94301ef 100644
--- a/src/hooks/useLoginState.js
+++ b/src/hooks/useLoginState.js
@@ -1,10 +1,8 @@
-import {useState} from 'react';
+import { useState } from "react";
export default function useLoginState() {
const [userInfo, setUserInfoState] = useState(
- localStorage.userInfo ?
- JSON.parse(localStorage.userInfo) :
- {}
+ localStorage.userInfo ? JSON.parse(localStorage.userInfo) : {},
);
function setUserInfo(userInfo) {
@@ -16,18 +14,18 @@ export default function useLoginState() {
console.log(`logging in: ${username}, ${password}`);
// const userInfo = await api.login()
const userInfo = {
- username
+ username,
};
- console.log('Login success');
+ console.log("Login success");
setUserInfo(userInfo);
return userInfo;
- }
+ }
function logout() {
setUserInfo({});
}
const isLoggedIn = !!userInfo?.username;
-
- return {userInfo, isLoggedIn, login, logout};
+
+ return { userInfo, isLoggedIn, login, logout };
}
diff --git a/src/index.js b/src/index.js
index d563c0f..902eb7c 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,14 +1,14 @@
-import React from 'react';
-import ReactDOM from 'react-dom/client';
-import './index.css';
-import App from './App';
-import reportWebVitals from './reportWebVitals';
+import React from "react";
+import ReactDOM from "react-dom/client";
+import "./index.css";
+import App from "./App";
+import reportWebVitals from "./reportWebVitals";
-const root = ReactDOM.createRoot(document.getElementById('root'));
+const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
- </React.StrictMode>
+ </React.StrictMode>,
);
// If you want to start measuring performance in your app, pass a function
diff --git a/src/pages/Login/index.js b/src/pages/Login/index.js
index 1735d8e..6d16936 100644
--- a/src/pages/Login/index.js
+++ b/src/pages/Login/index.js
@@ -1,20 +1,19 @@
-import React, { useState } from 'react';
-import Box from '@mui/material/Box';
-import TextField from '@mui/material/TextField';
-import Button from '@mui/material/Button';
-import {Stack} from '@mui/system';
+import React, { useState } from "react";
+import Box from "@mui/material/Box";
+import TextField from "@mui/material/TextField";
+import Button from "@mui/material/Button";
+import { Stack } from "@mui/system";
export default function Login({ login }) {
- const [user, setUser] = useState('');
- const [password, setPassword] = useState('');
+ const [user, setUser] = useState("");
+ const [password, setPassword] = useState("");
const [loginFailed, setLoginFailed] = useState(false);
const getApiKey = () => {
login(user, password)
- .then(ok => {
+ .then((ok) => {
setLoginFailed(!ok);
- }
- )
+ })
.catch(console.error);
};
@@ -22,26 +21,26 @@ export default function Login({ login }) {
<Box
component="form"
sx={{
- '& > :not(style)': { m: 1 },
+ "& > :not(style)": { m: 1 },
flexGrow: 1,
}}
noValidate
autoComplete="off"
>
- <Stack spacing={1} maxWidth='20em'>
+ <Stack spacing={1} maxWidth="20em">
<h2>Repeated Surveyer</h2>
<h3>Login</h3>
<TextField
- label='Email Address'
- type='text'
+ label="Email Address"
+ type="text"
value={user}
- onChange={e => setUser(e.target.value.trim())}
+ onChange={(e) => setUser(e.target.value.trim())}
/>
<TextField
- label='Password'
- type='password'
+ label="Password"
+ type="password"
value={password}
- onChange={e => setPassword(e.target.value)}
+ onChange={(e) => setPassword(e.target.value)}
/>
<Button onClick={() => getApiKey()}>Login</Button>
{loginFailed && <b>Login Failed</b>}
@@ -49,4 +48,3 @@ export default function Login({ login }) {
</Box>
);
}
-
diff --git a/src/pages/Users/index.js b/src/pages/Users/index.js
index 43afe5d..1cc20ce 100644
--- a/src/pages/Users/index.js
+++ b/src/pages/Users/index.js
@@ -1,3 +1,8 @@
export default function Users() {
- return <>Users</>;
+ return (
+ <>
+ Users
+ <div>foo</div>
+ </>
+ );
}
diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js
index 5253d3a..9ecd33f 100644
--- a/src/reportWebVitals.js
+++ b/src/reportWebVitals.js
@@ -1,6 +1,6 @@
-const reportWebVitals = onPerfEntry => {
+const reportWebVitals = (onPerfEntry) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
- import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+ import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
diff --git a/src/setupTests.js b/src/setupTests.js
index 8f2609b..1dd407a 100644
--- a/src/setupTests.js
+++ b/src/setupTests.js
@@ -2,4 +2,4 @@
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
-import '@testing-library/jest-dom';
+import "@testing-library/jest-dom";