Skip to content

Commit

Permalink
react query
Browse files Browse the repository at this point in the history
  • Loading branch information
sasanqc committed Jun 22, 2023
1 parent 7237f4f commit 8db58d6
Show file tree
Hide file tree
Showing 12 changed files with 275 additions and 255 deletions.
1 change: 1 addition & 0 deletions components/TaskColumn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const TaskColumn: React.FC<TaskColumnProps> = ({ col, onClickedTask }) => {
const doneSubtasksNumber = (task: Task) => {
return task.subtasks.filter((el) => el.isCompleted).length;
};

return (
<div className="w-[280px] shrink-0 h-full">
<div className="flex mb-6">
Expand Down
11 changes: 7 additions & 4 deletions components/UI/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ const Dropdown: React.FC<DropdownProps> = ({ items }) => {
}, []);
return (
<div className="relative z-30" ref={menuRef}>
<VerticalElipsisIcon
className="cursor-pointer"
<div
className="cursor-pointer p-2 hover:bg-black1 rounded-md transition"
onClick={() => setMenuIsOpen(true)}
/>
>
<VerticalElipsisIcon />
</div>

{menuIsOpoen && (
<ul className="absolute text-base font-semibold bg-white dark:bg-black3 right-0 mt-8 w-48 p-4 rounded-md space-y-4">
<ul className="absolute text-base font-semibold bg-white dark:bg-black1 right-0 mt-4 w-48 p-4 rounded-md space-y-4">
{items.map((el, index) => {
return (
<li
Expand Down
2 changes: 1 addition & 1 deletion data/data.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"boards":[{"name":"Marketing Plan","columns":[{"name":"Todo","tasks":[{"title":"Plan Product Hunt launch","description":"","status":"Todo","subtasks":[{"title":"Find hunter","isCompleted":false},{"title":"Gather assets","isCompleted":false},{"title":"Draft product page","isCompleted":false},{"title":"Notify customers","isCompleted":false},{"title":"Notify network","isCompleted":false},{"title":"Launch!","isCompleted":false}]},{"title":"Share on Show HN","description":"","status":"","subtasks":[{"title":"Draft out HN post","isCompleted":false},{"title":"Get feedback and refine","isCompleted":false},{"title":"Publish post","isCompleted":false}]},{"title":"Write launch article to publish on multiple channels","description":"","status":"","subtasks":[{"title":"Write article","isCompleted":false},{"title":"Publish on LinkedIn","isCompleted":false},{"title":"Publish on Inndie Hackers","isCompleted":false},{"title":"Publish on Medium","isCompleted":false}]}]},{"name":"Doing","tasks":[]},{"name":"Done","tasks":[]}]},{"name":"Roadmap","columns":[{"name":"Now","tasks":[{"title":"Launch version one","description":"","status":"Now","subtasks":[{"title":"Launch privately to our waitlist","isCompleted":false},{"title":"Launch publicly on PH, HN, etc.","isCompleted":false}]},{"title":"Review early feedback and plan next steps for roadmap","description":"Beyond the initial launch, we're keeping the initial roadmap completely empty. This meeting will help us plan out our next steps based on actual customer feedback.","status":"Now","subtasks":[{"title":"Interview 10 customers","isCompleted":false},{"title":"Review common customer pain points and suggestions","isCompleted":false},{"title":"Outline next steps for our roadmap","isCompleted":false}]}]},{"name":"Next","tasks":[]},{"name":"Later","tasks":[]}]},{"name":"renamed board","columns":[{"name":"col 111","tasks":[]},{"name":"col 333","tasks":[]},{"name":"9999","tasks":[]}]}]}
{"boards":[{"name":"Marketing Plan","columns":[{"name":"Todo","tasks":[{"title":"Plan Product Hunt launch","description":"","status":"Todo","subtasks":[{"title":"Find hunter","isCompleted":true},{"title":"Gather assets","isCompleted":true},{"title":"Draft product page","isCompleted":false},{"title":"Notify customers","isCompleted":false},{"title":"Notify network","isCompleted":false},{"title":"Launch!","isCompleted":false}]},{"title":"Write launch article to publish on multiple channels","description":"","status":"","subtasks":[{"title":"Write article","isCompleted":false},{"title":"Publish on LinkedIn","isCompleted":false},{"title":"Publish on Inndie Hackers","isCompleted":false},{"title":"Publish on Medium","isCompleted":false}]}]},{"name":"Doing","tasks":[]},{"name":"Done","tasks":[{"title":"Share on Show HN","description":"","status":"Done","subtasks":[{"title":"Draft out HN post","isCompleted":true},{"title":"Get feedback and refine","isCompleted":true},{"title":"Publish post","isCompleted":true}]}]}]},{"name":"Roadmap","columns":[{"name":"Now","tasks":[{"title":"Launch version one","description":"","status":"Now","subtasks":[{"title":"Launch privately to our waitlist","isCompleted":true},{"title":"Launch publicly on PH, HN, etc.","isCompleted":false}]},{"title":"Review early feedback and plan next steps for roadmap","description":"Beyond the initial launch, we're keeping the initial roadmap completely empty. This meeting will help us plan out our next steps based on actual customer feedback.","status":"Now","subtasks":[{"title":"Interview 10 customers","isCompleted":false},{"title":"Review common customer pain points and suggestions","isCompleted":false},{"title":"Outline next steps for our roadmap","isCompleted":false}]}]},{"name":"Next","tasks":[]},{"name":"Later","tasks":[]}]},{"name":"fhdf","columns":[{"name":"fghfdh","tasks":[]},{"name":"sfasf","tasks":[]},{"name":"uyui","tasks":[]},{"name":"sfsdfsdfsdfs","tasks":[]}]},{"name":"fdsss","columns":[{"name":"uiouoiouio","tasks":[{"title":"yyyyrt","description":"rtyry","status":"uiouoiouio","subtasks":[{"title":"rtyry","isCompleted":false},{"title":"fgdfg","isCompleted":false}]}]},{"name":"lll","tasks":[{"title":"weeeee","description":"eeeeeee","status":"lll","subtasks":[{"title":"wwwww","isCompleted":true},{"title":"yyyyy","isCompleted":true}]}]},{"name":"www","tasks":[]}]}]}
14 changes: 14 additions & 0 deletions hooks/useBoard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Board from "@/model/Board";
import { getBoards } from "@/services/apiBoards";
import { useQuery } from "@tanstack/react-query";

export const useBoard = (prefetchedData: { boards: Board[] }) => {
const {
data: { boards },
} = useQuery({
queryKey: ["boards"],
queryFn: getBoards,
initialData: prefetchedData,
});
return boards;
};
22 changes: 22 additions & 0 deletions hooks/useCreateBoard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Board from "@/model/Board";
import { createBoardApi } from "@/services/apiBoards";
import { setActiveBoard, setActiveModal } from "@/store/uiSlice";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useDispatch } from "react-redux";

export const useCreateBoard = () => {
const dispatch = useDispatch();
const queryClient = useQueryClient();
const { mutate: createBoard, isLoading: isCreating } = useMutation({
mutationFn: createBoardApi,
onSuccess: async () => {
await queryClient.invalidateQueries({
queryKey: ["boards"],
});
const data = queryClient.getQueryData(["boards"]);
dispatch(setActiveBoard((data as { boards: Board[] }).boards.length - 1));
dispatch(setActiveModal(undefined));
},
});
return { isCreating, createBoard };
};
19 changes: 19 additions & 0 deletions hooks/useDeleteBoard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { deleteBoardApi } from "@/services/apiBoards";
import { setActiveBoard, setActiveModal } from "@/store/uiSlice";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useDispatch } from "react-redux";

export const useDeleteBoard = () => {
const queryClient = useQueryClient();
const dispatch = useDispatch();
const { isLoading: isDeleting, mutate: deleteBoard } = useMutation({
mutationFn: (id: string) => deleteBoardApi(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["boards"] });
dispatch(setActiveModal(undefined));
dispatch(setActiveBoard(0));
},
onError: () => {},
});
return { isDeleting, deleteBoard };
};
19 changes: 19 additions & 0 deletions hooks/useUpdateBoard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Board from "@/model/Board";
import { updateBoardApi } from "@/services/apiBoards";
import { setActiveModal } from "@/store/uiSlice";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useDispatch } from "react-redux";

export const useUpdateBoard = () => {
const queryClient = useQueryClient();
const dispatch = useDispatch();
const { mutate: updateBoard, isLoading: isUpdating } = useMutation({
mutationFn: ({ id, board }: { id: string; board: Board }) =>
updateBoardApi(id, board),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["boards"] });
dispatch(setActiveModal(undefined));
},
});
return { isUpdating, updateBoard };
};
7 changes: 0 additions & 7 deletions layout/Modals.tsx

