88 lines
3.6 KiB
TypeScript
88 lines
3.6 KiB
TypeScript
// components/pricing/PlanRecommender.tsx
|
||
"use client";
|
||
|
||
import { useMemo, useState } from "react";
|
||
import { Plan } from "./types";
|
||
|
||
export default function PlanRecommender({ plans }: { plans: Plan[] }) {
|
||
const [sessions, setSessions] = useState<number>(5000);
|
||
const [risk, setRisk] = useState<"low" | "medium" | "high">("medium");
|
||
const [hours, setHours] = useState<"business" | "around" | "always">("around");
|
||
|
||
const recommended = useMemo(() => {
|
||
// Simple heuristic: higher sessions + high risk + always-on => mission; else growth; else essential
|
||
if (sessions >= 20000 || risk === "high" || hours === "always") return "mission";
|
||
if (sessions >= 7000 || risk === "medium") return "growth";
|
||
return "essential";
|
||
}, [sessions, risk, hours]);
|
||
|
||
const plan = plans.find((p) => p.id === recommended)!;
|
||
|
||
return (
|
||
<div className="rounded-2xl border border-gray-200 bg-white p-6 shadow-sm">
|
||
<h2 className="text-xl font-semibold">Not sure where to start?</h2>
|
||
<p className="mt-1 text-sm text-gray-600">
|
||
Answer three quick questions and we’ll suggest a plan.
|
||
</p>
|
||
|
||
<div className="mt-6 grid gap-6 md:grid-cols-3">
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700">
|
||
Monthly sessions (est.)
|
||
</label>
|
||
<input
|
||
type="number"
|
||
className="mt-2 w-full rounded-lg border border-gray-300 px-3 py-2"
|
||
value={sessions}
|
||
onChange={(e) => setSessions(Number(e.target.value || 0))}
|
||
min={0}
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700">Risk tolerance</label>
|
||
<select
|
||
className="mt-2 w-full rounded-lg border border-gray-300 px-3 py-2"
|
||
value={risk}
|
||
onChange={(e) => setRisk(e.target.value as any)}
|
||
>
|
||
<option value="low">Low (occasional issues okay)</option>
|
||
<option value="medium">Medium (prefer stability)</option>
|
||
<option value="high">High (incidents must be rare)</option>
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700">Support window</label>
|
||
<select
|
||
className="mt-2 w-full rounded-lg border border-gray-300 px-3 py-2"
|
||
value={hours}
|
||
onChange={(e) => setHours(e.target.value as any)}
|
||
>
|
||
<option value="business">Business hours</option>
|
||
<option value="around">Extended (early/late)</option>
|
||
<option value="always">24/7</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mt-6 rounded-xl border border-emerald-200 bg-emerald-50 p-4">
|
||
<p className="text-sm font-semibold text-emerald-900">Recommended plan</p>
|
||
<p className="mt-1 text-lg font-semibold">
|
||
{plan.name} <span className="text-sm font-normal text-emerald-900">— {plan.bestFor}</span>
|
||
</p>
|
||
<p className="mt-1 text-sm text-emerald-900">
|
||
You indicated {sessions.toLocaleString()} sessions/mo, {risk} risk tolerance, and{" "}
|
||
{hours === "always" ? "24/7" : hours === "around" ? "extended" : "business-hours"} support.
|
||
</p>
|
||
<div className="mt-3">
|
||
<a
|
||
href={plan.contactOnly ? "/contact" : `/checkout?plan=${plan.id}`}
|
||
className="inline-flex items-center rounded-lg bg-emerald-600 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-700"
|
||
>
|
||
{plan.contactOnly ? "Talk to us" : "Start " + plan.name}
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|