/* Imports */ // React import { useRouter } from 'next/router'; // https://nextjs.org/docs/api-reference/next/router import React, { Fragment, useState } from 'react'; import { platformNames } from '../platforms.js'; // Data import searchAccordingToQueryData from '../worker/searchAccordingToQueryData'; import ButtonsForStars from './buttonsForStars.js'; // Parts import Form from './form.js'; import MultiSelectPlatform from './multiSelectPlatforms.js'; import { SliderElement } from './slider.js'; /* Definitions */ /* Helper functions */ // URL slugs let transformObjectIntoUrlSlug = (obj) => { let results = []; for (let key in obj) { if (typeof obj[key] == "number" || typeof obj[key] == "string") { results.push(`${key}=${obj[key]}`); } else if (key == "forecastingPlatforms") { let arr = obj[key].map((x) => x.value); let arrstring = arr.join("|"); results.push(`${key}=${arrstring}`); } } let string = "?" + results.join("&"); return string; }; /* Body */ export default function CommonDisplay({ initialResults, defaultResults, initialQueryParameters, hasSearchbar, hasCapture, hasAdvancedOptions, placeholder, setHasDisplayBeenCapturedOnChangeSearchInputs, displaySeeMoreHint, displayForecastsWrapper, }) { /* States */ const router = useRouter(); const [queryParameters, setQueryParameters] = useState( initialQueryParameters ); let initialSearchSpeedSettings = { timeoutId: null, awaitEndTyping: 500, time: Date.now(), }; const [searchSpeedSettings, setSearchSpeedSettings] = useState( initialSearchSpeedSettings ); const [results, setResults] = useState(initialResults); const [advancedOptions, showAdvancedOptions] = useState(false); const [hasDisplayBeenCaptured, setHasDisplayBeenCaptured] = useState(false); const [whichResultToDisplayAndCapture, setWhichResultToDisplayAndCapture] = useState(0); const [showIdToggle, setShowIdToggle] = useState(false); /* Functions which I want to have access to the Home namespace */ // I don't want to create an "defaultResults" object for each search. async function executeSearchOrAnswerWithDefaultResults(queryData) { console.log("executeSearchOrAnswerWithDefaultResults"); // the queryData object has the same contents as queryParameters. // but I wanted to spare myself having to think about namespace conflicts. let filterManually = (queryData, results) => { if ( queryData.forecastingPlatforms && queryData.forecastingPlatforms.length > 0 ) { let forecastingPlatforms = queryData.forecastingPlatforms.map( (platformObj) => platformObj.value ); results = results.filter((result) => forecastingPlatforms.includes(result.item.platform) ); } if (queryData.starsThreshold == 4) { results = results.filter( (result) => result.item.qualityindicators.stars >= 4 ); } if (queryData.forecastsThreshold) { // results = results.filter(result => (result.qualityindicators && result.item.qualityindicators.numforecasts > forecastsThreshold)) } return results; }; let results; switch ( !queryData || queryData.query == "" || queryData.query == undefined ) { case true: console.log(1); results = filterManually(queryData, defaultResults || initialResults); break; case false: console.log(2); results = await searchAccordingToQueryData(queryData); break; default: console.log(3); console.log("This should not be happening"); results = []; break; } console.log("executeSearchOrAnswerWithDefaultResults/queryData", queryData); console.log("defaultResults", defaultResults); console.log("initialResults", initialResults); console.log(results); setResults(results); // just double check } // I don't want the function which dispaly forecasts (displayForecasts) to change with a change in queryParameters. But I want it to have access to the queryParameters, and in particular access to queryParameters.numDisplay. Hence why this function lives inside Home. let getInfoToDisplayForecastsFunction = ( displayForecastsFunction, { results, hasDisplayBeenCaptured, setHasDisplayBeenCaptured, whichResultToDisplayAndCapture, showIdToggle, } ) => { let numDisplayRounded = queryParameters.numDisplay % 3 != 0 ? queryParameters.numDisplay + (3 - (Math.round(queryParameters.numDisplay) % 3)) : queryParameters.numDisplay; console.log("numDisplay", queryParameters.numDisplay); console.log("numDisplayRounded", numDisplayRounded); return displayForecastsFunction({ results, numDisplay: numDisplayRounded, hasDisplayBeenCaptured, setHasDisplayBeenCaptured, whichResultToDisplayAndCapture, showIdToggle, }); }; /* State controllers */ let onChangeSearchInputs = (newQueryParameters) => { setQueryParameters(newQueryParameters); // ({ ...newQueryParameters, processedUrlYet: true }); console.log("onChangeSearchInputs/newQueryParameters", newQueryParameters); setResults([]); setHasDisplayBeenCaptured(setHasDisplayBeenCapturedOnChangeSearchInputs()); clearTimeout(searchSpeedSettings.timeoutId); let newtimeoutId = setTimeout(async () => { console.log( "onChangeSearchInputs/timeout/newQueryParameters", newQueryParameters ); let urlSlug = transformObjectIntoUrlSlug(newQueryParameters); let urlWithoutDefaultParameters = urlSlug .replace("?query=&", "&") .replace("&starsThreshold=2", "") .replace("&numDisplay=21", "") .replace("&forecastsThreshold=0", "") .replace(`&forecastingPlatforms=${platformNames.join("|")}`, ""); if (urlWithoutDefaultParameters != "?query=") { if (typeof window !== "undefined") { if (!window.location.href.includes(urlWithoutDefaultParameters)) { window.history.replaceState( null, "Metaforecast", urlWithoutDefaultParameters ); } } // router.push(urlWithoutDefaultParameters); } executeSearchOrAnswerWithDefaultResults(newQueryParameters); setSearchSpeedSettings({ ...searchSpeedSettings, timeoutId: null }); }, searchSpeedSettings.awaitEndTyping); setSearchSpeedSettings({ ...searchSpeedSettings, timeoutId: newtimeoutId }); // avoid sending results if user has not stopped typing. }; /* Change the stars threshold */ let onChangeStars = (value) => { console.log("onChangeStars/buttons", value); let newQueryParameters = { ...queryParameters, starsThreshold: value }; onChangeSearchInputs(newQueryParameters); }; /* Change the number of elements to display */ let displayFunctionNumDisplaySlider = (value) => { return Math.round(value) != 1 ? "Show " + Math.round(value) + " results" : "Show " + Math.round(value) + " result"; }; let onChangeSliderForNumDisplay = (event) => { console.log("onChangeSliderForNumDisplay", event[0]); let newQueryParameters = { ...queryParameters, numDisplay: Math.round(event[0]), }; onChangeSearchInputs(newQueryParameters); // Slightly inefficient because it recomputes the search in time, but it makes my logic easier. }; /* Change the forecast threshold */ let displayFunctionNumForecasts = (value) => { return "# Forecasts > " + Math.round(value); }; let onChangeSliderForNumForecasts = (event) => { console.log("onChangeSliderForNumForecasts", event[0]); let newQueryParameters = { ...queryParameters, forecastsThreshold: Math.round(event[0]), }; onChangeSearchInputs(newQueryParameters); }; /* Change on the search bar */ let onChangeSearchBar = (value) => { console.log("onChangeSearchBar/New query:", value); let newQueryParameters = { ...queryParameters, query: value }; onChangeSearchInputs(newQueryParameters); }; /*Change selected platforms */ let onChangeSelectedPlatforms = (value) => { console.log("onChangeSelectedPlatforms/Change in platforms:", value); let newQueryParameters = { ...queryParameters, forecastingPlatforms: value, }; onChangeSearchInputs(newQueryParameters); }; // Change show id let onChangeShowId = () => { setShowIdToggle(!showIdToggle); }; // Capture functionality let onClickBack = () => { let decreaseUntil0 = (num) => (num - 1 > 0 ? num - 1 : 0); setWhichResultToDisplayAndCapture( decreaseUntil0(whichResultToDisplayAndCapture) ); setHasDisplayBeenCaptured(false); }; let onClickForward = (whichResultToDisplayAndCapture) => { setWhichResultToDisplayAndCapture(whichResultToDisplayAndCapture + 1); setHasDisplayBeenCaptured(false); // setTimeout(()=> {onClickForward(whichResultToDisplayAndCapture+1)}, 5000) }; /* Final return */ return (
{getInfoToDisplayForecastsFunction(displayForecastsWrapper, { results, hasDisplayBeenCaptured, setHasDisplayBeenCaptured, whichResultToDisplayAndCapture, showIdToggle, })}

{"Can't find what you were looking for?"} { setQueryParameters({ ...queryParameters, numDisplay: queryParameters.numDisplay * 2, }); }} key={"common-4-1-1"} > {" Show more, or"} {" "} suggest a question on Metaculus



); }