* refactor: move lighthouse audits to dataforseo (#43) * refactor: move lighthouse audits to dataforseo * chore: remove obsolete audit settings modal * refactor: rename psi flows to lighthouse * save * refactor: simplify audit lighthouse storage flow * fix: separate lighthouse metrics from actionable audits * refactor: remove redundant audit project inputs * feat: redesign lighthouse issues screen with score gauges and table layout Replace flat score cards with circular SVG gauges, condense metrics into a compact grid, and switch issue list from cards to an expandable table with fixed column widths. * test: harden lighthouse regression coverage * fix: restore project-scoped audit inputs * refactor: simplify lighthouse payload handling * refactor: inline lighthouse server handlers * refactor: share audit workflow types * refactor: simplify lighthouse payload flows * save * refactor: drop project pagespeed api key * fix: restore lighthouse issues loading with resilient project context * fix: restore audit issues back navigation * refactor: simplify project context and lighthouse error handling * fix: tolerate DataForSEO lighthouse payload drift * refactor: route audit lighthouse through dataforseo client --------- * refactor: move hosted billing to Autumn hooks * fix: satisfy ci checks for hosted billing * refactor: simplify hosted Autumn billing integration Limit Autumn wiring to the billing route and remove billing-specific indirection so the hosted billing flow is easier to reason about. Stop sending organization IDs as fake customer names to keep customer identity data honest. * fix: satisfy ci line-limit check for hosted billing --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
82 lines
2.0 KiB
TypeScript
82 lines
2.0 KiB
TypeScript
import { createFileRoute, notFound } from "@tanstack/react-router";
|
|
import { AutumnProvider, useCustomer, useListPlans } from "autumn-js/react";
|
|
import { LoaderCircle } from "lucide-react";
|
|
import { CenteredCard } from "@/client/features/billing/BillingRouteParts";
|
|
import { HostedBillingContent } from "@/client/features/billing/HostedBillingContent";
|
|
import { useSession } from "@/lib/auth-client";
|
|
import { isHostedClientAuthMode } from "@/lib/auth-mode";
|
|
|
|
export const Route = createFileRoute("/_app/billing")({
|
|
beforeLoad: () => {
|
|
if (!isHostedClientAuthMode()) {
|
|
throw notFound();
|
|
}
|
|
},
|
|
component: BillingPage,
|
|
});
|
|
|
|
function BillingPage() {
|
|
return (
|
|
<AutumnProvider>
|
|
<BillingPageContent />
|
|
</AutumnProvider>
|
|
);
|
|
}
|
|
|
|
function BillingPageContent() {
|
|
const { data: session, isPending: isSessionPending } = useSession();
|
|
|
|
const customerQuery = useCustomer({
|
|
queryOptions: {
|
|
enabled: Boolean(session?.user?.id),
|
|
},
|
|
});
|
|
|
|
const plansQuery = useListPlans({
|
|
queryOptions: {
|
|
enabled: Boolean(session?.user?.id),
|
|
},
|
|
});
|
|
|
|
if (
|
|
isSessionPending ||
|
|
(session?.user?.id && (customerQuery.isLoading || plansQuery.isLoading))
|
|
) {
|
|
return (
|
|
<div className="flex h-full items-center justify-center">
|
|
<LoaderCircle className="h-6 w-6 animate-spin text-base-content/60" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!session?.user?.id) {
|
|
return (
|
|
<CenteredCard
|
|
title="Sign in to manage billing"
|
|
body="Your hosted billing settings are tied to your OpenSEO organization."
|
|
action={
|
|
<a className="btn btn-primary" href="/sign-in">
|
|
Go to sign in
|
|
</a>
|
|
}
|
|
/>
|
|
);
|
|
}
|
|
|
|
if (customerQuery.isError || plansQuery.isError) {
|
|
return (
|
|
<CenteredCard
|
|
title="Billing unavailable"
|
|
body="We could not load your billing details right now. Please reload and try again."
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<HostedBillingContent
|
|
customerQuery={customerQuery}
|
|
plans={plansQuery.data ?? []}
|
|
/>
|
|
);
|
|
}
|