From 3c757c1f73cd5616f063dfae9ac5cd7a879898c4 Mon Sep 17 00:00:00 2001 From: Chris Parsons <438676+chrisparsons83@users.noreply.github.com> Date: Mon, 18 May 2026 16:08:10 -0700 Subject: [PATCH] Replace settings redirect with toast notification (#445) * Show toast instead of redirecting after league settings save Commishes now stay on the settings page when saving, with a Sonner toast confirming the save rather than being navigated to the league homepage. https://claude.ai/code/session_01PewdKxVfAbqasJbmk2UGw4 * Fix toast firing for unrelated intents after settings save Tag update responses with intent: "update" so the success useEffect only fires for the main settings form, not for owner/commissioner/ reset-draft actions which also return { success: true }. Also replaces the remaining ?updated=true redirect (no-season edge case) with the same response shape for consistency. https://claude.ai/code/session_01PewdKxVfAbqasJbmk2UGw4 --------- Co-authored-by: Claude --- app/components/league/settings/SettingsMessages.tsx | 7 ------- app/routes/leagues/$leagueId.settings.server.ts | 4 ++-- app/routes/leagues/$leagueId.settings.tsx | 12 ++++++++++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/components/league/settings/SettingsMessages.tsx b/app/components/league/settings/SettingsMessages.tsx index 1d52a83..f4cce8d 100644 --- a/app/components/league/settings/SettingsMessages.tsx +++ b/app/components/league/settings/SettingsMessages.tsx @@ -25,13 +25,6 @@ export function SettingsMessage({ actionData }: { actionData: SettingsActionData ); } - if (actionData.success) { - return ( -
- {actionData.message ?? "Settings updated successfully."} -
- ); - } return null; } diff --git a/app/routes/leagues/$leagueId.settings.server.ts b/app/routes/leagues/$leagueId.settings.server.ts index 18bc795..5120899 100644 --- a/app/routes/leagues/$leagueId.settings.server.ts +++ b/app/routes/leagues/$leagueId.settings.server.ts @@ -268,7 +268,7 @@ export async function action(args: Route.ActionArgs) { const season = await findCurrentSeasonWithSports(leagueId); if (!season) { if (intent === "update") { - return redirect(`/leagues/${leagueId}?updated=true`); + return { success: true, message: "Settings saved successfully.", intent: "update" as const }; } return { error: "No active season found" }; } @@ -776,7 +776,7 @@ export async function action(args: Route.ActionArgs) { } } - return redirect(`/leagues/${leagueId}?updated=true`); + return { success: true, message: "Settings saved successfully.", intent: "update" as const }; } catch (error) { logger.error("Error updating season settings:", error); return { error: "Failed to update season settings. Please try again." }; diff --git a/app/routes/leagues/$leagueId.settings.tsx b/app/routes/leagues/$leagueId.settings.tsx index 3467453..3356cfe 100644 --- a/app/routes/leagues/$leagueId.settings.tsx +++ b/app/routes/leagues/$leagueId.settings.tsx @@ -179,8 +179,8 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone setHasDraftOrderChanges(false); }, [draftSlots, teams]); - // Re-mark dirty if the settings save returned an error (success path redirects away, so no cleanup - // needed there). Guard against non-settings errors (e.g. draft-order) which carry a `section` field. + // Re-mark dirty if the settings save returned an error. Guard against non-settings errors + // (e.g. draft-order) which carry a `section` field. useEffect(() => { if (navigation.state !== "idle") return; if (actionData && "error" in actionData && !("section" in actionData)) { @@ -188,6 +188,14 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone } }, [actionData, navigation.state]); + useEffect(() => { + if (navigation.state !== "idle") return; + if (actionData && "intent" in actionData && actionData.intent === "update" && actionData.success) { + toast.success(actionData.message ?? "Settings saved!"); + setHasUnsavedSettingsChanges(false); + } + }, [actionData, navigation.state]); + const canEditSports = season?.status === "pre_draft"; const canEditTeamCount = season?.status === "pre_draft"; const canEditDraftOrder = season?.status === "pre_draft";