♻️ Clean up login page code (#1525)

This commit is contained in:
Luke Vella 2025-01-28 15:01:17 +00:00 committed by GitHub
parent fa3f5a9df3
commit 0117464344
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 50 additions and 107 deletions

View file

@ -1,8 +1,12 @@
"use client";
import { Button } from "@rallly/ui/button"; import { Button } from "@rallly/ui/button";
import { signIn } from "next-auth/react"; import { signIn } from "next-auth/react";
import { Trans } from "react-i18next/TransWithoutContext";
import { getTranslation } from "@/i18n/server";
export async function LoginWithOIDC({ name }: { name: string }) {
const { t } = await getTranslation();
export function LoginWithOIDC({ children }: { children: React.ReactNode }) {
return ( return (
<Button <Button
onClick={() => { onClick={() => {
@ -10,7 +14,13 @@ export function LoginWithOIDC({ children }: { children: React.ReactNode }) {
}} }}
variant="link" variant="link"
> >
{children} <Trans
t={t}
i18nKey="continueWithProvider"
ns="app"
defaultValue="Login with {{provider}}"
values={{ provider: name }}
/>
</Button> </Button>
); );
} }

View file

@ -1,8 +1,11 @@
export function OrDivider({ text }: { text: string }) { import { getTranslation } from "@/i18n/server";
export async function OrDivider() {
const { t } = await getTranslation();
return ( return (
<div className="flex items-center gap-x-2.5"> <div className="flex items-center gap-x-2.5">
<hr className="grow border-gray-100" /> <hr className="grow border-gray-100" />
<div className="text-muted-foreground lowercase">{text}</div> <div className="text-muted-foreground lowercase">{t("or")}</div>
<hr className="grow border-gray-100" /> <hr className="grow border-gray-100" />
</div> </div>
); );

View file

@ -1,8 +1,7 @@
import { unstable_cache } from "next/cache";
import Link from "next/link"; import Link from "next/link";
import { getProviders } from "next-auth/react";
import { Trans } from "react-i18next/TransWithoutContext"; import { Trans } from "react-i18next/TransWithoutContext";
import { getOAuthProviders } from "@/auth";
import { getTranslation } from "@/i18n/server"; import { getTranslation } from "@/i18n/server";
import { import {
@ -17,44 +16,20 @@ import { AuthErrors } from "./components/auth-errors";
import { LoginWithEmailForm } from "./components/login-email-form"; import { LoginWithEmailForm } from "./components/login-email-form";
import { LoginWithOIDC } from "./components/login-with-oidc"; import { LoginWithOIDC } from "./components/login-with-oidc";
import { OrDivider } from "./components/or-divider"; import { OrDivider } from "./components/or-divider";
import { SSOProviders } from "./sso-providers"; import { SSOProvider } from "./components/sso-provider";
export const dynamic = "force-dynamic";
export const revalidate = 0;
async function getOAuthProviders() {
const providers = await getProviders();
if (!providers) {
return [];
}
return Object.values(providers)
.filter((provider) => provider.type === "oauth")
.map((provider) => ({
id: provider.id,
name: provider.name,
}));
}
// Cache the OAuth providers to avoid re-fetching them on every page load
const getCachedOAuthProviders = unstable_cache(
getOAuthProviders,
["oauth-providers"],
{
revalidate: false,
},
);
export default async function LoginPage() { export default async function LoginPage() {
const { t } = await getTranslation(); const { t } = await getTranslation();
const oAuthProviders = await getCachedOAuthProviders(); const oAuthProviders = getOAuthProviders();
const socialProviders = oAuthProviders.filter(
(provider) => provider.id !== "oidc", const hasAlternateLoginMethods = oAuthProviders.length > 0;
);
const oidcProvider = oAuthProviders.find( const oidcProvider = oAuthProviders.find(
(provider) => provider.id === "oidc", (provider) => provider.id === "oidc",
); );
const socialProviders = oAuthProviders.filter(
(provider) => provider.id !== "oidc",
);
return ( return (
<AuthPageContainer> <AuthPageContainer>
@ -73,25 +48,19 @@ export default async function LoginPage() {
</AuthPageHeader> </AuthPageHeader>
<AuthPageContent> <AuthPageContent>
<LoginWithEmailForm /> <LoginWithEmailForm />
{oidcProvider ? ( {hasAlternateLoginMethods ? <OrDivider /> : null}
<div className="text-center"> {oidcProvider ? <LoginWithOIDC name={oidcProvider.name} /> : null}
<LoginWithOIDC> {socialProviders ? (
<Trans <div className="grid gap-4">
t={t} {socialProviders.map((provider) => (
i18nKey="continueWithProvider" <SSOProvider
ns="app" key={provider.id}
defaultValue="Login with {{provider}}" providerId={provider.id}
values={{ provider: oidcProvider.name }} name={provider.name}
/> />
</LoginWithOIDC> ))}
</div> </div>
) : null} ) : null}
{socialProviders.length > 0 ? (
<>
<OrDivider text={t("or")} />
<SSOProviders />
</>
) : null}
</AuthPageContent> </AuthPageContent>
<AuthErrors /> <AuthErrors />
<AuthPageExternal> <AuthPageExternal>

View file

@ -1,53 +0,0 @@
import { unstable_cache } from "next/cache";
import { getProviders } from "next-auth/react";
import { SSOProvider } from "./components/sso-provider";
export const dynamic = "force-dynamic";
export const revalidate = 0;
async function getOAuthProviders() {
const providers = await getProviders();
if (!providers) {
return [];
}
return Object.values(providers)
.filter((provider) => provider.type === "oauth")
.map((provider) => ({
id: provider.id,
name: provider.name,
}));
}
// Cache the OAuth providers to avoid re-fetching them on every page load
const getCachedOAuthProviders = unstable_cache(
getOAuthProviders,
["oauth-providers"],
{
revalidate: false,
},
);
export async function SSOProviders() {
const oAuthProviders = await getCachedOAuthProviders();
const socialProviders = oAuthProviders.filter(
(provider) => provider.id !== "oidc",
);
if (socialProviders.length === 0) {
return null;
}
return (
<div className="grid gap-4">
{socialProviders.map((provider) => (
<SSOProvider
key={provider.id}
providerId={provider.id}
name={provider.name}
/>
))}
</div>
);
}

View file

@ -355,3 +355,17 @@ export const isEmailBlocked = (email: string) => {
} }
return false; return false;
}; };
export function getOAuthProviders(): {
id: string;
name: string;
}[] {
return providers
.filter((provider) => provider.type === "oauth")
.map((provider) => {
return {
id: provider.id,
name: provider.options?.name || provider.name,
};
});
}