Skip to content

Commit

Permalink
Todo Task listing UI (#8)
Browse files Browse the repository at this point in the history
* feat: Task listing UI with mock data

* feat: components for tasks listing

* removed prev test folder
  • Loading branch information
VaibhavSingh8 authored Dec 27, 2024
1 parent 73286bd commit b3a50e3
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 8 deletions.
36 changes: 36 additions & 0 deletions app/tasks/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use client";
import { useEffect, useState } from "react";
import { TaskHeader } from "@/components/TaskHeader";
import { TaskList } from "@/components/TaskList";
import tasksData from "@/data/taskData.json";
import { Task } from "@/app/types/tasks";

const Tasks = () => {
const [tasks, setTasks] = useState<Task[]>([]);

useEffect(() => {
setTasks(tasksData);
}, []);

const todoTasks = tasks.filter((task) => task.status === "todo");
const inProgressTasks = tasks.filter((task) => task.status === "in-progress");

return (
<div
data-testid="tasks-container"
className="md:w-5/6 lg:w-3/4 flex flex-col mx-auto"
>
<section data-testid="todo-section">
<TaskHeader title="To Do" />
<TaskList tasks={todoTasks} />
</section>

<section data-testid="in-progress-section">
<TaskHeader title="In Progress" icon="/assets/InProgressEllipse.svg" />
<TaskList tasks={inProgressTasks} />
</section>
</div>
);
};

export default Tasks;
8 changes: 0 additions & 8 deletions app/test/home.test.tsx

This file was deleted.

8 changes: 8 additions & 0 deletions app/types/task.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type Task = {
id: number;
title: string;
assignee: string;
dueDate: string;
status: string;
profile?: string;
};
66 changes: 66 additions & 0 deletions components/TaskCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Task } from "@/app/types/tasks";
import { DateFormats, DateUtil } from "@/utils/dateUtil";
import Image from "next/image";

interface TaskCardProps {
task: Task;
className?: string;
}

const getStatusImagePath = (status: string): string => {
switch (status.toLowerCase()) {
case "in-progress":
return "/assets/InProgressEllipse.svg";
case "todo":
default:
return "/assets/ToDoEllipse.svg";
}
};

export const TaskCard = ({ task, className }: TaskCardProps) => {
const statusImagePath = getStatusImagePath(task.status);

const formattedDueDate = new DateUtil(task.dueDate).format(
DateFormats.D_MMM_YYYY
);

return (
<div
className={`flex justify-between items-center px-6 py-3 mt-1 mx-4 border border-[#D0D5DD] rounded-lg ${className}`}
data-testid={`task-${task.id}`}
>
<div className="flex items-center justify-between">
<h3 className="text-sm sm:text-base font-medium text-[#74777B] mr-2">
#{task.id}
</h3>
<Image
src={statusImagePath}
alt="task-status-icon"
width={20}
height={20}
/>
<h2 className="text-sm sm:text-base ml-2 font-medium">{task.title}</h2>
</div>

<div className="flex items-center space-x-6">
<div className="flex text-[#74787E] items-center justify-center space-x-2">
<div className="hidden md:flex px-2 py-[2px] rounded-full border border-[#4541C6] bg-[#F5F5FF] text-xs">
{task.assignee}
</div>
<div className="px-2 py-[2px] rounded-full border border-[#4541C6] bg-[#F5F5FF] text-xs">
{formattedDueDate}
</div>
</div>

<div className="md:hidden">
<Image
src={task.profile || "/assets/user.png"}
alt="assignee-profile"
width={20}
height={20}
/>
</div>
</div>
</div>
);
};
38 changes: 38 additions & 0 deletions components/TaskHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Image from "next/image";

interface TaskSectionProps {
className?: string;
icon?: string;
title: string;
onCreateTask?: () => void;
}

export const TaskHeader = ({
className,
icon,
title,
onCreateTask,
}: TaskSectionProps) => {
return (
<div
data-testid={`header-${title.toLowerCase().replace(" ", "-")}`}
className={`flex justify-between items-center px-6 py-3 bg-[#F5F5FF] mt-6 mb-2 mx-4 rounded-lg ${className}`}
>
<div className="flex items-center">
<Image
src={icon || "/assets/ToDoEllipse.svg"}
alt="header-icon"
width={20}
height={20}
/>
<h2 className="text-[#4541C6] text-base sm:text-lg ml-2 font-medium">
{title}
</h2>
</div>

<button onClick={onCreateTask}>
<Image src="/assets/plus.svg" alt="plusIcon" width={20} height={20} />
</button>
</div>
);
};
30 changes: 30 additions & 0 deletions components/TaskList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Task } from "@/app/types/tasks";
import { TaskCard } from "./TaskCard";

interface TaskListProps {
tasks: Task[];
}

export const TaskList = ({ tasks }: TaskListProps) => {
if (tasks.length === 0) {
return (
<div
className="text-gray-500 text-center py-8"
data-testid="empty-task-list"
>
No tasks available in this section
</div>
);
}
return (
<div data-testid={`task-list`}>
{tasks.map((task) => (
<TaskCard
key={task.id}
task={task}
className="transition-transform hover:scale-[1.01]"
/>
))}
</div>
);
};
34 changes: 34 additions & 0 deletions data/taskData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"id": 1,
"title": "Todo Listing",
"assignee": "Vaibhav Singh",
"dueDate": "2023-12-15",
"status": "todo",
"profile": "/assets/user.png"
},
{
"id": 2,
"title": "Prepare Design Doc",
"assignee": "Random 1",
"dueDate": "2023-12-10",
"status": "todo",
"profile": "/assets/user.png"
},
{
"id": 3,
"title": "Code Todo Frontend",
"assignee": "Random 2",
"dueDate": "2023-12-10",
"status": "in-progress",
"profile": "/assets/user.png"
},
{
"id": 4,
"title": "Code Todo Backend",
"assignee": "Random 3",
"dueDate": "2023-12-10",
"status": "in-progress",
"profile": "/assets/user.png"
}
]
4 changes: 4 additions & 0 deletions public/assets/InProgressEllipse.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/assets/ToDoEllipse.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/assets/plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/user.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b3a50e3

Please sign in to comment.