Skip to content

Commit

Permalink
feat: display tasks and projects
Browse files Browse the repository at this point in the history
  • Loading branch information
mfaux committed Oct 15, 2024
1 parent 0527c4c commit f4c2515
Show file tree
Hide file tree
Showing 15 changed files with 329 additions and 21 deletions.
5 changes: 4 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { ActionBar } from '@/components/ui/shell/action-bar';
import { HeaderBar } from '@/components/ui/shell/header-bar';
import { Main } from '@/components/ui/shell/main';
import { Shell } from '@/components/ui/shell/shell';
import { Toolbar } from '@/components/ui/toolbar';
Expand Down Expand Up @@ -28,7 +29,9 @@ export default function RootLayout({
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable}`}>
<Shell>
<Toolbar />
<HeaderBar>
<Toolbar />
</HeaderBar>
<ActionBar onNavigate={(path) => router.push(path)}></ActionBar>
<Main>{children}</Main>
</Shell>
Expand Down
49 changes: 49 additions & 0 deletions app/projects/_components/projects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use client';

import { Label } from '@/components/ui/label';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Project } from '@/db/types';
import { cn } from '@/lib/utils';
import { useState } from 'react';

type ProjectsProps = {
projects: Project[];
};

export default function Projects({ projects }: ProjectsProps) {
const [task, setTask] = useState({ selected: '' });
return (
<ScrollArea className="h-screen">
<Label>Projects</Label>

<div className="flex flex-col gap-4 p-4">
{projects.map((item) => (
<button
key={item.id}
className={cn(
'flex flex-col items-start gap-3 rounded-lg border p-3 text-left text-sm transition-all hover:bg-accent max-w-96 shadow-sm',
task.selected === item.id && 'bg-muted',
)}
onClick={() =>
setTask({
...task,
selected: item.id,
})
}
>
<div className="flex w-full flex-col gap-1">
<div className="flex items-center">
<div className="flex items-center gap-2">
<div className="font-semibold">{item.name}</div>
</div>
</div>
</div>
<div className="line-clamp-2 text-xs text-muted-foreground">
{item.description?.substring(0, 300)}
</div>
</button>
))}
</div>
</ScrollArea>
);
}
8 changes: 6 additions & 2 deletions app/projects/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export default function Projects() {
return <div>Projects</div>;
import { getAllProjects } from '@/db/queries';
import Projects from './_components/projects';

export default async function ProjectsPage() {
const projects = await getAllProjects('fox', 50, 0);
return <Projects projects={projects} />;
}
49 changes: 49 additions & 0 deletions app/tasks/_components/tasks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use client';

import { Label } from '@/components/ui/label';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Task } from '@/db/types';
import { cn } from '@/lib/utils';
import { useState } from 'react';

type TasksProps = {
tasks: Task[];
};

export default function Tasks({ tasks }: TasksProps) {
const [task, setTask] = useState({ selected: '' });
return (
<ScrollArea className="h-screen">
<Label>Tasks</Label>

<div className="flex flex-col gap-4 p-4">
{tasks.map((item) => (
<button
key={item.id}
className={cn(
'flex flex-col items-start gap-3 rounded-lg border p-3 text-left text-sm transition-all hover:bg-accent max-w-96 shadow-sm',
task.selected === item.id && 'bg-muted',
)}
onClick={() =>
setTask({
...task,
selected: item.id,
})
}
>
<div className="flex w-full flex-col gap-1">
<div className="flex items-center">
<div className="flex items-center gap-2">
<div className="font-semibold">{item.title}</div>
</div>
</div>
</div>
<div className="line-clamp-2 text-xs text-muted-foreground">
{item.description?.substring(0, 300)}
</div>
</button>
))}
</div>
</ScrollArea>
);
}
8 changes: 6 additions & 2 deletions app/tasks/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export default function Tasks() {
return <div>Tasks</div>;
import { getAllTasks } from '@/db/queries';
import Tasks from './_components/tasks';

export default async function TasksPage() {
const tasks = await getAllTasks('fox', 50, 0);
return <Tasks tasks={tasks} />;
}
48 changes: 48 additions & 0 deletions components/ui/scroll-area.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"use client"

import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"

import { cn } from "@/lib/utils"

const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
))
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName

const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({ className, orientation = "vertical", ...props }, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref}
orientation={orientation}
className={cn(
"flex touch-none select-none transition-colors",
orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
className
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
))
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName

export { ScrollArea, ScrollBar }
15 changes: 11 additions & 4 deletions components/ui/shell/action-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
'use client';
import { Button } from '@/components/ui/button';
import { Route } from '@/lib/routes';
import {
Expand Down Expand Up @@ -63,7 +62,9 @@ export const ActionBar = ({ onNavigate }: ActionBarProps) => {

return (
<div
className={'[grid-area:actionbar] w-max flex flex-col h-full bg-gray-200'}
className={
'[grid-area:actionbar] w-max flex flex-col h-full border-r shadow-md'
}
>
{buttons}
</div>
Expand Down Expand Up @@ -96,8 +97,14 @@ export const ActionBarButton = ({
onClick,
}: ActionBarButtonProps) => {
return (
<Button variant="ghost" size="icon" onClick={onClick} aria-label={label}>
<Icon className="h-5 w-5" />
<Button
variant="ghost"
size="default"
onClick={onClick}
aria-label={label}
className="h-12 w-12"
>
<Icon className="h-6 w-6" />
</Button>
);
};
4 changes: 3 additions & 1 deletion components/ui/shell/header-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ import type { PropsWithChildren } from 'react';
type HeaderBarProps = PropsWithChildren<{}>;

export const HeaderBar = ({ children }: HeaderBarProps) => {
return <div className="[grid-area:header] bg-yellow-200">{children}</div>;
return (
<div className="[grid-area:header] bg-gray-50 shadow-sm ">{children}</div>
);
};
4 changes: 1 addition & 3 deletions components/ui/shell/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,5 @@ import type { PropsWithChildren } from 'react';
type HeaderBarProps = PropsWithChildren<{}>;

export const Main = ({ children }: HeaderBarProps) => {
return (
<div className="[grid-area:main] grid place-content-center">{children}</div>
);
return <div className="[grid-area:main] grid p-4">{children}</div>;
};
2 changes: 1 addition & 1 deletion components/ui/toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const Toolbar = () => {
const [showNewTask, setShowNewTask] = useState(false);

return (
<div className="absolute left-1/2 transform -translate-x-1/2 top-3 flex flex-row items-center">
<div className="flex flex-row justify-center items-center">
<Button
variant={'outline'}
aria-label="New Task"
Expand Down
31 changes: 31 additions & 0 deletions db/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use server';

import { eq } from 'drizzle-orm';
import { db } from './drizzle';
import { projects, tasks } from './schema';

export const getAllTasks = async (
userId: string,
limit: number,
offset: number,
) => {
return await db
.select()
.from(tasks)
.limit(limit)
.offset(offset)
.where(eq(tasks.userId, userId));
};

export const getAllProjects = async (
userId: string,
limit: number,
offset: number,
) => {
return await db
.select()
.from(projects)
.limit(limit)
.offset(offset)
.where(eq(projects.userId, userId));
};
59 changes: 52 additions & 7 deletions db/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ async function seedUsers() {
async function seedProjects() {
await db.insert(projects).values([
{
id: 'my-project',
name: 'My Project',
description: 'This is a project',
id: 'swolo',
name: 'Project management app',
description: 'Project management and note-taking app wit GTD principles.',
userId: 'fox',
key: 'my-project',
key: 'swolo',
},
]);
}
Expand All @@ -40,13 +40,58 @@ async function seedTasks() {
await db.insert(tasks).values([
{
id: createId(),
title: 'My Task',
description: 'This is a task',
title: 'Implement synching',
description: 'Sync data from the cloud to the local desktop.',
status: 'todo',
userId: 'fox',
projectId: 'my-project',
projectId: 'swolo',
key: 'my-task',
},
{
id: createId(),
title: 'Design app layout',
description: 'Create wireframes and mockups for the app.',
status: 'in-progress',
userId: 'fox',
projectId: 'swolo',
key: 'design-layout',
},
{
id: createId(),
title: 'Develop authentication module',
description: 'Implement user login and registration functionality.',
status: 'todo',
userId: 'fox',
projectId: 'swolo',
key: 'auth-module',
},
{
id: createId(),
title: 'Set up database',
description: 'Configure the database schema and connections.',
status: 'todo',
userId: 'fox',
projectId: 'swolo',
key: 'setup-database',
},
{
id: createId(),
title: 'Create API endpoints',
description: 'Develop RESTful API endpoints for the app.',
status: 'todo',
userId: 'fox',
projectId: 'swolo',
key: 'create-api',
},
{
id: createId(),
title: 'Implement frontend',
description: 'Build the frontend using React.',
status: 'todo',
userId: 'fox',
projectId: 'swolo',
key: 'implement-frontend',
},
]);
}

Expand Down
4 changes: 4 additions & 0 deletions db/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { projects, tasks } from './schema';

export type Project = typeof projects.$inferSelect;
export type Task = typeof tasks.$inferSelect;
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-menubar": "^1.1.2",
"@radix-ui/react-scroll-area": "^1.2.0",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-visually-hidden": "^1.1.0",
Expand All @@ -43,6 +44,8 @@
"drizzle-kit": "^0.25.0",
"eslint": "^8",
"eslint-config-next": "14.2.15",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-tailwindcss": "^3.17.5",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"tailwindcss-animate": "^1.0.7",
Expand Down
Loading

0 comments on commit f4c2515

Please sign in to comment.