Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ name: CI for Next.js
on:
push:
branches:
- main
- master
pull_request:
branches:
- main
- master

jobs:
build:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Deploy to Netlify
on:
push:
branches:
- main
- master

jobs:
deploy:
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"postinstall": "prisma generate",
"build": "next build --no-lint",
"start": "next start",
"typecheck": "tsc --noEmit",
"lint": "next lint"
},
"dependencies": {
Expand Down
69 changes: 69 additions & 0 deletions src/app/(main)/projects/[id]/_components/DeleteTask.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"use client";

import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { deleteTask } from "@/lib/actions/task.action";
import { FileWarning } from "lucide-react";
import * as React from "react";
import { toast } from "sonner";

export function DeleteTaskDialog({ taskId }: { taskId: string }) {
const [loading, setLoading] = React.useState(false);

const handleDelete = async () => {
try {
setLoading(true);
const res = await deleteTask(taskId);
if (res.success) toast.success("Task deleted successfully.");
toast.error(res.message);
} finally {
setLoading(false);
}
};

return (
<Dialog>
<DialogTrigger asChild>
<p className="py-2 px-4 hover:bg-muted transition-all duration-100 cursor-pointer w-full whitespace-nowrap">
Delete task
</p>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<div className="flex items-center space-x-2">
<FileWarning className="h-5 w-5 text-red-500" />
<DialogTitle>Delete task</DialogTitle>
</div>
<DialogDescription>
Are you sure you want to delete this task? This action cannot be
undone.
</DialogDescription>
</DialogHeader>

<DialogFooter className="w-full flex justify-start sm:justify-start">
<DialogTrigger asChild>
<Button variant="outline" className="cursor-pointer rounded">
Cancel
</Button>
</DialogTrigger>
<Button
className="cursor-pointer rounded"
variant="destructive"
onClick={handleDelete}
disabled={loading}
>
{loading ? "Deleting..." : "Delete"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
10 changes: 4 additions & 6 deletions src/app/(main)/projects/[id]/_components/EditDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
"use client";

import * as React from "react";
import {
Dialog,
DialogTrigger,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
DialogTrigger
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import EditTaskForm from "./EditTaskForm";
import * as React from "react";
import { Task } from "../../../../../../prisma/src/generated/prisma";
import EditTaskForm from "./EditTaskForm";

export function EditTaskDialog({ task }: { task: Task }) {
const [open, setOpen] = React.useState(false);
Expand Down
14 changes: 8 additions & 6 deletions src/app/(main)/projects/[id]/_components/TaskActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

"use server";
import {
Popover,
PopoverContent,
PopoverTrigger,
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { MoreHorizontal } from "lucide-react";
import { EditTaskDialog } from "./EditDialog";
import { DeleteTaskDialog } from "./DeleteTask";

const TaskActions = async ({ task }: { task: any }) => {
return (
Expand All @@ -31,6 +32,7 @@ const TaskActions = async ({ task }: { task: any }) => {
</PopoverTrigger>
<PopoverContent className="w-[139px] text-sm rounded p-0">
<EditTaskDialog task={task} />
<DeleteTaskDialog taskId={task.id} />
</PopoverContent>
</Popover>
);
Expand Down
9 changes: 6 additions & 3 deletions src/app/(main)/projects/[id]/_components/TasksList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ const TasksList = async ({ data }: { data: any }) => {
return (
<TabsContent value="list">
<div className="w-full py-6">
<div className="w-full flex items-center gap-2 mb-6">
<SearchTasksInput />
<FiltersPopover />
<div className="w-full flex items-center gap-2 mb-6 justify-between">
<div className="flex w-full gap-2 items-center">
<SearchTasksInput />
<FiltersPopover />
</div>
<button className="button">Create task</button>
</div>
<ReusableTable data={data} columns={columns} />
</div>
Expand Down
7 changes: 5 additions & 2 deletions src/app/(main)/projects/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import formatDate from "@/lib/helper/convert-date";
import TasksList from "./_components/TasksList";
import { Priority, task } from "../../../../../prisma/src/generated/prisma";
import TaskActions from "./_components/TaskActions";
import { getProjectById } from "@/lib/actions/projects.action";

const tabs = [
{ text: "List", value: "list", icon: <List /> },
Expand Down Expand Up @@ -37,6 +38,8 @@ const ProjectTask = async ({ params, searchParams }: IProps) => {
pageSearchParams?.priority,
pageSearchParams?.status
);
const project = await getProjectById(id);
if (!project) return;
const data = rawData.map((item) => {
const avatarUrl = item.assignment.map((item) => ({
username: item.profiles.username || "U",
Expand All @@ -61,9 +64,9 @@ const ProjectTask = async ({ params, searchParams }: IProps) => {
</h1>
<div className="w-full flex gap-2 items-center pt-3">
<span className="w-5 h-5 rounded bg-button text-white flex items-center justify-center">
U
{project.name.slice(0, 1).toUpperCase()}
</span>
<p className="font-bold text-xl">My bim bam boom project</p>
<p className="font-bold text-xl">{project.name}</p>
</div>
<div className="w-full mt-4">
<Tabs defaultValue="list" className="w-full relative">
Expand Down
2 changes: 1 addition & 1 deletion src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,5 @@
}

@utility button {
@apply flex justify-center items-center px-4 py-2 border border-transparent text-sm font-medium rounded shadow-sm text-white bg-blue-600 hover:bg-button-hover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors active:scale-95 cursor-pointer;
@apply flex justify-center items-center px-4 py-2 border border-transparent text-sm font-medium rounded shadow-sm text-white bg-blue-600 hover:bg-button-hover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors active:scale-95 cursor-pointer whitespace-nowrap;
}
29 changes: 23 additions & 6 deletions src/lib/actions/task.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,27 @@ export async function updateTask(
dueDate: Date;
}
) {
await prisma.task.update({
where: { id },
data,
});
try {
return prisma.task.update({
where: { id },
data,
});
} catch (error) {
throw error;
} finally {
revalidatePath(`/projects/${id}`);
}
}

revalidatePath(`/projects/${id}`);
}
export async function deleteTask(id: string) {
try {
await prisma.task.delete({
where: { id },
});
return { success: true, message: "Task deleted successfully!" };
} catch (error) {
return { success: false, message: "Failed to delete task." };
} finally {
revalidatePath(`/projects/${id}`);
}
}
Loading