From 56902636060ef267e95a0fcc7578b88c11e27036 Mon Sep 17 00:00:00 2001 From: Alexander Kadyrov <gruz0.mail@gmail.com> Date: Fri, 17 Jan 2025 17:33:26 +0400 Subject: [PATCH] Refine concept pages --- .../concepts/[id]/NotWellDefinedProblem.tsx | 42 ++-- .../concepts/[id]/ProblemRequiresChanges.tsx | 186 +++++++++++------- src/app/concepts/[id]/ReportPage.tsx | 41 +--- src/app/concepts/[id]/WellDefinedProblem.tsx | 38 +++- src/components/ConceptForm.tsx | 5 +- src/components/Section.tsx | 2 +- 6 files changed, 183 insertions(+), 131 deletions(-) diff --git a/src/app/concepts/[id]/NotWellDefinedProblem.tsx b/src/app/concepts/[id]/NotWellDefinedProblem.tsx index 52c9fab..12857be 100644 --- a/src/app/concepts/[id]/NotWellDefinedProblem.tsx +++ b/src/app/concepts/[id]/NotWellDefinedProblem.tsx @@ -1,7 +1,7 @@ 'use client' import React from 'react' import ConceptForm from '@/components/ConceptForm' -import Paragraph from '@/components/Paragraph' + import Section from '@/components/Section' interface TargetAudience { @@ -26,22 +26,19 @@ interface Props { const NotWellDefinedProblem = ({ problem, evaluation }: Props) => ( <div> - <Section header="Oops! We Need a Bit More Information 🤔"> - <Paragraph> - It seems that the problem you've shared is a bit too unclear for us - to analyze the market effectively. - </Paragraph> - - <Paragraph> - To provide you with the best insights, could you please give us more - details about the specific challenges your product aims to solve? The - clearer you can be about the problem, the better we can assist you in - understanding the potential market for your idea. Feel free to give it - another shot in the form below! - </Paragraph> - </Section> + <h1 className="mb-6 text-3xl font-bold text-red-600 md:text-4xl"> + Hmm, We Need More Clarity! 🤔 + </h1> + + <p className="mb-6 text-lg md:text-2xl"> + No worries—sometimes ideas need a bit more detail. Let's make sure we + fully capture what you're trying to build, so we can offer the best + insights. + </p> + + <hr className="my-6 md:my-8" /> - <Section header="This Is How You Can Improve Your Problem Statement:"> + <Section header="✍️ Try These Steps to Sharpen Your Idea:"> <div className="grid grid-cols-1 gap-4 md:gap-6"> {evaluation.suggestions.map((item, index) => ( <div @@ -56,7 +53,18 @@ const NotWellDefinedProblem = ({ problem, evaluation }: Props) => ( <hr className="my-6 md:my-8" /> - <ConceptForm problem={problem} /> + <Section header="💡 Example of a Clear Problem Statement:"> + <div className="rounded-lg border border-gray-200 bg-gray-50 p-4 md:px-6 md:text-lg dark:bg-gray-900/50"> + I'm building a mobile app that connects local freelancers with + small businesses needing short-term services. My goal is to reduce the + time freelancers spend searching for gigs and provide businesses with a + quick hiring tool. + </div> + </Section> + + <hr className="my-6 md:my-8" /> + + <ConceptForm problem={problem} cta="Give It Another Shot" /> </div> ) diff --git a/src/app/concepts/[id]/ProblemRequiresChanges.tsx b/src/app/concepts/[id]/ProblemRequiresChanges.tsx index 15f3199..b2fbfe5 100644 --- a/src/app/concepts/[id]/ProblemRequiresChanges.tsx +++ b/src/app/concepts/[id]/ProblemRequiresChanges.tsx @@ -76,46 +76,57 @@ const ProblemRequiresChanges = ({ conceptId, problem, evaluation }: Props) => { return ( <div> + <h1 className="mb-6 text-3xl font-bold text-orange-600 md:text-4xl"> + Looks Good, But Let's Polish It Up + </h1> + {evaluation.marketExistence ? ( - <Section header="Market Existence:"> - <Paragraph> - {evaluation.marketExistence.split('\n').map((line, index) => ( - <React.Fragment key={index}> - {line} - <br /> - </React.Fragment> - ))} - </Paragraph> - </Section> + <> + <p className="mb-6 text-lg md:text-2xl"> + Your idea is off to a great start. We can either dive into the full + analysis now, or you can refine your problem statement for even more + accurate insights. + </p> + + <hr className="my-6 md:my-8" /> + + <Section header="🔎 How Big Could This Get?"> + <Paragraph> + {evaluation.marketExistence.split('\n').map((line, index) => ( + <React.Fragment key={index}> + {line} + <br /> + </React.Fragment> + ))} + </Paragraph> + </Section> + </> ) : ( - <Section header="Oops! We Need a Bit More Information 🤔"> - <Paragraph> - It looks like the problem you've provided is a little too vague - for us to figure out the market landscape. To give you the best - insights, could you please add more details about the specific - challenges your product addresses? The clearer your problem - definition, the better we can help you understand the potential - market for your idea. - </Paragraph> - + <Section header="Hmm, We Need More Clarity! 🤔"> <Paragraph> - Feel free to give it another shot in the form below! + No worries—sometimes ideas need a bit more detail. Let's make + sure we fully capture what you're trying to build, so we can + offer the best insights. </Paragraph> </Section> )} - <Section header="How You Described a Problem:"> - <Paragraph> + <hr className="my-6 md:my-8" /> + + <Section header="📝 Your Original Statement:"> + <div className="rounded-lg border border-gray-200 bg-gray-50 p-4 md:px-6 md:text-lg dark:bg-gray-900/50"> {problem.split('\n').map((line, index) => ( <React.Fragment key={index}> {line} <br /> </React.Fragment> ))} - </Paragraph> + </div> </Section> - <Section header="How To Improve Your Problem Statement:"> + <hr className="my-6 md:my-8" /> + + <Section header="✍️ Try These Steps to Sharpen Your Idea:"> <div className="grid grid-cols-1 gap-4 md:grid-cols-2 md:gap-6"> {evaluation.suggestions.map((item, index) => ( <div @@ -131,56 +142,81 @@ const ProblemRequiresChanges = ({ conceptId, problem, evaluation }: Props) => { </Section> {evaluation.recommendations.length > 0 && ( - <Section header="Alternative Problem Statements That Might Fit Better:"> - <div className="mb-6 grid grid-cols-1 gap-4 md:gap-6"> - {evaluation.recommendations.map((item, index) => ( - <div - key={index} - className="flex flex-col rounded-lg border border-gray-200 bg-gray-50 p-4 md:p-6 dark:bg-gray-900/50" - > - <p className="grow md:text-lg">{item}</p> - - <div className="mt-6"> - <Link - href={{ - pathname: '/start', - query: { problem: item }, - }} - target="_blank" - className="rounded bg-gray-500 px-4 py-2 text-white transition duration-300 hover:bg-blue-700" - > - Validate This Problem Instead - </Link> + <> + <hr className="my-6 md:my-8" /> + + <Section header="💡 Or Try These Auto-Generated Rewrites and Tweaks:"> + <div className="mb-6 grid grid-cols-1 gap-4 md:gap-6"> + {evaluation.recommendations.map((item, index) => ( + <div + key={index} + className="flex flex-col rounded-lg border border-gray-200 bg-gray-50 p-4 md:p-6 dark:bg-gray-900/50" + > + <p className="grow md:text-lg">{item}</p> + + <div className="mt-6"> + <Link + href={{ + pathname: '/start', + query: { problem: item }, + }} + target="_blank" + className="inline-flex items-center gap-2 rounded bg-gray-500 px-4 py-2 text-white transition duration-300 hover:bg-blue-700" + > + Validate This Problem Instead + <svg + xmlns="http://www.w3.org/2000/svg" + viewBox="0 0 20 20" + fill="currentColor" + className="size-4" + > + <path + fillRule="evenodd" + d="M4.25 5.5a.75.75 0 00-.75.75v8.5c0 .414.336.75.75.75h8.5a.75.75 0 00.75-.75v-4a.75.75 0 011.5 0v4A2.25 2.25 0 0112.75 17h-8.5A2.25 2.25 0 012 14.75v-8.5A2.25 2.25 0 014.25 4h5a.75.75 0 010 1.5h-5z" + clipRule="evenodd" + /> + <path + fillRule="evenodd" + d="M6.194 12.753a.75.75 0 001.06.053L16.5 4.44v2.81a.75.75 0 001.5 0v-4.5a.75.75 0 00-.75-.75h-4.5a.75.75 0 000 1.5h2.553l-9.056 8.194a.75.75 0 00-.053 1.06z" + clipRule="evenodd" + /> + </svg> + </Link> + </div> </div> - </div> - ))} - </div> - </Section> + ))} + </div> + </Section> + </> )} {evaluation.targetAudience.length > 0 && ( - <Section header="Target Audiences:"> - <div className="grid grid-cols-1 gap-6"> - {evaluation.targetAudience.map((item, index) => ( - <div - key={index} - className="flex flex-col rounded-lg border border-gray-200 bg-gray-50 p-4 pb-0 md:p-6 md:pb-0 dark:bg-gray-900/50" - > - <p className="mb-4 text-lg font-bold md:text-xl"> - {item.segment} - </p> - - <p className="mb-4 md:text-lg">{item.description}</p> - - <p className="mb-4 font-semibold md:text-lg"> - Their Challenges: - </p> - - <SimpleUnorderedList items={item.challenges} /> - </div> - ))} - </div> - </Section> + <> + <hr className="my-6 md:my-8" /> + + <Section header="👥 Who's This Really For?"> + <div className="grid grid-cols-1 gap-6"> + {evaluation.targetAudience.map((item, index) => ( + <div + key={index} + className="flex flex-col rounded-lg border border-gray-200 bg-gray-50 p-4 pb-0 md:p-6 md:pb-0 dark:bg-gray-900/50" + > + <p className="mb-4 text-lg font-bold md:text-xl"> + {item.segment} + </p> + + <p className="mb-4 md:text-lg">{item.description}</p> + + <p className="mb-4 font-semibold md:text-lg"> + Their Challenges: + </p> + + <SimpleUnorderedList items={item.challenges} /> + </div> + ))} + </div> + </Section> + </> )} <hr className="my-6 md:my-8" /> @@ -192,7 +228,11 @@ const ProblemRequiresChanges = ({ conceptId, problem, evaluation }: Props) => { )} {evaluation.marketExistence && evaluation.targetAudience.length > 0 ? ( - <div className="py-2 text-center md:py-4"> + <Section header="Ready for a Full Breakdown?"> + <p className="mb-6 text-lg md:text-xl"> + Explore complete competitor breakdowns, marketing angles, and more. + </p> + <button type="button" onClick={handleSubmit} @@ -201,7 +241,7 @@ const ProblemRequiresChanges = ({ conceptId, problem, evaluation }: Props) => { > {status === 'loading' ? 'Saving...' : 'Go To Detailed Analysis'} </button> - </div> + </Section> ) : ( <ConceptForm problem={problem} hideExamples /> )} diff --git a/src/app/concepts/[id]/ReportPage.tsx b/src/app/concepts/[id]/ReportPage.tsx index 5c8bf01..8658f53 100644 --- a/src/app/concepts/[id]/ReportPage.tsx +++ b/src/app/concepts/[id]/ReportPage.tsx @@ -37,40 +37,15 @@ const ReportPage = ({ concept }: Props) => { return ( <div className="p-4 md:p-6 lg:p-8"> - <h1 className="mb-6 text-3xl font-bold md:text-4xl"> - Concept Evaluation:{' '} - {concept.evaluation ? ( - <span - className={ - concept.evaluation.status === 'well-defined' - ? 'text-green-600' - : concept.evaluation.status === 'requires_changes' - ? 'text-orange-600' - : 'text-red-600' - } - > - {concept.evaluation.status === 'well-defined' - ? 'Well-defined' - : concept.evaluation.status === 'requires_changes' - ? 'Requires changes' - : 'Not well-defined'} - </span> - ) : ( - <span>Loading...</span> - )} - </h1> - - {concept.evaluation ? ( - <> - <hr className="my-6 md:my-8" /> + {concept.evaluation && ( + <ProblemEvaluationPage + conceptId={concept.id} + problem={concept.problem} + evaluation={concept.evaluation} + /> + )} - <ProblemEvaluationPage - conceptId={concept.id} - problem={concept.problem} - evaluation={concept.evaluation} - /> - </> - ) : ( + {!concept.evaluation && ( <> <FetchingDataMessage /> diff --git a/src/app/concepts/[id]/WellDefinedProblem.tsx b/src/app/concepts/[id]/WellDefinedProblem.tsx index 4e63bea..2f718d8 100644 --- a/src/app/concepts/[id]/WellDefinedProblem.tsx +++ b/src/app/concepts/[id]/WellDefinedProblem.tsx @@ -73,7 +73,25 @@ const WellDefinedProblem = ({ conceptId, evaluation }: Props) => { return ( <div> - <Section header="Here's What We've Found:"> + <h1 className="mb-6 text-3xl font-bold text-green-600 md:text-4xl"> + Great news! Your Idea Looks Solid! + </h1> + + <p className="mb-6 text-lg md:text-2xl"> + Based on your concept, here's a quick look at your potential + audience, market gaps, and common pain points. This snapshot uses a + GPT-4o AI model, so treat it as an informed starting point—not the final + word. + </p> + + <p className="mb-6 text-lg md:text-2xl"> + Scroll down to see the highlights and request a detailed report for + deeper analysis. + </p> + + <hr className="my-6 md:my-8" /> + + <Section header="🔎 How Big Could This Get?"> <Paragraph> {evaluation.marketExistence.split('\n').map((line, index) => ( <React.Fragment key={index}> @@ -84,7 +102,9 @@ const WellDefinedProblem = ({ conceptId, evaluation }: Props) => { </Paragraph> </Section> - <Section header="Common Pain Points That Are Relevant to The Problem:"> + <hr className="my-6 md:my-8" /> + + <Section header="⚠️ What's Bugging Your Users?"> <div className="grid grid-cols-1 gap-4 md:grid-cols-2 md:gap-6"> {evaluation.painPoints.map((item, index) => ( <div @@ -99,7 +119,9 @@ const WellDefinedProblem = ({ conceptId, evaluation }: Props) => { </div> </Section> - <Section header="Target Audiences:"> + <hr className="my-6 md:my-8" /> + + <Section header="👥 Who's This Really For?"> <div className="grid grid-cols-1 gap-6"> {evaluation.targetAudience.map((item, index) => ( <div @@ -126,7 +148,13 @@ const WellDefinedProblem = ({ conceptId, evaluation }: Props) => { </div> )} - <div className="py-2 text-center md:py-4"> + <hr className="my-6 md:my-8" /> + + <Section header="Ready for a Full Breakdown?"> + <p className="mb-6 text-lg md:text-xl"> + Explore complete competitor breakdowns, marketing angles, and more. + </p> + <button type="button" onClick={handleSubmit} @@ -135,7 +163,7 @@ const WellDefinedProblem = ({ conceptId, evaluation }: Props) => { > {status === 'loading' ? 'Saving...' : 'Go To Detailed Analysis'} </button> - </div> + </Section> </div> ) } diff --git a/src/components/ConceptForm.tsx b/src/components/ConceptForm.tsx index 02b4a44..9e50e28 100644 --- a/src/components/ConceptForm.tsx +++ b/src/components/ConceptForm.tsx @@ -7,6 +7,7 @@ import Paragraph from '@/components/Paragraph' interface Props { problem: string hideExamples?: boolean + cta?: string } const examples = [ @@ -84,7 +85,7 @@ Target Audience: }, ] -const DefineConceptForm = ({ problem, hideExamples }: Props) => { +const DefineConceptForm = ({ problem, hideExamples, cta }: Props) => { const [status, setStatus] = useState<string>('idle') const [errorMessage, setErrorMessage] = useState<string | null>(null) const [showHint, setShowHint] = useState<boolean>(false) @@ -206,7 +207,7 @@ Target Audience: className="rounded-md border border-transparent bg-blue-600 px-6 py-4 text-2xl font-medium text-white shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2" disabled={status === 'loading'} > - {status === 'loading' ? 'Saving...' : 'Analyze Idea'} + {status === 'loading' ? 'Saving...' : cta || 'Analyze Idea'} </button> </div> diff --git a/src/components/Section.tsx b/src/components/Section.tsx index b7ecee1..5bfd65e 100644 --- a/src/components/Section.tsx +++ b/src/components/Section.tsx @@ -8,7 +8,7 @@ interface SectionProps { const Section: React.FC<SectionProps> = ({ header, children }) => ( <div className="mb-8"> {header && ( - <div className="mb-4 flex items-center justify-between"> + <div className="mb-4 flex items-center justify-between md:mb-6 lg:mb-8"> <h3 className="text-xl font-semibold md:text-2xl">{header}</h3> </div> )}