Skip to content

Commit

Permalink
More sale phase info (#88)
Browse files Browse the repository at this point in the history
* More sale phase info

* sale phase info panel

* fixes

* remove big circular progress

* fix loading

* off-topic | remove border from network selector

* lint & format

* fix build error

---------

Co-authored-by: topeth <supernathanliu@gmail.com>
  • Loading branch information
Szegoo and TopETH committed Apr 30, 2024
1 parent b2be51c commit ac47b77
Show file tree
Hide file tree
Showing 14 changed files with 340 additions and 138 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"next": "^13.3.1",
"notistack": "^3.0.1",
"react": "^18.2.0",
"react-countdown-circle-timer": "^3.2.1",
"react-dom": "^18.2.0",
"sass": "^1.48.0",
"sharp": "^0.32.6"
Expand Down
64 changes: 0 additions & 64 deletions src/components/Elements/Progress/index.tsx

This file was deleted.

11 changes: 5 additions & 6 deletions src/components/Elements/SaleInfoPanel/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto auto;
gap: 2em;
padding: 1.5em;
border-radius: .5em;
box-shadow: 0 2px 5px 2px rgba(0, 0, 0, 0.2);
grid-column-gap: 0.75rem;
grid-row-gap: 0;
margin-top: 1rem;
}

.gridItem {
color: #181336
}
color: #181336;
}
10 changes: 2 additions & 8 deletions src/components/Elements/SaleInfoPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useCoretimeApi } from '@/contexts/apis';
import { SaleInfo, SalePhase } from '@/models';

import { DetailCard } from './DetailCard';
import styles from './index.module.scss';

