Skip to content
This repository was archived by the owner on Mar 21, 2026. It is now read-only.

Commit ed7daa9

Browse files
committed
adds board delete
1 parent 3673e4e commit ed7daa9

11 files changed

Lines changed: 240 additions & 17 deletions

File tree

server/controllers/boardsController.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,36 @@ const boardsController = {
124124
});
125125
}
126126
},
127+
getBoardFromId: async (req: Request, res: Response, next: NextFunction) => {
128+
try {
129+
// obtain the user document
130+
const board = await Board.findOne({ _id: req.params.boardId });
131+
res.locals.board = board;
132+
return next();
133+
} catch (err) {
134+
// pass error through to global error handler
135+
return next({
136+
log: `boardssController.getBoardFromId ERROR: ${err}`,
137+
status: 500,
138+
message: { err: "Error getting board" },
139+
});
140+
}
141+
},
142+
deleteBoard: async (req: Request, _res: Response, next: NextFunction) => {
143+
try {
144+
await Board.findOneAndDelete({
145+
_id: req.params.boardId,
146+
});
147+
return next();
148+
} catch (err) {
149+
// pass error through to global error handler
150+
return next({
151+
log: `tasksController.deleteBoard ERROR: ${err}`,
152+
status: 500,
153+
message: { err: "Error deleting board" },
154+
});
155+
}
156+
},
127157
};
128158

129159
export default boardsController;

server/controllers/tasksController.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,28 @@ const tasksController = {
139139
});
140140
}
141141
},
142+
clearTask: async (_req: Request, res: Response, next: NextFunction) => {
143+
try {
144+
await Card.deleteMany({
145+
_id: {
146+
$in: [
147+
...res.locals.board.backlog,
148+
...res.locals.board.inProgress,
149+
...res.locals.board.inReview,
150+
...res.locals.board.completed,
151+
],
152+
},
153+
});
154+
return next();
155+
} catch (err) {
156+
// pass error through to global error handler
157+
return next({
158+
log: `tasksController.clearTask ERROR: ${err}`,
159+
status: 500,
160+
message: { err: "Error clearing Tasks" },
161+
});
162+
}
163+
},
142164
};
143165

144166
export default tasksController;

server/routes/boardsRouter.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,15 @@ router.post(
3636
}
3737
);
3838

39+
// route for deleting a task card
40+
router.delete(
41+
"/delete/:boardId",
42+
boardsController.getBoardFromId,
43+
tasksController.clearTask,
44+
boardsController.deleteBoard,
45+
(_req: Request, res: Response) => {
46+
return res.status(200).json();
47+
}
48+
);
49+
3950
export default router;

