♻️ 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 { 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 (
<Button
onClick={() => {
@ -10,7 +14,13 @@ export function LoginWithOIDC({ children }: { children: React.ReactNode }) {
}}
variant="link"
>
{children}
<Trans
t={t}
i18nKey="continueWithProvider"
ns="app"
defaultValue="Login with {{provider}}"
values={{ provider: name }}
/>
</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 (
<div className="flex items-center gap-x-2.5">
<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" />
</div>
);

View file

@ -1,8 +1,7 @@
import { unstable_cache } from "next/cache";
import Link from "next/link";
import { getProviders } from "next-auth/react";
import { Trans } from "react-i18next/TransWithoutContext";
import { getOAuthProviders } from "@/auth";
import { getTranslation } from "@/i18n/server";
import {
@ -17,44 +16,20 @@ import { AuthErrors } from "./components/auth-errors";
import { LoginWithEmailForm } from "./components/login-email-form";
import { LoginWithOIDC } from "./components/login-with-oidc";
import { OrDivider } from "./components/or-divider";
import { SSOProviders } from "./sso-providers";
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,
},
);
import { SSOProvider } from "./components/sso-provider";
export default async function LoginPage() {
const { t } = await getTranslation();
const oAuthProviders = await getCachedOAuthProviders();
const socialProviders = oAuthProviders.filter(
(provider) => provider.id !== "oidc",
);
const oAuthProviders = getOAuthProviders();
const hasAlternateLoginMethods = oAuthProviders.length > 0;
const oidcProvider = oAuthProviders.find(
(provider) => provider.id === "oidc",
);
const socialProviders = oAuthProviders.filter(
(provider) => provider.id !== "oidc",
);
return (
<AuthPageContainer>
@ -73,25 +48,19 @@ export default async function LoginPage() {
</AuthPageHeader>
<AuthPageContent>
<LoginWithEmailForm />
{oidcProvider ? (
<div className="text-center">
<LoginWithOIDC>
<Trans
t={t}
i18nKey="continueWithProvider"
ns="app"
defaultValue="Login with {{provider}}"
values={{ provider: oidcProvider.name }}
{hasAlternateLoginMethods ? <OrDivider /> : null}
{oidcProvider ? <LoginWithOIDC name={oidcProvider.name} /> : null}
{socialProviders ? (
<div className="grid gap-4">
{socialProviders.map((provider) => (
<SSOProvider
key={provider.id}
providerId={provider.id}
name={provider.name}
/>
</LoginWithOIDC>
))}
</div>
) : null}
{socialProviders.length > 0 ? (
<>
<OrDivider text={t("or")} />
<SSOProviders />
</>
) : null}
</AuthPageContent>
<AuthErrors />
<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;
};
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,
};
});
}