From 1fbadf8181d69cc37037d51105ae54369d509922 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Sat, 17 Sep 2022 18:30:27 -0500 Subject: [PATCH] Improve Customize UI --- web/components/arrange-home.tsx | 63 ++++++++++++++++++++++++++------- web/hooks/use-group.ts | 16 +++++++++ web/pages/home/edit.tsx | 16 ++++++--- web/pages/home/index.tsx | 56 ++++++++++++++--------------- 4 files changed, 105 insertions(+), 46 deletions(-) diff --git a/web/components/arrange-home.tsx b/web/components/arrange-home.tsx index 96fe0e6f..4bc88f14 100644 --- a/web/components/arrange-home.tsx +++ b/web/components/arrange-home.tsx @@ -1,14 +1,22 @@ import clsx from 'clsx' import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd' import { MenuIcon } from '@heroicons/react/solid' +import { toast } from 'react-hot-toast' import { Col } from 'web/components/layout/col' import { Row } from 'web/components/layout/row' import { Subtitle } from 'web/components/subtitle' import { keyBy } from 'lodash' +import { XCircleIcon } from '@heroicons/react/outline' +import { Button } from './button' +import { updateUser } from 'web/lib/firebase/users' +import { leaveGroup } from 'web/lib/firebase/groups' +import { User } from 'common/user' +import { useUser } from 'web/hooks/use-user' +import { Group } from 'common/group' export function ArrangeHome(props: { - sections: { label: string; id: string }[] + sections: { label: string; id: string; group?: Group }[] setSectionIds: (sections: string[]) => void }) { const { sections, setSectionIds } = props @@ -40,8 +48,9 @@ export function ArrangeHome(props: { function DraggableList(props: { title: string - items: { id: string; label: string }[] + items: { id: string; label: string; group?: Group }[] }) { + const user = useUser() const { title, items } = props return ( @@ -66,6 +75,7 @@ function DraggableList(props: { snapshot.isDragging && 'z-[9000] bg-gray-200' )} item={item} + user={user} /> )} @@ -79,23 +89,52 @@ function DraggableList(props: { } const SectionItem = (props: { - item: { id: string; label: string } + item: { id: string; label: string; group?: Group } + user: User | null | undefined className?: string }) => { - const { item, className } = props + const { item, user, className } = props + const { group } = item return ( -
-
+ + + + {group && ( + + )} + ) } diff --git a/web/hooks/use-group.ts b/web/hooks/use-group.ts index d3d8dd9f..59b36b27 100644 --- a/web/hooks/use-group.ts +++ b/web/hooks/use-group.ts @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react' import { Group } from 'common/group' import { User } from 'common/user' import { + getGroup, getMemberGroups, GroupMemberDoc, groupMembers, @@ -102,6 +103,21 @@ export const useMemberGroupIds = (user: User | null | undefined) => { return memberGroupIds } +export function useMemberGroupsSubscription(user: User | null | undefined) { + const cachedGroups = useMemberGroups(user?.id) ?? [] + const groupIds = useMemberGroupIds(user) + const [groups, setGroups] = useState(cachedGroups) + + useEffect(() => { + if (groupIds) { + Promise.all(groupIds.map((id) => getGroup(id))).then((groups) => + setGroups(filterDefined(groups)) + ) + } + }, [groupIds]) + return groups +} + export function useMembers(groupId: string | undefined) { const [members, setMembers] = useState([]) useEffect(() => { diff --git a/web/pages/home/edit.tsx b/web/pages/home/edit.tsx index 9670181b..48e10c6c 100644 --- a/web/pages/home/edit.tsx +++ b/web/pages/home/edit.tsx @@ -7,12 +7,12 @@ import { Row } from 'web/components/layout/row' import { Page } from 'web/components/page' import { SiteLink } from 'web/components/site-link' import { Title } from 'web/components/title' -import { useMemberGroups } from 'web/hooks/use-group' +import { useMemberGroupsSubscription } from 'web/hooks/use-group' import { useTracking } from 'web/hooks/use-tracking' import { useUser } from 'web/hooks/use-user' import { updateUser } from 'web/lib/firebase/users' import { track } from 'web/lib/service/analytics' -import { getHomeItems } from '.' +import { getHomeItems, TrendingGroupsSection } from '.' export default function Home() { const user = useUser() @@ -27,7 +27,7 @@ export default function Home() { setHomeSections(newHomeSections) } - const groups = useMemberGroups(user?.id) ?? [] + const groups = useMemberGroupsSubscription(user) const { sections } = getHomeItems(groups, homeSections) return ( @@ -38,7 +38,15 @@ export default function Home() { - + + + + + + ) diff --git a/web/pages/home/index.tsx b/web/pages/home/index.tsx index d3009a84..17d55d56 100644 --- a/web/pages/home/index.tsx +++ b/web/pages/home/index.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode, useEffect, useState } from 'react' +import React, { ReactNode } from 'react' import Router from 'next/router' import { AdjustmentsIcon, @@ -22,18 +22,13 @@ import { SiteLink } from 'web/components/site-link' import { usePrivateUser, useUser } from 'web/hooks/use-user' import { useMemberGroupIds, - useMemberGroups, + useMemberGroupsSubscription, useTrendingGroups, } from 'web/hooks/use-group' import { Button } from 'web/components/button' import { Row } from 'web/components/layout/row' import { ProbChangeTable } from 'web/components/contract/prob-change-table' -import { - getGroup, - groupPath, - joinGroup, - leaveGroup, -} from 'web/lib/firebase/groups' +import { groupPath, joinGroup, leaveGroup } from 'web/lib/firebase/groups' import { usePortfolioHistory } from 'web/hooks/use-portfolio-history' import { formatMoney } from 'common/util/format' import { useProbChanges } from 'web/hooks/use-prob-changes' @@ -57,17 +52,7 @@ export default function Home() { useSaveReferral() usePrefetch(user?.id) - const cachedGroups = useMemberGroups(user?.id) ?? [] - const groupIds = useMemberGroupIds(user) - const [groups, setGroups] = useState(cachedGroups) - - useEffect(() => { - if (groupIds) { - Promise.all(groupIds.map((id) => getGroup(id))).then((groups) => - setGroups(filterDefined(groups)) - ) - } - }, [groupIds]) + const groups = useMemberGroupsSubscription(user) const { sections } = getHomeItems(groups, user?.homeSections ?? []) @@ -77,7 +62,10 @@ export default function Home() { - + <Row className="items-center gap-2"> + <Title className="!mt-0 !mb-0" text="Home" /> + <CustomizeButton justIcon /> + </Row> <DailyStats user={user} /> </Row> @@ -110,11 +98,12 @@ export const getHomeItems = (groups: Group[], sections: string[]) => { // Accommodate old home sections. if (!isArray(sections)) sections = [] - const items = [ + const items: { id: string; label: string; group?: Group }[] = [ ...HOME_SECTIONS, ...groups.map((g) => ({ label: g.name, id: g.id, + group: g, })), ] const itemsById = keyBy(items, 'id') @@ -225,7 +214,6 @@ function GroupSection(props: { <Col> <SectionHeader label={group.name} href={groupPath(group.slug)}> <Button - className="" color="gray-white" onClick={() => { if (user) { @@ -312,20 +300,24 @@ function DailyStats(props: { ) } -function TrendingGroupsSection(props: { user: User | null | undefined }) { - const { user } = props +export function TrendingGroupsSection(props: { + user: User | null | undefined + full?: boolean + className?: string +}) { + const { user, full, className } = props const memberGroupIds = useMemberGroupIds(user) || [] const groups = useTrendingGroups().filter( (g) => !memberGroupIds.includes(g.id) ) - const count = 25 + const count = full ? 100 : 25 const chosenGroups = groups.slice(0, count) return ( - <Col> + <Col className={className}> <SectionHeader label="Trending groups" href="/explore-groups"> - <CustomizeButton /> + {!full && <CustomizeButton className="mb-1" />} </SectionHeader> <Row className="flex-wrap gap-2"> {chosenGroups.map((g) => ( @@ -359,10 +351,14 @@ function TrendingGroupsSection(props: { user: User | null | undefined }) { ) } -function CustomizeButton() { +function CustomizeButton(props: { justIcon?: boolean; className?: string }) { + const { justIcon, className } = props return ( <SiteLink - className="mb-2 flex flex-row items-center text-xl hover:no-underline" + className={clsx( + className, + 'flex flex-row items-center text-xl hover:no-underline' + )} href="/home/edit" > <Button size="lg" color="gray" className={clsx('flex gap-2')}> @@ -370,7 +366,7 @@ function CustomizeButton() { className={clsx('h-[24px] w-5 text-gray-500')} aria-hidden="true" /> - Customize + {!justIcon && 'Customize'} </Button> </SiteLink> )