diff options
Diffstat (limited to 'src/app/groups/recent-group-list.tsx')
| -rw-r--r-- | src/app/groups/recent-group-list.tsx | 72 |
1 files changed, 56 insertions, 16 deletions
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> ) } |