interface SaleInfoGridProps {
saleInfo: SaleInfo;
Expand Down Expand Up @@ -43,14 +44,7 @@ export const SaleInfoPanel = ({
};

return (
<Box
sx={{
display: 'grid',
gridTemplateColumns: 'repeat(3, 1fr)',
mt: '2rem',
gap: '1rem',
}}
>
<Box className={styles.grid}>
<DetailCard
icon={ShoppingIcon}
title='Sale details'
Expand Down
53 changes: 53 additions & 0 deletions src/components/Elements/SalePhaseInfoPanel/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.container {
display: flex;
flex-direction: column;
position: relative;
gap: 2rem;
padding: 1.5rem;
flex-grow: 1;
box-shadow: 2px 2px 55px rgba(0, 0, 0, 0.08);
}

.titleWrapper {
display: flex;
justify-content: space-between;
align-items: center;
}

.progress {
margin-left: auto;
margin-right: auto;
}

.currentPhase {
font-weight: 700;
margin: 0 auto;
}

.buttonWrapper {
padding: 0.5rem 0.75rem;
border-radius: 1rem;
font-size: 0.75rem;
font-weight: 700;
margin-left: auto;
}

.timerWrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
margin-top: 2rem;
}

.countDown {
display: flex;
gap: 0.5rem;
}

.timeElement {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
192 changes: 192 additions & 0 deletions src/components/Elements/SalePhaseInfoPanel/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import { Box, Button, Paper, Typography, useTheme } from '@mui/material';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
import { CountdownCircleTimer } from 'react-countdown-circle-timer';

import { PhaseEndpoints } from '@/hooks/salePhase';

import { SalePhase } from '@/models';

import styles from './index.module.scss';

interface SalePhaseInfoPanelProps {
currentPhase: string;
saleEndTimestamp: number;
saleStartTimestamp: number;
endpoints: PhaseEndpoints;
}

export const SalePhaseInfoPanel = ({
currentPhase,
endpoints,
}: SalePhaseInfoPanelProps) => {
const theme = useTheme();
const router = useRouter();

const onManage = () => {
router.push({
pathname: '/regions',
query: { ...router.query },
});
};
const minuteSeconds = 60;
const hourSeconds = 3600;
const daySeconds = 86400;

const [remainingTime, setRemainingTime] = useState(0);
const [daysDuration, setDaysDuration] = useState(0);

useEffect(() => {
let _remainingTime;
if (currentPhase == SalePhase.Interlude) {
_remainingTime = Math.floor(
(endpoints.interlude.end - Date.now()) / 1000
);
} else if (currentPhase == SalePhase.Leadin) {
_remainingTime = Math.floor((endpoints.leadin.end - Date.now()) / 1000);
} else if (currentPhase == SalePhase.Regular) {
_remainingTime = Math.floor((endpoints.fixed.end - Date.now()) / 1000);
} else return;

const days = Math.ceil(_remainingTime / daySeconds);
const _daysDuration = days * daySeconds;

setDaysDuration(_daysDuration);
setRemainingTime(_remainingTime);
}, [endpoints, currentPhase]);

const timerProps = {
isPlaying: true,
size: 96,
strokeWidth: 2,
};

const renderTime = (dimension: string, time: number) => {
return (
<div className={styles.timeElement}>
<Typography
sx={{
fontWeight: 700,
fontSize: '1rem',
color: theme.palette.common.black,
}}
>
{time}
</Typography>
<Typography
sx={{
fontWeight: 400,
fontSize: '0.75rem',
color: theme.palette.text.primary,
}}
>
{dimension}
</Typography>
</div>
);
};

const getTimeSeconds = (time: number) => (minuteSeconds - time) | 0;
const getTimeMinutes = (time: number) =>
((time % hourSeconds) / minuteSeconds) | 0;
const getTimeHours = (time: number) =>
((time % daySeconds) / hourSeconds) | 0;
const getTimeDays = (time: number) => (time / daySeconds) | 0;

if (remainingTime <= 0) return <></>;

return (
<Paper className={styles.container}>
<Box className={styles.titleWrapper}>
<Typography
sx={{
color: theme.palette.common.black,
fontSize: '1rem',
fontWeight: 700,
}}
>
Current Phase
</Typography>

<Button
size='small'
variant='text'
className={styles.buttonWrapper}
sx={{
background: '#e8eff7',
color: theme.palette.text.secondary,
}}
onClick={onManage}
>
Manage your regions
</Button>
</Box>
<Box className={styles.timerWrapper}>
<Typography className={styles.currentPhase}>{currentPhase}</Typography>
<Typography>Ends in:</Typography>
<Box className={styles.countDown}>
<CountdownCircleTimer
{...timerProps}
colors='#64A537'
duration={daysDuration}
initialRemainingTime={remainingTime}
>
{({ elapsedTime, color }) => (
<span style={{ color }}>
{renderTime('days', getTimeDays(daysDuration - elapsedTime))}
</span>
)}
</CountdownCircleTimer>
<CountdownCircleTimer
{...timerProps}
colors='#64A537'
duration={daySeconds}
initialRemainingTime={remainingTime % daySeconds}
onComplete={(totalElapsedTime) => ({
shouldRepeat: remainingTime - totalElapsedTime > hourSeconds,
})}
>
{({ elapsedTime, color }) => (
<span style={{ color }}>
{renderTime('hours', getTimeHours(daySeconds - elapsedTime))}
</span>
)}
</CountdownCircleTimer>
<CountdownCircleTimer
{...timerProps}
colors='#64A537'
duration={hourSeconds}
initialRemainingTime={remainingTime % hourSeconds}
onComplete={(totalElapsedTime) => ({
shouldRepeat: remainingTime - totalElapsedTime > minuteSeconds,
})}
>
{({ elapsedTime, color }) => (
<span style={{ color }}>
{renderTime(
'minutes',
getTimeMinutes(hourSeconds - elapsedTime)
)}
</span>
)}
</CountdownCircleTimer>
<CountdownCircleTimer
{...timerProps}
colors='#64A537'
duration={minuteSeconds}
initialRemainingTime={remainingTime % minuteSeconds}
onComplete={(totalElapsedTime) => ({
shouldRepeat: remainingTime - totalElapsedTime > 0,
})}
>
{({ elapsedTime, color }) => (
<span style={{ color }}>
{renderTime('seconds', getTimeSeconds(elapsedTime))}
</span>
)}
</CountdownCircleTimer>
</Box>
</Box>
</Paper>
);
};
Loading

0 comments on commit ac47b77

Please sign in to comment.