Skip to content

Commit

Permalink
Merge branch 'websocket'
Browse files Browse the repository at this point in the history
  • Loading branch information
HugoRCD committed Oct 25, 2024
2 parents 50f7953 + e6552a5 commit 6e72bf3
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 29 deletions.
39 changes: 24 additions & 15 deletions app/components/chart/Line.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const isPositive = computed(() => {
if (!firstValue.value || !lastValue.value) return false
return lastValue.value > firstValue.value
})
const series = [
{
data: cryptoData ? cryptoData : getRandomDailyData(),
Expand Down Expand Up @@ -91,21 +92,13 @@ watch(colorMode, () => {
})
})
watch(
price,
() => {
emit('update:currentValue', price.value ? price.value : lastValue.value)
},
{ immediate: true },
)
watch(price, () => {
emit('update:currentValue', price.value ? price.value : lastValue.value)
}, { immediate: true })
watch(
variation,
() => {
emit('update:variation', variation.value)
},
{ immediate: true },
)
watch(variation, () => {
emit('update:variation', variation.value)
}, { immediate: true })
function mouseOut() {
emit('update:currentValue', lastValue.value)
Expand All @@ -127,6 +120,13 @@ const chartOptions = {
zoom: {
enabled: false,
},
animations: {
enabled: true,
easing: 'linear',
dynamicAnimation: {
speed: 1000
}
},
toolbar: {
show: false,
},
Expand Down Expand Up @@ -191,7 +191,6 @@ const chartOptions = {
},
},
tooltip: {
custom: function({ series, seriesIndex, dataPointIndex }) {
const value = series[seriesIndex][dataPointIndex] as number
price.value = value
Expand All @@ -216,6 +215,16 @@ const chartOptions = {
},
},
} satisfies ApexOptions
watch(() => cryptoData, () => {
const cryptoDataCopy = cryptoData
// sort by timestamp
chart.value.chart.updateSeries([
{
data: cryptoDataCopy.sort((a, b) => a.timestamp - b.timestamp)
}
])
})
</script>

<template>
Expand Down
59 changes: 55 additions & 4 deletions app/pages/app/crypto/[symbol].vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import type { Variations } from '~~/types/ApexChart'
import type { Crypto } from '~~/types/Crypto'
const dayjs = useDayjs()
const cryptos = usePublicCrypto()
const { symbol } = useRoute().params
Expand All @@ -10,28 +12,73 @@ if (!crypto) {
useRouter().push('/app/market')
}
const cryptoData = ref(crypto.data)
const variations = ref<Variations>({
percent: -1,
value: -1,
})
const price = ref(crypto.data[crypto.data.length - 1][1])
const series = crypto.data
const dynamicData = ref(0)
let ws: WebSocket | undefined
function connect() {
const isSecure = location.protocol === 'https:'
const url = `${isSecure ? 'wss' : 'ws'}://${location.host}/api/crypto/ws?symbol=${symbol}`
if (ws) {
console.log('ws', 'Closing previous connection before reconnecting...')
ws.close()
}
console.log('ws', 'Connecting to', url, '...')
ws = new WebSocket(url)
ws.addEventListener('message', (event) => {
if (event.data.includes('number')) {
dynamicData.value = JSON.parse(event.data).number
// add another day to the data
/*cryptoData.value.push([
dayjs().add(1, 'day').valueOf(),
dynamicData.value
])*/
}
if (event.data.includes('pong')) {
console.log('ws', 'Received pong')
}
})
}
const ping = () => {
console.log('ws', 'Sending ping')
ws!.send('ping')
}
onMounted(() => {
connect()
})
onUnmounted(() => {
console.log('ws', 'Closing connection...')
ws?.close()
})
</script>

<template>
<div class="flex flex-col gap-8">
<div class="flex flex-col gap-4">
<div style="--stagger: 1; --delay: 100ms" data-animate class="flex flex-row items-center gap-3">
<img :src="crypto.logo" class="size-7" :alt="crypto.name">
<h1 :key="crypto" class="text-2xl font-bold text-gray-700 dark:text-gray-200">
<h1 class="text-2xl font-bold text-gray-700 dark:text-gray-200">
{{ crypto.name }}
</h1>
</div>
<div style="--stagger: 2; --delay: 100ms" data-animate class="flex flex-col gap-2">
<div class="flex flex-row items-center">
<span class="text-4xl font-semibold text-gray-700 dark:text-gray-200">{{ displayNumberValue(price) }} $</span>
<span class="text-4xl font-semibold text-gray-700 dark:text-gray-200">{{ displayNumberValue(dynamicData) }} $</span>
</div>

<div class="flex flex-row items-center gap-2 font-sans text-sm font-medium" :class="variations.value > 0 ? 'positive' : 'negative'">
<div class="flex flex-row items-center gap-1">
<UIcon name="lucide:circle-arrow-down" class="size-5 transition-transform" :class="[variations.value > 0 && 'rotate-180 transform']" />
Expand All @@ -44,7 +91,7 @@ const series = crypto.data
<ChartLine
style="--stagger: 3; --delay: 100ms"
data-animate
:crypto-data="series"
:crypto-data
@update:current-value="price = $event"
@update:variation="variations = $event"
/>
Expand All @@ -55,6 +102,9 @@ const series = crypto.data
<p class="text-sm leading-relaxed text-gray-500 dark:text-gray-400">
{{ crypto.description }}
</p>
<div>
<UButton label="Ping" @click="ping" />
</div>
</div>
</div>
</template>
Expand All @@ -69,4 +119,5 @@ const series = crypto.data
@apply text-red-500;
text-shadow: 0 0 0.5rem rgba(245, 101, 101, 0.2);
}
</style>
3 changes: 3 additions & 0 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ export default defineNuxtConfig({
crawlLinks: true,
routes: ['/', '/app/market'],
},
experimental: {
websocket: true
}
},

