diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index 967463b04..73ded19be 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -1,19 +1,130 @@ import type { MetadataRoute } from "next"; import { client } from "studio/lib/client"; -import { DocumentWithSlug } from "studio/lib/interfaces/global"; -import { PageBuilder } from "studio/lib/interfaces/pages"; -import { DOCUMENTS_WITH_SLUG_QUERY } from "studio/lib/queries/siteMap"; -import { LANDING_PAGE_QUERY } from "studio/lib/queries/siteSettings"; -import { token } from "studio/lib/token"; +import { + DocumentTranslatedSitemapData, + FieldTranslatedSitemapData, + SitemapBaseData, + UntranslatedSitemapData, +} from "studio/lib/interfaces/sitemap"; +import { LanguageObject } from "studio/lib/interfaces/supportedLanguages"; +import { LEGAL_DOCUMENTS_SITEMAP_QUERY } from "studio/lib/queries/admin"; +import { PAGES_SITEMAP_QUERY } from "studio/lib/queries/pages"; +import { + LANDING_PAGE_SITEMAP_QUERY, + LANGUAGES_QUERY, +} from "studio/lib/queries/siteSettings"; +import { + COMPENSATIONS_PAGE_SITEMAP_QUERY, + CUSTOMER_CASES_PAGE_SITEMAP_QUERY, +} from "studio/lib/queries/specialPages"; +import { token as studioToken } from "studio/lib/token"; +import { sharedClient } from "studioShared/lib/client"; +import { CUSTOMER_CASES_SITEMAP_QUERY } from "studioShared/lib/queries/customerCases"; +import { token as sharedToken } from "studioShared/lib/token"; import { readBaseUrl } from "./env"; -const clientWithToken = client.withConfig({ token }); +const clientWithToken = client.withConfig({ token: studioToken }); +const sharedClientWithToken = sharedClient.withConfig({ token: sharedToken }); export const dynamic = "force-dynamic"; export const fetchCache = "default-no-store"; +type RelativeSiteMap = { + relativeUrl: string; + lastModified: Date; +}[]; + +async function landingPageSitemap(): Promise { + const languages = await clientWithToken.fetch( + LANGUAGES_QUERY, + ); + const page = await clientWithToken.fetch( + LANDING_PAGE_SITEMAP_QUERY, + ); + if (languages !== null && page !== null) { + const siteMap = languages.map((language) => ({ + relativeUrl: language.id, + lastModified: new Date(page._updatedAt), + })); + siteMap.push({ + relativeUrl: "", + lastModified: new Date(page._updatedAt), + }); + return siteMap; + } + return []; +} + +async function compensationsPageSitemap(): Promise { + const page = await clientWithToken.fetch( + COMPENSATIONS_PAGE_SITEMAP_QUERY, + ); + if (page?.slug !== undefined) { + return page.slug.map((slug) => { + return { + relativeUrl: `${slug._key}/${slug.value}`, + lastModified: new Date(page._updatedAt), + }; + }); + } + return []; +} + +async function dynamicPagesSitemap(): Promise { + const pages = await clientWithToken.fetch( + PAGES_SITEMAP_QUERY, + ); + if (pages !== null) { + return pages.map((page) => ({ + relativeUrl: page.slug.current, + lastModified: new Date(page._updatedAt), + })); + } + return []; +} + +async function customerCasesSitemap(): Promise { + const page = await clientWithToken.fetch( + CUSTOMER_CASES_PAGE_SITEMAP_QUERY, + ); + if (page !== null) { + const siteMap = [ + { + relativeUrl: page.slug.current, + lastModified: new Date(page._updatedAt), + }, + ]; + const cases = await sharedClientWithToken.fetch< + DocumentTranslatedSitemapData[] | null + >(CUSTOMER_CASES_SITEMAP_QUERY); + if (cases !== null) { + siteMap.push( + ...cases.map((customerCase) => ({ + relativeUrl: `${customerCase.language}/${page.slug.current}/${customerCase.slug.current}`, + lastModified: new Date(customerCase._updatedAt), + })), + ); + } + return siteMap; + } + return []; +} + +async function legalDocumentsSitemap(): Promise { + const pages = await clientWithToken.fetch< + DocumentTranslatedSitemapData[] | null + >(LEGAL_DOCUMENTS_SITEMAP_QUERY); + if (pages !== null) { + return pages.map((page) => ({ + relativeUrl: `${page.language}/${page.slug.current}`, + lastModified: new Date(page._updatedAt), + })); + } + return []; +} + export default async function sitemap(): Promise { const baseUrlResult = readBaseUrl(); if (!baseUrlResult.ok) { @@ -21,21 +132,18 @@ export default async function sitemap(): Promise { return []; } const baseUrl = baseUrlResult.value; - const slugDocuments = await clientWithToken.fetch( - DOCUMENTS_WITH_SLUG_QUERY, - ); - const sitemapEntries = slugDocuments.map((slugDocument) => ({ - url: new URL(slugDocument.slug.current, baseUrl).toString(), - lastModified: new Date(slugDocument._updatedAt), - })); - const landingPage = await clientWithToken.fetch( - LANDING_PAGE_QUERY, - ); - if (landingPage !== null) { - sitemapEntries.push({ - url: baseUrl.toString(), - lastModified: new Date(landingPage._updatedAt), - }); - } - return sitemapEntries; + return ( + await Promise.all([ + landingPageSitemap(), + compensationsPageSitemap(), + dynamicPagesSitemap(), + customerCasesSitemap(), + legalDocumentsSitemap(), + ]) + ) + .flat() + .map(({ lastModified, relativeUrl }) => ({ + url: new URL(relativeUrl, baseUrl).toString(), + lastModified, + })); } diff --git a/src/components/compensations/CompensationsPreview.tsx b/src/components/compensations/CompensationsPreview.tsx index 865fe79ee..8da5f8ab6 100644 --- a/src/components/compensations/CompensationsPreview.tsx +++ b/src/components/compensations/CompensationsPreview.tsx @@ -8,7 +8,7 @@ import { CompensationsPage } from "studio/lib/interfaces/compensations"; import { LocaleDocument } from "studio/lib/interfaces/locale"; import { COMPANY_LOCATIONS_QUERY } from "studio/lib/queries/admin"; import { LOCALE_QUERY } from "studio/lib/queries/locale"; -import { COMPENSATIONS_PAGE_QUERY } from "studio/lib/queries/specialPages"; +import { COMPENSATIONS_PAGE_BY_SLUG_QUERY } from "studio/lib/queries/specialPages"; import Compensations from "./Compensations"; @@ -24,7 +24,7 @@ const CompensationsPreview = ({ initialLocale, }: CompensationsPreviewProps) => { const { data: compensationsData } = useQuery( - COMPENSATIONS_PAGE_QUERY, + COMPENSATIONS_PAGE_BY_SLUG_QUERY, { slug: initialCompensations.data.slug, language: initialCompensations.data.language, diff --git a/src/utils/pageData.ts b/src/utils/pageData.ts index d29653cef..f7c66825e 100644 --- a/src/utils/pageData.ts +++ b/src/utils/pageData.ts @@ -14,7 +14,7 @@ import { import { LOCALE_QUERY } from "studio/lib/queries/locale"; import { PAGE_BY_SLUG_QUERY } from "studio/lib/queries/pages"; import { - COMPENSATIONS_PAGE_QUERY, + COMPENSATIONS_PAGE_BY_SLUG_QUERY, CUSTOMER_CASES_PAGE_QUERY, } from "studio/lib/queries/specialPages"; import { loadStudioQuery } from "studio/lib/store"; @@ -89,7 +89,7 @@ async function fetchCompensationsPage({ }; const compensationsPageResult = await loadStudioQuery( - COMPENSATIONS_PAGE_QUERY, + COMPENSATIONS_PAGE_BY_SLUG_QUERY, queryParams, { perspective, @@ -115,7 +115,7 @@ async function fetchCompensationsPage({ return null; } return { - query: COMPENSATIONS_PAGE_QUERY, + query: COMPENSATIONS_PAGE_BY_SLUG_QUERY, queryParams, queryResponse: { compensationsPage: { diff --git a/studio/lib/interfaces/sitemap.ts b/studio/lib/interfaces/sitemap.ts new file mode 100644 index 000000000..231dab8e2 --- /dev/null +++ b/studio/lib/interfaces/sitemap.ts @@ -0,0 +1,17 @@ +import { InternationalizedString, Slug } from "./global"; + +export interface SitemapBaseData { + _updatedAt: string; +} + +export interface FieldTranslatedSitemapData extends SitemapBaseData { + slug: InternationalizedString; +} + +export interface UntranslatedSitemapData extends SitemapBaseData { + slug: Slug; +} + +export interface DocumentTranslatedSitemapData extends UntranslatedSitemapData { + language: string; +} diff --git a/studio/lib/queries/admin.ts b/studio/lib/queries/admin.ts index 6a6c363b9..e2b04d475 100644 --- a/studio/lib/queries/admin.ts +++ b/studio/lib/queries/admin.ts @@ -12,3 +12,11 @@ export const COMPANY_LOCATIONS_QUERY = groq`*[_type == "companyLocation"]`; export const LEGAL_DOCUMENTS_BY_LANG_QUERY = groq`*[_type == "legalDocument" && language == $language]`; export const LEGAL_DOCUMENT_BY_SLUG_AND_LANG_QUERY = groq`*[_type == "legalDocument" && language == $language && slug.current == $slug][0]`; + +export const LEGAL_DOCUMENTS_SITEMAP_QUERY = groq` + *[_type == "legalDocument"] { + _updatedAt, + language, + slug + } +`; diff --git a/studio/lib/queries/pages.ts b/studio/lib/queries/pages.ts index a2647771d..d5bde970b 100644 --- a/studio/lib/queries/pages.ts +++ b/studio/lib/queries/pages.ts @@ -59,6 +59,21 @@ export const PAGE_QUERY = groq` } `; +export const PAGES_SITEMAP_QUERY = groq` + *[_type == "pageBuilder"]{ + _updatedAt, + slug + } +`; + +export const PAGE_SEO_QUERY = groq` + *[_type == "pageBuilder" && _id == $id][0]{ + "title": seo.seoTitle, + "description": seo.seoDescription, + "imageUrl": seo.seoImage.asset->url + } +`; + export const PAGE_BY_SLUG_QUERY = groq` *[_type == "pageBuilder" && slug.current == $slug][0]{ ${PAGE_FRAGMENT} diff --git a/studio/lib/queries/siteSettings.ts b/studio/lib/queries/siteSettings.ts index a207f0cbf..94ea11edd 100644 --- a/studio/lib/queries/siteSettings.ts +++ b/studio/lib/queries/siteSettings.ts @@ -47,6 +47,12 @@ export const LANDING_PAGE_QUERY = groq` } `; +export const LANDING_PAGE_SITEMAP_QUERY = groq` + *[_type == "navigationManager"][0].setLanding -> { + _updatedAt + } +`; + //Social Media Profiles export const SOME_PROFILES_QUERY = groq` *[_type == "soMeLinksID" && _id == "soMeLinksID"][0] diff --git a/studio/lib/queries/specialPages.ts b/studio/lib/queries/specialPages.ts index 0a249f2ce..e58ec2d2d 100644 --- a/studio/lib/queries/specialPages.ts +++ b/studio/lib/queries/specialPages.ts @@ -3,7 +3,7 @@ import { groq } from "next-sanity"; import { translatedFieldFragment } from "./utils/i18n"; //Compensations -export const COMPENSATIONS_PAGE_QUERY = groq` +export const COMPENSATIONS_PAGE_BY_SLUG_QUERY = groq` *[_type == "compensations" && ${translatedFieldFragment("slug")} == $slug][0] { ..., "language": $language, @@ -25,7 +25,20 @@ export const COMPENSATIONS_PAGE_QUERY = groq` }, } `; +export const COMPENSATIONS_PAGE_SITEMAP_QUERY = groq` + *[_type == "compensations"][0] { + _updatedAt, + slug + } +`; //Customer Cases export const CUSTOMER_CASES_PAGE_QUERY = groq` *[_type == "customerCasesPage" && slug.current == $slug][0]`; + +export const CUSTOMER_CASES_PAGE_SITEMAP_QUERY = groq` + *[_type == "customerCasesPage"][0] { + _updatedAt, + slug + } +`; diff --git a/studioShared/lib/queries/customerCases.ts b/studioShared/lib/queries/customerCases.ts index 271ed9eb5..156a7a39c 100644 --- a/studioShared/lib/queries/customerCases.ts +++ b/studioShared/lib/queries/customerCases.ts @@ -4,3 +4,11 @@ export const CUSTOMER_CASES_QUERY = groq`*[_type == "customerCase" && language = `; export const CUSTOMER_CASE_QUERY = groq`*[_type == "customerCase" && slug.current == $slug && language == $language][0]`; + +export const CUSTOMER_CASES_SITEMAP_QUERY = groq` + *[_type == "customerCase"] { + _updatedAt, + language, + slug + } +`;