Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import {
ResponsiveContainer,
BarChart,
Expand Down Expand Up @@ -37,13 +37,54 @@ export default function CustomBarChart<T>({
yAxisDomain,
yAxisTicks,
xTickFormatter,
yTickFormatter,
tooltipLabelFormatter,
tooltipValuesFormatter,
}: React.PropsWithChildren<BarChartProps<T>>) {
const theme = useTheme();
const isPhoneOrAbove = useMediaQuery({ query: queryPhone });
const [activeIndex, setActiveIndex] = useState<number | null>(null);

const yAxisNumberFormatter = useMemo(
() => new Intl.NumberFormat('en-US', { maximumSignificantDigits: 6 }),
[]
);

const getYAxisLabel = useCallback(
(value: number, index: number) => {
if (yTickFormatter) return yTickFormatter(value, index);
const abbreviated = formatNumberAbbreviated(value);
if (abbreviated.thousandsSuffix) {
return `$${abbreviated.string}`;
}
return `$${yAxisNumberFormatter.format(value)}`;
},
[yTickFormatter, yAxisNumberFormatter]
);

const yAxisWidth = useMemo(() => {
const values =
yAxisTicks && yAxisTicks.length
? yAxisTicks
: chartData.map((entry) => Number(entry[yDataKey] ?? 0));
let maxLength = 0;

values.forEach((value, index) => {
const numericValue = typeof value === 'number' ? value : Number(value);
if (Number.isNaN(numericValue)) return;
const label = getYAxisLabel(numericValue, index);
maxLength = Math.max(maxLength, label.length);
});

const estimatedCharWidth = isPhoneOrAbove ? 7 : 6;
const padding = isPhoneOrAbove ? 22 : 16;
const maxWidth = isPhoneOrAbove ? 220 : 160;
return Math.min(
maxWidth,
Math.max(60, maxLength * estimatedCharWidth + padding)
);
}, [chartData, yAxisTicks, yDataKey, getYAxisLabel, isPhoneOrAbove]);

const barColors = [
'#FFE3D4',
'#DCD28B',
Expand Down Expand Up @@ -145,8 +186,8 @@ export default function CustomBarChart<T>({
ticks={yAxisTicks}
axisLine={false}
tickLine={false}
tick={({ x, y, payload }) => {
const { string } = formatNumberAbbreviated(payload.value);
width={yAxisWidth}
tick={({ x, y, payload, index }) => {
return (
<text
key={`y-axis-tick-${payload.value}`}
Expand All @@ -164,7 +205,7 @@ export default function CustomBarChart<T>({
}}
>
<tspan x={x} dy={0}>
{`$${string}`}
{getYAxisLabel(payload.value, index)}
</tspan>
</text>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useSpiceAuctionCountdown } from 'hooks/spicebazaar/use-spice-auction-countdown';
import { SpiceAuctionInfo } from 'providers/SpiceAuctionProvider';
import styled from 'styled-components';
import { AuctionState } from 'utils/spice-auction-state';

const AuctionTimeStamp = styled.div`
font-size: 13px;
Expand All @@ -18,19 +19,38 @@ const ScheduledText = styled.p`
margin: 0px;
`;

const EndedText = styled.p`
font-size: 13px;
font-weight: 700;
line-height: 15px;
color: ${({ theme }) => theme.palette.brand};
margin: 0px;
`;

interface AuctionCountdownProps {
auction: SpiceAuctionInfo;
isLive: boolean;
}

export const AuctionCountdown = ({
auction,
isLive,
}: AuctionCountdownProps) => {
const countdown = useSpiceAuctionCountdown(auction);
return isLive ? (
<AuctionTimeStamp>Ends in {countdown}</AuctionTimeStamp>
) : (
<ScheduledText>Starts in {countdown}</ScheduledText>
);
const formatEndDate = (date: Date | null): string => {
if (!date) return '';
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0');
const year = date.getFullYear();
return `${day}/${month}/${year}`;
};

export const AuctionCountdown = ({ auction }: AuctionCountdownProps) => {
const { countdown, state, endDate } = useSpiceAuctionCountdown(auction);

switch (state) {
case AuctionState.LIVE:
return <AuctionTimeStamp>Ends in {countdown}</AuctionTimeStamp>;
case AuctionState.SCHEDULED:
return <ScheduledText>Starts in {countdown}</ScheduledText>;
case AuctionState.ENDED:
return <EndedText>on {formatEndDate(endDate)}</EndedText>;
case AuctionState.NOT_SCHEDULED:
default:
return <ScheduledText>Starts in TBD</ScheduledText>;
}
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import {
ResponsiveContainer,
BarChart,
Expand Down Expand Up @@ -37,12 +37,52 @@ export default function CustomBarChart<T>({
yAxisDomain,
yAxisTicks,
xTickFormatter,
yTickFormatter,
tooltipLabelFormatter,
tooltipValuesFormatter,
}: React.PropsWithChildren<BarChartProps<T>>) {
const theme = useTheme();
const isPhoneOrAbove = useMediaQuery({ query: queryPhone });
const [activeIndex, setActiveIndex] = useState<number | null>(null);
const yAxisNumberFormatter = useMemo(
() => new Intl.NumberFormat('en-US', { maximumSignificantDigits: 6 }),
[]
);

const getYAxisLabel = useCallback(
(value: number, index: number) => {
if (yTickFormatter) return yTickFormatter(value, index);
const abbreviated = formatNumberAbbreviated(value);
if (abbreviated.thousandsSuffix) {
return `${abbreviated.string} TGLD`;
}
return `${yAxisNumberFormatter.format(value)} TGLD`;
},
[yTickFormatter, yAxisNumberFormatter]
);

const yAxisWidth = useMemo(() => {
const values =
yAxisTicks && yAxisTicks.length
? yAxisTicks
: chartData.map((entry) => Number(entry[yDataKey] ?? 0));
let maxLength = 0;

values.forEach((value, index) => {
const numericValue = typeof value === 'number' ? value : Number(value);
if (Number.isNaN(numericValue)) return;
const label = getYAxisLabel(numericValue, index);
maxLength = Math.max(maxLength, label.length);
});

const estimatedChartWidth = isPhoneOrAbove ? 7 : 6;
const padding = isPhoneOrAbove ? 22 : 16;
const maxWidth = isPhoneOrAbove ? 220 : 160;
return Math.min(
maxWidth,
Math.max(60, maxLength * estimatedChartWidth + padding)
);
}, [chartData, yAxisTicks, yDataKey, getYAxisLabel, isPhoneOrAbove]);

const barColors = [
'#FFE3D4',
Expand Down Expand Up @@ -122,8 +162,9 @@ export default function CustomBarChart<T>({
ticks={yAxisTicks}
axisLine={false}
tickLine={false}
tick={({ x, y, payload }) => {
const { string } = formatNumberAbbreviated(payload.value);
width={yAxisWidth}
tick={({ x, y, payload, index }) => {
const label = getYAxisLabel(payload.value, index);
return (
<text
key={`y-axis-tick-${payload.value}`}
Expand All @@ -141,7 +182,7 @@ export default function CustomBarChart<T>({
}}
>
<tspan x={x} dy={0}>
{`${string} TGLD`}
{label}
</tspan>
</text>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import active from 'assets/icons/active.svg?react';
import scheduled from 'assets/icons/scheduled.svg?react';
import closed from 'assets/icons/closed.svg?react';
import linkSvg from 'assets/icons/link.svg?react';
import { AuctionState, getAuctionState } from 'utils/spice-auction-state';
import styled from 'styled-components';
import { useEffect, useState, useMemo } from 'react';
import { Button } from 'components/Button/Button';
Expand Down Expand Up @@ -111,7 +113,7 @@ export const Details = () => {
query: queryPhone,
});

const countdown = useSpiceAuctionCountdown(auction || null);
const { state } = useSpiceAuctionCountdown(auction || null);

const formatDate = (timestamp: number | undefined) => {
if (!timestamp) return 'DD/MM/YYYY';
Expand Down Expand Up @@ -201,14 +203,17 @@ export const Details = () => {
<Loader iconSize={32} />
) : (
<>
<StatusBadge
isLive={!!auction?.currentEpochAuctionLive}
>
{auction?.currentEpochAuctionLive ? (
<StatusBadge state={state}>
{state === AuctionState.LIVE ? (
<>
<Active />
ACTIVE
</>
) : state === AuctionState.ENDED ? (
<>
<Closed />
ENDED
</>
) : (
<>
<Scheduled />
Expand All @@ -219,7 +224,8 @@ export const Details = () => {
<TimestampContainer>
<TimeStampRow>
<TimeStampLabel>Start</TimeStampLabel>
{auction?.currentEpochAuctionLive ? (
{state === AuctionState.LIVE ||
state === AuctionState.ENDED ? (
<>
<TimeStampDate>
{formatDate(auction?.auctionStartTime)}
Expand Down Expand Up @@ -250,7 +256,8 @@ export const Details = () => {
</TimeStampRow>
<TimeStampRow>
<TimeStampLabel>End</TimeStampLabel>
{auction?.currentEpochAuctionLive ? (
{state === AuctionState.LIVE ||
state === AuctionState.ENDED ? (
<>
<TimeStampDate>
{formatDate(auction?.auctionEndTime)}
Expand Down Expand Up @@ -524,14 +531,27 @@ const HeaderRight = styled.div`
`)}
`;

const StatusBadge = styled.div<{ isLive: boolean }>`
const getStatusBadgeBorderColor = (state: AuctionState): string => {
switch (state) {
case AuctionState.LIVE:
return '#588f22';
case AuctionState.ENDED:
return '#6B7280';
case AuctionState.SCHEDULED:
case AuctionState.NOT_SCHEDULED:
default:
return '#EAB85B';
}
};

const StatusBadge = styled.div<{ state: AuctionState }>`
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
background: ${({ theme }) => theme.palette.black};
border: solid 1px;
border-color: ${({ isLive }) => (isLive ? '#588f22' : '#EAB85B')};
border-color: ${({ state }) => getStatusBadgeBorderColor(state)};
border-radius: 10px;
padding: 8px 24px;
gap: 10px;
Expand Down Expand Up @@ -589,6 +609,8 @@ const Active = styled(active)``;

const Scheduled = styled(scheduled)``;

const Closed = styled(closed)``;

const CurrentEpochNr = styled.h3`
display: flex;
justify-content: center;
Expand Down
Loading
Loading