kodadot/nft-gallery

View on GitHub
components/collection/activity/ownerInsightsTabs/FlipperTab.vue

Summary

Maintainability
Test Coverage
<template>
  <div>
    <div v-if="flippers.length">
      <div
        v-for="[
          flipperId,
          {
            bestFlip,
            owned,
            totalBought,
            totalsold,
            latestflipTimestamp,
            flips,
          },
        ] in displayedFlippers"
        :key="flipperId"
        class="hide-last-hr"
      >
        <div class="flex flex-col gap-2">
          <div class="px-5">
            <ProfileLink
              :address="flipperId"
              :avatar-size="35"
              class="font-bold"
            />
            <div class="flex justify-between mt-2">
              <span class="text-xs text-k-grey">{{
                $t('activity.owned')
              }}</span>
              <span>{{ owned }}</span>
            </div>
            <div class="flex justify-between">
              <span class="text-xs text-k-grey">{{
                $t('activity.totalBought')
              }}</span>
              <CommonTokenMoney :value="totalBought" />
            </div>
            <div class="flex justify-between">
              <span class="text-xs text-k-grey">{{
                $t('activity.totalSold')
              }}</span>
              <CommonTokenMoney :value="totalsold" />
            </div>
            <div class="flex justify-between">
              <span class="text-xs text-k-grey">{{
                $t('activity.bestFlip')
              }}</span>
              <span
                :class="{
                  'text-k-green': bestFlip > 0,
                  'text-k-red': bestFlip < 0,
                }"
              >{{ bestFlip === 0 ? '--' : `${format(bestFlip)}%` }}</span>
            </div>
            <div class="flex justify-between">
              <span class="text-xs text-k-grey">{{
                $t('activity.latestActivity')
              }}</span>
              <TimeAgo
                custom-class="whitespace-nowrap"
                :timestamp="latestflipTimestamp"
              />
            </div>
            <div>
              <div
                class="text-xs text-k-blue hover:text-k-blue-hover cursor-pointer"
                @click="toggleNFTDetails(flipperId)"
              >
                {{ $t('activity.nftDetails') }}
                <NeoIcon
                  :icon="
                    isNFTDetailsOpen[flipperId]
                      ? 'chevron-down'
                      : 'chevron-right'
                  "
                />
              </div>
            </div>
          </div>
          <div v-if="isNFTDetailsOpen[flipperId]">
            <NFTsDetaislDropdown
              :flips="flips"
              variant="Flippers"
            />
          </div>
        </div>
        <hr class="my-3 mx-5">
      </div>
      <div ref="target" />
    </div>

    <div
      v-else
      class="flex justify-center items-center pt-6"
    >
      <div class="text-k-grey">
        {{ $t('activity.noFlips') }}
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { NeoIcon } from '@kodadot1/brick'
import NFTsDetaislDropdown from './NFTsDetaislDropdown.vue'
import ProfileLink from '@/components/profile/ProfileLink.vue'
import { format } from '@/components/collection/activity/utils'

import type { Flippers } from '@/composables/collectionActivity/types'

const props = defineProps<{
  flippers?: Flippers
}>()
const target = ref<HTMLElement | null>(null)
const offset = ref(4)

const flippers = computed(() => Object.entries(props.flippers || {}))

const toggleNFTDetails = (flipperId: string) => {
  const isOpen = isNFTDetailsOpen.value[flipperId]
  isNFTDetailsOpen.value = {
    ...isNFTDetailsOpen.value,
    [flipperId]: !isOpen,
  }
}

useIntersectionObserver(target, ([{ isIntersecting }]) => {
  if (isIntersecting) {
    offset.value += 4
  }
})

const displayedFlippers = computed(() => flippers.value.slice(0, offset.value))
// map of flipper id to boolean, is the NFT details section of that flipper open or nor
// {id0: false, id1: true, id3: false, ...}
const isFlipperMoreNFTSectionOpen = flippers.value.reduce(

  (accumelator, [flipperId, _]) => ({
    ...accumelator,
    [flipperId]: false,
  }),
  {},
)

const isNFTDetailsOpen = ref(isFlipperMoreNFTSectionOpen)
</script>

<style lang="scss" scoped>
.hide-last-hr:last-child > hr {
  display: none;
}
</style>