feat(tender-details): enhance tender details page with improved layout and error handling

- Added SectionHeading and ExternalLinkIcon components for better structure and visual appeal.
- Improved error handling UI when tender data fails to load, providing user-friendly messages and navigation options.
- Refactored ShowcaseSection to accept additional className and rootClassName props for more flexible styling.
- Updated TendersTable to streamline action buttons and improve layout consistency.
This commit is contained in:
AmirReza Jamali
2026-05-02 10:05:48 +03:30
parent 73d11ac72b
commit 37c4053a6c
4 changed files with 252 additions and 117 deletions
+11 -3
View File
@@ -4,16 +4,24 @@ import type { ReactNode } from "react";
type PropsType = {
title?: string | ReactNode;
children: ReactNode;
/** Merges into the padded content wrapper below the title */
className?: string;
/** Merges into the outer card (e.g. `h-full flex flex-col` for grid rows) */
rootClassName?: string;
};
export function ShowcaseSection({ title, children, className }: PropsType) {
export function ShowcaseSection({ title, children, className, rootClassName }: PropsType) {
return (
<div className="relative overflow-hidden rounded-2xl border border-stroke/70 bg-gradient-to-br from-white via-white to-primary/[0.03] shadow-theme-xs dark:border-dark-3 dark:from-gray-dark dark:via-gray-dark dark:to-primary/[0.08]">
<div
className={cn(
"relative overflow-hidden rounded-2xl border border-stroke/70 bg-gradient-to-br from-white via-white to-primary/[0.03] shadow-theme-xs dark:border-dark-3 dark:from-gray-dark dark:via-gray-dark dark:to-primary/[0.08]",
rootClassName,
)}
>
<div className="pointer-events-none absolute -right-12 -top-12 h-32 w-32 rounded-full bg-primary/10 blur-3xl dark:bg-primary/20" />
<div className="pointer-events-none absolute -bottom-12 -left-12 h-32 w-32 rounded-full bg-purple-500/10 blur-3xl dark:bg-purple-500/20" />
{title && (
<h2 className="border-b border-stroke/70 bg-white/70 px-4 py-4 text-base font-semibold text-dark backdrop-blur-sm dark:border-dark-3 dark:bg-dark-2/40 dark:text-white sm:px-6 xl:px-7.5">
<h2 className="shrink-0 border-b border-stroke/70 bg-white/70 px-4 py-4 text-base font-semibold text-dark backdrop-blur-sm dark:border-dark-3 dark:bg-dark-2/40 dark:text-white sm:px-6 xl:px-7.5">
{title}
</h2>
)}
+30 -41
View File
@@ -24,7 +24,6 @@ import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip";
import { cn } from "@/lib/utils";
import { getPaginatedRowNumber } from "@/utils/shared";
import Link from "next/link";
import TenderListFilters from "./TenderListFilters";
const TendersTable = () => {
const {
@@ -89,49 +88,39 @@ const TendersTable = () => {
{item.country_code}
</TableCell>
<TableCell className={cn(`text capitalize`)} colSpan={100}>
{item.submission_url ? (
<Link target="_blank" href={item.submission_url}>
{item.submission_url}
</Link>
) : (
"-"
)}
</TableCell>
<TableCell className={cn(`text capitalize`)} colSpan={100}>
<Status status={item.status}>{item.status}</Status>
</TableCell>
<TableCell
className={cn(`text flex gap-2 capitalize`)}
colSpan={100}
>
<button
data-tooltip-id="details"
data-tooltip-content="Details"
data-tooltip-place="top"
onClick={() => {
router.push(`${pathName}/${item.id}`);
}}
>
<Tooltip
{..._TooltipDefaultParams({
id: "details",
})}
/>
<EyeIcon />
</button>
<button
data-tooltip-id="feedback"
data-tooltip-content="Feedback"
data-tooltip-place="top"
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}/feedback/${item.id}`);
}}
>
<Tooltip {..._TooltipDefaultParams({ id: "feedback" })} />
<ExclamationIcon />
</button>
<TableCell className="capitalize" colSpan={100}>
<div className="flex items-center gap-2">
<button
data-tooltip-id="details"
data-tooltip-content="Details"
data-tooltip-place="top"
onClick={() => {
router.push(`${pathName}/${item.id}`);
}}
>
<Tooltip
{..._TooltipDefaultParams({
id: "details",
})}
/>
<EyeIcon />
</button>
<button
data-tooltip-id="feedback"
data-tooltip-content="Feedback"
data-tooltip-place="top"
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}/feedback/${item.id}`);
}}
>
<Tooltip {..._TooltipDefaultParams({ id: "feedback" })} />
<ExclamationIcon />
</button>
</div>
</TableCell>
</TableRow>
))}
@@ -57,7 +57,6 @@ const useTenderListPresenter = () => {
"row",
"title",
"country code",
"submission url",
"status",
"actions",
];