feat: implement about and contact page

fetch localized content from Payload
main
RaviAnand Mohabir 3 weeks ago
parent f39059202f
commit ac318177d4

@ -1,6 +1,7 @@
import type { Options } from "node_modules/payload/dist/globals/operations/local/findOne";
import { getPayload } from "@/utils/payload"; import { getPayload } from "@/utils/payload";
export const getAbout = async () => { export const getAbout = async (opts: Omit<Options<"about">, "slug"> = {}) => {
const payload = await getPayload(); const payload = await getPayload();
return await payload.findGlobal({ slug: "about" }); return await payload.findGlobal({ slug: "about", ...opts });
}; };

@ -1,6 +1,7 @@
import type { Options } from "node_modules/payload/dist/globals/operations/local/findOne";
import { getPayload } from "@/utils/payload"; import { getPayload } from "@/utils/payload";
export const getContact = async () => { export const getContact = async (opts: Omit<Options<"contact">, "slug"> = {}) => {
const payload = await getPayload(); const payload = await getPayload();
return await payload.findGlobal({ slug: "contact" }); return await payload.findGlobal({ slug: "contact", ...opts });
}; };

@ -1,6 +1,7 @@
import type { Options } from "node_modules/payload/dist/globals/operations/local/findOne";
import { getPayload } from "@/utils/payload"; import { getPayload } from "@/utils/payload";
export const getGallery = async () => { export const getGallery = async (opts: Omit<Options<"gallery">, "slug"> = {}) => {
const payload = await getPayload(); const payload = await getPayload();
return await payload.findGlobal({ slug: "gallery" }); return await payload.findGlobal({ slug: "gallery", ...opts });
}; };

@ -1,6 +1,7 @@
import type { Options } from "node_modules/payload/dist/globals/operations/local/findOne";
import { getPayload } from "@/utils/payload"; import { getPayload } from "@/utils/payload";
export const getHome = async () => { export const getHome = async (opts: Omit<Options<"home">, "slug"> = {}) => {
const payload = await getPayload(); const payload = await getPayload();
return await payload.findGlobal({ slug: "home" }); return await payload.findGlobal({ slug: "home", ...opts });
}; };

