82 lines
3.1 KiB
TypeScript
82 lines
3.1 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||
import { toast } from "sonner";
|
||
import { Button, Textarea } from "@/components/ds";
|
||
import { workspaceApi } from "@/modules/workspace/services/workspace-api";
|
||
import { displayPerson, formatWhen } from "@/modules/workspace/labels";
|
||
import { WorkspacePageError, WorkspacePageLoader } from "@/modules/workspace/pages/shared";
|
||
|
||
export function CommentThread({
|
||
tenantId,
|
||
workHubId,
|
||
subjectType,
|
||
subjectId,
|
||
}: {
|
||
tenantId: string;
|
||
workHubId: string;
|
||
subjectType: "project" | "task" | "content" | "team";
|
||
subjectId: string;
|
||
}) {
|
||
const queryClient = useQueryClient();
|
||
const [body, setBody] = useState("");
|
||
const comments = useQuery({
|
||
queryKey: ["workspace", tenantId, "comments", subjectType, subjectId],
|
||
queryFn: () =>
|
||
workspaceApi.comments.list(tenantId, {
|
||
work_hub_id: workHubId,
|
||
subject_type: subjectType,
|
||
subject_id: subjectId,
|
||
}),
|
||
});
|
||
const create = useMutation({
|
||
mutationFn: () =>
|
||
workspaceApi.comments.create(tenantId, {
|
||
work_hub_id: workHubId,
|
||
subject_type: subjectType,
|
||
subject_id: subjectId,
|
||
body,
|
||
}),
|
||
onSuccess: () => {
|
||
setBody("");
|
||
toast.success("نظر ثبت شد");
|
||
void queryClient.invalidateQueries({ queryKey: ["workspace", tenantId, "comments"] });
|
||
void queryClient.invalidateQueries({ queryKey: ["workspace", tenantId, "activity"] });
|
||
},
|
||
onError: (error) => toast.error(error instanceof Error ? error.message : "ثبت نظر ناموفق بود"),
|
||
});
|
||
|
||
if (comments.isLoading) return <WorkspacePageLoader label="در حال بارگذاری گفتگو…" />;
|
||
if (comments.error) return <WorkspacePageError error={comments.error} onRetry={() => comments.refetch()} />;
|
||
|
||
return (
|
||
<div className="space-y-3">
|
||
<h3 className="text-sm font-semibold text-secondary">گفتگو</h3>
|
||
<div className="space-y-2">
|
||
{(comments.data ?? []).length === 0 ? (
|
||
<p className="text-sm text-[var(--muted)]">هنوز نظری ثبت نشده است. برای اشاره به فرد از @نام استفاده کنید.</p>
|
||
) : (
|
||
(comments.data ?? []).map((item) => (
|
||
<div key={String(item.id)} className="rounded-xl border border-[var(--border)] bg-[var(--surface)] p-3">
|
||
<p className="text-xs text-[var(--muted)]">
|
||
{displayPerson(String(item.author_user_id || ""))} · {formatWhen(String(item.created_at || ""))}
|
||
</p>
|
||
<p className="mt-1 text-sm text-secondary">{String(item.body || "")}</p>
|
||
</div>
|
||
))
|
||
)}
|
||
</div>
|
||
<Textarea
|
||
value={body}
|
||
onChange={(event) => setBody(event.target.value)}
|
||
placeholder="نظر خود را بنویسید…"
|
||
rows={3}
|
||
/>
|
||
<Button type="button" disabled={!body.trim() || create.isPending} onClick={() => create.mutate()}>
|
||
ثبت نظر
|
||
</Button>
|
||
</div>
|
||
);
|
||
}
|