mirror of
https://github.com/vercel/commerce.git
synced 2025-07-27 04:01:23 +00:00
updates
This commit is contained in:
99
components/agility-modules/BlogPostDetails.tsx
Normal file
99
components/agility-modules/BlogPostDetails.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import React from "react";
|
||||
import Head from "next/head";
|
||||
import { renderHTML } from "@agility/nextjs";
|
||||
import { AgilityImage } from "@agility/nextjs";
|
||||
import truncate from "truncate-html";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image"
|
||||
|
||||
const PostDetails = ({ dynamicPageItem }: any) => {
|
||||
|
||||
// post fields
|
||||
const post = dynamicPageItem.fields;
|
||||
|
||||
const productJSON = post.product
|
||||
const product = JSON.parse(productJSON)
|
||||
|
||||
// format date
|
||||
const dateStr = new Date(post.date).toLocaleDateString();
|
||||
|
||||
const description = truncate(post.content, {
|
||||
length: 160,
|
||||
decodeEntities: true,
|
||||
stripTags: true,
|
||||
reserveLastWord: true,
|
||||
});
|
||||
|
||||
let imageSrc = post.image?.url || null;
|
||||
|
||||
|
||||
// post image alt
|
||||
let imageAlt = post.image?.label || null;
|
||||
|
||||
|
||||
let ogImageSrc = `${imageSrc}?w=1600&h=900`
|
||||
|
||||
let imageHeight = 900
|
||||
let imageWidth = 1600
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<meta property="twitter:image" content={ogImageSrc} />
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta name="og:title" content={post.title} />
|
||||
<meta property="og:image" content={ogImageSrc} />
|
||||
<meta property="og:image:width" content={`${imageWidth}`} />
|
||||
<meta property="og:image:height" content={`${imageHeight}`} />
|
||||
<meta name="description" content={description} />
|
||||
<meta name="og:description" content={description} />
|
||||
<meta name="twitter:description" content={description} />
|
||||
<meta name="twitter:title" content={post.title} />
|
||||
</Head>
|
||||
<div className="relative px-8">
|
||||
|
||||
<div className="max-w-screen-xl mx-auto">
|
||||
<div className="h-64 md:h-96 aspect-w-16 aspect-h-9 relative">
|
||||
<AgilityImage
|
||||
src={imageSrc}
|
||||
alt={imageAlt}
|
||||
className="object-cover object-center rounded-lg"
|
||||
layout="fill"
|
||||
/>
|
||||
|
||||
<Link href={`/product${product.slug}`}>
|
||||
<a className="absolute" style={{bottom: "-80px", right: "-20px"}}>
|
||||
<Image src={product.imageUrl} alt={product.name} width={300} height={300} layout="fixed" />
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="max-w-2xl mx-auto mt-4">
|
||||
<Link href={`/product${product.slug}`}><a className="uppercase text-primary-500 text-xs font-bold tracking-widest leading-loose">{product.name}</a></Link>
|
||||
<div className="border-b-2 border-primary-500 w-8"></div>
|
||||
<div className="mt-4 uppercase text-gray-600 italic font-semibold text-xs">
|
||||
{dateStr}
|
||||
</div>
|
||||
<h1 className="font-display text-4xl font-bold my-6 text-secondary-500">
|
||||
{post.title}
|
||||
</h1>
|
||||
|
||||
<div
|
||||
className="prose max-w-full mb-20"
|
||||
dangerouslySetInnerHTML={renderHTML(post.content)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
PostDetails.getCustomInitialProps = async () => {
|
||||
return {
|
||||
cloud_name: process.env.CLOUDINARY_CLOUD_NAME
|
||||
}
|
||||
}
|
||||
|
||||
export default PostDetails;
|
87
components/agility-modules/BlogPostListing.tsx
Normal file
87
components/agility-modules/BlogPostListing.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image"
|
||||
|
||||
import { ModuleWithInit, AgilityImage } from '@agility/nextjs'
|
||||
import products from "pages/api/catalog/products";
|
||||
|
||||
interface ICustomData {
|
||||
|
||||
posts: []
|
||||
|
||||
}
|
||||
|
||||
interface IModule {
|
||||
|
||||
}
|
||||
|
||||
const PostsListing: ModuleWithInit<IModule, ICustomData> = ({ customData, module, languageCode, isDevelopmentMode, isPreview }) => {
|
||||
// get posts
|
||||
const { posts } = customData;
|
||||
|
||||
// set up href for internal links
|
||||
let href = "/pages/[...slug]";
|
||||
|
||||
// if there are no posts, display message on frontend
|
||||
if (posts.length <= 0) {
|
||||
return (
|
||||
<div className="mt-44 px-6 flex flex-col items-center justify-center">
|
||||
<h1 className="text-3xl text-center font-bold">No posts available.</h1>
|
||||
<div className="my-10">
|
||||
<Link href={href} as="/home">
|
||||
<a className="px-4 py-3 my-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-primary-600 hover:bg-primary-500 focus:outline-none focus:border-primary-700 focus:shadow-outline-primary transition duration-300">
|
||||
Return Home
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative px-8 mb-12">
|
||||
<div className="max-w-screen-xl mx-auto">
|
||||
<div className="sm:grid sm:gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{posts.map((post: any, index) => (
|
||||
<Link href={post.url} key={index}>
|
||||
<a>
|
||||
<div className="flex-col group mb-8 md:mb-0">
|
||||
<div className="relative h-64">
|
||||
<AgilityImage
|
||||
src={post.imageSrc}
|
||||
alt={post.imageAlt}
|
||||
className="object-cover object-center rounded-t-lg"
|
||||
layout="fill"
|
||||
|
||||
/>
|
||||
<div className="absolute right-0" style={{bottom: "-60px"}}>
|
||||
<Image src={post.productImageSrc} alt={post.productName} width={200} height={200} layout="fixed" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-100 p-8 border-2 border-t-0 rounded-b-lg">
|
||||
<div className="uppercase text-primary-500 text-xs font-bold tracking-widest leading-loose">
|
||||
{post.productName}
|
||||
</div>
|
||||
<div className="border-b-2 border-primary-500 w-8"></div>
|
||||
<div className="mt-4 uppercase text-gray-600 italic font-semibold text-xs">
|
||||
{post.date}
|
||||
</div>
|
||||
<h2 className="text-secondary-500 mt-1 font-black text-2xl group-hover:text-primary-500 transition duration-300">
|
||||
{post.title}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
export default PostsListing;
|
@@ -1,39 +0,0 @@
|
||||
import { FC } from "react"
|
||||
import { Grid, Marquee, Hero } from '@components/ui'
|
||||
import { ProductCard } from '@components/product'
|
||||
import { ModuleWithInit } from "@agility/nextjs"
|
||||
|
||||
interface ICustomData {
|
||||
products: any
|
||||
}
|
||||
|
||||
interface IModule {
|
||||
}
|
||||
|
||||
|
||||
const FeaturedProducts: ModuleWithInit<IModule, ICustomData> = ({ customData }) => {
|
||||
|
||||
if (! customData) {
|
||||
return <div>No featured products returned.</div>
|
||||
}
|
||||
|
||||
const products:any = customData.products
|
||||
|
||||
return (
|
||||
<Grid variant="filled">
|
||||
{products.slice(0, 3).map((product: any, i: number) => (
|
||||
<ProductCard
|
||||
key={product.id}
|
||||
product={product}
|
||||
imgProps={{
|
||||
width: i === 0 ? 1080 : 540,
|
||||
height: i === 0 ? 1080 : 540,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
export default FeaturedProducts
|
||||
|
@@ -1,42 +0,0 @@
|
||||
import React, { FC } from 'react'
|
||||
import HomeAllProductsGrid from '@components/common/HomeAllProductsGrid'
|
||||
import { ModuleWithInit } from '@agility/nextjs'
|
||||
import { ProductCard } from '@components/product'
|
||||
import { Grid, Marquee, Hero } from '@components/ui'
|
||||
|
||||
|
||||
interface ICustomData {
|
||||
|
||||
products: any
|
||||
|
||||
}
|
||||
|
||||
interface IModule {
|
||||
}
|
||||
|
||||
|
||||
const HomeAllProductsGridModule: ModuleWithInit<IModule, ICustomData> = ({ customData }) => {
|
||||
|
||||
|
||||
const products = customData.products
|
||||
|
||||
return (
|
||||
<Grid layout="B" variant="filled">
|
||||
{products.slice(0, 3).map((product: any, i: number) => (
|
||||
<ProductCard
|
||||
key={product.id}
|
||||
product={product}
|
||||
imgProps={{
|
||||
width: i === 0 ? 1080 : 540,
|
||||
height: i === 0 ? 1080 : 540,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default HomeAllProductsGridModule
|
||||
|
@@ -1,8 +1,44 @@
|
||||
const ProductListing = () => {
|
||||
return (
|
||||
<section>ProductListing</section>
|
||||
)
|
||||
import React, { FC } from 'react'
|
||||
import { ModuleWithInit } from '@agility/nextjs'
|
||||
import { ProductCard } from '@components/product'
|
||||
import { Grid, Marquee, Hero } from '@components/ui'
|
||||
|
||||
|
||||
interface ICustomData {
|
||||
|
||||
products: any
|
||||
|
||||
}
|
||||
|
||||
export default ProductListing
|
||||
interface IModule {
|
||||
numItems: string,
|
||||
layout?: 'A' | 'B' | 'C' | 'D' | 'normal'
|
||||
variant?: 'default' | 'filled'
|
||||
}
|
||||
|
||||
|
||||
const ProductListingModule: ModuleWithInit<IModule, ICustomData> = ( { customData, module, languageCode, isDevelopmentMode, isPreview }) => {
|
||||
|
||||
|
||||
const products = customData.products
|
||||
|
||||
return (
|
||||
<Grid layout={module.fields.layout} variant={module.fields.variant}>
|
||||
{products.map((product: any, i: number) => (
|
||||
<ProductCard
|
||||
key={product.id}
|
||||
product={product}
|
||||
imgProps={{
|
||||
width: i === 0 ? 1080 : 540,
|
||||
height: i === 0 ? 1080 : 540,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default ProductListingModule
|
||||
|
||||
|
@@ -12,7 +12,7 @@ interface IModule {
|
||||
}
|
||||
|
||||
|
||||
const BestsellingProducts: ModuleWithInit<IModule, ICustomData> = ({ customData }) => {
|
||||
const ProductMarqueeModule: ModuleWithInit<IModule, ICustomData> = ({ customData }) => {
|
||||
|
||||
const products = customData.products
|
||||
|
||||
@@ -26,5 +26,5 @@ const BestsellingProducts: ModuleWithInit<IModule, ICustomData> = ({ customData
|
||||
}
|
||||
|
||||
|
||||
export default BestsellingProducts
|
||||
export default ProductMarqueeModule
|
||||
|
@@ -8,8 +8,6 @@ interface Fields {
|
||||
|
||||
const RichTextArea:Module<Fields> = ({ module: {fields} }) => {
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Text className="prose prose-sm sm:prose lg:prose-lg xl:prose-xl" html={fields.textblob} />
|
||||
|
@@ -1,21 +1,22 @@
|
||||
import RichTextArea from "./RichTextArea"
|
||||
import BestsellingProducts from "./BestsellingProducts"
|
||||
import ProductMarquee from "./ProductMarquee"
|
||||
import ProductDetails from "./ProductDetails"
|
||||
import FeaturedProducts from "./FeaturedProducts"
|
||||
|
||||
import ProductListing from "./ProductListing"
|
||||
import ProductSearch from "./ProductSearch"
|
||||
import Hero from "./Hero"
|
||||
import HomeAllProductsGrid from "./HomeAllProductsGrid"
|
||||
import HomeAllProductsGrid from "./ProductListing"
|
||||
import Cart from "./Cart"
|
||||
import Orders from "./Orders"
|
||||
import Profile from "./Profile"
|
||||
import Wishlist from "./Wishlist"
|
||||
import BlogPostListing from "./BlogPostListing"
|
||||
import BlogPostDetails from "./BlogPostDetails"
|
||||
|
||||
|
||||
const allModules = [
|
||||
{ name: "RichTextArea", module: RichTextArea },
|
||||
{ name: "BestsellingProducts", module: BestsellingProducts },
|
||||
{ name: "FeaturedProducts", module: FeaturedProducts },
|
||||
{ name: "ProductMarquee", module: ProductMarquee },
|
||||
{ name: "ProductListing", module: ProductListing },
|
||||
{ name: "ProductSearch", module: ProductSearch },
|
||||
{ name: "Hero", module: Hero },
|
||||
@@ -23,8 +24,11 @@ const allModules = [
|
||||
{ name: "HomeAllProductsGrid", module: HomeAllProductsGrid },
|
||||
{ name: "Cart", module: Cart },
|
||||
{ name: "Orders", module: Orders },
|
||||
{ name: "Profile", module: Profile},
|
||||
{ name: "Wishlist", module: Wishlist}
|
||||
{ name: "Profile", module: Profile },
|
||||
{ name: "Wishlist", module: Wishlist },
|
||||
{ name: "BlogPostListing", module: BlogPostListing },
|
||||
{ name: "BlogPostDetails", module: BlogPostDetails }
|
||||
|
||||
]
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user