From 6ffeecfbd6f6b2e657da15bf04dc4918fa1b78df Mon Sep 17 00:00:00 2001 From: Joonatan Kuosa Date: Mon, 16 Dec 2024 10:53:42 +0200 Subject: [PATCH] add: query params to application view --- apps/ui/components/AccordionWithIcons.tsx | 13 +++++++++- .../application/ApprovedReservations.tsx | 14 +++++++---- .../ui/pages/applications/[id]/view/index.tsx | 24 ++++++++++++++++--- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/apps/ui/components/AccordionWithIcons.tsx b/apps/ui/components/AccordionWithIcons.tsx index c114da1b3..a16a4c5c9 100644 --- a/apps/ui/components/AccordionWithIcons.tsx +++ b/apps/ui/components/AccordionWithIcons.tsx @@ -4,6 +4,7 @@ import { truncatedText } from "common/styles/cssFragments"; import { Flex } from "common/styles/util"; import { IconAngleDown, IconAngleUp, useAccordion } from "hds-react"; import { useTranslation } from "next-i18next"; +import { useEffect, useRef } from "react"; import styled from "styled-components"; type Props = { @@ -16,6 +17,8 @@ type Props = { textPostfix?: string; icon: React.ReactNode; }>; + id?: string; + shouldScrollIntoView?: boolean; }; const Heading = styled.h2<{ as: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" }>` @@ -111,12 +114,20 @@ export function AccordionWithIcons({ initiallyOpen = false, icons = [], children, + shouldScrollIntoView, ...rest }: Props): JSX.Element { const { isOpen, openAccordion, closeAccordion } = useAccordion({ initiallyOpen, }); const { t } = useTranslation(); + const ref = useRef(null); + + useEffect(() => { + if (shouldScrollIntoView && ref.current) { + ref.current.scrollIntoView(); + } + }, [shouldScrollIntoView]); const handleToggle = () => { if (isOpen) { @@ -127,7 +138,7 @@ export function AccordionWithIcons({ }; return ( -
+
{heading} diff --git a/apps/ui/components/application/ApprovedReservations.tsx b/apps/ui/components/application/ApprovedReservations.tsx index 305dd7534..4f1739636 100644 --- a/apps/ui/components/application/ApprovedReservations.tsx +++ b/apps/ui/components/application/ApprovedReservations.tsx @@ -22,6 +22,7 @@ import { formatApiTimeInterval, fromMondayFirst, getLocalizationLang, + toNumber, type LocalizationLanguages, } from "common/src/helpers"; import { @@ -55,6 +56,7 @@ import { } from "@/modules/reservation"; import { formatDateTimeStrings } from "@/modules/util"; import { PopupMenu } from "common/src/components/PopupMenu"; +import { useSearchParams } from "next/navigation"; const N_RESERVATIONS_TO_SHOW = 20; @@ -236,6 +238,7 @@ function formatReservationTimes( export function ApprovedReservations({ application }: Props) { const { t, i18n } = useTranslation(); + const searchParams = useSearchParams(); const { data, loading } = useApplicationReservationsQuery({ variables: { id: application.id, @@ -244,8 +247,6 @@ export function ApprovedReservations({ application }: Props) { }); const { application: app } = data || {}; - const lang = getLocalizationLang(i18n.language); - const sections = filterNonNullable( app?.applicationSections?.filter((aes) => { const slots = aes.reservationUnitOptions.flatMap( @@ -254,14 +255,19 @@ export function ApprovedReservations({ application }: Props) { return slots.length > 0; }) ); - const initiallyOpen = sections.length === 1; + + const lang = getLocalizationLang(i18n.language); + const selectedSection = toNumber(searchParams.get("section")); + const hasOnlyOneSection = sections.length === 1; + return ( {loading && } {sections.map((aes) => ( ("reservations"); useToastIfQueryParam({ key: "deletedReservationPk", @@ -78,10 +78,28 @@ function View({ application, tos }: PropsNarrowed): JSX.Element { successMessage: translateDeletedSectionMessage, }); + const searchParams = useSearchParams(); + + const handleRouteChange = (query: URLSearchParams) => { + // [id] param is not included in the URLSearchParams object but required when routing + if (router.query.id) { + query.set("id", router.query.id as string); + } + router.replace({ query: query.toString() }, undefined, { + shallow: true, + scroll: false, + }); + }; + const handleTabChange = (tab_: TabOptions) => { - setTab(tab_); + const params = new URLSearchParams(searchParams); + params.set("tab", tab_); + handleRouteChange(params); }; + const tab = + searchParams.get("tab") === "application" ? "application" : "reservations"; + const round = application.applicationRound; const lang = getLocalizationLang(i18n.language); const applicationRoundName = getTranslationSafe(round, "name", lang);