Skip to content

Commit b9c3ccd

Browse files
author
Elise Bach
committed
Cleaned up + type + use rawRequest
1 parent 0c9d17b commit b9c3ccd

File tree

9 files changed

+281
-129
lines changed

9 files changed

+281
-129
lines changed

app/page.tsx

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Navigation from "@/components/navigation";
22
import styles from "./page.module.css";
3-
import { plainClient } from "@/utils/plainClient";
3+
import { plainClient } from "@/lib/plainClient";
44
import { ThreadRow } from "@/components/threadRow";
55
import { PaginationControls } from "@/components/paginationControls";
66

@@ -10,39 +10,39 @@ export const fetchCache = "force-no-store";
1010
const TENANT_EXTERNAL_ID = "abcd1234";
1111

1212
export default async function Home({
13-
searchParams,
13+
searchParams,
1414
}: {
15-
searchParams: { [key: string]: string | undefined };
15+
searchParams: { [key: string]: string | undefined };
1616
}) {
17-
const threads = await plainClient.getThreads({
18-
filters: {
19-
// If you want to only allow customers to view threads they have raised then you can filter by customerIds instead.
20-
// Note that if you provide multiple filters they are combined with AND rather than OR.
21-
// customerIds: ["c_01J28ZQKJX9CVRXVHBMAXNSV5G"],
22-
tenantIdentifiers: [{ externalId: TENANT_EXTERNAL_ID }],
23-
},
24-
after: searchParams.after as string | undefined,
25-
before: searchParams.before as string | undefined,
26-
});
17+
const threads = await plainClient.getThreads({
18+
filters: {
19+
// If you want to only allow customers to view threads they have raised then you can filter by customerIds instead.
20+
// Note that if you provide multiple filters they are combined with AND rather than OR.
21+
// customerIds: ["c_01J28ZQKJX9CVRXVHBMAXNSV5G"],
22+
tenantIdentifiers: [{ externalId: TENANT_EXTERNAL_ID }],
23+
},
24+
after: searchParams.after as string | undefined,
25+
before: searchParams.before as string | undefined,
26+
});
2727

28-
return (
29-
<>
30-
<Navigation title="Plain Headless Portal example" />
31-
<main className={styles.main}>
32-
<h2>Support requests</h2>
33-
{threads.data && (
34-
<>
35-
<div className={styles.list}>
36-
{threads.data?.threads.map((thread) => {
37-
return (
38-
<ThreadRow thread={thread} key={`thread-row-${thread.id}`} />
39-
);
40-
})}
41-
</div>
42-
<PaginationControls pageInfo={threads.data.pageInfo} />
43-
</>
44-
)}
45-
</main>
46-
</>
47-
);
28+
return (
29+
<>
30+
<Navigation title="Plain Headless Portal example" />
31+
<main className={styles.main}>
32+
<h2>Support requests</h2>
33+
{threads.data && (
34+
<>
35+
<div className={styles.list}>
36+
{threads.data?.threads.map((thread) => {
37+
return (
38+
<ThreadRow thread={thread} key={`thread-row-${thread.id}`} />
39+
);
40+
})}
41+
</div>
42+
<PaginationControls pageInfo={threads.data.pageInfo} />
43+
</>
44+
)}
45+
</main>
46+
</>
47+
);
4848
}

app/thread/[threadId]/page.tsx

Lines changed: 22 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,28 @@
11
import Navigation from "@/components/navigation";
22
import styles from "./page.module.css";
3-
import { getActorFullName } from "@/utils/getActorFullName";
4-
import { getFormattedDate } from "@/utils/getFormattedDate";
5-
import { getPriority } from "@/utils/getPriority";
3+
import { getActorFullName } from "@/lib/getActorFullName";
4+
import { getFormattedDate } from "@/lib/getFormattedDate";
5+
import { getPriority } from "@/lib/getPriority";
6+
import { fetchThreadTimelineEntries } from "@/lib/fetchThreadTimelineEntries";
7+
import { plainClient } from "@/lib/plainClient";
68

