Compare commits
No commits in common. "main" and "gh-pages" have entirely different histories.
23
.gitignore
vendored
23
.gitignore
vendored
@ -1,23 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
@ -1 +0,0 @@
|
||||
### You can visit app at [github.io](https://FutureXpo.github.io/gold-point).
|
13
asset-manifest.json
Normal file
13
asset-manifest.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/gold-point/static/css/main.1fde6137.css",
|
||||
"main.js": "/gold-point/static/js/main.1ee9530b.js",
|
||||
"index.html": "/gold-point/index.html",
|
||||
"main.1fde6137.css.map": "/gold-point/static/css/main.1fde6137.css.map",
|
||||
"main.1ee9530b.js.map": "/gold-point/static/js/main.1ee9530b.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.1fde6137.css",
|
||||
"static/js/main.1ee9530b.js"
|
||||
]
|
||||
}
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
1
index.html
Normal file
1
index.html
Normal file
@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/gold-point/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/gold-point/logo192.png"/><link rel="manifest" href="/gold-point/manifest.json"/><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"/><title>React App</title><script defer="defer" src="/gold-point/static/js/main.1ee9530b.js"></script><link href="/gold-point/static/css/main.1fde6137.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
12051
package-lock.json
generated
12051
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
49
package.json
49
package.json
@ -1,49 +0,0 @@
|
||||
{
|
||||
"name": "gold-point",
|
||||
"version": "0.1.0",
|
||||
"homepage": "https://FutureXpo.github.io/gold-point",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.8.2",
|
||||
"@emotion/styled": "^11.8.1",
|
||||
"@mui/material": "^5.5.1",
|
||||
"@testing-library/jest-dom": "^5.16.2",
|
||||
"@testing-library/react": "^12.1.4",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "5.0.0",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"format": "prettier --write --use-tabs \"src/**/*.js\"",
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
"predeploy": "npm run build",
|
||||
"deploy": "gh-pages -d build"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"gh-pages": "^3.2.3",
|
||||
"prettier": "^2.6.0"
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
@ -1,27 +0,0 @@
|
||||
.App {
|
||||
min-height: 100vh;
|
||||
background-color: #eeeeff;
|
||||
position:relative;
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
align-items: center;
|
||||
font-size: calc(1rem + 1.2vmin);
|
||||
}
|
||||
.body {
|
||||
padding-top:7.5rem;
|
||||
border-radius: 2rem;
|
||||
min-height: 30rem;
|
||||
width: 40rem;
|
||||
position:relative;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #282c34;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.body {
|
||||
width: 95%;
|
||||
padding-top:5.5rem;
|
||||
}
|
||||
}
|
121
src/App/App.js
121
src/App/App.js
@ -1,121 +0,0 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
|
||||
import Header from "../Components/Header/Header";
|
||||
import MoneyList from "../Components/MoneyList/MoneyList";
|
||||
import Loading from "../Components/Loading/Loading";
|
||||
import Footer from "../Components/Footer/Footer";
|
||||
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
|
||||
const [data, setData] = useState({money:{}, isLoading:true, error:false});
|
||||
|
||||
async function getDateInfo(date_url,next_day){
|
||||
try {
|
||||
var response = await fetch(date_url||"https://www.cbr-xml-daily.ru/daily_json.js").then(response => response.json());
|
||||
if (!response.Valute) {
|
||||
throw new Error("Something went wrong!");
|
||||
}
|
||||
const dayData = response.Valute;
|
||||
|
||||
const dailyData = {};
|
||||
for (const key in dayData) {
|
||||
let money_info = {
|
||||
charCode: dayData[key].CharCode,
|
||||
name: names[dayData[key].ID]||dayData[key].Name, //Поскольку сервер возвращает имена не в именительном падеже, необходимо брать имена из массива
|
||||
value: (dayData[key].Value/dayData[key].Nominal).toFixed(4),
|
||||
};
|
||||
dailyData[dayData[key].ID] = money_info;
|
||||
|
||||
if(next_day&&next_day.values[dayData[key].ID]){ //если есть информация про следующий день, вычисляем процентную разницу
|
||||
next_day.values[dayData[key].ID].diff = (((next_day.values[dayData[key].ID].value - money_info.value) / money_info.value) * 100).toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
date:response.Date,
|
||||
next_day:next_day,
|
||||
info:{
|
||||
values: dailyData,
|
||||
previousDate:response.PreviousDate,
|
||||
previousURL:response.PreviousURL
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {error:error}
|
||||
}
|
||||
}
|
||||
|
||||
const getData = useCallback(async () => {
|
||||
var money = {};
|
||||
let date_info = await getDateInfo();
|
||||
if(date_info.error) return setData({money:{}, error:date_info.error});
|
||||
|
||||
let previous_date_info = await getDateInfo(date_info.info.previousURL,date_info.info); //поскольку previousValue предоставляется без previousNominal, то необходимо получать все данные за прошлый день и вычислять diff используя их
|
||||
if(previous_date_info.error) return setData({money:{}, error:date_info.error});
|
||||
|
||||
money[date_info.date] = previous_date_info.next_day;
|
||||
money[previous_date_info.date] = previous_date_info.info;
|
||||
|
||||
setData({money:money, date:date_info.date});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, [getData]);
|
||||
|
||||
const updateData = (money) => setData({...data, money:money});
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<Header />
|
||||
<div className="body">
|
||||
{data.isLoading?
|
||||
<Loading />:
|
||||
<MoneyList money={data.money} date={data.date} updateData={updateData} getDateInfo={getDateInfo}/>
|
||||
}
|
||||
</div>
|
||||
<Footer isLoading={data.isLoading}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
const names = {
|
||||
"R01010":"Австралийский доллар",
|
||||
"R01020A":"Азербайджанский манат",
|
||||
"R01035":"Фунт стерлингов Соединенного королевства",
|
||||
"R01060":"Армянский драм",
|
||||
"R01090B":"Белорусский рубль",
|
||||
"R01100":"Болгарский лев",
|
||||
"R01115":"Бразильский реал",
|
||||
"R01135":"Венгерский форинт",
|
||||
"R01200":"Гонконгский доллар",
|
||||
"R01215":"Датская крона",
|
||||
"R01235":"Доллар США",
|
||||
"R01239":"Евро",
|
||||
"R01270":"Индийская рупия",
|
||||
"R01335":"Казахстанский тенге",
|
||||
"R01350":"Канадский доллар",
|
||||
"R01370":"Киргизский сом",
|
||||
"R01375":"Китайский юань",
|
||||
"R01500":"Молдавский лей",
|
||||
"R01535":"Норвежская крона",
|
||||
"R01565":"Польский злотый",
|
||||
"R01585F":"Румынский лей",
|
||||
"R01589":"СДР (специальные права заимствования)",
|
||||
"R01625":"Сингапурский доллар",
|
||||
"R01670":"Таджикский сомони",
|
||||
"R01700J":"Турецкая лира",
|
||||
"R01710A":"Новый туркменский манат",
|
||||
"R01717":"Узбекский сум",
|
||||
"R01720":"Украинская гривна",
|
||||
"R01760":"Чешская крона",
|
||||
"R01770":"Шведская крона",
|
||||
"R01775":"Швейцарский франк",
|
||||
"R01810":"Южноафриканский рэнд",
|
||||
"R01815":"Южнокорейская вона",
|
||||
"R01820":"Японская иена"
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
.footer {
|
||||
font-size:1.1rem;
|
||||
width:100%;
|
||||
/*background-color: #dddddd;*/
|
||||
padding-top:1rem;
|
||||
padding-bottom:1rem;
|
||||
text-align: center;
|
||||
}
|
||||
.fixed{
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
}
|
||||
.footer .link {
|
||||
color:darkblue;
|
||||
margin-left:0.5rem;
|
||||
}
|
||||
@media screen and (max-width: 700px) {
|
||||
.footer {
|
||||
font-size:0.9rem;
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
import './Footer.css';
|
||||
|
||||
export default function Footer(props) {
|
||||
return (
|
||||
<footer className={props.isLoading?"footer fixed":"footer"}>
|
||||
Создано при помощи
|
||||
<a href="https://www.cbr-xml-daily.ru/" className="link">API для курсов ЦБ РФ</a>
|
||||
</footer>
|
||||
);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
.header{
|
||||
width:100%;
|
||||
display:flex;
|
||||
justify-content:center;
|
||||
}
|
||||
.header_box {
|
||||
margin-top:1rem;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index:10;
|
||||
width: 41rem;
|
||||
}
|
||||
.header .under_titles {
|
||||
top: 0;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height:4rem;
|
||||
z-index:9;
|
||||
background-color: #eeeeff;
|
||||
}
|
||||
.header_box .titles {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
border-radius: 0.5rem;
|
||||
background-color: #8899dd;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.header_box {
|
||||
margin-top:0rem;
|
||||
width: 100%;
|
||||
}
|
||||
.header_box .titles {
|
||||
border-radius: 0rem;
|
||||
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import './Header.css';
|
||||
|
||||
export default function Header() {
|
||||
return (
|
||||
<header className="header">
|
||||
<div className="header_box">
|
||||
<div className="titles">
|
||||
<h4>Код валюты</h4>
|
||||
<h4>Курс (р.)</h4>
|
||||
<h4>Разница</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="under_titles"></div>
|
||||
</header>
|
||||
);
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
.loading{
|
||||
width:100%;
|
||||
height:25rem;
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
}
|
||||
.loading .loading_anim{
|
||||
width:100%;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
}
|
||||
.loading .loading_anim .loading_animation{
|
||||
transform:scale(.3);
|
||||
background-color:rgb(255,255,255);
|
||||
width:2rem;
|
||||
height:2rem;
|
||||
margin:0.1rem;
|
||||
border-radius:100%;
|
||||
animation: animation1 infinite 1000ms alternate ease-in-out forwards;
|
||||
}
|
||||
.loading .loading_anim .loading_animation.a2{
|
||||
animation-delay:100ms;
|
||||
}
|
||||
.loading .loading_anim .loading_animation.a3{
|
||||
animation-delay:200ms;
|
||||
}
|
||||
.loading .loading_anim .loading_animation.a4{
|
||||
animation-delay:300ms;
|
||||
}
|
||||
.loading .loading_anim .loading_animation.a5{
|
||||
animation-delay:400ms;
|
||||
}
|
||||
.loading .loading_anim .loading_animation.a6{
|
||||
animation-delay:500ms;
|
||||
}
|
||||
.loading .loading_anim .loading_animation.a7{
|
||||
animation-delay:600ms;
|
||||
}
|
||||
|
||||
@keyframes animation1{
|
||||
0%{
|
||||
transform:scale(.3);
|
||||
background-color:rgb(255,255,255);
|
||||
}
|
||||
|
||||
100%{
|
||||
transform:scale(1);
|
||||
background-color:rgb(0,0,0);
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import './Loading.css';
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
<div className="loading">
|
||||
<div className="loading_anim">
|
||||
<div className="loading_animation a1"></div>
|
||||
<div className="loading_animation a2"></div>
|
||||
<div className="loading_animation a3"></div>
|
||||
<div className="loading_animation a4"></div>
|
||||
<div className="loading_animation a5"></div>
|
||||
<div className="loading_animation a6"></div>
|
||||
<div className="loading_animation a7"></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
.item {
|
||||
display:inline-block;
|
||||
width:100%;
|
||||
max-width:100%;
|
||||
background: #aaaacc;
|
||||
border-radius:1rem;
|
||||
margin-top:0.3rem;
|
||||
padding-top:2rem;
|
||||
padding-bottom:2rem;
|
||||
transition: all 0.3s ease;
|
||||
position:relative;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.item_info{
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
.item_info .value{
|
||||
}
|
||||
.item_info .diff.plus{
|
||||
color:green;
|
||||
}
|
||||
.item_info .diff.minus{
|
||||
color:darkred;
|
||||
}
|
||||
|
||||
.item:hover{
|
||||
transform: scale(1.02);
|
||||
background: #cacafa;
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import './Item.css';
|
||||
|
||||
export default function Item(props) {
|
||||
return (
|
||||
<Tooltip title={props.item.name} followCursor arrow placement="bottom-end">
|
||||
<div className="item" onClick={()=>{props.openModal(props.item.id)}}>
|
||||
<Grid container rowSpacing={0} columnSpacing={{ xs: 1, sm: 2, md: 0 }} className="item_info">
|
||||
<Grid item xs={4} className="charCode">
|
||||
{props.item.charCode}
|
||||
</Grid>
|
||||
<Grid item xs={4} className="value">
|
||||
{props.item.value}
|
||||
</Grid>
|
||||
<Grid item xs={4} className={props.item.diff>=0?"diff plus":"diff minus"}>
|
||||
{props.item.diff}%{props.item.diff>=0?"▲":"▼"}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
.modal_item {
|
||||
width:100%;
|
||||
max-width:100%;
|
||||
background: #fff;
|
||||
margin-top:0.3rem;
|
||||
padding-top:1rem;
|
||||
padding-bottom:1rem;
|
||||
transition: all 0.3s ease;
|
||||
position:relative;
|
||||
border-bottom:1px solid;
|
||||
}
|
||||
.modal_item.first {
|
||||
border-top:1px solid;
|
||||
}
|
||||
.modal_item .item_info{
|
||||
padding-left:2rem;
|
||||
}
|
||||
.modal_item .item_info .date{
|
||||
font-size:1.5rem;
|
||||
text-align:left;
|
||||
color:#009;
|
||||
}
|
||||
.modal_item .item_info .value{
|
||||
font-size:1.2rem;
|
||||
font-weight:bold;
|
||||
text-align:right;
|
||||
}
|
||||
.modal_item .item_info .diff{
|
||||
text-align:center;
|
||||
}
|
||||
.modal_item .item_info .diff.plus{
|
||||
color:green;
|
||||
}
|
||||
.modal_item .item_info .diff.minus{
|
||||
color:darkred;
|
||||
}
|
||||
@media screen and (max-width: 700px) {
|
||||
.modal_item {
|
||||
margin-top:0.1rem;
|
||||
padding-top:0.7rem;
|
||||
padding-bottom:0.7rem;
|
||||
}
|
||||
.modal_item .item_info .date{
|
||||
font-size:1.3rem;
|
||||
}
|
||||
.modal_item .item_info .value{
|
||||
font-size:1.1rem;
|
||||
}
|
||||
.modal_item .item_info .diff{
|
||||
font-size:0.9rem;
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
import Grid from "@mui/material/Grid";
|
||||
import './Item.css';
|
||||
|
||||
export default function Item(props) {
|
||||
|
||||
function getDate(date){
|
||||
let d = new Date(date);
|
||||
return [("0" + d.getDate()).slice(-2),("0"+(d.getMonth()+1)).slice(-2),d.getFullYear()].join("/");
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={props.index===0?"modal_item first":"modal_item"} >
|
||||
<Grid container rowSpacing={0} columnSpacing={{ xs: 1, sm: 2, md: 2 }} className="item_info">
|
||||
<Grid item xs={5} className="date">
|
||||
{getDate(props.item.date)}
|
||||
</Grid>
|
||||
<Grid item xs={4} className="value">
|
||||
{props.item.value}₽
|
||||
</Grid>
|
||||
<Grid item xs={3} className={props.item.diff>=0?"diff plus":"diff minus"}>
|
||||
{props.item.diff}%{props.item.diff>=0?"▲":"▼"}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
.modal{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background:#fff;
|
||||
padding:2rem;
|
||||
border-radius:1rem;
|
||||
width:40rem;
|
||||
}
|
||||
|
||||
.modal-back{
|
||||
display:none;
|
||||
}
|
||||
.modal .modal_header{
|
||||
font-size: 2rem;
|
||||
text-align: center;
|
||||
padding-bottom:2rem;
|
||||
}
|
||||
.modal .modal_body {
|
||||
overflow-y:scroll;
|
||||
max-height:60vh;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.modal {
|
||||
overflow-y:scroll;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding:0;
|
||||
border-radius:0;
|
||||
}
|
||||
.modal .modal-back{
|
||||
padding-top:1.5rem;
|
||||
padding-bottom:1.5rem;
|
||||
padding-left:1rem;
|
||||
display: block;
|
||||
color:#555;
|
||||
}
|
||||
.modal .modal_header{
|
||||
padding-left:1rem;
|
||||
padding-right:1rem;
|
||||
font-size: 1.5rem;
|
||||
font-weight:bold;
|
||||
}
|
||||
.modal .modal_body {
|
||||
overflow-y:hidden;
|
||||
max-height:none;
|
||||
padding-bottom:2rem;
|
||||
padding-left:2.5%;
|
||||
padding-right:2.5%;
|
||||
max-width:95%;
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import Loading from "../../Loading/Loading";
|
||||
import Backdrop from '@mui/material/Backdrop';
|
||||
import Modal from '@mui/material/Modal';
|
||||
import Fade from '@mui/material/Fade';
|
||||
|
||||
import Item from "./Item/Item";
|
||||
|
||||
import './Modal.css';
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms || 250));
|
||||
}
|
||||
|
||||
export default function ModalMoney(props) {
|
||||
var {open, money, id, date} = props;
|
||||
const [data,setData]=useState({isLoading:true});
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, [props.open]);
|
||||
|
||||
if(!id) return null;
|
||||
|
||||
async function getData(){
|
||||
if(data.isLoading&&id){
|
||||
let day_date = date;
|
||||
let day_url = money[date].previousURL;
|
||||
let next_day_date;
|
||||
|
||||
let money_={...money}
|
||||
let data_ = [];
|
||||
|
||||
while (data_.length<11){
|
||||
if(!money_[day_date]){ //проверка что существует день
|
||||
let response = await props.getDateInfo(day_url,money_[next_day_date]||null); //получаем информацию за день и обновляем разцницу за следующий
|
||||
money_[day_date] = response.info;
|
||||
if(response.next_day){
|
||||
money_[next_day_date] = response.next_day;
|
||||
data_[data_.length-1].diff = response.next_day.values[id].diff
|
||||
}
|
||||
await sleep();
|
||||
}
|
||||
let date_info = {
|
||||
date:day_date,
|
||||
value:money_[day_date].values[id].value,
|
||||
diff:money_[day_date].values[id].diff
|
||||
}
|
||||
data_.push(date_info);
|
||||
|
||||
next_day_date = day_date;
|
||||
day_url = money_[day_date].previousURL;
|
||||
day_date = money_[day_date].previousDate;
|
||||
|
||||
}
|
||||
props.updateData(money_);
|
||||
setData({values:data_});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const closeModal = () => {
|
||||
props.closeModal();
|
||||
setTimeout(()=>{setData({isLoading:true})},300);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={closeModal}
|
||||
closeAfterTransition
|
||||
BackdropComponent={Backdrop}
|
||||
BackdropProps={{
|
||||
timeout: 300,
|
||||
}}
|
||||
>
|
||||
<Fade in={open} timeout={300}>
|
||||
<div className="modal">
|
||||
<div className="modal-back" onClick={()=>closeModal()}>
|
||||
← Вернуться к списку валют
|
||||
</div >
|
||||
<div className="modal_header">
|
||||
{money[date].values[id].name} ({money[date].values[id].charCode})
|
||||
</div>
|
||||
<div className="modal_body">
|
||||
{data.isLoading?<Loading/>:
|
||||
data.values.map((item, index) => {
|
||||
if(index===data.values.length-1) return null;
|
||||
return <Item item={item} index={index}/>;
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Fade>
|
||||
</Modal>
|
||||
);
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
.money-list {
|
||||
width:100%;
|
||||
position:relative;
|
||||
display:block;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import './MoneyList.css';
|
||||
|
||||
import Item from "./Item/Item";
|
||||
import Modal from "./Modal/Modal";
|
||||
|
||||
export default function MoneyList(props) {
|
||||
const [modal, setModal] = useState({open:false});
|
||||
|
||||
const openModal = (id) => setModal({id:id,open:true});
|
||||
const closeModal = () => setModal({...modal,open:false});
|
||||
|
||||
let values = [];
|
||||
|
||||
for (let [id, info] of Object.entries(props.money[props.date].values)) values.push({...info, id:id}); //получаем массив для вывода
|
||||
|
||||
return (
|
||||
<div className="money_list">
|
||||
{values.map((item, index) => { {
|
||||
return <Item item={item} openModal={openModal}/>;
|
||||
}})}
|
||||
<Modal id={modal.id} open={modal.open} money={props.money} date={props.date} closeModal={closeModal} updateData={props.updateData} getDateInfo={props.getDateInfo}/>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
11
src/index.js
11
src/index.js
@ -1,11 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App/App';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
2
static/css/main.1fde6137.css
Normal file
2
static/css/main.1fde6137.css
Normal file
@ -0,0 +1,2 @@
|
||||
body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.header{display:flex;justify-content:center;width:100%}.header_box{margin-top:1rem;position:fixed;top:0;width:41rem;z-index:10}.header .under_titles{background-color:#eef;height:4rem;position:fixed;top:0;width:100%;z-index:9}.header_box .titles{align-items:center;background-color:#89d;border-radius:.5rem;display:flex;gap:1rem;justify-content:space-around;width:100%}@media screen and (max-width:700px){.header_box{margin-top:0;width:100%}.header_box .titles{border-radius:0}}.money-list{display:block}.item,.money-list{position:relative;width:100%}.item{background:#aac;border-radius:1rem;display:inline-block;margin-top:.3rem;max-width:100%;padding-bottom:2rem;padding-top:2rem;text-align:center;transition:all .3s ease}.item_info{align-items:center;display:flex;justify-content:space-around}.item_info .diff.plus{color:green}.item_info .diff.minus{color:darkred}.item:hover{background:#cacafa;-webkit-transform:scale(1.02);transform:scale(1.02)}.loading{flex-direction:column;height:25rem}.loading,.loading .loading_anim{align-items:center;display:flex;justify-content:center;width:100%}.loading .loading_anim .loading_animation{-webkit-animation:animation1 1s ease-in-out infinite alternate forwards;animation:animation1 1s ease-in-out infinite alternate forwards;background-color:#fff;border-radius:100%;height:2rem;margin:.1rem;-webkit-transform:scale(.3);transform:scale(.3);width:2rem}.loading .loading_anim .loading_animation.a2{-webkit-animation-delay:.1s;animation-delay:.1s}.loading .loading_anim .loading_animation.a3{-webkit-animation-delay:.2s;animation-delay:.2s}.loading .loading_anim .loading_animation.a4{-webkit-animation-delay:.3s;animation-delay:.3s}.loading .loading_anim .loading_animation.a5{-webkit-animation-delay:.4s;animation-delay:.4s}.loading .loading_anim .loading_animation.a6{-webkit-animation-delay:.5s;animation-delay:.5s}.loading .loading_anim .loading_animation.a7{-webkit-animation-delay:.6s;animation-delay:.6s}@-webkit-keyframes animation1{0%{background-color:#fff;-webkit-transform:scale(.3);transform:scale(.3)}to{background-color:#000;-webkit-transform:scale(1);transform:scale(1)}}@keyframes animation1{0%{background-color:#fff;-webkit-transform:scale(.3);transform:scale(.3)}to{background-color:#000;-webkit-transform:scale(1);transform:scale(1)}}.modal_item{background:#fff;border-bottom:1px solid;margin-top:.3rem;max-width:100%;padding-bottom:1rem;padding-top:1rem;position:relative;transition:all .3s ease;width:100%}.modal_item.first{border-top:1px solid}.modal_item .item_info{padding-left:2rem}.modal_item .item_info .date{color:#009;font-size:1.5rem;text-align:left}.modal_item .item_info .value{font-size:1.2rem;font-weight:700;text-align:right}.modal_item .item_info .diff{text-align:center}.modal_item .item_info .diff.plus{color:green}.modal_item .item_info .diff.minus{color:darkred}@media screen and (max-width:700px){.modal_item{margin-top:.1rem;padding-bottom:.7rem;padding-top:.7rem}.modal_item .item_info .date{font-size:1.3rem}.modal_item .item_info .value{font-size:1.1rem}.modal_item .item_info .diff{font-size:.9rem}}.modal{background:#fff;border-radius:1rem;left:50%;padding:2rem;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:40rem}.modal-back{display:none}.modal .modal_header{font-size:2rem;padding-bottom:2rem;text-align:center}.modal .modal_body{max-height:60vh;overflow-y:scroll}@media screen and (max-width:700px){.modal{border-radius:0;height:100%;overflow-y:scroll;padding:0;width:100%}.modal .modal-back{color:#555;display:block;padding-bottom:1.5rem;padding-left:1rem;padding-top:1.5rem}.modal .modal_header{font-size:1.5rem;font-weight:700;padding-left:1rem;padding-right:1rem}.modal .modal_body{max-height:none;max-width:95%;overflow-y:hidden;padding-bottom:2rem;padding-left:2.5%;padding-right:2.5%}}.footer{font-size:1.1rem;padding-bottom:1rem;padding-top:1rem;text-align:center;width:100%}.fixed{bottom:0;position:absolute}.footer .link{color:#00008b;margin-left:.5rem}@media screen and (max-width:700px){.footer{font-size:.9rem}}.App{background-color:#eef;font-size:calc(1rem + 1.2vmin);min-height:100vh}.App,.body{align-items:center;display:flex;flex-direction:column;position:relative}.body{border-radius:2rem;color:#282c34;min-height:30rem;padding-top:7.5rem;width:40rem}@media screen and (max-width:700px){.body{padding-top:5.5rem;width:95%}}
|
||||
/*# sourceMappingURL=main.1fde6137.css.map*/
|
1
static/css/main.1fde6137.css.map
Normal file
1
static/css/main.1fde6137.css.map
Normal file
File diff suppressed because one or more lines are too long
3
static/js/main.1ee9530b.js
Normal file
3
static/js/main.1ee9530b.js
Normal file
File diff suppressed because one or more lines are too long
47
static/js/main.1ee9530b.js.LICENSE.txt
Normal file
47
static/js/main.1ee9530b.js.LICENSE.txt
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/
|
||||
|
||||
/** @license MUI v5.4.4
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v0.20.2
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
1
static/js/main.1ee9530b.js.map
Normal file
1
static/js/main.1ee9530b.js.map
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user