Route landing account sign-ins to checkout
This commit is contained in:
@@ -96,7 +96,7 @@ async function resolvePostAuthRedirect({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const redirectPath =
|
const redirectPath =
|
||||||
profile?.subscription_active === false ? TERMINAL_CHECKOUT_PATH : nextPath;
|
profile?.subscription_active === true ? nextPath : TERMINAL_CHECKOUT_PATH;
|
||||||
return new URL(redirectPath, baseUrl);
|
return new URL(redirectPath, baseUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -675,7 +675,7 @@ export function AccountCenter() {
|
|||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<Link
|
<Link
|
||||||
href="/auth/login?next=%2Faccount"
|
href="/auth/login?next=%2Faccount%3Fcheckout%3D1"
|
||||||
className="flex items-center gap-2 rounded-lg border border-blue-200 bg-blue-50 px-4 py-2 text-sm font-semibold text-blue-700 transition-all hover:bg-blue-100"
|
className="flex items-center gap-2 rounded-lg border border-blue-200 bg-blue-50 px-4 py-2 text-sm font-semibold text-blue-700 transition-all hover:bg-blue-100"
|
||||||
>
|
>
|
||||||
<LogIn size={16} /> {copy.signIn}
|
<LogIn size={16} /> {copy.signIn}
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ export function runTests() {
|
|||||||
const accountCenter = fs.readFileSync(path.join(accountDir, "AccountCenter.tsx"), "utf8");
|
const accountCenter = fs.readFileSync(path.join(accountDir, "AccountCenter.tsx"), "utf8");
|
||||||
const paymentFlow = fs.readFileSync(path.join(accountDir, "usePaymentFlow.ts"), "utf8");
|
const paymentFlow = fs.readFileSync(path.join(accountDir, "usePaymentFlow.ts"), "utf8");
|
||||||
const accountPayment = fs.readFileSync(path.join(accountDir, "useAccountPayment.ts"), "utf8");
|
const accountPayment = fs.readFileSync(path.join(accountDir, "useAccountPayment.ts"), "utf8");
|
||||||
|
const landingPage = fs.readFileSync(
|
||||||
|
path.join(projectRoot, "components", "landing", "InstitutionalLandingPage.tsx"),
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
|
const landingAuthActions = fs.readFileSync(
|
||||||
|
path.join(projectRoot, "components", "landing", "LandingAuthActions.tsx"),
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
const productAccess = fs.readFileSync(
|
const productAccess = fs.readFileSync(
|
||||||
path.join(projectRoot, "components", "dashboard", "scan-terminal", "ProductAccessRequired.tsx"),
|
path.join(projectRoot, "components", "dashboard", "scan-terminal", "ProductAccessRequired.tsx"),
|
||||||
"utf8",
|
"utf8",
|
||||||
@@ -30,6 +38,19 @@ export function runTests() {
|
|||||||
"account page must support /account?checkout=1 for direct upgrade entry",
|
"account page must support /account?checkout=1 for direct upgrade entry",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
accountCenter.includes('href="/auth/login?next=%2Faccount%3Fcheckout%3D1"'),
|
||||||
|
"account page sign-in button must preserve the checkout entry for unauthenticated subscription recovery",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
landingAuthActions.includes('href="/account?checkout=1"') &&
|
||||||
|
landingPage.includes('href="/account?checkout=1"') &&
|
||||||
|
!/href="\/account"(?![/?#])/.test(landingAuthActions) &&
|
||||||
|
!/href="\/account"(?![/?#])/.test(landingPage),
|
||||||
|
"landing subscription/account CTAs must open the checkout account entry instead of a generic account page",
|
||||||
|
);
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
productAccess.includes('href="/account?checkout=1"') &&
|
productAccess.includes('href="/account?checkout=1"') &&
|
||||||
productAccess.includes("Renew and restore access") &&
|
productAccess.includes("Renew and restore access") &&
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ async function resolvePostLoginRedirect({
|
|||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!response.ok) return nextPath;
|
if (!response.ok) return TERMINAL_CHECKOUT_PATH;
|
||||||
const payload = await response.json();
|
const payload = await response.json();
|
||||||
return payload?.subscription_active === false
|
return payload?.subscription_active === true
|
||||||
? TERMINAL_CHECKOUT_PATH
|
? nextPath
|
||||||
: nextPath;
|
: TERMINAL_CHECKOUT_PATH;
|
||||||
} catch {
|
} catch {
|
||||||
return nextPath;
|
return TERMINAL_CHECKOUT_PATH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,19 +20,22 @@ export function runTests() {
|
|||||||
loginClientSource.includes("TERMINAL_CHECKOUT_PATH") &&
|
loginClientSource.includes("TERMINAL_CHECKOUT_PATH") &&
|
||||||
loginClientSource.includes('"/account?checkout=1"') &&
|
loginClientSource.includes('"/account?checkout=1"') &&
|
||||||
loginClientSource.includes("resolvePostLoginRedirect") &&
|
loginClientSource.includes("resolvePostLoginRedirect") &&
|
||||||
loginClientSource.includes("subscription_active === false") &&
|
loginClientSource.includes("subscription_active === true") &&
|
||||||
|
loginClientSource.includes("return TERMINAL_CHECKOUT_PATH") &&
|
||||||
loginClientSource.includes("router.replace(redirectPath)") &&
|
loginClientSource.includes("router.replace(redirectPath)") &&
|
||||||
|
!loginClientSource.includes("if (!response.ok) return nextPath;") &&
|
||||||
|
!loginClientSource.includes("catch {\n return nextPath;") &&
|
||||||
!loginClientSource.includes("router.replace(nextPath);\n return;"),
|
!loginClientSource.includes("router.replace(nextPath);\n return;"),
|
||||||
"email/password terminal login must send non-members to the checkout account page instead of blindly returning to /terminal",
|
"email/password terminal login must only enter /terminal after confirmed active subscription; unknown or inactive users go to checkout",
|
||||||
);
|
);
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
authCallbackSource.includes("resolvePostAuthRedirect") &&
|
authCallbackSource.includes("resolvePostAuthRedirect") &&
|
||||||
authCallbackSource.includes("TERMINAL_CHECKOUT_PATH") &&
|
authCallbackSource.includes("TERMINAL_CHECKOUT_PATH") &&
|
||||||
authCallbackSource.includes('"/account?checkout=1"') &&
|
authCallbackSource.includes('"/account?checkout=1"') &&
|
||||||
authCallbackSource.includes("subscription_active === false") &&
|
authCallbackSource.includes("subscription_active === true") &&
|
||||||
authCallbackSource.includes("NextResponse.redirect(redirectUrl)") &&
|
authCallbackSource.includes("NextResponse.redirect(redirectUrl)") &&
|
||||||
authCallbackSource.includes("await resolvePostAuthRedirect"),
|
authCallbackSource.includes("await resolvePostAuthRedirect"),
|
||||||
"OAuth terminal callback must send non-members to the checkout account page instead of blindly returning to /terminal",
|
"OAuth terminal callback must only enter /terminal after confirmed active subscription; unknown or inactive users go to checkout",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -659,7 +659,7 @@ function InstitutionalLandingScreen({ locale }: { locale: LandingLocale }) {
|
|||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
<Link
|
<Link
|
||||||
href="/account"
|
href="/account?checkout=1"
|
||||||
className="mt-8 inline-flex h-11 items-center justify-center gap-2 rounded-md bg-slate-950 text-sm font-bold text-white hover:bg-slate-800"
|
className="mt-8 inline-flex h-11 items-center justify-center gap-2 rounded-md bg-slate-950 text-sm font-bold text-white hover:bg-slate-800"
|
||||||
>
|
>
|
||||||
{isEn ? "Subscribe monthly" : "订阅月付 Pro"}
|
{isEn ? "Subscribe monthly" : "订阅月付 Pro"}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ export function LandingHeaderActions({ locale }: { locale: LandingLocale }) {
|
|||||||
<ArrowIcon />
|
<ArrowIcon />
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="/account"
|
href="/account?checkout=1"
|
||||||
className="grid h-9 w-9 place-items-center rounded-md border border-slate-200 bg-white text-slate-600 shadow-sm hover:border-slate-300 hover:text-slate-950"
|
className="grid h-9 w-9 place-items-center rounded-md border border-slate-200 bg-white text-slate-600 shadow-sm hover:border-slate-300 hover:text-slate-950"
|
||||||
title={isEn ? "Account" : "账户"}
|
title={isEn ? "Account" : "账户"}
|
||||||
aria-label={isEn ? "Account" : "账户"}
|
aria-label={isEn ? "Account" : "账户"}
|
||||||
@@ -181,7 +181,7 @@ export function LandingHeroActions({ locale }: { locale: LandingLocale }) {
|
|||||||
<ArrowIcon />
|
<ArrowIcon />
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="/account"
|
href="/account?checkout=1"
|
||||||
className="inline-flex h-11 items-center justify-center gap-2 rounded-md border border-slate-200 bg-white px-5 text-sm font-bold text-slate-700 shadow-sm hover:border-slate-300 hover:text-slate-950"
|
className="inline-flex h-11 items-center justify-center gap-2 rounded-md border border-slate-200 bg-white px-5 text-sm font-bold text-slate-700 shadow-sm hover:border-slate-300 hover:text-slate-950"
|
||||||
>
|
>
|
||||||
{isEn ? "Subscribe / account" : "订阅 / 账户"}
|
{isEn ? "Subscribe / account" : "订阅 / 账户"}
|
||||||
|
|||||||
Reference in New Issue
Block a user