Skip to content

Commit 54f990f

Browse files
committed
Add saving to localStorage
1 parent 9b3b736 commit 54f990f

11 files changed

+5356
-3378
lines changed

.eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ module.exports = {
1010
rules: {
1111
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
1212
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
13+
"semi": "off"
1314
},
1415
};

.prettierrc.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
semi: false,
3+
}

package-lock.json

+5,019-3,243
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
"lint": "vue-cli-service lint"
99
},
1010
"dependencies": {
11+
"@tailwindcss/postcss7-compat": "^2.0.2",
12+
"autoprefixer": "^9",
1113
"core-js": "^3.6.5",
14+
"postcss": "^7",
15+
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.2",
1216
"vue": "^3.0.0"
1317
},
1418
"devDependencies": {
@@ -21,6 +25,7 @@
2125
"eslint": "^6.7.2",
2226
"eslint-plugin-prettier": "^3.3.1",
2327
"eslint-plugin-vue": "^7.0.0",
24-
"prettier": "^2.2.1"
28+
"prettier": "^2.2.1",
29+
"vue-cli-plugin-tailwind": "~2.0.6"
2530
}
2631
}

postcss.config.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {}
5+
}
6+
}

src/App.vue

+312-17
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,321 @@
11
<template>
2-
<img alt="Vue logo" src="./assets/logo.png" />
3-
<HelloWorld msg="Welcome to Your Vue.js App" />
2+
<div class="container mx-auto flex flex-col items-center bg-gray-100 p-4">
3+
<div class="container">
4+
<section>
5+
<div class="flex">
6+
<div class="max-w-xs">
7+
<label for="wallet" class="block text-sm font-medium text-gray-700"
8+
>Тикер</label
9+
>
10+
<div class="mt-1 relative rounded-md shadow-md">
11+
<input
12+
v-model="ticker"
13+
type="text"
14+
name="wallet"
15+
id="wallet"
16+
class="
17+
block
18+
w-full
19+
pr-10
20+
border-gray-300
21+
text-gray-900
22+
focus:outline-none focus:ring-gray-500 focus:border-gray-500
23+
sm:text-sm
24+
rounded-md
25+
p-1
26+
"
27+
placeholder="Например DOGE"
28+
/>
29+
</div>
30+
<div
31+
class="flex bg-white shadow-md p-1 rounded-md shadow-md flex-wrap"
32+
>
33+
<span
34+
class="
35+
inline-flex
36+
items-center
37+
px-2
38+
m-1
39+
rounded-md
40+
text-xs
41+
font-medium
42+
bg-gray-300
43+
text-gray-800
44+
cursor-pointer
45+
"
46+
>
47+
BTC
48+
</span>
49+
<span
50+
class="
51+
inline-flex
52+
items-center
53+
px-2
54+
m-1
55+
rounded-md
56+
text-xs
57+
font-medium
58+
bg-gray-300
59+
text-gray-800
60+
cursor-pointer
61+
"
62+
>
63+
DOGE
64+
</span>
65+
<span
66+
class="
67+
inline-flex
68+
items-center
69+
px-2
70+
m-1
71+
rounded-md
72+
text-xs
73+
font-medium
74+
bg-gray-300
75+
text-gray-800
76+
cursor-pointer
77+
"
78+
>
79+
BCH
80+
</span>
81+
<span
82+
class="
83+
inline-flex
84+
items-center
85+
px-2
86+
m-1
87+
rounded-md
88+
text-xs
89+
font-medium
90+
bg-gray-300
91+
text-gray-800
92+
cursor-pointer
93+
"
94+
>
95+
ETH
96+
</span>
97+
</div>
98+
<div class="text-sm text-red-600">Такой тикер уже добавлен</div>
99+
</div>
100+
</div>
101+
<button
102+
@click="add"
103+
type="button"
104+
class="
105+
my-4
106+
inline-flex
107+
items-center
108+
py-2
109+
px-4
110+
border border-transparent
111+
shadow-sm
112+
text-sm
113+
leading-4
114+
font-medium
115+
rounded-full
116+
text-white
117+
bg-gray-600
118+
hover:bg-gray-700
119+
transition-colors
120+
duration-300
121+
focus:outline-none
122+
focus:ring-2
123+
focus:ring-offset-2
124+
focus:ring-gray-500
125+
"
126+
>
127+
<!-- Heroicon name: solid/mail -->
128+
<svg
129+
class="-ml-0.5 mr-2 h-6 w-6"
130+
xmlns="http://www.w3.org/2000/svg"
131+
width="30"
132+
height="30"
133+
viewBox="0 0 24 24"
134+
fill="#ffffff"
135+
>
136+
<path
137+
d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"
138+
></path>
139+
</svg>
140+
Добавить
141+
</button>
142+
</section>
143+
<template v-if="tickers.length">
144+
<hr class="w-full border-t border-gray-600 my-4" />
145+
<dl class="mt-5 grid grid-cols-1 gap-5 sm:grid-cols-3">
146+
<div
147+
v-for="t in tickers"
148+
:key="t.name"
149+
@click="select(t)"
150+
:class="{
151+
'border-4': sel === t,
152+
}"
153+
class="
154+
bg-white
155+
overflow-hidden
156+
shadow
157+
rounded-lg
158+
border-purple-800 border-solid
159+
cursor-pointer
160+
"
161+
>
162+
<div class="px-4 py-5 sm:p-6 text-center">
163+
<dt class="text-sm font-medium text-gray-500 truncate">
164+
{{ t.name }} - USD
165+
</dt>
166+
<dd class="mt-1 text-3xl font-semibold text-gray-900">
167+
{{ t.price }}
168+
</dd>
169+
</div>
170+
<div class="w-full border-t border-gray-200"></div>
171+
<button
172+
@click.stop="handleDelete(t)"
173+
class="
174+
flex
175+
items-center
176+
justify-center
177+
font-medium
178+
w-full
179+
bg-gray-100
180+
px-4
181+
py-4
182+
sm:px-6
183+
text-md text-gray-500
184+
hover:text-gray-600 hover:bg-gray-200 hover:opacity-20
185+
transition-all
186+
focus:outline-none
187+
"
188+
>
189+
<svg
190+
class="h-5 w-5"
191+
xmlns="http://www.w3.org/2000/svg"
192+
viewBox="0 0 20 20"
193+
fill="#718096"
194+
aria-hidden="true"
195+
>
196+
<path
197+
fill-rule="evenodd"
198+
d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z"
199+
clip-rule="evenodd"
200+
></path></svg
201+
>Удалить
202+
</button>
203+
</div>
204+
</dl>
205+
<hr class="w-full border-t border-gray-600 my-4" />
206+
</template>
207+
<section v-if="sel" class="relative">
208+
<h3 class="text-lg leading-6 font-medium text-gray-900 my-8">
209+
{{ sel.name }} - USD
210+
</h3>
211+
<div class="flex items-end border-gray-600 border-b border-l h-64">
212+
<div
213+
v-for="(bar, idx) in normalizeGraph()"
214+
:key="idx"
215+
:style="{ height: `${bar}%` }"
216+
class="bg-purple-800 border w-10"
217+
></div>
218+
</div>
219+
<button
220+
@click="sel = null"
221+
type="button"
222+
class="absolute top-0 right-0"
223+
>
224+
<svg
225+
xmlns="http://www.w3.org/2000/svg"
226+
xmlns:xlink="http://www.w3.org/1999/xlink"
227+
xmlns:svgjs="http://svgjs.com/svgjs"
228+
version="1.1"
229+
width="30"
230+
height="30"
231+
x="0"
232+
y="0"
233+
viewBox="0 0 511.76 511.76"
234+
style="enable-background: new 0 0 512 512"
235+
xml:space="preserve"
236+
>
237+
<g>
238+
<path
239+
d="M436.896,74.869c-99.84-99.819-262.208-99.819-362.048,0c-99.797,99.819-99.797,262.229,0,362.048 c49.92,49.899,115.477,74.837,181.035,74.837s131.093-24.939,181.013-74.837C536.715,337.099,536.715,174.688,436.896,74.869z M361.461,331.317c8.341,8.341,8.341,21.824,0,30.165c-4.16,4.16-9.621,6.251-15.083,6.251c-5.461,0-10.923-2.091-15.083-6.251 l-75.413-75.435l-75.392,75.413c-4.181,4.16-9.643,6.251-15.083,6.251c-5.461,0-10.923-2.091-15.083-6.251 c-8.341-8.341-8.341-21.845,0-30.165l75.392-75.413l-75.413-75.413c-8.341-8.341-8.341-21.845,0-30.165 c8.32-8.341,21.824-8.341,30.165,0l75.413,75.413l75.413-75.413c8.341-8.341,21.824-8.341,30.165,0 c8.341,8.32,8.341,21.824,0,30.165l-75.413,75.413L361.461,331.317z"
240+
fill="#718096"
241+
data-original="#000000"
242+
></path>
243+
</g>
244+
</svg>
245+
</button>
246+
</section>
247+
</div>
248+
</div>
4249
</template>
5250

