Files
Project-Management-V2/frontend/app/main/planning/projects/[projectIdentifier]/component/issueTab/index.tsx
Your NamebaishaliHolocron b9ac5ae0b2 first commit
2026-06-15 12:57:03 +05:30

204 lines
5.8 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { DataTable } from "ikoncomponents";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "ikoncomponents";
import { ColumnDef } from "@tanstack/react-table";
import { Plus, SquarePenIcon, Trash } from "lucide-react";
import IssueForm from "./components/issueModal";
import { IconTextButtonWithTooltip } from "ikoncomponents";
import { DTExtraParamsProps } from "ikoncomponents";
import EditIssueModal from "./components/editIssue";
import {
createIssueApi,
issuesApi,
updateIssueApi,
} from "@/app/utils/api/issueApi";
import { IssueData } from "@/app/utils/interface/issue";
import { useAppCache } from "@/app/utils/context/AppCacheContext";
interface IssueComponentProps {
projectIdentifier: string;
}
export default function IssueComponent({
projectIdentifier,
}: IssueComponentProps) {
const { userNameMap } = useAppCache();
// ── State ─────────────────────────────────────────────────────
const [createOpen, setCreateOpen] = useState(false);
const [editOpen, setEditOpen] = useState(false);
const [selectedIssue, setSelectedIssue] = useState<IssueData | null>(null);
const [data, setData] = useState<IssueData[]>([]);
const [loading, setLoading] = useState(true);
// ── Fetch Issues from API ──────────────────────────────────────
const fetchIssues = async () => {
try {
setLoading(true);
const response = await issuesApi(projectIdentifier);
console.log("Issue list response -----> ", response);
setData(response?.data || response || []);
} catch (error) {
console.error("Error fetching issues:", error);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchIssues();
}, []);
// ── Handlers ───────────────────────────────────────────────────
const openForCreate = () => setCreateOpen(true);
const openForEdit = (issue: IssueData) => {
setSelectedIssue(issue);
setEditOpen(true);
};
const handleCreateSubmit = async (formData: IssueData) => {
try {
const response = await createIssueApi(formData);
console.log("Issue created -----> ", response);
setCreateOpen(false);
fetchIssues();
} catch (error) {
console.error("Error creating issue:", error);
}
};
const handleEditSave = async (updatedValues: IssueData) => {
if (!selectedIssue?.issueId) {
console.error("No issue selected for update");
return;
}
console.log("Updated Issue:", updatedValues);
const response = await updateIssueApi(
selectedIssue.issueId,
updatedValues
);
console.log(response);
setEditOpen(false);
setSelectedIssue(null);
fetchIssues();
};
// ── Table Columns ─────────────────────────────────────────────
const columns: ColumnDef<IssueData>[] = [
{
accessorKey: "issueDescription",
header: () => <div className="text-center">Description</div>,
},
{
accessorKey: "issueProbability",
header: () => <div className="text-center">Probability (%)</div>,
cell: ({ row }) => <span>{row.original.issueProbability}%</span>,
},
{
accessorKey: "issueImpact",
header: () => <div className="text-center">Impact</div>,
},
{
accessorKey: "probableIssueValue",
header: () => <div className="text-center">Score</div>,
},
{
accessorKey: "issueOwner",
header: () => <div className="text-center">Owner</div>,
cell: ({ row }) => (
<span>
{row.original.issueOwner
? userNameMap.get(row.original.issueOwner)
: "N/A"}
</span>
),
},
{
accessorKey: "issueStatus",
header: () => <div className="text-center">Status</div>,
},
];
// ── DataTable Extra Params ────────────────────────────────────
const extraParams: DTExtraParamsProps = {
extraTools: [
<IconTextButtonWithTooltip
key="create-issue"
tooltipContent="Add new issue"
variant="outline"
onClick={openForCreate}
>
<Plus />
</IconTextButtonWithTooltip>,
],
actionMenu: {
items: [
{
label: "Edit",
icon: SquarePenIcon,
onClick: (row: IssueData) => openForEdit(row),
},
{
label: "Delete",
icon: Trash,
onClick: (row: IssueData) => {
console.log("Delete", row.issueId);
},
},
],
},
};
// ── Render ────────────────────────────────────────────────────
return (
<>
<DataTable
columns={columns}
data={data}
extraParams={extraParams}
loading={loading}
/>
{selectedIssue && (
<EditIssueModal
open={editOpen}
onClose={() => {
setEditOpen(false);
setSelectedIssue(null);
}}
issueData={selectedIssue}
onSave={handleEditSave}
/>
)}
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
<DialogContent className="max-w-6xl! w-full">
<DialogHeader>
<DialogTitle>Add New Issue</DialogTitle>
</DialogHeader>
<IssueForm
projectIdentifier={projectIdentifier}
onSubmit={handleCreateSubmit}
/>
</DialogContent>
</Dialog>
</>
);
}