7-
export default async function ThreadPage() {
8-
const data = await fetch("https://core-api.uk.plain.com/graphql/v1", {
9-
method: "POST",
10-
body: JSON.stringify({
11-
query: `{
12-
thread(threadId: "th_01J299WQGA3VNQ4FDECV7JK6MC") {
13-
title
14-
description
15-
priority
16-
status
17-
createdAt {
18-
iso8601
19-
}
20-
createdBy {
21-
__typename
22-
... on UserActor {
23-
user {
24-
fullName
25-
}
26-
}
27-
... on CustomerActor {
28-
customer {
29-
fullName
30-
}
31-
}
32-
... on MachineUserActor {
33-
machineUser {
34-
fullName
35-
}
36-
}
37-
}
38-
updatedAt {
39-
iso8601
40-
}
41-
timelineEntries {
42-
edges {
43-
node {
44-
id
45-
timestamp {
46-
iso8601
47-
}
48-
actor {
49-
__typename
50-
... on UserActor {
51-
user {
52-
fullName
53-
}
54-
}
55-
... on CustomerActor {
56-
customer {
57-
fullName
58-
}
59-
}
60-
... on MachineUserActor {
61-
machineUser {
62-
fullName
63-
}
64-
}
65-
}
66-
entry {
67-
__typename
68-
... on CustomEntry {
69-
title
70-
components {
71-
__typename
72-
... on ComponentText {
73-
text
74-
}
75-
}
76-
}
77-
... on ChatEntry {
78-
chatId
79-
text
80-
}
81-
}
82-
}
83-
}
84-
}
85-
}
86-
}`,
87-
}),
88-
headers: {
89-
"Content-Type": "application/json",
90-
"Plain-Workspace-Id": "w_01J28VHKDK5PV3DJSZAA01XGAN",
91-
Authorization: `Bearer ${process.env.PLAIN_API_KEY}`,
92-
},
93-
}).then((res) => res.json());
9+
export default async function ThreadPage({
10+
params,
11+
}: {
12+
params: { threadId: string };
13+
}) {
14+
const threadId = params.threadId;
9415

95-
const thread = data.data.thread;
16+
const { data } = await fetchThreadTimelineEntries({
17+
threadId,
18+
first: 100,
19+
});
20+
21+
if (!data) {
22+
return null;
23+
}
24+
25+
const thread = data.thread;
9626
const timelineEntries = thread.timelineEntries;
9727

9828
return (
@@ -140,7 +70,7 @@ export default async function ThreadPage() {
14070
);
14171
}
14272

143-
return <div key={`comp_${idx}`}>TODO</div>;
73+
return null;
14474
})}
14575
{entry.entry.__typename === "ChatEntry" && (
14676
<div>{entry.entry.text}</div>

components/threadRow.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { plainClient } from "@/utils/plainClient";
1+
import { plainClient } from "@/lib/plainClient";
22
import type { ThreadPartsFragment } from "@team-plain/typescript-sdk";
33
import styles from "./threadRow.module.css";
44

lib/fetchThreadTimelineEntries.ts

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import type { PlainSDKError } from "@team-plain/typescript-sdk";
2+
import { plainClient } from "./plainClient";
3+
import type { ThreadTimelineResult } from "./types";
4+
5+
export async function fetchThreadTimelineEntries({
6+
threadId,
7+
first,
8+
after,
9+
last,
10+
before,
11+
}: {
12+
threadId: string;
13+
first?: number;
14+
after?: string;
15+
last?: number;
16+
before?: string;
17+
}): Promise<{
18+
data: ThreadTimelineResult;
19+
error: PlainSDKError | undefined;
20+
}> {
21+
const query = `
22+
query threadTimeline($threadId: ID!, $first: Int, $after: String, $last: Int, $before: String) {
23+
thread(threadId: $threadId) {
24+
title
25+
description
26+
priority
27+
status
28+
createdAt {
29+
__typename
30+
iso8601
31+
}
32+
createdBy {
33+
__typename
34+
... on UserActor {
35+
user {
36+
fullName
37+
}
38+
}
39+
... on CustomerActor {
40+
customer {
41+
fullName
42+
}
43+
}
44+
... on MachineUserActor {
45+
machineUser {
46+
fullName
47+
}
48+
}
49+
}
50+
updatedAt {
51+
__typename
52+
iso8601
53+
}
54+
timelineEntries(first: $first, after: $after, last: $last, before: $before) {
55+
edges {
56+
cursor
57+
node {
58+
id
59+
timestamp {
60+
__typename
61+
iso8601
62+
}
63+
actor {
64+
__typename
65+
... on UserActor {
66+
user {
67+
fullName
68+
}
69+
}
70+
... on CustomerActor {
71+
customer {
72+
fullName
73+
}
74+
}
75+
... on MachineUserActor {
76+
machineUser {
77+
fullName
78+
}
79+
}
80+
}
81+
entry {
82+
__typename
83+
... on CustomEntry {
84+
title
85+
components {
86+
__typename
87+
... on ComponentText {
88+
text
89+
}
90+
}
91+
}
92+
... on ChatEntry {
93+
chatId
94+
text
95+
}
96+
}
97+
}
98+
}
99+
pageInfo {
100+
__typename
101+
hasPreviousPage
102+
hasNextPage
103+
startCursor
104+
endCursor
105+
}
106+
}
107+
}
108+
}
109+
`;
110+
111+
const result = plainClient.rawRequest({
112+
query,
113+
variables: {
114+
threadId,
115+
first,
116+
after,
117+
last,
118+
before,
119+
},
120+
});
121+
122+
const data = (await result).data as ThreadTimelineResult;
123+
const error = (await result).error;
124+
125+
return { data, error };
126+
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
export function getActorFullName(actor) {
1+
import type { Actor } from "./types";
2+
3+
export function getActorFullName(actor: Actor) {
24
switch (actor.__typename) {
35
case "CustomerActor": {
46
return actor.customer.fullName;
@@ -7,7 +9,7 @@ export function getActorFullName(actor) {
79
return actor.user.fullName;
810
}
911
case "MachineUserActor": {
10-
return actor.user.fullName;
12+
return actor.machineUser.fullName;
1113
}
1214
}
1315
}
File renamed without changes.

utils/getPriority.ts renamed to lib/getPriority.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export function getPriority(priority: 0 | 1 | 2 | 3) {
1+
export function getPriority(priority: number) {
22
switch (priority) {
33
case 0: {
44
return "Urgent";
@@ -12,5 +12,8 @@ export function getPriority(priority: 0 | 1 | 2 | 3) {
1212
case 3: {
1313
return "Low";
1414
}
15+
default: {
16+
return "Normal";
17+
}
1518
}
1619
}
File renamed without changes.

0 commit comments

Comments
 (0)