src/components/Column.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import EditTaskModal from "./EditTaskModal.tsx";
77
const Column = ({
88
name,
99
create,
10-
user,
1110
currentBoard,
1211
boardState,
1312
setBoardState,
@@ -37,12 +36,7 @@ const Column = ({
3736
// map column to an array of task card components and then set as the state
3837
const cardsArray = column.map((task: TaskState) => {
3938
return (
40-
<Card
41-
info={task}
42-
editingTask={editingTask}
43-
setEditingTask={setEditingTask}
44-
key={task._id}
45-
/>
39+
<Card info={task} setEditingTask={setEditingTask} key={task._id} />
4640
);
4741
});
4842
setTaskCards(cardsArray);

src/components/CreateBoardModal.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const CreateBoardModal = ({
1111
setBoardList,
1212
handleBoardSelect,
1313
selectedBoard,
14+
setSelectedBoard,
1415
}: CreateBoardModalProps) => {
1516
const [boardName, setBoardName] = useState<string>("");
1617

@@ -53,6 +54,7 @@ const CreateBoardModal = ({
5354
);
5455
setBoardList([...boardList, newBoardListItem]);
5556
setCurrentBoard({ name: responseData.name, id: responseData._id });
57+
setSelectedBoard(responseData._id);
5658
setCreatingBoard(false);
5759
} else {
5860
console.log("Failed To create board.");

src/components/EditBoardModal.tsx

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { createPortal } from "react-dom";
2+
import { EditBoardModalProps } from "../types";
3+
import { useState } from "react";
4+
import "../scss/modal.scss";
5+
6+
const EditBoardModal = ({
7+
setEditingBoard,
8+
setCurrentBoard,
9+
currentBoard,
10+
}: EditBoardModalProps) => {
11+
const [boardName, setBoardName] = useState<string>(currentBoard.name);
12+
13+
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
14+
const inputValue: string = e.target.value;
15+
setBoardName(inputValue.trim()); //edge case for whitespace
16+
};
17+
18+
const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
19+
e.preventDefault();
20+
// send put request to /boards/edit with new boardName and id in body
21+
const body = {
22+
boardName: boardName,
23+
id: currentBoard.id,
24+
};
25+
const response: Response = await fetch("/boards/edit", {
26+
method: "PUT",
27+
headers: {
28+
"Content-type": "application/json; charset=UTF-8",
29+
},
30+
body: JSON.stringify(body),
31+
});
32+
// if request success, update currentBoard
33+
if (response.status === 200) {
34+
const responseData = await response.json();
35+
setCurrentBoard({ name: responseData.name, id: responseData._id });
36+
setEditingBoard(false);
37+
} else {
38+
console.log("Failed to edit board.");
39+
}
40+
};
41+
42+
const handleDeleteBoard = () => {
43+
const fetchDeleteBoard = async () => {
44+
const response: Response = await fetch(
45+
`/boards/delete/${currentBoard.id}`,
46+
{
47+
method: "DELETE",
48+
}
49+
);
50+
if (response.status === 200) {
51+
setCurrentBoard({
52+
name: "",
53+
id: "",
54+
});
55+
setEditingBoard(false);
56+
}
57+
};
58+
fetchDeleteBoard().catch(console.error);
59+
};
60+
61+
const isButtonDisabled: boolean = boardName === ""; //checking if boardName is empty? using trim in handle input
62+
63+
return createPortal(
64+
<div className="modal-overlay">
65+
<div className="modal">
66+
<form className="modal-form" onSubmit={handleFormSubmit}>
67+
<h2 className="modal-title">Edit Board</h2>
68+
<input
69+
className="modal-input"
70+
name="boardname"
71+
type="text"
72+
value={boardName}
73+
onChange={handleInputChange}
74+
required
75+
/>
76+
<div className="modal-btns">
77+
<button
78+
className="modal-submit"
79+
type="submit"
80+
disabled={isButtonDisabled}
81+
>
82+
Save
83+
</button>
84+
<button
85+
className="modal-cancel"
86+
onClick={() => {
87+
setEditingBoard(false);
88+
}}
89+
>
90+
Cancel
91+
</button>
92+
<button className="modal-delete" onClick={handleDeleteBoard}>
93+
Delete
94+
</button>
95+
</div>
96+
</form>
97+
</div>
98+
</div>,
99+
document.getElementById("portal") as Element
100+
);
101+
};
102+
103+
export default EditBoardModal;

src/containers/LeftContainer.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import { ReactNode, useEffect, useState } from "react";
33
import CreateBoardModal from "../components/CreateBoardModal";
44
import "../scss/leftContainer.scss";
55

6-
const LeftContainer = ({ user, setCurrentBoard }: LeftContainerProps) => {
6+
const LeftContainer = ({
7+
user,
8+
setCurrentBoard,
9+
currentBoard,
10+
}: LeftContainerProps) => {
711
// creating state to open board creating modal
812
const [creatingBoard, setCreatingBoard] = useState<boolean>(false);
913
// creating state to store the list of board names
@@ -32,7 +36,7 @@ const LeftContainer = ({ user, setCurrentBoard }: LeftContainerProps) => {
3236
};
3337
fetchBoardList().catch(console.error);
3438
// iterate through board names push buttons or components into array boardlist in state
35-
}, []);
39+
}, [currentBoard]);
3640

3741
// function for changing board when click selection button
3842
const handleBoardSelect = (e: React.MouseEvent<HTMLButtonElement>) => {
@@ -69,6 +73,7 @@ const LeftContainer = ({ user, setCurrentBoard }: LeftContainerProps) => {
6973
setBoardList={setBoardList}
7074
handleBoardSelect={handleBoardSelect}
7175
selectedBoard={selectedBoard}
76+
setSelectedBoard={setSelectedBoard}
7277
/>
7378
) : null}
7479
<footer>

src/containers/MainContainer.tsx

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@ import { useState, useEffect } from "react";
22
import "../scss/mainContainer.scss";
33
import { BoardState, MainContainerProps } from "../types";
44
import ColumnContainer from "./ColumnContainer.tsx";
5+
import editSvg from "../assets/edit-cover-1481-svgrepo-com.svg";
6+
import EditBoardModal from "../components/EditBoardModal.tsx";
57

6-
const MainContainer = ({ user, currentBoard }: MainContainerProps) => {
8+
const MainContainer = ({
9+
user,
10+
currentBoard,
11+
setCurrentBoard,
12+
}: MainContainerProps) => {
713
// set the board state as empty arrays, will be populated with card ids after fetch
814
const [boardState, setBoardState] = useState<BoardState>({
915
backlog: [],
@@ -12,6 +18,8 @@ const MainContainer = ({ user, currentBoard }: MainContainerProps) => {
1218
completed: [],
1319
});
1420

21+
const [editingBoard, setEditingBoard] = useState<boolean>(false);
22+
1523
// effect for fetching the current board info whenever currentBoard changes
1624
useEffect(() => {
1725
const fetchBoard = async () => {
@@ -48,13 +56,28 @@ const MainContainer = ({ user, currentBoard }: MainContainerProps) => {
4856

4957
return (
5058
<div className="main-container">
51-
<h1 className="board-title">{currentBoard.name}</h1>
59+
<div className="main-header">
60+
<h1 className="board-title">{currentBoard.name}</h1>
61+
<button
62+
className="edit-board-btn"
63+
onClick={() => setEditingBoard(true)}
64+
>
65+
<img src={editSvg} alt="Edit SVG" className="edit-svg" />
66+
</button>
67+
</div>
5268
<ColumnContainer
5369
user={user}
5470
currentBoard={currentBoard}
5571
boardState={boardState}
5672
setBoardState={setBoardState}
5773
/>
74+
{editingBoard ? (
75+
<EditBoardModal
76+
setEditingBoard={setEditingBoard}
77+
setCurrentBoard={setCurrentBoard}
78+
currentBoard={currentBoard}
79+
/>
80+
) : null}
5881
</div>
5982
);
6083
};

src/routes/Dashboard.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,16 @@ const Dashboard = ({ user }: DashboardProps) => {
1313
//state confirmDelete false
1414
return (
1515
<div className="main-page">
16-
<LeftContainer user={user} setCurrentBoard={setCurrentBoard} />
17-
<MainContainer user={user} currentBoard={currentBoard} />
16+
<LeftContainer
17+
user={user}
18+
setCurrentBoard={setCurrentBoard}
19+
currentBoard={currentBoard}
20+
/>
21+
<MainContainer
22+
user={user}
23+
setCurrentBoard={setCurrentBoard}
24+
currentBoard={currentBoard}
25+
/>
1826
</div>
1927
);
2028
};

src/scss/mainContainer.scss

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,25 @@
55
text-align: center;
66
height: 100%;
77

8-
.board-title {
9-
height: 5%;
10-
margin: 0;
11-
margin-top: 10px;
8+
.main-header {
9+
display: flex;
10+
align-items: center;
11+
justify-content: space-between;
12+
margin: 10px;
13+
14+
.edit-board-btn {
15+
padding: 5;
16+
height: fit-content;
17+
18+
.edit-svg {
19+
width: 20px;
20+
height: auto;
21+
margin: 0;
22+
}
23+
}
24+
25+
.board-title {
26+
margin: 0 auto;
27+
}
1228
}
1329
}

0 commit comments

Comments
 (0)