refactor: remove direct innerhtml resets from google auth card

This commit is contained in:
cesnimda
2026-03-22 14:36:49 +01:00
parent 8bd6f30973
commit 0b3d65e24b
@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useRef, useState } from "react"; import React, { useEffect, useMemo, useRef, useState } from "react";
import { Box, Button, Paper, Typography } from "@mui/material"; import { Box, Button, Chip, Paper, Typography } from "@mui/material";
import { api } from "../api"; import { api } from "../api";
import { clearAuthToken, decodeJwtPayload, getAuthToken, setAuthToken } from "../auth"; import { clearAuthToken, decodeJwtPayload, getAuthToken, setAuthToken } from "../auth";
@@ -30,7 +30,7 @@ function loadGoogleScript(): Promise<void> {
if (window.google?.accounts?.id) return resolve(); if (window.google?.accounts?.id) return resolve();
const existing = document.getElementById("google-gsi"); const existing = document.getElementById("google-gsi");
if (existing) { if (existing) {
existing.addEventListener("load", () => resolve()); existing.addEventListener("load", () => resolve(), { once: true });
return; return;
} }
const s = document.createElement("script"); const s = document.createElement("script");
@@ -97,17 +97,20 @@ export default function GoogleAuthCard({ onSignedIn }: { onSignedIn?: () => void
}, [token, isRawGoogleToken, onSignedIn, toast]); }, [token, isRawGoogleToken, onSignedIn, toast]);
useEffect(() => { useEffect(() => {
if (!clientId || !hostRef.current) return; const host = hostRef.current;
if (!clientId || !host) return;
const shouldRenderButton = !token || isRawGoogleToken || (me?.provider === "local" && !me?.googleLink?.linked); const shouldRenderButton = !token || isRawGoogleToken || (me?.provider === "local" && !me?.googleLink?.linked);
host.replaceChildren();
if (!shouldRenderButton) { if (!shouldRenderButton) {
hostRef.current.innerHTML = "";
return; return;
} }
let active = true;
void loadGoogleScript() void loadGoogleScript()
.then(() => { .then(() => {
if (!window.google?.accounts?.id || !hostRef.current) return; if (!active || !window.google?.accounts?.id || !hostRef.current) return;
hostRef.current.innerHTML = ""; hostRef.current.replaceChildren();
window.google.accounts.id.initialize({ window.google.accounts.id.initialize({
client_id: clientId, client_id: clientId,
callback: async (resp: any) => { callback: async (resp: any) => {
@@ -143,6 +146,11 @@ export default function GoogleAuthCard({ onSignedIn }: { onSignedIn?: () => void
}); });
}) })
.catch(() => toast("Google auth script failed to load.", "error")); .catch(() => toast("Google auth script failed to load.", "error"));
return () => {
active = false;
host.replaceChildren();
};
}, [clientId, me?.provider, me?.googleLink?.linked, onSignedIn, isRawGoogleToken, token, toast]); }, [clientId, me?.provider, me?.googleLink?.linked, onSignedIn, isRawGoogleToken, token, toast]);
return ( return (
@@ -159,6 +167,11 @@ export default function GoogleAuthCard({ onSignedIn }: { onSignedIn?: () => void
{clientId && ( {clientId && (
<Box sx={{ display: "flex", flexDirection: "column", gap: 1.25 }}> <Box sx={{ display: "flex", flexDirection: "column", gap: 1.25 }}>
<Box sx={{ display: "flex", gap: 1, flexWrap: "wrap" }}>
<Chip size="small" label={me?.googleLink?.linked ? "Linked" : "Available to link"} color={me?.googleLink?.linked ? "success" : "default"} variant={me?.googleLink?.linked ? "filled" : "outlined"} />
{me?.googleLink?.linkedAt ? <Chip size="small" variant="outlined" label={`Linked ${new Date(me.googleLink.linkedAt).toLocaleDateString()}`} /> : null}
</Box>
{!token ? ( {!token ? (
<Typography sx={{ color: "text.secondary" }}> <Typography sx={{ color: "text.secondary" }}>
Sign in with a Google account that has already been linked to your Job Tracker user. Sign in with a Google account that has already been linked to your Job Tracker user.