Files
channels-seerr/src/components/Login/OidcLoginButton.tsx
Puranjay Savar Mattas 67bbc73564 feat(api): refactor fetch calls to axios
Replaces the native fetch() API with axios for all OIDC-related frontend API calls. This improves
consistency with other parts of the codebase and simplifies error handling.

Addresses https://github.com/fallenbagel/jellyseerr/pull/1505#pullrequestreview-3001436908
2025-09-08 14:08:14 -04:00

85 lines
2.4 KiB
TypeScript

import defineMessages from '@app/utils/defineMessages';
import { processCallback } from '@app/utils/oidc';
import type { PublicOidcProvider } from '@server/lib/settings';
import axios from 'axios';
import { useRouter, useSearchParams } from 'next/navigation';
import { useCallback, useEffect, useState } from 'react';
import { useIntl } from 'react-intl';
import LoginButton from './LoginButton';
const messages = defineMessages('components.Login', {
oidcLoginError: 'An error occurred while logging in with {provider}.',
});
type OidcLoginButtonProps = {
provider: PublicOidcProvider;
onError?: (message: string) => void;
};
export default function OidcLoginButton({
provider,
onError,
}: OidcLoginButtonProps) {
const intl = useIntl();
const searchParams = useSearchParams();
const router = useRouter();
const [loading, setLoading] = useState(false);
const redirectToLogin = useCallback(async () => {
try {
const res = await axios.get<{ redirectUrl: string }>(
`/api/v1/auth/oidc/login/${provider.slug}`
);
window.location.href = res.data.redirectUrl;
} catch (e) {
setLoading(false);
onError?.(
intl.formatMessage(messages.oidcLoginError, {
provider: provider.name,
})
);
}
}, [provider, intl, onError]);
const handleCallback = useCallback(async () => {
const result = await processCallback(searchParams, provider.slug);
if (result.type === 'success') {
// redirect to homepage
router.push(result.message?.to ?? '/');
} else {
setLoading(false);
onError?.(
intl.formatMessage(messages.oidcLoginError, {
provider: provider.name,
})
);
}
}, [provider, searchParams, intl, onError, router]);
useEffect(() => {
if (loading) return;
const isCallback = searchParams.get('callback') === 'true';
const providerSlug = searchParams.get('provider');
if (providerSlug === provider.slug) {
setLoading(true);
if (isCallback) handleCallback();
else redirectToLogin();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<LoginButton loading={loading} onClick={() => redirectToLogin()}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={provider.logo || '/images/openid.svg'}
alt={provider.name}
className="mr-2 max-h-5 w-5"
/>
<span>{provider.name}</span>
</LoginButton>
);
}