From ba9658f254b4c1f2362438c42d2778fe260daa13 Mon Sep 17 00:00:00 2001 From: Mathias Oterhals Myklebust <24361490+mathiazom@users.noreply.github.com> Date: Wed, 30 Oct 2024 10:18:02 +0000 Subject: [PATCH] v3 - consultants in project (#831) * fix(CustomerCase): overflowing content width * feat(CustomerCase): project consultants section * feat(CustomerCase): add usage note to consultants field in project info * feat(CustomerCase): fetch employees by email instead of alias since we don't know if aliases are unique across countries * feat(CustomerCase): use email type for project consultant identifiers * refactor(CustomerCase): extract consultants section to own component * feat(CustomerCaseConsultants): add employee link to customer case consultant card * feat(CustomerCase): remove nowrap for project info --- .../customerCase/CustomerCase.tsx | 18 +++- .../customerCase/customerCase.module.css | 2 +- .../CustomerCaseConsultants.tsx | 95 +++++++++++++++++++ .../customerCaseConsulants.module.css | 60 ++++++++++++ src/components/link/CustomLink.tsx | 14 ++- src/components/link/link.module.css | 21 ++++ src/types/employees.ts | 2 + src/utils/employees.ts | 17 ++++ .../schemas/fields/customerCaseProjectInfo.ts | 5 +- 9 files changed, 226 insertions(+), 8 deletions(-) create mode 100644 src/components/customerCases/customerCase/sections/customerCaseConsultants/CustomerCaseConsultants.tsx create mode 100644 src/components/customerCases/customerCase/sections/customerCaseConsultants/customerCaseConsulants.module.css diff --git a/src/components/customerCases/customerCase/CustomerCase.tsx b/src/components/customerCases/customerCase/CustomerCase.tsx index 0aac97cf5..729afb24e 100644 --- a/src/components/customerCases/customerCase/CustomerCase.tsx +++ b/src/components/customerCases/customerCase/CustomerCase.tsx @@ -1,5 +1,6 @@ import { SanitySharedImage } from "src/components/image/SanityImage"; import Text from "src/components/text/Text"; +import { fetchEmployeesByEmails } from "src/utils/employees"; import { CustomerCase as CustomerCaseDocument, CustomerCaseSection as CustomerCaseSectionObject, @@ -8,6 +9,7 @@ import { import styles from "./customerCase.module.css"; import FeaturedCases from "./featuredCases/FeaturedCases"; +import CustomerCaseConsultants from "./sections/customerCaseConsultants/CustomerCaseConsultants"; import ImageSection from "./sections/image/ImageSection"; import RichTextSection from "./sections/richText/RichTextSection"; @@ -38,10 +40,14 @@ export interface CustomerCaseProps { customerCasesPagePath: string[]; } -export default function CustomerCase({ +export default async function CustomerCase({ customerCase, customerCasesPagePath, }: CustomerCaseProps) { + const consultantsResult = await fetchEmployeesByEmails( + customerCase.projectInfo.consultants, + ); + return (
@@ -116,14 +122,14 @@ export default function CustomerCase({ )}
)} - {customerCase.projectInfo.consultants && ( + {consultantsResult.ok && (
Konsulenter - {customerCase.projectInfo.consultants.join(", ")} + {consultantsResult.value.map((c) => c.name).join(", ")}
)} @@ -134,6 +140,12 @@ export default function CustomerCase({ ))}
+ {consultantsResult.ok && ( + + )} {customerCase.featuredCases && customerCase.featuredCases.length > 0 && ( ( + EMPLOYEE_PAGE_SLUG_QUERY, + { + language, + }, + ); + const employeePageSlug = employeePageSlugRes.data?.slug; + + return ( +
+ Varianter på prosjektet +
+ {consultants.map((consultant) => { + const title = ( +

{consultant.name}

+ ); + return ( + consultant.imageThumbUrl && + consultant.name && + consultant.email && ( +
+
+ {consultant.name} +
+
+ {employeePageSlug !== undefined ? ( + + {title} + + ) : ( + title + )} + {consultant.officeName && ( +

+ {consultant.officeName} +

+ )} + {consultant.email && ( +

{consultant.email}

+ )} + {consultant.telephone && ( +

+ {consultant.telephone} +

+ )} + +
+
+ ) + ); + })} +
+
+ ); +} diff --git a/src/components/customerCases/customerCase/sections/customerCaseConsultants/customerCaseConsulants.module.css b/src/components/customerCases/customerCase/sections/customerCaseConsultants/customerCaseConsulants.module.css new file mode 100644 index 000000000..09d000704 --- /dev/null +++ b/src/components/customerCases/customerCase/sections/customerCaseConsultants/customerCaseConsulants.module.css @@ -0,0 +1,60 @@ +.wrapper { + display: flex; + flex-direction: column; + gap: 2rem; + margin: 4rem 0; +} + +.content { + width: 100%; + text-wrap: wrap; + column-gap: 12px; + row-gap: 52px; + display: grid; + grid-template-columns: repeat(auto-fit, 350px); + justify-content: space-between; +} + +.consultant { + display: flex; + width: 100%; + gap: 1rem; +} + +.consultantImage { + display: flex; + flex-direction: column; + align-items: center; + background-color: var(--primary-black); + border-radius: 12px; + height: 125px; + width: 50%; + padding: 1rem; + position: relative; +} + +.consultantInfo { + display: flex; + flex-direction: column; + width: 50%; + gap: 0.5rem; +} + +.consultantName { + color: var(--primary-black); + font-size: 16px; + font-weight: 600; +} + +.consultantRole { + color: var(--primary-black); + font-size: 16px; + font-weight: 300; +} + +.consultantEmail, +.consultantTelephone { + color: var(--primary-black); + font-size: 14px; + font-weight: 300; +} diff --git a/src/components/link/CustomLink.tsx b/src/components/link/CustomLink.tsx index e357caab8..143805384 100644 --- a/src/components/link/CustomLink.tsx +++ b/src/components/link/CustomLink.tsx @@ -12,9 +12,15 @@ interface ICustomLink { type?: ComponentLinkType; link: ILink; isSelected?: boolean; + size?: "normal" | "small"; } -const CustomLink = ({ type = "link", link, isSelected }: ICustomLink) => { +const CustomLink = ({ + type = "link", + link, + isSelected, + size = "normal", +}: ICustomLink) => { const href = getHref(link); const newTab = link.newTab; const target = newTab ? "_blank" : undefined; @@ -27,7 +33,11 @@ const CustomLink = ({ type = "link", link, isSelected }: ICustomLink) => { return ( link.linkTitle && (type === "link" ? ( -
+
> { + const allEmployeesRes = await fetchAllChewbaccaEmployees(); + if (!allEmployeesRes.ok) { + return allEmployeesRes; + } + return ResultOk( + // mapping from input array (instead of filtering all employees) to preserve order + emails + .map((email) => + allEmployeesRes.value.find((employee) => employee.email === email), + ) + .filter((employee) => employee !== undefined), + ); +} diff --git a/studioShared/schemas/fields/customerCaseProjectInfo.ts b/studioShared/schemas/fields/customerCaseProjectInfo.ts index a9cfaf539..709c83746 100644 --- a/studioShared/schemas/fields/customerCaseProjectInfo.ts +++ b/studioShared/schemas/fields/customerCaseProjectInfo.ts @@ -68,9 +68,10 @@ export const customerCaseProjectInfo = defineField({ defineField({ // TODO: We should be able to select the consultants from a list name: "consultants", - description: "The consultants for the project", + description: + "The consultants for the project. Use employee emails (e.g. 'oms@variant.no').", type: "array", - of: [{ type: "string" }], + of: [{ type: "email" }], }), ], });