superhuman report

This commit is contained in:
knugget
2023-02-15 16:40:15 +01:00
parent 04c6462f41
commit 84ed5e7f35
5 changed files with 209 additions and 193 deletions

View File

@@ -63,7 +63,7 @@ export default function OverviewResults() {
<div>
<section aria-labelledby="filters" className="max-w-8xl mx-auto py-8 pt-6 pb-24 ">
<div className="grid grid-cols-1 gap-x-16 gap-y-10 md:grid-cols-4">
<div>
<div className="">
<SubmissionCounter
numFilteredSubmissions={filteredSubmissions.length}
numTotalSubmissions={numTotalSubmissions}
@@ -88,7 +88,7 @@ export default function OverviewResults() {
) : (
<>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
<div className="flex flex-col items-center justify-center rounded-lg bg-white p-2">
<div className="flex flex-col items-center justify-center rounded-lg bg-white p-2 shadow-sm">
<h3 className="text-sm font-medium text-slate-800">Disappointment Level</h3>
<Pie
submissions={filteredSubmissions}
@@ -96,7 +96,7 @@ export default function OverviewResults() {
fieldName={"disappointment"}
/>
</div>
<div className="flex flex-col items-center justify-center rounded-lg bg-white p-2">
<div className="flex flex-col items-center justify-center rounded-lg bg-white p-2 shadow-sm">
<h3 className="text-sm font-medium text-slate-800">Selected Segment</h3>
<Pie submissions={filteredSubmissions} schema={form.schema} fieldName={"role"} />
</div>

View File

@@ -4,6 +4,7 @@ import EmptyPageFiller from "@/components/EmptyPageFiller";
import LoadingSpinner from "@/components/LoadingSpinner";
import PMFThumb2 from "@/images/pmfthumb-2.webp";
import PMFThumb from "@/images/pmfthumb.webp";
import Rahul from "@/images/rahulvohra.jpg";
import { useForm } from "@/lib/forms";
import { getOptionLabelMap, useSubmissions } from "@/lib/submissions";
import { Pie } from "@formbricks/charts";
@@ -13,7 +14,6 @@ import Link from "next/link";
import { useRouter } from "next/router";
import { useMemo, useState } from "react";
import FilterNavigation from "../shared/FilterNavigation";
import { SubmissionCounter } from "../shared/SubmissionCounter";
const limitFields = ["role"];
@@ -56,54 +56,39 @@ export default function SegmentResults() {
return (
<div>
<div>
<section aria-labelledby="filters" className="max-w-8xl mx-auto py-8 pt-6">
<div className="grid grid-cols-1 gap-x-16 gap-y-10 md:grid-cols-4">
<div>
<div>
<SubmissionCounter
numFilteredSubmissions={filteredSubmissions.length}
numTotalSubmissions={submissions.length}
/>
<FilterNavigation
submissions={submissions}
setFilteredSubmissions={setFilteredSubmissions}
limitFields={limitFields}
/>
</div>
<div className="mb-2 flex py-2 text-sm font-bold">
<h4 className="text-slate-600">Tutorials</h4>
</div>
<Link
href="https://review.firstround.com/how-superhuman-built-an-engine-to-find-product-market-fit"
target={"_blank"}>
<div className="mb-4 rounded-md bg-white shadow-sm transition-all duration-100 ease-in-out hover:scale-105">
<Image src={PMFThumb} className="rounded-t-md" alt={"PMF Article Thumb 1"} />
<div className="p-4">
<p className="font-bold text-slate-600">
Superhuman built an engine to find Product-Market Fit
</p>
<p className="text-brand-dark text-sm">firstround.com</p>
</div>
</div>
</Link>
<Link href="https://coda.io/@rahulvohra/superhuman-product-market-fit-engine" target={"_blank"}>
<div className="mb-4 rounded-md bg-white shadow-sm transition-all duration-100 ease-in-out hover:scale-105">
<Image src={PMFThumb2} className="rounded-t-md" alt={"PMF Article Thumb 2"} />
<div className="p-4">
<p className="font-bold text-slate-600">The Superhuman Product/Market Fit Engine</p>
<p className="text-brand-dark text-sm">coda.io</p>
</div>
</div>
</Link>
</div>
<section aria-labelledby="filters" className="max-w-8xl mx-auto py-8 pt-10">
<div className="grid grid-cols-1 gap-x-6 gap-y-10 md:grid-cols-6 xl:gap-x-16">
{/* Double down on what they love*/}
<div className=" md:col-span-3">
<div className=" md:col-span-4">
<div className="mb-4 flex items-center rounded-lg bg-white p-4 shadow-sm lg:p-6">
<Image src={Rahul} alt="Rahul Vohra" className="mr-8 max-h-48 rounded-full" />
<div>
<h2 className="mb-3 text-2xl font-bold text-slate-600">
The Superhuman Product-Market Fit Approach
</h2>
<p className="mb-3 pr-3 text-slate-800">
Rahul Vohra, the founder of Superhuman, had a problem. His team spent over a year
carefully crafting the perfect email client for high-performers. And yet, they
weren&apos;t exactly there yet...
</p>
<p className="mb-3 pr-3 text-slate-800">
He looked for a method to rally his whole team around one goal: Moving closer to
Product-Market Fit. Every feature, every commit should make a difference. After extensive
research and experimentation, he came up with the{" "}
<a
href="https://review.firstround.com/how-superhuman-built-an-engine-to-find-product-market-fit"
target="_blank"
rel="noreferrer"
className="decoration-brand-dark underline">
&apos;Superhuman PMF Engine&apos;
</a>
. This overview will help you execute the same approach - in a fraction of the time.
</p>
</div>
</div>
{submissions.length === 0 ? (
<EmptyPageFiller
alertText="You haven't received any submissions yet."
@@ -113,15 +98,15 @@ export default function SegmentResults() {
</EmptyPageFiller>
) : (
<>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
<div className="flex flex-col items-center justify-center rounded-lg bg-white p-2">
<div className="mb-4 grid grid-cols-1 gap-4 lg:grid-cols-2">
<div className="flex flex-col items-center justify-center rounded-lg bg-white p-2 shadow-sm">
<h3 className="text-sm font-medium text-slate-800">All</h3>
<h3 className="text-xs font-light text-slate-800">
({submissions.length} submissions)
</h3>
<Pie submissions={submissions} schema={form.schema} fieldName={"disappointment"} />
</div>
<div className="flex flex-col items-center justify-center rounded-lg bg-white p-2">
<div className="flex flex-col items-center justify-center rounded-lg bg-white p-2 shadow-sm">
<h3 className="text-sm font-medium text-slate-800">Most disappointed segment</h3>
<h3 className="text-xs font-light text-slate-800">
({filteredSubmissions.length} submissions)
@@ -133,156 +118,187 @@ export default function SegmentResults() {
/>
</div>
</div>
<h2 className="mt-10 mb-4 text-2xl font-bold text-slate-500">
Double down on what they love
</h2>
<div className="rounded-md bg-teal-50 p-4">
<div className="flex">
<div className="flex-shrink-0">
<span className="inline-flex items-center rounded-full bg-teal-100 px-2.5 py-0.5 text-xs font-medium text-teal-800">
How it works
</span>
<div className="mb-4 rounded-lg bg-white p-6 shadow-sm">
<h2 className="my-4 text-xl font-bold text-slate-600">
Step 1: Double down on what they love
</h2>
<p className="mb-6 pr-3 text-slate-800">
Your first priority is making your happiest users happier. By deepening the value they
get from your product, you can make sure to not be taken over my competitors{" "}
<a
className="decoration-brand-dark underline"
href="https://www.lennysnewsletter.com/p/an-inside-look-at-mixpanels-product#details"
target="_blank"
rel="noreferrer">
(like it happened to Mixpanel).
</a>
</p>
<div className="my-4 rounded-lg bg-white">
<div className="text-md rounded-t-lg bg-slate-100 p-4 font-bold text-slate-600">
What is the main benefit you receive from our service?
</div>
<div className="ml-3 flex-1 md:flex md:justify-between">
<p className="text-sm text-teal-700">
Also referred to as &apos;deepening the value&apos;. Build what you&apos;re already
very happy users demand below:
</p>
<div className="grid grid-cols-5 gap-2 bg-slate-100 px-4 pb-2 text-sm font-semibold text-slate-500">
<div className="col-span-3">Response</div>
<div>Disappointment Level</div>
<div>Role</div>
</div>
</div>
</div>
<div className="my-4 rounded-lg bg-white">
<div className="rounded-t-lg bg-slate-100 p-4 text-lg font-bold text-slate-700">
What is the main benefit you receive from our service?
</div>
<div className="grid grid-cols-5 gap-2 bg-slate-100 px-4 pb-2 text-sm font-semibold text-slate-500">
<div className="col-span-3">Response</div>
<div>Disappointment Level</div>
<div>Role</div>
</div>
{lovers.length === 0 ? (
<div className="p-4">
<h3 className="text-center text-sm font-bold text-slate-400">
You dont have any submissions that fit this filter
</h3>
<p className="mt-1 text-center text-xs font-light text-slate-400">
Change your filters or come back when you have more submissions.
</p>
</div>
) : (
<div className="max-h-96 overflow-auto">
{lovers.map((submission) => (
<Link
className="bg-slate-100"
href={`${form.id.startsWith("demo") ? "/demo" : ""}/organisations/${
router.query.organisationId
}/customers/${submission.customerEmail}`}>
<div className="grid grid-cols-5 gap-2 p-4 text-sm hover:bg-slate-100/75">
<div className="col-span-3 text-slate-800">
{submission.data.mainBenefit || <NotProvided />}
</div>
<div>
{submission.data.disappointment === "veryDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
very disappointed
</span>
) : submission.data.disappointment === "notDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">
not disappointed
</span>
) : submission.data.disappointment === "somewhatDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800">
somewhat disappointed
</span>
) : null}
</div>
<div>
<div className="inline-flex items-center rounded-full bg-slate-200 px-2.5 py-0.5 text-xs text-slate-600">
{labelMap[submission.data.role] || <NotProvided />}
{lovers.length === 0 ? (
<div className="p-4">
<h3 className="text-center text-sm font-bold text-slate-400">
You dont have any submissions that fit this filter.
</h3>
<p className="mt-1 text-center text-xs font-light text-slate-400">
Change your filters or come back when you have more submissions.
</p>
</div>
) : (
<div className="max-h-96 overflow-auto rounded-b-lg">
{lovers.map((submission) => (
<Link
href={`${form.id.startsWith("demo") ? "/demo" : ""}/organisations/${
router.query.organisationId
}/customers/${submission.customerEmail}`}>
<div className="grid grid-cols-5 gap-2 bg-slate-50 p-4 text-sm hover:bg-slate-200">
<div className="col-span-3 text-slate-800">
{submission.data.mainBenefit || <NotProvided />}
</div>
<div>
{submission.data.disappointment === "veryDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
very disappointed
</span>
) : submission.data.disappointment === "notDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">
not disappointed
</span>
) : submission.data.disappointment === "somewhatDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800">
somewhat disappointed
</span>
) : null}
</div>
<div>
<div className="inline-flex items-center rounded-full bg-slate-200 px-2.5 py-0.5 text-xs text-slate-600">
{labelMap[submission.data.role] || <NotProvided />}
</div>
</div>
</div>
</div>
</Link>
))}
</div>
)}
</div>
<h2 className="mt-10 mb-4 text-2xl font-bold text-slate-500">
Fix whats holding them back
</h2>
<div className="rounded-md bg-teal-50 p-4">
<div className="flex">
<div className="flex-shrink-0">
<span className="inline-flex items-center rounded-full bg-teal-100 px-2.5 py-0.5 text-xs font-medium text-teal-800">
How it works
</span>
</div>
<div className="ml-3 flex-1 md:flex md:justify-between">
<p className="text-sm text-teal-700">
To make more users very disappointed when your product were to go away, you build
whats holding the somewhat disappointed users back.
</p>
</div>
</Link>
))}
</div>
)}
</div>
</div>
<div className="my-4 rounded-lg bg-white">
<div className="rounded-t-lg bg-slate-100 p-4 text-lg font-bold text-slate-700">
How can we improve our service for you?
</div>
<div className="grid grid-cols-5 gap-2 bg-slate-100 px-4 pb-2 text-sm font-semibold text-slate-500">
<div className="col-span-3">Response</div>
<div>Disappointment Level</div>
<div>Role</div>
</div>
{improvers.length === 0 ? (
<div className="p-4">
<h3 className="text-center text-sm font-bold text-slate-400">
You dont have any submissions that fit this filter
</h3>
<p className="mt-1 text-center text-xs font-light text-slate-400">
Change your filters or come back when you have more submissions.
</p>
<div className="mb-4 rounded-lg bg-white p-6 shadow-sm">
<h2 className="my-4 text-xl font-bold text-slate-600">
Step 2: Fix what&apos;s holding them back
</h2>
<p className="mb-6 pr-3 text-slate-800">
Your second priority is to increase the amount of people who would be &apos;very
disappointed&apos; when they could no longer use your product. This helps you craft a
product for a wider audience.
</p>
<div className="my-4 rounded-lg bg-white">
<div className="text-md rounded-t-lg bg-slate-100 p-4 font-bold text-slate-600">
How can we improve our service for you?
</div>
) : (
<div className="max-h-96 overflow-auto">
{improvers.map((submission) => (
<Link
href={`${form.id.startsWith("demo") ? "/demo" : ""}/organisations/${
router.query.organisationId
}/customers/${submission.customerEmail}`}>
<div className="grid grid-cols-5 gap-2 p-4 text-sm hover:bg-slate-100/75">
<div className="col-span-3 text-slate-800">
{submission.data.improvement || <NotProvided />}
</div>
<div>
{submission.data.disappointment === "veryDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
very disappointed
</span>
) : submission.data.disappointment === "notDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">
not disappointed
</span>
) : submission.data.disappointment === "somewhatDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800">
somewhat disappointed
</span>
) : null}
</div>
<div>
<div className="inline-flex items-center rounded-full bg-slate-200 px-2.5 py-0.5 text-xs text-slate-600">
{labelMap[submission.data.role] || <NotProvided />}
<div className="grid grid-cols-5 gap-2 bg-slate-100 px-4 pb-2 text-sm font-semibold text-slate-500">
<div className="col-span-3">Response</div>
<div>Disappointment Level</div>
<div>Role</div>
</div>
{improvers.length === 0 ? (
<div className="p-4">
<h3 className="text-center text-sm font-bold text-slate-400">
You dont have any submissions that fit this filter
</h3>
<p className="mt-1 text-center text-xs font-light text-slate-400">
Change your filters or come back when you have more submissions.
</p>
</div>
) : (
<div className="max-h-96 overflow-auto">
{improvers.map((submission) => (
<Link
href={`${form.id.startsWith("demo") ? "/demo" : ""}/organisations/${
router.query.organisationId
}/customers/${submission.customerEmail}`}>
<div className="grid grid-cols-5 gap-2 p-4 text-sm hover:bg-slate-100/75">
<div className="col-span-3 text-slate-800">
{submission.data.improvement || <NotProvided />}
</div>
<div>
{submission.data.disappointment === "veryDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
very disappointed
</span>
) : submission.data.disappointment === "notDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">
not disappointed
</span>
) : submission.data.disappointment === "somewhatDisappointed" ? (
<span className="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800">
somewhat disappointed
</span>
) : null}
</div>
<div>
<div className="inline-flex items-center rounded-full bg-slate-200 px-2.5 py-0.5 text-xs text-slate-600">
{labelMap[submission.data.role] || <NotProvided />}
</div>
</div>
</div>
</div>
</Link>
))}
</div>
)}
</Link>
))}
</div>
)}
</div>
</div>
</>
)}
</div>
<div className="col-span-2 h-fit rounded-lg bg-slate-100 p-4 xl:p-8">
<Link
href="https://review.firstround.com/how-superhuman-built-an-engine-to-find-product-market-fit"
target={"_blank"}>
<div className="mb-4 rounded-md bg-white shadow-sm transition-all duration-100 ease-in-out hover:scale-105">
<Image src={PMFThumb} className="w-full rounded-t-md" alt={"PMF Article Thumb 1"} />
<div className="p-4">
<p className="font-bold text-slate-600">
Superhuman built an engine to find Product-Market Fit
</p>
<p className="text-brand-dark mt-1 text-sm">
firstround.com{" "}
<span className="bg-brand-dark ml-2 rounded-full px-2 text-white">In-depth Guide</span>
</p>
</div>
</div>
</Link>
<Link href="https://coda.io/@rahulvohra/superhuman-product-market-fit-engine" target={"_blank"}>
<div className="mb-4 rounded-md bg-white shadow-sm transition-all duration-100 ease-in-out hover:scale-105">
<Image src={PMFThumb2} className="w-full rounded-t-md" alt={"PMF Article Thumb 2"} />
<div className="p-4">
<p className="font-bold text-slate-600">The Superhuman Product/Market Fit Engine</p>
<p className="text-brand-dark text-sm">
coda.io<span className="bg-brand-dark ml-2 rounded-full px-2 text-white">Tutorial</span>
</p>
</div>
</div>
</Link>
<FilterNavigation
submissions={submissions}
setFilteredSubmissions={setFilteredSubmissions}
limitFields={limitFields}
/>
</div>
</div>
</section>
</div>