@ -1,9 +1,11 @@
import { Options } from "node_modules/payload/dist/collections/operations/local/find"; import type { Options } from "node_modules/payload/dist/collections/operations/local/find";
import { getPayload } from "@/utils/payload"; import { getPayload } from "@/utils/payload";
export const getMenuCategories = async () => { export const getMenuCategories = async (
opts: Omit<Options<"menu-category">, "collection" | "pagination"> = {},
) => {
const payload = await getPayload(); const payload = await getPayload();
return payload.find({ collection: "menu-category", pagination: false }); return payload.find({ collection: "menu-category", pagination: false, ...opts });
}; };
export const getMenuItems = async (opts: Omit<Options<"menu-item">, "collection">) => { export const getMenuItems = async (opts: Omit<Options<"menu-item">, "collection">) => {

@ -1,6 +1,14 @@
import type { Options } from "node_modules/payload/dist/collections/operations/local/find";
import { getPayload } from "@/utils/payload"; import { getPayload } from "@/utils/payload";
export const getOpeningTimes = async () => { export const getOpeningTimes = async (
opts: Omit<Options<"opening-time">, "collection" | "sort" | "pagination">,
) => {
const payload = await getPayload(); const payload = await getPayload();
return await payload.find({ collection: "opening-time", sort: "from", pagination: false }); return await payload.find({
collection: "opening-time",
sort: "from",
pagination: false,
...opts,
});
}; };

@ -1,17 +1,18 @@
import { Box, styled } from "@styled-system/jsx"; import { Container } from "@styled-system/jsx";
import { Metadata } from "next"; import { Metadata } from "next";
import { Params } from "../shared";
import RichText from "@/components/rich-text"; import RichText from "@/components/rich-text";
import { getAbout } from "@/api"; import { getAbout } from "@/api";
import { getI18n } from "@/i18n/server";
export default async function About() { export default async function About({ params: { locale } }: { params: Params }) {
const about = await getAbout(); const t = await getI18n();
const about = await getAbout({ locale });
return ( return (
<Box> <Container pt={6}>
<styled.h1></styled.h1>
<RichText content={about.text!} /> <RichText content={about.text!} />
</Box> </Container>
); );
} }

@ -2,16 +2,17 @@ import { Box, HStack, Stack } from "@styled-system/jsx";
import { getAbout, getContact } from "@/api"; import { getAbout, getContact } from "@/api";
import { Heading } from "@/components/ui/heading"; import { Heading } from "@/components/ui/heading";
import { Params } from "../shared";
import { Text } from "@/components/ui/text"; import { Text } from "@/components/ui/text";
import { getI18n } from "@/i18n/server"; import { getI18n } from "@/i18n/server";
import { getOpeningTimes } from "@/api/openingTimes"; import { getOpeningTimes } from "@/api/openingTimes";
import { styled } from "@styled-system/jsx"; import { styled } from "@styled-system/jsx";
export default async function Contact() { export default async function Contact({ params: { locale } }: { params: Params }) {
const t = await getI18n(); const t = await getI18n();
const about = await getAbout(); const about = await getAbout({ locale });
const contact = await getContact(); const contact = await getContact({ locale });
const openingTimes = await getOpeningTimes(); const openingTimes = await getOpeningTimes({ locale });
return ( return (
<Stack p={6} gap={10}> <Stack p={6} gap={10}>

@ -1,9 +1,10 @@
import Carousel from "@/components/ui/carousel"; import Carousel from "@/components/ui/carousel";
import { Locale } from "@/i18n/settings";
import { Media } from "@/payload-types"; import { Media } from "@/payload-types";
import { getGallery } from "@/api"; import { getGallery } from "@/api";
export default async function Gallery() { export default async function Gallery({ locale }: { locale: Locale }) {
const { images } = await getGallery(); const { images } = await getGallery({ locale });
return <Carousel images={images.map(({ image }) => image as Media)} w="100%" />; return <Carousel images={images.map(({ image }) => image as Media)} w="100%" />;
} }

@ -4,6 +4,7 @@ import Footer from "@/components/layout/footer";
import { I18nProviderClient } from "@/i18n/client"; import { I18nProviderClient } from "@/i18n/client";
import { Metadata } from "next"; import { Metadata } from "next";
import Navbar from "@/components/layout/navbar"; import Navbar from "@/components/layout/navbar";
import { Params } from "./shared";
import { getAbout } from "@/api"; import { getAbout } from "@/api";
import localFont from "next/font/local"; import localFont from "next/font/local";
import { locales } from "@/i18n/settings"; import { locales } from "@/i18n/settings";
@ -18,18 +19,18 @@ export default async function RootLayout({
params: { locale }, params: { locale },
children, children,
}: { }: {
params: { locale: string }; params: Params;
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<html lang={locale}> <html lang={locale}>
<I18nProviderClient locale={locale}> <I18nProviderClient locale={locale}>
<styled.body className={moderustic.className}> <styled.body className={moderustic.className}>
<Navbar /> <Navbar locale={locale} />
<styled.main mt={20} pb={20}> <styled.main mt={20} pb={20}>
{children} {children}
</styled.main> </styled.main>
<Footer /> <Footer locale={locale} />
</styled.body> </styled.body>
</I18nProviderClient> </I18nProviderClient>
</html> </html>

@ -4,6 +4,7 @@ import { HoverCard } from "@/components/ui/hover-card";
import { IconButton } from "@/components/ui/icon-button"; import { IconButton } from "@/components/ui/icon-button";
import Image from "next/image"; import Image from "next/image";
import { Image as ImageIcon } from "lucide-react"; import { Image as ImageIcon } from "lucide-react";
import { Locale } from "@/i18n/settings";
import { Media } from "@/payload-types"; import { Media } from "@/payload-types";
import RichText from "@/components/rich-text"; import RichText from "@/components/rich-text";
import { TabContentBaseProps } from "@ark-ui/react"; import { TabContentBaseProps } from "@ark-ui/react";
@ -12,12 +13,11 @@ import { Text } from "@/components/ui/text";
import { css } from "@styled-system/css"; import { css } from "@styled-system/css";
import { formatToCHF } from "@/utils/formatters"; import { formatToCHF } from "@/utils/formatters";
import { getMenuItems } from "@/api"; import { getMenuItems } from "@/api";
import { locales } from "@/i18n/settings";
export default async function CategoryTabContent({ export default async function CategoryTabContent({
locale, locale,
...props ...props
}: { locale: (typeof locales)[number] } & TabContentBaseProps) { }: { locale: Locale } & TabContentBaseProps) {
const menuItems = await getMenuItems({ const menuItems = await getMenuItems({
locale, locale,
where: { category: { equals: props.value } }, where: { category: { equals: props.value } },

@ -9,7 +9,7 @@ import { getMenuCategories } from "@/api";
export default async function Menu({ params: { locale } }: { params: Params }) { export default async function Menu({ params: { locale } }: { params: Params }) {
const t = await getI18n(); const t = await getI18n();
const menuCategories = await getMenuCategories(); const menuCategories = await getMenuCategories({ locale });
return ( return (
<Stack p={6} align="center"> <Stack p={6} align="center">

@ -4,14 +4,14 @@ import { getAbout, getHome } from "@/api";
import Gallery from "./gallery"; import Gallery from "./gallery";
import Image from "next/image"; import Image from "next/image";
import { Media } from "@/payload-types"; import { Media } from "@/payload-types";
import { Metadata } from "next"; import { Params } from "./shared";
import RichText from "@/components/rich-text"; import RichText from "@/components/rich-text";
import { css } from "@styled-system/css"; import { css } from "@styled-system/css";
import { styled } from "@styled-system/jsx"; import { styled } from "@styled-system/jsx";
export default async function Home() { export default async function Home({ params: { locale } }: { params: Params }) {
const home = await getHome(); const home = await getHome({ locale });
const about = await getAbout(); const about = await getAbout({ locale });
return ( return (
<Stack gap={10} align="center"> <Stack gap={10} align="center">
@ -37,7 +37,7 @@ export default async function Home() {
<RichText content={home.aboutText} /> <RichText content={home.aboutText} />
</Container> </Container>
<Box maxW={600} w="100%" h="60vh"> <Box maxW={600} w="100%" h="60vh">
<Gallery /> <Gallery locale={locale} />
</Box> </Box>
</Stack> </Stack>
); );

@ -1,3 +1,3 @@
import { locales } from "@/i18n/settings"; import { Locale } from "@/i18n/settings";
export type Params = { locale: (typeof locales)[number] }; export type Params = { locale: Locale };

@ -2,13 +2,14 @@ import { Box, HStack, Stack, styled } from "@styled-system/jsx";
import { getAbout, getContact } from "@/api"; import { getAbout, getContact } from "@/api";
import { IconButton } from "@/components/ui/icon-button"; import { IconButton } from "@/components/ui/icon-button";
import { Locale } from "@/i18n/settings";
import { SiFacebook } from "@icons-pack/react-simple-icons"; import { SiFacebook } from "@icons-pack/react-simple-icons";
import { Text } from "@/components/ui/text"; import { Text } from "@/components/ui/text";
import { stack } from "@styled-system/patterns"; import { stack } from "@styled-system/patterns";
export default async function Footer() { export default async function Footer({ locale }: { locale: Locale }) {
const about = await getAbout(); const about = await getAbout({ locale });
const contact = await getContact(); const contact = await getContact({ locale });
return ( return (
<styled.footer h={60} p={8} className={stack({ gap: 4, justify: "end" })}> <styled.footer h={60} p={8} className={stack({ gap: 4, justify: "end" })}>

@ -1,6 +1,7 @@
import Image from "next/image"; import Image from "next/image";
import LanguagePicker from "./language-picker"; import LanguagePicker from "./language-picker";
import Link from "next/link"; import Link from "next/link";
import { Locale } from "@/i18n/settings";
import { Media } from "@/payload-types"; import { Media } from "@/payload-types";
import MobileNav from "./mobile-nav"; import MobileNav from "./mobile-nav";
import NavLink from "./nav-link"; import NavLink from "./nav-link";
@ -10,9 +11,9 @@ import { getAbout } from "@/api";
import { getI18n } from "@/i18n/server"; import { getI18n } from "@/i18n/server";
import { styled } from "@styled-system/jsx"; import { styled } from "@styled-system/jsx";
export default async function Navbar() { export default async function Navbar({ locale }: { locale: Locale }) {
const t = await getI18n(); const t = await getI18n();
const about = await getAbout(); const about = await getAbout({ locale });
return ( return (
<styled.nav <styled.nav

@ -8,9 +8,12 @@ import {
IS_UNDERLINE, IS_UNDERLINE,
} from "./node-format"; } from "./node-format";
import React, { Fragment, JSX } from "react"; import React, { Fragment, JSX } from "react";
import { css, cva } from "@styled-system/css";
import { DefaultNodeTypes } from "@payloadcms/richtext-lexical"; import { DefaultNodeTypes } from "@payloadcms/richtext-lexical";
import { cva } from "@styled-system/css"; import Image from "next/image";
import { Media } from "@/payload-types";
import { styled } from "@styled-system/jsx";
export type NodeTypes = DefaultNodeTypes; export type NodeTypes = DefaultNodeTypes;
@ -18,12 +21,12 @@ const headingRecipe = cva({
base: { fontSize: "xl" }, base: { fontSize: "xl" },
variants: { variants: {
size: { size: {
h1: { fontSize: "xl" }, h1: { fontSize: "4xl" },
h2: { fontSize: "2xl" }, h2: { fontSize: "3xl" },
h3: { fontSize: "3xl" }, h3: { fontSize: "2xl" },
h4: { fontSize: "4xl" }, h4: { fontSize: "xl" },
h5: { fontSize: "5xl" }, h5: { fontSize: "lg" },
h6: { fontSize: "6xl" }, h6: { fontSize: "md" },
}, },
}, },
}); });
@ -102,7 +105,11 @@ export function serializeLexical({ nodes }: Props): JSX.Element {
return <br key={index} />; return <br key={index} />;
} }
case "paragraph": { case "paragraph": {
return <p key={index}>{serializedChildren}</p>; return (
<styled.p key={index} mb={2}>
{serializedChildren}
</styled.p>
);
} }
case "heading": { case "heading": {
const Tag = node?.tag; const Tag = node?.tag;
@ -151,8 +158,23 @@ export function serializeLexical({ nodes }: Props): JSX.Element {
</a> </a>
); );
} }
case "upload": {
const media = node.value as Media;
return (
<styled.div textAlign="center">
<Image
height={250}
width={500}
src={media.url!}
alt={media.alt ?? ""}
className={css({ display: "inline-block" })}
/>
</styled.div>
);
}
default: default:
console.log(node.type);
return null; return null;
} }
})} })}

@ -1,3 +1,4 @@
import { ContactEmbedNotice } from "@/globals/ContactEmbedNotice";
import type { GlobalConfig } from "payload"; import type { GlobalConfig } from "payload";
export const Contact: GlobalConfig = { export const Contact: GlobalConfig = {
@ -52,20 +53,6 @@ export const Contact: GlobalConfig = {
name: "embeddedMaps", name: "embeddedMaps",
type: "code", type: "code",
}, },
{
name: "embeddedMapsNotice",
type: "ui",
admin: {
components: {
Field: () => (
<p>
Use a generator like <a href="https://www.maps.ie/create-google-map/">maps.ie</a>{" "}
to create a Google Maps embed.
</p>
),
},
},
},
], ],
}, },
{ {

@ -0,0 +1,6 @@
export const ContactEmbedNotice = () => (
<p>
Use a generator like <a href="https://www.maps.ie/create-google-map/">maps.ie</a> to create a
Google Maps embed.
</p>
);

@ -4,9 +4,21 @@ export default {
menu: "Menu", menu: "Menu",
contact: "Contact", contact: "Contact",
home: "Home", home: "Home",
address: "Address",
email: "Email",
openingTimes: "Opening Times",
en: "English", en: "English",
de: "German", de: "German",
fr: "French", fr: "French",
it: "Italian", it: "Italian",
}, },
days: {
"0": "Monday",
"1": "Tuesday",
"2": "Wednesday",
"3": "Thursday",
"4": "Friday",
"5": "Saturday",
"6": "Sunday",
},
} as const; } as const;

@ -1,2 +1,4 @@
export const defaultLocale = "de" as const; export const defaultLocale = "de" as const;
export const locales = [defaultLocale, "en"] as const; export const locales = [defaultLocale, "en"] as const;
export type Locale = (typeof locales)[number];

Loading…
Cancel
Save