From de595bbf515fee7c022b80aa6f7de7801b2c972e Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 27 Oct 2024 11:37:27 +0100 Subject: [PATCH 1/8] Avoid infinite loop by marking the component as server-side --- app/ui/guests/table.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/ui/guests/table.tsx b/app/ui/guests/table.tsx index 0f31a0c..d113e15 100644 --- a/app/ui/guests/table.tsx +++ b/app/ui/guests/table.tsx @@ -1,14 +1,6 @@ -'use client' - import { Guest } from '@/app/lib/definitions'; -import SkeletonRow from './skeleton-row'; -import { Suspense } from 'react'; import clsx from 'clsx'; -export function TableHeader() { - -} - export default async function guestsTable() { let guests: Guest[] = await fetch("http://localhost:3001/guests.json") From 63d44208067731390b39cd3c1188b66a579d776f Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 27 Oct 2024 11:52:42 +0100 Subject: [PATCH 2/8] Restore usage of client component and remove explicit async --- app/ui/guests/table.tsx | 42 ++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/app/ui/guests/table.tsx b/app/ui/guests/table.tsx index d113e15..f9094ec 100644 --- a/app/ui/guests/table.tsx +++ b/app/ui/guests/table.tsx @@ -1,23 +1,31 @@ -import { Guest } from '@/app/lib/definitions'; +'use client'; + import clsx from 'clsx'; +import React, { useState, useEffect } from 'react'; +import { Guest } from '@/app/lib/definitions'; -export default async function guestsTable() { - - let guests: Guest[] = await fetch("http://localhost:3001/guests.json") - .then((response) => response.json()) - .then((data) => { - return data.data.map((record: any) => { - return ({ - id: record.id, - name: record.attributes.name, - email: record.attributes.email, - group_name: record.attributes.group_name, - status: record.attributes.status - }); +export default function guestsTable() { + function loadGuests() { + fetch("http://localhost:3001/guests.json") + .then((response) => response.json()) + .then((data) => { + setGuests(data.data.map((record: any) => { + return ({ + id: record.id, + name: record.attributes.name, + email: record.attributes.email, + group_name: record.attributes.group_name, + status: record.attributes.status + }); + })); + }, (error) => { + return []; }); - }, (error) => { - return []; - }); + } + + const [guests, setGuests] = useState>([]); + + guests.length === 0 && loadGuests(); return (
From dde976b0769cf4a62d53b38ef9065bf32f8863ae Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 27 Oct 2024 11:05:56 +0100 Subject: [PATCH 3/8] Create a button to invite guests --- app/ui/guests/table.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/ui/guests/table.tsx b/app/ui/guests/table.tsx index f9094ec..d419c01 100644 --- a/app/ui/guests/table.tsx +++ b/app/ui/guests/table.tsx @@ -50,6 +50,7 @@ export default function guestsTable() { Status + Actions @@ -79,6 +80,11 @@ export default function guestsTable() { {guest.status} + + {guest.status === 'Considered' && ()} + ))} From 7ea96ea7adb8f181ba875df00785131233aaf1c2 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 27 Oct 2024 11:33:40 +0100 Subject: [PATCH 4/8] Make patch request to the backend whenever a guest is invited --- app/ui/guests/table.tsx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/ui/guests/table.tsx b/app/ui/guests/table.tsx index d419c01..56b6291 100644 --- a/app/ui/guests/table.tsx +++ b/app/ui/guests/table.tsx @@ -2,9 +2,11 @@ import clsx from 'clsx'; import React, { useState, useEffect } from 'react'; -import { Guest } from '@/app/lib/definitions'; +import { Guest } from '@/app/lib/definitions'; export default function guestsTable() { + const [guests, setGuests] = useState>([]); + function loadGuests() { fetch("http://localhost:3001/guests.json") .then((response) => response.json()) @@ -20,10 +22,18 @@ export default function guestsTable() { })); }, (error) => { return []; - }); + } + ); + }; + + + function handleInviteGuest() { + fetch("http://localhost:3001/guests/123.json", { method: 'PATCH', body: JSON.stringify({ guest: { status: 'Invited' } }) }) + .then((response) => console.log(response.json())) + .catch((error) => console.error(error)); } - const [guests, setGuests] = useState>([]); + guests.length === 0 && loadGuests(); @@ -81,7 +91,7 @@ export default function guestsTable() { - {guest.status === 'Considered' && ()} From ae7b338771b9be9bac9ea3c62232cbed398da82a Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 27 Oct 2024 11:58:48 +0100 Subject: [PATCH 5/8] Restructure the update payload --- app/ui/guests/table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/ui/guests/table.tsx b/app/ui/guests/table.tsx index 56b6291..9205a65 100644 --- a/app/ui/guests/table.tsx +++ b/app/ui/guests/table.tsx @@ -28,7 +28,7 @@ export default function guestsTable() { function handleInviteGuest() { - fetch("http://localhost:3001/guests/123.json", { method: 'PATCH', body: JSON.stringify({ guest: { status: 'Invited' } }) }) + fetch("http://localhost:3001/guests/bulk-status-change.json", { method: 'POST', body: JSON.stringify({ status: "Invited", guest_ids: [] }) }) .then((response) => console.log(response.json())) .catch((error) => console.error(error)); } From 45e2665997403eaf69121c36f11eaeab71a69d8f Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 27 Oct 2024 12:05:35 +0100 Subject: [PATCH 6/8] Pass the ID of the guests that has just been invited --- app/ui/guests/table.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/ui/guests/table.tsx b/app/ui/guests/table.tsx index 9205a65..66b2919 100644 --- a/app/ui/guests/table.tsx +++ b/app/ui/guests/table.tsx @@ -27,8 +27,8 @@ export default function guestsTable() { }; - function handleInviteGuest() { - fetch("http://localhost:3001/guests/bulk-status-change.json", { method: 'POST', body: JSON.stringify({ status: "Invited", guest_ids: [] }) }) + const handleInviteGuest = (e: React.MouseEvent) => { + fetch("http://localhost:3001/guests/bulk-status-change.json", { method: 'POST', body: JSON.stringify({ status: "Invited", guest_ids: [e.currentTarget.getAttribute('data-guest-id')] }) }) .then((response) => console.log(response.json())) .catch((error) => console.error(error)); } @@ -91,7 +91,7 @@ export default function guestsTable() { - {guest.status === 'Considered' && ()} From 1d59535eb6d9af761892661ef63f11db895003db Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 27 Oct 2024 14:02:10 +0100 Subject: [PATCH 7/8] Submit status changes to the backend --- app/lib/utils.ts | 7 +++++++ app/ui/guests/affinity-groups-tree.tsx | 2 +- app/ui/guests/table.tsx | 15 +++++++++++---- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/app/lib/utils.ts b/app/lib/utils.ts index b7f7cff..8c1a35a 100644 --- a/app/lib/utils.ts +++ b/app/lib/utils.ts @@ -7,6 +7,13 @@ export const formatCurrency = (amount: number) => { }); }; +export const getCsrfToken = () => { + return document.cookie + .split("; ") + .find((row) => row.startsWith("csrf-token")) + ?.split("=")[1] || 'unknown'; +} + export const formatDateToLocal = ( dateStr: string, locale: string = 'en-US', diff --git a/app/ui/guests/affinity-groups-tree.tsx b/app/ui/guests/affinity-groups-tree.tsx index 17e1371..58bb7cf 100644 --- a/app/ui/guests/affinity-groups-tree.tsx +++ b/app/ui/guests/affinity-groups-tree.tsx @@ -44,7 +44,7 @@ export default function AffinityGroupsTree() { if (nodes.length > 0) { return; } - fetch("http://localhost:3001/groups.json") + fetch("/api/groups.json") .then((response) => response.json()) .then((data) => { setNodes(data.data.map((record: any) => { diff --git a/app/ui/guests/table.tsx b/app/ui/guests/table.tsx index 66b2919..9d8cc51 100644 --- a/app/ui/guests/table.tsx +++ b/app/ui/guests/table.tsx @@ -3,12 +3,13 @@ import clsx from 'clsx'; import React, { useState, useEffect } from 'react'; import { Guest } from '@/app/lib/definitions'; +import { getCsrfToken } from '@/app/lib/utils'; export default function guestsTable() { const [guests, setGuests] = useState>([]); function loadGuests() { - fetch("http://localhost:3001/guests.json") + fetch("/api/guests.json") .then((response) => response.json()) .then((data) => { setGuests(data.data.map((record: any) => { @@ -28,13 +29,19 @@ export default function guestsTable() { const handleInviteGuest = (e: React.MouseEvent) => { - fetch("http://localhost:3001/guests/bulk-status-change.json", { method: 'POST', body: JSON.stringify({ status: "Invited", guest_ids: [e.currentTarget.getAttribute('data-guest-id')] }) }) + fetch("/api/guests/bulk_update.json", + { + method: 'POST', + body: JSON.stringify({ properties: { status: "Invited" }, guest_ids: [e.currentTarget.getAttribute('data-guest-id')] }), + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-TOKEN': getCsrfToken(), + } + }) .then((response) => console.log(response.json())) .catch((error) => console.error(error)); } - - guests.length === 0 && loadGuests(); return ( From 03b3a318c081141ed60e1fe0dc6f697b6bd23f0a Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 27 Oct 2024 19:03:56 +0100 Subject: [PATCH 8/8] Refresh list of guests after status update --- app/ui/guests/table.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/ui/guests/table.tsx b/app/ui/guests/table.tsx index 9d8cc51..1215907 100644 --- a/app/ui/guests/table.tsx +++ b/app/ui/guests/table.tsx @@ -32,13 +32,13 @@ export default function guestsTable() { fetch("/api/guests/bulk_update.json", { method: 'POST', - body: JSON.stringify({ properties: { status: "Invited" }, guest_ids: [e.currentTarget.getAttribute('data-guest-id')] }), + body: JSON.stringify({ properties: { status: "invited" }, guest_ids: [e.currentTarget.getAttribute('data-guest-id')] }), headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': getCsrfToken(), } }) - .then((response) => console.log(response.json())) + .then(() => loadGuests()) .catch((error) => console.error(error)); }