Commit fbffec54 authored by Max Alekseenko's avatar Max Alekseenko

improve login, fetch real data

parent 67acc9a4
......@@ -90,7 +90,15 @@ import type {
OptimismL2BatchBlocks,
} from 'types/api/optimisticL2';
import type { RawTracesResponse } from 'types/api/rawTrace';
import type { RewardsNonceResponse, RewardsCheckUserResponse, RewardsLoginResponse } from 'types/api/rewards';
import type {
RewardsNonceResponse,
RewardsCheckUserResponse,
RewardsLoginResponse,
RewardsUserBalancesResponse,
RewardsUserDailyCheckResponse,
RewardsUserDailyClaimResponse,
RewardsUserReferralsResponse,
} from 'types/api/rewards';
import type { SearchRedirectResult, SearchResult, SearchResultFilters, SearchResultItem } from 'types/api/search';
import type { ShibariumWithdrawalsResponse, ShibariumDepositsResponse } from 'types/api/shibarium';
import type { HomeStats } from 'types/api/stats';
......@@ -337,6 +345,31 @@ export const RESOURCES = {
endpoint: getFeaturePayload(config.features.rewards)?.api.endpoint,
basePath: getFeaturePayload(config.features.rewards)?.api.basePath,
},
rewards_logout: {
path: '/api/v1/auth/logout',
endpoint: getFeaturePayload(config.features.rewards)?.api.endpoint,
basePath: getFeaturePayload(config.features.rewards)?.api.basePath,
},
rewards_user_balances: {
path: '/api/v1/user/balances',
endpoint: getFeaturePayload(config.features.rewards)?.api.endpoint,
basePath: getFeaturePayload(config.features.rewards)?.api.basePath,
},
rewards_user_daily_check: {
path: '/api/v1/user/daily/check',
endpoint: getFeaturePayload(config.features.rewards)?.api.endpoint,
basePath: getFeaturePayload(config.features.rewards)?.api.basePath,
},
rewards_user_daily_claim: {
path: '/api/v1/user/daily/claim',
endpoint: getFeaturePayload(config.features.rewards)?.api.endpoint,
basePath: getFeaturePayload(config.features.rewards)?.api.basePath,
},
rewards_user_referrals: {
path: '/api/v1/user/referrals',
endpoint: getFeaturePayload(config.features.rewards)?.api.endpoint,
basePath: getFeaturePayload(config.features.rewards)?.api.basePath,
},
// BLOCKS, TXS
blocks: {
......@@ -1191,6 +1224,10 @@ Q extends 'withdrawals_counters' ? WithdrawalsCounters :
Q extends 'rewards_nonce' ? RewardsNonceResponse :
Q extends 'rewards_check_user' ? RewardsCheckUserResponse :
Q extends 'rewards_login' ? RewardsLoginResponse :
Q extends 'rewards_user_balances' ? RewardsUserBalancesResponse :
Q extends 'rewards_user_daily_check' ? RewardsUserDailyCheckResponse :
Q extends 'rewards_user_daily_claim' ? RewardsUserDailyClaimResponse :
Q extends 'rewards_user_referrals' ? RewardsUserReferralsResponse :
never;
/* eslint-enable @typescript-eslint/indent */
......
import { useBoolean } from '@chakra-ui/react';
import React, { createContext, useContext, useMemo } from 'react';
import React, { createContext, useContext, useEffect, useMemo } from 'react';
import type { RewardsUserBalancesResponse, RewardsUserDailyCheckResponse } from 'types/api/rewards';
import config from 'configs/app';
import useApiQuery from 'lib/api/useApiQuery';
import * as cookies from 'lib/cookies';
type Props = {
children: React.ReactNode;
......@@ -9,22 +15,52 @@ type TRewardsContext = {
isLoginModalOpen: boolean;
openLoginModal: () => void;
closeLoginModal: () => void;
balances: RewardsUserBalancesResponse | undefined;
dailyReward: RewardsUserDailyCheckResponse | undefined;
isLogedIn: boolean;
}
const RewardsContext = createContext<TRewardsContext>({
isLoginModalOpen: false,
openLoginModal: () => {},
closeLoginModal: () => {},
balances: undefined,
dailyReward: undefined,
isLogedIn: false,
});
export function RewardsContextProvider({ children }: Props) {
const apiToken = cookies.get(cookies.NAMES.REWARDS_API_TOKEN);
const apiQueryOptions = {
queryOptions: {
enabled: Boolean(apiToken) && config.features.rewards.isEnabled,
},
fetchParams: {
headers: {
Authorization: `Bearer ${ apiToken }`,
},
},
};
const [ isLoginModalOpen, setIsLoginModalOpen ] = useBoolean(false);
const balancesQuery = useApiQuery('rewards_user_balances', apiQueryOptions);
const dailyRewardQuery = useApiQuery('rewards_user_daily_check', apiQueryOptions);
useEffect(() => {
if (apiToken && balancesQuery.error?.status === 401) {
cookies.set(cookies.NAMES.REWARDS_API_TOKEN, '');
}
}, [ balancesQuery.error, apiToken ]);
const value = useMemo(() => ({
isLoginModalOpen,
openLoginModal: setIsLoginModalOpen.on,
closeLoginModal: setIsLoginModalOpen.off,
}), [ isLoginModalOpen, setIsLoginModalOpen ]);
balances: balancesQuery.data,
dailyReward: dailyRewardQuery.data,
isLogedIn: Boolean(apiToken),
}), [ isLoginModalOpen, setIsLoginModalOpen, balancesQuery.data, dailyRewardQuery.data, apiToken ]);
return (
<RewardsContext.Provider value={ value }>
......
......@@ -25,7 +25,11 @@ export function isInternalItem(item: NavItem): item is NavItemInternal {
export default function useNavItems(): ReturnType {
const router = useRouter();
const pathname = router.pathname;
const { openLoginModal: openRewardsLoginModal } = useRewardsContext();
const {
openLoginModal: openRewardsLoginModal,
balances: rewardsBalances,
isLogedIn: isLoggedInToRewards,
} = useRewardsContext();
return React.useMemo(() => {
let blockchainNavItems: Array<NavItem> | Array<Array<NavItem>> = [];
......@@ -268,11 +272,11 @@ export default function useNavItems(): ReturnType {
const accountNavItems: ReturnType['accountNavItems'] = [
config.features.rewards.isEnabled ? {
text: 'Merits',
// nextRoute: { pathname: '/account/rewards' as const },
onClick: openRewardsLoginModal,
text: rewardsBalances?.total ? `${ rewardsBalances?.total } Merits` : 'Merits',
nextRoute: isLoggedInToRewards ? { pathname: '/account/rewards' as const } : undefined,
onClick: isLoggedInToRewards ? undefined : openRewardsLoginModal,
icon: 'merits',
// isActive: pathname === '/account/rewards',
isActive: isLoggedInToRewards && pathname === '/account/rewards',
} : null,
{
text: 'Watch list',
......@@ -314,5 +318,5 @@ export default function useNavItems(): ReturnType {
};
return { mainNavItems, accountNavItems, profileItem };
}, [ pathname, openRewardsLoginModal ]);
}, [ pathname, openRewardsLoginModal, rewardsBalances, isLoggedInToRewards ]);
}
......@@ -23,7 +23,8 @@ export default function fetchFactory(
cookie: apiToken ? `${ cookies.NAMES.API_TOKEN }=${ apiToken }` : '',
..._pick(_req.headers, [
'x-csrf-token',
'Authorization',
'Authorization', // the old value, just in case
'authorization', // Node.js automatically lowercases headers
// feature flags
'updated-gas-oracle',
]) as Record<string, string | undefined>,
......
......@@ -10,3 +10,31 @@ export type RewardsLoginResponse = {
created: boolean;
token: string;
};
export type RewardsUserBalancesResponse = {
total: string;
staked: string;
unstaked: string;
total_staking_rewards: string;
total_referral_rewards: string;
pending_referral_rewards: string;
};
export type RewardsUserDailyCheckResponse = {
available: boolean;
daily_reward: string;
pending_referral_rewards: string;
date: string;
reset_at: string;
};
export type RewardsUserDailyClaimResponse = {
daily_reward: string;
pending_referral_rewards: string;
};
export type RewardsUserReferralsResponse = {
code: string;
link: string;
referrals: string;
};
import { Button, Flex, Text, useColorModeValue } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import { useRewardsContext } from 'lib/contexts/rewards';
import CopyField from 'ui/rewards/CopyField';
import RewardsDashboardCard from 'ui/rewards/RewardsDashboardCard';
import IconSvg from 'ui/shared/IconSvg';
......@@ -8,6 +10,13 @@ import LinkExternal from 'ui/shared/links/LinkExternal';
import PageTitle from 'ui/shared/Page/PageTitle';
const RewardsDashboard = () => {
const router = useRouter();
const { balances, dailyReward, isLogedIn } = useRewardsContext();
if (!isLogedIn) {
router.replace({ pathname: '/' }, undefined, { shallow: true });
}
return (
<>
<PageTitle
......@@ -26,8 +35,8 @@ const RewardsDashboard = () => {
<Flex gap={ 6 }>
<RewardsDashboardCard
description="Claim your daily merits and any merits received from referrals."
values={ [ { label: 'Total balance', value: 250 } ] }
contentAfter={ <Button>Claim X Merits</Button> }
values={ [ { label: 'Total balance', value: balances?.total } ] }
contentAfter={ <Button>Claim { dailyReward?.daily_reward } Merits</Button> }
/>
<RewardsDashboardCard
title="Title"
......
......@@ -7,7 +7,7 @@ import AvailableSoonLabel from './AvailableSoonLabel';
type Value = {
label: string;
value: number;
value: number | string | undefined;
type?: 'percentages';
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment