Skip to content

Commit

Permalink
feat: Nigeria meetup banner (#10767)
Browse files Browse the repository at this point in the history
<!--
Before opening a pull request, please read the [contributing
guidelines](https://github.com/pancakeswap/pancake-frontend/blob/develop/CONTRIBUTING.md)
first
-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the localization and UI components for a
new `NigeriaMeetupBanner`, adding new translations, and updating the
styling and functionality of banner elements.

### Detailed summary
- Added translations for `Nigeria` and `PancakeSwap Workshop` in
`translations.json`.
- Introduced `NigeriaMeetupBanner` component with countdown
functionality and styled elements.
- Updated `VariantTypes` to include `white` and `gold` in `BannerTitle`.
- Modified `BannerTitle` to use variant-specific stroke and color
properties.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your
question}`

<!-- end pr-codex -->

---------

Co-authored-by: chefmomota <[email protected]>
  • Loading branch information
memoyil and ChefMomota authored Oct 2, 2024
1 parent 713a687 commit 62908f7
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 9 deletions.
169 changes: 169 additions & 0 deletions apps/web/src/views/Home/components/Banners/NigeriaMeetupBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import { useCountdown } from '@pancakeswap/hooks'
import { useTranslation } from '@pancakeswap/localization'
import { Box, Flex, FlexGap, Text, useMatchBreakpoints } from '@pancakeswap/uikit'
import { memo, useMemo } from 'react'
import styled from 'styled-components'

import {
BackgroundGraphic,
BannerActionContainer,
BannerContainer,
BannerGraphics,
BannerMain,
BannerTitle,
FloatingGraphic,
LinkExternalAction,
PancakeSwapBadge,
} from '@pancakeswap/widgets-internal'
import { ASSET_CDN } from 'config/constants/endpoints'

const NumberDisplayContainer = styled(FlexGap)`
border-radius: 1.5rem;
background: #190b36;
border: 2px solid #ffffff;
padding: 0 0.625rem;
width: 6rem;
height: 8.3rem;
`
const CountDownWrapper = styled.div`
display: flex;
background-color: #082814;
font-family: Kanit;
font-size: 18px;
font-style: normal;
font-weight: 600;
line-height: 90%;
color: white;
padding: 8px;
border-radius: 8px;
margin-top: 5px;
gap: 0px;
flex-direction: column;
width: max-content;
${({ theme }) => theme.mediaQueries.sm} {
flex-direction: row;
gap: 8px;
font-size: 20px;
line-height: 110%; /* 22px */
}
`

type NumberDisplayProps = {
label: string
value?: number
}

export function NumberDisplay({ label, value }: NumberDisplayProps) {
const valueDisplay = useMemo(() => (value === undefined ? '-' : String(value).padStart(2, '0')), [value])

return (
<NumberDisplayContainer flexDirection="column" alignItems="center" justifyContent="center" gap="0.5rem" flex={1}>
<Text fontSize="4rem" lineHeight="100%" fontFamily="Inter, Sans-Serif" color="white">
{valueDisplay}
</Text>
<Text textTransform="uppercase" fontSize="0.825rem" color="white">
{label}
</Text>
</NumberDisplayContainer>
)
}

export function Countdown() {
const { t } = useTranslation()
const { isMobile } = useMatchBreakpoints()
const countdown = useCountdown(1728723600)
if (!countdown) {
return null
}
const hours = countdown?.hours < 10 ? `0${countdown?.hours}` : countdown?.hours
const minutes = countdown?.minutes < 10 ? `0${countdown?.minutes}` : countdown?.minutes
const days = countdown?.days < 10 ? `0${countdown?.days}` : countdown?.days
return (
<CountDownWrapper>
<Box style={{ fontSize: isMobile ? '12px' : '20px' }}>{t('Starts in')}</Box>
<Box>
{days}
{t('d')} : {hours}
{t('h')} : {minutes}
{t('m')}
</Box>
</CountDownWrapper>
)
}

const VerticalDivider = styled.span`
background: #999999;
width: 1.5px;
height: 1.5rem;
margin: 2px;
`

type ActionsType = { href: string; text: string; icon?: 'arrowForward' | 'openNew' }
type IActions = ActionsType & Partial<CSSStyleDeclaration>

export const NigeriaMeetupBanner = memo(function NigeriaMeetupBanner() {
const { t } = useTranslation()
const { isMobile, isTablet, isMd } = useMatchBreakpoints()

const Action = ({ href, icon, text, ...props }: IActions) => (
<Box display={props.display} marginTop={props.marginTop}>
<LinkExternalAction href={href} externalIcon={icon} color={props.color}>
{t(text)}
</LinkExternalAction>
</Box>
)

return (
<BannerContainer background="radial-gradient(94.59% 117.72% at 26.47% 0%, #B1F5CE 0%, #50936B 46.5%, #125429 79.02%)">
<BannerMain
badges={
<Flex alignItems="center" height="20px" style={{ gap: '4px' }} minWidth="220px">
<PancakeSwapBadge />
<VerticalDivider />
<BannerTitle variant="gold" fontSize={18} strokeSize={1}>
{t('Nigeria')}
</BannerTitle>
</Flex>
}
title={
<BannerTitle variant="white" marginTop={isMd ? '-10px' : '0px'}>
{t('PancakeSwap Workshop')}
</BannerTitle>
}
desc={<Countdown />}
actions={
<BannerActionContainer>
<Action
href="https://lu.ma/n2v007vd"
display="flex"
icon="openNew"
alignItems="center"
text={t('Learn More')}
color="white"
/>
</BannerActionContainer>
}
/>

<BannerGraphics>
<BackgroundGraphic
src={`${ASSET_CDN}/web/banners/nigeria-meet-up/nigeria-meetup-bunny.png`}
width={isMobile ? 185 : isTablet ? 265 : 360}
height={isMobile ? 120 : isTablet ? 170 : 227}
/>
<Box
position="absolute"
width="100%"
left={isMobile ? '5%' : isTablet ? '-8%' : '-5%'}
top={isMobile ? '15%' : isTablet ? '10%' : null}
>
<FloatingGraphic
src={`${ASSET_CDN}/web/banners/nigeria-meet-up/floating-cake.png`}
width={isMobile ? 70 : isTablet ? 86 : 104}
height={isMobile ? 68 : isTablet ? 84 : 101}
/>
</Box>
</BannerGraphics>
</BannerContainer>
)
})
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import useIsRenderCompetitionBanner from './useIsRenderCompetitionBanner'
import { useIsRenderIfoBannerFromConfig } from './useIsRenderIFOBanner'
import { useIsRenderTgPredictionBotBanner } from './useIsRenderTgPredictionBotBanner'
import useIsRenderUserBanner from './useIsRenderUserBanner'
import { NigeriaMeetupBanner } from '../NigeriaMeetupBanner'

interface IBannerConfig {
shouldRender: boolean
Expand Down Expand Up @@ -46,6 +47,10 @@ export const useMultipleBannerConfig = () => {

return useMemo(() => {
const NO_SHUFFLE_BANNERS: IBannerConfig[] = [
{
shouldRender: true,
banner: <NigeriaMeetupBanner />,
},
{
shouldRender: isRenderIFOBannerFromConfig,
banner: <EigenpieIFOBanner />,
Expand Down
4 changes: 3 additions & 1 deletion packages/localization/src/config/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -3547,5 +3547,7 @@
"Wormhole": "Wormhole",
"Aptos": "Aptos",
"Play": "Play",
"Legacy products": "Legacy products"
"Legacy products": "Legacy products",
"Nigeria": "Nigeria",
"PancakeSwap Workshop": "PancakeSwap Workshop"
}
42 changes: 34 additions & 8 deletions packages/widgets-internal/components/Banner/BannerTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Text, TextProps, breakpoints } from "@pancakeswap/uikit";
import { PropsWithChildren } from "react";
import styled from "styled-components";

type VariantTypes = "purple" | "orange" | "yellow" | "listaBlue" | "green";
type VariantTypes = "white" | "gold" | "purple" | "orange" | "yellow" | "listaBlue" | "green";

type Props = {
variant: VariantTypes | Variant;
Expand All @@ -22,6 +22,22 @@ type Variant = {
};

const variants: { [key in VariantTypes]: Variant } = {
white: {
color: "#ffffff",
strokeColor: "#000000",
strokeSize: 2,
fontSize: 28,
lineHeight: 30,
fontWeight: 800,
},
gold: {
color: "#FFF500",
strokeColor: "#081910",
strokeSize: 2,
fontSize: 28,
lineHeight: 30,
fontWeight: 800,
},
purple: {
color: "#7645D9",
strokeColor: "#ffffff",
Expand Down Expand Up @@ -127,24 +143,34 @@ const FancyText = styled(Text)<{
}
`;

const defaultStrokeSize = 2;
const defaultStrokeColor = "#ffffff";

export function BannerTitle({
children,
variant,
strokeSize: defaultStrokeSize = 2,
strokeColor: defaultStrokeColor = "#ffffff",
color: defaultColor,
strokeSize,
strokeColor,
color,
...props
}: PropsWithChildren<Omit<TextProps, "fontSize" | "lineHeight"> & Props>) {
const variantData = typeof variant === "string" ? variants[variant] : variant;
const { color, fontSize, fontWeight, strokeSize, strokeColor, lineHeight } = variantData;
const {
color: variantColor,
fontSize,
fontWeight,
strokeSize: variantStrokeSize,
strokeColor: variantStrokeColor,
lineHeight,
} = variantData;
return (
<FancyText
color={color ?? defaultColor}
color={color ?? variantColor}
fontSize={fontSize}
lineHeight={lineHeight}
fontWeight={fontWeight}
$strokeSize={strokeSize ?? defaultStrokeSize}
$strokeColor={strokeColor ?? defaultStrokeColor}
$strokeSize={strokeSize ?? variantStrokeSize ?? defaultStrokeSize}
$strokeColor={strokeColor ?? variantStrokeColor ?? defaultStrokeColor}
{...props}
>
{children}
Expand Down

0 comments on commit 62908f7

Please sign in to comment.