refactor : rename TaskType to TaskTag across the stack
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-lg font-bold text-neutral-900">Types</h2>
|
||||
<h2 class="text-lg font-bold text-neutral-900">Tags</h2>
|
||||
<button
|
||||
class="rounded-md bg-primary-500 px-4 py-2 text-sm font-semibold text-white hover:bg-secondary-500"
|
||||
@click="openCreate"
|
||||
>
|
||||
+ Ajouter un type
|
||||
+ Ajouter un tag
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
:columns="columns"
|
||||
:items="items"
|
||||
:loading="isLoading"
|
||||
empty-message="Aucun type trouvé."
|
||||
empty-message="Aucun tag trouvé."
|
||||
deletable
|
||||
@row-click="openEdit"
|
||||
@delete="(item) => handleDelete(item.id)"
|
||||
@@ -27,7 +27,7 @@
|
||||
</template>
|
||||
</DataTable>
|
||||
|
||||
<TaskTypeDrawer
|
||||
<TaskTagDrawer
|
||||
v-model="drawerOpen"
|
||||
:item="selectedItem"
|
||||
@saved="onSaved"
|
||||
@@ -36,8 +36,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { TaskType } from '~/services/dto/task-type'
|
||||
import { useTaskTypeService } from '~/services/task-types'
|
||||
import type { TaskTag } from '~/services/dto/task-tag'
|
||||
import { useTaskTagService } from '~/services/task-tags'
|
||||
|
||||
import type { DataTableColumn } from '~/components/ui/DataTable.vue'
|
||||
|
||||
@@ -46,11 +46,11 @@ const columns: DataTableColumn[] = [
|
||||
{ key: 'color', label: 'Couleur' },
|
||||
]
|
||||
|
||||
const { getAll, remove } = useTaskTypeService()
|
||||
const items = ref<TaskType[]>([])
|
||||
const { getAll, remove } = useTaskTagService()
|
||||
const items = ref<TaskTag[]>([])
|
||||
const isLoading = ref(true)
|
||||
const drawerOpen = ref(false)
|
||||
const selectedItem = ref<TaskType | null>(null)
|
||||
const selectedItem = ref<TaskTag | null>(null)
|
||||
|
||||
async function loadItems() {
|
||||
isLoading.value = true
|
||||
@@ -66,7 +66,7 @@ function openCreate() {
|
||||
drawerOpen.value = true
|
||||
}
|
||||
|
||||
function openEdit(item: TaskType) {
|
||||
function openEdit(item: TaskTag) {
|
||||
selectedItem.value = item
|
||||
drawerOpen.value = true
|
||||
}
|
||||
@@ -7,7 +7,10 @@
|
||||
@click="emit('click')"
|
||||
>
|
||||
<div class="flex items-start justify-between gap-2">
|
||||
<h4 class="text-sm font-semibold text-neutral-900">{{ task.title }}</h4>
|
||||
<div class="min-w-0">
|
||||
<span v-if="task.project && task.number" class="text-xs font-medium text-neutral-400">{{ task.project.code }}{{ task.number }}</span>
|
||||
<h4 class="text-sm font-semibold text-neutral-900">{{ task.title }}</h4>
|
||||
</div>
|
||||
<button
|
||||
class="shrink-0 transition-colors"
|
||||
:class="isTimerOnTask ? 'text-[#F18619] hover:text-[#d97314]' : 'text-neutral-400 hover:text-primary-500'"
|
||||
@@ -26,12 +29,12 @@
|
||||
{{ task.priority.label }}
|
||||
</span>
|
||||
<span
|
||||
v-for="type in task.types"
|
||||
:key="type.id"
|
||||
v-for="tag in task.tags"
|
||||
:key="tag.id"
|
||||
class="rounded-full px-2 py-0.5 text-xs font-semibold text-white"
|
||||
:style="{ backgroundColor: type.color }"
|
||||
:style="{ backgroundColor: tag.color }"
|
||||
>
|
||||
{{ type.label }}
|
||||
{{ tag.label }}
|
||||
</span>
|
||||
<span
|
||||
v-if="task.assignee"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<AppDrawer v-model="isOpen" :title="isEditing ? 'Modifier un type' : 'Ajouter un type'">
|
||||
<AppDrawer v-model="isOpen" :title="isEditing ? 'Modifier un tag' : 'Ajouter un tag'">
|
||||
<form @submit.prevent="handleSubmit" class="flex flex-col gap-2">
|
||||
<MalioInputText
|
||||
v-model="form.label"
|
||||
@@ -26,12 +26,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { TaskType, TaskTypeWrite } from '~/services/dto/task-type'
|
||||
import { useTaskTypeService } from '~/services/task-types'
|
||||
import type { TaskTag, TaskTagWrite } from '~/services/dto/task-tag'
|
||||
import { useTaskTagService } from '~/services/task-tags'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean
|
||||
item: TaskType | null
|
||||
item: TaskTag | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -69,7 +69,7 @@ watch(() => props.modelValue, (open) => {
|
||||
}
|
||||
})
|
||||
|
||||
const { create, update } = useTaskTypeService()
|
||||
const { create, update } = useTaskTagService()
|
||||
|
||||
async function handleSubmit() {
|
||||
touched.label = true
|
||||
@@ -77,7 +77,7 @@ async function handleSubmit() {
|
||||
|
||||
isSubmitting.value = true
|
||||
try {
|
||||
const payload: TaskTypeWrite = {
|
||||
const payload: TaskTagWrite = {
|
||||
label: form.label.trim(),
|
||||
color: form.color,
|
||||
}
|
||||
@@ -25,14 +25,14 @@
|
||||
<span class="ml-auto shrink-0 text-[10px] tabular-nums opacity-80">{{ duration }}</span>
|
||||
</div>
|
||||
<div v-if="entry.project" class="truncate text-[10px] opacity-80">{{ entry.project.name }}</div>
|
||||
<div v-if="entry.types.length" class="mt-0.5 flex items-center gap-1 overflow-hidden">
|
||||
<div v-if="entry.tags.length" class="mt-0.5 flex items-center gap-1 overflow-hidden">
|
||||
<span
|
||||
v-for="type in entry.types"
|
||||
:key="type.id"
|
||||
v-for="tag in entry.tags"
|
||||
:key="tag.id"
|
||||
class="inline-flex items-center gap-0.5 truncate text-[9px] opacity-90"
|
||||
>
|
||||
<span class="inline-block h-1.5 w-1.5 shrink-0 rounded-full" :style="{ backgroundColor: type.color }" />
|
||||
{{ type.label }}
|
||||
<span class="inline-block h-1.5 w-1.5 shrink-0 rounded-full" :style="{ backgroundColor: tag.color }" />
|
||||
{{ tag.label }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -73,25 +73,25 @@
|
||||
/>
|
||||
|
||||
<div>
|
||||
<p class="mb-2 text-sm font-semibold text-neutral-700">Types</p>
|
||||
<p class="mb-2 text-sm font-semibold text-neutral-700">Tags</p>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<label
|
||||
v-for="type in types"
|
||||
:key="type.id"
|
||||
v-for="tag in tags"
|
||||
:key="tag.id"
|
||||
class="cursor-pointer rounded-full px-3 py-1 text-xs font-semibold transition"
|
||||
:class="form.typeIds.includes(type.id)
|
||||
:class="form.tagIds.includes(tag.id)
|
||||
? 'text-white'
|
||||
: 'bg-neutral-100 text-neutral-600 hover:bg-neutral-200'"
|
||||
:style="form.typeIds.includes(type.id) ? { backgroundColor: type.color } : {}"
|
||||
:style="form.tagIds.includes(tag.id) ? { backgroundColor: tag.color } : {}"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="hidden"
|
||||
:value="type.id"
|
||||
:checked="form.typeIds.includes(type.id)"
|
||||
@change="toggleType(type.id)"
|
||||
:value="tag.id"
|
||||
:checked="form.tagIds.includes(tag.id)"
|
||||
@change="toggleTag(tag.id)"
|
||||
/>
|
||||
{{ type.label }}
|
||||
{{ tag.label }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -120,7 +120,7 @@
|
||||
import type { TimeEntry } from '~/services/dto/time-entry'
|
||||
import type { UserData } from '~/services/dto/user-data'
|
||||
import type { Project } from '~/services/dto/project'
|
||||
import type { TaskType } from '~/services/dto/task-type'
|
||||
import type { TaskTag } from '~/services/dto/task-tag'
|
||||
import { useTimeEntryService } from '~/services/time-entries'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -129,7 +129,7 @@ const props = defineProps<{
|
||||
prefillStartedAt?: string | null
|
||||
users: UserData[]
|
||||
projects: Project[]
|
||||
types: TaskType[]
|
||||
tags: TaskTag[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -154,7 +154,7 @@ const form = reactive({
|
||||
endTime: '',
|
||||
userId: authStore.user?.id ?? null as number | null,
|
||||
projectId: null as number | null,
|
||||
typeIds: [] as number[],
|
||||
tagIds: [] as number[],
|
||||
})
|
||||
|
||||
const userOptions = computed(() =>
|
||||
@@ -176,12 +176,12 @@ const durationLabel = computed(() => {
|
||||
return m > 0 ? `${h}h${String(m).padStart(2, '0')}` : `${h}h`
|
||||
})
|
||||
|
||||
function toggleType(id: number) {
|
||||
const idx = form.typeIds.indexOf(id)
|
||||
function toggleTag(id: number) {
|
||||
const idx = form.tagIds.indexOf(id)
|
||||
if (idx >= 0) {
|
||||
form.typeIds.splice(idx, 1)
|
||||
form.tagIds.splice(idx, 1)
|
||||
} else {
|
||||
form.typeIds.push(id)
|
||||
form.tagIds.push(id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ function populateForm(entry: TimeEntry | null | undefined) {
|
||||
form.endTime = entry.stoppedAt ? toLocalTime(entry.stoppedAt) : ''
|
||||
form.userId = entry.user?.id ?? authStore.user?.id ?? null
|
||||
form.projectId = entry.project?.id ?? null
|
||||
form.typeIds = entry.types?.map(t => t.id) ?? []
|
||||
form.tagIds = entry.tags?.map(t => t.id) ?? []
|
||||
} else {
|
||||
form.title = ''
|
||||
form.description = ''
|
||||
@@ -221,7 +221,7 @@ function populateForm(entry: TimeEntry | null | undefined) {
|
||||
form.endTime = ''
|
||||
form.userId = authStore.user?.id ?? null
|
||||
form.projectId = null
|
||||
form.typeIds = []
|
||||
form.tagIds = []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ async function onSubmit() {
|
||||
stoppedAt: form.endTime ? toISO(form.date, form.endTime) : null,
|
||||
user: `/api/users/${form.userId}`,
|
||||
project: form.projectId ? `/api/projects/${form.projectId}` : null,
|
||||
types: form.typeIds.map(id => `/api/task_types/${id}`),
|
||||
tags: form.tagIds.map(id => `/api/task_tags/${id}`),
|
||||
}
|
||||
|
||||
if (isEditing.value && props.entry) {
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
{{ entry.title || 'Sans titre' }}
|
||||
</span>
|
||||
<span
|
||||
v-for="type in entry.types"
|
||||
:key="type.id"
|
||||
v-for="tag in entry.tags"
|
||||
:key="tag.id"
|
||||
class="shrink-0 rounded-full px-2 py-0.5 text-[10px] font-semibold text-white"
|
||||
:style="{ backgroundColor: type.color }"
|
||||
:style="{ backgroundColor: tag.color }"
|
||||
>
|
||||
{{ type.label }}
|
||||
{{ tag.label }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-0.5 flex items-center gap-2 text-xs text-neutral-500">
|
||||
|
||||
Reference in New Issue
Block a user