Skip to content

Commit

Permalink
Merge pull request #52 from Weaverse/feature/add-count-down-section
Browse files Browse the repository at this point in the history
Add count down section
  • Loading branch information
hta218 committed Nov 24, 2023
2 parents ecf95f8 + 43aaad7 commit ef60233
Show file tree
Hide file tree
Showing 5 changed files with 402 additions and 0 deletions.
49 changes: 49 additions & 0 deletions app/sections/count-down/heading-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type {
HydrogenComponentProps,
HydrogenComponentSchema,
} from '@weaverse/hydrogen';
import { forwardRef, CSSProperties } from 'react';


interface CountDownHeadingProps extends HydrogenComponentProps {
heading: string;
textColor: string;
}

let CountDownHeading = forwardRef<HTMLDivElement, CountDownHeadingProps>((props, ref) => {
let { heading, textColor, ...rest } = props;
let headingStyle: CSSProperties = {
'--heading-text-color': textColor,
} as CSSProperties;
return (
<div ref={ref} {...rest} style={headingStyle}>
{heading && <h3 className='font-medium text-[var(--heading-text-color)]'>{heading}</h3>}
</div>
);
});

export default CountDownHeading;

export let schema: HydrogenComponentSchema = {
type: 'count-down--heading',
title: 'Heading',
inspector: [
{
group: 'Heading',
inputs: [
{
type: 'text',
name: 'heading',
label: 'Heading',
defaultValue: 'Countdown heading',
},
{
type: 'color',
name: 'textColor',
label: 'Color',
defaultValue: '#000000',
}
],
},
],
};
175 changes: 175 additions & 0 deletions app/sections/count-down/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import type {
HydrogenComponentProps,
HydrogenComponentSchema,
WeaverseImage,
} from '@weaverse/hydrogen';
import { forwardRef, CSSProperties } from 'react';
import clsx from 'clsx';
import { Image } from '@shopify/hydrogen';


interface CountDownProps extends HydrogenComponentProps {
backgroundColor: string;
backgroundImage: WeaverseImage;
overlayColor: string;
overlayOpacity: number;
buttonLabel1: string;
buttonLink1: string;
buttonLabel2: string;
buttonLink2: string;
enableNewtab: boolean;
buttonStyle1: string;
buttonStyle2: string;
sectionHeight: number;
}

let Countdown = forwardRef<HTMLElement, CountDownProps>((props, ref) => {
let { backgroundColor, backgroundImage, overlayColor, overlayOpacity, buttonLabel1, buttonLink1, buttonLabel2, buttonLink2, enableNewtab, buttonStyle1, buttonStyle2, sectionHeight, children, ...rest } = props;
let sectionStyle: CSSProperties = {
'--section-height': `${sectionHeight}px`,
'--section-background-color': backgroundColor,
'--overlay-color': overlayColor,
'--overlay-opacity': `${overlayOpacity}%`,
} as CSSProperties;

return (
<section ref={ref} {...rest} className='flex relative items-center justify-center text-center px-10 py-16 w-full sm-max:px-4 h-[var(--section-height)]' style={sectionStyle}>
<div className='absolute inset-0 bg-[var(--section-background-color)]'>
{backgroundImage && <Image data={backgroundImage} className='w-full h-full object-cover' />}
{backgroundImage && <div className='absolute inset-0 bg-[var(--overlay-color)] opacity-[var(--overlay-opacity)]'></div>}
</div>
<div className='flex flex-col gap-3 items-center w-5/6 sm-max:w-full z-10'>
{children}
<div className='flex gap-3 mt-3'>
{buttonLabel1 && <a className={clsx('py-3 px-4 cursor-pointer rounded', buttonStyle1)} href={buttonLink1} target={enableNewtab ? '_blank' : ''}>{buttonLabel1}</a>}
{buttonLabel2 && <a className={clsx('py-3 px-4 cursor-pointer rounded', buttonStyle2)} href={buttonLink2} target={enableNewtab ? '_blank' : ''}>{buttonLabel2}</a>}
</div>
</div>
</section>
);
});

export default Countdown;

