mirror of https://github.com/certusone/oyster.git
feat: auction
This commit is contained in:
parent
3807f564c3
commit
2a8a65feb0
|
@ -1,28 +1,116 @@
|
|||
import React from 'react'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { Card } from 'antd'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
// import { useHistory } from 'react-router-dom'
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
Divider,
|
||||
Button,
|
||||
InputNumber
|
||||
} from 'antd'
|
||||
|
||||
import { Auction } from '../../types'
|
||||
import { Auction, Presale } from '../../types'
|
||||
|
||||
import './index.less'
|
||||
import { getCountdown } from '../../utils/utils'
|
||||
import { solanaToUSD } from '../../utils/assets'
|
||||
|
||||
const Price = ({amt}: {amt: number}) => {
|
||||
const [USDamt, setUSDamt] = useState<number>(0)
|
||||
|
||||
export const AuctionCard = ({ auction, sold }: { auction: Auction, sold?: boolean }) => {
|
||||
const history = useHistory()
|
||||
|
||||
const handleCoverClick = async () => {
|
||||
history.push(auction.link)
|
||||
}
|
||||
useEffect(() => {
|
||||
solanaToUSD(amt).then(setUSDamt)
|
||||
}, [amt])
|
||||
|
||||
return (
|
||||
<Card
|
||||
hoverable
|
||||
style={{ width: 210, textAlign: 'left' }}
|
||||
cover={<img alt={auction.name} src={auction.image} onClick={handleCoverClick} />}
|
||||
>
|
||||
<div>{auction.name}</div>
|
||||
<a href={auction.auctionerLink}>{auction.auctionerName}</a>
|
||||
<div className="auction-bid">{sold ? 'SOLD' : 'Highest Bid:'} <span style={{color: '#13c2c2'}}>${auction.highestBid}</span> / ◎{auction.solAmt}</div>
|
||||
</Card>
|
||||
<div>
|
||||
<span className="cd-number">◎{amt}</span>
|
||||
<span className="cd-label">${USDamt.toFixed(2)}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const AuctionCard = ({ auction }: { auction: Auction }) => {
|
||||
const [hours, setHours] = useState<number>(23)
|
||||
const [minutes, setMinutes] = useState<number>(59)
|
||||
const [seconds, setSeconds] = useState<number>(59)
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
const { hours, minutes, seconds } = getCountdown(auction.endingTS)
|
||||
|
||||
setHours(hours)
|
||||
setMinutes(minutes)
|
||||
setSeconds(seconds)
|
||||
}, 1000)
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="presale-card-container">
|
||||
<div className="info-header">STARTING BID</div>
|
||||
<div style={{ fontWeight: 700, fontSize: '1.6rem' }}>◎40.00</div>
|
||||
<br/>
|
||||
<div className="info-header">AUCTION ENDS IN</div>
|
||||
<Row style={{ width: 300 }}>
|
||||
<Col span={8}>
|
||||
<div className="cd-number">{hours || '--'}</div>
|
||||
<div className="cd-label">hours</div>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<div className="cd-number">{minutes || '--'}</div>
|
||||
<div className="cd-label">minutes</div>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<div className="cd-number">{seconds || '--'}</div>
|
||||
<div className="cd-label">seconds</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<br/>
|
||||
<div className="info-content" style={{ color: 'rgba(255, 255, 255, 0.7)', fontSize: '0.9rem' }}>
|
||||
Any bids placed in the last 15 minutes will extend the auction for another 15 minutes.
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div className="info-line"/>
|
||||
|
||||
<InputNumber
|
||||
autoFocus
|
||||
className="input"
|
||||
placeholder="Max 50 characters"
|
||||
// value={props.attributes.name}
|
||||
// onChange={info =>
|
||||
// props.setAttributes({
|
||||
// ...props.attributes,
|
||||
// name: info.target.value,
|
||||
// })
|
||||
// }
|
||||
/>
|
||||
|
||||
<div className="info-content" style={{ color: 'rgba(255, 255, 255, 0.7)', fontSize: '0.9rem' }}>
|
||||
Your Balance: ◎ {0.0} (${0.0})
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
className="action-btn"
|
||||
style={{ marginTop: 20 }}
|
||||
>
|
||||
PLACE BID
|
||||
</Button>
|
||||
|
||||
{/* <div className="info-header">TARGET PRICE PER SHARE (NVA)</div>
|
||||
<div><Price amt={auction.targetPricePerShare as number}/></div>
|
||||
<Divider />
|
||||
<div className="info-header">PRICE PER SHARE (NVA)</div>
|
||||
<div><Price amt={auction.pricePerShare as number}/></div>
|
||||
<br />
|
||||
<div className="info-header">MARKET CAP</div>
|
||||
<div><Price amt={auction.marketCap as number}/></div> */}
|
||||
{/* <Row>
|
||||
<Col span={12}><Button className="primary-button">BUY SHARES</Button></Col>
|
||||
<Col span={12}><Button className="gradients-metal">SELL SHARES</Button></Col>
|
||||
</Row> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
padding: 30px;
|
||||
}
|
||||
|
||||
.info-line {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: rgba(255, 255, 255, 0.2);;
|
||||
}
|
||||
|
||||
.info-header {
|
||||
font-size: 1rem;
|
||||
font-style: normal;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from './useArt';
|
||||
export * from './useAuctions';
|
||||
export * from './useUserArts';
|
||||
export * from './useAuction';
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import { sampleAuction } from '../views/home/sampleData';
|
||||
import { useMeta } from './../contexts';
|
||||
|
||||
export const useAuction = (id: string) => {
|
||||
const { metadata } = useMeta();
|
||||
|
||||
return sampleAuction;
|
||||
}
|
|
@ -8,6 +8,8 @@ export interface Auction {
|
|||
solAmt: number;
|
||||
link: string;
|
||||
image: string;
|
||||
|
||||
endingTS: number;
|
||||
}
|
||||
|
||||
export interface Artist {
|
||||
|
|
|
@ -1,9 +1,47 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Row, Col, Divider, Layout, Image } from 'antd';
|
||||
import { AuctionCard } from '../../components/AuctionCard';
|
||||
import { useArt, useAuction } from '../../hooks';
|
||||
import { ArtContent } from '../../components/ArtContent';
|
||||
import { sampleArtist } from '../home/sampleData';
|
||||
|
||||
const { Content } = Layout
|
||||
|
||||
export const AuctionView = () => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const auction = useAuction(id);
|
||||
const art = useArt(id);
|
||||
const artist = sampleArtist
|
||||
|
||||
return (
|
||||
<div className="flexColumn" style={{ flex: 1 }}>
|
||||
TODO: Auction view
|
||||
</div>
|
||||
<Content>
|
||||
<Col>
|
||||
<Row>
|
||||
<ArtContent category={art.category} content={art.image} className="artwork-image" />
|
||||
</Row>
|
||||
<Divider />
|
||||
<Row style={{ margin: '0 30px', textAlign: 'left', fontSize: '1.4rem' }}>
|
||||
<Col span={12} >
|
||||
<div style={{ fontWeight: 700 }}>{art.title}</div>
|
||||
<br />
|
||||
<div className="info-header">CREATED BY</div>
|
||||
<div className="info-content"><img src={artist.image} className="artist-image" /> @{art.artist}</div>
|
||||
<br />
|
||||
<div className="info-header">CREATOR ROYALTIES</div>
|
||||
<div className="royalties">{art.royalties}%</div>
|
||||
<br />
|
||||
<div className="info-header">ABOUT THE CREATION</div>
|
||||
<div className="info-content">{art.about}</div>
|
||||
<br />
|
||||
<div className="info-header">ABOUT THE CREATOR</div>
|
||||
<div className="info-content">{artist.about}</div>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<AuctionCard auction={auction} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Content>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ export const sampleAuction: Auction = {
|
|||
solAmt: 200,
|
||||
link: '/auction/1234abcd',
|
||||
image: 'img/auction1.jpg',
|
||||
endingTS: 1618447663000,
|
||||
};
|
||||
|
||||
export const sampleAuctions: Array<Auction> = [
|
||||
|
@ -19,6 +20,7 @@ export const sampleAuctions: Array<Auction> = [
|
|||
solAmt: 115,
|
||||
link: '/auction/1234abcd',
|
||||
image: 'img/auction2.jpg',
|
||||
endingTS: 1618447663000,
|
||||
},
|
||||
{
|
||||
name: 'Miko 4',
|
||||
|
@ -29,6 +31,7 @@ export const sampleAuctions: Array<Auction> = [
|
|||
solAmt: 75,
|
||||
link: '/auction/1234abcd',
|
||||
image: 'img/auction3.jpg',
|
||||
endingTS: 1618447663000,
|
||||
},
|
||||
{
|
||||
name: 'Tell Me',
|
||||
|
@ -38,6 +41,7 @@ export const sampleAuctions: Array<Auction> = [
|
|||
solAmt: 120,
|
||||
link: '/auction/1234abcd',
|
||||
image: 'img/auction4.jpg',
|
||||
endingTS: 1618447663000,
|
||||
},
|
||||
{
|
||||
name: 'Saucy',
|
||||
|
@ -47,6 +51,7 @@ export const sampleAuctions: Array<Auction> = [
|
|||
solAmt: 200,
|
||||
link: '/auction/1234abcd',
|
||||
image: 'img/auction5.jpg',
|
||||
endingTS: 1618447663000,
|
||||
},
|
||||
{
|
||||
name: 'Haze',
|
||||
|
@ -56,6 +61,7 @@ export const sampleAuctions: Array<Auction> = [
|
|||
solAmt: 200,
|
||||
link: '/auction/1234abcd',
|
||||
image: 'img/auction6.jpg',
|
||||
endingTS: 1618447663000,
|
||||
},
|
||||
{
|
||||
name: 'Wounderground',
|
||||
|
@ -65,6 +71,7 @@ export const sampleAuctions: Array<Auction> = [
|
|||
solAmt: 200,
|
||||
link: '/auction/1234abcd',
|
||||
image: 'img/auction7.jpg',
|
||||
endingTS: 1618447663000,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
Loading…
Reference in New Issue