F
This commit is contained in:
@@ -6,17 +6,28 @@ interface CsrfResponse {
|
||||
}
|
||||
|
||||
let cachedToken: string | null = null
|
||||
let inflight: Promise<string> | null = null
|
||||
|
||||
export function clearCsrfCache(): void {
|
||||
cachedToken = null
|
||||
inflight = null
|
||||
}
|
||||
|
||||
export async function getCsrfToken(): Promise<string> {
|
||||
if (cachedToken) return cachedToken
|
||||
const res = await fetch(`${API_URL}/csrf/token`, {
|
||||
credentials: 'include',
|
||||
})
|
||||
const data: CsrfResponse = await res.json()
|
||||
cachedToken = data.token
|
||||
return cachedToken
|
||||
export function getCsrfToken(): Promise<string> {
|
||||
if (cachedToken) return Promise.resolve(cachedToken)
|
||||
if (inflight) return inflight
|
||||
|
||||
inflight = fetch(`${API_URL}/csrf/token`, { credentials: 'include' })
|
||||
.then((res) => res.json() as Promise<CsrfResponse>)
|
||||
.then((data) => {
|
||||
cachedToken = data.token
|
||||
inflight = null
|
||||
return cachedToken
|
||||
})
|
||||
.catch((err) => {
|
||||
inflight = null
|
||||
throw err
|
||||
})
|
||||
|
||||
return inflight
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export const COUNTDOWN_DAYS = 3
|
||||
export const COUNTDOWN_TARGET = new Date('2026-05-21T00:00:00').getTime()
|
||||
export const USDT_RATE = 80.00
|
||||
export const GAS_PRICE = 21.00
|
||||
|
||||
@@ -2,11 +2,8 @@ import logo from '@shared/assets/logo-full-white.png'
|
||||
import styles from './Header.module.css'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { ROUTES } from '@shared/config/routes'
|
||||
import { useIsAuthenticated } from '@features/auth'
|
||||
|
||||
export function Header() {
|
||||
const isAuthenticated = useIsAuthenticated()
|
||||
|
||||
return (
|
||||
<nav className={styles.nav}>
|
||||
<a className={styles.logo} href="/">
|
||||
@@ -16,7 +13,7 @@ export function Header() {
|
||||
<a className={styles.link} href="#about">
|
||||
О нас
|
||||
</a>
|
||||
<Link className={styles.btn} to={isAuthenticated ? ROUTES.WALLET : ROUTES.LOGIN}>
|
||||
<Link className={styles.btn} to={ROUTES.WALLET}>
|
||||
Личный кабинет
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
const STORAGE_KEY = 'eksa_countdown_target'
|
||||
|
||||
export interface CountdownValue {
|
||||
d: string
|
||||
h: string
|
||||
@@ -9,15 +7,7 @@ export interface CountdownValue {
|
||||
s: string
|
||||
}
|
||||
|
||||
export function useCountdown(days: number): CountdownValue {
|
||||
const [target] = useState<number>(() => {
|
||||
const saved = localStorage.getItem(STORAGE_KEY)
|
||||
if (saved) return Number.parseInt(saved, 10)
|
||||
const t = Date.now() + days * 86_400_000
|
||||
localStorage.setItem(STORAGE_KEY, String(t))
|
||||
return t
|
||||
})
|
||||
|
||||
export function useCountdown(target: number): CountdownValue {
|
||||
const [now, setNow] = useState<number>(Date.now())
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -9,11 +9,11 @@ const UNITS: Array<['d' | 'h' | 'm' | 's', string]> = [
|
||||
]
|
||||
|
||||
interface Props {
|
||||
days: number
|
||||
target: number
|
||||
}
|
||||
|
||||
export function Countdown({ days }: Props) {
|
||||
const cd = useCountdown(days)
|
||||
export function Countdown({ target }: Props) {
|
||||
const cd = useCountdown(target)
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { COUNTDOWN_DAYS } from '@shared/config/constants'
|
||||
import { COUNTDOWN_TARGET } from '@shared/config/constants'
|
||||
import { ConversionFlow } from './ConversionFlow'
|
||||
import { Countdown } from './Countdown'
|
||||
import { ExchangeCard } from './ExchangeCard'
|
||||
@@ -31,7 +31,7 @@ export function Hero() {
|
||||
</span>
|
||||
</h1>
|
||||
<div>
|
||||
<Countdown days={COUNTDOWN_DAYS} />
|
||||
<Countdown target={COUNTDOWN_TARGET} />
|
||||
<a href="#converter" className={styles.cta}>
|
||||
Попробовать калькулятор
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user