Ported more functionality

This commit is contained in:
Henrik Larsson
2023-05-04 09:20:26 +02:00
parent a9ad63d056
commit c68f95e454
27 changed files with 197 additions and 121 deletions

View File

@@ -0,0 +1,115 @@
import {
CarouselItemProps as ItemProps,
CarouselProps as Props,
} from 'components/modules/carousel/carousel'
import dynamic from 'next/dynamic'
const Carousel = dynamic<Props>(() =>
import('components/modules/carousel/carousel').then((mod) => mod.Carousel)
)
const CarouselItem = dynamic<ItemProps>(() =>
import('components/modules/carousel/carousel').then((mod) => mod.CarouselItem)
)
const Card = dynamic(() => import('components/ui/card'))
import Text from 'components/ui/text'
interface BlurbSectionProps {
blurbs: any
title: string
mobileLayout: string
desktopLayout: string
imageFormat: 'square' | 'portrait' | 'landscape'
}
const BlurbSection = ({
title,
mobileLayout,
desktopLayout,
blurbs,
imageFormat,
}: BlurbSectionProps) => {
const gridLayout =
desktopLayout === '2-column'
? 'lg:grid-cols-2'
: desktopLayout === '3-column'
? 'lg:grid-cols-3'
: 'lg:grid-cols-4'
const sliderLayout =
desktopLayout === '2-column' ? 2 : desktopLayout === '3-column' ? 3 : 4
return (
<div>
{title ? (
<Text
className="mb-4 px-4 lg:px-8 lg:mb-6 2xl:px-16 2xl:mb-8"
variant="sectionHeading"
>
{title}
</Text>
) : (
<Text
className="italic mb-4 px-4 lg:px-8 lg:mb-6 2xl:px-16 2xl:mb-8"
variant="sectionHeading"
>
No title provided yet
</Text>
)}
<div
className={`px-4 grid ${gridLayout} gap-x-4 gap-y-8 ${
mobileLayout === 'stacked' ? 'lg:hidden' : 'hidden'
} lg:px-8 2xl:!px-16`}
>
{blurbs.map((blurb: object | any, index: number) => {
return (
<div key={index}>
<Card
title={blurb?.title}
link={blurb?.link}
image={blurb?.image}
text={blurb?.text}
imageFormat={blurb?.imageFormat}
/>
</div>
)
})}
</div>
<div
className={`${
mobileLayout === 'stacked' ? 'hidden lg:block' : 'block'
}`}
>
{blurbs && (
<Carousel
gliderClasses={'px-4 lg:px-8 2xl:px-16'}
gliderItemWrapperClasses={''}
hasDots={true}
slidesToShow={2.2}
responsive={{
breakpoint: 1024,
settings: {
slidesToShow:
sliderLayout <= 4 ? sliderLayout + 0.5 : sliderLayout,
},
}}
>
{blurbs.map((blurb: any, index: number) => (
<CarouselItem key={`${index}`}>
<Card
title={blurb?.title}
link={blurb?.link}
image={blurb?.image}
text={blurb.text}
imageFormat={imageFormat}
/>
</CarouselItem>
))}
</Carousel>
)}
</div>
</div>
)
}
export default BlurbSection

View File

@@ -0,0 +1,2 @@
export { default } from './blurb-section';

View File

@@ -0,0 +1,60 @@
import 'glider-js/glider.min.css'
import { ArrowLeft, ArrowRight } from 'lucide-react'
import React from 'react'
import Glider from 'react-glider'
export interface CarouselItemProps {
children: React.ReactNode
className?: string
}
export const CarouselItem: React.FC<CarouselItemProps> = ({
children,
className = 'ml-2 first:ml-0 lg:ml-4'
}: CarouselItemProps) => {
return <div className={className}>{children}</div>
}
export interface CarouselProps {
children: JSX.Element | JSX.Element[] | any
gliderClasses?: string
hasArrows?: boolean
hasDots?: boolean
slidesToShow?: number
slidesToScroll?: number
responsive?: any
}
export const Carousel: React.FC<CarouselProps> = ({
children,
gliderClasses,
hasArrows = true,
hasDots = true,
slidesToShow = 1,
slidesToScroll = 1,
responsive,
}) => {
return (
<>
<Glider
className={`block relative ${gliderClasses}`}
draggable
slidesToShow={slidesToShow}
scrollLock
slidesToScroll={slidesToScroll}
hasArrows={hasArrows}
hasDots={hasDots}
iconLeft={<ArrowLeft className="stroke-current" />}
iconRight={<ArrowRight className="stroke-current" />}
responsive={[responsive]}
>
{React.Children.map(children, (child) => {
return React.cloneElement(child)
})}
</Glider>
</>
)
}

View File

