diff --git a/app/page.module.css b/app/page.module.css
index d845868..29ec808 100644
--- a/app/page.module.css
+++ b/app/page.module.css
@@ -1,8 +1,14 @@
.main {
display: flex;
flex-direction: column;
- gap: 16px;
+ gap: 32px;
align-items: center;
- padding: 6rem;
+ padding: 2rem;
min-height: 100vh;
}
+
+.list {
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+}
diff --git a/app/page.tsx b/app/page.tsx
index 430f374..5b975a9 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,48 +1,48 @@
import Navigation from "@/components/navigation";
import styles from "./page.module.css";
-import { PlainClient } from "@team-plain/typescript-sdk";
+import { plainClient } from "@/utils/plainClient";
+import { ThreadRow } from "@/components/threadRow";
+import { PaginationControls } from "@/components/paginationControls";
export const fetchCache = "force-no-store";
-const apiKey = process.env.PLAIN_API_KEY;
-if (!apiKey) {
- throw new Error("Please set the `PLAIN_API_KEY` environment variable");
-}
-
-export const client = new PlainClient({
- apiKey,
-});
+// When adapting this example get the tenant id as part of auth or fetch it afterwards
+const TENANT_EXTERNAL_ID = "abcd1234";
export default async function Home({
- params,
- searchParams,
+ searchParams,
}: {
- params: { slug: string };
- searchParams: { [key: string]: string | string[] | undefined };
+ searchParams: { [key: string]: string | undefined };
}) {
- const threads = await client.getThreads({
- filters: {
- // customerIds: ["c_01J28ZQKJX9CVRXVHBMAXNSV5G"],
- tenantIdentifiers: [{ tenantId: "te_01J299SM3E25EJHT7JKYS6G7K5" }],
- },
- });
-
- console.log(threads.data?.threads.length);
+ const threads = await plainClient.getThreads({
+ filters: {
+ // If you want to only allow customers to view threads they have raised then you can filter by customerIds instead.
+ // Note that if you provide multiple filters they are combined with AND rather than OR.
+ // customerIds: ["c_01J28ZQKJX9CVRXVHBMAXNSV5G"],
+ tenantIdentifiers: [{ externalId: TENANT_EXTERNAL_ID }],
+ },
+ after: searchParams.after as string | undefined,
+ before: searchParams.before as string | undefined,
+ });
- return (
- <>
-
-
-
- {threads.data?.threads.map((thread) => {
- return (
-
- );
- })}
-
-
- >
- );
+ return (
+ <>
+
+
+ Support requests
+ {threads.data && (
+ <>
+
+ {threads.data?.threads.map((thread) => {
+ return (
+
+ );
+ })}
+
+
+ >
+ )}
+
+ >
+ );
}
diff --git a/app/thread/[threadId]/page.tsx b/app/thread/[threadId]/page.tsx
index 8d4f3ec..ae5fcab 100644
--- a/app/thread/[threadId]/page.tsx
+++ b/app/thread/[threadId]/page.tsx
@@ -115,9 +115,6 @@ export default async function ThreadPage({
},
})
.then((res) => res.json())
- .catch((err) => {
- console.log(err);
- });
const thread = data.data.thread;
const timelineEntries = thread.timelineEntries;
diff --git a/components/navigation.tsx b/components/navigation.tsx
index 536dd20..65122fb 100644
--- a/components/navigation.tsx
+++ b/components/navigation.tsx
@@ -1,19 +1,19 @@
import styles from "./navigation.module.css";
export default function Navigation({
- hasBackButton = false,
- title,
+ hasBackButton = false,
+ title,
}: {
- hasBackButton?: boolean;
- title: string;
+ hasBackButton?: boolean;
+ title: string;
}) {
- return (
-
- {hasBackButton && < Go back }
- {title}
-
- );
+ return (
+
+ {hasBackButton && < Go back }
+ {title}
+
+ );
}
diff --git a/components/paginationControls.module.css b/components/paginationControls.module.css
new file mode 100644
index 0000000..2b97d5d
--- /dev/null
+++ b/components/paginationControls.module.css
@@ -0,0 +1,4 @@
+.pageWrapper {
+ display: flex;
+ gap: 8px
+}
\ No newline at end of file
diff --git a/components/paginationControls.tsx b/components/paginationControls.tsx
new file mode 100644
index 0000000..beb270e
--- /dev/null
+++ b/components/paginationControls.tsx
@@ -0,0 +1,37 @@
+"use client";
+import { PageInfoPartsFragment } from "@team-plain/typescript-sdk";
+import { usePathname, useRouter } from "next/navigation";
+import styles from "./paginationControls.module.css";
+
+export function PaginationControls({
+ pageInfo,
+}: {
+ pageInfo: PageInfoPartsFragment;
+}) {
+ const router = useRouter();
+ const pathname = usePathname();
+ return (
+
+ {
+ if (pageInfo.startCursor) {
+ router.push(`${pathname}?before=${pageInfo.startCursor}`);
+ }
+ }}
+ disabled={!pageInfo.hasPreviousPage}
+ >
+ Previous page
+
+ {
+ if (pageInfo.endCursor) {
+ router.push(`${pathname}?after=${pageInfo.endCursor}`);
+ }
+ }}
+ disabled={!pageInfo.hasNextPage}
+ >
+ Next page
+
+
+ );
+}
diff --git a/components/threadRow.module.css b/components/threadRow.module.css
new file mode 100644
index 0000000..901272d
--- /dev/null
+++ b/components/threadRow.module.css
@@ -0,0 +1,5 @@
+.row {
+ display: flex;
+ gap: 16px;
+ align-items: 'center';
+}
\ No newline at end of file
diff --git a/components/threadRow.tsx b/components/threadRow.tsx
new file mode 100644
index 0000000..c2da812
--- /dev/null
+++ b/components/threadRow.tsx
@@ -0,0 +1,13 @@
+import { plainClient } from "@/utils/plainClient";
+import { ThreadPartsFragment } from "@team-plain/typescript-sdk";
+import styles from './threadRow.module.css';
+
+export async function ThreadRow({ thread }: { thread: ThreadPartsFragment }) {
+ const customer = await plainClient.getCustomerById({ customerId: thread.customer.id });
+
+ return (
+
+ {customer.data?.fullName}
{thread.title} {thread.previewText}
+
+ )
+}
\ No newline at end of file
diff --git a/utils/createdBy.ts b/utils/createdBy.ts
new file mode 100644
index 0000000..e69de29
diff --git a/utils/plainClient.ts b/utils/plainClient.ts
new file mode 100644
index 0000000..9cd40cd
--- /dev/null
+++ b/utils/plainClient.ts
@@ -0,0 +1,10 @@
+import { PlainClient } from "@team-plain/typescript-sdk";
+
+const apiKey = process.env.PLAIN_API_KEY;
+if (!apiKey) {
+ throw new Error("Please set the `PLAIN_API_KEY` environment variable");
+}
+
+export const plainClient = new PlainClient({
+ apiKey,
+});
\ No newline at end of file