feat(feedback): add feedback button to tenders table

This commit introduces the ability for users to navigate to a feedback page directly from the tenders list.

A new feedback icon and a corresponding button have been added to the actions column of the tenders table. Clicking this button redirects the user to the feedback page associated with that specific tender.

To support this feature, the following changes were made:
- Added a new `FeedbackIcon` SVG component.
- Defined API endpoints and created query hooks for the feedback module.
- Fixed a query key inconsistency for company details to ensure data is correctly refetched after updates.
This commit is contained in:
AmirReza Jamali
2025-09-23 11:16:02 +03:30
parent 0abfdde285
commit 1d944739bc
15 changed files with 237 additions and 7 deletions
@@ -0,0 +1,83 @@
"use client";
import { ExclamationIcon } from "@/assets/icons";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
} from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton";
import { unixToDate } from "@/utils/shared";
import { TableRow } from "../../../ui/table";
import useTenderFeedbackPresenter from "./useTenderFeedbackPresenter";
import { cn } from "@/lib/utils";
interface IProps {
id: string;
}
const TenderFeedbackTable = ({ id }: IProps) => {
const { feedback, isLoading, columns, pathName, router } =
useTenderFeedbackPresenter({ id });
return (
<div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
<Table>
<TableHeader>
<TableRow>
{columns.map((column) => (
<TableHead className="capitalize" key={column} colSpan={100}>
{column}
</TableHead>
))}
</TableRow>
</TableHeader>
{isLoading && <TableSkeleton column={columns.length} />}
<TableBody>
{feedback?.map((item, index) =>
!item ? (
<h6 key={index}>No feedback is submitted for this tender</h6>
) : (
<TableRow
key={item.id}
className="odd:bg-gray-2 dark:odd:bg-gray-7"
>
<TableCell className="text-start" colSpan={100}>
{index + 1}
</TableCell>
<TableCell className="uppercase" colSpan={100}>
{item.feedback_type}
</TableCell>
<TableCell className="uppercase" colSpan={100}>
{unixToDate(item.updated_at)}
</TableCell>
<TableCell className="uppercase" colSpan={100}>
{item?.tender?.title ?? "-"}
</TableCell>
<TableCell className="uppercase" colSpan={100}>
{unixToDate(item.created_at)}
</TableCell>
<TableCell
className={cn(`text flex gap-2 capitalize`)}
colSpan={100}
>
<button
className="text-gray-40 rounded-full bg-gray-dark bg-opacity-5 hover:text-green-dark dark:bg-gray dark:bg-opacity-5"
onClick={() => {
router.push(`${pathName}/${item.id}`);
}}
>
<ExclamationIcon />
</button>
</TableCell>
</TableRow>
),
)}
</TableBody>
</Table>
</div>
);
};
export default TenderFeedbackTable;
@@ -0,0 +1,20 @@
"use client";
import { useGetFeedback } from "@/hooks/queries";
import { usePathname, useRouter } from "next/navigation";
const useTenderFeedbackPresenter = ({ id }: { id: string }) => {
const { data, isLoading } = useGetFeedback({ tender_id: id });
const router = useRouter();
const pathName = usePathname();
const columns = [
"row",
"feedback type",
"updated at",
"tender name",
"created at",
"actions",
];
return { feedback: data?.data, isLoading, columns, pathName, router };
};
export default useTenderFeedbackPresenter;
+12 -2
View File
@@ -11,7 +11,7 @@ import {
} from "@/components/ui/table";
import useTenderListPresenter from "./useTenderListPresenter";
import { ExclamationIcon } from "@/assets/icons";
import { ExclamationIcon, FeedbackIcon } from "@/assets/icons";
import Pagination from "@/components/ui/pagination";
import TableSkeleton from "@/components/ui/TableSkeleton";
import { cn } from "@/lib/utils";
@@ -65,7 +65,10 @@ const TendersTable = () => {
<TableCell className={cn(`text capitalize`)} colSpan={100}>
<Status status={item.status}>{item.status}</Status>
</TableCell>
<TableCell className={cn(`text capitalize`)} colSpan={100}>
<TableCell
className={cn(`text flex gap-2 capitalize`)}
colSpan={100}
>
<button
className="text-gray-40 rounded-full bg-gray-dark bg-opacity-5 hover:text-green-dark dark:bg-gray dark:bg-opacity-5"
onClick={() => {
@@ -74,6 +77,13 @@ const TendersTable = () => {
>
<ExclamationIcon />
</button>
<button
onClick={() => {
router.push(`${pathName}/feedback/${item.id}`);
}}
>
<FeedbackIcon />
</button>
</TableCell>
</TableRow>
),
@@ -528,7 +528,6 @@ const CreateCompany = ({ defaultValues, editMode, id }: IProps) => {
</div>
<FormFooter />
</form>
);
};