Create experimental home page
This commit is contained in:
		
							parent
							
								
									7a38d67c5b
								
							
						
					
					
						commit
						a8da5719fe
					
				|  | @ -91,6 +91,8 @@ export function ContractSearch(props: { | |||
|   useQuerySortLocalStorage?: boolean | ||||
|   useQuerySortUrlParams?: boolean | ||||
|   isWholePage?: boolean | ||||
|   maxItems?: number | ||||
|   noControls?: boolean | ||||
| }) { | ||||
|   const { | ||||
|     user, | ||||
|  | @ -105,6 +107,8 @@ export function ContractSearch(props: { | |||
|     useQuerySortLocalStorage, | ||||
|     useQuerySortUrlParams, | ||||
|     isWholePage, | ||||
|     maxItems, | ||||
|     noControls, | ||||
|   } = props | ||||
| 
 | ||||
|   const [numPages, setNumPages] = useState(1) | ||||
|  | @ -158,6 +162,8 @@ export function ContractSearch(props: { | |||
|   const contracts = pages | ||||
|     .flat() | ||||
|     .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) { | ||||
|     return <ContractSearchFirestore additionalFilter={additionalFilter} /> | ||||
|  | @ -175,10 +181,11 @@ export function ContractSearch(props: { | |||
|         useQuerySortUrlParams={useQuerySortUrlParams} | ||||
|         user={user} | ||||
|         onSearchParametersChanged={onSearchParametersChanged} | ||||
|         noControls={noControls} | ||||
|       /> | ||||
|       <ContractsGrid | ||||
|         contracts={pages.length === 0 ? undefined : contracts} | ||||
|         loadMore={performQuery} | ||||
|         contracts={renderedContracts} | ||||
|         loadMore={noControls ? undefined : performQuery} | ||||
|         showTime={showTime} | ||||
|         onContractClick={onContractClick} | ||||
|         highlightOptions={highlightOptions} | ||||
|  | @ -198,6 +205,7 @@ function ContractSearchControls(props: { | |||
|   useQuerySortLocalStorage?: boolean | ||||
|   useQuerySortUrlParams?: boolean | ||||
|   user?: User | null | ||||
|   noControls?: boolean | ||||
| }) { | ||||
|   const { | ||||
|     className, | ||||
|  | @ -209,6 +217,7 @@ function ContractSearchControls(props: { | |||
|     useQuerySortLocalStorage, | ||||
|     useQuerySortUrlParams, | ||||
|     user, | ||||
|     noControls, | ||||
|   } = props | ||||
| 
 | ||||
|   const savedSort = useQuerySortLocalStorage ? getSavedSort() : null | ||||
|  | @ -329,6 +338,10 @@ function ContractSearchControls(props: { | |||
|     }) | ||||
|   }, [query, index, searchIndex, filter, JSON.stringify(facetFilters)]) | ||||
| 
 | ||||
|   if (noControls) { | ||||
|     return <></> | ||||
|   } | ||||
| 
 | ||||
|   return ( | ||||
|     <Col | ||||
|       className={clsx('bg-base-200 sticky top-0 z-20 gap-3 pb-3', className)} | ||||
|  |  | |||
|  | @ -86,10 +86,12 @@ export function ContractsGrid(props: { | |||
|           /> | ||||
|         ))} | ||||
|       </Masonry> | ||||
|       <VisibilityObserver | ||||
|         onVisibilityUpdated={onVisibilityUpdated} | ||||
|         className="relative -top-96 h-1" | ||||
|       /> | ||||
|       {loadMore && ( | ||||
|         <VisibilityObserver | ||||
|           onVisibilityUpdated={onVisibilityUpdated} | ||||
|           className="relative -top-96 h-1" | ||||
|         /> | ||||
|       )} | ||||
|     </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