Skip to content

Commit

Permalink
feat: update profile page, leaderboard and quest-cards (#1474)
Browse files Browse the repository at this point in the history
  • Loading branch information
dennyscode authored Dec 26, 2024
1 parent 177b574 commit f314871
Show file tree
Hide file tree
Showing 136 changed files with 3,507 additions and 3,070 deletions.
18 changes: 18 additions & 0 deletions src/app/[lng]/(infos)/leaderboard/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Metadata } from 'next';
import LeaderboardPage from 'src/app/ui/leaderboard/LeaderboardPage';

export const metadata: Metadata = {
title: 'Jumper Leaderboard',
description: 'Jumper Leaderboard is the profile page of Jumper Exchange.',
alternates: {
canonical: `${process.env.NEXT_PUBLIC_SITE_URL}/leaderboard`,
},
};

export default async function Page({
searchParams,
}: {
searchParams: { page?: string };
}) {
return <LeaderboardPage page={searchParams.page} />;
}
4 changes: 2 additions & 2 deletions src/app/api/profile/[walletAddress]/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ export async function GET(
fill="white"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M13.5 9C13.125 9 12.75 9.375 12.75 9.75V13.5H16.5C18 13.5 18.75 12.375 18.75 11.25C18.75 10.125 18 9 16.5 9H13.5ZM16.5 10.5H14.25V12H16.5C17.0625 12 17.25 11.5261 17.25 11.25C17.25 10.9739 17.0625 10.5 16.5 10.5Z"
fill="white"
/>
Expand Down
2 changes: 2 additions & 0 deletions src/app/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import resourcesToBackend from 'i18next-resources-to-backend';
import { initReactI18next } from 'react-i18next/initReactI18next';
import i18nConfig from '../../i18nconfig';
import { currencyFormatter, decimalFormatter } from '@/utils/formatNumbers';
import { dateFormatter } from 'src/utils/formatDate';

// TODO: use https://nextjs.org/docs/app/building-your-application/routing/internationalization#localization
export default async function initTranslations(
Expand Down Expand Up @@ -41,6 +42,7 @@ export default async function initTranslations(

i18nInstance.services.formatter?.addCached('decimalExt', decimalFormatter);
i18nInstance.services.formatter?.addCached('currencyExt', currencyFormatter);
i18nInstance.services.formatter?.addCached('dateExt', dateFormatter);

return {
i18n: i18nInstance,
Expand Down
11 changes: 11 additions & 0 deletions src/app/ui/leaderboard/LeaderboardPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use client';
import { LeaderboardPage as LeaderboardPageComponent } from '@/components/Leaderboard/LeaderboardPage';

const LeaderboardPage = ({ page }: { page?: string }) => {
const parsedPage = parseInt(page || '', 10);
const defaultPage = !isNaN(parsedPage) && parsedPage >= 1 ? parsedPage : 1;

return <LeaderboardPageComponent page={defaultPage} />;
};

export default LeaderboardPage;
2 changes: 1 addition & 1 deletion src/app/ui/quests/QuestMissionPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { QuestsMissionPage } from 'src/components/Quests/QuestPage/QuestsMissionPage';
import { QuestsMissionPage } from 'src/components/QuestPage/QuestsMissionPage';
import { JUMPER_LOYALTY_PATH } from 'src/const/urls';

const QuestPage = ({ quest, url }: any) => {
Expand Down
4 changes: 3 additions & 1 deletion src/components/Banner/Banner.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';
import { Theme, Typography, useMediaQuery, useTheme } from '@mui/material';
import type { Theme } from '@mui/material';
import { Typography, useMediaQuery, useTheme } from '@mui/material';
import Image from 'next/image';
import { BannerContainer } from './Banner.style';
import { useUserTracking } from 'src/hooks/userTracking';
Expand Down Expand Up @@ -33,6 +34,7 @@ export const Banner = () => {
href="https://wrapped.jumper.exchange"
target="_blank"
style={{ textDecoration: 'none', color: 'inherit' }}
rel="noreferrer"
>
<BannerContainer onClick={handleClick}>
<Image
Expand Down
3 changes: 1 addition & 2 deletions src/components/Blog/BlogArticle/BlogArticle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import { ArticleJsonSchema } from '@/components/JsonSchema/JsonSchemaArticle';
import { Tag } from '@/components/Tag.style';
import type { AuthorData, StrapiImageData, TagData } from '@/types/strapi';
import type { ThemeMode } from '@/types/theme';
import { formatDate } from '@/utils/formatDate';
import { readingTime } from '@/utils/readingTime';
import type { RootNode } from 'node_modules/@strapi/blocks-react-renderer/dist/BlocksRenderer';
import { CustomRichBlocks, ShareArticleIcons } from '..';
Expand Down Expand Up @@ -95,7 +94,7 @@ export const BlogArticle = ({
{createdAt ? (
<BlogArticleHeaderMeta>
<BlogArticleHeaderMetaDate variant="bodyXSmall" as="span">
{formatDate(publishedAt || createdAt)}
{t('format.shortDate', { value: publishedAt || createdAt })}
</BlogArticleHeaderMetaDate>
<span>{t('blog.minRead', { minRead: minRead })}</span>
</BlogArticleHeaderMeta>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Blog/BlogArticleCard/BlogArticleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { JUMPER_LEARN_PATH } from '@/const/urls';
import { useUserTracking } from '@/hooks/userTracking/useUserTracking';
import { useMenuStore } from '@/stores/menu/MenuStore';
import type { BlogArticleData } from '@/types/strapi';
import { formatDate } from '@/utils/formatDate';
import { readingTime } from '@/utils/readingTime';
import type { CSSObject } from '@mui/material';
import { Skeleton } from '@mui/material';
Expand Down Expand Up @@ -99,10 +98,11 @@ export const BlogArticleCard = ({
hasTags={article.attributes.tags?.data.length > 0}
>
<BlogArticleMetaDate variant="bodyXSmall" as="span">
{formatDate(
article.attributes.publishedAt ||
{t('format.shortDate', {
value:
article.attributes.publishedAt ||
article.attributes.createdAt,
)}
})}
</BlogArticleMetaDate>
<BlogArticleMetaReadingTime variant="bodyXSmall" as="span">
{t('blog.minRead', { minRead: minRead })}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Breakpoint } from '@mui/material';
import { Grid } from '@mui/material';

import { styled } from '@mui/material/styles';
import { CarouselTitle } from '../BlogCarousel';
import { SectionTitle } from 'src/components/ProfilePage/ProfilePage.style';

export const BlogArticlesCollectionsContainer = styled(Grid)(({ theme }) => ({
display: 'flex',
Expand Down Expand Up @@ -48,7 +48,7 @@ export const BlogArticlesCollectionsContainer = styled(Grid)(({ theme }) => ({
},
}));

export const BlogArticlesCollectionsTitle = styled(CarouselTitle)(
export const BlogArticlesCollectionsTitle = styled(SectionTitle)(
({ theme }) => ({
color: theme.palette.text.primary,
}),
Expand Down
30 changes: 8 additions & 22 deletions src/components/Blog/BlogCarousel/CarouselContainer.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {
CSSObject,
IconButtonProps,
} from '@mui/material';
import { Box, Typography, styled } from '@mui/material';
import { Box, styled } from '@mui/material';

export interface CarouselContainerBoxProps extends Omit<BoxProps, 'variant'> {
styles?: CSSObject;
Expand All @@ -22,15 +22,10 @@ export const CarouselContainerBox = styled(Box, {
overflowY: 'hidden',
scrollSnapType: 'x mandatory',
'& > *': {
flexShrink: 0,
scrollSnapAlign: 'center',
},
'::-webkit-scrollbar': { display: 'none' },
[theme.breakpoints.up('sm' as Breakpoint)]: {
marginTop: theme.spacing(4),
},
[theme.breakpoints.up('xs' as Breakpoint)]: {
marginTop: theme.spacing(2),
},
...styles,
}));

Expand All @@ -49,21 +44,6 @@ export const CarouselHeader = styled(Box, {
},
}));

export const CarouselTitle = styled(Typography)(({ theme }) => ({
fontWeight: 700,
fontSize: '24px',
lineHeight: '32px',
color: 'inherit',
margin: theme.spacing(0, 1.5, 0),
[theme.breakpoints.up('sm' as Breakpoint)]: {
margin: theme.spacing(0, 1.5, 0),
},
[theme.breakpoints.up('lg' as Breakpoint)]: {
justifyContent: 'flex-start',
margin: 0,
},
}));

export interface CarouselNavigationContainerProps
extends Omit<BoxProps, 'variant'> {
hide?: boolean;
Expand All @@ -86,3 +66,9 @@ export const CarouselNavigationButton = styled(IconButtonTertiary, {
height: 40,
fontSize: 22,
}));

export const CarouselCenteredBox = styled(Box)(() => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}));
122 changes: 67 additions & 55 deletions src/components/Blog/BlogCarousel/CarouselContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import { Box, useTheme, type CSSObject } from '@mui/material';

import { TrackingAction, TrackingEventParameter } from '@/const/trackingKeys';
import { useUserTracking } from '@/hooks/userTracking/useUserTracking';
import type { ReactNode } from 'react';
import { useCallback, useRef } from 'react';
import { SectionTitle } from 'src/components/ProfilePage/ProfilePage.style';
import {
CarouselCenteredBox,
CarouselContainerBox,
CarouselHeader,
CarouselNavigationButton,
CarouselNavigationContainer,
CarouselTitle,
} from '.';
import IconHeader from 'src/components/ProfilePage/Common/IconHeader';
import useClient from 'src/hooks/useClient';

interface CarouselContainerProps {
title?: string;
updateTitle?: string;
updateTooltip?: string;
styles?: CSSObject;
children: ReactNode | ReactNode[];
trackingCategory?: string;
Expand All @@ -25,70 +28,79 @@ const swipeDistance = 420;
export const CarouselContainer = ({
styles,
title,
updateTitle,
updateTooltip,
children,
trackingCategory,
}: CarouselContainerProps) => {
const { trackEvent } = useUserTracking();
const theme = useTheme();
const carouselContainerRef = useRef<HTMLDivElement>(null);

const handleChange = useCallback(
(direction: 'next' | 'prev') => {
if (carouselContainerRef.current) {
const node: HTMLDivElement = carouselContainerRef.current;
const scrollLeftPos = node.scrollLeft;
const scrollWidth =
carouselContainerRef.current.scrollWidth -
carouselContainerRef.current.clientWidth;
const isClient = useClient();

let scrollPos = 0;
switch (direction) {
case 'next':
if (scrollLeftPos + swipeDistance < scrollWidth) {
scrollPos = scrollLeftPos + swipeDistance;
} else {
scrollPos = scrollWidth;
}
break;
case 'prev':
if (scrollLeftPos - swipeDistance > 0) {
scrollPos = scrollLeftPos - swipeDistance;
} else {
scrollPos = 0;
}
break;
}
const handleChange = useCallback((direction: 'next' | 'prev') => {
if (carouselContainerRef.current) {
const node: HTMLDivElement = carouselContainerRef.current;
const scrollLeftPos = node.scrollLeft;
const scrollWidth =
carouselContainerRef.current.scrollWidth -
carouselContainerRef.current.clientWidth;

node.scrollTo({
left: parseInt(`${scrollPos}`),
behavior: 'smooth',
});
} else {
let scrollPos = 0;
switch (direction) {
case 'next':
if (scrollLeftPos + swipeDistance < scrollWidth) {
scrollPos = scrollLeftPos + swipeDistance;
} else {
scrollPos = scrollWidth;
}
break;
case 'prev':
if (scrollLeftPos - swipeDistance > 0) {
scrollPos = scrollLeftPos - swipeDistance;
} else {
scrollPos = 0;
}
break;
}
},
[trackEvent, trackingCategory],
);

node.scrollTo({
left: parseInt(`${scrollPos}`),
behavior: 'smooth',
});
}
}, []);
return (
<Box>
<CarouselHeader>
{title && <CarouselTitle variant="headerMedium">{title}</CarouselTitle>}
{
<CarouselNavigationContainer>
<CarouselNavigationButton
aria-label="previous"
onClick={() => handleChange('prev')}
>
<ArrowBackIcon sx={{ width: '22px', height: '22px' }} />
</CarouselNavigationButton>
<CarouselNavigationButton
aria-label="next"
sx={{ marginLeft: theme.spacing(1) }}
onClick={() => handleChange('next')}
>
<ArrowForwardIcon sx={{ width: '22px', height: '22px' }} />
</CarouselNavigationButton>
</CarouselNavigationContainer>
}
<CarouselCenteredBox>
{title && <SectionTitle variant="headerMedium">{title}</SectionTitle>}
{updateTitle && (
<Box>
{isClient && (
<IconHeader
tooltipKey={updateTooltip || ''}
title={updateTitle}
/>
)}
</Box>
)}
</CarouselCenteredBox>
<CarouselNavigationContainer>
<CarouselNavigationButton
aria-label="previous"
onClick={() => handleChange('prev')}
>
<ArrowBackIcon sx={{ width: '22px', height: '22px' }} />
</CarouselNavigationButton>
<CarouselNavigationButton
aria-label="next"
sx={{ marginLeft: theme.spacing(1) }}
onClick={() => handleChange('next')}
>
<ArrowForwardIcon sx={{ width: '22px', height: '22px' }} />
</CarouselNavigationButton>
</CarouselNavigationContainer>
</CarouselHeader>
<CarouselContainerBox ref={carouselContainerRef} sx={styles}>
{children}
Expand Down
16 changes: 0 additions & 16 deletions src/components/Blog/FeaturedArticle/FeaturedArticle.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,6 @@ export const FeaturedArticleLink = styled(Link, {
},
}));

export const FeaturedArticleCard = styled(Box)<BoxProps>(({ theme }) => ({
display: 'flex',
backgroundColor: alpha(theme.palette.primary.main, 0.25),
top: theme.spacing(-4),
margin: theme.spacing(4, 2.5),
padding: theme.spacing(4),
borderRadius: '36px',
width: 'auto',
alignItems: 'center',
[theme.breakpoints.up('md' as Breakpoint)]: {
margin: theme.spacing(4, 2.5),
padding: theme.spacing(4),
height: 576,
},
}));

export const FeaturedArticleMetaContainer = styled(Box)<BoxProps>(
({ theme }) => ({
display: 'flex',
Expand Down
Loading

0 comments on commit f314871

Please sign in to comment.