tweak: Further question page changes
- Add estimate of likeliest option to top - Or of event happening for yes/no questions - Restore selection highlight from legend - But avoid weird color errors - Add a bunch of parameters to QuestionOptions - I could just have added a flag for isInQuestionPage, - Not sure if this is the best way to go about this I'm not particularly planning to continue with changes in the upcoming days
This commit is contained in:
		
							parent
							
								
									7236e9662f
								
							
						
					
					
						commit
						020f0c0c5e
					
				|  | @ -36,8 +36,8 @@ const getVictoryGroup = ({ | |||
|         style={{ | ||||
|           data: { | ||||
|             // strokeOpacity: highlight ?  1 : 0.5,
 | ||||
|             strokeOpacity: 0.6, | ||||
|             strokeWidth: 3, | ||||
|             strokeOpacity: highlight && !isBinary ? 0.8 : 0.6, | ||||
|             strokeWidth: highlight && !isBinary ? 4 : 3, | ||||
|           }, | ||||
|         }} | ||||
|       /> | ||||
|  | @ -196,14 +196,14 @@ export const InnerChart: React.FC<Props> = ({ | |||
|         // note: this produces an annoying change of color effect
 | ||||
|         /* | ||||
|         highlight === undefined | ||||
|         ? null | ||||
|         : // render highlighted series on top of everything else
 | ||||
|           getVictoryGroup({ | ||||
|             data: seriesList[highlight], | ||||
|             i: highlight,  | ||||
|             highlight: true, | ||||
|           }) | ||||
|         */ | ||||
|           ? null | ||||
|           : // render highlighted series on top of everything else
 | ||||
|             getVictoryGroup({ | ||||
|               data: seriesList[highlight], | ||||
|               i: highlight, | ||||
|               highlight: true, | ||||
|             }) | ||||
|             */ | ||||
|       } | ||||
|     </VictoryChart> | ||||
|   ); | ||||
|  |  | |||
|  | @ -116,14 +116,24 @@ export const QuestionCard: React.FC<Props> = ({ | |||
|           </div> | ||||
|           {isBinary ? ( | ||||
|             <div className="flex justify-between"> | ||||
|               <QuestionOptions question={question} /> | ||||
|               <QuestionOptions | ||||
|                 question={question} | ||||
|                 maxNumOptions={5} | ||||
|                 optionTextSize={"text-normal"} | ||||
|                 onlyFirstEstimate={false} | ||||
|               /> | ||||
|               <div className={`hidden ${showTimeStamp ? "sm:block" : ""}`}> | ||||
|                 <LastUpdated timestamp={lastUpdated} /> | ||||
|               </div> | ||||
|             </div> | ||||
|           ) : ( | ||||
|             <div className="space-y-2"> | ||||
|               <QuestionOptions question={question} /> | ||||
|               <QuestionOptions | ||||
|                 question={question} | ||||
|                 maxNumOptions={5} | ||||
|                 optionTextSize={"text-sm"} | ||||
|                 onlyFirstEstimate={false} | ||||
|               /> | ||||
|               <div className={`hidden ${showTimeStamp ? "sm:block" : ""} ml-6`}> | ||||
|                 <LastUpdated timestamp={lastUpdated} /> | ||||
|               </div> | ||||
|  |  | |||
|  | @ -1,4 +1,7 @@ | |||
| import { FullQuestionOption, isFullQuestionOption } from "../../../common/types"; | ||||
| import { | ||||
|   FullQuestionOption, | ||||
|   isFullQuestionOption, | ||||
| } from "../../../common/types"; | ||||
| import { QuestionFragment } from "../../fragments.generated"; | ||||
| import { isQuestionBinary } from "../../utils"; | ||||
| import { formatProbability } from "../utils"; | ||||
|  | @ -89,26 +92,38 @@ const chooseColor = (probability: number) => { | |||
|   } | ||||
| }; | ||||
| 
 | ||||
| const OptionRow: React.FC<{ option: FullQuestionOption }> = ({ option }) => { | ||||
| const OptionRow: React.FC<{ | ||||
|   option: FullQuestionOption; | ||||
|   optionTextSize: string; | ||||
| }> = ({ option, optionTextSize }) => { | ||||
|   return ( | ||||
|     <div className="flex items-center"> | ||||
|       <div | ||||
|         className={`${chooseColor( | ||||
|           option.probability | ||||
|         )} w-14 flex-none rounded-md py-0.5 text-sm text-center`}
 | ||||
|         )} w-14 flex-none rounded-md py-0.5 ${ | ||||
|           optionTextSize || "text-sm" | ||||
|         } text-center`}
 | ||||
|       > | ||||
|         {formatProbability(option.probability)} | ||||
|       </div> | ||||
|       <div className="text-gray-700 pl-3 leading-snug text-sm"> | ||||
|       <div | ||||
|         className={`text-gray-700 pl-3 leading-snug ${ | ||||
|           optionTextSize || "text-sm" | ||||
|         }`}
 | ||||
|       > | ||||
|         {option.name} | ||||
|       </div> | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| export const QuestionOptions: React.FC<{ question: QuestionFragment }> = ({ | ||||
|   question, | ||||
| }) => { | ||||
| export const QuestionOptions: React.FC<{ | ||||
|   question: QuestionFragment; | ||||
|   maxNumOptions: number; | ||||
|   optionTextSize: string; | ||||
|   onlyFirstEstimate: boolean; | ||||
| }> = ({ question, maxNumOptions, optionTextSize, onlyFirstEstimate }) => { | ||||
|   const isBinary = isQuestionBinary(question); | ||||
| 
 | ||||
|   if (isBinary) { | ||||
|  | @ -124,30 +139,65 @@ export const QuestionOptions: React.FC<{ question: QuestionFragment }> = ({ | |||
|         <span | ||||
|           className={`${primaryForecastColor( | ||||
|             yesOption.probability | ||||
|           )} text-white w-16 rounded-md px-1.5 py-0.5 font-bold`}
 | ||||
|           )} text-white w-16 rounded-md px-2 py-1 font-bold ${ | ||||
|             optionTextSize || "text-normal" | ||||
|           }`}
 | ||||
|         > | ||||
|           {formatProbability(yesOption.probability)} | ||||
|         </span> | ||||
|         <span | ||||
|           className={`${textColor( | ||||
|             yesOption.probability | ||||
|           )} text-gray-500 inline-block`}
 | ||||
|           className={`${textColor(yesOption.probability)} ${ | ||||
|             optionTextSize || "text-normal" | ||||
|           } text-gray-500 inline-block`}
 | ||||
|         > | ||||
|           {primaryEstimateAsText(yesOption.probability)} | ||||
|         </span> | ||||
|       </div> | ||||
|     ); | ||||
|   } else if (onlyFirstEstimate) { | ||||
|     if (question.options.length > 0) { | ||||
|       const yesOption = | ||||
|         question.options.length > 0 ? question.options[0] : null; | ||||
|       if (!yesOption) { | ||||
|         return null; // shouldn't happen
 | ||||
|       } | ||||
|       if (!isFullQuestionOption(yesOption)) { | ||||
|         return null; // missing data
 | ||||
|       } | ||||
|       return ( | ||||
|         <div className="space-x-2"> | ||||
|           <span | ||||
|             className={`${primaryForecastColor( | ||||
|               yesOption.probability | ||||
|             )} text-white w-16 rounded-md px-2 py-1 font-bold ${ | ||||
|               optionTextSize || "text-normal" | ||||
|             }`}
 | ||||
|           > | ||||
|             {formatProbability(yesOption.probability)} | ||||
|           </span> | ||||
|           <span | ||||
|             className={`${textColor(yesOption.probability)} ${ | ||||
|               optionTextSize || "text-normal" | ||||
|             } text-gray-500 inline-block`}
 | ||||
|           > | ||||
|             {yesOption.name} | ||||
|           </span> | ||||
|         </div> | ||||
|       ); | ||||
|     } else { | ||||
|       return null; | ||||
|     } | ||||
|   } else { | ||||
|     const optionsSorted = question.options | ||||
|       .filter(isFullQuestionOption) | ||||
|       .sort((a, b) => b.probability - a.probability); | ||||
| 
 | ||||
|     const optionsMax5 = optionsSorted.slice(0, 5); // display max 5 options.
 | ||||
|     const optionsMaxN = optionsSorted.slice(0, maxNumOptions); // display max 5 options.
 | ||||
| 
 | ||||
|     return ( | ||||
|       <div className="space-y-2"> | ||||
|         {optionsMax5.map((option, i) => ( | ||||
|           <OptionRow option={option} key={i} /> | ||||
|         {optionsMaxN.map((option, i) => ( | ||||
|           <OptionRow option={option} key={i} optionTextSize={optionTextSize} /> | ||||
|         ))} | ||||
|       </div> | ||||
|     ); | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ import { CaptureQuestion } from "../components/CaptureQuestion"; | |||
| import { HistoryChart } from "../components/HistoryChart"; | ||||
| import { IndicatorsTable } from "../components/IndicatorsTable"; | ||||
| import { Stars } from "../components/Stars"; | ||||
| import { QuestionOptions } from "../components/QuestionOptions"; | ||||
| import { QuestionPageDocument } from "../queries.generated"; | ||||
| 
 | ||||
| interface Props { | ||||
|  | @ -49,62 +50,78 @@ const Section: React.FC<{ title: string }> = ({ title, children }) => ( | |||
| 
 | ||||
| const LargeQuestionCard: React.FC<{ | ||||
|   question: QuestionWithHistoryFragment; | ||||
| }> = ({ question }) => ( | ||||
|   <Card highlightOnHover={false} large={true}> | ||||
|     <h1 className="sm:text-3xl text-xl"> | ||||
|       <a | ||||
|         className="text-black no-underline hover:text-gray-700" | ||||
|         href={question.url} | ||||
|         target="_blank" | ||||
|       > | ||||
|         {question.title}{" "} | ||||
|       </a> | ||||
|     </h1> | ||||
| }> = ({ question }) => { | ||||
|   let probabilities = question.options; | ||||
|   let optionsOrderedByProbability = question.options.sort((a, b) => | ||||
|     (a.probability || 0) > (b.probability || 0) ? -1 : 1 | ||||
|   ); | ||||
|   let optionWithHighestProbability = | ||||
|     question.options.length > 0 ? [optionsOrderedByProbability[0]] : []; | ||||
| 
 | ||||
|     <div className="flex gap-2 mb-5"> | ||||
|       <a | ||||
|         className="text-black no-underline border-2 rounded-lg border-gray-400 rounded p-1 px-2 text-2xs hover:text-gray-600" | ||||
|         href={question.url} | ||||
|         target="_blank" | ||||
|       > | ||||
|         {question.platform.label}{" "} | ||||
|         <FaExternalLinkAlt className="text-gray-400 inline sm:text-md text-md mb-1" /> | ||||
|       </a> | ||||
|       <Stars num={question.qualityIndicators.stars} /> | ||||
|     </div> | ||||
| 
 | ||||
|     <div className="mb-10"> | ||||
|       {question.platform.id === "guesstimate" && question.visualization ? ( | ||||
|         <a className="no-underline" href={question.url} target="_blank"> | ||||
|           <img | ||||
|             className="rounded-sm" | ||||
|             src={question.visualization} | ||||
|             alt="Guesstimate Screenshot" | ||||
|           /> | ||||
|         </a> | ||||
|       ) : ( | ||||
|         <HistoryChart question={question} /> | ||||
|       )} | ||||
|     </div> | ||||
| 
 | ||||
|     <div className="mx-auto max-w-prose"> | ||||
|       <Section title="Question description"> | ||||
|         <ReactMarkdown | ||||
|           linkTarget="_blank" | ||||
|           className="font-normal text-gray-900" | ||||
|   return ( | ||||
|     <Card highlightOnHover={false} large={true}> | ||||
|       <h1 className="sm:text-3xl text-xl"> | ||||
|         <a | ||||
|           className="text-black no-underline hover:text-gray-700" | ||||
|           href={question.url} | ||||
|           target="_blank" | ||||
|         > | ||||
|           {question.description.replaceAll("---", "")} | ||||
|         </ReactMarkdown> | ||||
|       </Section> | ||||
|       <div className="mt-5"> | ||||
|         <Section title="Indicators"> | ||||
|           <IndicatorsTable question={question} /> | ||||
|         </Section> | ||||
|       </div> | ||||
|     </div> | ||||
|   </Card> | ||||
| ); | ||||
|           {question.title}{" "} | ||||
|         </a> | ||||
|       </h1> | ||||
| 
 | ||||
|       <div className="flex gap-2 mb-5 mt-5"> | ||||
|         <a | ||||
|           className="text-black no-underline border-2 rounded-lg border-gray-400 rounded p-1 px-2 text-normal hover:text-gray-600" | ||||
|           href={question.url} | ||||
|           target="_blank" | ||||
|         > | ||||
|           {question.platform.label}{" "} | ||||
|           <FaExternalLinkAlt className="text-gray-400 inline sm:text-md text-md mb-1" /> | ||||
|         </a> | ||||
|         <Stars num={question.qualityIndicators.stars} /> | ||||
|         <span className="border-2 border-white p-1 px-2 "> | ||||
|           <QuestionOptions | ||||
|             question={{ ...question }} | ||||
|             maxNumOptions={1} | ||||
|             optionTextSize={"text-normal"} | ||||
|             onlyFirstEstimate={true} | ||||
|           /> | ||||
|         </span> | ||||
|       </div> | ||||
| 
 | ||||
|       <div className="mb-10"> | ||||
|         {question.platform.id === "guesstimate" && question.visualization ? ( | ||||
|           <a className="no-underline" href={question.url} target="_blank"> | ||||
|             <img | ||||
|               className="rounded-sm" | ||||
|               src={question.visualization} | ||||
|               alt="Guesstimate Screenshot" | ||||
|             /> | ||||
|           </a> | ||||
|         ) : ( | ||||
|           <HistoryChart question={question} /> | ||||
|         )} | ||||
|       </div> | ||||
| 
 | ||||
|       <div className="mx-auto max-w-prose"> | ||||
|         <Section title="Question description"> | ||||
|           <ReactMarkdown | ||||
|             linkTarget="_blank" | ||||
|             className="font-normal text-gray-900" | ||||
|           > | ||||
|             {question.description.replaceAll("---", "")} | ||||
|           </ReactMarkdown> | ||||
|         </Section> | ||||
|         <div className="mt-5"> | ||||
|           <Section title="Indicators"> | ||||
|             <IndicatorsTable question={question} /> | ||||
|           </Section> | ||||
|         </div> | ||||
|       </div> | ||||
|     </Card> | ||||
|   ); | ||||
| }; | ||||
| const QuestionScreen: React.FC<{ question: QuestionWithHistoryFragment }> = ({ | ||||
|   question, | ||||
| }) => ( | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user