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 && (
+
+
+
+
+
+ {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" }],
}),
],
});