92 lines
4.0 KiB
Vue
92 lines
4.0 KiB
Vue
<script setup lang="ts">
|
|
import { Form } from '@inertiajs/vue3';
|
|
import { updateStatusTransitions } from '@/actions/App/Http/Controllers/ProjectBoardSettingsController';
|
|
import InputError from '@/components/InputError.vue';
|
|
import { Button } from '@/components/ui/button';
|
|
import { useLocalization } from '@/composables/useLocalization';
|
|
import { ticketStatusLabel } from '@/lib/tickets';
|
|
import type { TicketStatusModel } from '@/types/models/ticket-status-model';
|
|
|
|
defineProps<{ projectId: number; statuses: TicketStatusModel[] }>();
|
|
const { t } = useLocalization();
|
|
</script>
|
|
|
|
<template>
|
|
<details class="bg-card min-w-0 rounded-xl border">
|
|
<summary
|
|
class="focus-visible:ring-ring/40 cursor-pointer rounded-xl p-5 font-semibold outline-none focus-visible:ring-2 sm:p-6"
|
|
>
|
|
{{ t('workflow.transitions') }}
|
|
</summary>
|
|
<div class="grid min-w-0 gap-4 border-t p-5 sm:p-6">
|
|
<p class="text-muted-foreground text-sm">
|
|
{{ t('workflow.transitionsDescription') }}
|
|
</p>
|
|
<Form
|
|
v-for="source in statuses"
|
|
:key="source.id"
|
|
v-bind="updateStatusTransitions.form([projectId, source.id])"
|
|
preserve-scroll
|
|
set-defaults-on-success
|
|
class="grid min-w-0 gap-3 rounded-lg border p-4"
|
|
v-slot="{ errors, processing, recentlySuccessful }"
|
|
>
|
|
<fieldset :disabled="processing" class="grid min-w-0 gap-3">
|
|
<legend class="mb-3 break-words font-medium">
|
|
{{ ticketStatusLabel(source, '') }}
|
|
</legend>
|
|
<p
|
|
v-if="statuses.length <= 1"
|
|
class="text-muted-foreground text-sm"
|
|
>
|
|
{{ t('workflow.noTargets') }}
|
|
</p>
|
|
<div v-else class="grid min-w-0 gap-2 sm:grid-cols-2">
|
|
<label
|
|
v-for="target in statuses.filter(
|
|
(item) => item.id !== source.id,
|
|
)"
|
|
:key="target.id"
|
|
class="border-input flex min-h-11 min-w-0 items-center gap-3 rounded-lg border px-3 py-2 text-sm"
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
name="allowed_ticket_status_ids[]"
|
|
:value="target.id"
|
|
:checked="
|
|
source.allowed_target_statuses?.some(
|
|
(item) => item.id === target.id,
|
|
) ?? false
|
|
"
|
|
class="border-input accent-primary focus-visible:ring-ring/40 size-4 shrink-0 rounded focus-visible:ring-2"
|
|
/>
|
|
<span class="min-w-0 break-words">{{
|
|
ticketStatusLabel(target, '')
|
|
}}</span>
|
|
</label>
|
|
</div>
|
|
</fieldset>
|
|
<InputError
|
|
v-for="(message, key) in errors"
|
|
:key="key"
|
|
:message="message"
|
|
/>
|
|
<div class="flex flex-wrap items-center gap-3">
|
|
<Button
|
|
type="submit"
|
|
variant="outline"
|
|
:loading="processing"
|
|
>{{ t('common.save') }}</Button
|
|
>
|
|
<span
|
|
v-if="recentlySuccessful"
|
|
role="status"
|
|
class="text-primary text-sm"
|
|
>{{ t('feedback.saved') }}</span
|
|
>
|
|
</div>
|
|
</Form>
|
|
</div>
|
|
</details>
|
|
</template>
|