diff --git a/apps/admin-ui/src/common/urls.ts b/apps/admin-ui/src/common/urls.ts index b3eb4bf1e4..eeaaf5ffe0 100644 --- a/apps/admin-ui/src/common/urls.ts +++ b/apps/admin-ui/src/common/urls.ts @@ -13,16 +13,18 @@ export const allReservationsUrl = "/reservations/all"; export const myUnitsUrl = "/my-units"; export function getApplicationRoundUrl( - applicationRoundId: Maybe | undefined, - includePrefix = false + applicationRoundId: Maybe | undefined ): string { if (applicationRoundId == null || !(applicationRoundId > 0)) { return ""; } - const prefix = includePrefix ? PUBLIC_URL : ""; - return `${prefix}${applicationRoundsUrl}/${applicationRoundId}`; + return `${applicationRoundsUrl}/${applicationRoundId}`; } +/// @param pk is the primary key of the reservation +/// @param includePrefix is for anchor or vanilla js route manipulation +/// @returns the url for the reservation +/// Generally never enable includePrefix use react-router-dom link / router instead. export function getReservationUrl( pk: Maybe | undefined, includePrefix = false @@ -36,14 +38,12 @@ export function getReservationUrl( export function getApplicationUrl( pk: Maybe | undefined, - sectionPk?: Maybe | undefined, - includePrefix = false + sectionPk?: Maybe | undefined ): string { if (pk == null || !(pk > 0)) { return ""; } - const prefix = includePrefix ? PUBLIC_URL : ""; - const baseUrl = `${prefix}${applicationsUrl}/${pk}`; + const baseUrl = `${applicationsUrl}/${pk}`; if (sectionPk == null || !(sectionPk > 0)) { return baseUrl; } @@ -52,14 +52,21 @@ export function getApplicationUrl( export function getReservationUnitUrl( reservationUnitPk: Maybe | undefined, - unitPk: Maybe | undefined, - includePrefix = false + unitPk: Maybe | undefined ): string { if (unitPk == null) { return ""; } - const prefix = includePrefix ? PUBLIC_URL : ""; - return `${prefix}/unit/${unitPk}/reservationUnit/${reservationUnitPk ?? ""}`; + return `/unit/${unitPk}/reservationUnit/${reservationUnitPk ?? ""}`; +} + +export function getSpacesResourcesUrl( + unitPk: Maybe | undefined +): string { + if (unitPk == null) { + return ""; + } + return `/unit/${unitPk}/spacesResources`; } export function getSpaceUrl( @@ -82,30 +89,19 @@ export function getResourceUrl( return `/unit/${unitPk}/resource/${resourcePk}`; } -export function getUnitUrl( - unitPk: Maybe | undefined, - includePrefix = false -): string { - const prefix = includePrefix ? PUBLIC_URL : ""; - return `${prefix}/unit/${unitPk}`; +export function getUnitUrl(unitPk: Maybe | undefined): string { + return `/unit/${unitPk}`; } -export function getMyUnitUrl( - unitPk: Maybe | undefined, - includePrefix = false -): string { - const prefix = includePrefix ? PUBLIC_URL : ""; - return `${prefix}/my-units/${unitPk}`; +export function getMyUnitUrl(unitPk: Maybe | undefined): string { + return `/my-units/${unitPk}`; } -// TODO PUBLIC_URL is problematic, it needs to be added when not using react-router or something else? export function getRecurringReservationUrl( - pk: Maybe | undefined, - includePrefix = false + pk: Maybe | undefined ): string { if (pk == null || !(Number(pk) > 0)) { return ""; } - const prefix = includePrefix ? PUBLIC_URL : ""; - return `${prefix}/my-units/${pk}/recurring`; + return `/my-units/${pk}/recurring`; } diff --git a/apps/admin-ui/src/component/ExternalLink.tsx b/apps/admin-ui/src/component/ExternalLink.tsx index 9eed1553e3..1b6c310067 100644 --- a/apps/admin-ui/src/component/ExternalLink.tsx +++ b/apps/admin-ui/src/component/ExternalLink.tsx @@ -1,6 +1,7 @@ import React from "react"; import { IconLinkExternal } from "hds-react"; import styled from "styled-components"; +import { Link } from "react-router-dom"; type Props = { to: string | null; @@ -34,11 +35,11 @@ export function ExternalLink({ return null; } return ( - + {children} - + ); } diff --git a/apps/admin-ui/src/component/Table.tsx b/apps/admin-ui/src/component/Table.tsx index 61717e12a0..7e5e7cbb47 100644 --- a/apps/admin-ui/src/component/Table.tsx +++ b/apps/admin-ui/src/component/Table.tsx @@ -1,6 +1,5 @@ import { get } from "lodash"; import React from "react"; -import { Link } from "react-router-dom"; import styled from "styled-components"; import { Table, TableProps } from "hds-react"; import { fontBold } from "common"; @@ -95,26 +94,3 @@ function replacer(_key: string, value: unknown) { } return value; } - -const A = styled(Link)` - color: black; -`; - -// NOTE not using IconButton because of hover effect -export const ExternalTableLink = styled.a` - color: var(--color-black); - display: flex; - align-items: center; - gap: var(--spacing-3-xs); - & > svg { - margin-top: var(--spacing-3-xs); - } -`; - -export const TableLink = ({ - href, - children, -}: { - href: string; - children: React.ReactNode; -}): JSX.Element => {children}; diff --git a/apps/admin-ui/src/spa/application-rounds/[id]/allocation/ApplicationEventCard.tsx b/apps/admin-ui/src/spa/application-rounds/[id]/allocation/ApplicationEventCard.tsx index ed0c687e3c..a723cec8ce 100644 --- a/apps/admin-ui/src/spa/application-rounds/[id]/allocation/ApplicationEventCard.tsx +++ b/apps/admin-ui/src/spa/application-rounds/[id]/allocation/ApplicationEventCard.tsx @@ -1,4 +1,9 @@ -import { IconAngleDown, IconAngleUp, Link, RadioButton } from "hds-react"; +import { + IconAngleDown, + IconAngleUp, + IconLinkExternal, + RadioButton, +} from "hds-react"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import styled, { css } from "styled-components"; @@ -25,6 +30,7 @@ import { errorToast } from "common/src/common/toast"; import { getApplicantName } from "@/helpers"; import { MAX_ALLOCATION_CARD_UNIT_NAME_LENGTH } from "@/common/const"; import { formatAgeGroup } from "@/common/util"; +import { Link } from "react-router-dom"; export type AllocationApplicationSectionCardType = | "unallocated" @@ -207,15 +213,15 @@ export function ApplicationSectionCard({ refetch={refetch} /> {t("Allocation.openApplication")}{" "} {applicationSection.application.pk}-{applicationSection.pk} +
{t("Allocation.ageGroup")}:{" "} diff --git a/apps/admin-ui/src/spa/application-rounds/[id]/review/AllocatedEventsTable.tsx b/apps/admin-ui/src/spa/application-rounds/[id]/review/AllocatedEventsTable.tsx index efbb1ad417..84d3caa579 100644 --- a/apps/admin-ui/src/spa/application-rounds/[id]/review/AllocatedEventsTable.tsx +++ b/apps/admin-ui/src/spa/application-rounds/[id]/review/AllocatedEventsTable.tsx @@ -7,7 +7,8 @@ import type { AllocatedTimeSlotsQuery } from "@gql/gql-types"; import { convertWeekday } from "common/src/conversion"; import { getApplicantName, truncate } from "@/helpers"; import { getApplicationUrl, getReservationUrl } from "@/common/urls"; -import { CustomTable, ExternalTableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; +import { ExternalTableLink, TableLink } from "@/styles/util"; const unitsTruncateLen = 23; const applicantTruncateLen = 20; @@ -87,11 +88,7 @@ const COLS = [ applicationPk, pk, }: ApplicationScheduleView) => ( - + {truncate(applicantName ?? "-", applicantTruncateLen)} @@ -131,7 +128,7 @@ const COLS = [ key: "allocated_time_of_week", transform: ({ time, link }: ApplicationScheduleView) => { if (link !== "") { - return {time}; + return {time}; } return {time}; }, diff --git a/apps/admin-ui/src/spa/application-rounds/[id]/review/ApplicationEventsTable.tsx b/apps/admin-ui/src/spa/application-rounds/[id]/review/ApplicationEventsTable.tsx index 168306fe90..73eb8a0581 100644 --- a/apps/admin-ui/src/spa/application-rounds/[id]/review/ApplicationEventsTable.tsx +++ b/apps/admin-ui/src/spa/application-rounds/[id]/review/ApplicationEventsTable.tsx @@ -7,12 +7,13 @@ import type { ApplicationSectionsQuery } from "@gql/gql-types"; import { MAX_APPLICATION_ROUND_NAME_LENGTH } from "@/common/const"; import { getApplicantName, truncate } from "@/helpers"; import { getApplicationUrl } from "@/common/urls"; -import { CustomTable, ExternalTableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; import { ApplicationSectionStatusCell } from "./StatusCell"; import { calculateAppliedReservationTime, formatAppliedReservationTime, } from "./utils"; +import { ExternalTableLink } from "@/styles/util"; const unitsTruncateLen = 23; const applicantTruncateLen = 20; @@ -84,11 +85,7 @@ const COLS = [ isSortable: true, key: "applicant", transform: ({ applicantName, applicationPk, pk }: ApplicationEventView) => ( - + {truncate(applicantName ?? "-", applicantTruncateLen)} diff --git a/apps/admin-ui/src/spa/application-rounds/[id]/review/ApplicationsTable.tsx b/apps/admin-ui/src/spa/application-rounds/[id]/review/ApplicationsTable.tsx index b7ba453b95..469cdaadff 100644 --- a/apps/admin-ui/src/spa/application-rounds/[id]/review/ApplicationsTable.tsx +++ b/apps/admin-ui/src/spa/application-rounds/[id]/review/ApplicationsTable.tsx @@ -9,13 +9,14 @@ import type { } from "@gql/gql-types"; import { filterNonNullable } from "common/src/helpers"; import { getApplicantName, truncate } from "@/helpers"; -import { CustomTable, ExternalTableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; import { ApplicationStatusCell } from "./StatusCell"; import { calculateAppliedReservationTime, formatAppliedReservationTime, } from "./utils"; import { getApplicationUrl } from "@/common/urls"; +import { ExternalTableLink } from "@/styles/util"; const unitsTruncateLen = 23; const applicantTruncateLen = 20; @@ -52,19 +53,12 @@ const COLS = [ headerTKey: "Application.headings.customer", isSortable: true, key: "applicant", - transform: ({ applicantName, pk }: ApplicationView) => - pk ? ( - - {truncate(applicantName ?? "-", applicantTruncateLen)} - - - ) : ( - {truncate(applicantName ?? "-", applicantTruncateLen)} - ), + transform: ({ applicantName, pk }: ApplicationView) => ( + + {truncate(applicantName ?? "-", applicantTruncateLen)} + + + ), }, { headerTKey: "Application.applicantType", diff --git a/apps/admin-ui/src/spa/application-rounds/[id]/review/RejectedOccurrencesTable.tsx b/apps/admin-ui/src/spa/application-rounds/[id]/review/RejectedOccurrencesTable.tsx index 1b6b736b91..a0a22ca8f7 100644 --- a/apps/admin-ui/src/spa/application-rounds/[id]/review/RejectedOccurrencesTable.tsx +++ b/apps/admin-ui/src/spa/application-rounds/[id]/review/RejectedOccurrencesTable.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { CustomTable, ExternalTableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; import { getApplicationUrl, getReservationUrl } from "@/common/urls"; import type { RejectedOccurrencesQuery } from "@gql/gql-types"; import { truncate } from "common/src/helpers"; @@ -10,6 +10,7 @@ import type { TFunction } from "i18next"; import { getApplicantName } from "@/helpers"; import { toUIDate } from "common/src/common/util"; import { formatTime } from "@/common/util"; +import { ExternalTableLink } from "@/styles/util"; const unitsTruncateLen = 23; const applicantTruncateLen = 20; @@ -94,11 +95,7 @@ const COLS = [ applicationPk, pk, }: RejectedOccurrencesView) => ( - + {truncate(applicantName ?? "-", applicantTruncateLen)} @@ -138,7 +135,7 @@ const COLS = [ key: "time_of_occurrence", transform: ({ time, link }: RejectedOccurrencesView) => { if (link !== "") { - return {time}; + return {time}; } return {time}; }, diff --git a/apps/admin-ui/src/spa/application-rounds/index.tsx b/apps/admin-ui/src/spa/application-rounds/index.tsx index f0616b7877..64b3200fc7 100644 --- a/apps/admin-ui/src/spa/application-rounds/index.tsx +++ b/apps/admin-ui/src/spa/application-rounds/index.tsx @@ -19,8 +19,8 @@ import { Container } from "@/styles/layout"; import { truncate } from "@/helpers"; import Loader from "@/component/Loader"; import { ApplicationRoundCard } from "./ApplicationRoundCard"; -import { TableLink } from "@/component/Table"; import { StyledHDSTable } from "./CustomTable"; +import { TableLink } from "@/styles/util"; const AccordionContainer = styled.div` display: flex; @@ -180,7 +180,7 @@ function AllApplicationRounds(): JSX.Element | null { isSortable: true, headerName: t("ApplicationRound.headings.name"), transform: (applicationRound: ApplicationRoundNode) => ( - + {truncate(applicationRound.nameFi ?? "", 50)} diff --git a/apps/admin-ui/src/spa/notifications/index.tsx b/apps/admin-ui/src/spa/notifications/index.tsx index f8bfe004bd..d6ed8c5b1c 100644 --- a/apps/admin-ui/src/spa/notifications/index.tsx +++ b/apps/admin-ui/src/spa/notifications/index.tsx @@ -14,9 +14,10 @@ import Loader from "@/component/Loader"; import { ButtonLikeLink } from "@/component/ButtonLikeLink"; import { valueForDateInput, valueForTimeInput } from "@/helpers"; import { GQL_MAX_RESULTS_PER_QUERY } from "@/common/const"; -import { CustomTable, TableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; import { filterNonNullable } from "common/src/helpers"; import { More } from "@/component/More"; +import { TableLink } from "@/styles/util"; const notificationUrl = (pk: number) => `/messaging/notifications/${pk}`; @@ -41,7 +42,7 @@ const getColConfig = (t: TFunction) => [ isSortable: true, transform: (notification: NonNullable) => notification.pk ? ( - + {notification.name ?? t("Notifications.noName")} ) : ( diff --git a/apps/admin-ui/src/spa/reservation-units/ReservationUnitsTable.tsx b/apps/admin-ui/src/spa/reservation-units/ReservationUnitsTable.tsx index 24838ba68b..15b346024c 100644 --- a/apps/admin-ui/src/spa/reservation-units/ReservationUnitsTable.tsx +++ b/apps/admin-ui/src/spa/reservation-units/ReservationUnitsTable.tsx @@ -4,8 +4,9 @@ import type { TFunction } from "i18next"; import type { SearchReservationUnitsQuery } from "@gql/gql-types"; import { truncate } from "@/helpers"; import { getReservationUnitUrl } from "@/common/urls"; -import { CustomTable, TableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; import { MAX_NAME_LENGTH } from "@/common/const"; +import { TableLink } from "@/styles/util"; type ReservationUnitList = NonNullable< SearchReservationUnitsQuery["reservationUnits"] @@ -25,7 +26,7 @@ const getColConfig = (t: TFunction) => [ headerName: t("ReservationUnits.headings.name"), key: "nameFi", transform: ({ nameFi, pk, unit }: ReservationUnitNode) => ( - + {truncate(nameFi ?? "-", MAX_NAME_LENGTH)} ), diff --git a/apps/admin-ui/src/spa/reservations/ReservationsTable.tsx b/apps/admin-ui/src/spa/reservations/ReservationsTable.tsx index fd01c07fae..69ceffa328 100644 --- a/apps/admin-ui/src/spa/reservations/ReservationsTable.tsx +++ b/apps/admin-ui/src/spa/reservations/ReservationsTable.tsx @@ -10,8 +10,9 @@ import { formatDateTimeRange, getReserveeName, } from "@/common/util"; -import { CustomTable, TableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; import { MAX_NAME_LENGTH } from "@/common/const"; +import { TableLink } from "@/styles/util"; type ReservationTableColumn = { headerName: string; @@ -48,7 +49,7 @@ const getColConfig = (t: TFunction): ReservationTableColumn[] => [ MAX_NAME_LENGTH ); return ( - + {reservationDisplayName || t("RequestedReservation.noName")} ); diff --git a/apps/admin-ui/src/spa/unit/ResourcesTable.tsx b/apps/admin-ui/src/spa/unit/ResourcesTable.tsx index 7bad6326c3..ddadb23bae 100644 --- a/apps/admin-ui/src/spa/unit/ResourcesTable.tsx +++ b/apps/admin-ui/src/spa/unit/ResourcesTable.tsx @@ -13,10 +13,11 @@ import { } from "@gql/gql-types"; import { PopupMenu } from "@/component/PopupMenu"; import { getResourceUrl } from "@/common/urls"; -import { CustomTable, TableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; import { errorToast, successToast } from "common/src/common/toast"; import { truncate } from "common/src/helpers"; import { MAX_NAME_LENGTH } from "@/common/const"; +import { TableLink } from "@/styles/util"; interface IProps { unit: UnitQuery["unit"]; @@ -72,7 +73,7 @@ export function ResourcesTable({ unit, refetch }: IProps): JSX.Element { const link = getResourceUrl(pk, unit?.pk); const name = nameFi != null && nameFi.length > 0 ? nameFi : "-"; return ( - + {truncate(trim(name), MAX_NAME_LENGTH)} ); diff --git a/apps/admin-ui/src/spa/unit/SpacesTable.tsx b/apps/admin-ui/src/spa/unit/SpacesTable.tsx index 249da92561..80cd1fb518 100644 --- a/apps/admin-ui/src/spa/unit/SpacesTable.tsx +++ b/apps/admin-ui/src/spa/unit/SpacesTable.tsx @@ -16,10 +16,11 @@ import { PopupMenu } from "@/component/PopupMenu"; import Modal, { useModal as useHDSModal } from "@/component/HDSModal"; import { NewSpaceModal } from "./space/new-space-modal/NewSpaceModal"; import { errorToast } from "common/src/common/toast"; -import { CustomTable, TableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; import { getSpaceUrl } from "@/common/urls"; import { truncate } from "common/src/helpers"; import { MAX_NAME_LENGTH } from "@/common/const"; +import { TableLink } from "@/styles/util"; interface IProps { unit: UnitQuery["unit"]; @@ -140,7 +141,7 @@ export function SpacesTable({ unit, refetch }: IProps): JSX.Element { const link = getSpaceUrl(pk, unit?.pk); const name = nameFi != null && nameFi.length > 0 ? nameFi : "-"; return ( - + {truncate(trim(name), MAX_NAME_LENGTH)} ); diff --git a/apps/admin-ui/src/spa/unit/UnitsTable.tsx b/apps/admin-ui/src/spa/unit/UnitsTable.tsx index dd94e3ecf5..8d0330c0c4 100644 --- a/apps/admin-ui/src/spa/unit/UnitsTable.tsx +++ b/apps/admin-ui/src/spa/unit/UnitsTable.tsx @@ -5,8 +5,9 @@ import type { UnitsQuery } from "@gql/gql-types"; import type { TFunction } from "i18next"; import { truncate } from "@/helpers"; import { getMyUnitUrl, getUnitUrl } from "@/common/urls"; -import { CustomTable, TableLink } from "@/component/Table"; +import { CustomTable } from "@/component/Table"; import { MAX_UNIT_NAME_LENGTH } from "@/common/const"; +import { TableLink } from "@/styles/util"; type UnitType = NonNullable< NonNullable["edges"][0]>["node"] @@ -33,7 +34,7 @@ function getColConfig(t: TFunction, isMyUnits?: boolean): ColumnType[] { headerName: t("Units.headings.name"), key: "nameFi", transform: ({ nameFi, pk }: UnitType) => ( - + {truncate(nameFi ?? "-", MAX_UNIT_NAME_LENGTH)} ), diff --git a/apps/admin-ui/src/spa/unit/[id]/index.tsx b/apps/admin-ui/src/spa/unit/[id]/index.tsx index b291a6811c..a39b24efcc 100644 --- a/apps/admin-ui/src/spa/unit/[id]/index.tsx +++ b/apps/admin-ui/src/spa/unit/[id]/index.tsx @@ -15,7 +15,7 @@ import { ExternalLink } from "@/component/ExternalLink"; import { base64encode, filterNonNullable } from "common/src/helpers"; import Error404 from "@/common/Error404"; import { ReservationUnitList } from "./ReservationUnitList"; -import { getReservationUnitUrl } from "@/common/urls"; +import { getReservationUnitUrl, getSpacesResourcesUrl } from "@/common/urls"; interface IProps { [key: string]: string; @@ -139,7 +139,7 @@ function Unit(): JSX.Element { return ( - + {t("Unit.showSpacesAndResources")} @@ -161,7 +161,7 @@ function Unit(): JSX.Element { size="large" > {t("Unit.noSpacesResources")}{" "} - + {t("Unit.createSpaces")} diff --git a/apps/admin-ui/src/spa/unit/space/Head.tsx b/apps/admin-ui/src/spa/unit/space/Head.tsx index 1f6a21171c..cbe27d3e13 100644 --- a/apps/admin-ui/src/spa/unit/space/Head.tsx +++ b/apps/admin-ui/src/spa/unit/space/Head.tsx @@ -6,6 +6,7 @@ import styled from "styled-components"; import { breakpoints } from "common/src/common/style"; import type { SpaceQuery } from "@gql/gql-types"; import { parseAddress } from "@/common/util"; +import { getUnitUrl } from "@/common/urls"; interface IProps { title: string; @@ -59,8 +60,7 @@ export function Head({ const { unit } = space || {}; const { t } = useTranslation(); - // TODO use urlBuilder - const unitUrl = `/unit/${unit?.pk}`; + const unitUrl = getUnitUrl(unit?.pk); return ( diff --git a/apps/admin-ui/src/styles/util.ts b/apps/admin-ui/src/styles/util.ts index 2c4cdda26a..4c4b4bed13 100644 --- a/apps/admin-ui/src/styles/util.ts +++ b/apps/admin-ui/src/styles/util.ts @@ -18,6 +18,7 @@ export const Seranwrap = styled.div` opacity: 0.2; `; +// TODO link component naming? export const BasicLink = styled(Link)` color: var(--tilavaraus-admin-content-text-color); text-decoration: none; @@ -28,6 +29,24 @@ export const BasicLink = styled(Link)` gap: var(--spacing-xs); `; +export const TableLink = styled(Link)` + color: black; +`; + +// NOTE not using IconButton because of hover effect +export const ExternalTableLink = styled(Link).attrs({ + target: "_blank", + rel: "noopener noreferrer", +})` + color: var(--color-black); + display: flex; + align-items: center; + gap: var(--spacing-3-xs); + & > svg { + margin-top: var(--spacing-3-xs); + } +`; + export const DialogActionsButtons = styled(Dialog.ActionButtons)` justify-content: space-between; `; diff --git a/packages/common/src/termsbox/TermsBox.tsx b/packages/common/src/termsbox/TermsBox.tsx index 3373178d2a..3f44f502e3 100644 --- a/packages/common/src/termsbox/TermsBox.tsx +++ b/packages/common/src/termsbox/TermsBox.tsx @@ -3,6 +3,7 @@ import React from "react"; import styled from "styled-components"; import { breakpoints } from "../common/style"; import { H6 } from "../common/typography"; +import Link from "next/link"; type LinkT = { href: string; @@ -53,7 +54,7 @@ const Content = styled.div` } `; -const Links = styled.ul` +const LinkList = styled.ul` list-style: none; margin-bottom: 0; padding: 0; @@ -62,9 +63,7 @@ const Links = styled.ul` gap: var(--spacing-2-xs); `; -const Link = styled.li``; - -const Anchor = styled.a` +const Anchor = styled(Link)` color: var(--color-black) !important; text-decoration: underline; display: flex; @@ -111,9 +110,9 @@ const TermsBox = ({ {heading}

{body}

{links && links?.length > 0 && ( - + {links.map((link) => ( - +
  • - +
  • ))} -
    + )} {canAccept && (