View File

@@ -194,7 +194,7 @@ export default function FilterNavigation({
<div className="space-y-4">
{filters.map((filter) => (
<div key={filter.name}>
<div className="flex py-2 text-sm font-bold">
<div className="flex space-x-10 py-2 text-sm font-bold">
<h4 className="text-slate-600">{camelToTitle(filter.name)}</h4>
</div>
{filter.options.map((option) => (
@@ -208,7 +208,7 @@ export default function FilterNavigation({
option.active || option.pinned
? "bg-slate-200 text-slate-900"
: "text-slate-600 hover:bg-slate-100 hover:text-slate-900",
"group flex w-full items-center rounded-md px-3 py-2 text-sm font-medium"
"group my-1 flex w-full items-center rounded-md px-3 py-1.5 text-sm font-medium"
)}
aria-current={option.active ? "page" : undefined}>
<div className={clsx("-ml-1 mr-3 h-2 w-2 flex-shrink-0 rounded-full")} />

View File

@@ -1,6 +1,6 @@
export function SubmissionCounter({ numFilteredSubmissions, numTotalSubmissions }) {
return (
<div className="mb-4 rounded-lg bg-white p-3 shadow-md">
<div className="shadow-sms mb-4 rounded-lg bg-white p-3">
<div className="inline-block text-base font-bold text-slate-600">
{numFilteredSubmissions} responses
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB