diff --git a/packages/atlas/src/components/_crt/StartRevenueShareModal/StartRevenueShareModal.tsx b/packages/atlas/src/components/_crt/StartRevenueShareModal/StartRevenueShareModal.tsx new file mode 100644 index 0000000000..bffffdc62b --- /dev/null +++ b/packages/atlas/src/components/_crt/StartRevenueShareModal/StartRevenueShareModal.tsx @@ -0,0 +1,231 @@ +import styled from '@emotion/styled' +import { useCallback, useMemo, useState } from 'react' +import { Controller, useForm } from 'react-hook-form' + +import { FlexBox } from '@/components/FlexBox/FlexBox' +import { JoyTokenIcon } from '@/components/JoyTokenIcon' +import { NumberFormat } from '@/components/NumberFormat' +import { Text } from '@/components/Text' +import { TextButton } from '@/components/_buttons/Button' +import { AuctionDatePicker, AuctionDatePickerProps } from '@/components/_inputs/AuctionDatePicker' +import { FormField } from '@/components/_inputs/FormField' +import { TokenInput } from '@/components/_inputs/TokenInput' +import { DetailsContent } from '@/components/_nft/NftTile' +import { DialogModal } from '@/components/_overlays/DialogModal' +import { useMediaMatch } from '@/hooks/useMediaMatch' +import { pluralizeNoun } from '@/utils/misc' + +export type SellTokenModalProps = { + tokenId: string + onClose: () => void + show: boolean +} + +const getTokenDetails = (_: string) => ({ + title: 'JBC', + pricePerUnit: 1000, + tokensOnSale: 67773, + userBalance: 100000, + patronageRate: 0.8, +}) + +const datePickerItemsFactory = (days: number[]) => + days.map((value) => ({ + name: pluralizeNoun(value, 'day'), + value: { + type: 'duration' as const, + durationDays: value, + }, + })) + +const endDateItems = datePickerItemsFactory([7, 14, 30]) + +export const StartRevenueShare = ({ tokenId, onClose, show }: SellTokenModalProps) => { + const [tokens, setTokens] = useState(null) + const smMatch = useMediaMatch('sm') + const { patronageRate, userBalance, title } = getTokenDetails(tokenId) + + const form = useForm<{ + tokens: number | null + startDate: AuctionDatePickerProps['value'] | null + endDate: AuctionDatePickerProps['value'] | null + }>() + const { trigger, control, watch } = form + + const details = useMemo( + () => [ + { + title: 'You will receive', + content: ( + + + + ({Math.round(patronageRate * 100)}%) + + + ), + }, + { + title: 'You will spend', + content: ( + + + + ( {Math.round(1 - patronageRate) * 100}%) + + + ), + }, + ], + [patronageRate, tokens] + ) + + const [startDate, endDate] = watch(['startDate', 'endDate']) + + const selectDurationToDate = useCallback((value: AuctionDatePickerProps['value'], base?: Date) => { + if (value?.type === 'date') { + return value.date + } + + if (value?.type === 'duration') { + const now = base ? new Date(base.getTime()) : new Date() + now.setDate(now.getDate() + value.durationDays) + return now + } + return undefined + }, []) + + return ( + + + + } + withDenomination + /> + + + + + $0.00 + + Max + + } + /> + + + + {details.map((row) => ( + + + + {row.title} + + + {row.content} + + ))} + + + + ( + + + + { + onChange(value) + trigger('startDate') + }} + value={value} + /> + + + + )} + /> + ( + + + + { + onChange(value) + trigger('endDate') + }} + value={value} + /> + + + + )} + /> + + + + ) +} + +const OuterBox = styled.div` + position: relative; + height: 50px; +` + +const InnerBox = styled.div` + position: absolute; + inset: 0; +` diff --git a/packages/atlas/src/components/_inputs/AuctionDatePicker/AuctionDatePicker.tsx b/packages/atlas/src/components/_inputs/AuctionDatePicker/AuctionDatePicker.tsx index 6cb9f41368..c3c5e3175c 100644 --- a/packages/atlas/src/components/_inputs/AuctionDatePicker/AuctionDatePicker.tsx +++ b/packages/atlas/src/components/_inputs/AuctionDatePicker/AuctionDatePicker.tsx @@ -136,6 +136,7 @@ export const AuctionDatePicker: FC = ({ offset={[0, 8]} ref={popOverRef} triggerMode="manual" + appendTo={document.body} triggerTarget={selectRef.current} trigger={null} onShow={() => { diff --git a/packages/atlas/src/views/studio/CrtDashboard/CrtDashboard.tsx b/packages/atlas/src/views/studio/CrtDashboard/CrtDashboard.tsx index 4defa9590f..9a9703464d 100644 --- a/packages/atlas/src/views/studio/CrtDashboard/CrtDashboard.tsx +++ b/packages/atlas/src/views/studio/CrtDashboard/CrtDashboard.tsx @@ -1,7 +1,13 @@ import BN from 'bn.js' import { useCallback, useState } from 'react' -import { SvgActionChevronR, SvgActionEdit, SvgActionLinkUrl, SvgActionSell } from '@/assets/icons' +import { + SvgActionChevronR, + SvgActionEdit, + SvgActionLinkUrl, + SvgActionRevenueShare, + SvgActionSell, +} from '@/assets/icons' import { LimitedWidthContainer } from '@/components/LimitedWidthContainer' import { NumberFormat } from '@/components/NumberFormat' import { Tabs } from '@/components/Tabs' @@ -9,6 +15,7 @@ import { Text } from '@/components/Text' import { WidgetTile } from '@/components/WidgetTile' import { Button, TextButton } from '@/components/_buttons/Button' import { HoldersTable } from '@/components/_crt/HoldersTable/HoldersTable' +import { StartRevenueShare } from '@/components/_crt/StartRevenueShareModal/StartRevenueShareModal' import { BigWidgetContainer, HeaderContainer, @@ -25,6 +32,7 @@ const TABS = ['Dashboard', 'Holders', 'Revenue share', 'Settings'] as const export const CrtDashboard = () => { const [currentTab, setCurrentTab] = useState(0) + const [openRevenueShareModal, setOpenRevenueShareModal] = useState(false) const handleChangeTab = useCallback((idx: number) => { setCurrentTab(idx) }, []) @@ -33,6 +41,7 @@ export const CrtDashboard = () => { return ( + setOpenRevenueShareModal(false)} /> @@ -45,10 +54,19 @@ export const CrtDashboard = () => { - - + {currentTab === 0 && ( + <> + + + + )} + {currentTab === 2 && ( + + )} {currentTab === 1 && (