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:
@@ -1,7 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
import { useMemo, useState, useTransition } from "react";
|
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 { toast } from "sonner";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -98,6 +99,7 @@ export function CalendarClient({ events, customers }: Props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEdit = (event: EventRow) => {
|
const handleEdit = (event: EventRow) => {
|
||||||
|
if (event.source === "task") return;
|
||||||
setEditing(event);
|
setEditing(event);
|
||||||
setDefaultDate(undefined);
|
setDefaultDate(undefined);
|
||||||
setFormOpen(true);
|
setFormOpen(true);
|
||||||
@@ -186,7 +188,21 @@ export function CalendarClient({ events, customers }: Props) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-0.5">
|
<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
|
<button
|
||||||
key={e.id}
|
key={e.id}
|
||||||
type="button"
|
type="button"
|
||||||
@@ -207,7 +223,8 @@ export function CalendarClient({ events, customers }: Props) {
|
|||||||
)}
|
)}
|
||||||
{e.title}
|
{e.title}
|
||||||
</button>
|
</button>
|
||||||
))}
|
),
|
||||||
|
)}
|
||||||
{dayEvents.length > 3 && (
|
{dayEvents.length > 3 && (
|
||||||
<span className="text-muted-foreground px-1 text-xs">
|
<span className="text-muted-foreground px-1 text-xs">
|
||||||
+{dayEvents.length - 3} daha
|
+{dayEvents.length - 3} daha
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ export type EventRow = {
|
|||||||
customerId: string;
|
customerId: string;
|
||||||
customerName: string;
|
customerName: string;
|
||||||
color: string;
|
color: string;
|
||||||
|
source?: "event" | "task";
|
||||||
|
taskStatus?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Customer = { id: string; name: 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",
|
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",
|
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",
|
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",
|
"": "bg-primary/10 text-primary border-primary/20",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { redirect } from "next/navigation";
|
|||||||
|
|
||||||
import { listCalendarEvents } from "@/lib/appwrite/calendar-queries";
|
import { listCalendarEvents } from "@/lib/appwrite/calendar-queries";
|
||||||
import { listCustomers } from "@/lib/appwrite/customer-queries";
|
import { listCustomers } from "@/lib/appwrite/customer-queries";
|
||||||
|
import { listTasks } from "@/lib/appwrite/task-queries";
|
||||||
import { requireTenant } from "@/lib/appwrite/tenant-guard";
|
import { requireTenant } from "@/lib/appwrite/tenant-guard";
|
||||||
import { CalendarClient } from "./components/calendar-client";
|
import { CalendarClient } from "./components/calendar-client";
|
||||||
|
|
||||||
@@ -18,13 +19,43 @@ export default async function CalendarPage() {
|
|||||||
redirect("/onboarding");
|
redirect("/onboarding");
|
||||||
}
|
}
|
||||||
|
|
||||||
const [events, customers] = await Promise.all([
|
const [events, customers, tasks] = await Promise.all([
|
||||||
listCalendarEvents(ctx.tenantId),
|
listCalendarEvents(ctx.tenantId),
|
||||||
listCustomers(ctx.tenantId),
|
listCustomers(ctx.tenantId),
|
||||||
|
listTasks(ctx.tenantId),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const customerMap = new Map(customers.map((c) => [c.$id, c.name]));
|
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 (
|
return (
|
||||||
<div className="flex-1 space-y-6 px-6 pt-0">
|
<div className="flex-1 space-y-6 px-6 pt-0">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
@@ -36,17 +67,7 @@ export default async function CalendarPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CalendarClient
|
<CalendarClient
|
||||||
events={events.map((e) => ({
|
events={[...mappedEvents, ...mappedTasks]}
|
||||||
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 ?? "",
|
|
||||||
}))}
|
|
||||||
customers={customers.map((c) => ({ id: c.$id, name: c.name }))}
|
customers={customers.map((c) => ({ id: c.$id, name: c.name }))}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user