more
This commit is contained in:
@@ -12,141 +12,9 @@ import TierPicker from "../../components/TierPicker";
|
||||
import "./Subscribe.css";
|
||||
|
||||
const STEPS = ["Create Account", "Choose Plan"];
|
||||
|
||||
export default function Subscribe() {
|
||||
const { currentUser, signup } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
const hasPaymentReturn = searchParams.get("payment") === "success";
|
||||
const [step, setStep] = useState(hasPaymentReturn || currentUser ? 2 : 1);
|
||||
const [loading, setLoading] = useState(hasPaymentReturn);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
const [data, setData] = useState({
|
||||
selectedTier: "",
|
||||
email: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
});
|
||||
|
||||
function set(field, value) {
|
||||
setData((prev) => ({ ...prev, [field]: value }));
|
||||
}
|
||||
|
||||
// Handle Stripe payment returns
|
||||
useEffect(() => {
|
||||
const payment = searchParams.get("payment");
|
||||
const sessionId = searchParams.get("session_id");
|
||||
|
||||
if (payment === "cancelled") {
|
||||
setSearchParams({}, { replace: true });
|
||||
setStep(2);
|
||||
setError("Payment was cancelled. Please try again.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (payment !== "success" || !sessionId) return;
|
||||
|
||||
// Phase 1: no account yet — create it. Auth state change remounts the
|
||||
// component (App.jsx swaps route trees) and Phase 2 runs on the next mount.
|
||||
if (!currentUser) {
|
||||
const savedEmail = sessionStorage.getItem("kp_onboard_email");
|
||||
const savedPw = sessionStorage.getItem("kp_onboard_pw");
|
||||
if (!savedEmail || !savedPw) {
|
||||
setSearchParams({}, { replace: true });
|
||||
setError("Session expired. Please start the signup process again.");
|
||||
setStep(1);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
signup(savedEmail, savedPw).catch((err) => {
|
||||
setSearchParams({}, { replace: true });
|
||||
setError("Account creation failed: " + err.message);
|
||||
setStep(1);
|
||||
setLoading(false);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Phase 2: authenticated — verify the checkout and go to the dashboard.
|
||||
setSearchParams({}, { replace: true });
|
||||
setLoading(true);
|
||||
sessionStorage.removeItem("kp_onboard_email");
|
||||
sessionStorage.removeItem("kp_onboard_pw");
|
||||
|
||||
verifyCheckoutSession(sessionId)
|
||||
.then(() => {
|
||||
navigate("/addresses", { replace: true });
|
||||
})
|
||||
.catch((err) => {
|
||||
setError("Payment verification failed: " + err.message);
|
||||
setStep(2);
|
||||
})
|
||||
.finally(() => setLoading(false));
|
||||
}, [currentUser, searchParams, setSearchParams, signup, navigate]);
|
||||
|
||||
// ── Step handlers ─────────────────────────────────────────────────────────
|
||||
|
||||
function handleStep1() {
|
||||
setError("");
|
||||
if (!data.email || !data.password || !data.confirmPassword) {
|
||||
setError("Please fill in all fields");
|
||||
return;
|
||||
}
|
||||
if (data.password !== data.confirmPassword) {
|
||||
setError("Passwords do not match");
|
||||
return;
|
||||
}
|
||||
if (data.password.length < 6) {
|
||||
setError("Password must be at least 6 characters");
|
||||
return;
|
||||
}
|
||||
setStep(2);
|
||||
}
|
||||
|
||||
async function handleStep2() {
|
||||
setError("");
|
||||
if (!data.selectedTier) {
|
||||
setError("Please select a plan to continue");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
if (data.selectedTier === "free") {
|
||||
if (!currentUser) {
|
||||
await signup(data.email, data.password);
|
||||
}
|
||||
await activateFreeTier();
|
||||
navigate("/addresses", { replace: true });
|
||||
return;
|
||||
}
|
||||
|
||||
sessionStorage.setItem("kp_onboard_email", data.email);
|
||||
sessionStorage.setItem("kp_onboard_pw", data.password);
|
||||
const { url } = await createOnboardingCheckout(
|
||||
data.email,
|
||||
data.selectedTier,
|
||||
);
|
||||
window.location.href = url;
|
||||
} catch (err) {
|
||||
if (err.code === "auth/email-already-in-use") {
|
||||
setError("Email already in use. Try logging in instead.");
|
||||
} else if (err.code === "auth/invalid-email") {
|
||||
setError("Invalid email address");
|
||||
} else if (err.code === "auth/weak-password") {
|
||||
setError("Password is too weak");
|
||||
} else {
|
||||
setError("Failed to process plan selection: " + err.message);
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Progress bar ──────────────────────────────────────────────────────────
|
||||
|
||||
function ProgressBar() {
|
||||
return (
|
||||
@@ -165,8 +33,7 @@ export default function Subscribe() {
|
||||
<div key={label} className="progress-bar__step">
|
||||
{i > 0 && (
|
||||
<div
|
||||
className={`progress-bar__connector ${
|
||||
done || active
|
||||
className={`progress-bar__connector ${done || active
|
||||
? "progress-bar__connector--active"
|
||||
: "progress-bar__connector--inactive"
|
||||
}`}
|
||||
@@ -177,8 +44,7 @@ export default function Subscribe() {
|
||||
{done ? "\u2713" : stepNum}
|
||||
</div>
|
||||
<div
|
||||
className={`progress-bar__label ${
|
||||
active
|
||||
className={`progress-bar__label ${active
|
||||
? "progress-bar__label--active"
|
||||
: "progress-bar__label--inactive"
|
||||
}`}
|
||||
|
||||
Reference in New Issue
Block a user