This file was deleted.

6 changes: 4 additions & 2 deletions layout/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import BoardsList from "@/components/BoardsList";
import ToggleTheme from "@/components/ToggleTheme";
import { useBoard } from "@/hooks/useBoard";
import HideIcon from "@/icons/icon-hide.svg";
import BoardListProps from "@/model/BoardListProps";

const Sidebar: React.FC<BoardListProps> = ({ boards }) => {
const Sidebar = () => {
const boards = useBoard({ boards: [] });
console.log("render sidebar");
return (
<div className="w-[260px] md:w-[300px] border-r border-r-gray1 dark:border-r-black1 relative hidden sm:inline-block">
<BoardsList boards={boards} />
Expand Down
45 changes: 26 additions & 19 deletions layout/Tasks.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
import TaskColumn from "@/components/TaskColumn";
import Button from "@/components/UI/Button";
import { useBoard } from "@/hooks/useBoard";
import Board from "@/model/Board";
import ModalEnum from "@/model/ModalEnum";
import Task from "@/model/Task";
import { selectBoard, setActiveModal, setOpenedTask } from "@/store/uiSlice";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";

interface TasksProps {
board: Board;
onCreateColumn: () => void;
onClickedTask: (colIndex: number, taskIndex: number) => void;
}
const Tasks: React.FC<{ board: Board }> = () => {
const dispatch = useDispatch();
const activeBoard = useSelector(selectBoard);
const board = useBoard({ boards: [] })?.[activeBoard];
const onClickedTask = (colIndex: number, taskIndex: number) => {
dispatch(setOpenedTask({ taskIndex, colIndex }));
};

const Tasks: React.FC<TasksProps> = ({
board,
onCreateColumn,
onClickedTask,
}) => {
return (
<div className="flex-1 h-full p-6 flex gap-6 overflow-auto flex-nowrap bg-white2 dark:bg-black3 border-t border-t-gray1 dark:border-t-black1">
{board?.columns?.map((col, index) => (
<TaskColumn
col={col}
key={index}
onClickedTask={(taskIndex: number) => onClickedTask(index, taskIndex)}
/>
))}
{board?.columns?.map(
(col: { name: string; tasks: Task[] }, index: number) => (
<TaskColumn
col={col}
key={index}
onClickedTask={(taskIndex: number) =>
onClickedTask(index, taskIndex)
}
/>
)
)}
{board?.columns?.length > 0 && (
<div className="bg-gray1 dark:bg-black2 text-center mt-10 flex rounded-md">
<h1
onClick={onCreateColumn}
onClick={() => dispatch(setActiveModal(ModalEnum.EDIT_BOARD))}
className="text-gray3 w-[280px] my-auto cursor-pointer hover:text-gray1 transition-colors"
>
+ New Column
Expand All @@ -41,7 +48,7 @@ const Tasks: React.FC<TasksProps> = ({
<Button
label="+ Add New Column"
type="primary large"
onClick={onCreateColumn}
onClick={() => dispatch(setActiveModal(ModalEnum.EDIT_BOARD))}
/>
</div>
))}
Expand Down
Loading

0 comments on commit 8db58d6

Please sign in to comment.