chore: update app version and enhance UI components
- Bumped NEXT_PUBLIC_APP_VERSION to 2.0.3 for the latest release. - Improved Cypress test for customer feedback page to handle delayed route transitions. - Refactored CompanyDetailsPage to enhance layout and added new components for better structure. - Updated TenderDetails to conditionally render location and currency information based on validity checks. - Added data-cy attributes to various form elements and tables for improved testing capabilities.
This commit is contained in:
@@ -2,20 +2,56 @@
|
||||
import Loading from "@/components/loading";
|
||||
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
|
||||
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
|
||||
import IsVisible from "@/components/ui/IsVisible";
|
||||
import Status from "@/components/ui/Status";
|
||||
import { useCompanyDetails } from "@/hooks/queries";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { BreadcrumbItem } from "@/types/shared";
|
||||
import { formatPhoneNumber, unixToDate } from "@/utils/shared";
|
||||
import getSymbolFromCurrency from "currency-symbol-map";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { use } from "react";
|
||||
|
||||
interface IProps {
|
||||
params: Promise<{ id: string }>;
|
||||
}
|
||||
|
||||
function SectionHeading({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="mb-4 flex items-center gap-3">
|
||||
<span className="h-px flex-1 bg-gradient-to-r from-stroke/0 via-stroke/80 to-stroke/0 dark:from-dark-3/0 dark:via-dark-3 dark:to-dark-3/0" />
|
||||
<h2 className="shrink-0 text-[11px] font-semibold uppercase tracking-[0.2em] text-dark-5 dark:text-dark-6">
|
||||
{children}
|
||||
</h2>
|
||||
<span className="h-px flex-1 bg-gradient-to-l from-stroke/0 via-stroke/80 to-stroke/0 dark:from-dark-3/0 dark:via-dark-3 dark:to-dark-3/0" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ExternalLinkIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
className={cn("h-4 w-4 shrink-0", className)}
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
strokeWidth={2}
|
||||
aria-hidden
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
const SHOWCASE_CENTERED_BODY = {
|
||||
rootClassName: "flex h-full min-h-0 flex-col",
|
||||
className:
|
||||
"flex min-h-0 flex-1 flex-col items-center justify-center text-center",
|
||||
} as const;
|
||||
|
||||
const CompanyDetailsPage = ({ params }: IProps) => {
|
||||
const { id } = use(params);
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
@@ -33,8 +69,9 @@ const CompanyDetailsPage = ({ params }: IProps) => {
|
||||
},
|
||||
];
|
||||
const { data, isLoading } = useCompanyDetails(id);
|
||||
const router = useRouter();
|
||||
if (isLoading) return <Loading />;
|
||||
const company = data.data;
|
||||
const website = company.website?.trim();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -42,71 +79,142 @@ const CompanyDetailsPage = ({ params }: IProps) => {
|
||||
|
||||
<ShowcaseSection
|
||||
title={
|
||||
<div className="flex justify-between">
|
||||
<strong>{data.data.name}</strong>
|
||||
<Status status={data?.data?.status}>{data.data.status}</Status>
|
||||
<div className="flex flex-col gap-5 lg:flex-row lg:items-start lg:justify-between">
|
||||
<div className="min-w-0 space-y-2">
|
||||
<p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-primary">
|
||||
Company
|
||||
</p>
|
||||
<h1 className="text-balance text-xl font-bold leading-tight text-dark dark:text-white sm:text-2xl lg:text-[1.65rem]">
|
||||
{company.name}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="flex shrink-0 flex-col gap-3 sm:flex-row sm:items-center sm:justify-end">
|
||||
<Status status={company.status}>{company.status}</Status>
|
||||
{website && (
|
||||
<Link
|
||||
href={website}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="shadow-theme-xs inline-flex items-center justify-center gap-2 rounded-xl bg-primary px-4 py-2.5 text-sm font-medium text-white transition hover:bg-primary/90 hover:shadow-md"
|
||||
>
|
||||
<span>Visit website</span>
|
||||
<ExternalLinkIcon className="opacity-90" />
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
className="!p-0"
|
||||
>
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
<ShowcaseSection title={"Currency"}>
|
||||
<strong>
|
||||
{`${data?.data?.currency} ${getSymbolFromCurrency(data?.data.currency ?? "USD")}`}
|
||||
</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Language"}>
|
||||
<strong className="uppercase">{data?.data?.language}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Created At"}>
|
||||
<strong>{unixToDate({ unix: data?.data?.created_at })}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Annual revenue"}>
|
||||
<strong>{data?.data?.annual_revenue}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Email"}>
|
||||
<strong>{data?.data?.email}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Employee count"}>
|
||||
<strong>{data?.data?.employee_count}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Founded Year"}>
|
||||
<strong>{data?.data?.founded_year}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Industry"}>
|
||||
<strong>{data?.data?.industry}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Is Compliant"}>
|
||||
<strong>{data?.data?.is_compliant ? "Yes" : "No"}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Is Verified"}>
|
||||
<strong>{data?.data?.is_verified ? "Yes" : "No"}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Phone"}>
|
||||
<strong>{formatPhoneNumber(data?.data?.phone ?? 0)}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Registration Number"}>
|
||||
<strong>{data?.data?.registration_number}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Tax id"}>
|
||||
<strong>{data?.data?.tax_id}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Type"}>
|
||||
<strong>{data?.data?.type}</strong>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title={"Updated at"}>
|
||||
<strong>{unixToDate({ unix: data?.data?.updated_at ?? 0 })}</strong>
|
||||
</ShowcaseSection>
|
||||
<IsVisible condition={!!data.data.website}>
|
||||
<ShowcaseSection title={"Website"}>
|
||||
<Link
|
||||
href={data.data.website}
|
||||
className="font-bold"
|
||||
target="_blank"
|
||||
<div className="space-y-10 px-4 pb-8 pt-2 sm:px-6 sm:pb-10 xl:px-10">
|
||||
<div>
|
||||
<SectionHeading>Profile</SectionHeading>
|
||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
<ShowcaseSection title="Industry" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{company.industry || "—"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Type" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{company.type || "—"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Language" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium uppercase text-dark dark:text-white">
|
||||
{company.language || "—"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Founded year" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{company.founded_year || "—"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<SectionHeading>Business</SectionHeading>
|
||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
<ShowcaseSection title="Currency" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{`${company.currency || "—"} ${getSymbolFromCurrency(company.currency ?? "USD")}`}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Annual revenue" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{company.annual_revenue || "—"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Employee count" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{company.employee_count || "—"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection
|
||||
title="Registration number"
|
||||
{...SHOWCASE_CENTERED_BODY}
|
||||
>
|
||||
{data.data.website}
|
||||
</Link>
|
||||
</ShowcaseSection>
|
||||
</IsVisible>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{company.registration_number || "—"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Tax ID" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{company.tax_id || "—"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Compliant" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{company.is_compliant ? "Yes" : "No"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Verified" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{company.is_verified ? "Yes" : "No"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<SectionHeading>Contact & timeline</SectionHeading>
|
||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
<ShowcaseSection title="Email" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="break-all font-medium text-dark dark:text-white">
|
||||
{company.email || "—"}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Phone" {...SHOWCASE_CENTERED_BODY}>
|
||||
<span className="font-medium text-dark dark:text-white">
|
||||
{formatPhoneNumber(company.phone ?? 0)}
|
||||
</span>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Created at" {...SHOWCASE_CENTERED_BODY}>
|
||||
<time className="font-medium tabular-nums text-dark dark:text-white">
|
||||
{unixToDate({ unix: company.created_at })}
|
||||
</time>
|
||||
</ShowcaseSection>
|
||||
<ShowcaseSection title="Updated at" {...SHOWCASE_CENTERED_BODY}>
|
||||
<time className="font-medium tabular-nums text-dark dark:text-white">
|
||||
{unixToDate({ unix: company.updated_at ?? 0 })}
|
||||
</time>
|
||||
</ShowcaseSection>
|
||||
{website && (
|
||||
<ShowcaseSection title="Website" {...SHOWCASE_CENTERED_BODY}>
|
||||
<Link
|
||||
href={website}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex max-w-full items-center gap-1.5 break-all font-medium text-primary underline-offset-4 hover:underline"
|
||||
>
|
||||
<ExternalLinkIcon className="shrink-0" />
|
||||
{website}
|
||||
</Link>
|
||||
</ShowcaseSection>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ShowcaseSection>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user