From 0e7b879aa8d771b58fc5783f78f981cb29432361 Mon Sep 17 00:00:00 2001
From: Sebastien Castiel <sebastien@castiel.me>
Date: Thu, 7 Dec 2023 20:54:11 -0500
Subject: Redesign the groups page

---
 src/app/groups/recent-group-list.tsx | 72 ++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 16 deletions(-)

(limited to 'src/app/groups/recent-group-list.tsx')

diff --git a/src/app/groups/recent-group-list.tsx b/src/app/groups/recent-group-list.tsx
index e728193..ef43372 100644
--- a/src/app/groups/recent-group-list.tsx
+++ b/src/app/groups/recent-group-list.tsx
@@ -1,6 +1,8 @@
 'use client'
 import { getRecentGroups } from '@/app/groups/recent-groups-helpers'
 import { Button } from '@/components/ui/button'
+import { getGroups } from '@/lib/api'
+import { Loader2 } from 'lucide-react'
 import Link from 'next/link'
 import { useEffect, useState } from 'react'
 import { z } from 'zod'
@@ -13,31 +15,69 @@ const recentGroupsSchema = z.array(
 )
 type RecentGroups = z.infer<typeof recentGroupsSchema>
 
-type State = { status: 'pending' } | { status: 'success'; groups: RecentGroups }
+type State =
+  | { status: 'pending' }
+  | { status: 'partial'; groups: RecentGroups }
+  | {
+      status: 'complete'
+      groups: RecentGroups
+      groupsDetails: Awaited<ReturnType<typeof getGroups>>
+    }
 
-export function RecentGroupList() {
+type Props = {
+  getGroupsAction: (groupIds: string[]) => ReturnType<typeof getGroups>
+}
+
+export function RecentGroupList({ getGroupsAction }: Props) {
   const [state, setState] = useState<State>({ status: 'pending' })
 
   useEffect(() => {
     const groupsInStorage = getRecentGroups()
-    setState({ status: 'success', groups: groupsInStorage })
-  }, [])
+    setState({ status: 'partial', groups: groupsInStorage })
+    getGroupsAction(groupsInStorage.map((g) => g.id)).then((groupsDetails) => {
+      setState({ status: 'complete', groups: groupsInStorage, groupsDetails })
+    })
+  }, [getGroupsAction])
+
+  if (state.status === 'pending')
+    return (
+      <p>
+        <Loader2 className="w-4 m-4 mr-2 inline animate-spin" /> Loading recent
+        groups…
+      </p>
+    )
 
   return (
-    <ul className="flex flex-col gap-2 mt-2">
-      {state.status === 'pending' ? (
-        <li>
-          <em>Loading recent groups…</em>
-        </li>
-      ) : (
-        state.groups.map(({ id, name }) => (
-          <li key={id}>
-            <Button asChild variant="outline">
-              <Link href={`/groups/${id}`}>{name}</Link>
+    <ul className="grid grid-cols-1 gap-2 mt-2 sm:grid-cols-3">
+      {state.groups.map((group) => {
+        const details =
+          state.status === 'complete'
+            ? state.groupsDetails.find((d) => d.id === group.id)
+            : null
+        return (
+          <li key={group.id}>
+            <Button variant="outline" className="h-fit w-full py-3" asChild>
+              <Link href={`/groups/${group.id}`} className="text-base">
+                <div className="w-full flex flex-col items-start gap-1">
+                  <div className="text-base">{group.name}</div>
+                  <div className="text-muted-foreground font-normal text-xs">
+                    {details ? (
+                      <>
+                        {details._count.participants} participants ·{' '}
+                        {details.currency}
+                      </>
+                    ) : (
+                      <>
+                        <Loader2 className="w-3 h-3 mr-1 inline animate-spin" />
+                      </>
+                    )}
+                  </div>
+                </div>
+              </Link>
             </Button>
           </li>
-        ))
-      )}
+        )
+      })}
     </ul>
   )
 }
-- 
cgit v1.3

