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) => { //Form state const [titleState, setTitle] = useState(props.query.title || ''); const [authorState, setAuthor] = useState(props.query.author || ''); const [legacyState, setLegacy] = useState(props.query.legacy !== 'false'); const [v3State, setV3] = useState(props.query.v3 !== 'false'); const [countState, setCount] = useState(props.query.count || 20); const [pageState, setPage] = 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, false, true); }, []); const updateStateWithBrews = (brews, page) => { setBrewCollection(brews || null); setPage(parseInt(page) || 1); setSearching(false); }; const updateUrl = (title, author, count, v3, legacy, page) => { const url = new URL(window.location.href); const urlParams = new URLSearchParams(); Object.entries({ title, author, count, v3, legacy, page, }).forEach(([key, value]) => urlParams.set(key, value)); url.search = urlParams.toString(); window.history.replaceState(null, null, url); }; const performSearch = async ({ titleValue, authorValue, countValue, v3Value, legacyValue, page }) => { updateUrl(titleValue, authorValue, countValue, v3Value, legacyValue, page); console.log(title, author, count, v3, legacy); if ((titleValue || authorValue) && (v3Value || legacyValue)) { const response = await request.get( `/api/vault?title=${titleValue}&author=${authorValue}&v3=${v3Value}&legacy=${legacyValue}&count=${countValue}&page=${page}` ).catch((error)=>{ console.log('error at loadPage: ', error); setError(`${error.response ? error.response.status : error.message}` ); updateStateWithBrews([], 1); }); if (response.ok) updateStateWithBrews(response.body.brews, page); } }; const loadTotal = async ({ titleValue, authorValue, v3Value, legacyValue }) => { setTotalBrews(null); if ((titleValue || authorValue) && (v3Value || legacyValue)) { const response = await request.get( `/api/vault/total?title=${titleValue}&author=${authorValue}&v3=${v3Value}&legacy=${legacyValue}` ).catch((error)=>{ console.log('error at loadTotal: ', error); setError(`${error.response ? error.response.status : error.message}` ); updateStateWithBrews([], 1); }); if (response.ok) setTotalBrews(response.body.totalBrews); } }; const loadPage = async (page, update, total) => { if (!validateForm()) { return; } setSearching(true); setError(null); const titleValue = titleRef.current.value || ''; const authorValue = authorRef.current.value || ''; const countValue = countRef.current.value || 10; const v3Value = v3Ref.current.checked != false; const legacyValue = legacyRef.current.checked != false; if (update) { setTitle(titleValue); setAuthor(authorValue); setCount(countValue); setV3(v3Value); setLegacy(legacyValue); setPage(page); } // Perform search with the latest input values, because state is not fast enough performSearch({ titleValue, authorValue, countValue, v3Value, legacyValue, page }); if (total) { loadTotal({ titleValue, authorValue, v3Value, legacyValue }); } }; 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, make sure you are writing it correctly
  • 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(countState); 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, false)} > {startPage + index} )); return (
    {startPage > 1 && ( loadPage(1, false, false)} > 1 ... )} {pagesAroundCurrent} {endPage < totalPages && ( loadPage(totalPages, false, false)} > ... {totalPages} )}
); }; const renderFoundBrews = () => { if (searching) { return (

Searching

); } if (error) { const errorText = ErrorIndex({ brew })[brew.HBErrorCode.toString()] || ''; console.log('render Error: ', error); 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) => { const processedAuthors = brew.authors.map(author => author.includes('@') ? 'hidden' : author ); return ( ); })} {renderPaginationControls()}
); }; return (
{renderNavItems()}
{renderForm()}
{renderFoundBrews()}
); }; module.exports = VaultPage;