diff --git a/web/components/votes/vote-item.tsx b/web/components/votes/vote-item.tsx index 2d10258..eeb7729 100644 --- a/web/components/votes/vote-item.tsx +++ b/web/components/votes/vote-item.tsx @@ -4,10 +4,9 @@ import {Row as rowFor} from 'common/supabase/utils' import {Content} from 'web/components/widgets/editor' import {JSONContent} from '@tiptap/core' import {VoteButtons} from 'web/components/votes/vote-buttons' -import {getVoteCreator} from "web/lib/supabase/votes"; -import {useEffect, useState} from "react"; import Link from "next/link"; import {STATUS_CHOICES} from "common/votes/constants"; +import {useUserInStore} from "web/hooks/use-user-supabase"; export type Vote = rowFor<'votes'> & { votes_for: number @@ -17,15 +16,22 @@ export type Vote = rowFor<'votes'> & { status?: string } +function Username(props: { + creatorId: string +}) { + const {creatorId} = props + const creator = useUserInStore(creatorId) + return <> + {creator?.username && + {creator.username}} + ; +} + export function VoteItem(props: { vote: Vote onVoted?: () => void | Promise }) { const {vote, onVoted} = props - const [creator, setCreator] = useState(null) - useEffect(() => { - getVoteCreator(vote.creator_id).then(setCreator) - }, [vote.creator_id]) // console.debug('creator', creator, vote) return ( @@ -37,8 +43,7 @@ export function VoteItem(props: { {!!vote.priority ?
Priority: {vote.priority.toFixed(0)}%
:

} - {!vote.is_anonymous && creator?.username && - {creator.username}} + {!vote.is_anonymous && }
diff --git a/web/hooks/use-user-supabase.ts b/web/hooks/use-user-supabase.ts index 77380a6..29abdac 100644 --- a/web/hooks/use-user-supabase.ts +++ b/web/hooks/use-user-supabase.ts @@ -1,15 +1,11 @@ -import { useEffect, useRef, useState } from 'react' -import { useEffectCheckEquality } from './use-effect-check-equality' -import { uniqBy, uniq } from 'lodash' -import { usePersistentLocalState } from 'web/hooks/use-persistent-local-state' -import { filterDefined } from 'common/util/array' -import { usePersistentInMemoryState } from './use-persistent-in-memory-state' -import { - DisplayUser, - getDisplayUsers, - getFullUserById, -} from 'web/lib/supabase/users' -import { FullUser } from 'common/api/user-types' +import {useEffect, useState} from 'react' +import {useEffectCheckEquality} from './use-effect-check-equality' +import {uniq, uniqBy} from 'lodash' +import {usePersistentLocalState} from 'web/hooks/use-persistent-local-state' +import {filterDefined} from 'common/util/array' +import {usePersistentInMemoryState} from './use-persistent-in-memory-state' +import {DisplayUser, getDisplayUsers, getFullUserById,} from 'web/lib/supabase/users' +import {FullUser} from 'common/api/user-types' export function useUserById(userId: string | undefined) { const [user, setUser] = usePersistentInMemoryState< @@ -25,8 +21,8 @@ export function useUserById(userId: string | undefined) { return user } -const cache = new Map() - +// const cache = new Map() +// // export function useDisplayUserById(userId: string | undefined) { // const [user, setUser] = usePersistentInMemoryState< // DisplayUser | null | undefined @@ -51,45 +47,48 @@ const cache = new Map() // return user // } -export function useUsers(userIds: string[]) { - const [users, setUsers] = useState<(DisplayUser | null)[] | undefined>( - undefined - ) - - const requestIdRef = useRef(0) - useEffectCheckEquality(() => { - const requestId = ++requestIdRef.current - - const missing = userIds.filter((id) => !cache.has(id)) - - getDisplayUsers(missing).then((users) => { - users.forEach((user) => { - cache.set(user.id, user) - }) - if (requestId !== requestIdRef.current) return - setUsers(userIds.map((id) => cache.get(id) ?? null)) - }) - }, [userIds]) - - return users -} +// export function useUsers(userIds: string[]) { +// const [users, setUsers] = useState<(DisplayUser | null)[] | undefined>( +// undefined +// ) +// +// const requestIdRef = useRef(0) +// useEffectCheckEquality(() => { +// const requestId = ++requestIdRef.current +// +// const missing = userIds.filter((id) => !cache.has(id)) +// +// getDisplayUsers(missing).then((users) => { +// users.forEach((user) => { +// cache.set(user.id, user) +// }) +// if (requestId !== requestIdRef.current) return +// setUsers(userIds.map((id) => cache.get(id) ?? null)) +// }) +// }, [userIds]) +// +// return users +// } // TODO: decide whether in-memory or in-localstorage is better and stick to it export function useUsersInStore( - userIds: string[], + userIds: (string | null)[], key: string, limit?: number ) { + const validUserIds = Array.from(new Set(userIds.filter((id): id is string => !!id))) + const [users, setUsers] = usePersistentLocalState( undefined, - 'use-users-in-local-storage' + key + 'use-users-in-local-storage-' + key ) // Fetch all users at least once on load. const [userIdsFetched, setUserIdsFetched] = useState([]) const fetchedSet = new Set(userIdsFetched) - const userIdsNotFetched = userIds.filter((id) => !fetchedSet.has(id)) + + const userIdsNotFetched = validUserIds.filter((id) => !fetchedSet.has(id)) const userIdsToFetch = limit ? userIdsNotFetched.slice(0, limit) : userIdsNotFetched @@ -104,5 +103,12 @@ export function useUsersInStore( }) }, [userIdsToFetch]) - return users?.filter((user) => userIds.includes(user?.id)) + return users?.filter((user) => validUserIds.includes(user?.id)) +} + +export function useUserInStore(userId: string | null) { + if (!userId) return null // early return avoids invalid key + hook calls are safe + + const users = useUsersInStore(userId ? [userId] : [], userId ?? 'empty') + return users?.[0] ?? null } diff --git a/web/lib/supabase/votes.ts b/web/lib/supabase/votes.ts index 44c563a..c509618 100644 --- a/web/lib/supabase/votes.ts +++ b/web/lib/supabase/votes.ts @@ -1,10 +1,9 @@ -import {run} from 'common/supabase/utils' import {db} from 'web/lib/supabase/db' import {OrderBy} from "common/votes/constants"; export const getVotes = async (params: { orderBy: OrderBy }) => { - const { orderBy } = params + const {orderBy} = params const {data, error} = await db.rpc('get_votes_with_results' as any, { order_by: orderBy, }); @@ -12,15 +11,3 @@ export const getVotes = async (params: { orderBy: OrderBy }) => { return data } - -export const getVoteCreator = async (creatorId: string) => { - const {data} = await run( - db - .from('users') - .select(`id, name, username`) - .eq('id', creatorId) - .limit(1) - ) - - return data[0] -}