6251
<script>
7-
import HelloWorld from "./components/HelloWorld.vue";
8-
9252
export default {
10253
name: "App",
11-
components: {
12-
HelloWorld,
254+
data() {
255+
return {
256+
ticker: "",
257+
tickers: [],
258+
filter: false,
259+
260+
sel: null,
261+
graph: [],
262+
263+
coinList: [],
264+
}
13265
},
14-
};
15-
</script>
266+
created() {
267+
const tickersData = localStorage.getItem("cryptonomicon-list")
268+
if (tickersData) {
269+
this.tickers = JSON.parse(tickersData)
270+
this.tickers.forEach((ticker) => {
271+
this.subcribeToUpdates(ticker.name)
272+
})
273+
}
274+
},
275+
methods: {
276+
subcribeToUpdates(tickerName) {
277+
setInterval(async () => {
278+
const f = await fetch(
279+
`https://min-api.cryptocompare.com/data/price?fsym=${tickerName}&tsyms=USD&api_key=7f4f460334f56d02b536a87a10f7dbb84b2945658df6e04417fc15bdc39742b7`
280+
)
281+
const data = await f.json()
282+
console.log(data)
283+
this.tickers.find((t) => t.name === tickerName).price =
284+
data.USD > 1 ? data.USD.toFixed(2) : data.USD.toPrecision(2)
285+
if (this.sel?.name === tickerName) {
286+
this.graph.push(data.USD)
287+
}
288+
}, 5000)
289+
this.ticker = ""
290+
},
291+
add() {
292+
console.log(this.coinList.length)
293+
const currentTicker = {
294+
name: this.ticker,
295+
price: "-",
296+
graph: [],
297+
}
298+
this.tickers.push(currentTicker)
16299
17-
<style>
18-
#app {
19-
font-family: Avenir, Helvetica, Arial, sans-serif;
20-
-webkit-font-smoothing: antialiased;
21-
-moz-osx-font-smoothing: grayscale;
22-
text-align: center;
23-
color: #2c3e50;
24-
margin-top: 60px;
300+
localStorage.setItem("cryptonomicon-list", JSON.stringify(this.tickers))
301+
this.subcribeToUpdates(currentTicker.name)
302+
},
303+
handleDelete(tickerToRemove) {
304+
this.tickers = this.tickers.filter((t) => t !== tickerToRemove)
305+
},
306+
normalizeGraph() {
307+
const maxValue = Math.max(...this.graph)
308+
const minValue = Math.min(...this.graph)
309+
return this.graph.map(
310+
(price) => 5 + ((price - minValue) * 95) / (maxValue - minValue)
311+
)
312+
},
313+
select(ticker) {
314+
this.sel = ticker
315+
this.graph = []
316+
},
317+
},
25318
}
26-
</style>
319+
</script>
320+
321+
<style src="./assets/tailwind.css"></style>

src/api.js

Whitespace-only changes.

src/assets/logo.png

-6.69 KB
Binary file not shown.

src/assets/tailwind.css

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@tailwind base;
2+
3+
@tailwind components;
4+
5+
@tailwind utilities;

0 commit comments

Comments
 (0)