Skip to content

Commit

Permalink
Merge pull request #12 from OS-Builders/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
johnlcos authored Feb 21, 2024
2 parents 24752c6 + fb11415 commit 3417275
Show file tree
Hide file tree
Showing 13 changed files with 28 additions and 75 deletions.
43 changes: 18 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Task Pro

Task Pro is an intuitive web application crafted to streamline project and task management.
Task Pro is an intuitive web application crafted to streamline project and task management.

It empowers users of all proficiency levels to enhance their time management and organizational abilities with its user-friendly interface.
It empowers users of all proficiency levels to enhance their time management and organizational abilities with its user-friendly interface.

Whether you opt for private usage or collaboration, Task Pro offers a comprehensive solution for creating, organizing, and sharing projects seamlessly.

Expand All @@ -11,47 +11,45 @@ Whether you opt for private usage or collaboration, Task Pro offers a comprehens
![React](https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) ![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) ![JavaScript](https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E) ![React Router](https://img.shields.io/badge/React_Router-CA4245?style=for-the-badge&logo=react-router&logoColor=white) ![SASS](https://img.shields.io/badge/SASS-hotpink.svg?style=for-the-badge&logo=SASS&logoColor=white) ![Vite](https://img.shields.io/badge/vite-%23646CFF.svg?style=for-the-badge&logo=vite&logoColor=white) ![MongoDB](https://img.shields.io/badge/MongoDB-%234ea94b.svg?style=for-the-badge&logo=mongodb&logoColor=white) ![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) ![Express.js](https://img.shields.io/badge/express.js-%23404d59.svg?style=for-the-badge&logo=express&logoColor=%2361DAFB)

## Project Frames
![Project Frame](src/assets/projectFrame.png)


![Project Frame](src/assets/projectFrame.png)

## Features

### User Sign-Up and Login

- Easily create a user profile to personalize user experience.
- Secure authentication ensures your private boards are only accessible to you.


![Authentication](src/assets/authPage.png)



### Board Management
- Create new board with ease.
- Organize your task for different stage for efficiently managing a project.

- Create, edit and delete boards with ease.
- Instantly swap between boards to display their corresponding tasks.
- All changes to boards and tasks are maintained on the frontend and backend.

![Dashboard](src/assets/Dashboard.png)

### Task Management

![taskCreation](src/assets/taskCreation.png)


- Create any number of new task cards with name, notes and status.
- Edit and delete task cards as needed.
- Move cards from one status column to another.

![taskCreation](src/assets/taskCreation.png)

## Front End
## Front End

- Developed using **React** for a responsive and dynamic user interface.
- Utilizes **React Router** for smooth navigation between pages.
- Stylish and customizable design with **SASS** for a modern look and organized styling.


## Back End

- Powered by **Node.js** and **Express** for robust server-side functionality.
- Data storage and retrieval are handled by **MongoDB**, ensuring data persistence and flexibility.


## Stretch Features

In the future, we plan to introduce the following features:
Expand All @@ -63,25 +61,20 @@ In the future, we plan to introduce the following features:
- Light and Dark mode.
- OTP/Email 2 step authentication.




## To Launch the Application

**Step 1**. Clone repo to code editor
**Step 1**. Clone repo to code editor

**Step 2**. Run npm install to install all dependencies
**Step 2**. Run npm install to install all dependencies

**Step 3**. Make sure node version is 18.17.1 or older, can use nvm to install the needed version.
**Step 3**. Make sure node version is 18.17.1 or older, can use nvm to install the needed version.

**Step 4**. Create env file and make sure to have ```PORT = 3000``` and ```MONGO_URI = (Mongodb connection URI)```

**Step 5**. start the project with ```npm start``` or ```npm run dev``` (for dev mode)
**Step 4**. Create env file and make sure to have `PORT = 3000` and `MONGO_URI = (Mongodb connection URI)`

**Step 5**. start the project with `npm start` or `npm run dev` (for dev mode)

## Authors

- Nam Ha: [Github](https://github.com/namos2502)

- John Costello: [Github](https://github.com/johnlcos)

4 changes: 1 addition & 3 deletions server/controllers/boardsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { BoardListItemState, BoardType } from "../../src/types.ts";
const boardsController = {
getMyBoards: async (req: Request, res: Response, next: NextFunction) => {
try {
// find all boards beloning to the user, push board names into an array and save on locals
// find all boards from the user, push board names into an array and save on locals
const user = await User.findOne({ _id: req.params.userId }).populate(
"boards"
);
Expand Down Expand Up @@ -144,7 +144,6 @@ const boardsController = {
await Board.findOneAndDelete({
_id: req.params.boardId,
});
console.log("board deleted");
return next();
} catch (err) {
// pass error through to global error handler
Expand All @@ -164,7 +163,6 @@ const boardsController = {
},
{ new: true }
);
console.log("editedBoard: ", editedBoard);
res.locals.board = editedBoard;
return next();
} catch (err) {
Expand Down
12 changes: 0 additions & 12 deletions server/controllers/userController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,9 @@ const userController = {

// middleware for verifying a user on login
verifyUser: async (req: Request, res: Response, next: NextFunction) => {
// obtain user name password from request body
// obtain user name password from request body
const { username, password } = req.body;
// check for a missing input
// check for a missing input
if (!username || !password) {
return next({
log: "Missing username or password in verifyUser",
Expand All @@ -54,23 +52,19 @@ const userController = {
});
}
try {
// search DB for the user based on the username
// search DB for the user based on the username
const user = await User.findOne({ username });
// if now user is found error out
// if now user is found error out
if (!user) {
return next({
log: `userController.verifyUser ERROR: no user with input username found in DB`,
status: 400,
message: { err: "Invalid username or password" },
});
} else {
// else a user is found, check passwords
// else a user is found, check passwords
const resultPassword = await bcrypt.compare(password, user.password);
// if passwords do not match error out
// if passwords do not match error out
if (!resultPassword) {
return next({
log: `userController.verifyUser ERROR: input password does not match stored password`,
Expand All @@ -89,12 +83,6 @@ const userController = {
status: 500,
message: { err: "Error occured creating user" },
});
// send any errors to global error handler
return next({
log: `usersController.createUser ERROR: ${err}`,
status: 500,
message: { err: "Error occured creating user" },
});
}
},
};
Expand Down
2 changes: 2 additions & 0 deletions server/routes/boardsRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ router.get(
}
);

// route for getting all tasks associated with a board
router.get(
"/board",
boardsController.getCurrentBoard,
Expand All @@ -27,6 +28,7 @@ router.get(
}
);

// route for creating a new baord
router.post(
"/create",
boardsController.createBoard,
Expand Down
Binary file modified src/assets/Dashboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/taskCreation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 0 additions & 10 deletions src/components/Column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,19 @@ const Column = ({
boardState,
setBoardState,
}: ColumnProps) => {
// state for rendering new task modal
const [addingTask, setAddingTask] = useState<boolean>(false);

// state for number of tasks in a column
const [numTasks, setNumTasks] = useState<number>(0);

// state for storing task card components
const [taskCards, setTaskCards] = useState<ReactNode[]>([]);

// state for editing a task card
const [editingTask, setEditingTask] = useState<TaskState | null>(null);

// render new task modal on button click
const handleNewTask = () => {
setAddingTask(true);
};

//effect for rendering cards
useEffect(() => {
const column = boardState[name];
console.log("Column column: ", column);
setNumTasks(column.length);
// map column to an array of task card components and then set as the state
const cardsArray = column.map((task: TaskState) => {
return (
<Card info={task} setEditingTask={setEditingTask} key={task._id} />
Expand Down
6 changes: 2 additions & 4 deletions src/components/CreateBoardModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@ const CreateBoardModal = ({
},
body: JSON.stringify(body),
});
// receive username and id from backend
// if request success, save username to state and route to dashboard
// receive board name and id from backend
if (response.status === 200) {
const responseData = await response.json();
console.log("Board created: ", responseData);
const newBoardListItem = (
<button
className={`board-selector ${
Expand All @@ -61,7 +59,7 @@ const CreateBoardModal = ({
}
};

const isButtonDisabled: boolean = boardName === ""; //checking if boardName is empty? using trim in handle input
const isButtonDisabled: boolean = boardName === "";

return createPortal(
<div className="modal-overlay">
Expand Down
4 changes: 2 additions & 2 deletions src/components/EditBoardModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const EditBoardModal = ({
},
body: JSON.stringify(body),
});
// if request success, update currentBoard
// receive board name and id from backend
if (response.status === 200) {
const responseData = await response.json();
setCurrentBoard({ name: responseData.name, id: responseData._id });
Expand Down Expand Up @@ -58,7 +58,7 @@ const EditBoardModal = ({
fetchDeleteBoard().catch(console.error);
};

const isButtonDisabled: boolean = boardName === ""; //checking if boardName is empty? using trim in handle input
const isButtonDisabled: boolean = boardName === "";

return createPortal(
<div className="modal-overlay">
Expand Down
2 changes: 1 addition & 1 deletion src/components/EditTaskModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const EditTaskModal = ({
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault;
console.log("Edit Task Form Submitted: ", formData);
// send POST request with the new task card, edited task and current board
// send POST request with the edited task, originla column and current board
const fetchEditTask = async () => {
const body = {
...formData,
Expand Down
10 changes: 2 additions & 8 deletions src/containers/LeftContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ const LeftContainer = ({
setCurrentBoard,
currentBoard,
}: LeftContainerProps) => {
// creating state to open board creating modal
const [creatingBoard, setCreatingBoard] = useState<boolean>(false);
// creating state to store the list of board names
const [boardList, setBoardList] = useState<ReactNode[]>([]);
//state for selected board
const [selectedBoard, setSelectedBoard] = useState<string | null>(null);
// make a request for all board naames, return an array containing strings of the board names

// make a request for all board names, return an array containing strings of the board names
useEffect(() => {
const fetchBoardList = async () => {
const reponse: Response = await fetch(`/boards/myboards/${user.id}`);
Expand All @@ -35,10 +33,8 @@ const LeftContainer = ({
setBoardList(boardSelectors);
};
fetchBoardList().catch(console.error);
// iterate through board names push buttons or components into array boardlist in state
}, [currentBoard]);

// function for changing board when click selection button
const handleBoardSelect = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
setCurrentBoard({
Expand All @@ -48,9 +44,7 @@ const LeftContainer = ({
setSelectedBoard(e.currentTarget.id);
};

// function for creating a new board
const handleCreateBoard = () => {
// create a pop up to create the new board
setCreatingBoard(true);
};

Expand Down
8 changes: 0 additions & 8 deletions src/containers/MainContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const MainContainer = ({
inReview: [],
completed: [],
});

const [editingBoard, setEditingBoard] = useState<boolean>(false);

// effect for fetching the current board info whenever currentBoard changes
Expand All @@ -29,8 +28,6 @@ const MainContainer = ({
`/boards/board?board=${currentBoard.id}&user=${user.id}`
);
const board = await reponse.json();
// update state with the fetched data
console.log("MainContainer board: ", board);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { boardOwner, name, _id, __v, ...columns } = board;
await setBoardState({ ...columns });
Expand All @@ -39,11 +36,6 @@ const MainContainer = ({
fetchBoard().catch(console.error);
}, [currentBoard]);

//
useEffect(() => {
console.log("MainContainer boardState:", boardState); // Log the updated state after it's set
}, [boardState]); // Log when the boardState changes

if (!currentBoard?.name) {
return (
<div className="main-container">
Expand Down
2 changes: 0 additions & 2 deletions src/routes/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import { useState } from "react";
import "../scss/dashBoard.scss";

const Dashboard = ({ user }: DashboardProps) => {
// state of current board selected
const [currentBoard, setCurrentBoard] = useState<CurrentBoardState>({
name: "",
id: "",
});
//state confirmDelete false
return (
<div className="main-page">
<LeftContainer
Expand Down

0 comments on commit 3417275

Please sign in to comment.