@@ -10,6 +10,7 @@ import ErrorBoundary from "./components/ErrorBoundary";
|
|||||||
import { ErrorPage } from "./pages/ErrorPage";
|
import { ErrorPage } from "./pages/ErrorPage";
|
||||||
import ConsoleLayout from "./layouts/ConsoleLayout";
|
import ConsoleLayout from "./layouts/ConsoleLayout";
|
||||||
import { RelayEnvironment } from "./RelayEnvironment";
|
import { RelayEnvironment } from "./RelayEnvironment";
|
||||||
|
import PeopleOverviewPage from "@/pages/PeopleOverviewPage";
|
||||||
|
|
||||||
posthog.init(process.env.POSTHOG_KEY!, {
|
posthog.init(process.env.POSTHOG_KEY!, {
|
||||||
api_host: process.env.POSTHOG_HOST,
|
api_host: process.env.POSTHOG_HOST,
|
||||||
@@ -80,6 +81,16 @@ function App() {
|
|||||||
</Suspense>
|
</Suspense>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path="/peoples/:peopleId"
|
||||||
|
element={
|
||||||
|
<Suspense>
|
||||||
|
<ErrorBoundaryWithLocation>
|
||||||
|
<PeopleOverviewPage />
|
||||||
|
</ErrorBoundaryWithLocation>
|
||||||
|
</Suspense>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/vendors"
|
path="/vendors"
|
||||||
element={
|
element={
|
||||||
|
|||||||
@@ -112,9 +112,10 @@ function PeopleListPageContent({
|
|||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{peoples.map((person) => (
|
{peoples.map((person) => (
|
||||||
<div
|
<Link
|
||||||
key={person?.id}
|
key={person?.id}
|
||||||
className="flex items-center justify-between p-4 rounded-lg border bg-card text-card-foreground shadow-sm"
|
to={`/peoples/${person?.id}`}
|
||||||
|
className="flex items-center justify-between p-4 rounded-lg border bg-card text-card-foreground shadow-sm hover:bg-accent/50"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<Avatar className="h-10 w-10">
|
<Avatar className="h-10 w-10">
|
||||||
@@ -180,7 +181,7 @@ function PeopleListPageContent({
|
|||||||
Delete
|
Delete
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Link>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div className="flex gap-2 justify-end mt-4">
|
<div className="flex gap-2 justify-end mt-4">
|
||||||
|
|||||||
144
apps/console/src/pages/PeopleOverviewPage.tsx
Normal file
144
apps/console/src/pages/PeopleOverviewPage.tsx
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
import {
|
||||||
|
graphql,
|
||||||
|
PreloadedQuery,
|
||||||
|
usePreloadedQuery,
|
||||||
|
useQueryLoader,
|
||||||
|
} from "react-relay";
|
||||||
|
import { Suspense, useEffect } from "react";
|
||||||
|
import type { PeopleOverviewPageQuery as PeopleOverviewPageQueryType } from "./__generated__/peopleOverviewPageQuery.graphql";
|
||||||
|
import { useParams } from "react-router";
|
||||||
|
import { Helmet } from "react-helmet-async";
|
||||||
|
import { useBreadcrumb } from "@/contexts/BreadcrumbContext";
|
||||||
|
|
||||||
|
const peopleOverviewPageQuery = graphql`
|
||||||
|
query PeopleOverviewPageQuery($peopleId: ID!) {
|
||||||
|
node(id: $peopleId) {
|
||||||
|
... on People {
|
||||||
|
id
|
||||||
|
fullName
|
||||||
|
primaryEmailAddress
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
function PeopleOverviewPageContent({
|
||||||
|
queryRef,
|
||||||
|
}: {
|
||||||
|
queryRef: PreloadedQuery<PeopleOverviewPageQueryType>;
|
||||||
|
}) {
|
||||||
|
const data = usePreloadedQuery(peopleOverviewPageQuery, queryRef);
|
||||||
|
const { setBreadcrumbSegment } = useBreadcrumb();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data.node?.primaryEmailAddress) {
|
||||||
|
setBreadcrumbSegment('peoples/:id', data.node.primaryEmailAddress);
|
||||||
|
}
|
||||||
|
}, [data.node?.primaryEmailAddress, setBreadcrumbSegment]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6 p-4 md:p-6 lg:p-8">
|
||||||
|
<div className="mx-auto max-w-4xl space-y-6">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h1 className="text-xl font-semibold text-gray-900">
|
||||||
|
{data.node?.fullName}
|
||||||
|
</h1>
|
||||||
|
<p className="text-gray-600">
|
||||||
|
View and manage person details
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h2 className="text-lg font-medium">Personal Information</h2>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
Basic information about the person
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div className="col-span-2">
|
||||||
|
<label className="text-sm font-medium text-gray-700">Full Name</label>
|
||||||
|
<p className="mt-1">{data.node?.fullName}</p>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-2">
|
||||||
|
<label className="text-sm font-medium text-gray-700">Email</label>
|
||||||
|
<p className="mt-1">{data.node?.primaryEmailAddress}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h2 className="text-lg font-medium">System Information</h2>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
System-related information about the person
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<label className="text-sm font-medium text-gray-700">Created At</label>
|
||||||
|
<p className="mt-1">{new Date(data.node?.createdAt).toLocaleString()}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="text-sm font-medium text-gray-700">Last Updated</label>
|
||||||
|
<p className="mt-1">{new Date(data.node?.updatedAt).toLocaleString()}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function PeopleOverviewPageFallback() {
|
||||||
|
return (
|
||||||
|
<div className="p-6 space-y-6">
|
||||||
|
<div className="space-y-1">
|
||||||
|
<div className="h-8 w-48 bg-muted animate-pulse rounded" />
|
||||||
|
<div className="h-4 w-96 bg-muted animate-pulse rounded" />
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
{[1, 2].map((i) => (
|
||||||
|
<div key={i} className="h-20 bg-muted animate-pulse rounded-lg" />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PeopleOverviewPage() {
|
||||||
|
const { peopleId } = useParams();
|
||||||
|
const [queryRef, loadQuery] = useQueryLoader<PeopleOverviewPageQueryType>(
|
||||||
|
peopleOverviewPageQuery,
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadQuery({ peopleId: peopleId! });
|
||||||
|
}, [loadQuery, peopleId]);
|
||||||
|
|
||||||
|
if (!queryRef) {
|
||||||
|
return <PeopleOverviewPageFallback />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Helmet>
|
||||||
|
<title>People Overview - Probo Console</title>
|
||||||
|
</Helmet>
|
||||||
|
<Suspense fallback={<PeopleOverviewPageFallback />}>
|
||||||
|
<PeopleOverviewPageContent queryRef={queryRef} />
|
||||||
|
</Suspense>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
164
apps/console/src/pages/__generated__/PeopleOverviewPageQuery.graphql.ts
generated
Normal file
164
apps/console/src/pages/__generated__/PeopleOverviewPageQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<ee2731bf27a12fb704f79cf4058e2d80>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type PeopleOverviewPageQuery$variables = {
|
||||||
|
peopleId: string;
|
||||||
|
};
|
||||||
|
export type PeopleOverviewPageQuery$data = {
|
||||||
|
readonly node: {
|
||||||
|
readonly createdAt?: any;
|
||||||
|
readonly fullName?: string;
|
||||||
|
readonly id?: string;
|
||||||
|
readonly primaryEmailAddress?: string;
|
||||||
|
readonly updatedAt?: any;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type PeopleOverviewPageQuery = {
|
||||||
|
response: PeopleOverviewPageQuery$data;
|
||||||
|
variables: PeopleOverviewPageQuery$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "peopleId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "id",
|
||||||
|
"variableName": "peopleId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v2 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v3 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "fullName",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v4 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "primaryEmailAddress",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v5 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "createdAt",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v6 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "updatedAt",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "PeopleOverviewPageQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v1/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
(v2/*: any*/),
|
||||||
|
(v3/*: any*/),
|
||||||
|
(v4/*: any*/),
|
||||||
|
(v5/*: any*/),
|
||||||
|
(v6/*: any*/)
|
||||||
|
],
|
||||||
|
"type": "People",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Query",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "PeopleOverviewPageQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v1/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__typename",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
(v2/*: any*/),
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/),
|
||||||
|
(v4/*: any*/),
|
||||||
|
(v5/*: any*/),
|
||||||
|
(v6/*: any*/)
|
||||||
|
],
|
||||||
|
"type": "People",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "0cd0dd96cb7a84c2016bfe1f088f8245",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "PeopleOverviewPageQuery",
|
||||||
|
"operationKind": "query",
|
||||||
|
"text": "query PeopleOverviewPageQuery(\n $peopleId: ID!\n) {\n node(id: $peopleId) {\n __typename\n ... on People {\n id\n fullName\n primaryEmailAddress\n createdAt\n updatedAt\n }\n id\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "16b3f0915f69d8475d745b0c7f13b029";
|
||||||
|
|
||||||
|
export default node;
|
||||||
Reference in New Issue
Block a user