added some stuff to help get ready for after logging in
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
module.exports = {
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.m?js/,
|
||||||
|
resolve: {
|
||||||
|
fullySpecified: false, // Disables strict extension requirements
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// eslint.config.js (Advanced alternative)
|
||||||
|
import prettierPlugin from 'eslint-plugin-prettier'
|
||||||
|
import prettierConfig from 'eslint-config-prettier'
|
||||||
|
import prettierOptions from './prettier.config.js' // Import your config directly
|
||||||
|
import importPlugin from 'eslint-plugin-import'
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
prettier: prettierPlugin,
|
||||||
|
import: importPlugin,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
...prettierConfig.rules,
|
||||||
|
'prettier/prettier': ['error', prettierOptions],
|
||||||
|
'no-sequences': 'off',
|
||||||
|
'no-console': 'warn',
|
||||||
|
'import/first': 'error',
|
||||||
|
'import/newline-after-import': 'error',
|
||||||
|
'import/no-duplicates': 'error',
|
||||||
|
'import/no-unresolved': 'error',
|
||||||
|
'import/no-unused-modules': ['warn', { missingExports: true }],
|
||||||
|
quotes: ['error', 'single'],
|
||||||
|
semi: 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
Generated
+13213
-1710
File diff suppressed because it is too large
Load Diff
+23
-4
@@ -3,6 +3,11 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.14.0",
|
||||||
|
"@emotion/styled": "^11.14.1",
|
||||||
|
"@fontsource/roboto": "^5.2.10",
|
||||||
|
"@mui/icons-material": "^9.1.1",
|
||||||
|
"@mui/material": "^9.1.1",
|
||||||
"@testing-library/dom": "^10.4.1",
|
"@testing-library/dom": "^10.4.1",
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "^16.3.2",
|
"@testing-library/react": "^16.3.2",
|
||||||
@@ -10,13 +15,15 @@
|
|||||||
"react": "^19.2.7",
|
"react": "^19.2.7",
|
||||||
"react-dom": "^19.2.7",
|
"react-dom": "^19.2.7",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
"react-transition-group": "4.4.2",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "craco start",
|
||||||
"build": "react-scripts build",
|
"build": "craco build",
|
||||||
"test": "react-scripts test",
|
"test": "craco test",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject",
|
||||||
|
"lint:fix": "eslint . --fix"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
@@ -35,5 +42,17 @@
|
|||||||
"last 1 firefox version",
|
"last 1 firefox version",
|
||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^8.0.1",
|
||||||
|
"@babel/preset-env": "^8.0.2",
|
||||||
|
"@craco/craco": "^7.1.0",
|
||||||
|
"babel-jest": "^30.4.1",
|
||||||
|
"eslint": "^8.57.1",
|
||||||
|
"eslint-config-prettier": "^10.1.8",
|
||||||
|
"eslint-plugin-import": "^2.32.0",
|
||||||
|
"eslint-plugin-prettier": "^5.5.6",
|
||||||
|
"jest": "^27.5.1",
|
||||||
|
"prettier": "^3.8.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// prettier.config.js
|
||||||
|
export default {
|
||||||
|
trailingComma: 'es5',
|
||||||
|
tabWidth: 2,
|
||||||
|
semi: false, // Crucial: Sets semicolon removal.
|
||||||
|
useTabs: true,
|
||||||
|
singleQuote: true,
|
||||||
|
}
|
||||||
-38
@@ -1,38 +0,0 @@
|
|||||||
.App {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-logo {
|
|
||||||
height: 40vmin;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
.App-logo {
|
|
||||||
animation: App-logo-spin infinite 20s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-header {
|
|
||||||
background-color: #282c34;
|
|
||||||
min-height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: calc(10px + 2vmin);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-link {
|
|
||||||
color: #61dafb;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes App-logo-spin {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
import logo from './logo.svg';
|
|
||||||
import './App.css';
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div className="App">
|
|
||||||
<header className="App-header">
|
|
||||||
<img src={logo} className="App-logo" alt="logo" />
|
|
||||||
<p>
|
|
||||||
Edit <code>src/App.js</code> and save to reload.
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
className="App-link"
|
|
||||||
href="https://reactjs.org"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Learn React
|
|
||||||
</a>
|
|
||||||
</header>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
test('renders learn react link', () => {
|
|
||||||
render(<App />);
|
|
||||||
const linkElement = screen.getByText(/learn react/i);
|
|
||||||
expect(linkElement).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
export default {
|
const constants = {
|
||||||
baseUrl: "http://192.168.68.150:8469"
|
baseUrl: 'http://192.168.68.150:8469',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default constants
|
||||||
|
|||||||
+2
-2
@@ -1,13 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import Login from './pages/login';
|
||||||
import reportWebVitals from './reportWebVitals';
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||||
root.render(
|
root.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<Login />
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+101
-50
@@ -1,22 +1,30 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react'
|
||||||
import './style.css';
|
import {
|
||||||
|
Container,
|
||||||
|
Box,
|
||||||
|
Avatar,
|
||||||
|
Typography,
|
||||||
|
TextField,
|
||||||
|
FormControlLabel,
|
||||||
|
Checkbox,
|
||||||
|
Button,
|
||||||
|
Grid,
|
||||||
|
Link,
|
||||||
|
Paper
|
||||||
|
} from '@mui/material'
|
||||||
|
import LockOutlinedIcon from '@mui/icons-material/LockOutlined'
|
||||||
|
import './style.css'
|
||||||
|
|
||||||
import { baseUrl } from "../../constants";
|
import constants from "../../constants/index";
|
||||||
|
|
||||||
class Login extends React.Component {
|
function Login() {
|
||||||
state = {
|
const [formData, setFormData] = useState({ username: '', password: '' })
|
||||||
username: '',
|
const [error, setError] = useState(false)
|
||||||
password: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = (event) => {
|
const handleSubmit = (event) => {
|
||||||
this.setState({ [event.target.name]: event.target.value });
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSubmit = (event) => {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const { username, password } = this.state;
|
const { username, password } = formData;
|
||||||
fetch(`${baseUrl}/auth/login`, {
|
fetch(`${constants.baseUrl}/auth/login`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@@ -34,41 +42,84 @@ class Login extends React.Component {
|
|||||||
alert('Invalid username or password');
|
alert('Invalid username or password');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => console.error(error));
|
.catch(error => console.error(error))
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="login-page">
|
|
||||||
<div className="login-container">
|
|
||||||
<h2>Login</h2>
|
|
||||||
<form onSubmit={this.handleSubmit} className="login-form">
|
|
||||||
<div>
|
|
||||||
<label htmlFor="username">Username:</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="username"
|
|
||||||
value={this.state.username}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label htmlFor="password">Password:</label>
|
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
name="password"
|
|
||||||
value={this.state.password}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<button type="submit">Login</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container component="main" maxWidth="xs">
|
||||||
|
<Paper
|
||||||
|
elevation={6}
|
||||||
|
sx={{
|
||||||
|
marginTop: 8,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: 4,
|
||||||
|
borderRadius: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
|
||||||
|
<LockOutlinedIcon />
|
||||||
|
</Avatar>
|
||||||
|
<Typography component="h1" variant="h5">
|
||||||
|
Sign in
|
||||||
|
</Typography>
|
||||||
|
<Box component="form" onSubmit={handleSubmit} noValidate sx={{ mt: 1 }}>
|
||||||
|
<TextField
|
||||||
|
margin="normal"
|
||||||
|
required
|
||||||
|
fullWidth
|
||||||
|
id="username"
|
||||||
|
label="Username or Email"
|
||||||
|
name="username"
|
||||||
|
autoComplete="username"
|
||||||
|
autoFocus
|
||||||
|
value={formData.username}
|
||||||
|
onChange={(e) => setFormData({ ...formData, username: e.target.value })}
|
||||||
|
error={error}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
margin="normal"
|
||||||
|
required
|
||||||
|
fullWidth
|
||||||
|
name="password"
|
||||||
|
label="Password"
|
||||||
|
type="password"
|
||||||
|
id="password"
|
||||||
|
autoComplete="current-password"
|
||||||
|
value={formData.password}
|
||||||
|
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
|
||||||
|
error={error}
|
||||||
|
helperText={error ? "Incorrect username or password" : ""}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
control={<Checkbox value="remember" color="primary" />}
|
||||||
|
label="Remember me"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
fullWidth
|
||||||
|
variant="contained"
|
||||||
|
sx={{ mt: 3, mb: 2 }}
|
||||||
|
>
|
||||||
|
Sign In
|
||||||
|
</Button>
|
||||||
|
<Grid container>
|
||||||
|
<Grid item xs>
|
||||||
|
<Link href="#" variant="body2">
|
||||||
|
Forgot password?
|
||||||
|
</Link>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Link href="#" variant="body2">
|
||||||
|
{"Don't have an account? Sign Up"}
|
||||||
|
</Link>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Login;
|
export default Login
|
||||||
|
|||||||
+12
-12
@@ -1,13 +1,13 @@
|
|||||||
const reportWebVitals = onPerfEntry => {
|
const reportWebVitals = (onPerfEntry) => {
|
||||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
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);
|
getCLS(onPerfEntry)
|
||||||
getFID(onPerfEntry);
|
getFID(onPerfEntry)
|
||||||
getFCP(onPerfEntry);
|
getFCP(onPerfEntry)
|
||||||
getLCP(onPerfEntry);
|
getLCP(onPerfEntry)
|
||||||
getTTFB(onPerfEntry);
|
getTTFB(onPerfEntry)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export default reportWebVitals;
|
export default reportWebVitals
|
||||||
|
|||||||
+1
-1
@@ -2,4 +2,4 @@
|
|||||||
// allows you to do things like:
|
// allows you to do things like:
|
||||||
// expect(element).toHaveTextContent(/react/i)
|
// expect(element).toHaveTextContent(/react/i)
|
||||||
// learn more: https://github.com/testing-library/jest-dom
|
// learn more: https://github.com/testing-library/jest-dom
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom'
|
||||||
|
|||||||
Reference in New Issue
Block a user