mirror of
https://github.com/TurTaskProject/TurTaskWeb.git
synced 2025-12-19 05:54:07 +01:00
Format code with Prettier
This commit is contained in:
parent
bac1f96ad8
commit
038a0c84b7
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import { Navigate, Outlet } from 'react-router-dom';
|
import { Navigate, Outlet } from "react-router-dom";
|
||||||
import IsAuthenticated from './hooks/authentication/IsAuthenticated';
|
import IsAuthenticated from "./hooks/authentication/IsAuthenticated";
|
||||||
|
|
||||||
const PrivateRoute = () => {
|
const PrivateRoute = () => {
|
||||||
const auth = IsAuthenticated();
|
const auth = IsAuthenticated();
|
||||||
return auth ? <Outlet /> : <Navigate to="/login" />;
|
return auth ? <Outlet /> : <Navigate to="/login" />;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default PrivateRoute;
|
export default PrivateRoute;
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import axios from 'axios';
|
import axios from "axios";
|
||||||
|
|
||||||
const ApiUpdateUserProfile = async (formData) => {
|
const ApiUpdateUserProfile = async formData => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('http://127.0.1:8000/api/user/update/', formData, {
|
const response = await axios.post("http://127.0.1:8000/api/user/update/", formData, {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': "Bearer " + localStorage.getItem('access_token'),
|
Authorization: "Bearer " + localStorage.getItem("access_token"),
|
||||||
'Content-Type': 'multipart/form-data',
|
"Content-Type": "multipart/form-data",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ const ApiUpdateUserProfile = async (formData) => {
|
|||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating user profile:', error);
|
console.error("Error updating user profile:", error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import axios from 'axios';
|
import axios from "axios";
|
||||||
import { redirect } from 'react-router-dom';
|
import { redirect } from "react-router-dom";
|
||||||
|
|
||||||
const axiosInstance = axios.create({
|
const axiosInstance = axios.create({
|
||||||
baseURL: 'http://127.0.0.1:8000/api/',
|
baseURL: "http://127.0.0.1:8000/api/",
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': "Bearer " + localStorage.getItem('access_token'),
|
Authorization: "Bearer " + localStorage.getItem("access_token"),
|
||||||
'Content-Type': 'application/json',
|
"Content-Type": "application/json",
|
||||||
'accept': 'application/json',
|
accept: "application/json",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -16,28 +16,30 @@ axiosInstance.interceptors.response.use(
|
|||||||
response => response,
|
response => response,
|
||||||
error => {
|
error => {
|
||||||
const originalRequest = error.config;
|
const originalRequest = error.config;
|
||||||
const refresh_token = localStorage.getItem('refresh_token');
|
const refresh_token = localStorage.getItem("refresh_token");
|
||||||
|
|
||||||
// Check if the error is due to 401 and a refresh token is available
|
// Check if the error is due to 401 and a refresh token is available
|
||||||
if (error.response.status === 401 && error.response.statusText === "Unauthorized" && refresh_token !== "undefined") {
|
if (
|
||||||
|
error.response.status === 401 &&
|
||||||
|
error.response.statusText === "Unauthorized" &&
|
||||||
|
refresh_token !== "undefined"
|
||||||
|
) {
|
||||||
return axiosInstance
|
return axiosInstance
|
||||||
.post('/token/refresh/', { refresh: refresh_token })
|
.post("/token/refresh/", { refresh: refresh_token })
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
|
localStorage.setItem("access_token", response.data.access);
|
||||||
|
|
||||||
localStorage.setItem('access_token', response.data.access);
|
axiosInstance.defaults.headers["Authorization"] = "Bearer " + response.data.access;
|
||||||
|
originalRequest.headers["Authorization"] = "Bearer " + response.data.access;
|
||||||
axiosInstance.defaults.headers['Authorization'] = "Bearer " + response.data.access;
|
|
||||||
originalRequest.headers['Authorization'] = "Bearer " + response.data.access;
|
|
||||||
|
|
||||||
return axiosInstance(originalRequest);
|
return axiosInstance(originalRequest);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.log('Interceptors error: ', err);
|
console.log("Interceptors error: ", err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
export default axiosInstance;
|
export default axiosInstance;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
|
|
||||||
function EachBlog({ name, colorCode }) {
|
function EachBlog({ name, colorCode }) {
|
||||||
return (
|
return (
|
||||||
@ -6,18 +6,16 @@ function EachBlog({ name, colorCode }) {
|
|||||||
<div className={`text-xl font-bold`} style={{ color: colorCode }}>
|
<div className={`text-xl font-bold`} style={{ color: colorCode }}>
|
||||||
{name}
|
{name}
|
||||||
</div>
|
</div>
|
||||||
<div className='h-36'>
|
<div className="h-36">Content goes here</div>
|
||||||
Content goes here
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Eisenhower() {
|
function Eisenhower() {
|
||||||
return (
|
return (
|
||||||
<div className='bg-slate-100 text-left p-4 m-auto'>
|
<div className="bg-slate-100 text-left p-4 m-auto">
|
||||||
<h1 className="text-3xl font-bold mb-4">The Eisenhower Matrix</h1>
|
<h1 className="text-3xl font-bold mb-4">The Eisenhower Matrix</h1>
|
||||||
<div className='grid grid-rows-2 grid-cols-2 gap-2'>
|
<div className="grid grid-rows-2 grid-cols-2 gap-2">
|
||||||
<EachBlog name="Urgent & Important" colorCode="#FF5733" />
|
<EachBlog name="Urgent & Important" colorCode="#FF5733" />
|
||||||
<EachBlog name="Urgent & Not important" colorCode="#FDDD5C" />
|
<EachBlog name="Urgent & Not important" colorCode="#FDDD5C" />
|
||||||
<EachBlog name="Not urgent & Important" colorCode="#189AB4" />
|
<EachBlog name="Not urgent & Important" colorCode="#189AB4" />
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
|
|
||||||
function HomePage() {
|
function HomePage() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import React, { useState, useRef } from 'react';
|
import React, { useState, useRef } from "react";
|
||||||
import { ApiUpdateUserProfile } from '../api/UserProfileApi';
|
import { ApiUpdateUserProfile } from "../api/UserProfileApi";
|
||||||
|
|
||||||
function ProfileUpdate() {
|
function ProfileUpdate() {
|
||||||
const [file, setFile] = useState(null);
|
const [file, setFile] = useState(null);
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState("");
|
||||||
const [fullName, setFullName] = useState('');
|
const [fullName, setFullName] = useState("");
|
||||||
const [about, setAbout] = useState('');
|
const [about, setAbout] = useState("");
|
||||||
const defaultImage = 'https://i1.sndcdn.com/artworks-cTz48e4f1lxn5Ozp-L3hopw-t500x500.jpg';
|
const defaultImage = "https://i1.sndcdn.com/artworks-cTz48e4f1lxn5Ozp-L3hopw-t500x500.jpg";
|
||||||
const fileInputRef = useRef(null);
|
const fileInputRef = useRef(null);
|
||||||
|
|
||||||
const handleImageUpload = () => {
|
const handleImageUpload = () => {
|
||||||
@ -15,7 +15,7 @@ function ProfileUpdate() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFileChange = (e) => {
|
const handleFileChange = e => {
|
||||||
const selectedFile = e.target.files[0];
|
const selectedFile = e.target.files[0];
|
||||||
if (selectedFile) {
|
if (selectedFile) {
|
||||||
setFile(selectedFile);
|
setFile(selectedFile);
|
||||||
@ -24,9 +24,9 @@ function ProfileUpdate() {
|
|||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('profile_pic', file);
|
formData.append("profile_pic", file);
|
||||||
formData.append('first_name', username);
|
formData.append("first_name", username);
|
||||||
formData.append('about', about);
|
formData.append("about", about);
|
||||||
|
|
||||||
ApiUpdateUserProfile(formData);
|
ApiUpdateUserProfile(formData);
|
||||||
};
|
};
|
||||||
@ -45,10 +45,7 @@ function ProfileUpdate() {
|
|||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div
|
<div className="avatar w-32 h-32 cursor-pointer hover:blur" onClick={handleImageUpload}>
|
||||||
className="avatar w-32 h-32 cursor-pointer hover:blur"
|
|
||||||
onClick={handleImageUpload}
|
|
||||||
>
|
|
||||||
{file ? (
|
{file ? (
|
||||||
<img src={URL.createObjectURL(file)} alt="Profile" className="rounded-full" />
|
<img src={URL.createObjectURL(file)} alt="Profile" className="rounded-full" />
|
||||||
) : (
|
) : (
|
||||||
@ -69,7 +66,7 @@ function ProfileUpdate() {
|
|||||||
placeholder="Enter your username"
|
placeholder="Enter your username"
|
||||||
className="input w-full"
|
className="input w-full"
|
||||||
value={username}
|
value={username}
|
||||||
onChange={(e) => setUsername(e.target.value)}
|
onChange={e => setUsername(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -81,7 +78,7 @@ function ProfileUpdate() {
|
|||||||
placeholder="Enter your full name"
|
placeholder="Enter your full name"
|
||||||
className="input w-full"
|
className="input w-full"
|
||||||
value={fullName}
|
value={fullName}
|
||||||
onChange={(e) => setFullName(e.target.value)}
|
onChange={e => setFullName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -92,7 +89,7 @@ function ProfileUpdate() {
|
|||||||
placeholder="Tell us about yourself"
|
placeholder="Tell us about yourself"
|
||||||
className="textarea w-full h-32"
|
className="textarea w-full h-32"
|
||||||
value={about}
|
value={about}
|
||||||
onChange={(e) => setAbout(e.target.value)}
|
onChange={e => setAbout(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,31 +1,30 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from "react";
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from "react-router-dom";
|
||||||
import axiosapi from '../../api/AuthenticationApi';
|
import axiosapi from "../../api/AuthenticationApi";
|
||||||
|
|
||||||
import Avatar from '@mui/material/Avatar';
|
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import CssBaseline from '@mui/material/CssBaseline';
|
|
||||||
import TextField from '@mui/material/TextField';
|
|
||||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
|
||||||
import Checkbox from '@mui/material/Checkbox';
|
|
||||||
import Link from '@mui/material/Link';
|
|
||||||
import Grid from '@mui/material/Grid';
|
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
import Container from '@mui/material/Container';
|
|
||||||
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
|
||||||
|
|
||||||
|
import Avatar from "@mui/material/Avatar";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import CssBaseline from "@mui/material/CssBaseline";
|
||||||
|
import TextField from "@mui/material/TextField";
|
||||||
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||||
|
import Checkbox from "@mui/material/Checkbox";
|
||||||
|
import Link from "@mui/material/Link";
|
||||||
|
import Grid from "@mui/material/Grid";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Container from "@mui/material/Container";
|
||||||
|
import { createTheme, ThemeProvider } from "@mui/material/styles";
|
||||||
|
|
||||||
function Copyright(props) {
|
function Copyright(props) {
|
||||||
return (
|
return (
|
||||||
<Typography variant="body2" color="text.secondary" align="center" {...props}>
|
<Typography variant="body2" color="text.secondary" align="center" {...props}>
|
||||||
{'Copyright © '}
|
{"Copyright © "}
|
||||||
<Link color="inherit" href="https://github.com/TurTaskProject/TurTaskWeb">
|
<Link color="inherit" href="https://github.com/TurTaskProject/TurTaskWeb">
|
||||||
TurTask
|
TurTask
|
||||||
</Link>{' '}
|
</Link>{" "}
|
||||||
{new Date().getFullYear()}
|
{new Date().getFullYear()}
|
||||||
{'.'}
|
{"."}
|
||||||
</Typography>
|
</Typography>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -33,18 +32,17 @@ function Copyright(props) {
|
|||||||
const defaultTheme = createTheme();
|
const defaultTheme = createTheme();
|
||||||
|
|
||||||
export default function SignUp() {
|
export default function SignUp() {
|
||||||
|
|
||||||
const Navigate = useNavigate();
|
const Navigate = useNavigate();
|
||||||
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
email: '',
|
email: "",
|
||||||
username: '',
|
username: "",
|
||||||
password: '',
|
password: "",
|
||||||
});
|
});
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
|
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
@ -52,15 +50,15 @@ export default function SignUp() {
|
|||||||
try {
|
try {
|
||||||
axiosapi.createUser(formData);
|
axiosapi.createUser(formData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating user:', error);
|
console.error("Error creating user:", error);
|
||||||
setError('Registration failed. Please try again.');
|
setError("Registration failed. Please try again.");
|
||||||
} finally {
|
} finally {
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
}
|
}
|
||||||
Navigate('/login');
|
Navigate("/login");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChange = (e) => {
|
const handleChange = e => {
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target;
|
||||||
setFormData({ ...formData, [name]: value });
|
setFormData({ ...formData, [name]: value });
|
||||||
};
|
};
|
||||||
@ -72,12 +70,11 @@ export default function SignUp() {
|
|||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
display: 'flex',
|
display: "flex",
|
||||||
flexDirection: 'column',
|
flexDirection: "column",
|
||||||
alignItems: 'center',
|
alignItems: "center",
|
||||||
}}
|
}}>
|
||||||
>
|
<Avatar sx={{ m: 1, bgcolor: "secondary.main" }}>
|
||||||
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
|
|
||||||
<LockOutlinedIcon />
|
<LockOutlinedIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Typography component="h1" variant="h5">
|
<Typography component="h1" variant="h5">
|
||||||
@ -127,12 +124,7 @@ export default function SignUp() {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Button
|
<Button type="submit" fullWidth variant="contained" sx={{ mt: 3, mb: 2 }}>
|
||||||
type="submit"
|
|
||||||
fullWidth
|
|
||||||
variant="contained"
|
|
||||||
sx={{ mt: 3, mb: 2 }}
|
|
||||||
>
|
|
||||||
Sign Up
|
Sign Up
|
||||||
</Button>
|
</Button>
|
||||||
<Grid container justifyContent="flex-end">
|
<Grid container justifyContent="flex-end">
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import axios from 'axios';
|
import axios from "axios";
|
||||||
|
|
||||||
async function refreshAccessToken() {
|
async function refreshAccessToken() {
|
||||||
const refresh_token = localStorage.getItem('refresh_token');
|
const refresh_token = localStorage.getItem("refresh_token");
|
||||||
const access_token = localStorage.getItem('access_token');
|
const access_token = localStorage.getItem("access_token");
|
||||||
|
|
||||||
if (access_token) {
|
if (access_token) {
|
||||||
return true;
|
return true;
|
||||||
@ -12,7 +12,7 @@ async function refreshAccessToken() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const refreshUrl = 'http://127.0.0.1:8000/api/token/refresh/';
|
const refreshUrl = "http://127.0.0.1:8000/api/token/refresh/";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(refreshUrl, { refresh: refresh_token });
|
const response = await axios.post(refreshUrl, { refresh: refresh_token });
|
||||||
@ -22,8 +22,8 @@ async function refreshAccessToken() {
|
|||||||
const newAccessToken = response.data.access;
|
const newAccessToken = response.data.access;
|
||||||
const newRefreshToken = response.data.refresh;
|
const newRefreshToken = response.data.refresh;
|
||||||
|
|
||||||
localStorage.setItem('access_token', newAccessToken);
|
localStorage.setItem("access_token", newAccessToken);
|
||||||
localStorage.setItem('refresh_token', newRefreshToken);
|
localStorage.setItem("refresh_token", newRefreshToken);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { fetchTodoTasks } from '../../api/TaskApi';
|
import { fetchTodoTasks } from "../../api/TaskApi";
|
||||||
|
|
||||||
let eventGuid = 0
|
let eventGuid = 0;
|
||||||
|
|
||||||
// function getDateAndTime(dateString) {
|
// function getDateAndTime(dateString) {
|
||||||
// const dateObject = new Date(dateString);
|
// const dateObject = new Date(dateString);
|
||||||
@ -18,14 +18,14 @@ let eventGuid = 0
|
|||||||
// return dateFormatted + timeFormatted;
|
// return dateFormatted + timeFormatted;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const mapResponseToEvents = (response) => {
|
const mapResponseToEvents = response => {
|
||||||
return response.map(item => ({
|
return response.map(item => ({
|
||||||
id: createEventId(),
|
id: createEventId(),
|
||||||
title: item.title,
|
title: item.title,
|
||||||
start: item.start_event,
|
start: item.start_event,
|
||||||
end: item.end_event,
|
end: item.end_event,
|
||||||
}));
|
}));
|
||||||
}
|
};
|
||||||
|
|
||||||
export async function getEvents() {
|
export async function getEvents() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from "react";
|
||||||
import { formatDate } from "@fullcalendar/core";
|
import { formatDate } from "@fullcalendar/core";
|
||||||
import FullCalendar from "@fullcalendar/react";
|
import FullCalendar from "@fullcalendar/react";
|
||||||
import dayGridPlugin from "@fullcalendar/daygrid";
|
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||||
@ -79,7 +79,7 @@ export default class Calendar extends React.Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDateSelect = (selectInfo) => {
|
handleDateSelect = selectInfo => {
|
||||||
let title = prompt("Please enter a new title for your event");
|
let title = prompt("Please enter a new title for your event");
|
||||||
let calendarApi = selectInfo.view.calendar;
|
let calendarApi = selectInfo.view.calendar;
|
||||||
|
|
||||||
@ -96,13 +96,13 @@ export default class Calendar extends React.Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleEventClick = (clickInfo) => {
|
handleEventClick = clickInfo => {
|
||||||
if (confirm(`Are you sure you want to delete the event '${clickInfo.event.title}'`)) {
|
if (confirm(`Are you sure you want to delete the event '${clickInfo.event.title}'`)) {
|
||||||
clickInfo.event.remove();
|
clickInfo.event.remove();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleEvents = (events) => {
|
handleEvents = events => {
|
||||||
this.setState({
|
this.setState({
|
||||||
currentEvents: events,
|
currentEvents: events,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
|
|
||||||
function PlusIcon() {
|
function PlusIcon() {
|
||||||
return (
|
return (
|
||||||
@ -8,13 +8,8 @@ function PlusIcon() {
|
|||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
className="w-6 h-6"
|
className="w-6 h-6">
|
||||||
>
|
<path strokeLinecap="round" strokeLinejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +1,20 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
|
|
||||||
function TrashIcon() {
|
function TrashIcon() {
|
||||||
return (
|
return React.createElement(
|
||||||
React.createElement(
|
|
||||||
"svg",
|
"svg",
|
||||||
{
|
{
|
||||||
xmlns: "http://www.w3.org/2000/svg",
|
xmlns: "http://www.w3.org/2000/svg",
|
||||||
fill: "none",
|
fill: "none",
|
||||||
viewBox: "0 0 24 24",
|
viewBox: "0 0 24 24",
|
||||||
strokeWidth: 1.5,
|
strokeWidth: 1.5,
|
||||||
className: "w-6 h-6"
|
className: "w-6 h-6",
|
||||||
},
|
},
|
||||||
React.createElement("path", {
|
React.createElement("path", {
|
||||||
strokeLinecap: "round",
|
strokeLinecap: "round",
|
||||||
strokeLinejoin: "round",
|
strokeLinejoin: "round",
|
||||||
d: "M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
|
d: "M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0",
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,29 +5,14 @@ import { useMemo, useState } from "react";
|
|||||||
import PlusIcon from "../icons/plusIcon";
|
import PlusIcon from "../icons/plusIcon";
|
||||||
import TaskCard from "./taskCard";
|
import TaskCard from "./taskCard";
|
||||||
|
|
||||||
function ColumnContainer({
|
function ColumnContainer({ column, deleteColumn, updateColumn, createTask, tasks, deleteTask, updateTask }) {
|
||||||
column,
|
|
||||||
deleteColumn,
|
|
||||||
updateColumn,
|
|
||||||
createTask,
|
|
||||||
tasks,
|
|
||||||
deleteTask,
|
|
||||||
updateTask,
|
|
||||||
}) {
|
|
||||||
const [editMode, setEditMode] = useState(false);
|
const [editMode, setEditMode] = useState(false);
|
||||||
|
|
||||||
const tasksIds = useMemo(() => {
|
const tasksIds = useMemo(() => {
|
||||||
return tasks.map((task) => task.id);
|
return tasks.map(task => task.id);
|
||||||
}, [tasks]);
|
}, [tasks]);
|
||||||
|
|
||||||
const {
|
const { setNodeRef, attributes, listeners, transform, transition, isDragging } = useSortable({
|
||||||
setNodeRef,
|
|
||||||
attributes,
|
|
||||||
listeners,
|
|
||||||
transform,
|
|
||||||
transition,
|
|
||||||
isDragging,
|
|
||||||
} = useSortable({
|
|
||||||
id: column.id,
|
id: column.id,
|
||||||
data: {
|
data: {
|
||||||
type: "Column",
|
type: "Column",
|
||||||
@ -57,8 +42,7 @@ function ColumnContainer({
|
|||||||
rounded-md
|
rounded-md
|
||||||
flex
|
flex
|
||||||
flex-col
|
flex-col
|
||||||
"
|
"></div>
|
||||||
></div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,8 +58,7 @@ function ColumnContainer({
|
|||||||
rounded-md
|
rounded-md
|
||||||
flex
|
flex
|
||||||
flex-col
|
flex-col
|
||||||
"
|
">
|
||||||
>
|
|
||||||
{/* Column title */}
|
{/* Column title */}
|
||||||
<div
|
<div
|
||||||
{...attributes}
|
{...attributes}
|
||||||
@ -97,8 +80,7 @@ function ColumnContainer({
|
|||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
"
|
">
|
||||||
>
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<div
|
<div
|
||||||
className="
|
className="
|
||||||
@ -110,8 +92,7 @@ function ColumnContainer({
|
|||||||
py-1
|
py-1
|
||||||
text-sm
|
text-sm
|
||||||
rounded-full
|
rounded-full
|
||||||
"
|
">
|
||||||
>
|
|
||||||
0
|
0
|
||||||
</div>
|
</div>
|
||||||
{!editMode && column.title}
|
{!editMode && column.title}
|
||||||
@ -119,12 +100,12 @@ function ColumnContainer({
|
|||||||
<input
|
<input
|
||||||
className="bg-black focus:border-rose-500 border rounded outline-none px-2"
|
className="bg-black focus:border-rose-500 border rounded outline-none px-2"
|
||||||
value={column.title}
|
value={column.title}
|
||||||
onChange={(e) => updateColumn(column.id, e.target.value)}
|
onChange={e => updateColumn(column.id, e.target.value)}
|
||||||
autoFocus
|
autoFocus
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
setEditMode(false);
|
setEditMode(false);
|
||||||
}}
|
}}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={e => {
|
||||||
if (e.key !== "Enter") return;
|
if (e.key !== "Enter") return;
|
||||||
setEditMode(false);
|
setEditMode(false);
|
||||||
}}
|
}}
|
||||||
@ -142,8 +123,7 @@ function ColumnContainer({
|
|||||||
rounded
|
rounded
|
||||||
px-1
|
px-1
|
||||||
py-2
|
py-2
|
||||||
"
|
">
|
||||||
>
|
|
||||||
<TrashIcon />
|
<TrashIcon />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -151,13 +131,8 @@ function ColumnContainer({
|
|||||||
{/* Column task container */}
|
{/* Column task container */}
|
||||||
<div className="flex flex-grow flex-col gap-4 p-2 overflow-x-hidden overflow-y-auto">
|
<div className="flex flex-grow flex-col gap-4 p-2 overflow-x-hidden overflow-y-auto">
|
||||||
<SortableContext items={tasksIds}>
|
<SortableContext items={tasksIds}>
|
||||||
{tasks.map((task) => (
|
{tasks.map(task => (
|
||||||
<TaskCard
|
<TaskCard key={task.id} task={task} deleteTask={deleteTask} updateTask={updateTask} />
|
||||||
key={task.id}
|
|
||||||
task={task}
|
|
||||||
deleteTask={deleteTask}
|
|
||||||
updateTask={updateTask}
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</SortableContext>
|
</SortableContext>
|
||||||
</div>
|
</div>
|
||||||
@ -166,8 +141,7 @@ function ColumnContainer({
|
|||||||
className="flex gap-2 items-center border-columnBackgroundColor border-2 rounded-md p-4 border-x-columnBackgroundColor hover:bg-mainBackgroundColor hover:text-rose-500 active:bg-black"
|
className="flex gap-2 items-center border-columnBackgroundColor border-2 rounded-md p-4 border-x-columnBackgroundColor hover:bg-mainBackgroundColor hover:text-rose-500 active:bg-black"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
createTask(column.id);
|
createTask(column.id);
|
||||||
}}
|
}}>
|
||||||
>
|
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
Add task
|
Add task
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -1,13 +1,7 @@
|
|||||||
import PlusIcon from "../icons/plusIcon"
|
import PlusIcon from "../icons/plusIcon";
|
||||||
import { useMemo, useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import ColumnContainer from "./columnContainer";
|
import ColumnContainer from "./columnContainer";
|
||||||
import {
|
import { DndContext, DragOverlay, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
|
||||||
DndContext,
|
|
||||||
DragOverlay,
|
|
||||||
PointerSensor,
|
|
||||||
useSensor,
|
|
||||||
useSensors,
|
|
||||||
} from "@dnd-kit/core";
|
|
||||||
import { SortableContext, arrayMove } from "@dnd-kit/sortable";
|
import { SortableContext, arrayMove } from "@dnd-kit/sortable";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
import TaskCard from "./taskCard";
|
import TaskCard from "./taskCard";
|
||||||
@ -98,7 +92,7 @@ const defaultTasks = [
|
|||||||
|
|
||||||
function KanbanBoard() {
|
function KanbanBoard() {
|
||||||
const [columns, setColumns] = useState(defaultCols);
|
const [columns, setColumns] = useState(defaultCols);
|
||||||
const columnsId = useMemo(() => columns.map((col) => col.id), [columns]);
|
const columnsId = useMemo(() => columns.map(col => col.id), [columns]);
|
||||||
|
|
||||||
const [tasks, setTasks] = useState(defaultTasks);
|
const [tasks, setTasks] = useState(defaultTasks);
|
||||||
|
|
||||||
@ -123,18 +117,12 @@ function KanbanBoard() {
|
|||||||
items-center
|
items-center
|
||||||
overflow-x-auto
|
overflow-x-auto
|
||||||
overflow-y-hidden
|
overflow-y-hidden
|
||||||
"
|
">
|
||||||
>
|
<DndContext sensors={sensors} onDragStart={onDragStart} onDragEnd={onDragEnd} onDragOver={onDragOver}>
|
||||||
<DndContext
|
|
||||||
sensors={sensors}
|
|
||||||
onDragStart={onDragStart}
|
|
||||||
onDragEnd={onDragEnd}
|
|
||||||
onDragOver={onDragOver}
|
|
||||||
>
|
|
||||||
<div className="m-auto flex gap-4">
|
<div className="m-auto flex gap-4">
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<SortableContext items={columnsId}>
|
<SortableContext items={columnsId}>
|
||||||
{columns.map((col) => (
|
{columns.map(col => (
|
||||||
<ColumnContainer
|
<ColumnContainer
|
||||||
key={col.id}
|
key={col.id}
|
||||||
column={col}
|
column={col}
|
||||||
@ -143,7 +131,7 @@ function KanbanBoard() {
|
|||||||
createTask={createTask}
|
createTask={createTask}
|
||||||
deleteTask={deleteTask}
|
deleteTask={deleteTask}
|
||||||
updateTask={updateTask}
|
updateTask={updateTask}
|
||||||
tasks={tasks.filter((task) => task.columnId === col.id)}
|
tasks={tasks.filter(task => task.columnId === col.id)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</SortableContext>
|
</SortableContext>
|
||||||
@ -166,8 +154,7 @@ function KanbanBoard() {
|
|||||||
hover:ring-2
|
hover:ring-2
|
||||||
flex
|
flex
|
||||||
gap-2
|
gap-2
|
||||||
"
|
">
|
||||||
>
|
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
Add Column
|
Add Column
|
||||||
</button>
|
</button>
|
||||||
@ -183,18 +170,10 @@ function KanbanBoard() {
|
|||||||
createTask={createTask}
|
createTask={createTask}
|
||||||
deleteTask={deleteTask}
|
deleteTask={deleteTask}
|
||||||
updateTask={updateTask}
|
updateTask={updateTask}
|
||||||
tasks={tasks.filter(
|
tasks={tasks.filter(task => task.columnId === activeColumn.id)}
|
||||||
(task) => task.columnId === activeColumn.id
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{activeTask && (
|
|
||||||
<TaskCard
|
|
||||||
task={activeTask}
|
|
||||||
deleteTask={deleteTask}
|
|
||||||
updateTask={updateTask}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{activeTask && <TaskCard task={activeTask} deleteTask={deleteTask} updateTask={updateTask} />}
|
||||||
</DragOverlay>,
|
</DragOverlay>,
|
||||||
document.body
|
document.body
|
||||||
)}
|
)}
|
||||||
@ -213,12 +192,12 @@ function KanbanBoard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteTask(id) {
|
function deleteTask(id) {
|
||||||
const newTasks = tasks.filter((task) => task.id !== id);
|
const newTasks = tasks.filter(task => task.id !== id);
|
||||||
setTasks(newTasks);
|
setTasks(newTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTask(id, content) {
|
function updateTask(id, content) {
|
||||||
const newTasks = tasks.map((task) => {
|
const newTasks = tasks.map(task => {
|
||||||
if (task.id !== id) return task;
|
if (task.id !== id) return task;
|
||||||
return { ...task, content };
|
return { ...task, content };
|
||||||
});
|
});
|
||||||
@ -236,15 +215,15 @@ function KanbanBoard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteColumn(id) {
|
function deleteColumn(id) {
|
||||||
const filteredColumns = columns.filter((col) => col.id !== id);
|
const filteredColumns = columns.filter(col => col.id !== id);
|
||||||
setColumns(filteredColumns);
|
setColumns(filteredColumns);
|
||||||
|
|
||||||
const newTasks = tasks.filter((t) => t.columnId !== id);
|
const newTasks = tasks.filter(t => t.columnId !== id);
|
||||||
setTasks(newTasks);
|
setTasks(newTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateColumn(id, title) {
|
function updateColumn(id, title) {
|
||||||
const newColumns = columns.map((col) => {
|
const newColumns = columns.map(col => {
|
||||||
if (col.id !== id) return col;
|
if (col.id !== id) return col;
|
||||||
return { ...col, title };
|
return { ...col, title };
|
||||||
});
|
});
|
||||||
@ -279,10 +258,10 @@ function KanbanBoard() {
|
|||||||
const isActiveAColumn = active.data.current?.type === "Column";
|
const isActiveAColumn = active.data.current?.type === "Column";
|
||||||
if (!isActiveAColumn) return;
|
if (!isActiveAColumn) return;
|
||||||
|
|
||||||
setColumns((columns) => {
|
setColumns(columns => {
|
||||||
const activeColumnIndex = columns.findIndex((col) => col.id === activeId);
|
const activeColumnIndex = columns.findIndex(col => col.id === activeId);
|
||||||
|
|
||||||
const overColumnIndex = columns.findIndex((col) => col.id === overId);
|
const overColumnIndex = columns.findIndex(col => col.id === overId);
|
||||||
|
|
||||||
return arrayMove(columns, activeColumnIndex, overColumnIndex);
|
return arrayMove(columns, activeColumnIndex, overColumnIndex);
|
||||||
});
|
});
|
||||||
@ -303,9 +282,9 @@ function KanbanBoard() {
|
|||||||
if (!isActiveATask) return;
|
if (!isActiveATask) return;
|
||||||
|
|
||||||
if (isActiveATask && isOverATask) {
|
if (isActiveATask && isOverATask) {
|
||||||
setTasks((tasks) => {
|
setTasks(tasks => {
|
||||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
const activeIndex = tasks.findIndex(t => t.id === activeId);
|
||||||
const overIndex = tasks.findIndex((t) => t.id === overId);
|
const overIndex = tasks.findIndex(t => t.id === overId);
|
||||||
|
|
||||||
if (tasks[activeIndex].columnId !== tasks[overIndex].columnId) {
|
if (tasks[activeIndex].columnId !== tasks[overIndex].columnId) {
|
||||||
tasks[activeIndex].columnId = tasks[overIndex].columnId;
|
tasks[activeIndex].columnId = tasks[overIndex].columnId;
|
||||||
@ -319,8 +298,8 @@ function KanbanBoard() {
|
|||||||
const isOverAColumn = over.data.current?.type === "Column";
|
const isOverAColumn = over.data.current?.type === "Column";
|
||||||
|
|
||||||
if (isActiveATask && isOverAColumn) {
|
if (isActiveATask && isOverAColumn) {
|
||||||
setTasks((tasks) => {
|
setTasks(tasks => {
|
||||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
const activeIndex = tasks.findIndex(t => t.id === activeId);
|
||||||
|
|
||||||
tasks[activeIndex].columnId = overId;
|
tasks[activeIndex].columnId = overId;
|
||||||
return arrayMove(tasks, activeIndex, activeIndex);
|
return arrayMove(tasks, activeIndex, activeIndex);
|
||||||
|
|||||||
@ -7,14 +7,7 @@ function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
const [mouseIsOver, setMouseIsOver] = useState(false);
|
const [mouseIsOver, setMouseIsOver] = useState(false);
|
||||||
const [editMode, setEditMode] = useState(true);
|
const [editMode, setEditMode] = useState(true);
|
||||||
|
|
||||||
const {
|
const { setNodeRef, attributes, listeners, transform, transition, isDragging } = useSortable({
|
||||||
setNodeRef,
|
|
||||||
attributes,
|
|
||||||
listeners,
|
|
||||||
transform,
|
|
||||||
transition,
|
|
||||||
isDragging,
|
|
||||||
} = useSortable({
|
|
||||||
id: task.id,
|
id: task.id,
|
||||||
data: {
|
data: {
|
||||||
type: "Task",
|
type: "Task",
|
||||||
@ -29,7 +22,7 @@ function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleEditMode = () => {
|
const toggleEditMode = () => {
|
||||||
setEditMode((prev) => !prev);
|
setEditMode(prev => !prev);
|
||||||
setMouseIsOver(false);
|
setMouseIsOver(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,8 +46,7 @@ function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
style={style}
|
style={style}
|
||||||
{...attributes}
|
{...attributes}
|
||||||
{...listeners}
|
{...listeners}
|
||||||
className="bg-mainBackgroundColor p-2.5 h-[100px] min-h-[100px] items-center flex text-left rounded-xl hover:ring-2 hover:ring-inset hover:ring-rose-500 cursor-grab relative"
|
className="bg-mainBackgroundColor p-2.5 h-[100px] min-h-[100px] items-center flex text-left rounded-xl hover:ring-2 hover:ring-inset hover:ring-rose-500 cursor-grab relative">
|
||||||
>
|
|
||||||
<textarea
|
<textarea
|
||||||
className="
|
className="
|
||||||
h-[90%]
|
h-[90%]
|
||||||
@ -64,12 +56,12 @@ function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
autoFocus
|
autoFocus
|
||||||
placeholder="Task content here"
|
placeholder="Task content here"
|
||||||
onBlur={toggleEditMode}
|
onBlur={toggleEditMode}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={e => {
|
||||||
if (e.key === "Enter" && e.shiftKey) {
|
if (e.key === "Enter" && e.shiftKey) {
|
||||||
toggleEditMode();
|
toggleEditMode();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onChange={(e) => updateTask(task.id, e.target.value)}
|
onChange={e => updateTask(task.id, e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -88,19 +80,15 @@ function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
}}
|
}}
|
||||||
onMouseLeave={() => {
|
onMouseLeave={() => {
|
||||||
setMouseIsOver(false);
|
setMouseIsOver(false);
|
||||||
}}
|
}}>
|
||||||
>
|
<p className="my-auto h-[90%] w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap">{task.content}</p>
|
||||||
<p className="my-auto h-[90%] w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap">
|
|
||||||
{task.content}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{mouseIsOver && (
|
{mouseIsOver && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
deleteTask(task.id);
|
deleteTask(task.id);
|
||||||
}}
|
}}
|
||||||
className="stroke-white absolute right-4 top-1/2 -translate-y-1/2 bg-columnBackgroundColor p-2 rounded opacity-60 hover:opacity-100"
|
className="stroke-white absolute right-4 top-1/2 -translate-y-1/2 bg-columnBackgroundColor p-2 rounded opacity-60 hover:opacity-100">
|
||||||
>
|
|
||||||
<TrashIcon />
|
<TrashIcon />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import IsAuthenticated from "../../hooks/authentication/IsAuthenticated";
|
|||||||
import axiosapi from "../../api/AuthenticationApi";
|
import axiosapi from "../../api/AuthenticationApi";
|
||||||
|
|
||||||
const settings = {
|
const settings = {
|
||||||
Profile: '/update_profile',
|
Profile: "/update_profile",
|
||||||
Account: '/account',
|
Account: "/account",
|
||||||
};
|
};
|
||||||
|
|
||||||
function NavBar() {
|
function NavBar() {
|
||||||
|
|||||||
@ -1,26 +1,26 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from "react";
|
||||||
import axiosapi from '../api/axiosapi';
|
import axiosapi from "../api/axiosapi";
|
||||||
import TextField from '@material-ui/core/TextField';
|
import TextField from "@material-ui/core/TextField";
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from "@material-ui/core/Typography";
|
||||||
import CssBaseline from '@material-ui/core/CssBaseline';
|
import CssBaseline from "@material-ui/core/CssBaseline";
|
||||||
import Container from '@material-ui/core/Container';
|
import Container from "@material-ui/core/Container";
|
||||||
import Button from '@material-ui/core/Button';
|
import Button from "@material-ui/core/Button";
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
// Styles for various elements
|
// Styles for various elements
|
||||||
paper: {
|
paper: {
|
||||||
marginTop: theme.spacing(8),
|
marginTop: theme.spacing(8),
|
||||||
display: 'flex',
|
display: "flex",
|
||||||
flexDirection: 'column',
|
flexDirection: "column",
|
||||||
alignItems: 'center',
|
alignItems: "center",
|
||||||
},
|
},
|
||||||
avatar: {
|
avatar: {
|
||||||
margin: theme.spacing(1),
|
margin: theme.spacing(1),
|
||||||
backgroundColor: theme.palette.secondary.main,
|
backgroundColor: theme.palette.secondary.main,
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
width: '100%',
|
width: "100%",
|
||||||
marginTop: theme.spacing(1),
|
marginTop: theme.spacing(1),
|
||||||
},
|
},
|
||||||
submit: {
|
submit: {
|
||||||
@ -31,14 +31,14 @@ const useStyles = makeStyles((theme) => ({
|
|||||||
const Signup = () => {
|
const Signup = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
email: '',
|
email: "",
|
||||||
username: '',
|
username: "",
|
||||||
password: '',
|
password: "",
|
||||||
});
|
});
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
|
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
@ -46,14 +46,14 @@ const Signup = () => {
|
|||||||
try {
|
try {
|
||||||
axiosapi.createUser(formData);
|
axiosapi.createUser(formData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating user:', error);
|
console.error("Error creating user:", error);
|
||||||
setError('Registration failed. Please try again.'); // Set an error message
|
setError("Registration failed. Please try again."); // Set an error message
|
||||||
} finally {
|
} finally {
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChange = (e) => {
|
const handleChange = e => {
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target;
|
||||||
setFormData({ ...formData, [name]: value });
|
setFormData({ ...formData, [name]: value });
|
||||||
};
|
};
|
||||||
@ -102,9 +102,8 @@ const Signup = () => {
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.submit}
|
className={classes.submit}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}>
|
||||||
>
|
{isSubmitting ? "Signing up..." : "Sign Up"}
|
||||||
{isSubmitting ? 'Signing up...' : 'Sign Up'}
|
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
{error && <Typography color="error">{error}</Typography>}
|
{error && <Typography color="error">{error}</Typography>}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from "react";
|
||||||
import axiosapi from '../api/AuthenticationApi';
|
import axiosapi from "../api/AuthenticationApi";
|
||||||
import { Button } from '@mui/material';
|
import { Button } from "@mui/material";
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
function TestAuth() {
|
function TestAuth() {
|
||||||
let Navigate = useNavigate();
|
let Navigate = useNavigate();
|
||||||
@ -10,10 +10,13 @@ function TestAuth() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Fetch the "hello" data from the server when the component mounts
|
// Fetch the "hello" data from the server when the component mounts
|
||||||
axiosapi.getGreeting().then(res => {
|
axiosapi
|
||||||
|
.getGreeting()
|
||||||
|
.then(res => {
|
||||||
console.log(res.data);
|
console.log(res.data);
|
||||||
setMessage(res.data.user);
|
setMessage(res.data.user);
|
||||||
}).catch(err => {
|
})
|
||||||
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
setMessage("");
|
setMessage("");
|
||||||
});
|
});
|
||||||
@ -22,8 +25,8 @@ function TestAuth() {
|
|||||||
const logout = () => {
|
const logout = () => {
|
||||||
// Log out the user, clear tokens, and navigate to the "/testAuth" route
|
// Log out the user, clear tokens, and navigate to the "/testAuth" route
|
||||||
axiosapi.apiUserLogout();
|
axiosapi.apiUserLogout();
|
||||||
Navigate('/testAuth');
|
Navigate("/testAuth");
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -31,7 +34,9 @@ function TestAuth() {
|
|||||||
<div>
|
<div>
|
||||||
<h1 class="text-xl font-bold">Login! Hello!</h1>
|
<h1 class="text-xl font-bold">Login! Hello!</h1>
|
||||||
<h2>{message}</h2>
|
<h2>{message}</h2>
|
||||||
<Button variant="contained" onClick={logout}>Logout</Button>
|
<Button variant="contained" onClick={logout}>
|
||||||
|
Logout
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{message === "" && <h1 class="text-xl font-bold">Need to sign in, No authentication found</h1>}
|
{message === "" && <h1 class="text-xl font-bold">Need to sign in, No authentication found</h1>}
|
||||||
|
|||||||
@ -1,21 +1,21 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
function IsAuthenticated() {
|
function IsAuthenticated() {
|
||||||
const [isAuthenticated, setIsAuthenticated] = useState(() => {
|
const [isAuthenticated, setIsAuthenticated] = useState(() => {
|
||||||
const access_token = localStorage.getItem('access_token');
|
const access_token = localStorage.getItem("access_token");
|
||||||
return !!access_token;
|
return !!access_token;
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleTokenChange = () => {
|
const handleTokenChange = () => {
|
||||||
const newAccessToken = localStorage.getItem('access_token');
|
const newAccessToken = localStorage.getItem("access_token");
|
||||||
setIsAuthenticated(!!newAccessToken);
|
setIsAuthenticated(!!newAccessToken);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('storage', handleTokenChange);
|
window.addEventListener("storage", handleTokenChange);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('storage', handleTokenChange);
|
window.removeEventListener("storage", handleTokenChange);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@ -8,20 +8,18 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans",
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
"Droid Sans", "Helvetica Neue", sans-serif;
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||||
monospace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link{
|
.nav-link {
|
||||||
color:black;
|
color: black;
|
||||||
/* border: 1px solid white; */
|
/* border: 1px solid white; */
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user