fix:changes

This commit is contained in:
Shagun Sharma 2025-01-28 12:33:29 +05:30
parent b09395972a
commit 27f6a7777f
15 changed files with 285 additions and 145 deletions

View file

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/src/assets/favicon.jpg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>

70
package-lock.json generated
View file

@ -15,7 +15,8 @@
"axios": "^1.7.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-redux": "^9.2.0"
"react-redux": "^9.2.0",
"react-router-dom": "^7.1.3"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
@ -1721,6 +1722,12 @@
"@babel/types": "^7.20.7"
}
},
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
"license": "MIT"
},
"node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
@ -2282,6 +2289,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/cookie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/cosmiconfig": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
@ -4453,6 +4469,46 @@
"node": ">=0.10.0"
}
},
"node_modules/react-router": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.3.tgz",
"integrity": "sha512-EezYymLY6Guk/zLQ2vRA8WvdUhWFEj5fcE3RfWihhxXBW7+cd1LsIiA3lmx+KCmneAGQuyBv820o44L2+TtkSA==",
"license": "MIT",
"dependencies": {
"@types/cookie": "^0.6.0",
"cookie": "^1.0.1",
"set-cookie-parser": "^2.6.0",
"turbo-stream": "2.4.0"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
}
}
},
"node_modules/react-router-dom": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.3.tgz",
"integrity": "sha512-qQGTE+77hleBzv9SIUIkGRvuFBQGagW+TQKy53UTZAO/3+YFNBYvRsNIZ1GT17yHbc63FylMOdS+m3oUriF1GA==",
"license": "MIT",
"dependencies": {
"react-router": "7.1.3"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
}
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@ -4680,6 +4736,12 @@
"semver": "bin/semver.js"
}
},
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT"
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@ -4989,6 +5051,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/turbo-stream": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
"integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
"license": "ISC"
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",

View file

@ -17,7 +17,8 @@
"axios": "^1.7.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-redux": "^9.2.0"
"react-redux": "^9.2.0",
"react-router-dom": "^7.1.3"
},
"devDependencies": {
"@eslint/js": "^9.17.0",

View file

@ -1,42 +0,0 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}

View file

@ -1,35 +1,41 @@
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0)
import React, { useState } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './app/store';
import LoginPage from './pages/LoginPage';
import JobDescriptionPage from './pages/JobDescriptionPage';
import InterviewQuestionsPage from './pages/InterviewQuestionsPage';
import ResourceInvitePage from './pages/ResourceInvitePage';
import { ThemeProvider, CssBaseline, Button } from '@mui/material';
import { darkTheme, lightTheme } from './theme';
const App = () => {
const [darkMode, setDarkMode] = useState(false);
const toggleDarkMode = () => setDarkMode(!darkMode);
return (
<>
<div>
<a href="https://vite.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.jsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
}
<Provider store={store}>
<ThemeProvider theme={darkMode ? darkTheme : lightTheme}>
<CssBaseline />
<Router>
<Button
onClick={toggleDarkMode}
variant="contained"
sx={{ position: 'fixed', top: 10, right: 10, zIndex: 1000 }}
>
Toggle {darkMode ? 'Light' : 'Dark'} Mode
</Button>
<Routes>
<Route path="/" element={<LoginPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/job-description" element={<JobDescriptionPage />} />
<Route path="/interview-questions" element={<InterviewQuestionsPage />} />
<Route path="/resource-invite" element={<ResourceInvitePage />} />
</Routes>
</Router>
</ThemeProvider>
</Provider>
);
};
export default App
export default App;

12
src/app/store.js Normal file
View file

@ -0,0 +1,12 @@
import { configureStore } from '@reduxjs/toolkit';
import authReducer from '../features/auth/authSlice';
// import jobReducer from '../features/job/jobSlice';
const store = configureStore({
reducer: {
auth: authReducer,
// job: jobReducer,
},
});
export default store;

BIN
src/assets/favicon.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View file

@ -0,0 +1,28 @@
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
user: null,
isAuthenticated: false,
error: null,
};
const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
loginSuccess: (state, action) => {
state.user = action.payload;
state.isAuthenticated = true;
},
logout: (state) => {
state.user = null;
state.isAuthenticated = false;
},
setError: (state, action) => {
state.error = action.payload;
},
},
});
export const { loginSuccess, logout, setError } = authSlice.actions;
export default authSlice.reducer;

9
src/helper/helper.js Normal file
View file

@ -0,0 +1,9 @@
// src/
// ├── components/ # Reusable UI components
// ├── features/ # Redux slices and related logic
// ├── pages/ # Page components for routes
// ├── app/ # Redux store setup
// ├── services/ # API calls and services
// ├── utils/ # Utility functions
// ├── App.jsx # Main App component
// └── main.jsx # Entry point

View file

@ -1,68 +0,0 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

View file

@ -0,0 +1,8 @@
function InterviewQuestionsPage(params) {
return(
<h1>
InterviewQuestionsPage</h1>
)
}
export default InterviewQuestionsPage

View file

@ -0,0 +1,8 @@
function JobDescriptionPage(params) {
return(
<h1>
JobDescriptionPage</h1>
)
}
export default JobDescriptionPage

53
src/pages/LoginPage.jsx Normal file
View file

@ -0,0 +1,53 @@
import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { loginSuccess, setError } from '../features/auth/authSlice';
import { Box, Button, TextField, Typography, Alert } from '@mui/material';
const LoginPage = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setErrorState] = useState(null);
const dispatch = useDispatch();
const handleLogin = () => {
if (!email || !password) {
setErrorState('Email and Password are required.');
return;
}
// Simulate login API call
try {
dispatch(loginSuccess({ email })); // Replace with actual API response
} catch (err) {
dispatch(setError(err.message));
setErrorState('Invalid credentials.');
}
};
return (
<Box p={3} maxWidth="400px" mx="auto">
<Typography variant="h5" mb={2}>Login</Typography>
{error && <Alert severity="error">{error}</Alert>}
<TextField
label="Email"
fullWidth
margin="normal"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<TextField
label="Password"
type="password"
fullWidth
margin="normal"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<Button variant="contained" color="primary" fullWidth onClick={handleLogin}>
Login
</Button>
</Box>
);
};
export default LoginPage;

View file

@ -0,0 +1,8 @@
function ResourceInvitePage(params) {
return(
<h1>
ResourceInvitePage</h1>
)
}
export default ResourceInvitePage

49
src/theme.js Normal file
View file

@ -0,0 +1,49 @@
import { createTheme } from '@mui/material/styles';
const lightTheme = createTheme({
palette: {
mode: 'light',
primary: {
main: '#2196f3', // Light Blue
},
secondary: {
main: '#90caf9', // Lighter Blue
},
background: {
default: '#f5f5f5', // Light Gray
paper: '#ffffff', // White
},
text: {
primary: '#000000', // Black
secondary: '#555555', // Dark Gray
},
},
typography: {
fontFamily: `'Roboto', 'Arial', sans-serif`,
},
});
const darkTheme = createTheme({
palette: {
mode: 'dark',
primary: {
main: '#2196f3', // Light Blue
},
secondary: {
main: '#64b5f6', // Slightly Lighter Blue
},
background: {
default: '#121212', // Black
paper: '#1e1e1e', // Dark Gray
},
text: {
primary: '#ffffff', // White
secondary: '#bbbbbb', // Light Gray
},
},
typography: {
fontFamily: `'Roboto', 'Arial', sans-serif`,
},
});
export { lightTheme, darkTheme };