feat(task) : add client ticket selector in TaskModal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-15 20:14:56 +01:00
parent 6c910e7fcc
commit a2fc8e6e52
2 changed files with 27 additions and 1 deletions

View File

@@ -102,6 +102,14 @@
empty-option-label="Aucun groupe"
min-width="w-full"
/>
<MalioSelect
v-if="clientTicketOptions.length"
v-model="form.clientTicketId"
:options="clientTicketOptions"
label="Ticket client"
empty-option-label="Aucun ticket client"
min-width="w-full"
/>
</div>
<!-- Tags -->
@@ -245,8 +253,10 @@
<script setup lang="ts">
import type { Task, TaskWrite } from '~/services/dto/task'
import type { TaskDocument } from '~/services/dto/task-document'
import type { ClientTicket } from '~/services/dto/client-ticket'
import { useGiteaService } from '~/services/gitea'
import { useTaskDocumentService } from '~/services/task-documents'
import { useClientTicketService } from '~/services/client-tickets'
import ConfirmDeleteDocumentModal from '~/components/ui/ConfirmDeleteDocumentModal.vue'
import type { TaskStatus } from '~/services/dto/task-status'
import type { TaskEffort } from '~/services/dto/task-effort'
@@ -306,6 +316,7 @@ const form = reactive({
assigneeId: null as number | null,
groupId: null as number | null,
tagIds: [] as number[],
clientTicketId: null as number | null,
})
const touched = reactive({
@@ -362,6 +373,7 @@ function populateForm(task: Task | null) {
form.assigneeId = task.assignee?.id ?? null
form.groupId = task.group?.id ?? null
form.tagIds = task.tags.map(t => t.id)
form.clientTicketId = task.clientTicket?.id ?? null
} else {
form.title = ''
form.description = ''
@@ -371,13 +383,19 @@ function populateForm(task: Task | null) {
form.assigneeId = null
form.groupId = null
form.tagIds = []
form.clientTicketId = null
}
touched.title = false
}
watch(() => props.modelValue, (open) => {
watch(() => props.modelValue, async (open) => {
if (open) {
populateForm(props.task)
try {
clientTickets.value = await clientTicketService.getAll({ project: props.projectId })
} catch {
clientTickets.value = []
}
}
})
@@ -400,8 +418,14 @@ watch(() => props.modelValue, async (open) => {
const { create, update, remove } = useTaskService()
const { remove: removeDocument, getByTask: getDocumentsByTask } = useTaskDocumentService()
const clientTicketService = useClientTicketService()
const { t } = useI18n()
const clientTickets = ref<ClientTicket[]>([])
const clientTicketOptions = computed(() =>
clientTickets.value.map(ct => ({ label: `CT-${String(ct.number).padStart(3, '0')}${ct.title}`, value: ct.id }))
)
const authStore = useAuthStore()
const isAdmin = computed(() => authStore.user?.roles?.includes('ROLE_ADMIN') ?? false)
@@ -532,6 +556,7 @@ async function handleSubmit() {
group: form.groupId ? `/api/task_groups/${form.groupId}` : null,
project: `/api/projects/${props.projectId}`,
tags: form.tagIds.map(id => `/api/task_tags/${id}`),
clientTicket: form.clientTicketId ? `/api/client_tickets/${form.clientTicketId}` : null,
}
if (isEditing.value && props.task) {

View File

@@ -42,4 +42,5 @@ export type TaskWrite = {
project: string
tags: string[]
archived?: boolean
clientTicket?: string | null
}