diff --git a/src/backend/API/timeoff.js b/src/backend/API/timeoff.js
index 5dd82f1..16b4560 100644
--- a/src/backend/API/timeoff.js
+++ b/src/backend/API/timeoff.js
@@ -2,20 +2,24 @@ const express = require("express");
const router = express.Router();
const db = require("../database");
-router.get('/', async (req, res) => {
+router.get("/", async (req, res) => {
try {
- const allTimeOffs = await db.select('*').from('timeoff');
- res.json(allTimeOffs);
+ const allTimeOffs = await db.select("*").from("timeoff");
+ res.json(allTimeOffs);
} catch (error) {
console.error(error);
- res.status(500).json({ error: 'An unexpected error occurred while processing your request.' });
+ res
+ .status(500)
+ .json({
+ error: "An unexpected error occurred while processing your request.",
+ });
}
});
router.post("/:id", async (request, response) => {
- const { start_date, end_date, description, member_id } = request.body;
+ const { start_date, end_date, description, member_id } = request.body;
if (!start_date || !end_date || !description || !member_id) {
- return response.status(400).json({ error: 'Missing required fields' });
+ return response.status(400).json({ error: "Missing required fields" });
}
const addTimeOff = {
@@ -30,9 +34,24 @@ router.post("/:id", async (request, response) => {
await db("timeoff").insert(addTimeOff);
response.status(201).json("New timeoff has been added");
} catch (error) {
- console.error(error);
+ console.error(error);
response.status(500).json({ error: "Failed to add a new timeoff" });
}
});
+router.delete("/", async (request, response) => {
+ const eventId = request.body.id;
+ if (!eventId) {
+ return response.status(400).json({ error: "Event ID is required" });
+ }
+
+ try {
+ await db("timeoff").where({ id: eventId }).del();
+ response.status(204).send();
+ } catch (error) {
+ console.error(error);
+ response.status(500).json({ error: "Failed to delete the event" });
+ }
+});
+
module.exports = router;
diff --git a/src/component/Calendar.jsx b/src/component/Calendar.jsx
index 00e636f..fd75216 100644
--- a/src/component/Calendar.jsx
+++ b/src/component/Calendar.jsx
@@ -4,13 +4,15 @@ import dayjs from "dayjs";
import "react-big-calendar/lib/css/react-big-calendar.css";
import { TeamDataContext } from "../component/Context";
import { apiPath } from "../api";
-import '../styles/calender.css'
+import "../styles/calender.css";
+import "../styles/deleteTimeoff.css";
function MyCalendar() {
const localizer = dayjsLocalizer(dayjs);
- const { teams, members } = useContext(TeamDataContext);
+ const { teams, members, refreshTeamData } = useContext(TeamDataContext);
const [events, setEvents] = useState([]);
const [selectedEvent, setSelectedEvent] = useState(null);
+ const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);
useEffect(() => {
const teamCode = window.location.pathname.split("/").pop();
@@ -34,6 +36,7 @@ function MyCalendar() {
(member) => member.id === event.member_id
);
return {
+ id: event.id,
start: new Date(event.start_date),
end: new Date(event.end_date),
title: member ? `${member.first_name} ${member.last_name}` : "",
@@ -43,6 +46,7 @@ function MyCalendar() {
});
setEvents(formattedEvents);
+ refreshTeamData();
} catch (error) {
console.error("Error fetching events:", error);
}
@@ -55,6 +59,31 @@ function MyCalendar() {
setSelectedEvent(event);
};
+ const handleDeleteEvent = async () => {
+ setShowDeleteConfirmation(true);
+ };
+
+ const confirmDelete = async () => {
+ try {
+ await fetch(apiPath(`/timeoff`), {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ id: selectedEvent.id }),
+ });
+ setEvents(events.filter((event) => event.id !== selectedEvent.id));
+ setSelectedEvent(null);
+ setShowDeleteConfirmation(false);
+ } catch (error) {
+ console.error("Error deleting event:", error);
+ }
+ };
+
+ const cancelDelete = () => {
+ setShowDeleteConfirmation(false);
+ };
+
return (
{selectedEvent.title}
{selectedEvent.description}
+
+ {showDeleteConfirmation && (
+
+
Are you sure you want to delete this event?
+
+
+
+ )}
)}
diff --git a/src/component/Context.jsx b/src/component/Context.jsx
index 07fec3e..af6bc4e 100644
--- a/src/component/Context.jsx
+++ b/src/component/Context.jsx
@@ -7,9 +7,13 @@ const TeamDataProvider = ({ children }) => {
const [teams, setTeams] = useState([]);
const [members, setMembers] = useState([]);
const [timeOff, setTimeOff] = useState([]);
+ const [dataIsOld, setDataIsOld] = useState(false);
- useEffect(() => {
- const fetchData = async () => {
+ const refreshTeamData = () => {
+ setDataIsOld(true)
+ }
+
+ const fetchData = async () => {
try {
const [teamsResponse, membersResponse, timeOffResponse] = await Promise.all([
fetch(apiPath('/teams')),
@@ -28,12 +32,20 @@ const TeamDataProvider = ({ children }) => {
console.error('Error fetching data:', error);
}
};
-
+
+ useEffect(() => {
fetchData();
}, []);
+ useEffect(() => {
+ if(dataIsOld) {
+ fetchData();
+ setDataIsOld(false)
+ }
+ }, [dataIsOld]);
+
return (
-
+
{children}
);
diff --git a/src/component/CreateMember.jsx b/src/component/CreateMember.jsx
index 09b5c4d..70df033 100644
--- a/src/component/CreateMember.jsx
+++ b/src/component/CreateMember.jsx
@@ -1,13 +1,12 @@
import { useState, useEffect, useContext } from "react";
import { useParams } from "react-router-dom";
-import { apiPath } from '../api';
-import { TeamDataContext } from '../component/Context';
-import '../styles/createMember.css'
+import { apiPath } from "../api";
+import { TeamDataContext } from "../component/Context";
+import "../styles/createMember.css";
function CreateMember() {
- const { code } = useParams();
- const contextData = useContext(TeamDataContext);
- const teams = contextData.teams;
+ const { code } = useParams();
+ const { teams, refreshTeamData } = useContext(TeamDataContext);
const [teamId, setTeamId] = useState(null);
const [memberData, setMemberData] = useState({
@@ -15,11 +14,11 @@ function CreateMember() {
last_name: "",
email: "",
color: "#000000",
- allowed_dayoff: 0,
+ allowed_dayoff: 0,
});
useEffect(() => {
- const team = teams.find(team => team.team_code === code);
+ const team = teams.find((team) => team.team_code === code);
if (team) {
setTeamId(team.id);
} else {
@@ -31,7 +30,7 @@ function CreateMember() {
e.preventDefault();
try {
- const response = await fetch(apiPath('/members'), {
+ const response = await fetch(apiPath("/members"), {
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -39,13 +38,20 @@ function CreateMember() {
body: JSON.stringify({
...memberData,
team_id: teamId,
- assigned_dayoff: 0,
+ assigned_dayoff: 0,
}),
});
if (response.ok) {
alert("Member created successfully!");
- setMemberData({ first_name: "", last_name: "", email: "", color: "#000000", allowed_dayoff: 0 });
+ refreshTeamData();
+ setMemberData({
+ first_name: "",
+ last_name: "",
+ email: "",
+ color: "#000000",
+ allowed_dayoff: 0,
+ });
} else {
const data = await response.json();
alert(data.error || "Failed to create member. Please try again.");
@@ -58,7 +64,7 @@ function CreateMember() {
const handleChange = (e) => {
const { name, value } = e.target;
- setMemberData(prevState => ({
+ setMemberData((prevState) => ({
...prevState,
[name]: value,
}));
diff --git a/src/component/DeleteMember.jsx b/src/component/DeleteMember.jsx
index 961347b..80d3159 100644
--- a/src/component/DeleteMember.jsx
+++ b/src/component/DeleteMember.jsx
@@ -5,7 +5,7 @@ import { useParams } from 'react-router-dom';
import '../styles/deleteMember.css';
const DeleteMember = () => {
- const { members, teams } = useContext(TeamDataContext);
+ const { members, teams, setMembers } = useContext(TeamDataContext);
const [selectedMember, setSelectedMember] = useState('');
const [filteredMembers, setFilteredMembers] = useState([]);
const { code } = useParams();
@@ -48,9 +48,10 @@ const DeleteMember = () => {
});
if (response.ok) {
- const updatedMembers = filteredMembers.filter(member => member.id !== selectedMember);
+ const updatedMembers = filteredMembers.filter(member => member.id !== Number(selectedMember));
setFilteredMembers(updatedMembers);
alert('Member deleted successfully');
+ setMembers(updatedMembers)
} else {
alert('Failed to delete member. Please try again.');
}
diff --git a/src/pages/Team.jsx b/src/pages/Team.jsx
index e6492dc..d9f744a 100644
--- a/src/pages/Team.jsx
+++ b/src/pages/Team.jsx
@@ -27,9 +27,7 @@ return(
-
+
diff --git a/src/styles/deleteTimeoff.css b/src/styles/deleteTimeoff.css
new file mode 100644
index 0000000..52418cf
--- /dev/null
+++ b/src/styles/deleteTimeoff.css
@@ -0,0 +1,11 @@
+button {
+ width: 8em;
+ background-color: #e10808;
+ color: white;
+ border: none;
+ border-radius: 10px;
+ cursor: pointer;
+ font-family: 'Poppins';
+ padding: 6px;
+ margin: 1em;
+}
\ No newline at end of file
diff --git a/src/styles/team.css b/src/styles/team.css
index 929f6fb..c0c3d11 100644
--- a/src/styles/team.css
+++ b/src/styles/team.css
@@ -9,6 +9,7 @@
.container-section {
display: flex;
+ height: 69em;
}
.left-section {