feat(calendar): görevleri takvimde göster

- Bitiş tarihi olan ve done olmayan görevler takvimde turuncu pill olarak gösteriliyor
- Göreve tıklamak /tasks sayfasına yönlendiriyor, etkinlik formu açmıyor
- COLOR_BG'ye 'task' rengi eklendi (orange)
This commit is contained in:
kovakmedya
2026-05-07 19:47:50 +03:00
parent 63531d30d9
commit a0aec13b8c
3 changed files with 76 additions and 35 deletions
@@ -1,7 +1,8 @@
"use client";
import Link from "next/link";
import { useMemo, useState, useTransition } from "react";
import { ChevronLeft, ChevronRight, Loader2, Plus, Trash2 } from "lucide-react";
import { ChevronLeft, ChevronRight, Loader2, Plus, SquareCheckBig, Trash2 } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
@@ -98,6 +99,7 @@ export function CalendarClient({ events, customers }: Props) {
};
const handleEdit = (event: EventRow) => {
if (event.source === "task") return;
setEditing(event);
setDefaultDate(undefined);
setFormOpen(true);
@@ -186,7 +188,21 @@ export function CalendarClient({ events, customers }: Props) {
</button>
</div>
<div className="flex flex-col gap-0.5">
{dayEvents.slice(0, 3).map((e) => (
{dayEvents.slice(0, 3).map((e) =>
e.source === "task" ? (
<Link
key={e.id}
href="/tasks"
className={cn(
"flex items-center gap-1 truncate rounded border px-1.5 py-0.5 text-left text-xs",
COLOR_BG["task"],
)}
title={e.title}
>
<SquareCheckBig className="size-3 shrink-0 opacity-70" />
<span className="truncate">{e.title}</span>
</Link>
) : (
<button
key={e.id}
type="button"
@@ -207,7 +223,8 @@ export function CalendarClient({ events, customers }: Props) {
)}
{e.title}
</button>
))}
),
)}
{dayEvents.length > 3 && (
<span className="text-muted-foreground px-1 text-xs">
+{dayEvents.length - 3} daha
@@ -8,6 +8,8 @@ export type EventRow = {
customerId: string;
customerName: string;
color: string;
source?: "event" | "task";
taskStatus?: string;
};
export type Customer = { id: string; name: string };
@@ -28,5 +30,6 @@ export const COLOR_BG: Record<string, string> = {
red: "bg-red-500/15 text-red-700 dark:text-red-300 border-red-500/30",
violet: "bg-violet-500/15 text-violet-700 dark:text-violet-300 border-violet-500/30",
slate: "bg-slate-500/15 text-slate-700 dark:text-slate-300 border-slate-500/30",
task: "bg-orange-500/15 text-orange-700 dark:text-orange-300 border-orange-500/30",
"": "bg-primary/10 text-primary border-primary/20",
};
+33 -12
View File
@@ -3,6 +3,7 @@ import { redirect } from "next/navigation";
import { listCalendarEvents } from "@/lib/appwrite/calendar-queries";
import { listCustomers } from "@/lib/appwrite/customer-queries";
import { listTasks } from "@/lib/appwrite/task-queries";
import { requireTenant } from "@/lib/appwrite/tenant-guard";
import { CalendarClient } from "./components/calendar-client";
@@ -18,13 +19,43 @@ export default async function CalendarPage() {
redirect("/onboarding");
}
const [events, customers] = await Promise.all([
const [events, customers, tasks] = await Promise.all([
listCalendarEvents(ctx.tenantId),
listCustomers(ctx.tenantId),
listTasks(ctx.tenantId),
]);
const customerMap = new Map(customers.map((c) => [c.$id, c.name]));
const mappedEvents = events.map((e) => ({
id: e.$id,
title: e.title,
description: e.description ?? "",
start: e.start,
end: e.end,
allDay: Boolean(e.allDay),
customerId: e.customerId ?? "",
customerName: e.customerId ? customerMap.get(e.customerId) ?? "" : "",
color: e.color ?? "",
source: "event" as const,
}));
const mappedTasks = tasks
.filter((t) => t.dueDate && t.status !== "done")
.map((t) => ({
id: t.$id,
title: t.title,
description: t.description ?? "",
start: t.dueDate!,
end: t.dueDate!,
allDay: true,
customerId: "",
customerName: "",
color: "task",
source: "task" as const,
taskStatus: t.status,
}));
return (
<div className="flex-1 space-y-6 px-6 pt-0">
<div className="flex flex-col gap-1">
@@ -36,17 +67,7 @@ export default async function CalendarPage() {
</div>
<CalendarClient
events={events.map((e) => ({
id: e.$id,
title: e.title,
description: e.description ?? "",
start: e.start,
end: e.end,
allDay: Boolean(e.allDay),
customerId: e.customerId ?? "",
customerName: e.customerId ? customerMap.get(e.customerId) ?? "" : "",
color: e.color ?? "",
}))}
events={[...mappedEvents, ...mappedTasks]}
customers={customers.map((c) => ({ id: c.$id, name: c.name }))}
/>
</div>