From ebedc47e1780d7fba9b780a24ebb306bf8caf6c6 Mon Sep 17 00:00:00 2001 From: Adam Azad Date: Wed, 31 Aug 2022 19:34:18 +0100 Subject: [PATCH] feat(#1368): add Expeditions Task Cards --- .../expeditions/ExpeditionsModal.tsx | 56 ---------------- .../ExpeditionsCard.styled.tsx | 25 +++++++ .../ExpeditionsCard/ExpeditionsCard.tsx} | 55 ++++++--------- .../components/ExpeditionsCard/index.ts | 1 + .../ExpeditionsModal/ExpeditionsModal.tsx | 58 ++++++++++++++++ .../components/ExpeditionsModal/index.ts | 1 + .../LiquidityProvisionTaskCard.tsx | 64 ++++++++++++++++++ .../LiquidityProvisionTaskCard/index.ts | 1 + .../LiquidityStakingTaskCard.tsx | 67 +++++++++++++++++++ .../LiquidityStakingTaskCard/index.ts | 1 + src/modules/expeditions/index.tsx | 1 + src/modules/expeditions/utils/index.ts | 13 ++++ 12 files changed, 252 insertions(+), 91 deletions(-) delete mode 100644 src/components/expeditions/ExpeditionsModal.tsx create mode 100644 src/modules/expeditions/components/ExpeditionsCard/ExpeditionsCard.styled.tsx rename src/{components/expeditions/TaskCard.tsx => modules/expeditions/components/ExpeditionsCard/ExpeditionsCard.tsx} (56%) create mode 100644 src/modules/expeditions/components/ExpeditionsCard/index.ts create mode 100644 src/modules/expeditions/components/ExpeditionsModal/ExpeditionsModal.tsx create mode 100644 src/modules/expeditions/components/ExpeditionsModal/index.ts create mode 100644 src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityProvisionTaskCard/LiquidityProvisionTaskCard.tsx create mode 100644 src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityProvisionTaskCard/index.ts create mode 100644 src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityStakingTaskCard/LiquidityStakingTaskCard.tsx create mode 100644 src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityStakingTaskCard/index.ts create mode 100644 src/modules/expeditions/index.tsx create mode 100644 src/modules/expeditions/utils/index.ts diff --git a/src/components/expeditions/ExpeditionsModal.tsx b/src/components/expeditions/ExpeditionsModal.tsx deleted file mode 100644 index 628286318..000000000 --- a/src/components/expeditions/ExpeditionsModal.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { ReactNode } from 'react' -import styled from 'styled-components' - -import SwprLogo from '../../assets/images/swpr-logo.png' -import { useShowExpeditionsPopup } from '../../state/application/hooks' -import { ExternalLink, TYPE } from '../../theme' -import { AutoColumn } from '../Column' -import Modal from '../Modal' -import Row from '../Row' - -const ContentWrapper = styled(AutoColumn)` - width: 100%; - background-color: ${({ theme }) => theme.dark1}; -` - -const UpperAutoColumn = styled(AutoColumn)` - padding: 32px; -` - -const Text = ({ children }: { children: ReactNode }) => ( - - {children} - -) - -export default function ExpeditionsModal({ onDismiss }: { onDismiss: () => void }) { - const open = useShowExpeditionsPopup() - - return ( - - - - - SwprLogo - Swapr Expeditions - - - - Embark on a journey through space-time. In Swapr expeditions, you will traverse the lavender sea, making - incredible discoveries along the way. - - - - Get ready, Expeditions is launching very soon. - - - - Follow Swapr Twitter or{' '} - Discord to get updates on Expeditions. - - - - - - ) -} diff --git a/src/modules/expeditions/components/ExpeditionsCard/ExpeditionsCard.styled.tsx b/src/modules/expeditions/components/ExpeditionsCard/ExpeditionsCard.styled.tsx new file mode 100644 index 000000000..b748ff569 --- /dev/null +++ b/src/modules/expeditions/components/ExpeditionsCard/ExpeditionsCard.styled.tsx @@ -0,0 +1,25 @@ +import { ExternalLink } from 'react-feather' +import { Box } from 'rebass' +import styled from 'styled-components' + +export const Wrapper = styled.div` + border-radius: 12px; + background-color: ${({ theme }) => theme.bg1And2}; +` + +export const Card = styled(Box)` + display: flex; + flex-flow: column nowrap; + padding: 24px; + gap: 16px; +` + +export const StyledExternalLink = styled(ExternalLink)` + font-size: 13px; + font-style: italic; + text-decoration: underline; + + &:hover { + color: white; + } +` diff --git a/src/components/expeditions/TaskCard.tsx b/src/modules/expeditions/components/ExpeditionsCard/ExpeditionsCard.tsx similarity index 56% rename from src/components/expeditions/TaskCard.tsx rename to src/modules/expeditions/components/ExpeditionsCard/ExpeditionsCard.tsx index 281323a5e..8abe52f1e 100644 --- a/src/components/expeditions/TaskCard.tsx +++ b/src/modules/expeditions/components/ExpeditionsCard/ExpeditionsCard.tsx @@ -1,33 +1,8 @@ -import { ExternalLink } from 'react-feather' -import { Box } from 'rebass' -import styled from 'styled-components' - -import { TYPE } from '../../theme' -import { ButtonPrimary } from '../Button' -import Row from '../Row' -import { TagFailed, TagSuccess, TagWarning } from '../Tag' - -const Wrapper = styled.div` - border-radius: 12px; - background-color: ${({ theme }) => theme.bg1And2}; -` - -const Card = styled(Box)` - display: flex; - flex-flow: column nowrap; - padding: 24px; - gap: 16px; -` - -export const StyledExternalLink = styled(ExternalLink)` - font-size: 13px; - font-style: italic; - text-decoration: underline; - - &:hover { - color: white; - } -` +import { ButtonPrimary } from '../../../../components/Button' +import Row from '../../../../components/Row' +import { TagFailed, TagSuccess, TagWarning } from '../../../../components/Tag' +import { TYPE } from '../../../../theme' +import { Card, StyledExternalLink, Wrapper } from './ExpeditionsCard.styled' type StatusTags = 'active' | 'upcoming' | 'expired' @@ -37,7 +12,9 @@ export interface TaskCardProps { title: string description: string buttonText: string + butttonDisabled?: boolean infoLink?: string + onClick?: () => void } const StatusTag = ({ status }: Pick) => { @@ -53,7 +30,16 @@ const StatusTag = ({ status }: Pick) => { // Buttons to be implemented as needed. Maybe fixed set of buttons or button can be passed as child -export const TaskCard = ({ duration = 'Weekly', title, description, infoLink, status, buttonText }: TaskCardProps) => { +export function TaskCard({ + duration = 'Weekly', + title, + description, + infoLink, + status, + buttonText, + butttonDisabled = false, + onClick, +}: TaskCardProps) { return ( @@ -63,13 +49,12 @@ export const TaskCard = ({ duration = 'Weekly', title, description, infoLink, st - {title} - {description} - {infoLink && More info} - {buttonText} + + {buttonText} + ) diff --git a/src/modules/expeditions/components/ExpeditionsCard/index.ts b/src/modules/expeditions/components/ExpeditionsCard/index.ts new file mode 100644 index 000000000..b20abd5df --- /dev/null +++ b/src/modules/expeditions/components/ExpeditionsCard/index.ts @@ -0,0 +1 @@ +export * from './ExpeditionsCard' diff --git a/src/modules/expeditions/components/ExpeditionsModal/ExpeditionsModal.tsx b/src/modules/expeditions/components/ExpeditionsModal/ExpeditionsModal.tsx new file mode 100644 index 000000000..d1cffe72c --- /dev/null +++ b/src/modules/expeditions/components/ExpeditionsModal/ExpeditionsModal.tsx @@ -0,0 +1,58 @@ +import { ReactNode } from 'react' +import styled from 'styled-components' + +import SwprLogo from '../../../../assets/images/swpr-logo.png' +import { AutoColumn } from '../../../../components/Column' +import Modal from '../../../../components/Modal' +import Row from '../../../../components/Row' +import { useShowExpeditionsPopup } from '../../../../state/application/hooks' +import { TYPE } from '../../../../theme' +import { LiquidityProvisionTaskCard } from './partials/LiquidityProvisionTaskCard/LiquidityProvisionTaskCard' +import { LiquidityStakingTaskCard } from './partials/LiquidityStakingTaskCard' + +const ContentWrapper = styled(AutoColumn)` + width: 100%; + background-color: ${({ theme }) => theme.dark1}; + padding: 32px; + overflow-y: auto; +` + +const Text = ({ children }: { children: ReactNode }) => ( + + {children} + +) + +export interface ExpeditionsModalProps { + onDismiss: () => void +} + +export function ExpeditionsModal({ onDismiss }: ExpeditionsModalProps) { + const open = useShowExpeditionsPopup() + + return ( + + + + + SwprLogo + Swapr Expeditions + + + + Expeditions are missions you can complete on Swapr to earn “Star Fragments”. These can be redeemed for + special NFT's and various other rewards. + + + + Learn More + + + + + + + + + ) +} diff --git a/src/modules/expeditions/components/ExpeditionsModal/index.ts b/src/modules/expeditions/components/ExpeditionsModal/index.ts new file mode 100644 index 000000000..e2b12b3dc --- /dev/null +++ b/src/modules/expeditions/components/ExpeditionsModal/index.ts @@ -0,0 +1 @@ +export * from './ExpeditionsModal' diff --git a/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityProvisionTaskCard/LiquidityProvisionTaskCard.tsx b/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityProvisionTaskCard/LiquidityProvisionTaskCard.tsx new file mode 100644 index 000000000..d433a85ee --- /dev/null +++ b/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityProvisionTaskCard/LiquidityProvisionTaskCard.tsx @@ -0,0 +1,64 @@ +import { useContext, useState } from 'react' + +import { claimUserWeeklyFragments } from '../../../../api' +import { WeeklyFragmentType } from '../../../../constants' +import { ExpeditionsContext } from '../../../../contexts/ExpeditionsContext' +import { computeFragmentState } from '../../../../utils' +import { TaskCard as TaskCardBase, TaskCardProps } from '../../../ExpeditionsCard' + +const TaskCard = (props: Omit) => ( + +) + +export function LiquidityProvisionTaskCard() { + const [isClaiming, setIsClaiming] = useState(false) + const { rewards, isLoading, provider } = useContext(ExpeditionsContext) + + if (isLoading) { + return + } + + const { liquidityProvision } = rewards + const { isAvailableToClaim, isClaimed, isIncomplete } = computeFragmentState(liquidityProvision) + + const claimFrgments = async () => { + if (!isClaimed && !isAvailableToClaim && !isClaiming) { + return + } + + setIsClaiming(true) + try { + const address = await provider.getSigner().getAddress() + const signature = await provider.getSigner().signMessage('Claim Swapr weekly liquidity provision fragments') + await claimUserWeeklyFragments({ address, signature, type: WeeklyFragmentType.LIQUIDITY_PROVISION }) + } catch (error) { + console.error(error) + } finally { + setIsClaiming(true) + } + } + + let buttonText: string = '' + + if (isClaimed) { + buttonText = 'Claimed' + } else if (isAvailableToClaim) { + buttonText = `Claim ${liquidityProvision.claimableFragments} Fragments` + } else if (isIncomplete) { + buttonText = 'TASK NOT YET COMPLETED' + } + + return ( + 0 ? 'active' : 'upcoming'} + butttonDisabled={isIncomplete} + onClick={claimFrgments} + /> + ) +} diff --git a/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityProvisionTaskCard/index.ts b/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityProvisionTaskCard/index.ts new file mode 100644 index 000000000..a47886313 --- /dev/null +++ b/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityProvisionTaskCard/index.ts @@ -0,0 +1 @@ +export * from './LiquidityProvisionTaskCard' diff --git a/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityStakingTaskCard/LiquidityStakingTaskCard.tsx b/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityStakingTaskCard/LiquidityStakingTaskCard.tsx new file mode 100644 index 000000000..5f05d4b16 --- /dev/null +++ b/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityStakingTaskCard/LiquidityStakingTaskCard.tsx @@ -0,0 +1,67 @@ +import { useContext, useState } from 'react' + +import { claimUserWeeklyFragments } from '../../../../api' +import { WeeklyFragmentType } from '../../../../constants' +import { ExpeditionsContext } from '../../../../contexts/ExpeditionsContext' +import { computeFragmentState } from '../../../../utils' +import { TaskCard as TaskCardBase, TaskCardProps } from '../../../ExpeditionsCard' + +const TaskCard = (props: Omit) => ( + +) + +export function LiquidityStakingTaskCard() { + const [isClaiming, setIsClaiming] = useState(false) + const { rewards, isLoading, provider } = useContext(ExpeditionsContext) + + if (isLoading) { + return + } + + const { liquidityStaking } = rewards + const { isAvailableToClaim, isClaimed, isIncomplete } = computeFragmentState(liquidityStaking) + + const claimFrgments = async () => { + if (!isClaimed && !isAvailableToClaim && !isClaiming) { + return + } + + setIsClaiming(true) + try { + const address = await provider.getSigner().getAddress() + const signature = await provider.getSigner().signMessage('Claim Swapr weekly liquidity staking fragments') + await claimUserWeeklyFragments({ address, signature, type: WeeklyFragmentType.LIQUIDITY_STAKING }) + // Update local state + } catch (error) { + console.error(error) + } finally { + setIsClaiming(true) + } + } + + let buttonText: string = '' + + if (isClaiming) { + buttonText = 'Claiming...' + } else if (isClaimed) { + buttonText = 'Claimed' + } else if (isAvailableToClaim) { + buttonText = `Claim ${liquidityStaking.claimableFragments} Fragments` + } else if (isIncomplete) { + buttonText = 'TASK NOT YET COMPLETED' + } + + return ( + 0 ? 'active' : 'upcoming'} + butttonDisabled={isIncomplete} + onClick={claimFrgments} + /> + ) +} diff --git a/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityStakingTaskCard/index.ts b/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityStakingTaskCard/index.ts new file mode 100644 index 000000000..9ec2af81c --- /dev/null +++ b/src/modules/expeditions/components/ExpeditionsModal/partials/LiquidityStakingTaskCard/index.ts @@ -0,0 +1 @@ +export * from './LiquidityStakingTaskCard' diff --git a/src/modules/expeditions/index.tsx b/src/modules/expeditions/index.tsx new file mode 100644 index 000000000..336ce12bb --- /dev/null +++ b/src/modules/expeditions/index.tsx @@ -0,0 +1 @@ +export {} diff --git a/src/modules/expeditions/utils/index.ts b/src/modules/expeditions/utils/index.ts new file mode 100644 index 000000000..9f1ed01c7 --- /dev/null +++ b/src/modules/expeditions/utils/index.ts @@ -0,0 +1,13 @@ +import { WeeklyFragmentRewards } from '../api' + +export function computeFragmentState(rewards: WeeklyFragmentRewards) { + const isClaimed = rewards.claimedFragments > 0 + const isAvailableToClaim = rewards.claimableFragments > 0 + const isIncomplete = !isClaimed && !isAvailableToClaim + + return { + isClaimed, + isAvailableToClaim, + isIncomplete, + } +}