Skip to content

Commit

Permalink
feat: Add a Slots feed section to Landing (basic slot index only). Ad…
Browse files Browse the repository at this point in the history
…d a useSlotsFeed hook. (#1173)

Co-authored-by: Begoña Álvarez de la Cruz <[email protected]>
  • Loading branch information
msarcev and begonaalvarezd authored Feb 23, 2024
1 parent 1e8b18d commit 44b713b
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 49 deletions.
45 changes: 7 additions & 38 deletions client/src/app/components/nova/landing/LandingEpochSection.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@
background-color: $gray-1;
border-radius: 8px;

.epoch-section__header {
width: fit-content;
margin: 0 auto;
padding: 20px;
}

.epoch-progress__wrapper {
display: flow-root;
background-color: $gray-3;
margin: 20px;
margin: 0 20px 20px;
border-radius: 8px;

.epoch-progress__header {
width: fit-content;
margin: 0 auto;
padding: 20px;
}

.epoch-progress__stats-wrapper {
display: flex;
padding: 12px;
Expand All @@ -33,37 +33,6 @@
text-align: center;
}
}

.progress-bar__wrapper {
$bar-height: 32px;

.progress-bar {
position: relative;
background-color: $gray-5;
margin: 20px 12px;
height: $bar-height;
border-radius: 4px;
text-align: center;
overflow: hidden;

.progress-bar__label {
position: absolute;
left: 0;
right: 0;
line-height: $bar-height;
margin: 0 auto;
font-weight: 600;
}

.progress-bar__fill {
position: absolute;
width: 100%;
height: 100%;
background-color: #36c636;
transform: translateX(-100%);
}
}
}
}

