Create experimental home page
This commit is contained in:
		
							parent
							
								
									7a38d67c5b
								
							
						
					
					
						commit
						a8da5719fe
					
				|  | @ -91,6 +91,8 @@ export function ContractSearch(props: { | ||||||
|   useQuerySortLocalStorage?: boolean |   useQuerySortLocalStorage?: boolean | ||||||
|   useQuerySortUrlParams?: boolean |   useQuerySortUrlParams?: boolean | ||||||
|   isWholePage?: boolean |   isWholePage?: boolean | ||||||
|  |   maxItems?: number | ||||||
|  |   noControls?: boolean | ||||||
| }) { | }) { | ||||||
|   const { |   const { | ||||||
|     user, |     user, | ||||||
|  | @ -105,6 +107,8 @@ export function ContractSearch(props: { | ||||||
|     useQuerySortLocalStorage, |     useQuerySortLocalStorage, | ||||||
|     useQuerySortUrlParams, |     useQuerySortUrlParams, | ||||||
|     isWholePage, |     isWholePage, | ||||||
|  |     maxItems, | ||||||
|  |     noControls, | ||||||
|   } = props |   } = props | ||||||
| 
 | 
 | ||||||
|   const [numPages, setNumPages] = useState(1) |   const [numPages, setNumPages] = useState(1) | ||||||
|  | @ -158,6 +162,8 @@ export function ContractSearch(props: { | ||||||
|   const contracts = pages |   const contracts = pages | ||||||
|     .flat() |     .flat() | ||||||
|     .filter((c) => !additionalFilter?.excludeContractIds?.includes(c.id)) |     .filter((c) => !additionalFilter?.excludeContractIds?.includes(c.id)) | ||||||
|  |   const renderedContracts = | ||||||
|  |     pages.length === 0 ? undefined : contracts.slice(0, maxItems) | ||||||
| 
 | 
 | ||||||
|   if (IS_PRIVATE_MANIFOLD || process.env.NEXT_PUBLIC_FIREBASE_EMULATE) { |   if (IS_PRIVATE_MANIFOLD || process.env.NEXT_PUBLIC_FIREBASE_EMULATE) { | ||||||
|     return <ContractSearchFirestore additionalFilter={additionalFilter} /> |     return <ContractSearchFirestore additionalFilter={additionalFilter} /> | ||||||
|  | @ -175,10 +181,11 @@ export function ContractSearch(props: { | ||||||
|         useQuerySortUrlParams={useQuerySortUrlParams} |         useQuerySortUrlParams={useQuerySortUrlParams} | ||||||
|         user={user} |         user={user} | ||||||
|         onSearchParametersChanged={onSearchParametersChanged} |         onSearchParametersChanged={onSearchParametersChanged} | ||||||
|  |         noControls={noControls} | ||||||
|       /> |       /> | ||||||
|       <ContractsGrid |       <ContractsGrid | ||||||
|         contracts={pages.length === 0 ? undefined : contracts} |         contracts={renderedContracts} | ||||||
|         loadMore={performQuery} |         loadMore={noControls ? undefined : performQuery} | ||||||
|         showTime={showTime} |         showTime={showTime} | ||||||
|         onContractClick={onContractClick} |         onContractClick={onContractClick} | ||||||
|         highlightOptions={highlightOptions} |         highlightOptions={highlightOptions} | ||||||
|  | @ -198,6 +205,7 @@ function ContractSearchControls(props: { | ||||||
|   useQuerySortLocalStorage?: boolean |   useQuerySortLocalStorage?: boolean | ||||||
|   useQuerySortUrlParams?: boolean |   useQuerySortUrlParams?: boolean | ||||||
|   user?: User | null |   user?: User | null | ||||||
|  |   noControls?: boolean | ||||||
| }) { | }) { | ||||||
|   const { |   const { | ||||||
|     className, |     className, | ||||||
|  | @ -209,6 +217,7 @@ function ContractSearchControls(props: { | ||||||
|     useQuerySortLocalStorage, |     useQuerySortLocalStorage, | ||||||
|     useQuerySortUrlParams, |     useQuerySortUrlParams, | ||||||
|     user, |     user, | ||||||
|  |     noControls, | ||||||
|   } = props |   } = props | ||||||
| 
 | 
 | ||||||
|   const savedSort = useQuerySortLocalStorage ? getSavedSort() : null |   const savedSort = useQuerySortLocalStorage ? getSavedSort() : null | ||||||
|  | @ -329,6 +338,10 @@ function ContractSearchControls(props: { | ||||||
|     }) |     }) | ||||||
|   }, [query, index, searchIndex, filter, JSON.stringify(facetFilters)]) |   }, [query, index, searchIndex, filter, JSON.stringify(facetFilters)]) | ||||||
| 
 | 
 | ||||||
|  |   if (noControls) { | ||||||
|  |     return <></> | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <Col |     <Col | ||||||
|       className={clsx('bg-base-200 sticky top-0 z-20 gap-3 pb-3', className)} |       className={clsx('bg-base-200 sticky top-0 z-20 gap-3 pb-3', className)} | ||||||
|  |  | ||||||
|  | @ -86,10 +86,12 @@ export function ContractsGrid(props: { | ||||||
|           /> |           /> | ||||||
|         ))} |         ))} | ||||||
|       </Masonry> |       </Masonry> | ||||||
|       <VisibilityObserver |       {loadMore && ( | ||||||
|         onVisibilityUpdated={onVisibilityUpdated} |         <VisibilityObserver | ||||||
|         className="relative -top-96 h-1" |           onVisibilityUpdated={onVisibilityUpdated} | ||||||
|       /> |           className="relative -top-96 h-1" | ||||||
|  |         /> | ||||||
|  |       )} | ||||||
|     </Col> |     </Col> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										118
									
								
								web/pages/experimental/home.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								web/pages/experimental/home.tsx
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,118 @@ | ||||||
|  | import React from 'react' | ||||||
|  | import { useRouter } from 'next/router' | ||||||
|  | import { PlusSmIcon } from '@heroicons/react/solid' | ||||||
|  | 
 | ||||||
|  | import { Page } from 'web/components/page' | ||||||
|  | import { Col } from 'web/components/layout/col' | ||||||
|  | import { ContractSearch } from 'web/components/contract-search' | ||||||
|  | import { User } from 'common/user' | ||||||
|  | import { getUserAndPrivateUser } from 'web/lib/firebase/users' | ||||||
|  | import { useTracking } from 'web/hooks/use-tracking' | ||||||
|  | import { track } from 'web/lib/service/analytics' | ||||||
|  | import { authenticateOnServer } from 'web/lib/firebase/server-auth' | ||||||
|  | import { useSaveReferral } from 'web/hooks/use-save-referral' | ||||||
|  | import { GetServerSideProps } from 'next' | ||||||
|  | import { Sort } from 'web/hooks/use-sort-and-query-params' | ||||||
|  | import { Button } from 'web/components/button' | ||||||
|  | import { Spacer } from 'web/components/layout/spacer' | ||||||
|  | import { useMemberGroups } from 'web/hooks/use-group' | ||||||
|  | import { Group } from 'common/group' | ||||||
|  | import { Title } from 'web/components/title' | ||||||
|  | 
 | ||||||
|  | export const getServerSideProps: GetServerSideProps = async (ctx) => { | ||||||
|  |   const creds = await authenticateOnServer(ctx) | ||||||
|  |   const auth = creds ? await getUserAndPrivateUser(creds.user.uid) : null | ||||||
|  |   return { props: { auth } } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const Home = (props: { auth: { user: User } | null }) => { | ||||||
|  |   const user = props.auth ? props.auth.user : null | ||||||
|  | 
 | ||||||
|  |   const router = useRouter() | ||||||
|  |   useTracking('view home') | ||||||
|  | 
 | ||||||
|  |   useSaveReferral() | ||||||
|  | 
 | ||||||
|  |   const memberGroups = (useMemberGroups(user?.id) ?? []).filter( | ||||||
|  |     (group) => group.contractIds.length > 0 | ||||||
|  |   ) | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <Page> | ||||||
|  |       <Col className="mx-auto mb-8 w-full"> | ||||||
|  |         <SearchSection label="Trending" sort="score" user={user} /> | ||||||
|  |         <SearchSection label="Newest" sort="newest" user={user} /> | ||||||
|  |         <SearchSection label="Closing soon" sort="close-date" user={user} /> | ||||||
|  |         {memberGroups.map((group) => ( | ||||||
|  |           <GroupSection key={group.id} group={group} user={user} /> | ||||||
|  |         ))} | ||||||
|  |       </Col> | ||||||
|  |       <button | ||||||
|  |         type="button" | ||||||
|  |         className="fixed bottom-[70px] right-3 inline-flex items-center rounded-full border border-transparent bg-indigo-600 p-3 text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 lg:hidden" | ||||||
|  |         onClick={() => { | ||||||
|  |           router.push('/create') | ||||||
|  |           track('mobile create button') | ||||||
|  |         }} | ||||||
|  |       > | ||||||
|  |         <PlusSmIcon className="h-8 w-8" aria-hidden="true" /> | ||||||
|  |       </button> | ||||||
|  |     </Page> | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function SearchSection(props: { | ||||||
|  |   label: string | ||||||
|  |   user: User | null | ||||||
|  |   sort: Sort | ||||||
|  | }) { | ||||||
|  |   const { label, user, sort } = props | ||||||
|  | 
 | ||||||
|  |   const router = useRouter() | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <Col> | ||||||
|  |       <Title className="mx-2 !text-gray-800 sm:mx-0" text={label} /> | ||||||
|  |       <Spacer h={2} /> | ||||||
|  |       <ContractSearch user={user} defaultSort={sort} maxItems={4} noControls /> | ||||||
|  |       <Button | ||||||
|  |         className="self-end" | ||||||
|  |         color="blue" | ||||||
|  |         size="sm" | ||||||
|  |         onClick={() => router.push(`/home?s=${sort}`)} | ||||||
|  |       > | ||||||
|  |         See more | ||||||
|  |       </Button> | ||||||
|  |     </Col> | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function GroupSection(props: { group: Group; user: User | null }) { | ||||||
|  |   const { group, user } = props | ||||||
|  | 
 | ||||||
|  |   const router = useRouter() | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <Col className=""> | ||||||
|  |       <Title className="mx-2 !text-gray-800 sm:mx-0" text={group.name} /> | ||||||
|  |       <Spacer h={2} /> | ||||||
|  |       <ContractSearch | ||||||
|  |         user={user} | ||||||
|  |         defaultSort={'score'} | ||||||
|  |         additionalFilter={{ groupSlug: group.slug }} | ||||||
|  |         maxItems={4} | ||||||
|  |         noControls | ||||||
|  |       /> | ||||||
|  |       <Button | ||||||
|  |         className="mr-2 self-end" | ||||||
|  |         color="blue" | ||||||
|  |         size="sm" | ||||||
|  |         onClick={() => router.push(`/group/${group.slug}`)} | ||||||
|  |       > | ||||||
|  |         See more | ||||||
|  |       </Button> | ||||||
|  |     </Col> | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default Home | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user