diff --git a/package.json b/package.json index 044312b5..e9a4dcc6 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "decimal.js": "^10.4.3", "humanize-duration": "^3.31.0", "javascript-time-ago": "^2.5.9", + "moment": "^2.30.1", "next": "^13.3.1", "notistack": "^3.0.1", "react": "^18.2.0", diff --git a/src/assets/dollar.png b/src/assets/dollar.png new file mode 100644 index 00000000..6e3e6b18 Binary files /dev/null and b/src/assets/dollar.png differ diff --git a/src/assets/graph.png b/src/assets/graph.png new file mode 100644 index 00000000..3b1f8b54 Binary files /dev/null and b/src/assets/graph.png differ diff --git a/src/assets/list.png b/src/assets/list.png new file mode 100644 index 00000000..bcc168c5 Binary files /dev/null and b/src/assets/list.png differ diff --git a/src/components/Elements/Buttons/ActionButton/index.module.scss b/src/components/Elements/Buttons/ActionButton/index.module.scss new file mode 100644 index 00000000..41e71bf8 --- /dev/null +++ b/src/components/Elements/Buttons/ActionButton/index.module.scss @@ -0,0 +1,8 @@ +.buttonContainer { + background:linear-gradient(180deg, #E84D68 0%, #AD2B49 100%); + border-radius: 100px; + font-weight: 500; + text-transform: none; + padding: 0.5rem 1.25rem; + font-size: 0.8rem; +} \ No newline at end of file diff --git a/src/components/Elements/Buttons/ActionButton/index.tsx b/src/components/Elements/Buttons/ActionButton/index.tsx new file mode 100644 index 00000000..f38eb933 --- /dev/null +++ b/src/components/Elements/Buttons/ActionButton/index.tsx @@ -0,0 +1,19 @@ +import { Button } from '@mui/material'; + +import styles from './index.module.scss'; + +interface ActionButtonProps { + label: string; + onClick: () => void; +} +export const ActionButton = ({ label, onClick }: ActionButtonProps) => { + return ( + + ); +}; diff --git a/src/components/Elements/Buttons/ProgressButton/index.module.scss b/src/components/Elements/Buttons/ProgressButton/index.module.scss new file mode 100644 index 00000000..41e71bf8 --- /dev/null +++ b/src/components/Elements/Buttons/ProgressButton/index.module.scss @@ -0,0 +1,8 @@ +.buttonContainer { + background:linear-gradient(180deg, #E84D68 0%, #AD2B49 100%); + border-radius: 100px; + font-weight: 500; + text-transform: none; + padding: 0.5rem 1.25rem; + font-size: 0.8rem; +} \ No newline at end of file diff --git a/src/components/Elements/Buttons/ProgressButton/index.tsx b/src/components/Elements/Buttons/ProgressButton/index.tsx new file mode 100644 index 00000000..29175669 --- /dev/null +++ b/src/components/Elements/Buttons/ProgressButton/index.tsx @@ -0,0 +1,25 @@ +import { LoadingButton } from '@mui/lab'; + +import styles from './index.module.scss'; + +interface ProgressButtonProps { + label: string; + onClick: () => void; + loading: boolean; +} +export const ProgressButton = ({ + label, + onClick, + loading, +}: ProgressButtonProps) => { + return ( + + {label} + + ); +}; diff --git a/src/components/Elements/Buttons/index.tsx b/src/components/Elements/Buttons/index.tsx new file mode 100644 index 00000000..1a65d096 --- /dev/null +++ b/src/components/Elements/Buttons/index.tsx @@ -0,0 +1,2 @@ +export * from './ActionButton'; +export * from './ProgressButton'; diff --git a/src/components/Elements/CoreDetailsPanel/index.module.scss b/src/components/Elements/CoreDetailsPanel/index.module.scss new file mode 100644 index 00000000..9fe0fd9e --- /dev/null +++ b/src/components/Elements/CoreDetailsPanel/index.module.scss @@ -0,0 +1,39 @@ +.container { + display: flex; + flex-direction: column; + gap: 2rem; + padding: 1.5rem; + flex-grow: 1; + box-shadow: 2px 2px 55px rgba(0, 0, 0, 0.08); +} + +.titleWrapper { + display: flex; + align-items: center; +} + +.iconWrapper { + width: 1.5rem; + height: 1.5rem; + margin: 0.5rem; +} + +.infoWrapper { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.detailWrapper { + display: flex; + justify-content: space-between; + padding: 1.5rem; +} + +.valueWrapper { + background: #ecf1f9; + padding: 0.5rem 0.75rem; + border-radius: 0.5rem; + display: flex; + align-items: center; +} diff --git a/src/components/Elements/CoreDetailsPanel/index.tsx b/src/components/Elements/CoreDetailsPanel/index.tsx new file mode 100644 index 00000000..0969d133 --- /dev/null +++ b/src/components/Elements/CoreDetailsPanel/index.tsx @@ -0,0 +1,94 @@ +import { Box, Paper, Typography, useTheme } from '@mui/material'; +import Image from 'next/image'; + +import GraphIcon from '@/assets/graph.png'; +import { SaleInfo } from '@/models'; + +import styles from './index.module.scss'; + +interface DetailItemProps { + label: string; + description: string; + value: number; +} + +const DetailItem = ({ label, description, value }: DetailItemProps) => { + const theme = useTheme(); + return ( + + + + {label} + + + {description} + + + + + {value} + + + + ); +}; + +interface CoreDetailsPanelProps { + saleInfo: SaleInfo; +} + +export const CoreDetailsPanel = ({ saleInfo }: CoreDetailsPanelProps) => { + const theme = useTheme(); + return ( + + + graph + + Core Details + + + + + + + + + ); +}; diff --git a/src/components/Elements/SaleInfo/index.tsx b/src/components/Elements/SaleInfo/index.tsx deleted file mode 100644 index 338e29a3..00000000 --- a/src/components/Elements/SaleInfo/index.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Box, Typography } from '@mui/material'; -import TimeAgo from 'javascript-time-ago'; -import en from 'javascript-time-ago/locale/en.json'; - -import { formatBalance } from '@/utils/functions'; - -import { useCoretimeApi } from '@/contexts/apis'; -import { SaleInfo, SalePhase } from '@/models'; - -import styles from './index.module.scss'; - -interface SaleInfoGridProps { - saleInfo: SaleInfo; - currentPhase: SalePhase; - currentPrice: number; - saleEndTimestamp: number; - saleStartTimestamp: number; -} - -export const SaleInfoGrid = ({ - saleInfo, - currentPhase, - currentPrice, - saleEndTimestamp, - saleStartTimestamp, -}: SaleInfoGridProps) => { - TimeAgo.addLocale(en); - const timeAgo = new TimeAgo('en-US'); - - const { - state: { symbol }, - } = useCoretimeApi(); - - const nextPhase = (): SalePhase => { - const phases = Object.values(SalePhase); - const currentIndex = phases.indexOf(currentPhase); - - // Calculate the index of the next phase - const nextIndex = (currentIndex + 1) % phases.length; - return phases[nextIndex]; - }; - - return ( - - - - {`Sale start: ${timeAgo.format(saleStartTimestamp)}`} - - - {`Sale ends ${timeAgo.format(saleEndTimestamp)}`} - - - - {`Current phase: ${currentPhase}`} - {`Upcoming phase: ${nextPhase()}`} - - - - {`Current price: ${formatBalance(currentPrice.toString(), false)} ${symbol}`} - - - {`Floor price: ${formatBalance(saleInfo.price.toString(), false)} ${symbol}`} - - - - - - {`Cores offered: ${saleInfo.coresOffered}`} - - Number of cores which are offered for sale. - - - - - - {`Cores sold: ${saleInfo.coresSold}`} - - Number of cores which have been sold - - - - - - {`Ideal cores sold: ${saleInfo.idealCoresSold}`} - - - Number of cores sold to not affect the price for next sale - - - - - ); -}; diff --git a/src/components/Elements/SaleInfoPanel/DetailCard/index.module.scss b/src/components/Elements/SaleInfoPanel/DetailCard/index.module.scss new file mode 100644 index 00000000..4292c791 --- /dev/null +++ b/src/components/Elements/SaleInfoPanel/DetailCard/index.module.scss @@ -0,0 +1,31 @@ +.container { + display: flex; + flex-direction: column; + padding: 1rem 2rem; + border-radius: .5rem; + gap: 1.5rem; +} + +.titleWrapper { + display: flex; + align-items: center; +} + +.iconWrapper { + margin: 0.5rem; + margin-left: 0; + width: 2rem; + height: 2rem; +} + +.infoSection { + display: flex; + align-items: center; + justify-content: space-between; +} + +.infoItem { + display: flex; + flex-direction: column; + gap: 0.5rem; +} \ No newline at end of file diff --git a/src/components/Elements/SaleInfoPanel/DetailCard/index.tsx b/src/components/Elements/SaleInfoPanel/DetailCard/index.tsx new file mode 100644 index 00000000..6da14b9e --- /dev/null +++ b/src/components/Elements/SaleInfoPanel/DetailCard/index.tsx @@ -0,0 +1,49 @@ +import { Box, Paper, Typography, useTheme } from '@mui/material'; +import Image from 'next/image'; + +import styles from './index.module.scss'; + +interface ItemDetail { + label: string; + value: string; +} + +interface DetailCardProps { + icon: any; + title: string; + left: ItemDetail; + right: ItemDetail; +} + +const ItemContainer = ({ label, value }: ItemDetail) => { + const theme = useTheme(); + return ( + + {label} + + {value} + + + ); +}; + +export const DetailCard = ({ icon, title, left, right }: DetailCardProps) => { + const theme = useTheme(); + return ( + + + icon + + {title} + + + + + + + + ); +}; diff --git a/src/components/Elements/SaleInfo/index.module.scss b/src/components/Elements/SaleInfoPanel/index.module.scss similarity index 100% rename from src/components/Elements/SaleInfo/index.module.scss rename to src/components/Elements/SaleInfoPanel/index.module.scss diff --git a/src/components/Elements/SaleInfoPanel/index.tsx b/src/components/Elements/SaleInfoPanel/index.tsx new file mode 100644 index 00000000..305579cf --- /dev/null +++ b/src/components/Elements/SaleInfoPanel/index.tsx @@ -0,0 +1,86 @@ +import { Box } from '@mui/material'; +import TimeAgo from 'javascript-time-ago'; +import en from 'javascript-time-ago/locale/en.json'; +import moment from 'moment'; + +import { formatBalance } from '@/utils/functions'; + +import DollarIcon from '@/assets/dollar.png'; +import ListIcon from '@/assets/list.png'; +import ShoppingIcon from '@/assets/shopping.png'; +import { useCoretimeApi } from '@/contexts/apis'; +import { SaleInfo, SalePhase } from '@/models'; + +import { DetailCard } from './DetailCard'; + +interface SaleInfoGridProps { + saleInfo: SaleInfo; + currentPhase: SalePhase; + currentPrice: number; + saleEndTimestamp: number; + saleStartTimestamp: number; +} + +export const SaleInfoPanel = ({ + saleInfo, + currentPhase, + currentPrice, + saleEndTimestamp, + saleStartTimestamp, +}: SaleInfoGridProps) => { + TimeAgo.addLocale(en); + const { + state: { symbol }, + } = useCoretimeApi(); + + const nextPhase = (): SalePhase => { + const phases = Object.values(SalePhase); + const currentIndex = phases.indexOf(currentPhase); + + // Calculate the index of the next phase + const nextIndex = (currentIndex + 1) % phases.length; + return phases[nextIndex]; + }; + + return ( + + + + + + ); +}; diff --git a/src/components/Elements/index.ts b/src/components/Elements/index.ts index 6b96619d..0456f2fd 100644 --- a/src/components/Elements/index.ts +++ b/src/components/Elements/index.ts @@ -1,10 +1,13 @@ export * from './AmountInput'; export * from './Banner'; +export * from './Buttons'; +export * from './CoreDetailsPanel'; export * from './FeatureCard'; export * from './Label'; export * from './ListingCard'; export * from './MarketFilters'; export * from './Progress'; export * from './RegionCard'; -export * from './SaleInfo'; +export * from './SaleInfoPanel'; +export * from './Selectors'; export * from './StatusIndicator'; diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 4ea3b70e..7f033806 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,7 +1,6 @@ import { ExpandMore } from '@mui/icons-material'; import { Box, - Button, Collapse, Divider, List, @@ -12,6 +11,7 @@ import { useInkathon } from '@scio-labs/use-inkathon'; import React, { useState } from 'react'; import styles from './index.module.scss'; +import { ActionButton } from '../Elements'; import { WalletModal } from '../Modals/WalletConnect'; export const Header = () => { @@ -96,13 +96,10 @@ export const Header = () => { ) : ( - + label='Connect Wallet' + /> )} diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index 76c86ddd..42e81386 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -1,4 +1,3 @@ -import { Paper } from '@mui/material'; import React, { ReactElement } from 'react'; import styles from './index.module.scss'; @@ -15,18 +14,7 @@ export const Layout = ({ children }: Props) => {
- -
{children}
-
+
{children}
); diff --git a/src/components/index.ts b/src/components/index.ts index ea987eed..93333dfa 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,5 +1,4 @@ export * from './Elements'; -export * from './Elements/Selectors'; export * from './Header'; export * from './Layout'; export * from './Modals'; diff --git a/src/pages/purchase.tsx b/src/pages/purchase.tsx index b91cca66..24a869da 100644 --- a/src/pages/purchase.tsx +++ b/src/pages/purchase.tsx @@ -1,4 +1,3 @@ -import { LoadingButton } from '@mui/lab'; import { Box, Button, Typography, useTheme } from '@mui/material'; import { useInkathon } from '@scio-labs/use-inkathon'; import TimeAgo from 'javascript-time-ago'; @@ -11,7 +10,7 @@ import useSalePhase from '@/hooks/salePhase'; import useSalePrice from '@/hooks/salePrice'; import { formatBalance } from '@/utils/functions'; -import { Progress, SaleInfoGrid } from '@/components'; +import { CoreDetailsPanel, ProgressButton, SaleInfoPanel } from '@/components'; import { useCoretimeApi } from '@/contexts/apis'; import { ApiState } from '@/contexts/apis/types'; @@ -25,7 +24,6 @@ const Purchase = () => { const [working, setWorking] = useState(false); TimeAgo.addLocale(en); // Create formatter (English). - const timeAgo = new TimeAgo('en-US'); const { activeSigner, activeAccount } = useInkathon(); const { toastError, toastSuccess, toastInfo } = useToast(); @@ -39,13 +37,8 @@ const Purchase = () => { const balance = useBalance(); const currentPrice = useSalePrice(); - const { - currentPhase, - progress, - saleStartTimestamp, - saleEndTimestamp, - saleSections, - } = useSalePhase(); + const { currentPhase, progress, saleStartTimestamp, saleEndTimestamp } = + useSalePhase(); const purchase = async () => { if (!api || apiState !== ApiState.READY || !activeAccount || !activeSigner) @@ -86,6 +79,7 @@ const Purchase = () => { sx={{ display: 'flex', justifyContent: 'space-between', + alignItems: 'center', }} > @@ -99,11 +93,14 @@ const Purchase = () => { variant='subtitle2' sx={{ color: theme.palette.text.primary }} > - Purchase a core directly from the Coretime chain + Buy a core straight from the Coretime chain - {`Your balance: ${formatBalance(balance.toString(), false)} ${symbol}`} + {`Your balance: ${formatBalance( + balance.toString(), + false + )} ${symbol}`} @@ -114,40 +111,25 @@ const Purchase = () => { !saleEndTimestamp ? ( <> - Connect your wallet + Check your network conection and connect your wallet ) : ( - <> - - - - - - Current Bulk Sale: - Ends {timeAgo.format(saleEndTimestamp)} - - - - + + + + + + { - - Purchase - + label='Purchase Core' + /> - + )} diff --git a/src/pages/regions.tsx b/src/pages/regions.tsx index cfdfa542..5446d679 100644 --- a/src/pages/regions.tsx +++ b/src/pages/regions.tsx @@ -5,6 +5,7 @@ import { Box, Button, CircularProgress, + Paper, Typography, useTheme, } from '@mui/material'; @@ -176,11 +177,10 @@ const Dashboard = () => { )} - { ))} - + {regionSelected && ( <>