add styles
This commit is contained in:
parent
3fc789bb02
commit
e693462f0f
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "cryptocurrency-converter",
|
"name": "cryptocurrency-converter",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"homepage": "https://dmitry220.github.io/crypto-converter",
|
"homepage": "https://vbatischev1.github.io/crypto-converter",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/react-query": "^5.0.0-beta.9",
|
"@tanstack/react-query": "^5.0.0-beta.9",
|
||||||
|
88
src/App.scss
88
src/App.scss
@ -1,8 +1,16 @@
|
|||||||
|
body{
|
||||||
|
background: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.converter{
|
.converter{
|
||||||
|
|
||||||
max-width: 812px;
|
max-width: 610px;
|
||||||
margin: 50px auto;
|
margin: 50px auto;
|
||||||
padding: 0 15px;
|
background: #fff;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
|
||||||
&__head{
|
&__head{
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@ -26,6 +34,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__row{
|
&__row{
|
||||||
|
border-radius: 10px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -39,10 +48,11 @@
|
|||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
&_border{
|
&_border{
|
||||||
border: 3px solid gray;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
&__crypto-name{
|
&__crypto-name{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
@ -50,42 +60,52 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 15px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
display: flex;
|
border-left: 2px solid rgba(7, 28, 71, 0.12);
|
||||||
align-items: center;
|
font-weight: 700;
|
||||||
flex-direction: column;
|
border: 2px solid rgba(7, 28, 71, 0.12);
|
||||||
|
border-left: none;
|
||||||
|
border-radius: 0 10px 10px 0;
|
||||||
|
&-title{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
img{
|
img{
|
||||||
width: 50px;
|
width: 40px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__arrow{
|
&__arrow{
|
||||||
width: 50px;
|
|
||||||
height: 35px;
|
height: 35px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@media (max-width:768px) {
|
width: 20px;
|
||||||
height: 50px;
|
background: #999;
|
||||||
width: 50px;
|
-webkit-mask: url(//yastatic.net/s3/web4static/_/v2/static/media/Swap_16.c0236c02.svg) no-repeat center;
|
||||||
}
|
mask: url(//yastatic.net/s3/web4static/_/v2/static/media/Swap_16.c0236c02.svg) no-repeat center;
|
||||||
@media (max-width:576px) {
|
|
||||||
height: 25px;
|
|
||||||
width: 25px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__input{
|
&__input{
|
||||||
|
border: 2px solid rgba(7, 28, 71, 0.12);
|
||||||
|
border-radius: 10px 0 0 10px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-family: HelveticaNeue-Light,"Helvetica Neue Light",Helvetica,Arial,sans-serif;
|
font-family: HelveticaNeue-Light,"Helvetica Neue Light",Helvetica,Arial,sans-serif;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
width: 201px;
|
||||||
color: #000;
|
color: #000;
|
||||||
border-width: 0 5px 0px 0px;
|
position: relative;
|
||||||
border-color: rgb(107 107 107);
|
top: 0;
|
||||||
|
padding: 0 10px 0 0;
|
||||||
|
outline: none;
|
||||||
@media (max-width:768px) {
|
@media (max-width:768px) {
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
}
|
}
|
||||||
@ -94,34 +114,4 @@
|
|||||||
&__footer{
|
&__footer{
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.popup-converter{
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
inset: 75px auto auto 0;
|
|
||||||
width: 95%;
|
|
||||||
box-shadow: 0 4px 24px rgba(0,0,0,.25);
|
|
||||||
background: #fff;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 10px;
|
|
||||||
gap: 12px;
|
|
||||||
border-radius: 5px;
|
|
||||||
&__button{
|
|
||||||
background: transparent;
|
|
||||||
transition: 0.3s all ease;
|
|
||||||
padding: 10px;
|
|
||||||
font-size: 18px;
|
|
||||||
cursor: pointer;
|
|
||||||
border: none;
|
|
||||||
&_active{
|
|
||||||
background: green;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
&:hover{
|
|
||||||
background: green;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
297
src/App.tsx
297
src/App.tsx
@ -1,155 +1,194 @@
|
|||||||
import React, {ChangeEvent, useEffect, useRef, useState} from 'react';
|
import { ChangeEvent, useEffect, useRef, useState } from 'react';
|
||||||
import './App.scss';
|
import './App.scss';
|
||||||
import arrowSwap from '../src/assets/images/arrow-right-left.svg'
|
|
||||||
import btc from '../src/assets/images/btc.svg'
|
import btc from '../src/assets/images/btc.svg'
|
||||||
import usdt from '../src/assets/images/usdt.svg'
|
import usdt from '../src/assets/images/usdt.svg'
|
||||||
import eth from '../src/assets/images/eth.svg'
|
import eth from '../src/assets/images/eth.svg'
|
||||||
import useOnClickOutside from './hooks/useOnClickOutside';
|
import useOnClickOutside from './hooks/useOnClickOutside';
|
||||||
import {SecondValuationItem} from './Components/SecondValutionItem/SecondValutionItem';
|
import { PopupConverter } from './Components/popup-converter/Popup-converter';
|
||||||
import {FirstValuationItem} from './Components/FirstValutionItem/FirstValutionItem';
|
import { convert } from '.';
|
||||||
import {convert} from '.';
|
import { IValutions } from './models/IValutions';
|
||||||
import {IValutions} from './models/IValutions';
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
const valuations: IValutions[] = [
|
const valuations: IValutions[] = [
|
||||||
{
|
{
|
||||||
title: 'BTC',
|
title: 'BTC',
|
||||||
img: btc
|
img: btc,
|
||||||
},
|
alt: 'Bitcoin'
|
||||||
{
|
},
|
||||||
title: 'USDT',
|
{
|
||||||
img: usdt
|
title: 'USDT',
|
||||||
},
|
img: usdt,
|
||||||
{
|
alt: 'Tether'
|
||||||
title: 'ETH',
|
},
|
||||||
img: eth
|
{
|
||||||
},
|
title: 'ETH',
|
||||||
]
|
img: eth,
|
||||||
|
alt: 'Ethereum'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const [firstValue, setFirstValue] = useState<number>(0)
|
const [firstValue, setFirstValue] = useState<string>('1')
|
||||||
const [secondValue, setSecondValue] = useState<number>(0)
|
const [secondValue, setSecondValue] = useState<string>('1')
|
||||||
const [firstValuation, setFirstValuation] = useState<IValutions>(valuations[0])
|
const [firstValuation, setFirstValuation] = useState<IValutions>(valuations[0])
|
||||||
const [secondValuation, setSecondValuation] = useState<IValutions>(valuations[1])
|
const [secondValuation, setSecondValuation] = useState<IValutions>(valuations[1])
|
||||||
const [showFirstValuation, setShowFirstValuation] = useState<boolean>()
|
const [showFirstValuation, setShowFirstValuation] = useState<boolean>()
|
||||||
const [showSecondValuation, setShowSecondValuation] = useState<boolean>()
|
const [showSecondValuation, setShowSecondValuation] = useState<boolean>()
|
||||||
const [isSwap, setSwap] = useState(false)
|
const [isSwap, setSwap] = useState(true)
|
||||||
|
|
||||||
|
|
||||||
const handlerInputOne = (e: ChangeEvent<HTMLInputElement>) => {
|
const regexInput = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFirstValue(+e.target.value)
|
|
||||||
getSecondValuation(+e.target.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlerInputTwo = (e: ChangeEvent<HTMLInputElement>) => {
|
let [_, sign, integer, decimals]: any = e.target.value.replace(/[^\d\.\-]/g, "")
|
||||||
setSecondValue(+e.target.value)
|
.replace(/(\..*?)\./g, "$1")
|
||||||
getFirstValuation(+e.target.value)
|
.replace(/(.+)-/g, "$1")
|
||||||
}
|
.match(/^(-?)(.*?)((?:\.\d*)?)$/);
|
||||||
|
|
||||||
const openFirstListValuation = () => setShowFirstValuation(true)
|
let pos: number = Number(e.target.selectionStart) - 1;
|
||||||
|
if (!integer && decimals) pos += 2;
|
||||||
|
|
||||||
const openSecondListValuation = () => setShowSecondValuation(true)
|
if (integer || decimals) {
|
||||||
|
integer = +integer;
|
||||||
|
}
|
||||||
|
|
||||||
const getSecondValuation = async (value: number) => {
|
const formatted = sign + integer + decimals;
|
||||||
await convert.ready()
|
|
||||||
setSecondValue(convert[firstValuation.title][secondValuation.title](value))
|
|
||||||
|
|
||||||
}
|
if (formatted !== e.target.value) {
|
||||||
const getFirstValuation = async (value: number) => {
|
e.target.value = formatted;
|
||||||
await convert.ready()
|
e.target.setSelectionRange(pos, pos);
|
||||||
setFirstValue(convert[secondValuation.title][firstValuation.title](value))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const swap = () => {
|
|
||||||
setSwap(true)
|
|
||||||
setSecondValuation(firstValuation)
|
|
||||||
setFirstValuation(secondValuation)
|
|
||||||
}
|
|
||||||
|
|
||||||
useOnClickOutside(ref, () => {
|
|
||||||
setShowSecondValuation(false)
|
|
||||||
setShowFirstValuation(false)
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getSecondValuation(firstValue)
|
|
||||||
}, [firstValuation])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if(isSwap){
|
|
||||||
setSwap(false)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
getFirstValuation(secondValue)
|
|
||||||
}, [secondValuation])
|
const handlerInputOne = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
regexInput(e)
|
||||||
|
setFirstValue(e.target.value)
|
||||||
|
getSecondValuation(+e.target.value || 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlerInputTwo = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
regexInput(e)
|
||||||
|
setSecondValue(e.target.value)
|
||||||
|
getFirstValuation(+e.target.value || 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const openFirstListValuation = () => setShowFirstValuation(true)
|
||||||
|
|
||||||
|
const openSecondListValuation = () => setShowSecondValuation(true)
|
||||||
|
|
||||||
|
const getSecondValuation = async (value: number) => {
|
||||||
|
await convert.ready()
|
||||||
|
setSecondValue(convert[firstValuation.title][secondValuation.title](value) || 0)
|
||||||
|
|
||||||
|
}
|
||||||
|
const getFirstValuation = async (value: number) => {
|
||||||
|
await convert.ready()
|
||||||
|
setFirstValue(convert[secondValuation.title][firstValuation.title](value) || 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const swap = () => {
|
||||||
|
setSwap(true)
|
||||||
|
setSecondValuation(firstValuation)
|
||||||
|
setFirstValuation(secondValuation)
|
||||||
|
}
|
||||||
|
|
||||||
|
useOnClickOutside(ref, () => {
|
||||||
|
setShowSecondValuation(false)
|
||||||
|
setShowFirstValuation(false)
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getSecondValuation(+firstValue)
|
||||||
|
}, [firstValuation])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isSwap) {
|
||||||
|
setSwap(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
getFirstValuation(+secondValue)
|
||||||
|
}, [secondValuation])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
getSecondValuation(+firstValue)
|
||||||
|
}, 25000)
|
||||||
|
return () => clearInterval(interval)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="converter">
|
<div className="converter">
|
||||||
<div className="converter__head">
|
<div className="converter__body">
|
||||||
Тестовое задание. React. Typescript
|
<div className="converter__row converter__row_border">
|
||||||
</div>
|
<input className='converter__input' type="text" value={firstValue}
|
||||||
<div className="converter__body">
|
onChange={handlerInputOne} />
|
||||||
{ }
|
<span className='converter__crypto-name' onClick={openFirstListValuation}>
|
||||||
<div className="converter__row converter__row_border">
|
<div className={'converter__crypto-name-title'}>
|
||||||
<input className='converter__input' min={0} type="number" value={firstValue} onChange={handlerInputOne} />
|
<img src={firstValuation.img} alt="" />
|
||||||
<span className='converter__crypto-name' onClick={openFirstListValuation}>
|
{firstValuation.title}
|
||||||
<img src={firstValuation.img} alt="" />
|
</div>
|
||||||
{firstValuation.title}
|
<div>
|
||||||
|
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" width="8" height="14"><path
|
||||||
|
d="M4 0l4 6H0l4-6zm0 14l4-6H0l4 6z" /></svg>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
{showFirstValuation && <div className='converter__popup popup-converter' ref={ref}>
|
||||||
|
{valuations.map((item, index) =>
|
||||||
|
<PopupConverter
|
||||||
|
key={index}
|
||||||
|
item={item}
|
||||||
|
setValuation={setFirstValuation}
|
||||||
|
valuation={firstValuation.title}
|
||||||
|
|
||||||
</span>
|
/>)}
|
||||||
{showFirstValuation && <div className='converter__popup popup-converter' ref={ref}>
|
|
||||||
{valuations.map((item, index) =>
|
|
||||||
<FirstValuationItem
|
|
||||||
key={index}
|
|
||||||
item={item}
|
|
||||||
firstValuation={firstValuation.title}
|
|
||||||
setSecondValuation={setSecondValuation}
|
|
||||||
secondValuation={secondValuation.title}
|
|
||||||
setFirstValuation={setFirstValuation}
|
|
||||||
/>)}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
|
<div className="converter__row">
|
||||||
|
<div className={'converter__arrow'} onClick={swap} />
|
||||||
|
</div>
|
||||||
|
<div className="converter__row converter__row_border">
|
||||||
|
<input className='converter__input' min={0} type="text" maxLength={20} value={secondValue}
|
||||||
|
onChange={handlerInputTwo} />
|
||||||
|
<span className='converter__crypto-name' onClick={openSecondListValuation}>
|
||||||
|
<div className={'converter__crypto-name-title'}>
|
||||||
|
<img src={secondValuation.img} alt="" />
|
||||||
|
{secondValuation.title}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" width="8" height="14"><path
|
||||||
|
d="M4 0l4 6H0l4-6zm0 14l4-6H0l4 6z" /></svg>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
{showSecondValuation && <div className='converter__popup popup-converter' ref={ref}>
|
||||||
|
{valuations.map((item, index) =>
|
||||||
|
<PopupConverter
|
||||||
|
key={index}
|
||||||
|
item={item}
|
||||||
|
valuation={secondValuation.title}
|
||||||
|
setValuation={setSecondValuation}
|
||||||
|
/>)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer className="converter__footer">
|
||||||
|
<b>{(firstValue || 0) + ' ' + firstValuation.title + ' = ' + (secondValue || 0) + ' ' + secondValuation.title}</b>
|
||||||
|
<br />
|
||||||
|
Данные носят ознакомительный характер {'\t'}
|
||||||
|
<b>
|
||||||
|
{
|
||||||
|
new Date(convert.lastUpdated).toLocaleDateString() + ' ' +
|
||||||
|
new Date(convert.lastUpdated).getHours() + ':' +
|
||||||
|
new Date(convert.lastUpdated).getMinutes().toString().padStart(2, '0')
|
||||||
|
}
|
||||||
|
</b>
|
||||||
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
<div className="converter__row">
|
);
|
||||||
<img className='converter__arrow' src={arrowSwap} alt="" onClick={swap} />
|
|
||||||
</div>
|
|
||||||
<div className="converter__row converter__row_border">
|
|
||||||
<input className='converter__input' min={0} type="number" value={secondValue} onChange={handlerInputTwo} />
|
|
||||||
<span className='converter__crypto-name' onClick={openSecondListValuation}>
|
|
||||||
<img src={secondValuation.img} alt="" />
|
|
||||||
{secondValuation.title}
|
|
||||||
</span>
|
|
||||||
{showSecondValuation && <div className='converter__popup popup-converter' ref={ref}>
|
|
||||||
{valuations.map((item, index) =>
|
|
||||||
<SecondValuationItem
|
|
||||||
key={index}
|
|
||||||
item={item}
|
|
||||||
firstValuation={firstValuation.title}
|
|
||||||
setSecondValuation={setSecondValuation}
|
|
||||||
secondValuation={secondValuation.title}
|
|
||||||
setFirstValuation={setFirstValuation}
|
|
||||||
/>)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer className="converter__footer">
|
|
||||||
<b>{(firstValue || 0) + ' ' + firstValuation.title + ' = ' + (secondValue || 0) + ' ' + secondValuation.title}</b> <br />
|
|
||||||
Данные носят ознакомительный характер {'\t'}
|
|
||||||
<b>
|
|
||||||
{
|
|
||||||
new Date(convert.lastUpdated).toLocaleDateString() + ' ' +
|
|
||||||
new Date(convert.lastUpdated).getHours() + ':' +
|
|
||||||
new Date(convert.lastUpdated).getMinutes().toString().padStart(2,'0')
|
|
||||||
}
|
|
||||||
</b>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
import { Dispatch, FC, MouseEvent } from "react"
|
|
||||||
import { IListValuationsName } from "../../models/IListValutionsName"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const FirstValuationItem: FC<IListValuationsName> = (
|
|
||||||
{
|
|
||||||
item,
|
|
||||||
firstValuation,
|
|
||||||
secondValuation,
|
|
||||||
setFirstValuation,
|
|
||||||
setSecondValuation
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button type='button'
|
|
||||||
className={firstValuation != item.title ? 'popup-converter__button' : 'popup-converter__button popup-converter__button_active'}
|
|
||||||
value={item.title}
|
|
||||||
onClick={(e: MouseEvent<HTMLButtonElement>) => {
|
|
||||||
setFirstValuation({
|
|
||||||
img: item.img,
|
|
||||||
title: e.currentTarget.value
|
|
||||||
})
|
|
||||||
}}>{item.title}</button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
import { Dispatch, FC, MouseEvent } from "react"
|
|
||||||
import { IListValuationsName } from "../../models/IListValutionsName"
|
|
||||||
|
|
||||||
|
|
||||||
export const SecondValuationItem: FC<IListValuationsName> = ({
|
|
||||||
item,
|
|
||||||
firstValuation,
|
|
||||||
secondValuation,
|
|
||||||
setFirstValuation,
|
|
||||||
setSecondValuation
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button type='button'
|
|
||||||
className={secondValuation != item.title ? 'popup-converter__button' : 'popup-converter__button popup-converter__button_active'}
|
|
||||||
value={item.title} onClick={(e: MouseEvent<HTMLButtonElement>) => {
|
|
||||||
setSecondValuation({
|
|
||||||
img: item.img,
|
|
||||||
title: e.currentTarget.value
|
|
||||||
})
|
|
||||||
|
|
||||||
}}>{item.title}</button>
|
|
||||||
)
|
|
||||||
}
|
|
54
src/Components/popup-converter/Popup-converter.scss
Normal file
54
src/Components/popup-converter/Popup-converter.scss
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
.popup-converter{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
inset: 75px auto auto 0;
|
||||||
|
width: 100%;
|
||||||
|
box-shadow: 0 4px 24px rgba(0,0,0,.25);
|
||||||
|
background: #fff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 10px 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
&__container{
|
||||||
|
padding: 4px 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover{
|
||||||
|
background: #ffeca1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__check{
|
||||||
|
display: flex;
|
||||||
|
flex: 0 0 16px;
|
||||||
|
}
|
||||||
|
&__body{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
&__img{
|
||||||
|
flex: 0 0 20px;
|
||||||
|
height: 20px;
|
||||||
|
img{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__button{
|
||||||
|
background: transparent;
|
||||||
|
transition: 0.3s all ease;
|
||||||
|
// padding: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
span{
|
||||||
|
margin: 0 4px;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
color: rgba(84,96,122,.68);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
src/Components/popup-converter/Popup-converter.tsx
Normal file
42
src/Components/popup-converter/Popup-converter.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import {Dispatch, FC, MouseEvent} from "react"
|
||||||
|
import {IListValuationsName} from "../../models/IListValutionsName"
|
||||||
|
import './Popup-converter.scss'
|
||||||
|
|
||||||
|
|
||||||
|
export const PopupConverter: FC<IListValuationsName> = (
|
||||||
|
{
|
||||||
|
item,
|
||||||
|
valuation,
|
||||||
|
setValuation,
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
|
||||||
|
const setActiveValuation = (e: MouseEvent<HTMLDivElement>) => {
|
||||||
|
setValuation({
|
||||||
|
img: item.img,
|
||||||
|
title: item.title
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'popup-converter__container'} onClick={setActiveValuation}>
|
||||||
|
<div className={'popup-converter__check'}>
|
||||||
|
{valuation === item.title &&
|
||||||
|
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" width="16" height="10">
|
||||||
|
<path d="M7.207 7.506L3.629 3.81 2.343 4.939l4.841 5.002 8.462-8.428L14.382.362z"/>
|
||||||
|
</svg>}
|
||||||
|
</div>
|
||||||
|
<div className={'popup-converter__body'}>
|
||||||
|
<img className={'popup-converter__img'} src={item.img} alt="icon"/>
|
||||||
|
<button type='button'
|
||||||
|
className={'popup-converter__button'}
|
||||||
|
value={item.title}
|
||||||
|
>{item.title} <span>{item.alt}</span></button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
|
|||||||
const CryptoConvert = require("crypto-convert").default;
|
const CryptoConvert = require("crypto-convert").default;
|
||||||
|
|
||||||
export const convert = new CryptoConvert({
|
export const convert = new CryptoConvert({
|
||||||
cryptoInterval: 600000, //Crypto prices update interval in ms (default 5 seconds on Node.js & 15 seconds on Browsers)
|
cryptoInterval: 20000, //Crypto prices update interval in ms (default 5 seconds on Node.js & 15 seconds on Browsers)
|
||||||
fiatInterval: (60 * 1e3 * 60), //Fiat prices update interval (default every 1 hour)
|
fiatInterval: (60 * 1e3 * 60), //Fiat prices update interval (default every 1 hour)
|
||||||
calculateAverage: true, //Calculate the average crypto price from exchanges
|
calculateAverage: true, //Calculate the average crypto price from exchanges
|
||||||
binance: true, //Use binance rates
|
binance: true, //Use binance rates
|
||||||
|
@ -3,8 +3,6 @@ import { IValutions } from "./IValutions";
|
|||||||
|
|
||||||
export interface IListValuationsName {
|
export interface IListValuationsName {
|
||||||
item: IValutions,
|
item: IValutions,
|
||||||
setFirstValuation: Dispatch<IValutions>,
|
setValuation: Dispatch<IValutions>,
|
||||||
setSecondValuation: Dispatch<IValutions>,
|
valuation: string
|
||||||
secondValuation: string,
|
|
||||||
firstValuation: string
|
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
export interface IValutions {
|
export interface IValutions {
|
||||||
title: string,
|
title: string,
|
||||||
img: string
|
img: string,
|
||||||
|
alt?: string
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user