Untitled

 avatar
unknown
javascript
4 months ago
7.7 kB
2
Indexable
import { Stack, Paper, Box, Button, Breadcrumbs, Grid, Link as MuiLink, Typography, Divider } from "@mui/material";
import { Link, SliceRootContainer } from "@origen-studio/starter-components-library";
import { useGetDocumentHref } from "@origen-studio/starter-sanity";
import Image from 'next/image';
import { setComponentSanityDocumentProviderConfig } from "@origen-studio/starter-sanity/next/pages/client.js";
import type { InferGetStaticPropsType } from "next";
import { ComponentProps } from "react";
import { fetchLayoutProps } from "../../lib/layoutProps.jsx";
import { makeGetStaticPaths, makeGetStaticProps } from "../../lib/next/server/context.js";
import { makeReleaseSlices } from "../../lib/sanity/documents/release/slices.jsx";
import {
	fetchReleaseSlicesUseComponentsConfig,
	makeReleaseSlicesServer,
} from "../../lib/sanity/documents/release/slices.server.js";
import {
	fetchPathResolverDocument,
	fetchPathResolverDocumentStaticPaths,
	getRouteFileNameSlugParamConfig,
	NextDynamicRouteFileName,
} from "../../lib/sanity/pages.server.js";
import { Layout } from "../../src/components/index.js";
import { ReleaseStepper } from "../../src/components/ReleaseStepper/ReleaseStepper.jsx";
import { ReleaseTimelineItem } from "../../src/components/ReleaseTimelineItem/ReleaseTimelineItem.jsx";
import { PortableText } from '@portabletext/react';

const typeName = "release";
const slugParamConfig = getRouteFileNameSlugParamConfig(
	__filename as NextDynamicRouteFileName<"slug">,
);

export const getStaticProps = makeGetStaticProps(async (context) => {
	const [layoutProps, release, releasesPage] = await Promise.all([
		fetchLayoutProps(context),
		fetchPathResolverDocument({
			context,
			typeName,
			...slugParamConfig,
			queryFields: ReleaseQueryFields,
		}),
		fetchPathResolverDocument({
			context,
			typeName: "releasesPage",
			slugParam: undefined,
			queryFields: `
				breadcrumb,
				releaseLabels {...}
			`,
		}),
	]);

	if (!release) {
		return { notFound: true };
	}

	return {
		props: {
			layoutProps,
			release: release as typeof release & {
				previous: null | typeof release;
				next: null | typeof release;
			},
			releaseSliceZoneProps: await fetchReleaseSlicesUseComponentsConfig({
				context,
				release,
			}),
			releasesPage,
		},
		revalidate: 1,
	};
});

export const getStaticPaths = makeGetStaticPaths(async (context) => ({
	paths: await fetchPathResolverDocumentStaticPaths({
		context,
		typeName,
		...slugParamConfig,
	}),
	fallback: true,
}));

const ReleaseSlices = makeReleaseSlices();
const ReleaseSlicesServer = makeReleaseSlicesServer();