export let schema: HydrogenComponentSchema = {
type: 'count-down',
title: 'Count down',
toolbar: ['general-settings', ['duplicate', 'delete']],
inspector: [
{
group: 'Countdown',
inputs: [
{
type: 'color',
name: 'backgroundColor',
label: 'Background color',
defaultValue: '#ffffff',
},
{
type: 'image',
name: 'backgroundImage',
label: 'Background image',
},
{
type: 'color',
name: 'overlayColor',
label: 'Overlay color',
},
{
type: 'range',
name: 'overlayOpacity',
label: 'Overlay opacity',
defaultValue: 50,
configs: {
min: 10,
max: 100,
step: 10,
unit: '%',
},
},
{
type: 'text',
name: 'buttonLabel1',
label: 'Button #1 label',
defaultValue: 'Shop this',
},
{
type: 'text',
name: 'buttonLink1',
label: 'Button #1 link',
placeholder: 'https://',
},
{
type: 'text',
name: 'buttonLabel2',
label: 'Button #2 label',
defaultValue: 'Shop all',
},
{
type: 'text',
name: 'buttonLink2',
label: 'Button #2 link',
placeholder: 'https://',
},
{
type: 'switch',
name: 'enableNewtab',
label: 'Open in new tab',
defaultValue: true,
},
{
type: 'toggle-group',
label: 'Button #1 style',
name: 'buttonStyle1',
configs: {
options: [
{ label: '1', value: 'transition hover:bg-white border-2 border-solid hover:border-gray-900 hover:text-black bg-black text-white' },
{ label: '2', value: 'transition bg-white border-2 border-solid border-gray-900 text-black hover:bg-black hover:text-white' },
{ label: '3', value: 'transition hover:bg-white border-2 border-solid border-white hover:text-black bg-gray-200 text-white' },
],
},
defaultValue: 'transition bg-white border-2 border-solid border-gray-900 text-black hover:bg-black hover:text-white',
},
{
type: 'toggle-group',
label: 'Button #2 style',
name: 'buttonStyle2',
configs: {
options: [
{ label: '1', value: 'transition hover:bg-white border-2 border-solid hover:border-gray-900 hover:text-black bg-black text-white' },
{ label: '2', value: 'transition bg-white border-2 border-solid border-gray-900 text-black hover:bg-black hover:text-white' },
{ label: '3', value: 'transition hover:bg-white border-2 border-solid border-white hover:text-black bg-gray-200 text-white' },
],
},
defaultValue: 'transition bg-white border-2 border-solid border-gray-900 text-black hover:bg-black hover:text-white',
},
{
type: 'range',
name: 'sectionHeight',
label: 'Section height',
defaultValue: 450,
configs: {
min: 400,
max: 700,
step: 10,
unit: 'px',
},
},
],
},
],
childTypes: ['count-down--heading', 'count-down--subheading', 'count-down--timer'],
presets: {
children: [
{
type: 'count-down--heading',
},
{
type: 'count-down--subheading',
},
{
type: 'count-down--timer',
},
],
},
};
66 changes: 66 additions & 0 deletions app/sections/count-down/subheading-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type {
HydrogenComponentProps,
HydrogenComponentSchema,
} from '@weaverse/hydrogen';
import { forwardRef, CSSProperties } from 'react';


interface CountDownSubheadingProps extends HydrogenComponentProps {
subHeading: string;
textColor: string;
subHeadingSize: string;
}

let CountDownSubheading = forwardRef<HTMLDivElement, CountDownSubheadingProps>((props, ref) => {
let { subHeading, subHeadingSize, textColor, ...rest } = props;
let subHeadingStyle: CSSProperties = {
'--subheading-text-color': textColor,
fontSize: subHeadingSize,
} as CSSProperties;
return (
<div ref={ref} {...rest}>
{subHeading && <p className='font-normal text-base text-[var(--subheading-text-color)]' style={subHeadingStyle}>{subHeading}</p>}
</div>
);
});

export default CountDownSubheading;

