profile editor bug fixes
This commit is contained in:
parent
0cbeca833f
commit
16ae6d9c1c
4 changed files with 194 additions and 122 deletions
|
|
@ -1,7 +1,7 @@
|
|||
// components/account/ProfileEditor.tsx
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
type Me = {
|
||||
id: string;
|
||||
|
|
@ -24,33 +24,38 @@ export default function ProfileEditor({
|
|||
const [first_name, setFirst] = useState("");
|
||||
const [last_name, setLast] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [profileLocation, setProfileLocation] = useState(""); // renamed to avoid shadowing window.location
|
||||
const [profileLocation, setProfileLocation] = useState("");
|
||||
const [msg, setMsg] = useState<string | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [loading, setLoading] = useState(!meProp);
|
||||
|
||||
const nextAccount = "/portal/account";
|
||||
|
||||
// Load profile if not provided via props
|
||||
useEffect(() => {
|
||||
if (meProp) {
|
||||
setMe(meProp);
|
||||
setLoading(false);
|
||||
} else {
|
||||
(async () => {
|
||||
try {
|
||||
const r = await fetch("/api/account", { credentials: "include", cache: "no-store" });
|
||||
if (!r.ok) throw new Error(String(r.status));
|
||||
const j = await r.json();
|
||||
const user: Me | undefined = j?.user ?? j?.data ?? undefined;
|
||||
if (!user) throw new Error("Bad response");
|
||||
setMe(user);
|
||||
} catch (e: any) {
|
||||
setMsg(`Failed to load: ${e?.message || e}`);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
})();
|
||||
return;
|
||||
}
|
||||
let alive = true;
|
||||
(async () => {
|
||||
try {
|
||||
const r = await fetch("/api/account", { credentials: "include", cache: "no-store" });
|
||||
if (!r.ok) throw new Error(String(r.status));
|
||||
const j = await r.json();
|
||||
const user: Me | undefined = j?.user ?? j?.data ?? undefined;
|
||||
if (!user) throw new Error("Bad response");
|
||||
if (alive) setMe(user);
|
||||
} catch (e: any) {
|
||||
if (alive) setMsg(`Failed to load: ${e?.message || e}`);
|
||||
} finally {
|
||||
if (alive) setLoading(false);
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
alive = false;
|
||||
};
|
||||
}, [meProp]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -61,6 +66,41 @@ export default function ProfileEditor({
|
|||
setProfileLocation(me.location || "");
|
||||
}, [me]);
|
||||
|
||||
// Auto-retry a pending sensitive update after coming back from reauth
|
||||
useEffect(() => {
|
||||
const raw = typeof window !== "undefined" ? sessionStorage.getItem("pendingProfileUpdate") : null;
|
||||
if (!raw) return;
|
||||
let pending: Record<string, any> | null = null;
|
||||
try {
|
||||
pending = JSON.parse(raw);
|
||||
} catch {
|
||||
pending = null;
|
||||
}
|
||||
if (!pending) {
|
||||
sessionStorage.removeItem("pendingProfileUpdate");
|
||||
return;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const r = await fetch("/api/account/profile", {
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(pending),
|
||||
});
|
||||
const j = await r.json().catch(() => ({}));
|
||||
if (!r.ok) {
|
||||
setMsg(j?.error || "Update after re-auth failed");
|
||||
} else {
|
||||
setMsg("Saved after re-authentication.");
|
||||
onUpdated?.();
|
||||
}
|
||||
} finally {
|
||||
sessionStorage.removeItem("pendingProfileUpdate");
|
||||
}
|
||||
})();
|
||||
}, [onUpdated]);
|
||||
|
||||
const onSave = async () => {
|
||||
setMsg(null);
|
||||
setBusy(true);
|
||||
|
|
@ -76,9 +116,12 @@ export default function ProfileEditor({
|
|||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (r.status === 428) {
|
||||
// Need reauth for sensitive change (email)
|
||||
if (typeof window !== "undefined") {
|
||||
// Stash the pending payload so we can retry after reauth
|
||||
sessionStorage.setItem("pendingProfileUpdate", JSON.stringify(payload));
|
||||
window.location.assign(
|
||||
`/auth/sign-in?reauth=1&next=${encodeURIComponent(nextAccount + "#security")}`
|
||||
);
|
||||
|
|
@ -91,6 +134,7 @@ export default function ProfileEditor({
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const j = await r.json().catch(() => ({}));
|
||||
if (!r.ok) {
|
||||
setMsg(j?.error || "Update failed");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue