diff --git a/frontend/components/task/TaskModal.vue b/frontend/components/task/TaskModal.vue
index 3f3ceeb..e9f45e7 100644
--- a/frontend/components/task/TaskModal.vue
+++ b/frontend/components/task/TaskModal.vue
@@ -65,6 +65,20 @@
@blur="touched.title = true"
/>
+
+
+
+
+ Le projet est requis
+
+
+
()
const emit = defineEmits<{
@@ -318,10 +335,12 @@ const form = reactive({
groupId: null as number | null,
tagIds: [] as number[],
clientTicketId: null as number | null,
+ projectId: null as number | null,
})
const touched = reactive({
title: false,
+ project: false,
})
const statusOptions = computed(() =>
@@ -340,8 +359,22 @@ const userOptions = computed(() =>
props.users.map(u => ({ label: u.username, value: u.id }))
)
-const groupOptions = computed(() =>
- props.groups.map(g => ({ label: g.title, value: g.id }))
+const groupOptions = computed(() => {
+ let filtered = props.groups
+ if (showProjectSelect.value && form.projectId) {
+ filtered = filtered.filter(g => g.project?.id === form.projectId)
+ }
+ return filtered.map(g => ({ label: g.title, value: g.id }))
+})
+
+const showProjectSelect = computed(() => !!props.projects?.length && !isEditing.value)
+
+const projectOptions = computed(() =>
+ (props.projects ?? []).map(p => ({ label: p.name, value: p.id }))
+)
+
+const resolvedProjectId = computed(() =>
+ showProjectSelect.value ? form.projectId : props.projectId
)
const canArchive = computed(() => {
@@ -385,8 +418,10 @@ function populateForm(task: Task | null) {
form.groupId = null
form.tagIds = []
form.clientTicketId = null
+ form.projectId = null
}
touched.title = false
+ touched.project = false
}
watch(() => props.modelValue, async (open) => {
@@ -394,9 +429,14 @@ watch(() => props.modelValue, async (open) => {
confirmDeleteDocOpen.value = false
documentToDelete.value = null
populateForm(props.task)
- try {
- clientTickets.value = await clientTicketService.getAll({ project: props.projectId })
- } catch {
+ const pid = resolvedProjectId.value
+ if (pid) {
+ try {
+ clientTickets.value = await clientTicketService.getAll({ project: pid })
+ } catch {
+ clientTickets.value = []
+ }
+ } else {
clientTickets.value = []
}
if (props.task?.project?.giteaOwner && props.task?.project?.giteaRepo && !giteaUrl.value) {
@@ -426,6 +466,22 @@ const clientTicketOptions = computed(() =>
clientTickets.value.map(ct => ({ label: `CT-${String(ct.number).padStart(3, '0')} — ${ct.title}`, value: ct.id }))
)
+// Reset group and reload client tickets when project changes in create mode
+watch(() => form.projectId, async (pid) => {
+ if (!showProjectSelect.value) return
+ form.groupId = null
+ form.clientTicketId = null
+ if (pid) {
+ try {
+ clientTickets.value = await clientTicketService.getAll({ project: pid })
+ } catch {
+ clientTickets.value = []
+ }
+ } else {
+ clientTickets.value = []
+ }
+})
+
const authStore = useAuthStore()
const isAdmin = computed(() => authStore.user?.roles?.includes('ROLE_ADMIN') ?? false)
@@ -541,7 +597,9 @@ async function handleUnarchive() {
async function handleSubmit() {
touched.title = true
+ touched.project = true
if (!form.title.trim()) return
+ if (showProjectSelect.value && !form.projectId) return
isSubmitting.value = true
try {
@@ -553,7 +611,7 @@ async function handleSubmit() {
priority: form.priorityId ? `/api/task_priorities/${form.priorityId}` : null,
assignee: form.assigneeId ? `/api/users/${form.assigneeId}` : null,
group: form.groupId ? `/api/task_groups/${form.groupId}` : null,
- project: `/api/projects/${props.projectId}`,
+ project: `/api/projects/${resolvedProjectId.value}`,
tags: form.tagIds.map(id => `/api/task_tags/${id}`),
clientTicket: form.clientTicketId ? `/api/client_tickets/${form.clientTicketId}` : null,
}
diff --git a/frontend/i18n/locales/fr.json b/frontend/i18n/locales/fr.json
index 1044ec1..859a668 100644
--- a/frontend/i18n/locales/fr.json
+++ b/frontend/i18n/locales/fr.json
@@ -112,7 +112,8 @@
"allEfforts": "Tous les efforts",
"allAssignees": "Tous",
"noTasks": "Aucune tâche",
- "backlog": "Backlog"
+ "backlog": "Backlog",
+ "createTask": "Créer une tâche"
},
"dashboard": {
"title": "Tableau de bord",
diff --git a/frontend/layouts/default.vue b/frontend/layouts/default.vue
index bbf64ae..3c6f7fb 100644
--- a/frontend/layouts/default.vue
+++ b/frontend/layouts/default.vue
@@ -123,9 +123,9 @@
-
+
-
+
diff --git a/frontend/pages/my-tasks.vue b/frontend/pages/my-tasks.vue
index bb28a10..dabc8b3 100644
--- a/frontend/pages/my-tasks.vue
+++ b/frontend/pages/my-tasks.vue
@@ -214,6 +214,11 @@ async function onDropBacklog(event: DragEvent) {
}
// Modal
+function openTaskCreate() {
+ selectedTask.value = null
+ taskModalOpen.value = true
+}
+
function openTaskEdit(task: Task) {
selectedTask.value = task
taskModalOpen.value = true
@@ -229,28 +234,37 @@ onMounted(() => {
-
+
{{ $t('myTasks.title') }}
-
+
-
+
+
+
+
@@ -314,11 +328,11 @@ onMounted(() => {
-
+
{
:tags="tags"
:groups="selectedTask?.project?.id ? groups.filter(g => g.project?.id === selectedTask?.project?.id) : groups"
:users="users"
+ :projects="projects"
@saved="onSaved"
/>
diff --git a/frontend/pages/projects/[id]/index.vue b/frontend/pages/projects/[id]/index.vue
index 5d24a9d..07532b3 100644
--- a/frontend/pages/projects/[id]/index.vue
+++ b/frontend/pages/projects/[id]/index.vue
@@ -1,5 +1,5 @@
-
+
{{ project?.name ?? '' }}
@@ -62,11 +62,11 @@
-