Compare commits
11 Commits
a8877ab28e
...
9e0e35d71f
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e0e35d71f | |||
| ac22af3062 | |||
| 2bbeb707db | |||
| fbe380c771 | |||
| c74d559499 | |||
| 06734c95ff | |||
| b45d4172b6 | |||
| dae97d21e1 | |||
| b9490a4472 | |||
| 9d11803b42 | |||
| 739925b046 |
6
composer.json
Normal file
6
composer.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"require": {
|
||||
"laravel/sanctum": "^4.0",
|
||||
"laravel/ui": "^4.5"
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,15 @@ function App() {
|
||||
const getCSRF = async ()=>{
|
||||
try {
|
||||
await http.get('/sanctum/csrf-cookie')
|
||||
const res= await http.get('/api/user')
|
||||
console.log(res.data);
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='App' style={{marginTop: '20px' }}>
|
||||
<div className='App' style={{marginTop: '20px' }}>
|
||||
<AppShell
|
||||
header={{height: 50}}
|
||||
navbar={{width: 300, breakpoint: 'sm', collapsed: {mobile: !opened}}}
|
||||
|
||||
@@ -2,7 +2,6 @@ import React,{ useEffect,useState } from 'react';
|
||||
import {Button, TextInput, rem, PasswordInput} from '@mantine/core';
|
||||
import { IconAt } from '@tabler/icons-react';
|
||||
import { useParams,useNavigate } from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import {http} from "../middleware/axiosConfig";
|
||||
|
||||
const Edit = () => {
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { Flex, AppShell, Burger, Button, Paper, useMantineColorScheme, useComputedColorScheme} from '@mantine/core';
|
||||
import {FaSun, FaMoon} from 'react-icons/fa';
|
||||
import { Text } from '@mantine/core';
|
||||
import List from './Lists';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
const Header = ({toggle, opened}) => {
|
||||
const {setColorScheme} = useMantineColorScheme();
|
||||
const computedColorScheme = useComputedColorScheme('light');
|
||||
|
||||
const navigate= useNavigate();
|
||||
|
||||
const clickToBackHandler=()=>{
|
||||
navigate("/*");
|
||||
}
|
||||
|
||||
const toggleColorScheme = () => {
|
||||
setColorScheme(computedColorScheme === "dark" ? "light" : "dark")}
|
||||
|
||||
@@ -22,7 +28,15 @@ const Header = ({toggle, opened}) => {
|
||||
>
|
||||
ADMIN MANAGEMENT
|
||||
</Text></div>
|
||||
<Button size="sm" variant="link" onClick={toggleColorScheme}>{computedColorScheme === "dark" ? <FaSun/> : <FaMoon/>}</Button>
|
||||
<div>
|
||||
<Button size="xs" variant="link" onClick={toggleColorScheme}>{computedColorScheme === "dark" ? <FaSun/> : <FaMoon/>}</Button>
|
||||
<Button
|
||||
style={{ marginLeft: '10px' }}
|
||||
variant="gradient"
|
||||
gradient={{ from: 'blue', to: 'green', deg: 229 }}
|
||||
size="xs"
|
||||
onClick={clickToBackHandler}>Log Out</Button>
|
||||
</div>
|
||||
</Flex>
|
||||
</AppShell.Header>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Button, TextInput, rem, PasswordInput} from '@mantine/core';
|
||||
import {Button, TextInput, rem, PasswordInput, Text} from '@mantine/core';
|
||||
import { IconAt } from '@tabler/icons-react';
|
||||
import {useState} from 'react';
|
||||
import {http} from "../middleware/axiosConfig";
|
||||
@@ -25,17 +25,38 @@ function Home() {
|
||||
// Initialize state to handle loading state
|
||||
const [loading,setLoading]=useState()
|
||||
|
||||
const [errors, setErrors] =useState({})
|
||||
|
||||
|
||||
//Inserts new account to the Database{reactapp.users}.post
|
||||
const onSubmitChange = async (e) => {
|
||||
e.preventDefault();
|
||||
try{
|
||||
const response= await http.post("/api/addnew", userField);
|
||||
console.log(response)
|
||||
setLoading(true);
|
||||
} catch(err){
|
||||
console.error(err)
|
||||
console.log("Something's Wrong!");
|
||||
//validation for errors
|
||||
const validationErrors = {}
|
||||
if (!userField.name.trim()){
|
||||
validationErrors.name = <Text size="xs" fw={500} fs="italic" c="red">Name is Required!</Text>
|
||||
}
|
||||
if (!userField.email.trim()){
|
||||
validationErrors.email = <Text size="xs" fw={500} fs="italic" c="red">Email is Required!</Text>
|
||||
} else if(!/^\S+@\S+$/.test(userField.email)){
|
||||
validationErrors.email = <Text size="xs" fw={500} fs="italic" c="red">Email is Invalid!</Text>
|
||||
}
|
||||
if (!userField.password.trim()){
|
||||
validationErrors.password = <Text size="xs" fw={500} fs="italic" c="red">Password is Required!</Text>
|
||||
} else if(userField.password.length < 6){
|
||||
validationErrors.password = <Text size="xs" fw={500} fs="italic" c="red">Password should be at least 6 characters!</Text>
|
||||
}
|
||||
|
||||
try {
|
||||
setErrors(validationErrors)
|
||||
const response = await http.post('/api/addnew', userField);
|
||||
console.log(response);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
console.log("Something's Wrong!");
|
||||
} finally {
|
||||
setLoading(true);
|
||||
}
|
||||
}
|
||||
|
||||
//If loading is true, return to <Home />
|
||||
@@ -47,7 +68,7 @@ function Home() {
|
||||
return (
|
||||
<div className="container">
|
||||
<h2 className='w-100 d-flex justify-content-center p-3'> ADD ACCOUNT </h2>
|
||||
<form>
|
||||
<form onSubmit={onSubmitChange}>
|
||||
<div>
|
||||
{/* Name Input */}
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
||||
@@ -58,11 +79,13 @@ function Home() {
|
||||
name='name'
|
||||
id='name'
|
||||
onChange={e => changeUserFieldHandler(e)}
|
||||
style={{ width: '400px', marginBottom: '10px' }}/></div>
|
||||
style={{ width: '400px', marginBottom: '10px' }}/>
|
||||
</div>
|
||||
{/* Validation Error */}
|
||||
{errors.name && <div>{errors.name}</div>}
|
||||
{/* E-mail Input */}
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
||||
<TextInput
|
||||
required
|
||||
leftSectionPointerEvents="none"
|
||||
leftSection={icon}
|
||||
label="E-mail:"
|
||||
@@ -73,20 +96,23 @@ function Home() {
|
||||
onChange={e => changeUserFieldHandler(e)}
|
||||
style={{ width: '400px', marginBottom: '10px' }}/>
|
||||
</div>
|
||||
{/* Validation Error */}
|
||||
{errors.email && <div>{errors.email}</div>}
|
||||
{/* Password Input */}
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
||||
<PasswordInput
|
||||
required
|
||||
name='password'
|
||||
label="Password"
|
||||
withAsterisk
|
||||
description="Please ensure that no special characters are included."
|
||||
placeholder="Enter Your Password"
|
||||
onChange={e => changeUserFieldHandler(e)}
|
||||
style={{ width: '400px', marginBottom: '10px' }}/>
|
||||
</div>
|
||||
{/* Validation Error */}
|
||||
{errors.password && <div>{errors.password}</div>}
|
||||
{/* Submit Button - triggers the onSubmitChange function*/}
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
||||
<Button style={{ margin: 25 }} variant="filled" color="rgba(30, 128, 10, 1)" size="sm" radius="xl" onClick={e => onSubmitChange(e)}>Sign Up</Button>
|
||||
<Button type="submit" style={{ margin: 25 }} variant="filled" color="rgba(30, 128, 10, 1)" size="sm" radius="xl" onClick={e => onSubmitChange(e)}>Sign Up</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -94,4 +120,4 @@ function Home() {
|
||||
);
|
||||
}
|
||||
|
||||
export default Home;
|
||||
export default Home
|
||||
@@ -1,13 +1,16 @@
|
||||
import React, { useState,useEffect } from 'react';
|
||||
import { Button, Table } from '@mantine/core';
|
||||
import { Dialog, Button, Table, Text, Group } from '@mantine/core';
|
||||
import { Link } from 'react-router-dom';
|
||||
import {http} from "../middleware/axiosConfig";
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
|
||||
const List = () => {
|
||||
|
||||
// Initialize state for user data
|
||||
const [ userData, setUserData] = useState([]);
|
||||
|
||||
const [opened, { toggle, close }] = useDisclosure(false);
|
||||
|
||||
//useEffect hook -
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
@@ -60,14 +63,30 @@ const List = () => {
|
||||
<Table.Td>
|
||||
{/* Action.View Button - triggers the View module */}
|
||||
<Link to={`/view/${users.id}`}>
|
||||
<Button style={{ marginRight: '10px' }} variant="filled" color="rgba(81, 194, 52, 1)">View</Button>
|
||||
<Button style={{ marginRight: '10px' }} variant="outline" color="rgba(81, 194, 52, 1)">View</Button>
|
||||
</Link>
|
||||
{/* Action.Edit Button - triggers the Edit module */}
|
||||
<Link to={`/edit/${users.id}`}>
|
||||
<Button style={{ marginRight: '10px' }} variant="filled">Edit</Button>
|
||||
<Button style={{ marginRight: '10px' }} variant="outline">Edit</Button>
|
||||
</Link>
|
||||
{/* Delete Button - triggers the handleDelete function */}
|
||||
<Button onClick={()=>handleDelete(users.id)} style={{ marginRight: '10px' }} variant="filled" color="rgba(227, 9, 9, 1)">Delete</Button>
|
||||
{/* <Button onClick={()=>handleDelete(users.id)} style={{ marginRight: '10px' }} variant="filled" color="rgba(227, 9, 9, 1)">Delete</Button> */}
|
||||
<Button onClick={toggle} style={{ marginRight: '10px' }} variant="outline" color="rgba(227, 9, 9, 1)">Delete</Button>
|
||||
<Dialog
|
||||
position={{ top: 200, left: 500 }} opened={opened}
|
||||
shadow="xl"
|
||||
onclose={close}
|
||||
size="lg"
|
||||
radius="md"
|
||||
withBorder
|
||||
style={{ backgroundColor: 'lightblue' }} >
|
||||
<Text size="sm" mb="xs" fw={500} align="center">
|
||||
Are you sure you want to Delete this account? </Text>
|
||||
<Group algin="flex-end">
|
||||
<Button onClick={close} style={{ marginLeft: '90px', marginTop: '10px' }} variant="filled" color="rgba(5, 66, 1, 1)">Cancel</Button>
|
||||
<Button onClick={()=>handleDelete(users.id)} style={{ marginRight: '45px', marginTop: '10px' }} variant="filled" color="rgba(227, 9, 9, 1)">Delete</Button>
|
||||
</Group>
|
||||
</Dialog>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
)})
|
||||
|
||||
@@ -4,38 +4,37 @@ import { Paper, Text, TextInput, PasswordInput, Button, rem} from "@mantine/core
|
||||
import {useState} from 'react';
|
||||
import {http} from "../middleware/axiosConfig";
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {useForm} from 'react-hook-form'
|
||||
|
||||
|
||||
const Login = () => {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [userField, setUserField] = useState({
|
||||
email:"",
|
||||
password:""
|
||||
});
|
||||
const {register, handleSubmit, } = useForm({
|
||||
defaultValue: {
|
||||
email: '',
|
||||
password: ''
|
||||
}
|
||||
})
|
||||
|
||||
const changeFieldHandler = (e) => {
|
||||
setUserField({
|
||||
...userField,
|
||||
[e.target.email]: e.target.value
|
||||
});
|
||||
}
|
||||
const {formState: { errors }} = useForm();
|
||||
|
||||
const [loginError, setloginError] = useState(false);
|
||||
|
||||
const onLogin = async (e) => {
|
||||
try {
|
||||
setloginError(false);
|
||||
await http.get("/sanctum/csrf-cookie");
|
||||
const res = await http.post("/api/login", {
|
||||
email: e.email,
|
||||
password: e.password,
|
||||
});
|
||||
const res = await http.post("/api/login", e);
|
||||
if (res.status === 200){
|
||||
navigate("/lists");
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err)
|
||||
console.log("Something's Wrong!");
|
||||
catch (error) {
|
||||
if (error.response.status === 401) {
|
||||
setloginError(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,7 +43,7 @@ const Login = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Paper radius="md" p="xl" withBorder>
|
||||
<Paper shadow="md" radius="md" p="xl" withBorder>
|
||||
<Text size="xl" fw={900} variant="gradient"
|
||||
gradient={{ from: 'red', to: 'rgba(227, 0, 0, 1)', deg: 227 }}>WELCOME ADMIN!</Text>
|
||||
<Text size="sm">Please login to access the Admin Account Management Site</Text>
|
||||
@@ -52,26 +51,34 @@ const Login = () => {
|
||||
<TextInput
|
||||
style={{ width: '400px', marginBottom: '10px', marginTop: '15px' }}
|
||||
label="Email"
|
||||
leftSectionPointerEvents="none"
|
||||
leftSection={icon}
|
||||
withAsterisk
|
||||
onChange={e => changeFieldHandler(e)}
|
||||
{...register('email')}
|
||||
placeholder="Enter your work email address"
|
||||
error={errors.email ? "Please enter a valid email" : null}
|
||||
/></div>
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
||||
<PasswordInput
|
||||
style={{ width: '400px', marginBottom: '10px' }}
|
||||
label="Password"
|
||||
placeholder="Enter your Password"
|
||||
withAsterisk
|
||||
onChange={e => changeFieldHandler(e)}
|
||||
{...register('password')}
|
||||
visible={visible}
|
||||
onVisibilityChange={toggle}
|
||||
error={
|
||||
errors.password
|
||||
? "Please enter a valid password"
|
||||
: null
|
||||
}
|
||||
/></div>
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
||||
<Button variant="filled" color="lime" style={{ margin: 25 }} onClick={e => onLogin(e)}>Log In
|
||||
<Button variant="filled" color="lime" style={{ margin: 25 }} onClick={e => handleSubmit(onLogin)()}>Log In
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
||||
{loginError && (
|
||||
<Text fw={500} fs="italic" c="red">
|
||||
Login failed! Please verify your credentials and try again.
|
||||
</Text>)}</div>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
|
||||
19
src/components/ProtectedRoute.js
Normal file
19
src/components/ProtectedRoute.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Navigate } from "react-router-dom"
|
||||
import React from "react"
|
||||
import Root from "../routes/Root"
|
||||
|
||||
export default function ProtectedRoute({ user, loading }) {
|
||||
return (
|
||||
<>
|
||||
{!loading ? (
|
||||
user ? (
|
||||
<Root />
|
||||
) : (
|
||||
<Navigate to="/login" />
|
||||
)
|
||||
) : (
|
||||
<div>loading....</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// import { Paper, Text, TextInput } from "@mantine/core";
|
||||
|
||||
// const Registration = () => {
|
||||
// return (
|
||||
// <div>
|
||||
// <Paper radius="md" p="xl" withBorder>
|
||||
// <Text size="xl" fw={900} variant="gradient"
|
||||
// gradient={{ from: 'orange', to: 'yellow', deg: 102 }}>WELCOME ADMIN!</Text>
|
||||
// <Text size="sm">Please login to access the Admin Account Management Site</Text>
|
||||
// <TextInput>
|
||||
|
||||
// </TextInput>
|
||||
// </Paper>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default Registration;
|
||||
36
src/components/Root.js
Normal file
36
src/components/Root.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import NavBar from './components/NavBar';
|
||||
import Header from './components/Header';
|
||||
import RouterSwitcher from './components/RouterSwitcher';
|
||||
import {AppShell} from '@mantine/core';
|
||||
|
||||
|
||||
export default function Root({ logout }) {
|
||||
const location = useLocation();
|
||||
|
||||
const [active, setActive] = useState(
|
||||
data.findIndex((item) => item.link === location.pathname)
|
||||
);
|
||||
|
||||
const [opened, {toggle}] = useDisclosure();
|
||||
|
||||
return(
|
||||
<div className='App' style={{marginTop: '20px' }}>
|
||||
<AppShell
|
||||
header={{height: 50}}
|
||||
navbar={{width: 300, breakpoint: 'sm', collapsed: {mobile: !opened}}}
|
||||
padding="md">
|
||||
<Header toggle={toggle} opened={opened}/>
|
||||
<NavBar />
|
||||
<AppShell.Main>
|
||||
<RouterSwitcher>
|
||||
</RouterSwitcher>
|
||||
</ AppShell.Main>
|
||||
<AppShell.Footer zIndex={opened ? 'auto': 201}>
|
||||
Built by Maritoni V. Benjamin
|
||||
</AppShell.Footer>
|
||||
</AppShell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -4,15 +4,13 @@ import NotFound from "./NotFound";
|
||||
import List from "./Lists";
|
||||
import View from './View';
|
||||
import Edit from "./Edit";
|
||||
// import Registration from "./Registration";
|
||||
// import Login from "./Login";
|
||||
import Login from "./Login";
|
||||
|
||||
|
||||
const RouterSwitcher = () => {
|
||||
return(
|
||||
<Routes>
|
||||
{/* <Route path="/*" element={<Registration />} /> */}
|
||||
{/* <Route path="/*" element={<Login />} /> */}
|
||||
<Route path="/*" element={<Login />} />
|
||||
<Route path="/home" element={<Home />} />
|
||||
<Route path="/lists" element={<List />} />
|
||||
<Route path="/view/:id" element={<View />} />
|
||||
|
||||
Reference in New Issue
Block a user