kodadot/nft-gallery

View on GitHub
components/collection/activity/ActivityChart.vue

Summary

Maintainability
Test Coverage
<template>
  <PriceChart
    v-if="events.length > 0"
    v-model:hide-outliers="hideOutliers"
    v-model:apply-smoothing="applySmoothing"
    :price-chart-data="chartData"
    chart-height="350px"
    data-testid="collection-activity-chart"
  />
  <div
    v-else-if="loading"
    class="relative h-[350px]"
  >
    <SkeletonLoader
      :title="$t('activity.generatingChart')"
      class="absolute"
    />
  </div>
</template>

<script setup lang="ts">
import { Interaction } from '@kodadot1/minimark/v1'
import type {
  DataPoint } from './utils'
import {
  bin,
  displayValue,
  getBinSizeForRange,
  removeOutliers,
  sortAsc,
  toDataPoint,
} from './utils'
import type { ActivityInteraction } from '@/types'
import PriceChart from '@/components/chart/PriceChart.vue'

const { decimals } = useChain()

const props = withDefaults(
  defineProps<{
    events: ActivityInteraction[]
    loading?: boolean
  }>(),
  {
    events: () => [],
    loading: false,
  },
)
const hideOutliers = ref(true)
const applySmoothing = ref(true)

const buyEvents = computed(() =>
  sortAsc(
    props.events
      .filter(e => e.interaction === Interaction.BUY)
      .map(toDataPoint),
  ),
)
const listEvents = computed(() => {
  const listDataPoints = sortAsc(
    props.events
      .filter(e => e.interaction === Interaction.LIST)
      .map(toDataPoint),
  )
  return hideOutliers.value ? removeOutliers(listDataPoints) : listDataPoints
})

const toChartFormat = (events: DataPoint[]) =>
  events.map(({ timestamp, value }) => [
    new Date(timestamp),
    displayValue(value, decimals.value),
  ])

const chartData = computed(() => {
  if (!applySmoothing.value) {
    return [toChartFormat(buyEvents.value), toChartFormat(listEvents.value)]
  }
  const buyBinSize = getBinSizeForRange({
    timestamps: buyEvents.value.map(e => e.timestamp),
  })
  const listBinSize = getBinSizeForRange({
    timestamps: listEvents.value.map(e => e.timestamp),
  })
  const buyBins = bin(buyEvents.value, buyBinSize)
  const listBins = bin(listEvents.value, listBinSize)

  return [toChartFormat(buyBins), toChartFormat(listBins)]
})
</script>