Newer
Older
gnexus-tasks / frontend / src / components / TaskBadges.vue
<script setup lang="ts">
// Строка бейджей метаданных задачи (статус, проект, приоритет, время, дедлайн, бюджет, теги).
import { useI18n } from 'vue-i18n'
import type { Task } from '../api'
import {
  budgetBadge,
  deadlineLabel,
  deadlineOverdue,
  formatMinutes,
  recurrenceLabel,
  statusIcon,
  statusLabel,
  statusVariant,
} from '../taskui'
import PriorityBadge from './PriorityBadge.vue'

defineProps<{ task: Task; hideProject?: boolean }>()

const { t } = useI18n()

// Палитра тегов: цвет — по имени тега (стабильный хеш, один тег всегда одного
// цвета); оттенки — варианты бейджа кита
const TAG_VARIANTS = ['info', 'secondary', 'success', 'warning', 'primary'] as const

function tagVariant(name: string): string {
  let hash = 0
  for (let i = 0; i < name.length; i++) hash = (hash * 31 + name.charCodeAt(i)) % 9973
  return TAG_VARIANTS[hash % TAG_VARIANTS.length]
}
</script>

<template>
  <GnBadge :variant="statusVariant(task.status)">
    <i :class="`ph ${statusIcon(task.status)}`" aria-hidden="true" />{{ statusLabel(task.status) }}
  </GnBadge>
  <!-- проект: контурный бейдж-«ссылка» на сущность -->
  <GnBadge v-if="task.project && !hideProject" variant="primary" outline><i class="ph ph-folder" aria-hidden="true" />
    {{ task.project.name }}
  </GnBadge>
  <PriorityBadge v-if="task.priority !== null" :priority="task.priority" />
  <GnBadge v-if="task.estimated_minutes" variant="primary">
    <i class="ph ph-timer" aria-hidden="true" />≈ {{ formatMinutes(task.estimated_minutes) }}
  </GnBadge>
  <GnBadge v-if="task.task_type === 'recurring'" variant="info"><i class="ph ph-repeat" aria-hidden="true" />
    {{ recurrenceLabel(task) || t('taskui.recur.recurring') }}
  </GnBadge>
  <GnBadge
    v-if="deadlineLabel(task)"
    :variant="deadlineOverdue(task) ? 'error' : 'warning'"
  ><i class="ph ph-alarm" aria-hidden="true" />
    {{ deadlineLabel(task) }}
  </GnBadge>
  <GnBadge v-if="task.mentally_hard" variant="warning">
    <i class="ph ph-brain" aria-hidden="true" />{{ t('task.mentallyHard.badge') }}
  </GnBadge>
  <GnBadge v-if="task.budget_money !== null" variant="warning">
    <i class="ph ph-coins" aria-hidden="true" />{{ budgetBadge(task) }}
  </GnBadge>
  <GnBadge v-for="tag in task.tags" :key="tag.id" :variant="tagVariant(tag.name)" class="tag-badge">
    <i class="ph ph-tag" aria-hidden="true" />{{ tag.name }}
  </GnBadge>
</template>