64 lines
1.8 KiB
TypeScript
64 lines
1.8 KiB
TypeScript
"use client";
|
|
|
|
import { Suspense } from "react";
|
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
import { AuthCard, AuthFooterLink } from "@/components/auth/auth-card";
|
|
import { LoginForm } from "@/components/auth/login-form";
|
|
|
|
function LoginContent() {
|
|
const router = useRouter();
|
|
const params = useSearchParams();
|
|
const next = params.get("next") ?? "/u/me";
|
|
const oauthError = params.get("oauth_error");
|
|
|
|
return (
|
|
<AuthCard
|
|
title="Welcome back"
|
|
description="Log in to access your bookmarks, notes, and collections."
|
|
footer={
|
|
<AuthFooterLink prefix="No account?" href="/signup" label="Create one" />
|
|
}
|
|
>
|
|
{oauthError ? (
|
|
<p className="text-sm text-destructive">
|
|
{oauthErrorMessage(oauthError)}
|
|
</p>
|
|
) : null}
|
|
<LoginForm
|
|
oauthNext={next}
|
|
onSuccess={() => {
|
|
router.push(next);
|
|
router.refresh();
|
|
}}
|
|
/>
|
|
</AuthCard>
|
|
);
|
|
}
|
|
|
|
function oauthErrorMessage(code: string): string {
|
|
switch (code) {
|
|
case "invalid_state":
|
|
case "missing_state":
|
|
return "Your sign-in link expired. Please try again.";
|
|
case "exchange_failed":
|
|
case "profile_failed":
|
|
return "Sign-in failed while talking to the provider. Please try again.";
|
|
case "unknown_provider":
|
|
return "That sign-in provider isn't configured. Please use email or another method.";
|
|
case "unavailable":
|
|
return "Social sign-in is temporarily unavailable. Please use email/password.";
|
|
case "server":
|
|
return "Something went wrong on our side. Please try again in a moment.";
|
|
default:
|
|
return "Sign-in failed. Please try again.";
|
|
}
|
|
}
|
|
|
|
export default function LoginPage() {
|
|
return (
|
|
<Suspense fallback={null}>
|
|
<LoginContent />
|
|
</Suspense>
|
|
);
|
|
}
|