/*eslint max-lines: ["warn", {"max": 400, "skipBlankLines": true, "skipComments": true}]*/ /*eslint max-params:["warn", { max: 10 }], */ 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'); import request from '../../utils/request-middleware.js'; const VaultPage = (props)=>{ const [pageState, setPageState] = useState(parseInt(props.query.page) || 1); const [sortState, setSort] = useState(props.query.sort || 'title'); const [dirState, setdir] = useState(props.query.dir || 'asc'); //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, props.query.sort, props.query.dir); }, []); const updateStateWithBrews = (brews, page)=>{ setBrewCollection(brews || null); setPageState(parseInt(page) || 1); setSearching(false); }; const updateUrl = (titleValue, authorValue, countValue, v3Value, legacyValue, page, sort, dir)=>{ 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); urlParams.set('sort', sort); urlParams.set('dir', dir); url.search = urlParams.toString(); window.history.replaceState(null, '', url.toString()); }; const performSearch = async (title, author, count, v3, legacy, page, sort, dir)=>{ updateUrl(title, author, count, v3, legacy, page, sort, dir); const response = await request .get(`/api/vault?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}&count=${count}&page=${page}&sort=${sort}&dir=${dir}`) .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, sort, dir)=>{ 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; const sortOption = sort || 'title'; const dirOption = dir || 'asc'; const pageProp = page || 1; setSort(sortOption); setdir(dirOption); performSearch(title, author, count, v3, legacy, pageProp, sortOption, dirOption); 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
New features will be coming, such as filters and search by tags.
); const renderSortOption = (optionTitle, optionValue)=>{ const oppositeDir = dirState === 'asc' ? 'desc' : 'asc'; return (
{sortState === optionValue && ( )}
); }; const renderSortBar = ()=>{ return (
{renderSortOption('Title', 'title', props.query.dir)} {renderSortOption('Created Date', 'createdAt', props.query.dir)} {renderSortOption('Updated Date', 'updatedAt', props.query.dir)} {renderSortOption('Views', 'views', props.query.dir)}
); }; 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, sortState, dirState)} > {startPage + index} )); return (
    {startPage > 1 && ( loadPage(1, false, sortState, dirState)} > 1 ... )} {pagesAroundCurrent} {endPage < totalPages && ( loadPage(totalPages, false, sortState, dirState)} > ... {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()}
{renderSortBar()} {renderFoundBrews()}
); }; module.exports = VaultPage;