Skip to content

Commit

Permalink
v3 - featured customer cases (#837)
Browse files Browse the repository at this point in the history
* fix(customerCase): prevent content overflow

* feat(customerCase): featured customer cases

* feat(featuredCases): case link in title
  • Loading branch information
mathiazom authored Oct 30, 2024
1 parent 29051a1 commit f6b26ff
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 11 deletions.
7 changes: 6 additions & 1 deletion src/app/(main)/[lang]/[...path]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@ async function Page({ params }: Props) {
<CustomerCases customerCasesPage={queryResponse.data} />
);
case "customerCase":
return <CustomerCase customerCase={queryResponse.data} />;
return (
<CustomerCase
customerCase={queryResponse.customerCase.data}
customerCasesPagePath={queryResponse.customerCasesPagePath}
/>
);
case "legalDocument":
return isDraftMode ? (
<LegalPreview initialDocument={queryResponse} />
Expand Down
22 changes: 17 additions & 5 deletions src/components/customerCases/customerCase/CustomerCase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@ import {
} from "studioShared/lib/interfaces/customerCases";

import styles from "./customerCase.module.css";
import FeaturedCases from "./featuredCases/FeaturedCases";
import ImageSection from "./sections/image/ImageSection";
import RichTextSection from "./sections/richText/RichTextSection";

export interface CustomerCaseProps {
customerCase: CustomerCaseDocument;
}

function CustomerCaseSection({
section,
}: {
Expand All @@ -36,7 +33,15 @@ function CustomerCaseSection({
}
}

export default function CustomerCase({ customerCase }: CustomerCaseProps) {
export interface CustomerCaseProps {
customerCase: CustomerCaseDocument;
customerCasesPagePath: string[];
}

export default function CustomerCase({
customerCase,
customerCasesPagePath,
}: CustomerCaseProps) {
return (
<div className={styles.wrapper}>
<div className={styles.content}>
Expand Down Expand Up @@ -129,6 +134,13 @@ export default function CustomerCase({ customerCase }: CustomerCaseProps) {
<CustomerCaseSection key={section._key} section={section} />
))}
</div>
{customerCase.featuredCases &&
customerCase.featuredCases.length > 0 && (
<FeaturedCases
featuredCases={customerCase.featuredCases}
customerCasesPath={customerCasesPagePath}
/>
)}
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
.wrapper {
display: flex;
flex-direction: column;
margin: 4rem 0;
margin: 4rem 2rem;
align-items: center;

@media (max-width: 1024px) {
margin: 2rem 0;
margin: 2rem 1rem;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Link from "next/link";

import { SanitySharedImage } from "src/components/image/SanityImage";
import Text from "src/components/text/Text";
import { CustomerCaseBase } from "studioShared/lib/interfaces/customerCases";

import styles from "./featuredCases.module.css";

export interface FeaturedCasesProps {
featuredCases: CustomerCaseBase[];
customerCasesPath: string[];
}

export default function FeaturedCases({
featuredCases,
customerCasesPath,
}: FeaturedCasesProps) {
return (
featuredCases.length > 0 && (
<div className={styles.wrapper}>
<Text type={"h3"}>Lignende prosjekter</Text>
<div className={styles.content}>
{featuredCases.map((featuredCase) => (
<div key={featuredCase._id} className={styles.caseWrapper}>
<div className={styles.caseImageWrapper}>
<SanitySharedImage image={featuredCase.image} />
</div>
<div>
<Link
href={`/${[...customerCasesPath, featuredCase.slug].join("/")}`}
>
<Text type={"bodyBig"}>{featuredCase.basicTitle}</Text>
</Link>
<Text type={"bodySmall"}>{featuredCase.description}</Text>
</div>
</div>
))}
</div>
</div>
)
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.wrapper {
display: flex;
flex-direction: column;
gap: 2rem;
margin: 4rem 0;
}

.content {
display: flex;
gap: 5rem;

@media (max-width: 1024px) {
flex-direction: column;
}
}

.caseWrapper {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 500px;
flex-grow: 1;
flex-basis: 0;
}

.caseImageWrapper {
width: 100%;
height: 200px;
}

.caseImageWrapper img {
border-radius: 0.75rem;
width: 100% !important;
}
13 changes: 11 additions & 2 deletions src/utils/pageData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,13 @@ async function fetchCustomerCase({
perspective,
}: PageDataParams): Promise<
| PageFromParams<QueryResponseInitial<CustomerCasePage>, "customerCasesPage">
| PageFromParams<QueryResponseInitial<CustomerCase>, "customerCase">
| PageFromParams<
{
customerCase: QueryResponseInitial<CustomerCase>;
customerCasesPagePath: string[];
},
"customerCase"
>
| null
> {
if (path.length === 0) {
Expand Down Expand Up @@ -204,7 +210,10 @@ async function fetchCustomerCase({
},
);
return {
queryResponse: customerCaseResult,
queryResponse: {
customerCase: customerCaseResult,
customerCasesPagePath: [language, customerCasesPageResult.data.slug],
},
docType: customerCaseID,
pathTranslations:
casePathTranslations.data?.reduce<InternationalizedString>(
Expand Down
1 change: 1 addition & 0 deletions studioShared/lib/interfaces/customerCases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ export type CustomerCaseSection = RichTextBlock | ImageBlock | QuoteBlock;
export interface CustomerCase extends CustomerCaseBase {
projectInfo: CustomerCaseProjectInfo;
sections: CustomerCaseSection[];
featuredCases?: CustomerCaseBase[] | null;
}
3 changes: 3 additions & 0 deletions studioShared/lib/queries/customerCases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ export const CUSTOMER_CASE_QUERY = groq`
"quote": ${translatedFieldFragment("quote")},
"author": ${translatedFieldFragment("author")},
},
},
"featuredCases": featuredCases[] -> {
${CUSTOMER_CASE_BASE_FRAGMENT}
}
}
`;
Expand Down
49 changes: 48 additions & 1 deletion studioShared/schemas/documents/customerCase.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { defineField, defineType } from "sanity";
import { groq } from "next-sanity";
import { Reference, defineField, defineType } from "sanity";

import { isInternationalizedString } from "studio/lib/interfaces/global";
import { internationalizedImage } from "studio/schemas/fields/media";
import { titleID } from "studio/schemas/fields/text";
import { titleSlug } from "studio/schemas/schemaTypes/slug";
import { buildDraftId, buildPublishedId } from "studio/utils/documentUtils";
import { firstTranslation } from "studio/utils/i18n";
import { customerCaseProjectInfo } from "studioShared/schemas/fields/customerCaseProjectInfo";
import imageBlock from "studioShared/schemas/objects/imageBlock";
Expand Down Expand Up @@ -73,6 +75,51 @@ const customerCase = defineType({
type: "array",
of: [richTextBlock, imageBlock, listBlock, quoteBlock],
}),
defineField({
name: "featuredCases",
title: "Featured Cases",
description:
"List of Customer Cases that should be displayed at the bottom of this Customer Case",
type: "array",
of: [
{
type: "reference",
to: [{ type: customerCaseID }],
validation: (rule) =>
rule.custom((value: Reference, context) => {
if (
context.document !== undefined &&
buildPublishedId(value._ref) ===
buildPublishedId(context.document._id)
) {
return "Can not feature itself";
}
return true;
}),
options: {
disableNew: true,
filter: ({ document, parent }) => ({
// hide current and already featured customer cases
filter: groq`!(_id in $forbiddenIds)`,
params: {
forbiddenIds: [
buildPublishedId(document._id),
buildDraftId(document._id),
...(Array.isArray(parent)
? parent.flatMap((r) =>
typeof r._ref === "string"
? [buildPublishedId(r._ref), buildDraftId(r._ref)]
: undefined,
)
: []),
],
},
}),
},
},
],
validation: (rule) => rule.max(3).unique(),
}),
],
preview: {
select: {
Expand Down

0 comments on commit f6b26ff

Please sign in to comment.