export default function Release({
	release,
	releaseSliceZoneProps,
	releasesPage,
}: InferGetStaticPropsType<typeof getStaticProps>) {
	const releasesPageBreadcrumb = useReleasesPageBreadcrumb({ releasesPage });
	const getDocumentHref = useGetDocumentHref();

	if (!release) {
		return null;
	}


	const slices = release.body?.slices || null;
	const notes = release.notes || [];



	const styles = {
		mainContainer: {
			display: "flex",
			justifyContent: "center",
			alignItems: "center",
			padding: 5,
		},
		sidebar: {
			padding: 1.5,
			borderRadius: 2,
			marginRight: 3,
			width: 145,
		},
		sidebarTitle: {
			marginBottom: 1,
		},
		sidebarButton: {
			justifyContent: "flex-start",
			textTransform: "none",
			pl: 0,
			width: "100%",
		},
		sidebarButtonText: {
			display: "flex",
			alignItems: "center",
		},
		header: {
			marginTop: 0.5,
		},
		sectionContainer: {
			width: "100%",
			display: "flex",
			justifyContent: "flex-start",
			paddingX: 8,
			paddingY: 1,

		},
		sectionContent: {
			width: "calc(100% - 16px)",
		},
		divider: {
			borderColor: "primary.main",
			borderBottomWidth: 1,
			width: "calc(100% - 16px)",
			mb: 1,
		},
		sliceContainer: {
			width: "100%",
			paddingX: 8,
			paddingY: 2,
		},
		imageWrapper: {
			overflow: "hidden",
			borderRadius: 2,
			"&:hover": {
			transform: "scale(1.05)",
			boxShadow: "0px 4px 15px rgba(0, 0, 0, 0.2)",
		},
		},
	};


	return (
		<>
		<Box sx={styles.mainContainer}>
			{/* Sidebar */}
			<Paper elevation={2} sx={styles.sidebar}>
				<Typography variant="subtitle2" color="primary" sx={styles.sidebarTitle}>
					PAGE CONTENTS
				</Typography>
				<Box sx={{ mt: 1 }}>
					<Button
						component="a"
						href="#new-features"
						variant="text"
						color="inherit"
						sx={styles.sidebarButton}
					>
						<Typography variant="body2" sx={styles.sidebarButtonText}>
							<span style={{ marginRight: 8 }}>{'>'}</span> {slices ? "New Features" : "Notes"}
						</Typography>
					</Button>
				</Box>
			</Paper>

			{/* Header */}
			<Box>
				<Typography variant="h2" component="h2">
					{release.tag} {release.title ? ` - ${release.title}` : ""}
				</Typography>
				<Typography variant="body1" sx={styles.header}>
					{new Date(release.publishedAt).toLocaleDateString("en-GB", {
						day: "2-digit",
						month: "2-digit",
						year: "numeric",
					})}
				</Typography>
			</Box>
		</Box>

		{/* Section Title */}
		<Box sx={styles.sectionContainer}>
			<Box sx={styles.sectionContent}>
				<Typography id="new-features" variant="h4" component="h4" gutterBottom>
					{slices ? "New Features" : "Notes"}
				</Typography>
				<Divider sx={styles.divider} />
			</Box>
		</Box>

		{/* Slices or Notes */}
		{slices ? (
			slices.map((slice, index) => (
				<Box key={slice._key || index} sx={styles.sliceContainer}>
					<Grid container spacing={4} alignItems="center">
						{slice.media?.image?.asset?.url && (
							<Grid item xs={12} md={6}>
								<Paper elevation={2} sx={styles.imageWrapper}>
									<Image
										src={slice.media.image.asset.url}
										alt={slice.media.image.alt || "Feature Image"}
										width={600}
										height={400}
										layout="responsive"
										style={{ display: 'block' }}
									/>
								</Paper>
							</Grid>
						)}

						<Grid item xs={12} md={6}>
							{slice.title && slice.title[0]?.children?.[0]?.text && (
								<Typography variant="h5" component="h2" gutterBottom>
									{slice.title[0].children[0].text}
								</Typography>
							)}
							{slice.description && slice.description[0]?.children?.[0]?.text && (
								<Typography variant="body1">
									{slice.description[0].children[0].text}
								</Typography>
							)}
						</Grid>
					</Grid>
				</Box>
			))
		) : (
			<Box sx={styles.sliceContainer}>
				<Typography variant="body1" component="div">
					<ul>
					{notes.length > 0 && (
							<ul>
									{notes.map((note) => (
											<li key={note._key}>
													<PortableText value={note} />
											</li>
									))}
							</ul>
					)}
					</ul>
				</Typography>
			</Box>
		)}


		</>
	);
}

Release.Layout = Layout.Comp;
setComponentSanityDocumentProviderConfig(Release, (props) => props.release);

const ReleaseQueryFields = `
tag,
title,
slug,
notes[],
publishedAt,
body {
	sliceRootProps {
		...
	},
	slices[] {
		...,
		${ReleaseSlicesServer.query}
	}
},
"previous": *[_type=="release" && publishedAt < ^.publishedAt && !(_id in path("drafts.**"))] | order(publishedAt desc)[0] {
	_id,
	_type,
	title,
	tag,
	slug,
	publishedAt
},
"next": *[_type=="release" && publishedAt > ^.publishedAt && !(_id in path("drafts.**"))] | order(publishedAt asc)[0] {
	_id,
	_type,
	title,
	tag,
	slug,
	publishedAt
}
`;

function useReleasesPageBreadcrumb({
	releasesPage,
}: Pick<ComponentProps<typeof Release>, "releasesPage">) {
	const getDocumentHref = useGetDocumentHref();
	const href = releasesPage && getDocumentHref(releasesPage);
	return releasesPage && releasesPage.breadcrumb && href
		? {
				label: releasesPage.breadcrumb,
				href,
		  }
		: null;
}
Editor is loading...
Leave a Comment