Skip to content

Commit

Permalink
it seems finisheddddd
Browse files Browse the repository at this point in the history
  • Loading branch information
sasanqc committed Jun 24, 2023
1 parent 32b5968 commit a1db379
Show file tree
Hide file tree
Showing 16 changed files with 420 additions and 63 deletions.
11 changes: 8 additions & 3 deletions components/BoardsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ const BoardsList: React.FC<BoardListProps> = ({ boards }) => {
{boards.map((board, i) => (
<li
key={i}
className={`flex pl-8 py-4 gap-x-4 mr-6 items-center rounded-r-full cursor-pointer ${
activeBoard === i ? "bg-primary2 text-white" : "text-gray3"
className={`flex pl-8 py-4 gap-x-4 mr-6 items-center rounded-r-full cursor-pointer animate-opacity ${
activeBoard === i
? "bg-primary2 text-white animate-opacityAnimate"
: "text-gray3"
}`}
onClick={() => dispatch(setActiveBoard(i))}
onClick={() => {
dispatch(setActiveBoard(i));
dispatch(setActiveModal(undefined));
}}
>
<span>
<BoardIcon />
Expand Down
6 changes: 4 additions & 2 deletions components/MobileBoards.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { useBoard } from "@/hooks/useBoard";
import BoardsList from "./BoardsList";
import ToggleTheme from "./ToggleTheme";

const MobileBoards = () => {
const boards = useBoard({ boards: [] });
return (
<div className="bg-white rounded-md pt-2 mx-7">
{/* <BoardsList /> */}
<div className="bg-white dark:bg-black1 rounded-md pt-2 mx-7">
<BoardsList boards={boards} />
<div className="p-4">
<ToggleTheme />
</div>
Expand Down
76 changes: 57 additions & 19 deletions components/TaskColumn.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,77 @@
import Task from "@/model/Task";
import { Draggable, Droppable } from "react-beautiful-dnd";

interface TaskColumnProps {
col: { name: string; tasks: Task[] };
onClickedTask: (index: number) => void;
id: string;
}
const TaskColumn: React.FC<TaskColumnProps> = ({ col, onClickedTask }) => {

const colColors = [
"bg-[#49C4E5]",
"bg-[#8471F2]",
"bg-[#f3e849]",
"bg-[#67E2AE]",
"bg-[#ee9b57]",
"bg-[#cbabe9]",
];
const TaskColumn: React.FC<TaskColumnProps> = ({ col, onClickedTask, id }) => {
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">
<div className="w-4 h-4 bg-primary2 rounded-full inline-block mr-3"></div>
<div
className={`w-4 h-4 ${
colColors?.[parseInt(id)] ||
colColors?.[parseInt(id) - colColors.length]
} rounded-full inline-block mr-3`}
></div>
<h4 className="text-gray3">
{col.name} ({col.tasks.length})
</h4>
</div>
<ul className="space-y-5 pb-6 ">
{col.tasks.map((task, index) => (
<li key={index}>
<section
className="py-6 px-4 bg-white dark:bg-black2 rounded-lg shadow-task cursor-pointer"
onClick={(e) => onClickedTask(index)}
>
<h3 className="mb-2">{task.title}</h3>
<p className="text-sm text-gray3 font-bold ">
{`${doneSubtasksNumber(task)} of ${
task.subtasks.length
} subtasks`}
</p>
</section>
</li>
))}
</ul>
<Droppable droppableId={`${id}`}>
{(provided) => (
<ul
className="space-y-5 pb-6 "
ref={provided.innerRef}
{...provided.droppableProps}
>
{col.tasks.map((task, index) => (
<Draggable
draggableId={id + index.toString()}
index={index}
key={index}
>
{(provided, snapshot) => {
return (
<li
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<section
className="py-6 px-4 bg-white dark:bg-black2 rounded-lg shadow-task cursor-pointer"
onClick={(e) => onClickedTask(index)}
>
<h3 className="mb-2">{task.title}</h3>
<p className="text-sm text-gray3 font-bold ">
{`${doneSubtasksNumber(task)} of ${
task.subtasks.length
} subtasks`}
</p>
</section>
</li>
);
}}
</Draggable>
))}
</ul>
)}
</Droppable>
</div>
);
};
Expand Down
2 changes: 1 addition & 1 deletion components/UI/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const Dropdown: React.FC<DropdownProps> = ({ items }) => {
return (
<div className="relative z-30" ref={menuRef}>
<div
className="cursor-pointer p-2 hover:bg-black1 rounded-md transition"
className="cursor-pointer p-2 dark:hover:bg-black1 hover:bg-gray1 rounded-md transition"
onClick={() => setMenuIsOpen(true)}
>
<VerticalElipsisIcon />
Expand Down
9 changes: 5 additions & 4 deletions components/UI/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const Modal: React.FC<ModalProps> = ({

const backDropHandler = useCallback((e: MouseEvent) => {
if (!modalRef?.current?.contains(e.target as Node)) {
console.log("on Clicked Backdrop");
onClickBackdrop();
}
}, []);
Expand All @@ -29,10 +28,12 @@ const Modal: React.FC<ModalProps> = ({
}, [backDropHandler]);

return (
<div className=" w-screen h-screen absolute top-0 left-0 z-10 bg-[#00000080]">
<div className=" w-screen h-screen absolute top-0 left-0 z-10 bg-[#00000080] ">
<div
className={`w-full md:w-fit md:left-1/2 absolute md:-translate-x-1/2 px-4 ${
center ? "top-1/2 -translate-y-1/2" : "top-24"
className={`w-full md:w-[480px] md:left-1/2 absolute md:-translate-x-1/2 px-4 ${
center
? "top-1/2 -translate-y-1/2 animate-fadeIn"
: "top-24 animate-fadeInMobile"
}`}
ref={modalRef}
>
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":[]},{"name":"Doing","tasks":[]},{"name":"Done","tasks":[]}]},{"name":"Roadmap","columns":[{"name":"Now","tasks":[]},{"name":"Next","tasks":[]},{"name":"Later","tasks":[]}]},{"name":"fhdf","columns":[{"name":"fghfdh","tasks":[]}]},{"name":"fdsss","columns":[{"name":"sww2222 dsfsdf","tasks":[{"title":"this is not a simple task ","description":"test desc edited","status":"sww2222 dsfsdf","subtasks":[{"title":"sub t2","isCompleted":true},{"title":"give a name","isCompleted":true}]}]},{"name":"qwesdf fsdf","tasks":[]}]},{"name":"sf","columns":[{"name":"wew","tasks":[]},{"name":"wew","tasks":[]}]},{"name":"safir","columns":[{"name":"col1","tasks":[]},{"name":"col2","tasks":[]},{"name":"sdfsf","tasks":[]},{"name":"sdfsdfsf","tasks":[]},{"name":"sdfsfsf","tasks":[]},{"name":"sfsdfsdfsfsfsf","tasks":[]}]}]}
{"boards":[{"name":"Platform Launch","columns":[{"name":"Todo","tasks":[{"title":"Build UI for onboarding flow","description":"","status":"Todo","subtasks":[{"title":"Sign up page","isCompleted":true},{"title":"Sign in page","isCompleted":false},{"title":"Welcome page","isCompleted":false}]},{"title":"Add account management endpoints","description":"","status":"Doing","subtasks":[{"title":"Upgrade plan","isCompleted":true},{"title":"Cancel plan","isCompleted":true},{"title":"Update payment method","isCompleted":false}]},{"title":"Build UI for search","description":"","status":"Todo","subtasks":[{"title":"Search page","isCompleted":false}]},{"title":"QA and test all major user journeys","description":"Once we feel version one is ready, we need to rigorously test it both internally and externally to identify any major gaps.","status":"Todo","subtasks":[{"title":"Internal testing","isCompleted":false},{"title":"External testing","isCompleted":false}]},{"title":"Create paper prototypes and conduct 10 usability tests with potential customers","description":"","status":"Todo","subtasks":[{"title":"Create paper prototypes for version one","isCompleted":false},{"title":"Complete 10 usability tests","isCompleted":false}]}]},{"name":"Doingffff","tasks":[{"title":"Design settings and search pages","description":"","status":"Doing","subtasks":[{"title":"Settings - Account page","isCompleted":true},{"title":"Settings - Billing page","isCompleted":true},{"title":"Search page","isCompleted":false}]},{"title":"Review results of usability tests and iterate","description":"Keep iterating through the subtasks until we're clear on the core concepts for the app.","status":"Done","subtasks":[{"title":"Meet to review notes from previous tests and plan changes","isCompleted":true},{"title":"Make changes to paper prototypes","isCompleted":true},{"title":"Conduct 5 usability tests","isCompleted":true}]},{"title":"Build settings UI","description":"","status":"Todo","subtasks":[{"title":"Account page","isCompleted":false},{"title":"Billing page","isCompleted":false}]},{"title":"Design onboarding flow","description":"","status":"Doing","subtasks":[{"title":"Sign up page","isCompleted":true},{"title":"Sign in page","isCompleted":false},{"title":"Welcome page","isCompleted":false}]},{"title":"Create wireframe prototype","description":"Create a greyscale clickable wireframe prototype to test our asssumptions so far.","status":"Done","subtasks":[{"title":"Create clickable wireframe prototype in Balsamiq","isCompleted":true}]},{"title":"Research the market","description":"We need to get a solid overview of the market to ensure we have up-to-date estimates of market size and demand.","status":"Done","subtasks":[{"title":"Write up research analysis","isCompleted":true},{"title":"Calculate TAM","isCompleted":true}]},{"title":"Add search enpoints","description":"","status":"Doing","subtasks":[{"title":"Add search endpoint","isCompleted":true},{"title":"Define search filters","isCompleted":false}]},{"title":"Add authentication endpoints","description":"","status":"Doing","subtasks":[{"title":"Define user model","isCompleted":true},{"title":"Add auth endpoints","isCompleted":false}]},{"title":"Research pricing points of various competitors and trial different business models","description":"We know what we're planning to build for version one. Now we need to finalise the first pricing model we'll use. Keep iterating the subtasks until we have a coherent proposition.","status":"Doing","subtasks":[{"title":"Research competitor pricing and business models","isCompleted":true},{"title":"Outline a business model that works for our solution","isCompleted":false},{"title":"Talk to potential customers about our proposed solution and ask for fair price expectancy","isCompleted":false}]},{"title":"this is a new task","description":"dfsdfadaf","status":"Doing","subtasks":[{"title":"subtask 1","isCompleted":true},{"title":"subtask 2","isCompleted":true}]}]}]},{"name":"Marketing Planet","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":"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":"a test board","columns":[{"name":"col 1","tasks":[]},{"name":"col 2","tasks":[]}]},{"name":"second test board","columns":[{"name":"col 1 test","tasks":[{"title":"first task for this app","description":"this is a des","status":"col 2 test","subtasks":[{"title":"sub t1","isCompleted":false},{"title":"subt 2","isCompleted":false}]}]},{"name":"col 2 test","tasks":[]}]}]}
38 changes: 29 additions & 9 deletions layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useDispatch, useSelector } from "react-redux";
import Button from "../components/UI/Button";
import VerticalElipsisIcon from "@/icons/icon-vertical-ellipsis.svg";
import LogoDarkIcon from "@/icons/logo-dark.svg";
import LogoLightIcon from "@/icons/logo-light.svg";
import LogoMobileIcon from "@/icons/logo-mobile.svg";
Expand All @@ -12,7 +11,7 @@ import ModalEnum from "@/model/ModalEnum";
import { useQuery } from "@tanstack/react-query";
import Board from "@/model/Board";
const Header = () => {
const dipsatch = useDispatch();
const dispatch = useDispatch();
const { data } = useQuery<{ boards: Board[] }>({ queryKey: ["boards"] });
const activeBoard = useSelector(selectBoard);

Expand All @@ -31,19 +30,19 @@ const Header = () => {
label="+ Add New Task"
type="primary large"
disabled={data?.boards?.[activeBoard]?.columns.length === 0}
onClick={() => dipsatch(setActiveModal(ModalEnum.CREATE_TASK))}
onClick={() => dispatch(setActiveModal(ModalEnum.CREATE_TASK))}
/>
<Dropdown
items={[
{
label: "Edit Board",
onClick: () => dipsatch(setActiveModal(ModalEnum.EDIT_BOARD)),
onClick: () => dispatch(setActiveModal(ModalEnum.EDIT_BOARD)),
className: "text-gray3",
},
{
label: "Delete Board",
onClick: () =>
dipsatch(setActiveModal(ModalEnum.DELETE_BOARD)),
dispatch(setActiveModal(ModalEnum.DELETE_BOARD)),
className: "text-destructive2",
},
]}
Expand All @@ -53,18 +52,39 @@ const Header = () => {
</div>
{/* Mobile Header */}
<div className="sm:hidden items-center justify-between w-full flex px-4 py-5">
<div className="flex">
<div
className="flex"
onClick={() => dispatch(setActiveModal(ModalEnum.MOBILE_MENU))}
>
<LogoMobileIcon className="mr-4" />
<div className="flex items-center gap-x-2">
<h2 className="">Platform Launch</h2>
<h2 className="">{data?.boards?.[activeBoard]?.name}</h2>
<ChevronDownIcon />
</div>
</div>
<div className="flex items-center gap-x-4">
<button className="bg-primary2 py-4 px-6 rounded-full">
<button
className="bg-primary2 py-4 px-6 rounded-full"
onClick={() => {
dispatch(setActiveModal(ModalEnum.CREATE_TASK));
}}
>
<AddIcon />
</button>
<VerticalElipsisIcon className="mr-2 cursor-pointer" />
<Dropdown
items={[
{
label: "Edit Board",
onClick: () => dispatch(setActiveModal(ModalEnum.EDIT_BOARD)),
className: "text-gray3",
},
{
label: "Delete Board",
onClick: () => dispatch(setActiveModal(ModalEnum.DELETE_BOARD)),
className: "text-destructive2",
},
]}
/>
</div>
</div>
</div>
Expand Down
20 changes: 18 additions & 2 deletions layout/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,35 @@ import BoardsList from "@/components/BoardsList";
import ToggleTheme from "@/components/ToggleTheme";
import { useBoard } from "@/hooks/useBoard";
import HideIcon from "@/icons/icon-hide.svg";

import ShowIcon from "@/icons/icon-show-sidebar.svg";
import { useDispatch } from "react-redux";
import { selectSidebar, toggleSidebar } from "@/store/uiSlice";
import { useSelector } from "react-redux";
const Sidebar = () => {
const boards = useBoard({ boards: [] });
const dispatch = useDispatch();
const sidebarIsOpen = useSelector(selectSidebar);
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} />
<div className="absolute bottom-12 w-full px-4 space-y-4">
<ToggleTheme />
<div className=" text-gray3 flex items-center gap-x-4 mx-auto cursor-pointer">
<div
className=" text-gray3 flex items-center gap-x-4 mx-auto cursor-pointer"
onClick={() => dispatch(toggleSidebar())}
>
<HideIcon />
<h3 className="">Hide Sidebar</h3>
</div>
</div>
{!sidebarIsOpen && (
<div
className="fixed bottom-9 bg-primary2 px-5 py-4 rounded-r-full cursor-pointer hover:bg-primary1 transition left-0"
onClick={() => dispatch(toggleSidebar())}
>
<ShowIcon />
</div>
)}
</div>
);
};
Expand Down
35 changes: 20 additions & 15 deletions layout/Tasks.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { DragDropContext, DropResult } from "react-beautiful-dnd";
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";

const Tasks: React.FC<{ board: Board }> = () => {
const Tasks: React.FC<{
onDragEnd: (result: DropResult) => void;
}> = ({ onDragEnd }) => {
const dispatch = useDispatch();
const activeBoard = useSelector(selectBoard);
const board = useBoard({ boards: [] })?.[activeBoard];
Expand All @@ -19,22 +20,26 @@ const Tasks: React.FC<{ board: Board }> = () => {

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: { name: string; tasks: Task[] }, index: number) => (
<TaskColumn
col={col}
key={index}
onClickedTask={(taskIndex: number) =>
onClickedTask(index, taskIndex)
}
/>
)
)}
<DragDropContext onDragEnd={onDragEnd}>
{board?.columns?.map(
(col: { name: string; tasks: Task[] }, index: number) => (
<TaskColumn
col={col}
id={index.toString()}
key={index}
onClickedTask={(taskIndex: number) =>
onClickedTask(index, taskIndex)
}
/>
)
)}
</DragDropContext>

{board?.columns?.length > 0 && (
<div className="bg-gray1 dark:bg-black2 text-center mt-10 flex rounded-md">
<h1
onClick={() => dispatch(setActiveModal(ModalEnum.EDIT_BOARD))}
className="text-gray3 w-[280px] my-auto cursor-pointer hover:text-gray1 transition-colors"
className="text-gray3 w-[280px] my-auto cursor-pointer hover:text-gray2 transition-colors"
>
+ New Column
</h1>
Expand Down
1 change: 1 addition & 0 deletions model/ModalEnum.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ enum ModalEnum {
DELETE_BOARD = "DELETE_BOARD",
DELETE_TASK = "DELETE_TASK",
VIEW_TASK = "VIEW_TASK",
MOBILE_MENU = "MOBILE_MENU",
}
export default ModalEnum;
Loading

0 comments on commit a1db379

Please sign in to comment.