From b4fcb2f5a26e19199e4a9603c7f252a8913e8802 Mon Sep 17 00:00:00 2001 From: Mikael Brevik Date: Mon, 9 Dec 2024 20:29:37 +0100 Subject: [PATCH 1/3] refactor: clean up api fetching in contact box --- .../sections/contact-box/ContactBox.tsx | 42 +++----------- .../sections/contact-box/ContactSelector.tsx | 10 +--- src/components/sections/contact-box/api.ts | 57 +++++++++++++++++++ src/components/sections/contact-box/types.ts | 8 +++ studio/lib/interfaces/pages.ts | 1 + 5 files changed, 76 insertions(+), 42 deletions(-) create mode 100644 src/components/sections/contact-box/api.ts create mode 100644 src/components/sections/contact-box/types.ts diff --git a/src/components/sections/contact-box/ContactBox.tsx b/src/components/sections/contact-box/ContactBox.tsx index 57989e386..376f61089 100644 --- a/src/components/sections/contact-box/ContactBox.tsx +++ b/src/components/sections/contact-box/ContactBox.tsx @@ -2,14 +2,13 @@ import { Suspense } from "react"; import { EmployeeCardSkeleton } from "src/components/employeeCard/EmployeeCard"; import Text from "src/components/text/Text"; -import { ChewbaccaEmployee } from "src/types/employees"; -import { fetchEmployeesByEmails } from "src/utils/employees"; import { ContactBoxSection } from "studio/lib/interfaces/pages"; import { EMPLOYEE_PAGE_SLUG_QUERY } from "studio/lib/queries/siteSettings"; import { loadStudioQuery } from "studio/lib/store"; +import { fetchEmployeesWithTags, getEmployeesPageSlug } from "./api"; import styles from "./contact-box.module.css"; -import ContactSelector, { EmployeeAndTag } from "./ContactSelector"; +import ContactSelector from "./ContactSelector"; export interface ContactBoxProps { section: ContactBoxSection; @@ -20,21 +19,13 @@ export default async function ContactBox({ section, language, }: ContactBoxProps) { - const employeesPageRes = await loadStudioQuery<{ slug: string }>( - EMPLOYEE_PAGE_SLUG_QUERY, - { - language, - }, - ); - const employeesPageSlug = employeesPageRes.data.slug; + const employeesPageSlug = await getEmployeesPageSlug(language); - const contactPoints = fetchEmployeesByEmails( - section.contactPoints.map((contactPoint) => contactPoint.email), - ).then((result) => - result.ok - ? result.value.map((e) => employeeAndTag(e, section.contactPoints)) - : [], - ); + if (!employeesPageSlug) { + return null; + } + + const contactPoints = fetchEmployeesWithTags(section.contactPoints); const backgroundClass = section.background === "light" ? styles["contactBox__inner--light"] : ""; @@ -68,20 +59,3 @@ export default async function ContactBox({ ); } - -function employeeAndTag( - employee: ChewbaccaEmployee, - contactPoints: ContactBoxSection["contactPoints"], -): EmployeeAndTag { - const tag = - contactPoints.find((contactPoint) => contactPoint.email === employee.email) - ?.tag ?? ""; - return { - employee, - tag, - tagSlug: slugify(tag), - }; -} -function slugify(tag: string) { - return tag.toLowerCase().replace(/ /g, "-"); -} diff --git a/src/components/sections/contact-box/ContactSelector.tsx b/src/components/sections/contact-box/ContactSelector.tsx index 01e988a7f..9b431bfa4 100644 --- a/src/components/sections/contact-box/ContactSelector.tsx +++ b/src/components/sections/contact-box/ContactSelector.tsx @@ -4,18 +4,12 @@ import { use, useState } from "react"; import EmployeeCard from "src/components/employeeCard/EmployeeCard"; import { Tag } from "src/components/tag"; -import { ChewbaccaEmployee } from "src/types/employees"; import styles from "./contact-box.module.css"; - -export type EmployeeAndTag = { - employee: ChewbaccaEmployee; - tag: string; - tagSlug: string; -}; +import { EmployeeAndMetadata } from "./types"; export type ContactSelectorProps = { - contactPoints: Promise; + contactPoints: Promise; employeesPageSlug: string; language: string; background?: "dark" | "light"; diff --git a/src/components/sections/contact-box/api.ts b/src/components/sections/contact-box/api.ts new file mode 100644 index 000000000..ebbb69ef9 --- /dev/null +++ b/src/components/sections/contact-box/api.ts @@ -0,0 +1,57 @@ +import { ChewbaccaEmployee } from "src/types/employees"; +import { fetchEmployeesByEmails } from "src/utils/employees"; +import { ContactBoxSection } from "studio/lib/interfaces/pages"; +import { EmployeeAndMetadata } from "./types"; +import { loadStudioQuery } from "studio/lib/store"; +import { EMPLOYEE_PAGE_SLUG_QUERY } from "studio/lib/queries/siteSettings"; + +export async function getEmployeesPageSlug( + language: string, +): Promise { + const employeesPageRes = await loadStudioQuery<{ slug: string }>( + EMPLOYEE_PAGE_SLUG_QUERY, + { + language, + }, + { + cache: "force-cache", + next: { + // Cache for 1 day.. Not likely to change (or is it???) + revalidate: 60 * 60 * 24, + }, + }, + ); + + return employeesPageRes.data?.slug; +} + +export async function fetchEmployeesWithTags( + contactPoints: ContactBoxSection["contactPoints"], +) { + const contacts = fetchEmployeesByEmails( + contactPoints.map((contactPoint) => contactPoint.email), + ).then((result) => + result.ok + ? result.value.map((e) => employeeAndMetadata(e, contactPoints)) + : [], + ); + return contacts; +} + +function employeeAndMetadata( + employee: ChewbaccaEmployee, + contactPoints: ContactBoxSection["contactPoints"], +): EmployeeAndMetadata { + const metadata = contactPoints.find( + (contactPoint) => contactPoint.email === employee.email, + ); + return { + employee, + tag: metadata?.tag ?? "", + tagSlug: slugify(metadata?.tag ?? ""), + overrideTitle: metadata?.overrideTitle ?? "", + }; +} +function slugify(tag: string) { + return tag.toLowerCase().replace(/ /g, "-"); +} diff --git a/src/components/sections/contact-box/types.ts b/src/components/sections/contact-box/types.ts new file mode 100644 index 000000000..bf454fc68 --- /dev/null +++ b/src/components/sections/contact-box/types.ts @@ -0,0 +1,8 @@ +import { ChewbaccaEmployee } from "src/types/employees"; + +export type EmployeeAndMetadata = { + employee: ChewbaccaEmployee; + tag: string; + tagSlug: string; + overrideTitle: string; +}; diff --git a/studio/lib/interfaces/pages.ts b/studio/lib/interfaces/pages.ts index f42b81e66..5c08a1420 100644 --- a/studio/lib/interfaces/pages.ts +++ b/studio/lib/interfaces/pages.ts @@ -106,6 +106,7 @@ export interface ContactBoxSection { _key: string; _type: string; tag: string; + overrideTitle?: string; email: string; }[]; } From 2bfff89018b15d1a4a22f855803aada26072f059 Mon Sep 17 00:00:00 2001 From: Mikael Brevik Date: Mon, 9 Dec 2024 20:36:10 +0100 Subject: [PATCH 2/3] fix: adds optional title for contact box --- src/components/employeeCard/EmployeeCard.tsx | 26 ++++++++++++------- .../sections/contact-box/ContactBox.tsx | 2 -- .../sections/contact-box/ContactSelector.tsx | 1 + src/components/sections/contact-box/api.ts | 5 ++-- studio/lib/queries/pages.ts | 6 ++++- .../schemas/objects/sections/contact-box.ts | 7 +++++ 6 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/components/employeeCard/EmployeeCard.tsx b/src/components/employeeCard/EmployeeCard.tsx index f380657a9..0573f789e 100644 --- a/src/components/employeeCard/EmployeeCard.tsx +++ b/src/components/employeeCard/EmployeeCard.tsx @@ -13,12 +13,14 @@ export interface EmployeeCardProps { employee: ChewbaccaEmployee; employeePageSlug?: string; language: string; + overrideTitle?: string; } export default function EmployeeCard({ employee, employeePageSlug, language, + overrideTitle, }: EmployeeCardProps) { const t = useTranslations("employee_card"); return ( @@ -51,16 +53,22 @@ export default function EmployeeCard({
- {employee.competences.map((competence) => ( - - {t(competence)} + {overrideTitle ? ( + + {overrideTitle} - ))} + ) : ( + employee.competences.map((competence) => ( + + {t(competence)} + + )) + )}
diff --git a/src/components/sections/contact-box/ContactBox.tsx b/src/components/sections/contact-box/ContactBox.tsx index 376f61089..bb08c98e1 100644 --- a/src/components/sections/contact-box/ContactBox.tsx +++ b/src/components/sections/contact-box/ContactBox.tsx @@ -3,8 +3,6 @@ import { Suspense } from "react"; import { EmployeeCardSkeleton } from "src/components/employeeCard/EmployeeCard"; import Text from "src/components/text/Text"; import { ContactBoxSection } from "studio/lib/interfaces/pages"; -import { EMPLOYEE_PAGE_SLUG_QUERY } from "studio/lib/queries/siteSettings"; -import { loadStudioQuery } from "studio/lib/store"; import { fetchEmployeesWithTags, getEmployeesPageSlug } from "./api"; import styles from "./contact-box.module.css"; diff --git a/src/components/sections/contact-box/ContactSelector.tsx b/src/components/sections/contact-box/ContactSelector.tsx index 9b431bfa4..5bdb25905 100644 --- a/src/components/sections/contact-box/ContactSelector.tsx +++ b/src/components/sections/contact-box/ContactSelector.tsx @@ -62,6 +62,7 @@ export default function ContactSelector({ employee={contactPoint.employee} employeePageSlug={employeesPageSlug} language={language} + overrideTitle={contactPoint.overrideTitle} /> ))} diff --git a/src/components/sections/contact-box/api.ts b/src/components/sections/contact-box/api.ts index ebbb69ef9..b7da795f0 100644 --- a/src/components/sections/contact-box/api.ts +++ b/src/components/sections/contact-box/api.ts @@ -1,9 +1,10 @@ import { ChewbaccaEmployee } from "src/types/employees"; import { fetchEmployeesByEmails } from "src/utils/employees"; import { ContactBoxSection } from "studio/lib/interfaces/pages"; -import { EmployeeAndMetadata } from "./types"; -import { loadStudioQuery } from "studio/lib/store"; import { EMPLOYEE_PAGE_SLUG_QUERY } from "studio/lib/queries/siteSettings"; +import { loadStudioQuery } from "studio/lib/store"; + +import { EmployeeAndMetadata } from "./types"; export async function getEmployeesPageSlug( language: string, diff --git a/studio/lib/queries/pages.ts b/studio/lib/queries/pages.ts index 7b05dc448..cdb02762c 100644 --- a/studio/lib/queries/pages.ts +++ b/studio/lib/queries/pages.ts @@ -74,7 +74,11 @@ const SECTIONS_FRAGMENT = groq` }, _type == "contactBox" => { "basicTitle": ${translatedFieldFragment("basicTitle")}, - "optionalSubtitle": ${translatedFieldFragment("optionalSubtitle")} + "optionalSubtitle": ${translatedFieldFragment("optionalSubtitle")}, + "contactPoints": contactPoints[] { + ..., + "overrideTitle": ${translatedFieldFragment("overrideTitle")} + } }, _type == "jobs" => { "basicTitle": ${translatedFieldFragment("basicTitle")}, diff --git a/studio/schemas/objects/sections/contact-box.ts b/studio/schemas/objects/sections/contact-box.ts index 0cfcd1771..12035fbdf 100644 --- a/studio/schemas/objects/sections/contact-box.ts +++ b/studio/schemas/objects/sections/contact-box.ts @@ -67,6 +67,13 @@ export const contactBox = defineField({ StringInputWithCharacterCount({ ...props, maxCount: 30 }), }, }), + defineField({ + name: "overrideTitle", + title: "Override title", + type: "internationalizedArrayString", + description: + "Specify a title for the contact point. If left empty, the employee's default title will be used.", + }), defineField({ name: "email", title: "Enter the email address for contact point", From 85af1d6c94c17d6b2bc6d9f00390356d164bb141 Mon Sep 17 00:00:00 2001 From: Mikael Brevik Date: Mon, 9 Dec 2024 20:44:34 +0100 Subject: [PATCH 3/3] fix: overflow for contact box --- src/components/employeeCard/employeeCard.module.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/employeeCard/employeeCard.module.css b/src/components/employeeCard/employeeCard.module.css index a068f41e1..ab5b04a37 100644 --- a/src/components/employeeCard/employeeCard.module.css +++ b/src/components/employeeCard/employeeCard.module.css @@ -9,6 +9,8 @@ flex-direction: column; justify-content: space-between; gap: 0.375rem; + + overflow: hidden; } .contactInfo { @@ -27,6 +29,12 @@ .employeePhone a { color: currentColor; } +.employeeEmail a { + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} .employeeWrapper { container-type: inline-size;