diff --git a/client/homebrew/pages/vaultPage/vaultPage.jsx b/client/homebrew/pages/vaultPage/vaultPage.jsx
index 328348893..bfb20bd77 100644
--- a/client/homebrew/pages/vaultPage/vaultPage.jsx
+++ b/client/homebrew/pages/vaultPage/vaultPage.jsx
@@ -45,7 +45,12 @@ const VaultPage = (props)=>{
const v3Ref = useRef(null);
const legacyRef = useRef(null);
const submitButtonRef = useRef(null);
- const [tagsList, setTagList] = useState(props.query.tags.split(',') || []);
+
+ const parseTags = (value)=>value?.split(',').filter(Boolean) || [];
+
+ const [tagsListAnd, setTagListAnd] = useState(parseTags(props.query.tagsAnd));
+ const [tagsListOr, setTagListOr] = useState(parseTags(props.query.tagsOr));
+ const [tagsListNot, setTagListNot] = useState(parseTags(props.query.tagsNot));
useEffect(()=>{
disableSubmitIfFormInvalid();
@@ -65,54 +70,88 @@ const VaultPage = (props)=>{
setSearching(false);
};
- const updateUrl = (titleValue, authorValue, countValue, v3Value, legacyValue, tagsValue, page, sort, dir)=>{
+
+ const buildQueryParams = (entries)=>{
+ const params = new URLSearchParams();
+
+ entries.forEach(([key, value])=>{
+ if(value === undefined || value === null || value === '') return;
+ if(Array.isArray(value) && value.length === 0) return;
+
+ params.set(key, Array.isArray(value) ? value.join(',') : value);
+ });
+
+ return params.toString();
+ };
+
+
+ const updateUrl = (params)=>{
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('tags', tagsValue);
- urlParams.set('page', page);
- urlParams.set('sort', sort);
- urlParams.set('dir', dir);
+ url.search = params;
-
- console.log(urlParams.toString());
- url.search = urlParams.toString();
window.history.replaceState(null, '', url.toString());
};
- const performSearch = async (title, author, count, v3, legacy, tags, page, sort, dir)=>{
- updateUrl(title, author, count, v3, legacy, tags, page, sort, dir);
- const response = await request
- .get(`/api/vault?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}&tags=${tags}&count=${count}&page=${page}&sort=${sort}&dir=${dir}`)
- .catch((error)=>{
- console.log('error at loadPage: ', error);
- setError(error);
- updateStateWithBrews([], 1);
- });
+ const performSearch = async (formContents, page, sort, dir)=>{
+ const { title, author, count, v3, legacy, tagsAnd, tagsOr, tagsNot } = formContents;
- if(response?.ok)
+
+ const params = buildQueryParams([
+ ['title', title],
+ ['author', author],
+ ['v3', v3],
+ ['legacy', legacy],
+ ['tagsAnd', tagsAnd],
+ ['tagsOr', tagsOr],
+ ['tagsNot', tagsNot],
+ ['count', count],
+ ['page', page],
+ ['sort', sort],
+ ['dir', dir]
+ ]);
+
+ updateUrl(params);
+
+ const response = await request.get(`/api/vault?${params}`)
+ .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, tags)=>{
+ const loadTotal = async (formContents)=>{
+ const { title, author, count, v3, legacy, tagsAnd, tagsOr, tagsNot } = formContents;
+
setTotalBrews(null);
- const response = await request.get(`/api/vault/total?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}&tags=${tags}`)
- .catch((error)=>{
- console.log('error at loadTotal: ');
- console.error(error);
- setError(error);
- updateStateWithBrews([], 1);
- });
+ const params = buildQueryParams([
+ ['title', title],
+ ['author', author],
+ ['v3', v3],
+ ['legacy', legacy],
+ ['tagsAnd', tagsAnd],
+ ['tagsOr', tagsOr],
+ ['tagsNot', tagsNot]
+ ]);
- if(response.ok)
+ const response = await request.get(`/api/vault/total?${params}`)
+ .catch((error)=>{
+ console.log('error at loadTotal: ');
+ console.error(error);
+ setError(error);
+ updateStateWithBrews([], 1);
+ });
+
+ if(response?.ok) {
setTotalBrews(response.body.totalBrews);
+ }
};
const loadPage = async (page, updateTotal, sort, dir)=>{
@@ -126,7 +165,14 @@ const VaultPage = (props)=>{
const count = countRef.current.value || 20;
const v3 = v3Ref.current.checked != false;
const legacy = legacyRef.current.checked != false;
- const tags = tagsList;
+ const tagsAnd = tagsListAnd;
+ const tagsOr = tagsListOr;
+ const tagsNot = tagsListNot;
+
+ const formContents = {
+ title, author, count, v3, legacy, tagsAnd, tagsOr, tagsNot
+ };
+
const sortOption = sort || 'title';
const dirOption = dir || 'asc';
const pageProp = page || 1;
@@ -134,10 +180,10 @@ const VaultPage = (props)=>{
setSort(sortOption);
setdir(dirOption);
- performSearch(title, author, count, v3, legacy, tags, pageProp, sortOption, dirOption);
+ performSearch(formContents, pageProp, sortOption, dirOption);
if(updateTotal)
- loadTotal(title, author, v3, legacy, tags);
+ loadTotal(formContents);
};
const renderNavItems = ()=>(
@@ -161,8 +207,9 @@ const VaultPage = (props)=>{
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 isTagsValid = tagsListAnd.length >= 1 || tagsListOr.length >= 1;
- const isFormValid = (isTitleValid || isAuthorValid) && isCheckboxChecked;
+ const isFormValid = (isTitleValid || isAuthorValid || isTagsValid) && isCheckboxChecked;
return isFormValid;
};
@@ -173,7 +220,7 @@ const VaultPage = (props)=>{
const renderForm = ()=>(
-
Brew Lookup
+
Brew Lookup
-
+
Tag Search
+