|
@@ -13,7 +13,6 @@
|
|
|
@submit="onOKClick"
|
|
@submit="onOKClick"
|
|
|
>
|
|
>
|
|
|
<q-card-section class="q-pt-sm" style="flex: 1; overflow-y: auto; min-height: 0">
|
|
<q-card-section class="q-pt-sm" style="flex: 1; overflow-y: auto; min-height: 0">
|
|
|
- <!-- Tabs: only shown when editing -->
|
|
|
|
|
<CustomTabComponent
|
|
<CustomTabComponent
|
|
|
v-if="card?.id"
|
|
v-if="card?.id"
|
|
|
v-model:active-tab="currentTab"
|
|
v-model:active-tab="currentTab"
|
|
@@ -24,6 +23,7 @@
|
|
|
<!-- Tab: Atividade -->
|
|
<!-- Tab: Atividade -->
|
|
|
<div v-show="currentTab === 'atividade'">
|
|
<div v-show="currentTab === 'atividade'">
|
|
|
<div class="row q-col-gutter-sm">
|
|
<div class="row q-col-gutter-sm">
|
|
|
|
|
+ <!-- 1. Título -->
|
|
|
<DefaultInput
|
|
<DefaultInput
|
|
|
v-model="form.title"
|
|
v-model="form.title"
|
|
|
label="Título da Tarefa"
|
|
label="Título da Tarefa"
|
|
@@ -31,6 +31,18 @@
|
|
|
:rules="[val => !!val || 'Campo obrigatório']"
|
|
:rules="[val => !!val || 'Campo obrigatório']"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
|
|
+ <!-- 2. Destino (primeiro campo de configuração) -->
|
|
|
|
|
+ <DefaultSelect
|
|
|
|
|
+ v-model="form.scope"
|
|
|
|
|
+ label="Destino"
|
|
|
|
|
+ :options="scopeOptions"
|
|
|
|
|
+ emit-value
|
|
|
|
|
+ map-options
|
|
|
|
|
+ class="col-6"
|
|
|
|
|
+ :rules="[val => !!val || 'Campo obrigatório']"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Prazo ao lado do Destino -->
|
|
|
<DefaultInputDatePicker
|
|
<DefaultInputDatePicker
|
|
|
v-model="form.due_date_display"
|
|
v-model="form.due_date_display"
|
|
|
v-model:untreated-date="form.due_date"
|
|
v-model:untreated-date="form.due_date"
|
|
@@ -38,6 +50,14 @@
|
|
|
class="col-6"
|
|
class="col-6"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
|
|
+ <!-- Unidade específica — só aparece quando scope = specific -->
|
|
|
|
|
+ <UnitSelect
|
|
|
|
|
+ v-if="form.scope === 'specific'"
|
|
|
|
|
+ v-model="selectedUnit"
|
|
|
|
|
+ class="col-6"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 3. Prioridade + Fase -->
|
|
|
<DefaultSelect
|
|
<DefaultSelect
|
|
|
v-model="form.priority"
|
|
v-model="form.priority"
|
|
|
label="Prioridade"
|
|
label="Prioridade"
|
|
@@ -48,15 +68,6 @@
|
|
|
:rules="[val => !!val || 'Campo obrigatório']"
|
|
:rules="[val => !!val || 'Campo obrigatório']"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
- <DefaultSelect
|
|
|
|
|
- v-model="form.responsible_user_id"
|
|
|
|
|
- label="Responsável"
|
|
|
|
|
- :options="userOptions"
|
|
|
|
|
- emit-value
|
|
|
|
|
- map-options
|
|
|
|
|
- class="col-12"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
<DefaultSelect
|
|
<DefaultSelect
|
|
|
v-model="form.phase"
|
|
v-model="form.phase"
|
|
|
label="Fase"
|
|
label="Fase"
|
|
@@ -67,28 +78,14 @@
|
|
|
:rules="[val => !!val || 'Campo obrigatório']"
|
|
:rules="[val => !!val || 'Campo obrigatório']"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
|
|
+ <!-- 4. Setor -->
|
|
|
<DefaultInput
|
|
<DefaultInput
|
|
|
v-model="form.sector"
|
|
v-model="form.sector"
|
|
|
label="Setor"
|
|
label="Setor"
|
|
|
class="col-6"
|
|
class="col-6"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
- <DefaultSelect
|
|
|
|
|
- v-model="form.scope"
|
|
|
|
|
- label="Destino"
|
|
|
|
|
- :options="scopeOptions"
|
|
|
|
|
- emit-value
|
|
|
|
|
- map-options
|
|
|
|
|
- class="col-6"
|
|
|
|
|
- :rules="[val => !!val || 'Campo obrigatório']"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
- <UnitSelect
|
|
|
|
|
- v-if="form.scope === 'specific'"
|
|
|
|
|
- v-model="selectedUnit"
|
|
|
|
|
- class="col-6"
|
|
|
|
|
- />
|
|
|
|
|
-
|
|
|
|
|
|
|
+ <!-- 5. Descrição -->
|
|
|
<DefaultInput
|
|
<DefaultInput
|
|
|
v-model="form.description"
|
|
v-model="form.description"
|
|
|
label="Descrição"
|
|
label="Descrição"
|
|
@@ -130,10 +127,7 @@
|
|
|
@delete="onDeleteComment(reply)"
|
|
@delete="onDeleteComment(reply)"
|
|
|
/>
|
|
/>
|
|
|
</template>
|
|
</template>
|
|
|
- <div
|
|
|
|
|
- v-else
|
|
|
|
|
- class="flex flex-center full-height text-grey-5 text-body2"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <div v-else class="flex flex-center full-height text-grey-5 text-body2">
|
|
|
Nenhum comentário registrado.
|
|
Nenhum comentário registrado.
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -141,18 +135,8 @@
|
|
|
</q-card-section>
|
|
</q-card-section>
|
|
|
|
|
|
|
|
<q-card-actions align="right" class="q-px-md q-pb-md" style="flex-shrink: 0">
|
|
<q-card-actions align="right" class="q-px-md q-pb-md" style="flex-shrink: 0">
|
|
|
- <q-btn
|
|
|
|
|
- outline
|
|
|
|
|
- color="primary"
|
|
|
|
|
- label="Cancelar"
|
|
|
|
|
- @click="onDialogCancel"
|
|
|
|
|
- />
|
|
|
|
|
- <q-btn
|
|
|
|
|
- color="primary"
|
|
|
|
|
- label="Salvar"
|
|
|
|
|
- type="submit"
|
|
|
|
|
- :loading="loading"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <q-btn outline color="primary" label="Cancelar" @click="onDialogCancel" />
|
|
|
|
|
+ <q-btn color="primary" label="Salvar" type="submit" :loading="loading" />
|
|
|
</q-card-actions>
|
|
</q-card-actions>
|
|
|
</q-form>
|
|
</q-form>
|
|
|
</q-card>
|
|
</q-card>
|
|
@@ -179,20 +163,12 @@ import {
|
|
|
updateKanbanReply,
|
|
updateKanbanReply,
|
|
|
deleteKanbanReply,
|
|
deleteKanbanReply,
|
|
|
} from "src/api/kanban_reply";
|
|
} from "src/api/kanban_reply";
|
|
|
-import { getUsers } from "src/api/user";
|
|
|
|
|
|
|
|
|
|
defineEmits([...useDialogPluginComponent.emits]);
|
|
defineEmits([...useDialogPluginComponent.emits]);
|
|
|
|
|
|
|
|
const { card, initialPhase } = defineProps({
|
|
const { card, initialPhase } = defineProps({
|
|
|
- card: {
|
|
|
|
|
- type: Object,
|
|
|
|
|
- default: null,
|
|
|
|
|
- },
|
|
|
|
|
- /** Phase pre-selected when opening the dialog from a column's "add" button */
|
|
|
|
|
- initialPhase: {
|
|
|
|
|
- type: String,
|
|
|
|
|
- default: "a_fazer",
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ card: { type: Object, default: null },
|
|
|
|
|
+ initialPhase: { type: String, default: "a_fazer" },
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
@@ -200,39 +176,37 @@ const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
|
|
|
|
|
|
const $q = useQuasar();
|
|
const $q = useQuasar();
|
|
|
|
|
|
|
|
-const formRef = ref(null);
|
|
|
|
|
-const loading = ref(false);
|
|
|
|
|
|
|
+const formRef = ref(null);
|
|
|
|
|
+const loading = ref(false);
|
|
|
const currentTab = ref("atividade");
|
|
const currentTab = ref("atividade");
|
|
|
|
|
+const replies = ref([]);
|
|
|
const selectedUnit = ref(card?.target_unit_id ? { value: card.target_unit_id } : null);
|
|
const selectedUnit = ref(card?.target_unit_id ? { value: card.target_unit_id } : null);
|
|
|
-const userOptions = ref([]);
|
|
|
|
|
-const replies = ref([]);
|
|
|
|
|
|
|
|
|
|
const tabs = computed(() => [
|
|
const tabs = computed(() => [
|
|
|
- { name: "atividade", label: "Atividade" },
|
|
|
|
|
- { name: "comentarios", label: "Comentários" },
|
|
|
|
|
|
|
+ { name: "atividade", label: "Atividade" },
|
|
|
|
|
+ { name: "comentarios", label: "Comentários" },
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
const priorityOptions = [
|
|
const priorityOptions = [
|
|
|
- { label: "Alta", value: "alta" },
|
|
|
|
|
|
|
+ { label: "Alta", value: "alta" },
|
|
|
{ label: "Normal", value: "normal" },
|
|
{ label: "Normal", value: "normal" },
|
|
|
- { label: "Baixa", value: "baixa" },
|
|
|
|
|
|
|
+ { label: "Baixa", value: "baixa" },
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
const phaseOptions = [
|
|
const phaseOptions = [
|
|
|
- { label: "A Fazer", value: "a_fazer" },
|
|
|
|
|
- { label: "Em Progresso", value: "em_progresso" },
|
|
|
|
|
- { label: "Em Revisão", value: "em_revisao" },
|
|
|
|
|
- { label: "Concluído", value: "concluido" },
|
|
|
|
|
|
|
+ { label: "A Fazer", value: "a_fazer" },
|
|
|
|
|
+ { label: "Em Progresso", value: "em_progresso" },
|
|
|
|
|
+ { label: "Em Revisão", value: "em_revisao" },
|
|
|
|
|
+ { label: "Concluído", value: "concluido" },
|
|
|
{ label: "Demandas Especiais", value: "demandas_especiais" },
|
|
{ label: "Demandas Especiais", value: "demandas_especiais" },
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
const scopeOptions = [
|
|
const scopeOptions = [
|
|
|
- { label: "Interno", value: "internal" },
|
|
|
|
|
- { label: "Todas as Unidades", value: "all" },
|
|
|
|
|
|
|
+ { label: "Interno", value: "internal" },
|
|
|
|
|
+ { label: "Todas as Unidades", value: "all" },
|
|
|
{ label: "Unidade Específica", value: "specific" },
|
|
{ label: "Unidade Específica", value: "specific" },
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
-// Format date from YYYY-MM-DD to DD/MM/YYYY for display
|
|
|
|
|
const formatDisplayDate = (rawDate) => {
|
|
const formatDisplayDate = (rawDate) => {
|
|
|
if (!rawDate) return null;
|
|
if (!rawDate) return null;
|
|
|
const [y, m, d] = rawDate.split("-");
|
|
const [y, m, d] = rawDate.split("-");
|
|
@@ -240,44 +214,29 @@ const formatDisplayDate = (rawDate) => {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const form = ref({
|
|
const form = ref({
|
|
|
- title: card?.title ?? null,
|
|
|
|
|
- priority: card?.priority ?? "normal",
|
|
|
|
|
- phase: card?.phase ?? initialPhase,
|
|
|
|
|
- scope: card?.scope ?? "internal",
|
|
|
|
|
- sector: card?.sector ?? null,
|
|
|
|
|
- description: card?.description ?? null,
|
|
|
|
|
- due_date: card?.due_date ?? null,
|
|
|
|
|
|
|
+ title: card?.title ?? null,
|
|
|
|
|
+ priority: card?.priority ?? "normal",
|
|
|
|
|
+ phase: card?.phase ?? initialPhase,
|
|
|
|
|
+ scope: card?.scope ?? "internal",
|
|
|
|
|
+ sector: card?.sector ?? null,
|
|
|
|
|
+ description: card?.description ?? null,
|
|
|
|
|
+ due_date: card?.due_date ?? null,
|
|
|
due_date_display: formatDisplayDate(card?.due_date),
|
|
due_date_display: formatDisplayDate(card?.due_date),
|
|
|
- responsible_user_id: card?.responsible_user_id ?? null,
|
|
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-const buildPayload = () => {
|
|
|
|
|
- const payload = {
|
|
|
|
|
- title: form.value.title,
|
|
|
|
|
- priority: form.value.priority,
|
|
|
|
|
- phase: form.value.phase,
|
|
|
|
|
- scope: form.value.scope,
|
|
|
|
|
- sector: form.value.sector || null,
|
|
|
|
|
- description: form.value.description || null,
|
|
|
|
|
- due_date: form.value.due_date || null,
|
|
|
|
|
- responsible_user_id: form.value.responsible_user_id || null,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- if (form.value.scope === "specific") {
|
|
|
|
|
- payload.target_unit_id = selectedUnit.value?.value ?? null;
|
|
|
|
|
- } else {
|
|
|
|
|
- payload.target_unit_id = null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return payload;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const loadUsers = async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- const users = await getUsers();
|
|
|
|
|
- userOptions.value = users.map((u) => ({ label: u.name, value: u.id }));
|
|
|
|
|
- } catch {}
|
|
|
|
|
-};
|
|
|
|
|
|
|
+const buildPayload = () => ({
|
|
|
|
|
+ title: form.value.title,
|
|
|
|
|
+ priority: form.value.priority,
|
|
|
|
|
+ phase: form.value.phase,
|
|
|
|
|
+ scope: form.value.scope,
|
|
|
|
|
+ sector: form.value.sector || null,
|
|
|
|
|
+ description: form.value.description || null,
|
|
|
|
|
+ due_date: form.value.due_date || null,
|
|
|
|
|
+ responsible_user_id: null, // Matriz never assigns a responsible
|
|
|
|
|
+ target_unit_id: form.value.scope === "specific"
|
|
|
|
|
+ ? (selectedUnit.value?.value ?? null)
|
|
|
|
|
+ : null,
|
|
|
|
|
+});
|
|
|
|
|
|
|
|
const loadReplies = async () => {
|
|
const loadReplies = async () => {
|
|
|
if (!card?.id) return;
|
|
if (!card?.id) return;
|
|
@@ -287,12 +246,8 @@ const loadReplies = async () => {
|
|
|
const onAddComment = () => {
|
|
const onAddComment = () => {
|
|
|
$q.dialog({
|
|
$q.dialog({
|
|
|
title: "Adicionar Comentário",
|
|
title: "Adicionar Comentário",
|
|
|
- prompt: {
|
|
|
|
|
- model: "",
|
|
|
|
|
- type: "textarea",
|
|
|
|
|
- label: "Comentário",
|
|
|
|
|
- },
|
|
|
|
|
- ok: { label: "Salvar", color: "primary" },
|
|
|
|
|
|
|
+ prompt: { model: "", type: "textarea", label: "Comentário" },
|
|
|
|
|
+ ok: { label: "Salvar", color: "primary" },
|
|
|
cancel: { label: "Cancelar", color: "primary", outline: true },
|
|
cancel: { label: "Cancelar", color: "primary", outline: true },
|
|
|
}).onOk(async (text) => {
|
|
}).onOk(async (text) => {
|
|
|
if (!text?.trim()) return;
|
|
if (!text?.trim()) return;
|
|
@@ -304,12 +259,8 @@ const onAddComment = () => {
|
|
|
const onEditComment = (reply) => {
|
|
const onEditComment = (reply) => {
|
|
|
$q.dialog({
|
|
$q.dialog({
|
|
|
title: "Editar Comentário",
|
|
title: "Editar Comentário",
|
|
|
- prompt: {
|
|
|
|
|
- model: reply.reply,
|
|
|
|
|
- type: "textarea",
|
|
|
|
|
- label: "Comentário",
|
|
|
|
|
- },
|
|
|
|
|
- ok: { label: "Salvar", color: "primary" },
|
|
|
|
|
|
|
+ prompt: { model: reply.reply, type: "textarea", label: "Comentário" },
|
|
|
|
|
+ ok: { label: "Salvar", color: "primary" },
|
|
|
cancel: { label: "Cancelar", color: "primary", outline: true },
|
|
cancel: { label: "Cancelar", color: "primary", outline: true },
|
|
|
}).onOk(async (text) => {
|
|
}).onOk(async (text) => {
|
|
|
if (!text?.trim()) return;
|
|
if (!text?.trim()) return;
|
|
@@ -320,10 +271,10 @@ const onEditComment = (reply) => {
|
|
|
|
|
|
|
|
const onDeleteComment = (reply) => {
|
|
const onDeleteComment = (reply) => {
|
|
|
$q.dialog({
|
|
$q.dialog({
|
|
|
- title: "Excluir Comentário",
|
|
|
|
|
|
|
+ title: "Excluir Comentário",
|
|
|
message: "Tem certeza que deseja excluir este comentário?",
|
|
message: "Tem certeza que deseja excluir este comentário?",
|
|
|
- cancel: { outline: true, color: "primary", label: "Cancelar" },
|
|
|
|
|
- ok: { color: "negative", label: "Excluir" },
|
|
|
|
|
|
|
+ cancel: { outline: true, color: "primary", label: "Cancelar" },
|
|
|
|
|
+ ok: { color: "negative", label: "Excluir" },
|
|
|
}).onOk(async () => {
|
|
}).onOk(async () => {
|
|
|
await deleteKanbanReply(card.id, reply.id);
|
|
await deleteKanbanReply(card.id, reply.id);
|
|
|
loadReplies();
|
|
loadReplies();
|
|
@@ -345,8 +296,5 @@ const onOKClick = async () => {
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-onMounted(() => {
|
|
|
|
|
- loadUsers();
|
|
|
|
|
- loadReplies();
|
|
|
|
|
-});
|
|
|
|
|
|
|
+onMounted(loadReplies);
|
|
|
</script>
|
|
</script>
|