diff --git a/app/routes/plus/suggestions.tsx b/app/routes/plus/suggestions.tsx index d3e35f575..5761fa6e4 100644 --- a/app/routes/plus/suggestions.tsx +++ b/app/routes/plus/suggestions.tsx @@ -4,9 +4,9 @@ import type { MetaFunction, } from "@remix-run/node"; import { json } from "@remix-run/node"; -import { Link, Outlet, useLoaderData } from "@remix-run/react"; +import type { ShouldReloadFunction } from "@remix-run/react"; +import { Link, Outlet, useLoaderData, useSearchParams } from "@remix-run/react"; import clsx from "clsx"; -import * as React from "react"; import invariant from "tiny-invariant"; import { z } from "zod"; import { Avatar } from "~/components/Avatar"; @@ -115,6 +115,11 @@ export interface PlusSuggestionsLoaderData { suggestedForTiers: number[]; } +export const unstable_shouldReload: ShouldReloadFunction = ({ submission }) => { + // only reload if form submission not when user changes tabs + return Boolean(submission); +}; + export const loader: LoaderFunction = async ({ request }) => { const user = await getUser(request); @@ -138,13 +143,13 @@ export const loader: LoaderFunction = async ({ request }) => { export default function PlusSuggestionsPage() { const data = useLoaderData(); + const [searchParams, setSearchParams] = useSearchParams(); const user = useUser(); - // TODO: this stays undefined when adding first suggestion - const [tierVisible, setTierVisible] = React.useState( - tierVisibleInitialState(data.suggestions) - ); + const tierVisible = searchParamsToLegalTier(searchParams, data.suggestions); - useSetSelectedTierForFirstSuggestEffect({ tierVisible, setTierVisible }); + const handleTierChange = (tier: string) => { + setSearchParams({ tier }); + }; if (!user) { return ( @@ -206,7 +211,7 @@ export default function PlusSuggestionsPage() { name="tier" type="radio" checked={tierVisible === tier} - onChange={() => setTierVisible(tier)} + onChange={() => handleTierChange(tier)} data-cy={`plus${tier}-radio`} /> @@ -248,6 +253,22 @@ export default function PlusSuggestionsPage() { ); } +function searchParamsToLegalTier( + searchParams: URLSearchParams, + suggestions?: plusSuggestions.FindVisibleForUser +) { + const tierFromSearchParams = searchParams.get("tier"); + if ( + !tierFromSearchParams || + !suggestions || + !suggestions[tierFromSearchParams] + ) { + return tierVisibleInitialState(suggestions); + } + + return tierFromSearchParams; +} + function tierVisibleInitialState( suggestions?: plusSuggestions.FindVisibleForUser ) { @@ -255,21 +276,6 @@ function tierVisibleInitialState( return String(Math.min(...Object.keys(suggestions).map(Number))); } -function useSetSelectedTierForFirstSuggestEffect({ - tierVisible, - setTierVisible, -}: { - tierVisible?: string; - setTierVisible: (tier?: string) => void; -}) { - const data = useLoaderData(); - React.useEffect(() => { - if (tierVisible) return; - - setTierVisible(tierVisibleInitialState(data.suggestions)); - }, [data, tierVisible, setTierVisible]); -} - function SuggestedForInfo({ hideText = false }: { hideText?: boolean }) { const data = useLoaderData(); const user = useUser(); diff --git a/app/routes/plus/suggestions/comment.$tier.$userId.tsx b/app/routes/plus/suggestions/comment.$tier.$userId.tsx index 01464be96..fbea18b55 100644 --- a/app/routes/plus/suggestions/comment.$tier.$userId.tsx +++ b/app/routes/plus/suggestions/comment.$tier.$userId.tsx @@ -15,7 +15,7 @@ import { } from "~/permissions"; import { atOrError } from "~/utils/arrays"; import { parseRequestFormData, validate } from "~/utils/remix"; -import { PLUS_SUGGESTIONS_PAGE } from "~/utils/urls"; +import { plusSuggestionPage } from "~/utils/urls"; import { actualNumber } from "~/utils/zod"; import type { PlusSuggestionsLoaderData } from "../suggestions"; import { CommentTextarea } from "./new"; @@ -60,7 +60,7 @@ export const action: ActionFunction = async ({ request }) => { ...nextNonCompletedVoting(new Date()), }); - return redirect(PLUS_SUGGESTIONS_PAGE); + return redirect(plusSuggestionPage()); }; export default function PlusCommentModalPage() { @@ -86,7 +86,7 @@ export default function PlusCommentModalPage() { targetPlusTier: Number(tierSuggestedTo), }) ) { - return ; + return ; } return ( @@ -104,7 +104,7 @@ export default function PlusCommentModalPage() { Submit diff --git a/app/routes/plus/suggestions/new.tsx b/app/routes/plus/suggestions/new.tsx index 4f13a9cb5..0bbdda6e3 100644 --- a/app/routes/plus/suggestions/new.tsx +++ b/app/routes/plus/suggestions/new.tsx @@ -8,7 +8,7 @@ import { playerAlreadyMember, playerAlreadySuggested, } from "~/permissions"; -import { PLUS_SUGGESTIONS_PAGE } from "~/utils/urls"; +import { plusSuggestionPage } from "~/utils/urls"; import type { PlusSuggestionsLoaderData } from "../suggestions"; import * as React from "react"; import { Label } from "~/components/Label"; @@ -80,7 +80,7 @@ export const action: ActionFunction = async ({ request }) => { ...nextNonCompletedVoting(new Date()), }); - return redirect(PLUS_SUGGESTIONS_PAGE); + return redirect(plusSuggestionPage(data.tier)); }; export default function PlusNewSuggestionModalPage() { @@ -111,7 +111,7 @@ export default function PlusNewSuggestionModalPage() { }) || !targetPlusTier ) { - return ; + return ; } const selectedUserErrorMessage = getSelectedUserErrorMessage({ @@ -160,7 +160,7 @@ export default function PlusNewSuggestionModalPage() { Submit diff --git a/app/utils/urls.ts b/app/utils/urls.ts index 090d4d0c2..f974d2652 100644 --- a/app/utils/urls.ts +++ b/app/utils/urls.ts @@ -12,7 +12,6 @@ export const LEAN_TWITTER = "https://twitter.com/LeanYoshi"; export const UBERU_TWITTER = "https://twitter.com/uberu5"; export const LOG_IN_URL = "/auth"; export const LOG_OUT_URL = "/auth/logout"; -export const PLUS_SUGGESTIONS_PAGE = "/plus/suggestions"; export const ADMIN_PAGE = "/admin"; export const FAQ_PAGE = "/faq"; export const CONTRIBUTIONS_PAGE = "/contributions"; @@ -23,6 +22,8 @@ export const userPage = (discordId: string) => `/u/${discordId}`; export const impersonateUrl = (idToLogInAs: number) => `/auth/impersonate?id=${idToLogInAs}`; export const badgePage = (badgeId: number) => `${BADGES_PAGE}/${badgeId}`; +export const plusSuggestionPage = (tier?: string | number) => + `/plus/suggestions${tier ? `?tier=${tier}` : ""}`; export const badgeUrl = ({ code, diff --git a/cypress/e2e/plus.cy.ts b/cypress/e2e/plus.cy.ts index 0990e54c6..f842eed5d 100644 --- a/cypress/e2e/plus.cy.ts +++ b/cypress/e2e/plus.cy.ts @@ -1,4 +1,4 @@ -import { PLUS_SUGGESTIONS_PAGE } from "~/utils/urls"; +import { plusSuggestionPage } from "~/utils/urls"; export {}; @@ -9,13 +9,13 @@ describe("Plus suggestions page", () => { it("views suggestions status as non plus member", function () { cy.auth(151); - cy.visit(PLUS_SUGGESTIONS_PAGE); + cy.visit(plusSuggestionPage()); cy.contains("You are suggested"); }); it("adds a comment and deletes one", () => { cy.auth(); - cy.visit(PLUS_SUGGESTIONS_PAGE); + cy.visit(plusSuggestionPage()); cy.getCy("suggested-user-name") .first() @@ -45,7 +45,7 @@ describe("Plus suggestions page", () => { it("adds a new suggestion, validates suggested user and deletes it", () => { cy.clock(new Date(Date.UTC(2022, 5, 15))); // let's make sure voting is not happening cy.auth(); - cy.visit(PLUS_SUGGESTIONS_PAGE); + cy.visit(plusSuggestionPage()); cy.getCy("new-suggest-button").click(); cy.getCy("tier-select").select("2");