Untitled

 avatar
unknown
javascript
2 months ago
7.3 kB
3
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';
import { makeStyles } from "@origen-studio/starter-components-library/theming/component.js";

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();

	const useStyles = makeStyles((theme) => ({
		mainContainer: {
			display: "flex",
			justifyContent: "center",
			alignItems: "center",
			padding: theme.spacing(5),
		},
		sidebar: {
			padding: theme.spacing(1.5),
			borderRadius: theme.shape.borderRadius,
			marginRight: theme.spacing(3),
			width: 145,
		},
		header: {
			marginTop: theme.spacing(0.5),
		},
		sectionContainer: {
			width: "100%",
			display: "flex",
			justifyContent: "flex-start",
			paddingLeft: theme.spacing(8),
			paddingRight: theme.spacing(8),
			paddingTop: theme.spacing(1),
			paddingBottom: theme.spacing(1),
		},
		sectionContent: {
			width: "calc(100% - 16px)",
		},
		divider: {
			borderColor: theme.palette.primary.main,
			borderBottomWidth: 1,
			width: "calc(100% - 16px)",
			marginBottom: theme.spacing(1),
		},
		sliceContainer: {
			width: "100%",
			paddingLeft: theme.spacing(8),
			paddingRight: theme.spacing(8),
			paddingTop: theme.spacing(2),
			paddingBottom: theme.spacing(2),
		},
		imageWrapper: {
			overflow: "hidden",
			borderRadius: theme.shape.borderRadius,
			"&:hover": {
				transform: "scale(1.05)",
				boxShadow: "0px 4px 15px rgba(0, 0, 0, 0.2)",
			},
		},
	}));

	export default function Release({ release, releaseSliceZoneProps, releasesPage }) {
		const classes = useStyles();

		if (!release) {
			return null;
		}

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

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

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

				{slices ? (
					slices.map((slice, index) => (
						<Box key={slice._key || index} className={classes.sliceContainer}>
							<Grid container spacing={4} alignItems="center">
								{slice.media?.image?.asset?.url && (
									<Grid item xs={12} md={6}>
										<Paper elevation={2} className={classes.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 className={classes.sliceContainer}>
						<Typography variant="body1" component="div">
							<ul>
								{notes.length > 0 &&
									notes.map((note) => (
										<li key={note._key}>
											<PortableText value={note} />
										</li>
									))}
							</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;
}
Leave a Comment