Skip to content

Commit

Permalink
feat(CustomerCase): sales contact information
Browse files Browse the repository at this point in the history
  • Loading branch information
mathiazom committed Oct 31, 2024
1 parent 19be082 commit a2ad733
Show file tree
Hide file tree
Showing 14 changed files with 304 additions and 154 deletions.
3 changes: 2 additions & 1 deletion src/components/buttons/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 = ({
Expand Down
14 changes: 14 additions & 0 deletions src/components/buttons/button.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
74 changes: 74 additions & 0 deletions src/components/consultantCard/ConsultantCard.tsx
Original file line number Diff line number Diff line change
@@ -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 = <p className={styles.consultantName}>{consultant.name}</p>;
return (
consultant.imageThumbUrl &&
consultant.name &&
consultant.email && (
<div key={consultant.email} className={styles.consultant}>
<div className={styles.consultantImage}>
<Image
src={consultant.imageUrl ?? consultant.imageThumbUrl}
alt={consultant.name}
objectFit="cover"
fill={true}
/>
</div>
<div className={styles.consultantInfo}>
{employeePageSlug !== undefined ? (
<Link
href={`/${currentLanguage}/${employeePageSlug}/${aliasFromEmail(consultant.email)}`}
>
{title}
</Link>
) : (
title
)}
{consultant.officeName && (
<p className={styles.consultantRole}>{consultant.officeName}</p>
)}
{consultant.email && (
<p className={styles.consultantEmail}>{consultant.email}</p>
)}
{consultant.telephone && (
<p className={styles.consultantTelephone}>{consultant.telephone}</p>
)}
{employeePageSlug && (
<CustomLink
size={"small"}
link={{
_key: "go-to-mini-cv",
_type: "link",
linkType: LinkType.Internal,
linkTitle: "Gå til Mini-CV", // TODO: translate
language: currentLanguage,
internalLink: {
_ref: `${employeePageSlug}/${aliasFromEmail(consultant.email)}`,
},
}}
/>
)}
</div>
</div>
)
);
}
43 changes: 43 additions & 0 deletions src/components/consultantCard/consultantCard.module.css
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 1 addition & 1 deletion src/components/customerCases/customerCase/CustomerCase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export default async function CustomerCase({
customerCasesPath={customerCasesPagePath}
/>
)}
{<ContactInformation />}
<ContactInformation language={customerCase.language} />
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -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(["[email protected]"]);
interface ContactInformationProps {
language: string;
}

const ContactInformation = async () => {
const { perspective } = getDraftModeInfo();
async function fetchContactByLocationMap(
companyLocations: CompanyLocation[],
): Promise<ContactByLocationMap> {
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<CompanyLocation[]>(
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<CompanyLocation[]>(COMPANY_LOCATIONS_QUERY, {})
).data;
const contactByLocation = await fetchContactByLocationMap(companyLocations);
const locationIdsWithContact = Object.keys(contactByLocation);
const locationsWithContact = companyLocations.filter((location) =>
locationIdsWithContact.includes(location._id),
);

return (
<div className={styles.container}>
<div className={styles.titleSection}>
{/* TODO: translation */}
<Text type={"h3"}>
Trenger du hjelp med lignende eller noe helt annet?
</Text>
<Text type="bodyBig"> Kontakt salg! </Text>
</div>
<div className={styles.locationSection}>
{/* TODO: add logic for location buttons */}
{companyLocations &&
companyLocations.data.map((location) => (
<Button type="secondary" key={location._id}>
{location.companyLocationName}
</Button>
))}
<div className={styles.wrapper}>
<div className={styles.content}>
<div className={styles.titleSection}>
{/* TODO: translation */}
<Text type={"bodyXl"}>
Trenger du hjelp med lignende eller noe helt annet?
</Text>
<Text type="bodyBig"> Kontakt salg! </Text>
</div>
<div className={styles.contactSection}>
<ContactSelector
language={language}
locations={locationsWithContact}
contactByLocation={contactByLocation}
employeePageSlug={employeePageSlug}
/>
</div>
</div>
{consultantsResult.ok && (
<CustomerCaseConsultants
language={"no"}
consultants={consultantsResult.value}
/>
)}
</div>
);
};
export default ContactInformation;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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<string | null>(
locationIds.length === 0 ? locationIds[0] : null,
);

if (locationIds.length === 0) {
return;
}

const selectedOrDefaultLocationId = selectedLocationId ?? locationIds[0];

return (
<>
<div className={styles.locationSection}>
{locations.map((location) => (
<Button
type={
location._id === selectedOrDefaultLocationId
? "secondaryFilled"
: "secondary"
}
size={"extraSmall"}
key={location._id}
onClick={() => setSelectedLocationId(location._id)}
>
{location.companyLocationName}
</Button>
))}
</div>
<div className={styles.consultantSection}>
<ConsultantCard
currentLanguage={language}
consultant={contactByLocation[selectedOrDefaultLocationId]}
employeePageSlug={employeePageSlug}
/>
</div>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.locationSection {
display: flex;
flex-direction: column;
gap: 0.75rem;
}

.consultantSection {
min-width: 400px;
}
Loading

0 comments on commit a2ad733

Please sign in to comment.