* fix: use full page reload after email verification Client-side navigation via TanStack Router during the auth→app transition can race with Vite HMR, causing "action is not a function" server function errors. * feat: add minimal /subscribe onboarding page New post-auth subscribe page at /subscribe using the same centered layout as auth pages. Shows plan details and a single Subscribe CTA. Redirects PAYMENT_REQUIRED users here instead of /billing. * redesign: rewrite billing page with usage chart and cleaner layout Delete the sprawling multi-component billing page and replace it with a single-file implementation. Two cards sit side by side at the top (subscription summary + buy credits), with a 30-day usage bar chart below powered by Autumn's useAggregateEvents hook and recharts. Removed BillingRouteParts.tsx, HostedBillingContent.tsx, and trimmed HostedBillingContentUtils to only parseTopUpAmount. * polish: billing page improvements and OpenSEO nav link - Two-column layout with subscription summary and buy credits side by side - Usage bar chart using ResizeObserver instead of ResponsiveContainer - Input validation with inline error message - Full-page redirect state when navigating to Stripe - Make OpenSEO logo in navbar link to / * fix: guard app routes and include top-up usage * fix: restore billing onboarding guards Keep unpaid orgs on /subscribe and avoid misleading billing states when Autumn customer lookups fail. * fix: split billing usage chart for ci checks
44 lines
1.1 KiB
TypeScript
44 lines
1.1 KiB
TypeScript
import { Outlet, createFileRoute, useNavigate } from "@tanstack/react-router";
|
|
import { useEffect } from "react";
|
|
import { AuthenticatedAppLayout } from "@/client/layout/AppShell";
|
|
import { useSession } from "@/lib/auth-client";
|
|
import { isHostedClientAuthMode } from "@/lib/auth-mode";
|
|
import {
|
|
getCurrentAuthRedirectFromHref,
|
|
getSignInSearch,
|
|
} from "@/lib/auth-redirect";
|
|
|
|
export const Route = createFileRoute("/_app")({
|
|
component: AppRouteLayout,
|
|
});
|
|
|
|
function AppRouteLayout() {
|
|
const navigate = useNavigate();
|
|
const { data: session, isPending } = useSession();
|
|
const isHostedMode = isHostedClientAuthMode();
|
|
|
|
useEffect(() => {
|
|
if (isPending || !isHostedMode || session?.user?.id) {
|
|
return;
|
|
}
|
|
|
|
void navigate({
|
|
to: "/sign-in",
|
|
search: getSignInSearch(
|
|
getCurrentAuthRedirectFromHref(window.location.href),
|
|
),
|
|
replace: true,
|
|
});
|
|
}, [isPending, isHostedMode, session?.user?.id, navigate]);
|
|
|
|
if (isHostedMode && (isPending || !session?.user?.id)) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<AuthenticatedAppLayout>
|
|
<Outlet />
|
|
</AuthenticatedAppLayout>
|
|
);
|
|
}
|