)}
{preview && !(preview.file.kind === "image" && imgSrc(preview.file)) && Viewer && (
setPreview(null)} />
)}
);
}
/* Projects are created automatically when one task is assigned to 2+ users
(PRD §5.3). Progress stays per-user; the box shows the aggregate. */
function ProjectPanel({ tasks, onComment, commentCount, meId, onStart, onEditProject, onDeleteProject }) {
const all = projectsFrom(tasks);
const [detail, setDetail] = React.useState(null);
const [edit, setEdit] = React.useState(null); // {project, form}
const [remove, setRemove] = React.useState(null); // project yang akan dihapus
const isAdmin = meId == null || meId === 0;
// A user only sees the projects they were assigned to; Admin (id 0) sees all.
const projects = meId == null || meId === 0 ? all : all.filter((p) => p.members.includes(meId));
if (projects.length === 0) return null;
const open = detail ? projects.find((p) => p.name === detail) : null;
return (
Project
{projects.length}Klik project untuk melihat detail per user
{projects.map((p) => {
const member = meId == null || meId === 0 || p.members.includes(meId);
return (
setDetail(p.name)}>
setEdit({ ...edit, form: { ...edit.form, target: e.target.value } })} />
{edit.project.tasks.length} task milik {edit.project.members.length} user akan ikut diperbarui.
)}
{remove && (
setRemove(null)} title="Hapus Project"
description={`${remove.name} beserta ${remove.tasks.length} task di dalamnya akan dihapus.`}
footer={<>
>}>
Task yang sudah dikerjakan user ikut hilang dari daftar. Tindakan ini tercatat di Log Activity.
)}
{open && setDetail(null)} onComment={onComment}
meId={meId} onStart={onStart}
member={meId == null || meId === 0 || open.members.includes(meId)} />}