imports: {
Expand Down
9 changes: 0 additions & 9 deletions server/api/crypto/[symbol]/index.get.ts

This file was deleted.

32 changes: 32 additions & 0 deletions server/api/crypto/ws.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { Peer } from 'crossws'
import { getQuery } from 'ufo'

let intervalId: NodeJS.Timeout

export default defineWebSocketHandler({
open(peer: Peer) {
console.log(`[ws] open ${peer}`)
const { symbol } = getQuery(peer.url)
console.log(`[ws] symbol ${symbol}`)

peer.subscribe('value')

const sendRandomNumber = () => {
const randomNumber = generateRandomValue()
peer.send({ number: randomNumber })
}

intervalId = setInterval(sendRandomNumber, 1500)
},
message(peer, message) {
console.log(`[ws] message ${peer} ${message.text()}`)

if (message.text() === 'ping') {
peer.send('pong')
}
},
close(peer) {
console.log(`[ws] close ${peer}`)
clearInterval(intervalId)
}
})
6 changes: 5 additions & 1 deletion server/app/cryptoService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import dayjs from 'dayjs'
import type { UpsertCryptoDto } from '~~/types/Crypto'
import { generateRandomValue } from '~~/server/utils/number'

function smoothCryptoData(cryptoData: [timestamp: number, value: number][], windowSize: number) {
const smoothedData = []
Expand All @@ -24,7 +25,10 @@ export async function getAllCryptos(all: boolean = false) {
const cryptoList = cryptos.map((crypto) => {
const data = []
for (let i = 0; i < 365; i++) {
data.push([dayjs().subtract(i, 'day').valueOf(), Math.floor(Math.random() * (10000 - 300 + 1)) + 300])
data.push([
dayjs().subtract(i, 'day').valueOf(),
generateRandomValue()
])
}
crypto.data = smoothCryptoData(data, 7)
return crypto
Expand Down
3 changes: 3 additions & 0 deletions server/utils/number.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function generateRandomValue(min: number = 300, max: number = 10000): number {
return Math.floor(Math.random() * (max - min + 1)) + min
}

0 comments on commit 6e72bf3

Please sign in to comment.