Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 520x 71x 71x 71x 71x 71x 63x 63x 63x 57x 6x 6x 21x 21x 21x 21x | import { captureException } from "@sentry/react";
import { ReactElement, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { useSearchParams } from "react-router";
import { z } from "zod";
import { Button } from "client/components/Button";
import { ErrorMessage } from "client/components/ErrorMessage";
import { ButtonStyle } from "client/components/componentStyles";
import { postKompassiLoginRedirect } from "client/services/loginServices";
import { LoginErrorMessage } from "client/views/login/loginThunks";
export const KompassiLoginButton = (): ReactElement => {
const { t } = useTranslation();
const [searchParams, setSearchParams] = useSearchParams();
const [serverError, setServerError] = useState<LoginErrorMessage | null>(
null,
);
// A second click would store a second state while the first request is still
// in flight, and the page then leaves for whichever authorize URL resolves
// last - which may carry the state that is no longer stored. A ref rather
// than state on purpose: nothing renders from it, so a page restored from
// the bfcache (Back from the Kompassi consent screen) can't come back stuck
const redirecting = useRef(false);
useEffect(() => {
const error = searchParams.get("error");
const result = z.enum(LoginErrorMessage).safeParse(error);
if (!result.success) {
return;
}
Eif (error) {
// eslint-disable-next-line react-hooks/set-state-in-effect
setServerError(result.data);
}
}, [searchParams]);
return (
<>
<Button
buttonStyle={ButtonStyle.PRIMARY}
onClick={async () => {
Iif (redirecting.current) {
return;
}
redirecting.current = true;
try {
await postKompassiLoginRedirect();
} catch (error) {
// The request wrapper reports its own failures, so getting here
// means storage refused to keep the login state. Nothing else
// would notice: the click just appears to do nothing
captureException(error);
}
// Only reached when no redirect happened: the success path never
// resolves, because the page is unloading. A `finally` would say
// this better, but the React Compiler declines any function
// containing one
redirecting.current = false;
}}
>
{t("loginView.kompassiLogin")}
</Button>
{serverError && (
<ErrorMessage
message={t(serverError)}
closeError={() => {
setServerError(null);
setSearchParams("");
}}
/>
)}
</>
);
};
|