feat: activity assignment + team view for owner/admin

db: activities.assigneeId column (string, optional)

activity-actions: assigneeId saved on create (default: self), cleared on update
validation: assigneeId added to activitySchema
schema: assigneeId field on Activity type

activity-form-sheet: Atanan Kişi dropdown for owner/admin with member list
activity-team-view: new component — activities grouped by assignee,
  completion/edit/delete actions, overdue indicator, member avatars
activities-client: Ekip tab (owner/admin only), members + currentUserId props
activities page: fetches team memberships + user details, passes to client
activity-email-actions: filter by assigneeId ?? createdBy for both me/team modes
This commit is contained in:
egecankomur
2026-05-12 17:40:21 +03:00
parent 5ac6a1f8b0
commit 7c23a2b4ae
8 changed files with 319 additions and 7 deletions
@@ -2,7 +2,7 @@
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { DotsThree, Plus, PencilSimple, Trash, CheckCircle, List, CalendarDots } from '@/lib/icons';
import { DotsThree, Plus, PencilSimple, Trash, CheckCircle, List, CalendarDots, Users } from '@/lib/icons';
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
@@ -19,19 +19,23 @@ import {
} from "@/lib/appwrite/activity-actions";
import { ActivityFormSheet } from "./activity-form-sheet";
import { ActivityCalendar } from "./activity-calendar";
import { ActivityTeamView } from "./activity-team-view";
import { SendSummaryDialog } from "./send-summary-dialog";
import { DeleteConfirmDialog } from "@/components/ui/delete-confirm-dialog";
import type { Activity, Customer, Property } from "@/lib/appwrite/schema";
import { ACTIVITY_TYPE_LABELS } from "@/lib/appwrite/schema";
import type { TenantRole } from "@/lib/appwrite/tenant-guard";
import type { TeamMember } from "./activity-form-sheet";
type ViewMode = "list" | "calendar";
type ViewMode = "list" | "calendar" | "team";
interface ActivitiesClientProps {
initialActivities: Activity[];
customers: Customer[];
properties: Property[];
role: TenantRole;
members: TeamMember[];
currentUserId: string;
}
export function ActivitiesClient({
@@ -39,6 +43,8 @@ export function ActivitiesClient({
customers,
properties,
role,
members,
currentUserId,
}: ActivitiesClientProps) {
const router = useRouter();
const [activities, setActivities] = useState(initialActivities);
@@ -126,6 +132,20 @@ export function ActivitiesClient({
<CalendarDots className="size-3.5" />
Takvim
</button>
{(role === "owner" || role === "admin") && (
<button
type="button"
onClick={() => setViewMode("team")}
className={`flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium transition-colors ${
viewMode === "team"
? "bg-primary text-primary-foreground"
: "bg-background text-muted-foreground hover:text-foreground"
}`}
>
<Users className="size-3.5" />
Ekip
</button>
)}
</div>
<SendSummaryDialog role={role} />
<Button onClick={openCreate} size="sm" data-tour="activities-add">
@@ -146,6 +166,18 @@ export function ActivitiesClient({
/>
)}
{/* Team view — owner/admin only */}
{viewMode === "team" && (
<ActivityTeamView
activities={activities}
members={members}
currentUserId={currentUserId}
onEdit={openEdit}
onComplete={handleComplete}
onDelete={setDeleteTarget}
/>
)}
{/* List view */}
{viewMode === "list" && (
<div data-tour="activities-table" className="rounded-md border">
@@ -230,6 +262,9 @@ export function ActivitiesClient({
activity={editing}
customers={customers}
properties={properties}
members={members}
role={role}
currentUserId={currentUserId}
onSuccess={() => router.refresh()}
/>
<DeleteConfirmDialog