mirror of
https://github.com/hanzoai/dataroom.git
synced 2026-11-02 22:22:45 +00:00
124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
import ErrorPage from "next/error";
|
|
import Link from "next/link";
|
|
import { useRouter } from "next/router";
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { usePlan } from "@/lib/swr/use-billing";
|
|
import useViewer from "@/lib/swr/use-viewer";
|
|
|
|
import AppLayout from "@/components/layouts/app";
|
|
import {
|
|
Breadcrumb,
|
|
BreadcrumbItem,
|
|
BreadcrumbLink,
|
|
BreadcrumbList,
|
|
BreadcrumbPage,
|
|
BreadcrumbSeparator,
|
|
} from "@/components/ui/breadcrumb";
|
|
import { Separator } from "@/components/ui/separator";
|
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
import { ContactsDocumentsTable } from "@/components/visitors/contacts-document-table";
|
|
import { VisitorAvatar } from "@/components/visitors/visitor-avatar";
|
|
|
|
export default function VisitorDetailPage() {
|
|
const router = useRouter();
|
|
const { isFree, isTrial } = usePlan();
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
const [pageSize, setPageSize] = useState(10);
|
|
const [sortBy, setSortBy] = useState("lastViewed");
|
|
const [sortOrder, setSortOrder] = useState("desc");
|
|
|
|
const { viewer, durations, loadingDurations, error } = useViewer(
|
|
currentPage,
|
|
pageSize,
|
|
sortBy,
|
|
sortOrder,
|
|
);
|
|
const views = viewer?.views;
|
|
const pagination = viewer?.pagination;
|
|
const sorting = viewer?.sorting;
|
|
|
|
const handlePageChange = (page: number) => {
|
|
setCurrentPage(page);
|
|
};
|
|
|
|
const handlePageSizeChange = (size: number) => {
|
|
setPageSize(size);
|
|
setCurrentPage(1);
|
|
};
|
|
|
|
const handleSortChange = (newSortBy: string, newSortOrder: string) => {
|
|
setSortBy(newSortBy);
|
|
setSortOrder(newSortOrder);
|
|
setCurrentPage(1);
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (isFree && !isTrial) router.push("/documents");
|
|
}, [isTrial, isFree]);
|
|
|
|
if (error) {
|
|
return <ErrorPage statusCode={404} />;
|
|
}
|
|
|
|
return (
|
|
<AppLayout>
|
|
<div className="p-4 pb-0 sm:m-4 sm:py-4">
|
|
{viewer ? (
|
|
<section className="mb-4 flex flex-col justify-between md:mb-8 lg:mb-12">
|
|
<div className="mt-2 flex items-center gap-x-2">
|
|
<VisitorAvatar viewerEmail={viewer.email} />
|
|
|
|
<h2 className="text-xl font-semibold tracking-tight text-foreground sm:text-2xl">
|
|
{viewer.email}
|
|
</h2>
|
|
</div>
|
|
</section>
|
|
) : (
|
|
<VisitorDetailHeaderSkeleton />
|
|
)}
|
|
|
|
<Separator className="bg-gray-200 dark:bg-gray-800" />
|
|
</div>
|
|
|
|
<div className="relative p-4 pt-0 sm:mx-4 sm:mt-4">
|
|
<ContactsDocumentsTable
|
|
views={views}
|
|
durations={durations}
|
|
loadingDurations={loadingDurations}
|
|
pagination={pagination}
|
|
sorting={sorting}
|
|
onPageChange={handlePageChange}
|
|
onPageSizeChange={handlePageSizeChange}
|
|
onSortChange={handleSortChange}
|
|
/>
|
|
</div>
|
|
</AppLayout>
|
|
);
|
|
}
|
|
|
|
const VisitorDetailHeaderSkeleton = () => {
|
|
return (
|
|
<section className="mb-4 flex flex-col justify-between md:mb-8 lg:mb-12">
|
|
<Breadcrumb className="hidden md:flex">
|
|
<BreadcrumbList>
|
|
<BreadcrumbItem>
|
|
<BreadcrumbLink asChild>
|
|
<Link href="/visitors">All Visitors</Link>
|
|
</BreadcrumbLink>
|
|
</BreadcrumbItem>
|
|
<BreadcrumbSeparator />
|
|
<BreadcrumbItem>
|
|
<Skeleton className="h-6 w-24 rounded-md" />
|
|
</BreadcrumbItem>
|
|
</BreadcrumbList>
|
|
</Breadcrumb>
|
|
<div className="mt-2 flex items-center gap-x-2">
|
|
<Skeleton className="hidden h-10 w-10 flex-shrink-0 rounded-full sm:inline-flex" />
|
|
<Skeleton className="h-8 w-48 rounded-md sm:w-64" />
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|