.epoch-section__controls {
Expand Down
14 changes: 3 additions & 11 deletions client/src/app/components/nova/landing/LandingEpochSection.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import moment from "moment";
import React from "react";
import { useCurrentEpochProgress } from "~/helpers/nova/hooks/useCurrentEpochProgress";
import ProgressBar from "./ProgressBar";
import "./LandingEpochSection.scss";

const LandingEpochSection: React.FC = () => {
Expand Down Expand Up @@ -29,8 +30,8 @@ const LandingEpochSection: React.FC = () => {

return (
<div className="epoch-section">
<h2 className="epoch-section__header">Epoch {epochIndex} Progress</h2>
<div className="epoch-progress__wrapper">
<h2 className="epoch-progress__header">Epoch {epochIndex} Progress</h2>
<div className="epoch-progress__stats-wrapper">
<div className="epoch-progress__stat">Registration end: {registrationTimeRemaining}</div>
<div className="epoch-progress__stat">Time remaining: {epochTimeRemaining}</div>
Expand All @@ -40,7 +41,7 @@ const LandingEpochSection: React.FC = () => {
{epochTo}
</div>
</div>
<ProgressBar progress={epochProgressPercent} />
<ProgressBar progress={epochProgressPercent} showLabel />
</div>
<div className="epoch-section__controls">
<div className="epoch-section__button">previous</div>
Expand All @@ -51,13 +52,4 @@ const LandingEpochSection: React.FC = () => {
);
};

const ProgressBar: React.FC<{ progress: number }> = ({ progress }) => (
<div className="progress-bar__wrapper">
<div className="progress-bar">
<div className="progress-bar__fill" style={{ transform: `translateX(-${100 - progress}%)` }}></div>
<div className="progress-bar__label">{progress}%</div>
</div>
</div>
);

export default LandingEpochSection;
37 changes: 37 additions & 0 deletions client/src/app/components/nova/landing/LandingSlotSection.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@import "../../../../scss/variables";
@import "../../../../scss/fonts";

.slots-section {
font-family: $metropolis;
margin-top: 40px;
background-color: $gray-1;
border-radius: 8px;

.slots-section__header {
width: fit-content;
margin: 0 auto;
padding: 20px;
}

.slots-feed__wrapper {
margin: 0 20px 20px;

.slots-feed__item {
display: flex;
margin: 0px 12px;
align-items: center;
line-height: 32px;
justify-content: center;
background-color: $gray-5;
border-radius: 4px;

&.transparent {
background-color: transparent;
}

&:not(:last-child) {
margin-bottom: 20px;
}
}
}
}
30 changes: 30 additions & 0 deletions client/src/app/components/nova/landing/LandingSlotSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import useSlotsFeed from "~/helpers/nova/hooks/useSlotsFeed";
import "./LandingSlotSection.scss";
import ProgressBar from "./ProgressBar";

const LandingSlotSection: React.FC = () => {
const { currentSlot, currentSlotProgressPercent, latestSlots } = useSlotsFeed();

if (currentSlot === null || currentSlotProgressPercent === null) {
return null;
}

return (
<div className="slots-section">
<h2 className="slots-section__header">Latest Slots</h2>
<div className="slots-feed__wrapper">
<ProgressBar progress={currentSlotProgressPercent} showLabel={false}>
<div className="slots-feed__item transparent">{currentSlot}</div>
</ProgressBar>
{latestSlots?.map((slot) => (
<div key={`slot-key-${slot}`} className="slots-feed__item">
{slot}
</div>
))}
</div>
</div>
);
};

export default LandingSlotSection;
40 changes: 40 additions & 0 deletions client/src/app/components/nova/landing/ProgressBar.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
@import "../../../../scss/variables";

.progress-bar__wrapper {
$bar-height: 32px;

.progress-bar {
position: relative;
background-color: $gray-5;
margin: 20px 12px;
height: $bar-height;
border-radius: 4px;
text-align: center;
overflow: hidden;

.progress-bar__label {
position: absolute;
left: 0;
right: 0;
line-height: $bar-height;
margin: 0 auto;
font-weight: 600;
}

.progress-bar__children {
position: absolute;
left: 0;
right: 0;
line-height: $bar-height;
margin: 0 auto;
}

.progress-bar__fill {
position: absolute;
width: 100%;
height: 100%;
background-color: #36c636;
transform: translateX(-100%);
}
}
}
20 changes: 20 additions & 0 deletions client/src/app/components/nova/landing/ProgressBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";
import "./ProgressBar.scss";

interface ProgressBarProps {
progress: number;
showLabel: boolean;
children?: React.ReactNode | React.ReactElement;
}

const ProgressBar: React.FC<ProgressBarProps> = ({ progress, showLabel, children }) => (
<div className="progress-bar__wrapper">
<div className="progress-bar">
<div className="progress-bar__fill" style={{ transform: `translateX(-${100 - progress}%)` }} />
{showLabel && <div className="progress-bar__label">{progress}%</div>}
{children && <div className="progress-bar__children">{children}</div>}
</div>
</div>
);

export default ProgressBar;
2 changes: 2 additions & 0 deletions client/src/app/routes/nova/landing/Landing.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { RouteComponentProps } from "react-router-dom";
import LandingEpochSection from "~/app/components/nova/landing/LandingEpochSection";
import LandingSlotSection from "~/app/components/nova/landing/LandingSlotSection";
import { useNetworkConfig } from "~helpers/hooks/useNetworkConfig";
import { LandingRouteProps } from "../../LandingRouteProps";
import "./Landing.scss";
Expand Down Expand Up @@ -29,6 +30,7 @@ const Landing: React.FC<RouteComponentProps<LandingRouteProps>> = ({
<div className="wrapper">
<div className="inner">
<LandingEpochSection />
<LandingSlotSection />
</div>
</div>
</div>
Expand Down
53 changes: 53 additions & 0 deletions client/src/helpers/nova/hooks/useSlotsFeed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import moment from "moment";
import { useEffect, useState } from "react";
import { useNovaTimeConvert } from "./useNovaTimeConvert";

const DEFAULT_SLOT_LIMIT = 10;

export default function useSlotsFeed(slotsLimit: number = DEFAULT_SLOT_LIMIT): {
currentSlot: number | null;
currentSlotProgressPercent: number | null;
latestSlots: number[] | null;
} {
const { unixTimestampToSlotIndex, slotIndexToUnixTimeRange } = useNovaTimeConvert();
const [currentSlot, setCurrentSlot] = useState<number | null>(null);
const [latestSlots, setLatestSlots] = useState<number[] | null>(null);
const [currentSlotProgressPercent, setCurrentSlotProgressPercent] = useState<number | null>(null);
const [slotTimeUpdateHandle, setSlotTimeUpdateHandle] = useState<NodeJS.Timeout | null>(null);

const checkCurrentSlot = () => {
if (unixTimestampToSlotIndex && slotIndexToUnixTimeRange) {
const now = moment().unix();
const currentSlotIndex = unixTimestampToSlotIndex(now);
const slotTimeRange = slotIndexToUnixTimeRange(currentSlotIndex);

const slotProgressPercent = Math.trunc(((now - slotTimeRange.from) / (slotTimeRange.to - 1 - slotTimeRange.from)) * 100);
setCurrentSlot(currentSlotIndex);
setCurrentSlotProgressPercent(slotProgressPercent);
setLatestSlots(Array.from({ length: slotsLimit - 1 }, (_, i) => currentSlotIndex - 1 - i));
}
};

useEffect(() => {
if (slotTimeUpdateHandle === null) {
checkCurrentSlot();
const intervalTimerHandle = setInterval(() => {
checkCurrentSlot();
}, 950);

setSlotTimeUpdateHandle(intervalTimerHandle);
}

return () => {
if (slotTimeUpdateHandle) {
clearInterval(slotTimeUpdateHandle);
}
setSlotTimeUpdateHandle(null);
setCurrentSlot(null);
setCurrentSlotProgressPercent(null);
setLatestSlots(null);
};
}, []);

return { currentSlot, currentSlotProgressPercent, latestSlots };
}

0 comments on commit 44b713b

Please sign in to comment.