-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: Add Epoch section on Landing (#1135)
* feat: Add more util functions in novaTimeUtils. Fix novaTimeUtils to be aliged with the go implementation (https://github.com/iotaledger/iota.go/blob/develop/timeprovider.go) * feat: Add nova Landing page. Add mock "epoch section" to landing (WiP) * feat: Add utils to get the registration slotIndex from an epoch index * feat: Wire up epoch stats in LandingEpochSection --------- Co-authored-by: Begoña Álvarez de la Cruz <[email protected]>
- Loading branch information
1 parent
c4667fb
commit c168157
Showing
9 changed files
with
490 additions
and
10 deletions.
There are no files selected for viewing
81 changes: 81 additions & 0 deletions
81
client/src/app/components/nova/landing/LandingEpochSection.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
@import "../../../../scss/variables"; | ||
@import "../../../../scss/fonts"; | ||
|
||
.epoch-section { | ||
font-family: $metropolis; | ||
margin-top: 40px; | ||
background-color: $gray-1; | ||
border-radius: 8px; | ||
|
||
.epoch-progress__wrapper { | ||
display: flow-root; | ||
background-color: $gray-3; | ||
margin: 20px; | ||
border-radius: 8px; | ||
|
||
.epoch-progress__header { | ||
width: fit-content; | ||
margin: 0 auto; | ||
padding: 20px; | ||
} | ||
|
||
.epoch-progress__stats-wrapper { | ||
display: flex; | ||
padding: 12px; | ||
flex-direction: row; | ||
justify-content: space-evenly; | ||
|
||
.epoch-progress__stat { | ||
width: 160px; | ||
background-color: $gray-4; | ||
padding: 10px 20px; | ||
border-radius: 8px; | ||
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 { | ||
display: flex; | ||
margin: 20px; | ||
flex-direction: row; | ||
justify-content: space-between; | ||
|
||
.epoch-section__button { | ||
background-color: $gray-4; | ||
padding: 10px 20px; | ||
border-radius: 8px; | ||
} | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
client/src/app/components/nova/landing/LandingEpochSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import moment from "moment"; | ||
import React from "react"; | ||
import { useCurrentEpochProgress } from "~/helpers/nova/hooks/useCurrentEpochProgress"; | ||
import "./LandingEpochSection.scss"; | ||
|
||
const LandingEpochSection: React.FC = () => { | ||
const { epochIndex, epochUnixTimeRange, epochProgressPercent, registrationTime } = useCurrentEpochProgress(); | ||
|
||
if (epochIndex === null || epochProgressPercent === null) { | ||
return null; | ||
} | ||
|
||
let registrationTimeRemaining = "???"; | ||
let epochTimeRemaining = "???"; | ||
let epochFrom = "???"; | ||
let epochTo = "???"; | ||
|
||
if (epochUnixTimeRange && registrationTime) { | ||
const epochStartTime = moment.unix(epochUnixTimeRange.from); | ||
const epochEndTime = moment.unix(epochUnixTimeRange.to - 1); | ||
epochFrom = epochStartTime.format("DD MMM HH:mm:ss"); | ||
epochTo = epochEndTime.format("DD MMM HH:mm:ss"); | ||
|
||
const diffToEpochEnd = epochEndTime.diff(moment()); | ||
epochTimeRemaining = moment(diffToEpochEnd).format("H:mm:ss"); | ||
|
||
registrationTimeRemaining = moment.unix(registrationTime).fromNow(); | ||
} | ||
|
||
return ( | ||
<div className="epoch-section"> | ||
<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> | ||
<div className="epoch-progress__stat"> | ||
{epochFrom} | ||
<br /> | ||
{epochTo} | ||
</div> | ||
</div> | ||
<ProgressBar progress={epochProgressPercent} /> | ||
</div> | ||
<div className="epoch-section__controls"> | ||
<div className="epoch-section__button">previous</div> | ||
<div className="epoch-section__button">view more</div> | ||
<div className="epoch-section__button">next</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
@import "../../../../scss/fonts"; | ||
@import "../../../../scss/mixins"; | ||
@import "../../../../scss/media-queries"; | ||
@import "../../../../scss/variables"; | ||
@import "../../../../scss/themes"; | ||
|
||
.landing-nova { | ||
display: flex; | ||
flex-direction: column; | ||
|
||
.header-wrapper { | ||
position: relative; | ||
z-index: 0; | ||
overflow: hidden; | ||
background: var(--header-bg); | ||
|
||
.inner { | ||
position: relative; | ||
display: flex; | ||
justify-content: center; | ||
flex: 1; | ||
|
||
.header { | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
width: 100%; | ||
min-height: 400px; | ||
|
||
@include desktop-down { | ||
justify-content: start; | ||
} | ||
|
||
@include tablet-down { | ||
justify-content: center; | ||
} | ||
|
||
.header--title { | ||
text-align: center; | ||
|
||
@include desktop-down { | ||
margin: 0; | ||
margin-bottom: 28px; | ||
margin-left: 160px; | ||
} | ||
|
||
@include tablet-down { | ||
margin-bottom: 172px; | ||
margin-left: 0px; | ||
} | ||
|
||
h1 { | ||
@include font-size(48px, 58px); | ||
|
||
font-family: $metropolis-semi-bold; | ||
letter-spacing: 0.02em; | ||
|
||
@include phone-down { | ||
@include font-size(32px, 36px); | ||
} | ||
} | ||
|
||
h2 { | ||
@include font-size(16px, 24px); | ||
|
||
color: $mint-green-6; | ||
font-family: $metropolis-bold; | ||
letter-spacing: 0.15em; | ||
text-transform: uppercase; | ||
} | ||
|
||
.network-name { | ||
text-align: center; | ||
} | ||
} | ||
|
||
.switcher { | ||
margin: 0 20px 20px 20px; | ||
} | ||
|
||
@include phone-down { | ||
width: 100%; | ||
} | ||
} | ||
} | ||
} | ||
|
||
.wrapper { | ||
display: flex; | ||
justify-content: center; | ||
padding: 0 $inner-padding 44px; | ||
|
||
.inner { | ||
display: flex; | ||
flex: 1; | ||
flex-direction: column; | ||
max-width: 960px; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React from "react"; | ||
import { RouteComponentProps } from "react-router-dom"; | ||
import LandingEpochSection from "~/app/components/nova/landing/LandingEpochSection"; | ||
import { useNetworkConfig } from "~helpers/hooks/useNetworkConfig"; | ||
import { LandingRouteProps } from "../../LandingRouteProps"; | ||
import "./Landing.scss"; | ||
|
||
const Landing: React.FC<RouteComponentProps<LandingRouteProps>> = ({ | ||
match: { | ||
params: { network }, | ||
}, | ||
}) => { | ||
const [networkConfig] = useNetworkConfig(network); | ||
|
||
return ( | ||
<div className="landing-nova"> | ||
<div className="header-wrapper"> | ||
<div className="inner"> | ||
<div className="header"> | ||
<div className="header--title"> | ||
<h2>{networkConfig.isEnabled ? "Explore network" : ""}</h2> | ||
<div className="network-name"> | ||
<h1>{networkConfig.label}</h1> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div className="wrapper"> | ||
<div className="inner"> | ||
<LandingEpochSection /> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Landing; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import moment from "moment"; | ||
import { useEffect, useState } from "react"; | ||
import { useNovaTimeConvert } from "./useNovaTimeConvert"; | ||
|
||
export function useCurrentEpochProgress(): { | ||
epochIndex: number | null; | ||
epochUnixTimeRange: { from: number; to: number } | null; | ||
epochProgressPercent: number | null; | ||
registrationTime: number | null; | ||
} { | ||
const { slotIndexToUnixTimeRange, unixTimestampToEpochIndex, epochIndexToUnixTimeRange, getRegistrationSlotFromEpochIndex } = | ||
useNovaTimeConvert(); | ||
const [intervalTimerHandle, setIntervalTimerHandle] = useState<NodeJS.Timeout | null>(null); | ||
const [epochIndex, setEpochIndex] = useState<number | null>(null); | ||
const [epochProgressPercent, setEpochProgressPercent] = useState<number | null>(null); | ||
const [registrationTime, setRegistrationTime] = useState<number | null>(null); | ||
const [epochUnixTimeRange, setEpochUnixTimeRange] = useState<{ from: number; to: number } | null>(null); | ||
|
||
useEffect(() => { | ||
if (intervalTimerHandle === null) { | ||
checkCurrentEpochIndex(); | ||
|
||
const intervalTimerHandle = setInterval(() => { | ||
checkCurrentEpochIndex(); | ||
}, 1000); | ||
|
||
setIntervalTimerHandle(intervalTimerHandle); | ||
} | ||
|
||
return () => { | ||
if (intervalTimerHandle) { | ||
clearInterval(intervalTimerHandle); | ||
} | ||
setIntervalTimerHandle(null); | ||
setEpochIndex(null); | ||
}; | ||
}, []); | ||
|
||
const checkCurrentEpochIndex = () => { | ||
if (unixTimestampToEpochIndex && epochIndexToUnixTimeRange) { | ||
const now = moment().unix(); | ||
const currentEpochIndex = unixTimestampToEpochIndex(now); | ||
|
||
const epochTimeRange = epochIndexToUnixTimeRange(currentEpochIndex); | ||
|
||
const epochProgressPercent = Math.trunc(((now - epochTimeRange.from) / (epochTimeRange.to - 1 - epochTimeRange.from)) * 100); | ||
|
||
setEpochIndex(currentEpochIndex); | ||
setEpochUnixTimeRange(epochTimeRange); | ||
setEpochProgressPercent(epochProgressPercent); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
if (getRegistrationSlotFromEpochIndex && slotIndexToUnixTimeRange && epochIndex !== null) { | ||
const slotIndex = getRegistrationSlotFromEpochIndex(epochIndex); | ||
const slotTimeRange = slotIndexToUnixTimeRange(slotIndex); | ||
setRegistrationTime(slotTimeRange.to - 1); | ||
} | ||
}, [epochIndex]); | ||
|
||
return { epochIndex, epochUnixTimeRange, epochProgressPercent, registrationTime }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.