diff --git a/apps/app/src/pages/org/[slug]/[orgLocationId]/edit/[orgServiceId].tsx b/apps/app/src/pages/org/[slug]/[orgLocationId]/edit/[orgServiceId].tsx index f47acd9c21..ae142e0d69 100644 --- a/apps/app/src/pages/org/[slug]/[orgLocationId]/edit/[orgServiceId].tsx +++ b/apps/app/src/pages/org/[slug]/[orgLocationId]/edit/[orgServiceId].tsx @@ -1,12 +1,12 @@ -import { createStyles, Grid, rem, Stack } from '@mantine/core' +import { Grid, Stack } from '@mantine/core' import dynamic from 'next/dynamic' import { useRouter } from 'next/router' import { useTranslation } from 'next-i18next' import { type GetServerSideProps } from 'nextjs-routes' import { type ReactNode, Suspense, useEffect, useState } from 'react' -import { type Path, useFieldArray, useForm } from 'react-hook-form' +import { /*type Path,*/ useFieldArray, useForm } from 'react-hook-form' import { Textarea, TextInput } from 'react-hook-form-mantine' -import { type Merge } from 'type-fest' +// import { type Merge } from 'type-fest' import { z } from 'zod' import { prefixedId } from '@weareinreach/api/schemas/idPrefix' @@ -31,8 +31,7 @@ const FreetextObject = z }) .nullish() -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type MapValue = A extends Map ? V : never +// type MapValue = A extends Map ? V : never const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]) type Literal = z.infer @@ -95,10 +94,10 @@ const EditServicePage = () => { const activeServices = form.watch('services') ?? [] type AttrSectionKeys = 'clientsServed' | 'cost' | 'eligibility' | 'languages' | 'additionalInfo' - type AttrSectionVals = Merge< - FormSchemaType['attributes'][number], - { _rhfName: Path; _rhfLabel: string } - > + // type AttrSectionVals = Merge< + // FormSchemaType['attributes'][number], + // { _rhfName: Path; _rhfLabel: string } + // > const attributeBase: { [key in AttrSectionKeys]: ReactNode[] @@ -264,7 +263,7 @@ export const getServerSideProps: GetServerSideProps = async ({ locale, params, r }) .safeParse(params) if (!urlParams.success) return { notFound: true } - const { slug, orgLocationId, orgServiceId } = urlParams.data + const { slug, orgLocationId: _, orgServiceId } = urlParams.data const session = await checkServerPermissions({ ctx: { req, res }, permissions: ['dataPortalBasic'], diff --git a/apps/app/src/pages/org/[slug]/[orgLocationId]/index.tsx b/apps/app/src/pages/org/[slug]/[orgLocationId]/index.tsx index 438c8c497b..0e42aa3fae 100644 --- a/apps/app/src/pages/org/[slug]/[orgLocationId]/index.tsx +++ b/apps/app/src/pages/org/[slug]/[orgLocationId]/index.tsx @@ -1,4 +1,4 @@ -import { createStyles, Divider, Grid, Skeleton, Stack, Tabs, useMantineTheme } from '@mantine/core' +import { createStyles, Divider, Grid, Stack, Tabs, useMantineTheme } from '@mantine/core' import { useMediaQuery } from '@mantine/hooks' // import compact from 'just-compact' import { type GetStaticPaths, type GetStaticPropsContext, type NextPage } from 'next' diff --git a/apps/app/src/pages/org/[slug]/index.tsx b/apps/app/src/pages/org/[slug]/index.tsx index 0f78215ad4..7f33be4a0b 100644 --- a/apps/app/src/pages/org/[slug]/index.tsx +++ b/apps/app/src/pages/org/[slug]/index.tsx @@ -1,4 +1,4 @@ -import { createStyles, Divider, Grid, Skeleton, Stack, Tabs, useMantineTheme } from '@mantine/core' +import { createStyles, Divider, Grid, Stack, Tabs, useMantineTheme } from '@mantine/core' import { useElementSize, useMediaQuery } from '@mantine/hooks' import { type GetStaticPaths, type GetStaticPropsContext, type InferGetStaticPropsType } from 'next' import dynamic from 'next/dynamic' diff --git a/apps/app/src/providers/index.tsx b/apps/app/src/providers/index.tsx index b3e78a2836..33aa6e2479 100644 --- a/apps/app/src/providers/index.tsx +++ b/apps/app/src/providers/index.tsx @@ -1,12 +1,12 @@ 'use client' import { MantineProvider } from '@mantine/core' -import dynamic, { type LoaderComponent } from 'next/dynamic' -import { Noto_Color_Emoji, Work_Sans } from 'next/font/google' +// import dynamic, { type LoaderComponent } from 'next/dynamic' +import { /*Noto_Color_Emoji,*/ Work_Sans } from 'next/font/google' import { type Session } from 'next-auth' import { SessionProvider } from 'next-auth/react' -import { Trans, useTranslation } from 'next-i18next' -import { type ComponentPropsWithoutRef, useMemo } from 'react' -import { type ConsentBanner, type ConsentOptions } from 'react-hook-consent' +// import { Trans, useTranslation } from 'next-i18next' +// import { type ComponentPropsWithoutRef, useMemo } from 'react' +// import { type ConsentBanner, type ConsentOptions } from 'react-hook-consent' import { EditModeProvider } from '@weareinreach/ui/providers/EditMode' import { GoogleMapsProvider } from '@weareinreach/ui/providers/GoogleMaps' @@ -14,7 +14,7 @@ import { SearchStateProvider } from '@weareinreach/ui/providers/SearchState' import { appCache, appTheme } from '@weareinreach/ui/theme' import 'react-hook-consent/dist/styles/style.css' -const fallbackEmoji = Noto_Color_Emoji({ weight: '400', subsets: ['emoji'] }) +// const fallbackEmoji = Noto_Color_Emoji({ weight: '400', subsets: ['emoji'] }) const fontWorkSans = Work_Sans({ subsets: ['latin-ext'], @@ -33,68 +33,68 @@ const fontWorkSans = Work_Sans({ ], }) -const PrivacyStatementModal = dynamic( - () => - import('@weareinreach/ui/modals/PrivacyStatement').then( - (mod) => mod.PrivacyStatementModal - ) satisfies LoaderComponent -) -const Link = dynamic(() => import('@weareinreach/ui/components/core/Link').then((mod) => mod.Link)) +// const PrivacyStatementModal = dynamic( +// () => +// import('@weareinreach/ui/modals/PrivacyStatement').then( +// (mod) => mod.PrivacyStatementModal +// ) satisfies LoaderComponent +// ) +// const Link = dynamic(() => import('@weareinreach/ui/components/core/Link').then((mod) => mod.Link)) export const Providers = ({ children, session }: ProviderProps) => { - const { t } = useTranslation('common') + // const { t } = useTranslation('common') - const consentOptions: ConsentOptions = useMemo( - () => ({ - services: [ - { - id: 'basic', - name: t('cookie-consent.item-basic'), - mandatory: true, - }, - { - id: 'ga4', - name: t('cookie-consent.item-ga4'), - scripts: [ - { - id: 'ga4-consent', - code: `window.gtag && window.gtag('consent', 'update', {ad_storage: 'granted', analytics_storage: 'granted'})`, - }, - ], - }, - ], - theme: 'light', - }), - [t] - ) + // const consentOptions: ConsentOptions = useMemo( + // () => ({ + // services: [ + // { + // id: 'basic', + // name: t('cookie-consent.item-basic'), + // mandatory: true, + // }, + // { + // id: 'ga4', + // name: t('cookie-consent.item-ga4'), + // scripts: [ + // { + // id: 'ga4-consent', + // code: `window.gtag && window.gtag('consent', 'update', {ad_storage: 'granted', analytics_storage: 'granted'})`, + // }, + // ], + // }, + // ], + // theme: 'light', + // }), + // [t] + // ) - const consentBannerSettings: ConsentBannerOpts = useMemo( - () => ({ - settings: { - modal: { - title: t('cookie-consent.modal-title'), - approve: { label: t('cookie-consent.approve-selected') }, - approveAll: { label: t('cookie-consent.approve-all') }, - decline: { label: t('words.decline') }, - description: ( - This is a dynamic component */ - - ), - }} - /> - ), - }, - label: t('words.customize'), - }, - approve: { label: t('words.accept') }, - decline: { label: t('words.decline') }, - }), - [t] - ) + // const consentBannerSettings: ConsentBannerOpts = useMemo( + // () => ({ + // settings: { + // modal: { + // title: t('cookie-consent.modal-title'), + // approve: { label: t('cookie-consent.approve-selected') }, + // approveAll: { label: t('cookie-consent.approve-all') }, + // decline: { label: t('words.decline') }, + // description: ( + // This is a dynamic component */ + // + // ), + // }} + // /> + // ), + // }, + // label: t('words.customize'), + // }, + // approve: { label: t('words.accept') }, + // decline: { label: t('words.decline') }, + // }), + // [t] + // ) return ( +// type ConsentBannerOpts = ComponentPropsWithoutRef diff --git a/packages/api/router/organization/query.searchDistance.handler.ts b/packages/api/router/organization/query.searchDistance.handler.ts index 44973080a0..3035fca616 100644 --- a/packages/api/router/organization/query.searchDistance.handler.ts +++ b/packages/api/router/organization/query.searchDistance.handler.ts @@ -118,7 +118,7 @@ service_area as ( WHEN district."geoDataId" IS NOT NULL THEN district."geoDataId" END) AS "geoId", array_remove(array_agg(DISTINCT district.slug), NULL) AS "matchedDistricts", - array_remove(array_agg(DISTINCT country.cca3),NULL) AS "matchedCountries" + array_remove(array_agg(DISTINCT country.cca2),NULL) AS "matchedCountries" FROM "ServiceArea" sa LEFT JOIN "ServiceAreaCountry" sac ON sac. "serviceAreaId" = sa.id AND sac.active diff --git a/packages/ui/components/core/Badge/Group.tsx b/packages/ui/components/core/Badge/Group.tsx index 5d193b6555..b8c614d86c 100644 --- a/packages/ui/components/core/Badge/Group.tsx +++ b/packages/ui/components/core/Badge/Group.tsx @@ -1,5 +1,5 @@ import { Divider, List, type ListProps, useMantineTheme } from '@mantine/core' -import { Children, type ReactNode } from 'react' +import { Children, isValidElement, type ReactNode } from 'react' import { useCustomVariant } from '~ui/hooks/useCustomVariant' @@ -17,9 +17,11 @@ export const _BadgeGroup = ({ withSeparator, children, ...props }: BadgeGroupPro m={0} {...props} > - {Children.map(children, (child, idx) => ( - {child} - ))} + {Children.map(children, (child, idx) => { + const { key } = isValidElement(child) ? child : { key: idx } + + return {child} + })} ) } diff --git a/packages/ui/components/core/Badge/Leader.tsx b/packages/ui/components/core/Badge/Leader.tsx index 52a094a86f..f8a8d48495 100644 --- a/packages/ui/components/core/Badge/Leader.tsx +++ b/packages/ui/components/core/Badge/Leader.tsx @@ -19,7 +19,15 @@ export const _Leader = forwardRef( ) const badge = ( - + {minify ? null : {children}} ) diff --git a/packages/ui/components/core/Badge/National.tsx b/packages/ui/components/core/Badge/National.tsx index 526e04439c..59de9ebbda 100644 --- a/packages/ui/components/core/Badge/National.tsx +++ b/packages/ui/components/core/Badge/National.tsx @@ -1,4 +1,4 @@ -import { Badge, type BadgeProps, rem, Tooltip, useMantineTheme } from '@mantine/core' +import { Badge, type BadgeProps, Tooltip, useMantineTheme } from '@mantine/core' import compact from 'just-compact' import { useTranslation } from 'next-i18next' import { forwardRef } from 'react' @@ -16,17 +16,11 @@ export const _National = forwardRef( const variants = useCustomVariant() const leftSection = ( - + ) const badge = ( - + ) const listFormatter = new Intl.ListFormat(i18n.resolvedLanguage, { diff --git a/packages/ui/components/core/Badge/styles.ts b/packages/ui/components/core/Badge/styles.ts index 5322882df5..61975ac178 100644 --- a/packages/ui/components/core/Badge/styles.ts +++ b/packages/ui/components/core/Badge/styles.ts @@ -7,6 +7,8 @@ export const useSharedStyles = (variant: SharedStyles) => { case 'national': { return { leftSection: { + alignSelf: 'center', + lineHeight: variant === 'national' ? 0 : undefined, '& *': { fontSize: theme.fontSizes.xs, borderRadius: theme.radius.xl, @@ -14,7 +16,7 @@ export const useSharedStyles = (variant: SharedStyles) => { width: rem(24), margin: 0, textAlign: 'center', - paddingBottom: rem(4), + paddingBottom: variant === 'leader' ? rem(4) : 0, color: theme.other.colors.secondary.black, }, }, @@ -104,6 +106,6 @@ type SharedStyles = | 'attribute' | 'remote' -type CustomBadgeStyles = Partial<{ [className in BadgeStylesNames]: CSSObject }> +// type CustomBadgeStyles = Partial<{ [className in BadgeStylesNames]: CSSObject }> -type UseSharedStyles = (variant: SharedStyles) => CustomBadgeStyles +// type UseSharedStyles = (variant: SharedStyles) => CustomBadgeStyles diff --git a/packages/ui/components/core/SearchBox.tsx b/packages/ui/components/core/SearchBox.tsx index 981e16d135..9baa78f6c7 100644 --- a/packages/ui/components/core/SearchBox.tsx +++ b/packages/ui/components/core/SearchBox.tsx @@ -147,12 +147,12 @@ export const SearchBox = ({ const variants = useCustomVariant() const { t } = useTranslation() const router = useRouter() - const form = useForm({ initialValues: { search: initialValue } }) - const [search] = useDebouncedValue(form.values.search, 400) const [locationSearch, setLocationSearch] = useLocationSearch() const { isLoading, setLoading } = loadingManager const isOrgSearch = type === 'organization' - const { searchStateActions } = useSearchState() + const { searchStateActions, searchState } = useSearchState() + const form = useForm({ initialValues: { search: searchState.searchTerm || initialValue } }) + const [search] = useDebouncedValue(form.values.search, 400) // tRPC functions const { data: orgSearchData, isFetching: orgSearchLoading } = api.organization.searchName.useQuery( diff --git a/packages/ui/components/core/SearchResultCard.tsx b/packages/ui/components/core/SearchResultCard.tsx index c4c4232acd..52e4c136a1 100644 --- a/packages/ui/components/core/SearchResultCard.tsx +++ b/packages/ui/components/core/SearchResultCard.tsx @@ -6,7 +6,7 @@ import { type ApiOutput } from '@weareinreach/api' import { useCustomVariant } from '~ui/hooks' import { ActionButtons } from './ActionButtons' -import { BadgeGroup, type CustomBadgeProps } from './Badge' +import { Badge } from './Badge' import { Link } from './Link' const useStyles = createStyles((theme) => ({ @@ -64,30 +64,34 @@ const SearchResultData = ({ result }: SearchResultHasData) => { const { hovered, ref: hoverRef } = useHover() if (!i18nReady) return - const leaderBadges: CustomBadgeProps[] = orgLeader.map(({ icon, iconBg, tsKey }) => ({ - variant: 'leader', - icon: icon ?? '', - iconBg: iconBg ?? '#FFFFFF', - tsKey, - minify: true, - hideBg: true, - })) - const focusBadges: CustomBadgeProps[] = orgFocus.map(({ icon, tsKey }) => ({ - variant: 'community', - icon: icon ?? '', - tsKey, - })) - const serviceTags: CustomBadgeProps[] = serviceCategories.map(({ tsKey }) => ({ - variant: 'service', - tsKey, - })) - if (national.length) { - leaderBadges.push({ - variant: 'national', - tsKey: national, - }) - } + const leaderBadgeGroup = + orgLeader.length || national.length ? ( + + {orgLeader.map(({ icon, iconBg, id, tsKey }) => ( + + {t(tsKey, { ns: 'attribute' })} + + ))} + {national.length ? : null} + + ) : null + const communityFocusBadgeGroup = orgFocus.length ? ( + + {orgFocus.map(({ icon, id, tsKey }) => ( + + {t(tsKey, { ns: 'attribute' })} + + ))} + + ) : null + const serviceBadgeGroup = serviceCategories.length ? ( + + {serviceCategories.map(({ id, tsKey }) => ( + {t(tsKey, { ns: 'services' })} + ))} + + ) : null const cityList = (cities: string[]) => { //check for duplicates and be case insensitive, before switching @@ -142,7 +146,7 @@ const SearchResultData = ({ result }: SearchResultHasData) => { {name} - + {leaderBadgeGroup} @@ -161,8 +165,8 @@ const SearchResultData = ({ result }: SearchResultHasData) => { - - + {communityFocusBadgeGroup} + {serviceBadgeGroup} @@ -173,9 +177,6 @@ export const SearchResultCard = (props: SearchResultCardProps) => props.loading ? : export type SearchResultCardProps = SearchResultHasData | SearchResultLoading -// { -// result: NonNullable['orgs'][number] -// } type SearchResultHasData = { result: NonNullable['orgs'][number] diff --git a/packages/ui/modals/MoreFilter.tsx b/packages/ui/modals/MoreFilter.tsx index 193eb3ed86..eec63f6e5d 100644 --- a/packages/ui/modals/MoreFilter.tsx +++ b/packages/ui/modals/MoreFilter.tsx @@ -20,7 +20,6 @@ import { import { useForm } from '@mantine/form' import { useMediaQuery, useViewportSize } from '@mantine/hooks' import { createPolymorphicComponent } from '@mantine/utils' -import { useRouter } from 'next/router' import { useTranslation } from 'next-i18next' import { forwardRef, type JSX, type MouseEventHandler, useEffect, useState } from 'react' @@ -217,8 +216,7 @@ const MoreFilterBody = forwardRef( const { t } = useTranslation(['common', 'attribute']) const [opened, setOpened] = useState(false) const theme = useMantineTheme() - const router = useRouter() - const { searchStateActions } = useSearchState() + const { searchStateActions, searchState } = useSearchState() const isMobileQuery = useMediaQuery(`(max-width: ${theme.breakpoints.xs})`) const isLandscape = useMediaQuery(`(orientation: landscape) and (max-height: ${em(430)})`) @@ -233,11 +231,7 @@ const MoreFilterBody = forwardRef( type FilterValue = AttributeFilter & { checked: boolean } const form = useForm({ initialValues: [] }) - const preSelected = Array.isArray(router.query.a) - ? router.query.a - : typeof router.query.a === 'string' - ? [router.query.a] - : [] + const preSelected = searchState.attributes const generateInitialData = (opts?: { clear?: boolean }) => { if (!moreFilterOptionData) return [] diff --git a/packages/ui/modals/ServiceFilter/index.tsx b/packages/ui/modals/ServiceFilter/index.tsx index 5d54af78d9..0413c80bee 100644 --- a/packages/ui/modals/ServiceFilter/index.tsx +++ b/packages/ui/modals/ServiceFilter/index.tsx @@ -14,7 +14,6 @@ import { Checkbox as VanillaCheckbox, } from '@mantine/core' import { useMediaQuery, useViewportSize } from '@mantine/hooks' -import { useRouter } from 'next/router' import { useTranslation } from 'next-i18next' import { type BaseSyntheticEvent, type MouseEvent, useEffect, useMemo, useState } from 'react' import { useForm, useWatch } from 'react-hook-form' @@ -44,8 +43,7 @@ export const ServiceFilter = ({ resultCount, isFetching, disabled }: ServiceFilt const { t } = useTranslation(['common', 'services']) const [opened, setOpened] = useState(false) const theme = useMantineTheme() - const router = useRouter() - const { searchStateActions } = useSearchState() + const { searchStateActions, searchState } = useSearchState() // #region Media Queries const isMobileQuery = useMediaQuery(`(max-width: ${theme.breakpoints.xs})`) @@ -58,11 +56,7 @@ export const ServiceFilter = ({ resultCount, isFetching, disabled }: ServiceFilt const scrollAreaMaxHeight = isMobile ? viewportHeight - 210 + 30 : viewportHeight * 0.6 - 88 // #endregion - const preSelected = Array.isArray(router.query.s) - ? router.query.s - : typeof router.query.s === 'string' - ? [router.query.s] - : [] + const preSelected = searchState.services const form = useForm<{ selected: string[] }>({ values: { selected: preSelected }, })