export let schema: HydrogenComponentSchema = {
type: 'count-down--subheading',
title: 'Subheading',
inspector: [
{
group: 'Subheading',
inputs: [
{
type: 'text',
name: 'subHeading',
label: 'Subheading',
defaultValue: 'Countdown to our upcoming event',
},
{
type: 'toggle-group',
label: 'Subheading size',
name: 'subHeadingSize',
configs: {
options: [
{ label: 'XS', value: '14px' },
{ label: 'S', value: '16px' },
{ label: 'M', value: '18px' },
{ label: 'L', value: '20px' },
{ label: 'XL', value: '22px' },
],
},
defaultValue: '16px',
},
{
type: 'color',
name: 'textColor',
label: 'Color',
defaultValue: '#000000',
}
],
},
],
};
104 changes: 104 additions & 0 deletions app/sections/count-down/timer-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import type {
HydrogenComponentProps,
HydrogenComponentSchema,
} from '@weaverse/hydrogen';
import { useState, useEffect, forwardRef, CSSProperties } from 'react';

interface CountDownTimerProps extends HydrogenComponentProps {
textColor: string;
startDate: number;
}

let CountDownTimer = forwardRef<HTMLDivElement, CountDownTimerProps>((props, ref) => {
let { textColor, startDate, ...rest } = props;
const [timeRemaining, setTimeRemaining] = useState(calculateTimeRemaining(startDate));
useEffect(() => {
const intervalId = setInterval(() => {
const updatedTimeRemaining = calculateTimeRemaining(startDate);
setTimeRemaining(updatedTimeRemaining);
if (updatedTimeRemaining.days <= 0 && updatedTimeRemaining.hours <= 0 &&
updatedTimeRemaining.minutes <= 0 && updatedTimeRemaining.seconds <= 0) {
clearInterval(intervalId);
}
}, 1000);
return () => clearInterval(intervalId);
}, [startDate]);

function calculateTimeRemaining(startTime: number) {
const now = new Date().getTime();
const difference = startTime - now;
if (difference <= 0) {
return {
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
};
}

const days = Math.floor(difference / (1000 * 60 * 60 * 24));
const hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((difference % (1000 * 60)) / 1000);
return {
days,
hours,
minutes,
seconds,
};
}

let timerStyle: CSSProperties = {
'--timer-text-color': textColor,
} as CSSProperties;

return (
<div ref={ref} {...rest} className='flex justify-center gap-5 text-[var(--timer-text-color)] sm-max:gap-2' style={timerStyle}>
<div className=''>
<p className='text-5xl font-medium leading-tight sm-max:text-4xl'>{timeRemaining?.days || 0}</p>
<p className='text-base font-normal sm-max:text-sm'>DAYS</p>
</div>
<div className='bg-black w-px h-7 mt-4 sm-max:mt-2' />
<div className=''>
<p className='text-5xl font-medium leading-tight sm-max:text-4xl'>{timeRemaining?.hours || 0}</p>
<p className='text-base font-normal sm-max:text-sm'>HOURS</p>
</div>
<div className='bg-black w-px h-7 mt-4 sm-max:mt-2' />
<div className=''>
<p className='text-5xl font-medium leading-tight sm-max:text-4xl'>{timeRemaining?.minutes || 0}</p>
<p className='text-base font-normal sm-max:text-sm'>MINUTES</p>
</div>
<div className='bg-black w-px h-7 mt-4 sm-max:mt-2' />
<div className=''>
<p className='text-5xl font-medium leading-tight sm-max:text-4xl'>{timeRemaining?.seconds || 0}</p>
<p className='text-base font-normal sm-max:text-sm'>SECONDS</p>
</div>
</div>
);
});

export default CountDownTimer;

export let schema: HydrogenComponentSchema = {
type: 'count-down--timer',
title: 'Timer',
inspector: [
{
group: 'Timer',
inputs: [
{
type: 'color',
name: 'textColor',
label: 'Color',
defaultValue: '#000000',
},
{
type: "datepicker",
label: "Start date",
name: "startDate",
defaultValue: "2024-01-01"
}
],
},
],
};
Loading

0 comments on commit ef60233

Please sign in to comment.