@@ -0,0 +1,35 @@
'use client'
import Text from 'components/ui/text'
import dynamic from 'next/dynamic'
const ProductCard = dynamic(() => import('components/ui/product-card'))
interface SliderProps {
products: any
title: string
itemsToShow: number
}
const FilteredProductList = ({ title, products, itemsToShow }: SliderProps) => {
return (
<div className="px-4 lg:px-8 2xl:px-16">
{title ? (
<Text className="mb-4 lg:mb-6 2xl:mb-8" variant="sectionHeading">
{title}
</Text>
) : (
<Text className="italic mb-4 lg:mb-6 2xl:mb-8" variant="sectionHeading">
No title provided yet
</Text>
)}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{products.slice(0, itemsToShow).map((product: any, index: number) => (
<ProductCard key={`${product.id}-${index}`} product={product} />
))}
</div>
</div>
)
}
export default FilteredProductList

View File

@@ -0,0 +1,2 @@
export { default } from './filtered-product-list';

View File

@@ -0,0 +1,82 @@
'use client'
import dynamic from 'next/dynamic'
const SanityImage = dynamic(() => import('components/ui/sanity-image'))
const Link = dynamic(() => import('components/ui/link'))
const Text = dynamic(() => import('components/ui/text'))
interface HeroProps {
variant: string
text?: string
label?: string
title: string
image: object | any
desktopImage: object | any
link: {
title: string
reference: {
title: string
slug: {
current: string
}
}
}
}
type HeroSize = keyof typeof heroSize
const heroSize = {
fullScreen: 'aspect-[3/4] lg:aspect-auto lg:h-[calc(100vh-4rem)]',
halfScreen: 'aspect-square max-h-[60vh] lg:aspect-auto lg:min-h-[60vh]',
}
const Hero = ({ variant, title, text, label, image, link }: HeroProps) => {
const heroClass = heroSize[variant as HeroSize] || heroSize.fullScreen
return (
<div
className={`relative w-screen ${heroClass} flex flex-col justify-end relative text-high-contrast`}
>
{image && (
<SanityImage
image={image}
alt={image.alt}
priority={true}
width={1200}
height={600}
className="absolute inset-0 h-full w-full object-cover z-10"
/>
)}
<div className="flex flex-col items-start text-high-contrast absolute max-w-sm z-40 left-4 bottom-5 lg:max-w-xl lg:bottom-8 lg:left-8 2xl:left-16 2xl:bottom-16">
{label && (
<Text className="mb-1 lg:mb-2" variant="label">
{label}
</Text>
)}
{title ? (
<Text variant="heading">{title}</Text>
) : (
<Text variant="heading" className="italic">
No title provided yet
</Text>
)}
{text && (
<Text className="mt-4" variant="paragraph">
{label}
</Text>
)}
{link?.reference && (
<Link
className="inline-flex transition bg-high-contrast text-white text-base py-4 px-10 mt-6 hover:bg-low-contrast lg:mt-8"
href={link.reference.slug.current}
>
{link?.title ? link.title : link.reference.title}
</Link>
)}
</div>
</div>
)
}
export default Hero

View File

@@ -0,0 +1,2 @@
export { default } from './hero';

View File

@@ -0,0 +1,2 @@
export { default } from './slider';

View File

@@ -0,0 +1,73 @@
import {
CarouselItemProps as ItemProps,
CarouselProps as Props,
} from 'components/modules/carousel/carousel'
import Text from 'components/ui/text'
import dynamic from 'next/dynamic'
import { useEffect, useState } from 'react'
const Carousel = dynamic<Props>(() =>
import('components/modules/carousel/carousel').then((mod) => mod.Carousel)
)
const CarouselItem = dynamic<ItemProps>(() =>
import('components/modules/carousel/carousel').then((mod) => mod.CarouselItem)
)
const ProductCard = dynamic(() => import('components/ui/product-card'))
const CategoryCard = dynamic(() => import('components/ui/category-card'))
interface SliderProps {
products: [] | any
title: string
categories: [] | any
sliderType: String
}
const Slider = ({ products, categories, title, sliderType }: SliderProps) => {
const [items, setItems] = useState([])
useEffect(() => {
if (sliderType === 'products') setItems(products)
else if (sliderType === 'categories') setItems(categories)
}, [])
return (
<div className="flex flex-col">
{title ? (
<Text
className="mb-4 px-4 lg:px-8 lg:mb-6 2xl:px-16 2xl:mb-8"
variant="sectionHeading"
>
{title}
</Text>
) : (
<Text
className="italic mb-4 px-4 lg:px-8 lg:mb-6 2xl:px-16 2xl:mb-8"
variant="sectionHeading"
>
No title provided yet
</Text>
)}
{items && (
<Carousel
gliderClasses={'flex px-4 lg:px-8 2xl:px-16'}
slidesToShow={2.2}
responsive={{
breakpoint: 1024,
settings: {
slidesToShow: 4.5
},
}}
>
{items.map((item: any, index: number) => (
<CarouselItem key={`${sliderType}-${index}`}>
{sliderType === 'products' && <ProductCard product={item} />}
{sliderType === 'categories' && <CategoryCard category={item} />}
</CarouselItem>
))}
</Carousel>
)}
</div>
)
}
export default Slider