Untitled

mail@pastecode.io avatar
unknown
typescript
a month ago
1.8 kB
5
Indexable
Never
<template>
  <div
    ref="containerRef"
    class="relative w-full overflow-x-auto snap-x snap-mandatory scroll-smooth scrollbar-thin scrollbar-thumb-gray-400 scrollbar-track-gray-200"
  >
    <div :style="{ width: totalWidth }" class="flex space-x-2">
      <div
        v-for="(stage, key) in stages"
        :key="key"
        class="snap-start"
        style="width: 2000px"
        :data-id="stage.id"
      >
        <slot :stage="stage" />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {ref, computed, onMounted, onUnmounted} from 'vue';
import { useStageStore } from '@/stores/stage-store';

const MIN_STAGE_WIDTH = 300;

const props = defineProps<{
  pipelineId: number;
}>();

const stageStore = useStageStore();

const stages = computed(() => {
  return stageStore.state.stageMapPipelineId[props.pipelineId] || {};
});

const containerRef = ref<HTMLElement | null>(null);
const containerWidth = ref(0);

const stagesCount = computed(() => Object.keys(stages.value).length);

//WTF? Ko hiểu sao nó hoạt động đúng?
const stageWidth = computed(() => {
  const MAX_VISIBLE_STAGES = 5;
  const maxVisibleStages = Math.min(
    Math.floor(containerWidth.value / MIN_STAGE_WIDTH),
    MAX_VISIBLE_STAGES
  );
  const calculatedWidth = containerWidth.value / Math.min(maxVisibleStages, stagesCount.value);
  return Math.max(calculatedWidth, MIN_STAGE_WIDTH);
});

const totalWidth = computed(() => `${stageWidth.value * stagesCount.value}px`);

const updateContainerWidth = () => {
  if (containerRef.value) {
    containerWidth.value = containerRef.value.offsetWidth;
  }
};

onMounted(() => {
  updateContainerWidth();
  window.addEventListener('resize', updateContainerWidth);
});

onUnmounted(() => {
  window.removeEventListener('resize', updateContainerWidth);
});
</script>
Leave a Comment