diff --git a/apps/vth-frontend/public/favicon/android-chrome-192x192.png b/apps/vth-frontend/public/favicon/android-chrome-192x192.png new file mode 100644 index 000000000..79952d14e Binary files /dev/null and b/apps/vth-frontend/public/favicon/android-chrome-192x192.png differ diff --git a/apps/vth-frontend/public/favicon/android-chrome-512x512.png b/apps/vth-frontend/public/favicon/android-chrome-512x512.png new file mode 100644 index 000000000..7e89aba7c Binary files /dev/null and b/apps/vth-frontend/public/favicon/android-chrome-512x512.png differ diff --git a/apps/vth-frontend/public/favicon/apple-touch-icon.png b/apps/vth-frontend/public/favicon/apple-touch-icon.png new file mode 100644 index 000000000..ce372576d Binary files /dev/null and b/apps/vth-frontend/public/favicon/apple-touch-icon.png differ diff --git a/apps/vth-frontend/public/favicon/favicon-16x16.png b/apps/vth-frontend/public/favicon/favicon-16x16.png new file mode 100644 index 000000000..12c54fc55 Binary files /dev/null and b/apps/vth-frontend/public/favicon/favicon-16x16.png differ diff --git a/apps/vth-frontend/public/favicon/favicon-32x32.png b/apps/vth-frontend/public/favicon/favicon-32x32.png new file mode 100644 index 000000000..969e806d5 Binary files /dev/null and b/apps/vth-frontend/public/favicon/favicon-32x32.png differ diff --git a/apps/vth-frontend/public/favicon/site.webmanifest b/apps/vth-frontend/public/favicon/site.webmanifest new file mode 100644 index 000000000..fa99de77d --- /dev/null +++ b/apps/vth-frontend/public/favicon/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/apps/vth-frontend/src/app/[locale]/(nestedNavLayout)/layout.tsx b/apps/vth-frontend/src/app/[locale]/(nestedNavLayout)/layout.tsx index 8a242e11b..0fa2e98fc 100644 --- a/apps/vth-frontend/src/app/[locale]/(nestedNavLayout)/layout.tsx +++ b/apps/vth-frontend/src/app/[locale]/(nestedNavLayout)/layout.tsx @@ -1,18 +1,42 @@ import classnames from 'classnames'; import { dir } from 'i18next'; import type { Metadata } from 'next'; -import { draftMode } from 'next/headers'; +import { draftMode, headers } from 'next/headers'; +import Link from 'next/link'; import Script from 'next/script'; import React from 'react'; -import { useTranslation } from '@/app/i18n'; import { QueryClientProvider } from '@/client'; -import { Footer, FooterData, Page, PreviewAlert, Surface } from '@/components'; +import { + Footer, + FooterData, + Grid, + GridCell, + Logo, + LogoImage, + Navigation, + NavigationListType, + Page, + PageContent, + PageHeader, + PreviewAlert, + SkipLink, + Surface, +} from '@/components'; +// import { ClientLanguageSwitcher } from '@/components/ClientLanguageSwitcher'; import '@utrecht/component-library-css'; import '@utrecht/design-tokens/dist/index.css'; +import { Main } from '@/components/Main'; +import { SearchBar } from '@/components/SearchBar'; import 'react-loading-skeleton/dist/skeleton.css'; -import { Editoria11y } from '@/components/Editoria11y'; +import { GET_OPEN_FORMS_TEMPLATE } from '@/query'; +import { buildAlternateLinks, createStrapiURL, fetchData } from '@/util'; +import { ComponentComponentsUtrechtNavigation, GetTemplateDataQuery } from '../../../../gql/graphql'; +import { getLiveSuggestions, onSearchSubmitAction } from '../../actions'; +import { useTranslation } from '../../i18n/index'; +import { languages } from '../../i18n/settings'; import '@frameless/ui/dist/bundle.css'; import '../../../styles/globals.css'; +import '../../../styles/openforms.scss'; interface LayoutProps { children: React.ReactNode; @@ -30,17 +54,71 @@ type Params = { export async function generateMetadata({ params: { locale } }: Params): Promise { // eslint-disable-next-line react-hooks/rules-of-hooks const { t } = await useTranslation(locale, 'common'); + const url = `${process.env.FRONTEND_PUBLIC_URL}/${locale}`; return { title: { template: `%s | ${t('website-setting.website-name')}`, default: `${t('website-setting.website-name')}`, }, + icons: { + icon: [ + { + url: '/favicon/favicon.ico', + }, + { + url: '/favicon/android-chrome-192x192.png', + type: 'image/png', + sizes: '192x192', + }, + { + url: '/favicon/android-chrome-512x512.png', + type: 'image/png', + sizes: '512x512', + }, + { + url: '/favicon/favicon-32x32.png', + type: 'image/png', + sizes: '32x32', + }, + { + url: '/favicon/favicon-16x16.png', + type: 'image/png', + sizes: '16x16', + }, + ], + apple: [{ url: '/favicon/apple-touch-icon.png', type: 'image/png', sizes: '180x180' }], + }, + manifest: '/favicon/site.webmanifest', + openGraph: { + type: 'website', + locale, + siteName: t('website-setting.website-name') || 'Gemeente Utrecht', + countryName: 'NL', + url, + }, + metadataBase: new URL(process.env.FRONTEND_PUBLIC_URL || 'http://localhost:3000'), + alternates: { + canonical: `/${locale}`, + languages: { + ...buildAlternateLinks({ languages }), + }, + }, }; } const RootLayout = async ({ children, params: { locale } }: LayoutProps) => { + const nonce = headers().get('x-nonce') || ''; const { t } = await useTranslation(locale, ['layout', 'common']); const { isEnabled } = draftMode(); + const { data } = await fetchData<{ data: GetTemplateDataQuery }>({ + url: createStrapiURL(), + query: GET_OPEN_FORMS_TEMPLATE, + variables: { locale }, + }); + + const navigationData = data.pdcTemplate?.data?.attributes?.sections?.find( + (component) => component?.__typename === 'ComponentComponentsUtrechtNavigation', + ) as ComponentComponentsUtrechtNavigation; const footerData = { title: t('footer.title'), @@ -61,55 +139,23 @@ const RootLayout = async ({ children, params: { locale } }: LayoutProps) => { href: t('footer.list.listItem.0.link.2.href'), textContent: t('footer.list.listItem.0.link.2.textContent'), }, - { - href: t('footer.list.listItem.0.link.3.href'), - textContent: t('footer.list.listItem.0.link.3.textContent'), - }, ], }, ], }, address: t('footer.address'), - socialMediaList: { - link: [ - { - href: t('footer.socialMediaList.link.0.href'), - icon: t('footer.socialMediaList.link.0.icon'), - textContent: t('footer.socialMediaList.link.0.textContent'), - }, - { - href: t('footer.socialMediaList.link.1.href'), - icon: t('footer.socialMediaList.link.1.icon'), - textContent: t('footer.socialMediaList.link.1.textContent'), - }, - { - href: t('footer.socialMediaList.link.2.href'), - icon: t('footer.socialMediaList.link.2.icon'), - textContent: t('footer.socialMediaList.link.2.textContent'), - }, - { - href: t('footer.socialMediaList.link.3.href'), - icon: t('footer.socialMediaList.link.3.icon'), - textContent: t('footer.socialMediaList.link.3.textContent'), - }, - { - href: t('footer.socialMediaList.link.4.href'), - icon: t('footer.socialMediaList.link.4.icon'), - textContent: t('footer.socialMediaList.link.4.textContent'), - }, - { - href: t('footer.socialMediaList.link.5.href'), - icon: t('footer.socialMediaList.link.5.icon'), - textContent: t('footer.socialMediaList.link.5.textContent'), - }, - ], - }, }; return ( {isEnabled && ( @@ -123,22 +169,94 @@ const RootLayout = async ({ children, params: { locale } }: LayoutProps) => { )} - - {isEnabled && } - {children} + + + {t('components.skip-link.main')} + {t('components.skip-link.menu')} + {t('components.skip-link.search-input')} + + +
+ + + + + +
+
+ {/* + + */} + +
+ +
+
+ {navigationData?.navigationList && navigationData?.navigationList?.length > 0 && ( + + + + )} +
+
+ +
{children}
+
+
+