Files
probo/apps/console/src/pages/iam/auth/sign-in/SSOSignInPage.tsx
Émile Ré c168be6de0 Add import order sorting rules
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-22 20:38:37 +04:00

135 lines
3.6 KiB
TypeScript

import { useTranslate } from "@probo/i18n";
import { Button, Field, IconChevronLeft, useToast } from "@probo/ui";
import { type FormEventHandler, useEffect, useState } from "react";
import {
type PreloadedQuery,
usePreloadedQuery,
useQueryLoader,
} from "react-relay";
import { Link, useNavigate } from "react-router";
import { graphql } from "relay-runtime";
import type { SSOSignInPageQuery } from "/__generated__/iam/SSOSignInPageQuery.graphql";
const ssoAvailabilityQuery = graphql`
query SSOSignInPageQuery($email: EmailAddr!) {
ssoLoginURL(email: $email) @catch(to: RESULT)
}
`;
export default function SSOSignInPage() {
const { __ } = useTranslate();
const [queryRef, loadQuery]
= useQueryLoader<SSOSignInPageQuery>(ssoAvailabilityQuery);
const [checking, setChecking] = useState(false);
const handleSSOCheck: FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
setChecking(true);
const formData = new FormData(e.currentTarget);
const email = formData.get("email") ? (formData.get("email") as string).toString() : "";
if (!email) return;
loadQuery({ email }, { fetchPolicy: "network-only" });
};
return (
<>
<form className="space-y-4" onSubmit={handleSSOCheck}>
<Link
to="/auth/login"
className="flex items-center gap-2 text-txt-secondary hover:text-txt-primary transition-colors mb-4"
>
<IconChevronLeft size={20} />
<span className="text-sm">{__("Back")}</span>
</Link>
<h1 className="text-center text-2xl font-bold">
{__("Login with SSO")}
</h1>
<p className="text-center text-txt-tertiary mt-1 mb-6">
{__("Enter your work email to continue with SSO")}
</p>
<Field
required
placeholder={__("Work Email")}
name="email"
type="email"
label={__("Work Email")}
autoFocus
/>
<Button className="w-full" disabled={checking}>
{checking ? __("Checking...") : __("Continue with SSO")}
</Button>
<div className="text-center mt-6 text-sm text-txt-secondary">
{__("Don't have an account ?")}
{" "}
<Link
to="/auth/register"
className="underline hover:text-txt-primary"
>
{__("Register")}
</Link>
</div>
</form>
{queryRef && (
<NavigateToSSOLoginURL
onSSOAvailabilityCheck={setChecking}
queryRef={queryRef}
/>
)}
</>
);
}
function NavigateToSSOLoginURL(props: {
queryRef: PreloadedQuery<SSOSignInPageQuery>;
onSSOAvailabilityCheck: (checking: boolean) => void;
}) {
const { queryRef } = props;
const { __ } = useTranslate();
const { toast } = useToast();
const navigate = useNavigate();
const { ssoLoginURL } = usePreloadedQuery<SSOSignInPageQuery>(
ssoAvailabilityQuery,
queryRef,
);
useEffect(() => {
if (!ssoLoginURL.ok) {
toast({
title: __("Error"),
description:
ssoLoginURL.errors[0] instanceof Error
? ssoLoginURL.errors[0].message
: __("SSO not available for this email domain"),
variant: "error",
});
void navigate("/auth/login");
return;
}
if (!ssoLoginURL.value) {
toast({
title: __("Error"),
description: __("SSO not available for this email domain"),
variant: "error",
});
return;
}
window.location.href = ssoLoginURL.value;
}, [__, navigate, ssoLoginURL, toast]);
return null;
}