From a2ad733696a598ad53945a8af9d1896c0848d7f7 Mon Sep 17 00:00:00 2001 From: Mathias Oterhals Myklebust Date: Thu, 31 Oct 2024 14:54:26 +0100 Subject: [PATCH] feat(CustomerCase): sales contact information --- src/components/buttons/Button.tsx | 3 +- src/components/buttons/button.module.css | 14 +++ .../consultantCard/ConsultantCard.tsx | 74 ++++++++++++++ .../consultantCard/consultantCard.module.css | 43 ++++++++ .../customerCase/CustomerCase.tsx | 2 +- .../contactInformation/ContactInformation.tsx | 98 ++++++++++++------- .../contactInformation.module.css | 27 +++-- .../contactSelector/ContactSelector.tsx | 68 +++++++++++++ .../contactSelector.module.css | 9 ++ .../CustomerCaseConsultants.tsx | 72 ++------------ .../customerCaseConsulants.module.css | 44 --------- src/styles/global.css | 1 + studio/lib/interfaces/companyDetails.ts | 1 + .../documents/admin/companyLocation.ts | 2 +- 14 files changed, 304 insertions(+), 154 deletions(-) create mode 100644 src/components/consultantCard/ConsultantCard.tsx create mode 100644 src/components/consultantCard/consultantCard.module.css create mode 100644 src/components/customerCases/customerCase/contactInformation/contactSelector/ContactSelector.tsx create mode 100644 src/components/customerCases/customerCase/contactInformation/contactSelector/contactSelector.module.css diff --git a/src/components/buttons/Button.tsx b/src/components/buttons/Button.tsx index 094f49e76..1a0b77f68 100644 --- a/src/components/buttons/Button.tsx +++ b/src/components/buttons/Button.tsx @@ -2,7 +2,7 @@ import React from "react"; import styles from "./button.module.css"; -type ButtonType = "primary" | "secondary"; +type ButtonType = "primary" | "secondary" | "secondaryFilled"; type ButtonSize = "large" | "small" | "extraSmall"; interface IButton { @@ -24,6 +24,7 @@ const sizeClassMap: { [key in ButtonSize]: string } = { const typeClassMap: { [key in ButtonType]: string } = { primary: styles.primary, secondary: styles.secondary, + secondaryFilled: styles.secondaryFilled, }; const Button = ({ diff --git a/src/components/buttons/button.module.css b/src/components/buttons/button.module.css index 48e692b96..8ff950baf 100644 --- a/src/components/buttons/button.module.css +++ b/src/components/buttons/button.module.css @@ -76,6 +76,20 @@ } } +.secondaryFilled { + background: var(--primary-black); + color: var(--primary-white); + border: 1px solid var(--primary-black); + + &:hover { + background: var(--primary-black-darker); + } + + &:active { + background: var(--primary-black-darker); + } +} + .back { composes: secondary; diff --git a/src/components/consultantCard/ConsultantCard.tsx b/src/components/consultantCard/ConsultantCard.tsx new file mode 100644 index 000000000..046cde83a --- /dev/null +++ b/src/components/consultantCard/ConsultantCard.tsx @@ -0,0 +1,74 @@ +import Image from "next/image"; +import Link from "next/link"; + +import CustomLink from "src/components/link/CustomLink"; +import { ChewbaccaEmployee } from "src/types/employees"; +import { aliasFromEmail } from "src/utils/employees"; +import { LinkType } from "studio/lib/interfaces/navigation"; + +import styles from "./consultantCard.module.css"; + +export interface ConsultantCardProps { + currentLanguage: string; + consultant: ChewbaccaEmployee; + employeePageSlug?: string; +} + +export default function ConsultantCard({ + currentLanguage, + consultant, + employeePageSlug, +}: ConsultantCardProps) { + 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}

+ )} + {employeePageSlug && ( + + )} +
+
+ ) + ); +} diff --git a/src/components/consultantCard/consultantCard.module.css b/src/components/consultantCard/consultantCard.module.css new file mode 100644 index 000000000..b9df285ca --- /dev/null +++ b/src/components/consultantCard/consultantCard.module.css @@ -0,0 +1,43 @@ +.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/customerCases/customerCase/CustomerCase.tsx b/src/components/customerCases/customerCase/CustomerCase.tsx index 46f98a7ae..7e55c09d2 100644 --- a/src/components/customerCases/customerCase/CustomerCase.tsx +++ b/src/components/customerCases/customerCase/CustomerCase.tsx @@ -130,7 +130,7 @@ export default async function CustomerCase({ customerCasesPath={customerCasesPagePath} /> )} - {} + ); diff --git a/src/components/customerCases/customerCase/contactInformation/ContactInformation.tsx b/src/components/customerCases/customerCase/contactInformation/ContactInformation.tsx index c18e74521..71651ad57 100644 --- a/src/components/customerCases/customerCase/contactInformation/ContactInformation.tsx +++ b/src/components/customerCases/customerCase/contactInformation/ContactInformation.tsx @@ -1,53 +1,75 @@ -import Button from "src/components/buttons/Button"; -import CustomerCaseConsultants from "src/components/customerCases/customerCase/sections/customerCaseConsultants/CustomerCaseConsultants"; import Text from "src/components/text/Text"; -import { getDraftModeInfo } from "src/utils/draftmode"; import { fetchEmployeesByEmails } from "src/utils/employees"; import { CompanyLocation } from "studio/lib/interfaces/companyDetails"; import { COMPANY_LOCATIONS_QUERY } from "studio/lib/queries/admin"; +import { EMPLOYEE_PAGE_SLUG_QUERY } from "studio/lib/queries/siteSettings"; import { loadStudioQuery } from "studio/lib/store"; import styles from "./contactInformation.module.css"; +import ContactSelector, { + ContactByLocationMap, +} from "./contactSelector/ContactSelector"; -//TODO: Create SanityField type for Sales Contact in location schema use it to fetch employee data from chewbacca. -const consultantsResult = await fetchEmployeesByEmails(["amn@variant.no"]); +interface ContactInformationProps { + language: string; +} -const ContactInformation = async () => { - const { perspective } = getDraftModeInfo(); +async function fetchContactByLocationMap( + companyLocations: CompanyLocation[], +): Promise { + const contactByLocation: ContactByLocationMap = {}; + for (const location of companyLocations) { + if ( + location.contactPerson === undefined || + location.contactPerson.length === 0 + ) { + continue; + } + const contactRes = await fetchEmployeesByEmails([location.contactPerson]); + if (!contactRes.ok || contactRes.value.length === 0) { + continue; + } + contactByLocation[location._id] = contactRes.value[0]; + } + return contactByLocation; +} - const [companyLocations] = await Promise.all([ - loadStudioQuery( - COMPANY_LOCATIONS_QUERY, - {}, - { perspective }, - ), - ]); +export default async function ContactInformation({ + language, +}: ContactInformationProps) { + const employeePageSlug = ( + await loadStudioQuery<{ slug: string } | null>(EMPLOYEE_PAGE_SLUG_QUERY, { + language, + }) + ).data?.slug; + const companyLocations = ( + await loadStudioQuery(COMPANY_LOCATIONS_QUERY, {}) + ).data; + const contactByLocation = await fetchContactByLocationMap(companyLocations); + const locationIdsWithContact = Object.keys(contactByLocation); + const locationsWithContact = companyLocations.filter((location) => + locationIdsWithContact.includes(location._id), + ); return ( -
-
- {/* TODO: translation */} - - Trenger du hjelp med lignende eller noe helt annet? - - Kontakt salg! -
-
- {/* TODO: add logic for location buttons */} - {companyLocations && - companyLocations.data.map((location) => ( - - ))} +
+
+
+ {/* TODO: translation */} + + Trenger du hjelp med lignende eller noe helt annet? + + Kontakt salg! +
+
+ +
- {consultantsResult.ok && ( - - )}
); -}; -export default ContactInformation; +} diff --git a/src/components/customerCases/customerCase/contactInformation/contactInformation.module.css b/src/components/customerCases/customerCase/contactInformation/contactInformation.module.css index cccd8e441..e86f6bf9c 100644 --- a/src/components/customerCases/customerCase/contactInformation/contactInformation.module.css +++ b/src/components/customerCases/customerCase/contactInformation/contactInformation.module.css @@ -1,17 +1,32 @@ -.container { +.wrapper { + display: flex; + flex-direction: column; + margin: 4rem 0; + + @media (min-width: 1024px) { + align-items: center; + } +} + +.content { display: flex; flex-direction: row; - gap: 3rem; - padding: 0 12.5rem; + gap: 1rem; + max-width: 960px; + + @media (max-width: 1024px) { + flex-direction: column; + gap: 2rem; + } } .titleSection { display: flex; flex-direction: column; + gap: 0.75rem; } -.locationSection { +.contactSection { display: flex; - flex-direction: column; - gap: 0.75rem; + gap: 1.5rem; } diff --git a/src/components/customerCases/customerCase/contactInformation/contactSelector/ContactSelector.tsx b/src/components/customerCases/customerCase/contactInformation/contactSelector/ContactSelector.tsx new file mode 100644 index 000000000..479bb362e --- /dev/null +++ b/src/components/customerCases/customerCase/contactInformation/contactSelector/ContactSelector.tsx @@ -0,0 +1,68 @@ +"use client"; + +import { useState } from "react"; + +import Button from "src/components/buttons/Button"; +import ConsultantCard from "src/components/consultantCard/ConsultantCard"; +import { ChewbaccaEmployee } from "src/types/employees"; +import { CompanyLocation } from "studio/lib/interfaces/companyDetails"; + +import styles from "./contactSelector.module.css"; + +export type ContactByLocationMap = { + [locationId: string]: ChewbaccaEmployee; +}; + +export interface ContactSelectorProps { + language: string; + locations: CompanyLocation[]; + contactByLocation: ContactByLocationMap; + employeePageSlug?: string; +} + +export default function ContactSelector({ + language, + locations, + contactByLocation, + employeePageSlug, +}: ContactSelectorProps) { + const locationIds = Object.keys(contactByLocation); + + const [selectedLocationId, setSelectedLocationId] = useState( + locationIds.length === 0 ? locationIds[0] : null, + ); + + if (locationIds.length === 0) { + return; + } + + const selectedOrDefaultLocationId = selectedLocationId ?? locationIds[0]; + + return ( + <> +
+ {locations.map((location) => ( + + ))} +
+
+ +
+ + ); +} diff --git a/src/components/customerCases/customerCase/contactInformation/contactSelector/contactSelector.module.css b/src/components/customerCases/customerCase/contactInformation/contactSelector/contactSelector.module.css new file mode 100644 index 000000000..e0f2ce2ef --- /dev/null +++ b/src/components/customerCases/customerCase/contactInformation/contactSelector/contactSelector.module.css @@ -0,0 +1,9 @@ +.locationSection { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.consultantSection { + min-width: 400px; +} diff --git a/src/components/customerCases/customerCase/sections/customerCaseConsultants/CustomerCaseConsultants.tsx b/src/components/customerCases/customerCase/sections/customerCaseConsultants/CustomerCaseConsultants.tsx index 385872e7d..ed91f8204 100644 --- a/src/components/customerCases/customerCase/sections/customerCaseConsultants/CustomerCaseConsultants.tsx +++ b/src/components/customerCases/customerCase/sections/customerCaseConsultants/CustomerCaseConsultants.tsx @@ -1,11 +1,6 @@ -import Image from "next/image"; -import Link from "next/link"; - -import CustomLink from "src/components/link/CustomLink"; +import ConsultantCard from "src/components/consultantCard/ConsultantCard"; import Text from "src/components/text/Text"; import { ChewbaccaEmployee } from "src/types/employees"; -import { aliasFromEmail } from "src/utils/employees"; -import { LinkType } from "studio/lib/interfaces/navigation"; import { EMPLOYEE_PAGE_SLUG_QUERY } from "studio/lib/queries/siteSettings"; import { loadStudioQuery } from "studio/lib/store"; @@ -32,63 +27,14 @@ export default async function CustomerCaseConsultants({
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} -

- )} - -
-
- ) - ); - })} + {consultants.map((consultant) => ( + + ))}
); diff --git a/src/components/customerCases/customerCase/sections/customerCaseConsultants/customerCaseConsulants.module.css b/src/components/customerCases/customerCase/sections/customerCaseConsultants/customerCaseConsulants.module.css index 09d000704..0745727f4 100644 --- a/src/components/customerCases/customerCase/sections/customerCaseConsultants/customerCaseConsulants.module.css +++ b/src/components/customerCases/customerCase/sections/customerCaseConsultants/customerCaseConsulants.module.css @@ -14,47 +14,3 @@ 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/styles/global.css b/src/styles/global.css index d20a2e753..e266074ff 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -18,6 +18,7 @@ html { --primary-white-bright: #ffffff; --primary-white: #faf8f5; --primary-black: #2d2d2d; + --primary-black-darker: #000000; --secondary-off-white1: #f4efe8; --secondary-off-white2: #ece1d3; diff --git a/studio/lib/interfaces/companyDetails.ts b/studio/lib/interfaces/companyDetails.ts index 81dec6502..5cd64b12c 100644 --- a/studio/lib/interfaces/companyDetails.ts +++ b/studio/lib/interfaces/companyDetails.ts @@ -10,4 +10,5 @@ export interface CompanyLocation { _id: string; _updatedAt: string; companyLocationName: string; + contactPerson?: string; } diff --git a/studio/schemas/documents/admin/companyLocation.ts b/studio/schemas/documents/admin/companyLocation.ts index 0d87dee31..04ee26a6b 100644 --- a/studio/schemas/documents/admin/companyLocation.ts +++ b/studio/schemas/documents/admin/companyLocation.ts @@ -24,7 +24,7 @@ const companyLocation = defineType({ }), defineField({ name: companyLocationContactPersonID, - type: "string", + type: "email", title: "Contact person for Sales", description: "Add the email of the contact person for Sales", }),