require('./vaultPage.less'); const React = require('react'); const { useState, useEffect, useRef } = React; const Nav = require('naturalcrit/nav/nav.jsx'); const Navbar = require('../../navbar/navbar.jsx'); const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; const Account = require('../../navbar/account.navitem.jsx'); const NewBrew = require('../../navbar/newbrew.navitem.jsx'); const HelpNavItem = require('../../navbar/help.navitem.jsx'); const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx'); const SplitPane = require('../../../../shared/naturalcrit/splitPane/splitPane.jsx'); const ErrorIndex = require('../errorPage/errors/errorIndex.js'); const request = require('../../utils/request-middleware.js'); const VaultPage = (props)=>{ const [pageState, setPageState] = useState(parseInt(props.query.page) || 1); //Response state const [brewCollection, setBrewCollection] = useState(null); const [totalBrews, setTotalBrews] = useState(null); const [searching, setSearching] = useState(false); const [error, setError] = useState(null); const titleRef = useRef(null); const authorRef = useRef(null); const countRef = useRef(null); const v3Ref = useRef(null); const legacyRef = useRef(null); const submitButtonRef = useRef(null); useEffect(()=>{ disableSubmitIfFormInvalid(); loadPage(pageState, true); }, []); const updateStateWithBrews = (brews, page)=>{ setBrewCollection(brews || null); setPageState(parseInt(page) || 1); setSearching(false); }; const updateUrl = (titleValue, authorValue, countValue, v3Value, legacyValue, page)=>{ const url = new URL(window.location.href); const urlParams = new URLSearchParams(url.search); urlParams.set('title', titleValue); urlParams.set('author', authorValue); urlParams.set('count', countValue); urlParams.set('v3', v3Value); urlParams.set('legacy', legacyValue); urlParams.set('page', page); url.search = urlParams.toString(); window.history.replaceState(null, '', url.toString()); }; const performSearch = async (title, author, count, v3, legacy, page)=>{ updateUrl(title, author, count, v3, legacy, page); const response = await request.get( `/api/vault?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}&count=${count}&page=${page}` ).catch((error)=>{ console.log('error at loadPage: ', error); setError(error); updateStateWithBrews([], 1); }); if(response.ok) updateStateWithBrews(response.body.brews, page); }; const loadTotal = async (title, author, v3, legacy)=>{ setTotalBrews(null); const response = await request.get( `/api/vault/total?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}` ).catch((error)=>{ console.log('error at loadTotal: ', error); setError(error); updateStateWithBrews([], 1); }); if(response.ok) setTotalBrews(response.body.totalBrews); }; const loadPage = async (page, updateTotal)=>{ if(!validateForm()) return; setSearching(true); setError(null); const title = titleRef.current.value || ''; const author = authorRef.current.value || ''; const count = countRef.current.value || 10; const v3 = v3Ref.current.checked != false; const legacy = legacyRef.current.checked != false; performSearch(title, author, count, v3, legacy, page); if(updateTotal) loadTotal(title, author, v3, legacy); }; const renderNavItems = ()=>( Vault: Search for brews ); const validateForm = ()=>{ //form validity: title or author must be written, and at least one renderer set const isTitleValid = titleRef.current.validity.valid && titleRef.current.value; const isAuthorValid = authorRef.current.validity.valid && authorRef.current.value; const isCheckboxChecked = legacyRef.current.checked || v3Ref.current.checked; const isFormValid = (isTitleValid || isAuthorValid) && isCheckboxChecked; return isFormValid; }; const disableSubmitIfFormInvalid = ()=>{ submitButtonRef.current.disabled = !validateForm(); }; const renderForm = ()=>(

Brew Lookup

Tips and tricks

  • Only published brews are searchable via this tool
  • Usernames are case-sensitive
  • Use "word" to match an exact string, and - to exclude words (at least one word must not be negated)
  • Some common words like "a", "after", "through", "itself", "here", etc., are ignored in searches. The full list can be found   here
); const renderPaginationControls = ()=>{ if(!totalBrews) return null; const countInt = parseInt(props.query.count || 20); const totalPages = Math.ceil(totalBrews / countInt); let startPage, endPage; if(pageState <= 6) { startPage = 1; endPage = Math.min(totalPages, 10); } else if(pageState + 4 >= totalPages) { startPage = Math.max(1, totalPages - 9); endPage = totalPages; } else { startPage = pageState - 5; endPage = pageState + 4; } const pagesAroundCurrent = new Array(endPage - startPage + 1) .fill() .map((_, index)=>( loadPage(startPage + index, false)} > {startPage + index} )); return (
    {startPage > 1 && ( loadPage(1, false)} > 1 ... )} {pagesAroundCurrent} {endPage < totalPages && ( loadPage(totalPages, false)} > ... {totalPages} )}
); }; const renderFoundBrews = ()=>{ if(searching) { return (

Searching

); } if(error) { const errorText = ErrorIndex()[error.HBErrorCode.toString()] || ''; return (

Error: {errorText}

); } if(!brewCollection) { return (

No search yet

); } if(brewCollection.length === 0) { return (

No brews found

); } return (
{`Brews found: `} {totalBrews} {brewCollection.map((brew, index)=>{ return ( ); })} {renderPaginationControls()}
); }; return (
{renderNavItems()}
{renderForm()}
{renderFoundBrews()}
); }; module.exports = VaultPage;