|
1 | 1 | <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> |
4 | 249 | </template>
|
5 | 250 |
|
6 | 251 | <script>
|
7 |
| -import HelloWorld from "./components/HelloWorld.vue"; |
8 |
| -
|
9 | 252 | export default {
|
10 | 253 | 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 | + } |
13 | 265 | },
|
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) |
16 | 299 |
|
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 | + }, |
25 | 318 | }
|
26 |
| -</style> |
| 319 | +</script> |
| 320 | +
|
| 321 | +<style src="./assets/tailwind.css"></style> |
0 commit comments