StatisticalCard.vue 2.44 KB
<script lang="ts" setup>
  import { Card, Tooltip } from 'ant-design-vue';
  import { InfoCircleOutlined } from '@ant-design/icons-vue';
  import { CountTo } from '/@/components/CountTo';

  interface RecordType {
    value: number;
    label: string;
  }

  const props = withDefaults(
    defineProps<{
      value?: {
        images: string;
        totals: RecordType[];
        tooltips: RecordType[];
        todayTotals: RecordType[];
        withUnit?: boolean;
      };
    }>(),
    {
      value: () => ({
        images: new URL('../../../../assets/images/product.png', import.meta.url).href,
        totals: [],
        tooltips: [],
        todayTotals: [],
      }),
    }
  );

  const getThresholdValue = (value: number) => {
    const record = { value, unit: null };

    if (!props.value?.withUnit) return record;

    if (value > 10 ** 6) return { unit: 'M', value: value / 10 ** 6 };
    if (value > 10 ** 3) return { unit: 'K', value: value / 10 ** 3 };

    return record;
  };
</script>

<template>
  <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4">
    <main class="flex flex-col">
      <div class="flex">
        <img class="!w-22.5 !h-22.5 !mb-2.5 !mr-2.5" :src="value.images" alt="" />
        <div class="flex flex-1">
          <div
            class="flex-auto w-full"
            v-for="(item, index) in value.totals"
            :key="index"
            :style="{ width: `${100 / value.totals.length}%` }"
          >
            <div class="font-bold text-2xl">
              <CountTo :end-val="getThresholdValue(item.value).value ?? 0" class="break-all" />
              <span>{{ getThresholdValue(item.value).unit || '' }}</span>
            </div>
            <div class="text-gray-600">{{ item.label }}</div>
          </div>
        </div>
        <Tooltip>
          <template #title>
            <div v-for="(item, index) in value.tooltips" :key="index" class="w-25">
              <span>{{ item.label }}</span>
              <span class="ml-1">{{ item.value ?? 0 }}</span>
            </div>
          </template>
          <InfoCircleOutlined class="text-lg svg:fill-gray-400 w-4.5 h-4.5" />
        </Tooltip>
      </div>
      <div class="pt-4 border-t-2 border-gray-100 flex text-gray-600 justify-between">
        <div v-for="(item, index) in value.todayTotals" :key="index">
          <span>{{ item.label }}</span>
          <span class="ml-1">{{ item.value ?? 0 }}</span>
        </div>
      </div>
    </main>
  </Card>
</template>