Skip to content

Commit ccdd3f3

Browse files
authored
Merge pull request #29 from d4vidsha/d4vidsha/task-creation
feat: create task list page in `/tasks`
2 parents caedf15 + b58beaa commit ccdd3f3

File tree

7 files changed

+90
-14
lines changed

7 files changed

+90
-14
lines changed

frontend/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Stage 0, "build-stage", based on Node.js, to build and compile the frontend
2-
FROM node:20 as build-stage
2+
FROM node:20 AS build-stage
33

44
WORKDIR /app
55

frontend/src/components/Common/Navbar.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import { Button, Flex, Icon, useDisclosure } from "@chakra-ui/react"
2+
import type { ComponentType, ElementType } from "react"
23
import { FaPlus } from "react-icons/fa"
34

4-
import AddUser from "../Admin/AddUser"
5-
import AddItem from "../Items/AddItem"
6-
75
interface NavbarProps {
86
type: string
7+
addModalAs: ComponentType | ElementType
98
}
109

11-
const Navbar = ({ type }: NavbarProps) => {
12-
const addUserModal = useDisclosure()
13-
const addItemModal = useDisclosure()
14-
10+
const Navbar = ({ type, addModalAs }: NavbarProps) => {
11+
const addModal = useDisclosure()
12+
const AddModal = addModalAs
1513
return (
1614
<>
1715
<Flex py={8} gap={4}>
@@ -26,12 +24,11 @@ const Navbar = ({ type }: NavbarProps) => {
2624
variant="primary"
2725
gap={1}
2826
fontSize={{ base: "sm", md: "inherit" }}
29-
onClick={type === "User" ? addUserModal.onOpen : addItemModal.onOpen}
27+
onClick={addModal.onOpen}
3028
>
3129
<Icon as={FaPlus} /> Add {type}
3230
</Button>
33-
<AddUser isOpen={addUserModal.isOpen} onClose={addUserModal.onClose} />
34-
<AddItem isOpen={addItemModal.isOpen} onClose={addItemModal.onClose} />
31+
<AddModal isOpen={addModal.isOpen} onClose={addModal.onClose} />
3532
</Flex>
3633
</>
3734
)

frontend/src/components/navbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import UserMenu from "./user-menu"
1515

1616
const navigation = [
1717
{ icon: Calendar, title: "Calendar", path: "/" },
18-
{ icon: CheckSquare2, title: "Tasks", path: "/items" },
18+
{ icon: CheckSquare2, title: "Tasks", path: "/tasks" },
1919
]
2020

2121
const NavBar = () => {

frontend/src/components/user-auth-form.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
6262
render={({ field }) => (
6363
<FormItem>
6464
<FormControl>
65-
<Input placeholder="Email" type="email" {...field} />
65+
<Input
66+
placeholder="Email"
67+
type="email"
68+
disabled={isLoading}
69+
{...field}
70+
/>
6671
</FormControl>
6772
<FormMessage />
6873
</FormItem>
@@ -78,6 +83,7 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
7883
<Input
7984
placeholder="Password"
8085
type={showPassword ? "text" : "password"}
86+
disabled={isLoading}
8187
{...field}
8288
/>
8389
<EyeToggle

frontend/src/components/user-menu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const UserMenu = () => {
4141
</Link>
4242
</DropdownMenuItem>
4343
<DropdownMenuItem asChild>
44-
<Link to="/admin">
44+
<Link to="/admin" search>
4545
<Users className="mr-2 h-4 w-4" />
4646
<span>User Management</span>
4747
</Link>

frontend/src/routeTree.gen.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { Route as RecoverPasswordImport } from './routes/recover-password'
1717
import { Route as LoginImport } from './routes/login'
1818
import { Route as LayoutImport } from './routes/_layout'
1919
import { Route as LayoutIndexImport } from './routes/_layout/index'
20+
import { Route as LayoutTasksImport } from './routes/_layout/tasks'
2021
import { Route as LayoutSettingsImport } from './routes/_layout/settings'
2122
import { Route as LayoutItemsImport } from './routes/_layout/items'
2223
import { Route as LayoutAdminImport } from './routes/_layout/admin'
@@ -53,6 +54,11 @@ const LayoutIndexRoute = LayoutIndexImport.update({
5354
getParentRoute: () => LayoutRoute,
5455
} as any)
5556

57+
const LayoutTasksRoute = LayoutTasksImport.update({
58+
path: '/tasks',
59+
getParentRoute: () => LayoutRoute,
60+
} as any)
61+
5662
const LayoutSettingsRoute = LayoutSettingsImport.update({
5763
path: '/settings',
5864
getParentRoute: () => LayoutRoute,
@@ -104,6 +110,10 @@ declare module '@tanstack/react-router' {
104110
preLoaderRoute: typeof LayoutSettingsImport
105111
parentRoute: typeof LayoutImport
106112
}
113+
'/_layout/tasks': {
114+
preLoaderRoute: typeof LayoutTasksImport
115+
parentRoute: typeof LayoutImport
116+
}
107117
'/_layout/': {
108118
preLoaderRoute: typeof LayoutIndexImport
109119
parentRoute: typeof LayoutImport
@@ -118,6 +128,7 @@ export const routeTree = rootRoute.addChildren([
118128
LayoutAdminRoute,
119129
LayoutItemsRoute,
120130
LayoutSettingsRoute,
131+
LayoutTasksRoute,
121132
LayoutIndexRoute,
122133
]),
123134
LoginRoute,
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { createFileRoute } from "@tanstack/react-router"
2+
import { motion } from "framer-motion"
3+
import { Check, Circle } from "lucide-react"
4+
import { useState } from "react"
5+
6+
export const Route = createFileRoute("/_layout/tasks")({
7+
component: Tasks,
8+
})
9+
10+
const tasks = [
11+
{ id: 1, title: "Study for 3 hours", completed: true },
12+
{ id: 2, title: "Create task list", completed: false },
13+
{ id: 3, title: "Clean bedroom", completed: false },
14+
{
15+
id: 4,
16+
title:
17+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
18+
completed: false,
19+
},
20+
]
21+
22+
function Tasks() {
23+
return (
24+
<div className="mx-20 my-10">
25+
<div className="flex justify-center">
26+
<div className="flex-col shrink w-[800px] min-w-56">
27+
<header className="mb-4">
28+
<h1 className="text-3xl font-bold">Inbox</h1>
29+
</header>
30+
<main className="flex flex-col">
31+
{tasks.map((task) => (
32+
<Task key={task.id} task={task} />
33+
))}
34+
</main>
35+
</div>
36+
</div>
37+
</div>
38+
)
39+
}
40+
41+
function Task({
42+
task,
43+
}: { task: { id: number; title: string; completed: boolean } }) {
44+
const [isCompleted, setIsCompleted] = useState(task.completed)
45+
return (
46+
<div className="flex gap-2 shrink-1 border-b py-3">
47+
<motion.button
48+
whileTap={{ scale: 1.2 }}
49+
onTap={() => setIsCompleted(!isCompleted)}
50+
className="flex-none self-start"
51+
>
52+
<div className="grid grid-cols-1 grid-rows-1">
53+
<Circle className="h-5 w-5 row-start-1 row-end-1 col-start-1 col-end-1" />
54+
<div className="flex justify-center items-center row-start-1 row-end-1 col-start-1 col-end-1">
55+
{isCompleted && <Check strokeWidth={4.5} className="h-3 w-3" />}
56+
</div>
57+
</div>
58+
</motion.button>
59+
<p className="text-sm line-clamp-4 text-ellipsis">{task.title}</p>
60+
</div>
61+
)
62+
}

0 commit comments

Comments
 (0)