Files
KanbanGit/resources/js/pages/project-templates/Edit.vue
T
Twyco 1d8fff1d51
CI/CD / test_and_check_app (push) Successful in 3m53s
CI/CD / Publish immutable image (push) Successful in 1m33s
formatted
2026-09-08 14:24:04 +02:00

224 lines
9.1 KiB
Vue

<script setup lang="ts">
import { Head, Link, useForm } from '@inertiajs/vue3';
import { computed } from 'vue';
import Heading from '@/components/Heading.vue';
import InputError from '@/components/InputError.vue';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout.vue';
import {
edit as projectTemplatesEdit,
index as projectTemplatesIndex,
update as projectTemplatesUpdate,
} from '@/routes/project-templates';
import type { BreadcrumbItem, ProjectTemplatesEditPageProps } from '@/types';
const props = defineProps<ProjectTemplatesEditPageProps>();
const breadcrumbs: BreadcrumbItem[] = [
{
title: 'Project templates',
href: projectTemplatesIndex(),
},
{
title: props.template.name,
href: projectTemplatesEdit(props.template.id),
},
];
const form = useForm({
confirm_linked_projects_update: false,
copy_areas: [...props.template.copy_areas],
name: props.template.name,
});
const copyAreasError = computed(() => {
return (
form.errors.copy_areas ??
Object.entries(form.errors).find(([key]) =>
key.startsWith('copy_areas.'),
)?.[1] ??
''
);
});
const linkedProjectCount = computed(
() => props.template.linked_project_count ?? 0,
);
const submit = (): void => {
form.patch(projectTemplatesUpdate.url(props.template.id), {
preserveScroll: true,
});
};
</script>
<template>
<AppLayout :breadcrumbs="breadcrumbs">
<Head :title="`Edit ${template.name}`" />
<div class="mx-auto flex w-full max-w-3xl flex-1 flex-col gap-6 p-4">
<div class="space-y-3">
<div class="flex flex-wrap items-center gap-3">
<Badge variant="outline" class="px-3 py-1">{{
template.slug
}}</Badge>
<Badge v-if="linkedProjectCount > 0" variant="secondary">
{{ linkedProjectCount }} linked
{{ linkedProjectCount === 1 ? 'project' : 'projects' }}
</Badge>
</div>
<Heading
:title="`Edit ${template.name}`"
description="Refresh the template baseline from its source project while keeping immutable identifiers protected."
/>
</div>
<Card>
<CardHeader>
<CardTitle>Template details</CardTitle>
<CardDescription>
<template v-if="template.source_project">
This template baseline is rebuilt from
{{ template.source_project.name }} ({{
template.source_project.key
}}) when you save.
</template>
<template v-else>
This template baseline is rebuilt from its source
project when you save.
</template>
</CardDescription>
</CardHeader>
<CardContent>
<form class="space-y-6" @submit.prevent="submit">
<div class="grid gap-2">
<Label for="name">Template name</Label>
<Input
id="name"
v-model="form.name"
required
placeholder="Foundation template"
/>
<InputError :message="form.errors.name" />
</div>
<div class="grid gap-2">
<Label for="slug">Template slug</Label>
<Input
id="slug"
:model-value="template.slug"
disabled
/>
<p class="text-muted-foreground text-sm">
The slug stays locked so existing template
references remain stable.
</p>
</div>
<div class="grid gap-3">
<div>
<Label>Configuration groups</Label>
<p class="text-muted-foreground text-sm">
Saving rebuilds the selected groups from the
current source-project configuration.
</p>
</div>
<div class="grid gap-3">
<Label
v-for="copyAreaOption in copyAreaOptions"
:key="copyAreaOption.value"
class="flex cursor-pointer items-start gap-3 rounded-xl border p-4"
>
<input
v-model="form.copy_areas"
type="checkbox"
:value="copyAreaOption.value"
class="mt-1"
/>
<div class="space-y-1">
<div class="font-medium">
{{ copyAreaOption.label }}
</div>
<p
class="text-muted-foreground text-sm"
>
{{ copyAreaOption.description }}
</p>
</div>
</Label>
</div>
<InputError :message="copyAreasError" />
</div>
<div
v-if="linkedProjectCount > 0"
class="space-y-3 rounded-xl border border-amber-300 bg-amber-50 p-4 text-amber-950 dark:border-amber-900/70 dark:bg-amber-950/40 dark:text-amber-100"
>
<div class="space-y-1">
<div class="font-medium">Warning</div>
<p class="text-sm">
Saving this template updates the baseline
for {{ linkedProjectCount }} linked
{{
linkedProjectCount === 1
? 'project'
: 'projects'
}}. Inherited areas will follow the new
template version, while existing overrides
stay untouched.
</p>
</div>
<Label
class="flex cursor-pointer items-start gap-3"
>
<input
v-model="
form.confirm_linked_projects_update
"
type="checkbox"
class="mt-1"
/>
<span class="text-sm">
I understand that linked projects inheriting
from this template will be affected.
</span>
</Label>
<InputError
:message="
form.errors.confirm_linked_projects_update
"
/>
</div>
<div class="flex items-center gap-3">
<Button type="submit" :disabled="form.processing">
Save template changes
</Button>
<Button as-child variant="outline">
<Link :href="projectTemplatesIndex()"
>Cancel</Link
>
</Button>
</div>
</form>
</CardContent>
</Card>
</div>
</AppLayout>
</template>