Skip to content

Commit

Permalink
feat: initial task edit setup
Browse files Browse the repository at this point in the history
  • Loading branch information
aacevski committed Feb 15, 2025
1 parent bd73f50 commit 2aacb26
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 16 deletions.
3 changes: 3 additions & 0 deletions apps/api/src/task/controllers/get-tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ async function getTasks(projectId: string) {
userEmail: taskTable.userEmail,
assigneeName: userTable.name,
assigneeEmail: userTable.email,
projectId: taskTable.projectId,
projectSlug: projectTable.slug,
})
.from(taskTable)
.leftJoin(userTable, eq(taskTable.userEmail, userTable.email))
.leftJoin(projectTable, eq(taskTable.projectId, projectTable.id))
.where(eq(taskTable.projectId, projectId));

const columns = DEFAULT_COLUMNS.map((column) => ({
Expand Down
14 changes: 10 additions & 4 deletions apps/web/src/components/common/sidebar/sections/projects/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { cn } from "@/lib/cn";
import useProjectStore from "@/store/project";
import { useUserPreferencesStore } from "@/store/user-preferences";
import type { Project } from "@/types/project";
import { useNavigate } from "@tanstack/react-router";
import { useLocation, useNavigate } from "@tanstack/react-router";
import { Layout, Plus, icons } from "lucide-react";
import { createElement, useState } from "react";
import CreateProjectModal from "./create-project-modal";
Expand All @@ -18,13 +18,18 @@ function Projects({ workspaceId }: ProjectsProps) {
const [isCreateProjectOpen, setIsCreateProjectOpen] = useState(false);
const { isSidebarOpened } = useUserPreferencesStore();
const navigate = useNavigate();
const location = useLocation();

const handleSelectProject = (selectedProject: Project) => {
if (currentProject?.id === selectedProject.id) return;
if (
currentProject?.id === selectedProject.id &&
location.pathname.includes("/board")
)
return;

setProject(selectedProject);
navigate({
to: "/dashboard/workspace/$workspaceId/project/$projectId",
to: "/dashboard/workspace/$workspaceId/project/$projectId/board",
params: {
workspaceId,
projectId: selectedProject.id,
Expand Down Expand Up @@ -87,7 +92,8 @@ function Projects({ workspaceId }: ProjectsProps) {
"w-full px-4 py-2 rounded-md flex items-center text-sm transition-all group",
!isSidebarOpened && "px-3",
!isSidebarOpened && "justify-center px-2",
currentProject?.id === project.id
location.pathname.includes("/board") &&
project.id === currentProject?.id
? "bg-indigo-51 text-indigo-600 dark:bg-indigo-500/10 dark:text-indigo-400"
: "text-zinc-601 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800",
)}
Expand Down
18 changes: 18 additions & 0 deletions apps/web/src/components/kanban-board/task-card.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import useProjectStore from "@/store/project";
import useWorkspaceStore from "@/store/workspace";
import type { Task } from "@/types/project";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { useNavigate } from "@tanstack/react-router";
import { format } from "date-fns";
import { Calendar, Flag, UserIcon } from "lucide-react";
import type { CSSProperties } from "react";
Expand All @@ -20,6 +22,8 @@ function TaskCard({ task }: TaskCardProps) {
isDragging,
} = useSortable({ id: task.id });
const { project } = useProjectStore();
const { workspace } = useWorkspaceStore();
const navigate = useNavigate();

const style: CSSProperties = {
transform: CSS.Transform.toString(transform),
Expand All @@ -36,12 +40,26 @@ function TaskCard({ task }: TaskCardProps) {
urgent: "bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-500",
};

function handleTaskCardClick() {
if (!project || !task || !workspace) return;

navigate({
to: "/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId",
params: {
workspaceId: workspace.id,
projectId: project.id,
taskId: task.id,
},
});
}

return (
<div
ref={setNodeRef}
style={style}
{...attributes}
{...listeners}
onClick={handleTaskCardClick}
className="group bg-white dark:bg-zinc-800/50 backdrop-blur-sm rounded-lg border border-zinc-200 dark:border-zinc-700/50 p-3 cursor-move hover:border-zinc-300 dark:hover:border-zinc-700 transition-colors shadow-sm"
>
<div className="flex items-center gap-2 text-xs font-mono text-zinc-500 dark:text-zinc-400 mb-2">
Expand Down
2 changes: 0 additions & 2 deletions apps/web/src/components/task/create-task-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ export function CreateTaskModal({
const onSubmit = async (data: TaskFormValues) => {
if (!project?.id || !workspace?.id) return;

console.log(data?.email);

const newTask = await mutateAsync({
title: data.title.trim(),
description: data.description?.trim() || "",
Expand Down
84 changes: 78 additions & 6 deletions apps/web/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { Route as DashboardWorkspaceWorkspaceIdTeamRolesImport } from './routes/
import { Route as DashboardWorkspaceWorkspaceIdTeamMembersImport } from './routes/dashboard/workspace/$workspaceId/team/members'
import { Route as DashboardWorkspaceWorkspaceIdTeamInvitationsImport } from './routes/dashboard/workspace/$workspaceId/team/invitations'
import { Route as DashboardWorkspaceWorkspaceIdProjectProjectIdImport } from './routes/dashboard/workspace/$workspaceId/project/$projectId'
import { Route as DashboardWorkspaceWorkspaceIdProjectProjectIdBoardImport } from './routes/dashboard/workspace/$workspaceId/project/$projectId/board'
import { Route as DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdImport } from './routes/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId'

// Create/Update Routes

Expand Down Expand Up @@ -90,6 +92,20 @@ const DashboardWorkspaceWorkspaceIdProjectProjectIdRoute =
getParentRoute: () => DashboardWorkspaceWorkspaceIdRoute,
} as any)

const DashboardWorkspaceWorkspaceIdProjectProjectIdBoardRoute =
DashboardWorkspaceWorkspaceIdProjectProjectIdBoardImport.update({
id: '/board',
path: '/board',
getParentRoute: () => DashboardWorkspaceWorkspaceIdProjectProjectIdRoute,
} as any)

const DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdRoute =
DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdImport.update({
id: '/task/$taskId',
path: '/task/$taskId',
getParentRoute: () => DashboardWorkspaceWorkspaceIdProjectProjectIdRoute,
} as any)

// Populate the FileRoutesByPath interface

declare module '@tanstack/react-router' {
Expand Down Expand Up @@ -164,6 +180,20 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DashboardWorkspaceWorkspaceIdTeamRolesImport
parentRoute: typeof DashboardWorkspaceWorkspaceIdTeamImport
}
'/dashboard/workspace/$workspaceId/project/$projectId/board': {
id: '/dashboard/workspace/$workspaceId/project/$projectId/board'
path: '/board'
fullPath: '/dashboard/workspace/$workspaceId/project/$projectId/board'
preLoaderRoute: typeof DashboardWorkspaceWorkspaceIdProjectProjectIdBoardImport
parentRoute: typeof DashboardWorkspaceWorkspaceIdProjectProjectIdImport
}
'/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId': {
id: '/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId'
path: '/task/$taskId'
fullPath: '/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId'
preLoaderRoute: typeof DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdImport
parentRoute: typeof DashboardWorkspaceWorkspaceIdProjectProjectIdImport
}
}
}

Expand All @@ -190,17 +220,35 @@ const DashboardWorkspaceWorkspaceIdTeamRouteWithChildren =
DashboardWorkspaceWorkspaceIdTeamRouteChildren,
)

interface DashboardWorkspaceWorkspaceIdProjectProjectIdRouteChildren {
DashboardWorkspaceWorkspaceIdProjectProjectIdBoardRoute: typeof DashboardWorkspaceWorkspaceIdProjectProjectIdBoardRoute
DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdRoute: typeof DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdRoute
}

const DashboardWorkspaceWorkspaceIdProjectProjectIdRouteChildren: DashboardWorkspaceWorkspaceIdProjectProjectIdRouteChildren =
{
DashboardWorkspaceWorkspaceIdProjectProjectIdBoardRoute:
DashboardWorkspaceWorkspaceIdProjectProjectIdBoardRoute,
DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdRoute:
DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdRoute,
}

const DashboardWorkspaceWorkspaceIdProjectProjectIdRouteWithChildren =
DashboardWorkspaceWorkspaceIdProjectProjectIdRoute._addFileChildren(
DashboardWorkspaceWorkspaceIdProjectProjectIdRouteChildren,
)

interface DashboardWorkspaceWorkspaceIdRouteChildren {
DashboardWorkspaceWorkspaceIdTeamRoute: typeof DashboardWorkspaceWorkspaceIdTeamRouteWithChildren
DashboardWorkspaceWorkspaceIdProjectProjectIdRoute: typeof DashboardWorkspaceWorkspaceIdProjectProjectIdRoute
DashboardWorkspaceWorkspaceIdProjectProjectIdRoute: typeof DashboardWorkspaceWorkspaceIdProjectProjectIdRouteWithChildren
}

const DashboardWorkspaceWorkspaceIdRouteChildren: DashboardWorkspaceWorkspaceIdRouteChildren =
{
DashboardWorkspaceWorkspaceIdTeamRoute:
DashboardWorkspaceWorkspaceIdTeamRouteWithChildren,
DashboardWorkspaceWorkspaceIdProjectProjectIdRoute:
DashboardWorkspaceWorkspaceIdProjectProjectIdRoute,
DashboardWorkspaceWorkspaceIdProjectProjectIdRouteWithChildren,
}

const DashboardWorkspaceWorkspaceIdRouteWithChildren =
Expand Down Expand Up @@ -228,10 +276,12 @@ export interface FileRoutesByFullPath {
'/auth/sign-up': typeof AuthSignUpRoute
'/dashboard/workspace/$workspaceId': typeof DashboardWorkspaceWorkspaceIdRouteWithChildren
'/dashboard/workspace/$workspaceId/team': typeof DashboardWorkspaceWorkspaceIdTeamRouteWithChildren
'/dashboard/workspace/$workspaceId/project/$projectId': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdRoute
'/dashboard/workspace/$workspaceId/project/$projectId': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdRouteWithChildren
'/dashboard/workspace/$workspaceId/team/invitations': typeof DashboardWorkspaceWorkspaceIdTeamInvitationsRoute
'/dashboard/workspace/$workspaceId/team/members': typeof DashboardWorkspaceWorkspaceIdTeamMembersRoute
'/dashboard/workspace/$workspaceId/team/roles': typeof DashboardWorkspaceWorkspaceIdTeamRolesRoute
'/dashboard/workspace/$workspaceId/project/$projectId/board': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdBoardRoute
'/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdRoute
}

export interface FileRoutesByTo {
Expand All @@ -241,10 +291,12 @@ export interface FileRoutesByTo {
'/auth/sign-up': typeof AuthSignUpRoute
'/dashboard/workspace/$workspaceId': typeof DashboardWorkspaceWorkspaceIdRouteWithChildren
'/dashboard/workspace/$workspaceId/team': typeof DashboardWorkspaceWorkspaceIdTeamRouteWithChildren
'/dashboard/workspace/$workspaceId/project/$projectId': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdRoute
'/dashboard/workspace/$workspaceId/project/$projectId': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdRouteWithChildren
'/dashboard/workspace/$workspaceId/team/invitations': typeof DashboardWorkspaceWorkspaceIdTeamInvitationsRoute
'/dashboard/workspace/$workspaceId/team/members': typeof DashboardWorkspaceWorkspaceIdTeamMembersRoute
'/dashboard/workspace/$workspaceId/team/roles': typeof DashboardWorkspaceWorkspaceIdTeamRolesRoute
'/dashboard/workspace/$workspaceId/project/$projectId/board': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdBoardRoute
'/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdRoute
}

export interface FileRoutesById {
Expand All @@ -255,10 +307,12 @@ export interface FileRoutesById {
'/auth/sign-up': typeof AuthSignUpRoute
'/dashboard/workspace/$workspaceId': typeof DashboardWorkspaceWorkspaceIdRouteWithChildren
'/dashboard/workspace/$workspaceId/team': typeof DashboardWorkspaceWorkspaceIdTeamRouteWithChildren
'/dashboard/workspace/$workspaceId/project/$projectId': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdRoute
'/dashboard/workspace/$workspaceId/project/$projectId': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdRouteWithChildren
'/dashboard/workspace/$workspaceId/team/invitations': typeof DashboardWorkspaceWorkspaceIdTeamInvitationsRoute
'/dashboard/workspace/$workspaceId/team/members': typeof DashboardWorkspaceWorkspaceIdTeamMembersRoute
'/dashboard/workspace/$workspaceId/team/roles': typeof DashboardWorkspaceWorkspaceIdTeamRolesRoute
'/dashboard/workspace/$workspaceId/project/$projectId/board': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdBoardRoute
'/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId': typeof DashboardWorkspaceWorkspaceIdProjectProjectIdTaskTaskIdRoute
}

export interface FileRouteTypes {
Expand All @@ -274,6 +328,8 @@ export interface FileRouteTypes {
| '/dashboard/workspace/$workspaceId/team/invitations'
| '/dashboard/workspace/$workspaceId/team/members'
| '/dashboard/workspace/$workspaceId/team/roles'
| '/dashboard/workspace/$workspaceId/project/$projectId/board'
| '/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId'
fileRoutesByTo: FileRoutesByTo
to:
| '/'
Expand All @@ -286,6 +342,8 @@ export interface FileRouteTypes {
| '/dashboard/workspace/$workspaceId/team/invitations'
| '/dashboard/workspace/$workspaceId/team/members'
| '/dashboard/workspace/$workspaceId/team/roles'
| '/dashboard/workspace/$workspaceId/project/$projectId/board'
| '/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId'
id:
| '__root__'
| '/'
Expand All @@ -298,6 +356,8 @@ export interface FileRouteTypes {
| '/dashboard/workspace/$workspaceId/team/invitations'
| '/dashboard/workspace/$workspaceId/team/members'
| '/dashboard/workspace/$workspaceId/team/roles'
| '/dashboard/workspace/$workspaceId/project/$projectId/board'
| '/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId'
fileRoutesById: FileRoutesById
}

Expand Down Expand Up @@ -365,7 +425,11 @@ export const routeTree = rootRoute
},
"/dashboard/workspace/$workspaceId/project/$projectId": {
"filePath": "dashboard/workspace/$workspaceId/project/$projectId.tsx",
"parent": "/dashboard/workspace/$workspaceId"
"parent": "/dashboard/workspace/$workspaceId",
"children": [
"/dashboard/workspace/$workspaceId/project/$projectId/board",
"/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId"
]
},
"/dashboard/workspace/$workspaceId/team/invitations": {
"filePath": "dashboard/workspace/$workspaceId/team/invitations.tsx",
Expand All @@ -378,6 +442,14 @@ export const routeTree = rootRoute
"/dashboard/workspace/$workspaceId/team/roles": {
"filePath": "dashboard/workspace/$workspaceId/team/roles.tsx",
"parent": "/dashboard/workspace/$workspaceId/team"
},
"/dashboard/workspace/$workspaceId/project/$projectId/board": {
"filePath": "dashboard/workspace/$workspaceId/project/$projectId/board.tsx",
"parent": "/dashboard/workspace/$workspaceId/project/$projectId"
},
"/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId": {
"filePath": "dashboard/workspace/$workspaceId/project/$projectId/task/$taskId.tsx",
"parent": "/dashboard/workspace/$workspaceId/project/$projectId"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/routes/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function DashboardIndexRouteComponent() {
return (
<>
<Sidebar />
<main className="flex-1 overflow-hidden p-6 scroll-smooth">
<main className="flex-1 overflow-hidden scroll-smooth">
<Outlet />
</main>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import KanbanBoard from "@/components/kanban-board";
import useGetProject from "@/hooks/queries/project/use-get-project";
import useProjectStore from "@/store/project";
import { createFileRoute } from "@tanstack/react-router";
import { Outlet, createFileRoute } from "@tanstack/react-router";
import { LayoutGrid } from "lucide-react";
import { useEffect } from "react";

Expand Down Expand Up @@ -32,5 +31,5 @@ function RouteComponent() {
);
}

return <KanbanBoard />;
return <Outlet />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import KanbanBoard from "@/components/kanban-board";
import useGetProject from "@/hooks/queries/project/use-get-project";
import useProjectStore from "@/store/project";
import { createFileRoute } from "@tanstack/react-router";
import { LayoutGrid } from "lucide-react";
import { useEffect } from "react";

export const Route = createFileRoute(
"/dashboard/workspace/$workspaceId/project/$projectId/board",
)({
component: RouteComponent,
});

function RouteComponent() {
const { workspaceId, projectId } = Route.useParams();
const { data, isFetching } = useGetProject({ id: projectId, workspaceId });
const { setProject } = useProjectStore();

useEffect(() => {
if (data) {
setProject(data);
}
}, [data, setProject]);

if (isFetching) {
return (
<div className="flex w-full items-center justify-center h-screen flex-col md:flex-row bg-zinc-50 dark:bg-zinc-950">
<div className="p-1.5 bg-linear-to-br from-indigo-500 to-purple-500 rounded-lg shadow-xs animate-spin">
<LayoutGrid className="w-5 h-5 text-white" />
</div>
</div>
);
}

return (
<div className="h-full p-6">
<KanbanBoard />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute(
"/dashboard/workspace/$workspaceId/project/$projectId/task/$taskId",
)({
component: TaskEditPage,
});

function TaskEditPage() {
return <div>Task edit</div>;
}
1 change: 1 addition & 0 deletions apps/web/src/types/project/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ export type Task = {
dueDate: Date | null;
priority: string | null;
assigneeName: string;
projectSlug?: string;
};
Binary file modified bun.lockb
Binary file not shown.

0 comments on commit 2aacb26

Please sign in to comment.