Initial commit of testapi
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import AppLayout from '@/layouts/AppLayout.vue';
|
||||
import { type BreadcrumbItem } from '@/types';
|
||||
import { Head, Link, useForm, usePage } from '@inertiajs/vue3';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { Plus } from 'lucide-vue-next';
|
||||
|
||||
interface Profile { id: string; name: string };
|
||||
interface Department { id: number; name: string };
|
||||
|
||||
const page = usePage<{
|
||||
profiles: Profile[]
|
||||
departments: Department[]
|
||||
}>();
|
||||
|
||||
const profiles = computed(() => page.props.profiles);
|
||||
const departments = computed(() => page.props.departments);
|
||||
|
||||
const form = useForm({
|
||||
project_name: '',
|
||||
project_number: '',
|
||||
user_ids: [] as string[],
|
||||
department_ids:[] as number[],
|
||||
});
|
||||
|
||||
// toggle a profile id in the user_ids array
|
||||
function toggleUser(id: string, checked: boolean) {
|
||||
if (checked) {
|
||||
form.user_ids.push(id);
|
||||
} else {
|
||||
form.user_ids = form.user_ids.filter(x => x !== id);
|
||||
}
|
||||
}
|
||||
|
||||
// toggle a department id in the department_ids array
|
||||
function toggleDept(id: number, checked: boolean) {
|
||||
if (checked) {
|
||||
form.department_ids.push(id);
|
||||
} else {
|
||||
form.department_ids = form.department_ids.filter(x => x !== id);
|
||||
}
|
||||
}
|
||||
|
||||
const breadcrumbs: BreadcrumbItem[] = [
|
||||
{ title: 'Dashbord', href: '/dashboard' },
|
||||
{ title: 'Prosjekter', href: '/smartdok/projects' },
|
||||
{ title: 'Opprett', href: '/smartdok/projects/create' },
|
||||
];
|
||||
|
||||
function submit() {
|
||||
form.post(route('smartdok.projects.store'));
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Opprett prosjekt" />
|
||||
<AppLayout :breadcrumbs="breadcrumbs">
|
||||
<div class="mb-6 flex items-center justify-between p-6">
|
||||
<h3 class="scroll-m-20 text-2xl font-extrabold tracking-tight lg:text-3xl">
|
||||
Opprett prosjekt
|
||||
</h3>
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<form
|
||||
@submit.prevent="submit"
|
||||
class="space-y-6 min-w-2xl lg:min-w-3xl xl:min-w-4xl"
|
||||
>
|
||||
<!-- Prosjektnavn -->
|
||||
<div>
|
||||
<Label for="project_name">Prosjektnavn</Label>
|
||||
<Input
|
||||
id="project_name"
|
||||
v-model="form.project_name"
|
||||
placeholder="Skriv inn prosjektnavn"
|
||||
class="mt-2"
|
||||
/>
|
||||
<p v-if="form.errors.project_name" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.project_name }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Prosjektnummer -->
|
||||
<div>
|
||||
<Label for="project_number">Prosjektnummer</Label>
|
||||
<Input
|
||||
id="project_number"
|
||||
v-model="form.project_number"
|
||||
placeholder="Skriv inn prosjektnummer"
|
||||
class="mt-2"
|
||||
/>
|
||||
<p v-if="form.errors.project_number" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.project_number }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Tilknyttede brukere -->
|
||||
<div>
|
||||
<Label>Tilknyttede brukere</Label>
|
||||
<div class="mt-2 space-y-1">
|
||||
<div
|
||||
v-for="profile in profiles"
|
||||
:key="profile.id"
|
||||
class="flex items-center space-x-2"
|
||||
>
|
||||
<Checkbox
|
||||
:model-value="form.user_ids.includes(profile.id)"
|
||||
@update:modelValue="checked => toggleUser(profile.id, checked)"
|
||||
/>
|
||||
<span>{{ profile.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="form.errors.user_ids" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.user_ids }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Tilknyttede avdelinger -->
|
||||
<div>
|
||||
<Label>Tilknyttede avdelinger</Label>
|
||||
<div class="mt-2 space-y-1">
|
||||
<div
|
||||
v-for="dept in departments"
|
||||
:key="dept.id"
|
||||
class="flex items-center space-x-2"
|
||||
>
|
||||
<Checkbox
|
||||
:model-value="form.department_ids.includes(dept.id)"
|
||||
@update:modelValue="checked => toggleDept(dept.id, checked)"
|
||||
/>
|
||||
<span>{{ dept.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="form.errors.department_ids" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.department_ids }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Actions -->
|
||||
<div class="flex items-center justify-end space-x-4">
|
||||
<Link :href="route('smartdok.projects.index')">
|
||||
<Button variant="outline">Avbryt</Button>
|
||||
</Link>
|
||||
<Button type="submit" :disabled="form.processing">Opprett</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,159 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import AppLayout from '@/layouts/AppLayout.vue';
|
||||
import { Head, Link, usePage, useForm } from '@inertiajs/vue3';
|
||||
import type { BreadcrumbItem } from '@/types';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
|
||||
interface Profile { id: string; name: string };
|
||||
interface Department { id: number; name: string };
|
||||
interface Project {
|
||||
id: number
|
||||
project_name: string
|
||||
project_number: string
|
||||
user_ids: string[]
|
||||
department_ids: number[]
|
||||
};
|
||||
|
||||
const page = usePage<{
|
||||
project: Project
|
||||
profiles: Profile[]
|
||||
departments: Department[]
|
||||
}>();
|
||||
|
||||
const project = computed(() => page.props.project);
|
||||
const profilesList = computed(() => page.props.profiles);
|
||||
const deptsList = computed(() => page.props.departments);
|
||||
|
||||
const form = useForm({
|
||||
project_name: project.value.project_name,
|
||||
project_number: project.value.project_number,
|
||||
user_ids: project.value.user_ids,
|
||||
department_ids: project.value.department_ids,
|
||||
});
|
||||
|
||||
function toggleUser(id: string, checked: boolean) {
|
||||
form.user_ids = checked
|
||||
? [...form.user_ids, id]
|
||||
: form.user_ids.filter(x => x !== id);
|
||||
}
|
||||
|
||||
function toggleDept(id: number, checked: boolean) {
|
||||
form.department_ids = checked
|
||||
? [...form.department_ids, id]
|
||||
: form.department_ids.filter(x => x !== id);
|
||||
}
|
||||
|
||||
const breadcrumbs = computed<BreadcrumbItem[]>(() => [
|
||||
{ title: 'Dashbord', href: '/dashboard' },
|
||||
{ title: 'Prosjekter', href: '/smartdok/projects' },
|
||||
{
|
||||
title: 'Rediger',
|
||||
href: route('smartdok.projects.edit', project.value.id),
|
||||
},
|
||||
]);
|
||||
|
||||
function submit() {
|
||||
form.put(route('smartdok.projects.update', project.value.id));
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Rediger prosjekt" />
|
||||
<AppLayout :breadcrumbs="breadcrumbs">
|
||||
<div class="p-6 space-y-8">
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="scroll-m-20 text-2xl font-extrabold tracking-tight lg:text-3xl">
|
||||
Rediger prosjekt
|
||||
</h3>
|
||||
</div>
|
||||
<!-- Centered form -->
|
||||
<div class="flex justify-center items-center">
|
||||
<form
|
||||
@submit.prevent="submit"
|
||||
class="space-y-6 min-w-2xl lg:min-w-3xl xl:min-w-4xl"
|
||||
>
|
||||
<!-- Prosjektnavn -->
|
||||
<div>
|
||||
<Label for="project_name">Prosjektnavn</Label>
|
||||
<Input
|
||||
id="project_name"
|
||||
v-model="form.project_name"
|
||||
placeholder="Skriv inn prosjektnavn"
|
||||
class="mt-2"
|
||||
/>
|
||||
<p v-if="form.errors.project_name" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.project_name }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Prosjektnummer -->
|
||||
<div>
|
||||
<Label for="project_number">Prosjektnummer</Label>
|
||||
<Input
|
||||
id="project_number"
|
||||
v-model="form.project_number"
|
||||
placeholder="Skriv inn prosjektnummer"
|
||||
class="mt-2"
|
||||
/>
|
||||
<p v-if="form.errors.project_number" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.project_number }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Tilknyttede brukere -->
|
||||
<div>
|
||||
<Label>Tilknyttede brukere</Label>
|
||||
<div class="mt-2 space-y-1">
|
||||
<div
|
||||
v-for="p in profilesList"
|
||||
:key="p.id"
|
||||
class="flex items-center space-x-2"
|
||||
>
|
||||
<Checkbox
|
||||
:model-value="form.user_ids.includes(p.id)"
|
||||
@update:modelValue="checked => toggleUser(p.id, checked)"
|
||||
/>
|
||||
<span>{{ p.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="form.errors.user_ids" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.user_ids }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Tilknyttede avdelinger -->
|
||||
<div>
|
||||
<Label>Tilknyttede avdelinger</Label>
|
||||
<div class="mt-2 space-y-1">
|
||||
<div
|
||||
v-for="d in deptsList"
|
||||
:key="d.id"
|
||||
class="flex items-center space-x-2"
|
||||
>
|
||||
<Checkbox
|
||||
:model-value="form.department_ids.includes(d.id)"
|
||||
@update:modelValue="checked => toggleDept(d.id, checked)"
|
||||
/>
|
||||
<span>{{ d.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="form.errors.department_ids" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.department_ids }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Actions -->
|
||||
<div class="flex items-center justify-end space-x-4">
|
||||
<Link :href="route('smartdok.projects.index')">
|
||||
<Button variant="outline">Avbryt</Button>
|
||||
</Link>
|
||||
<Button type="submit" :disabled="form.processing">
|
||||
Oppdater
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,126 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import AppLayout from '@/layouts/AppLayout.vue';
|
||||
import { type BreadcrumbItem } from '@/types';
|
||||
import { Head, Link, usePage } from '@inertiajs/vue3';
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCaption,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Plus } from 'lucide-vue-next';
|
||||
|
||||
import ProjectDropdown from './ProjectDropdown.vue';
|
||||
|
||||
interface Project {
|
||||
id: number
|
||||
project_name: string
|
||||
project_number: string
|
||||
};
|
||||
|
||||
const page = usePage<{
|
||||
projects: {
|
||||
data: Project[]
|
||||
current_page: number
|
||||
last_page: number
|
||||
per_page: number
|
||||
total: number
|
||||
}
|
||||
}>();
|
||||
|
||||
// Reactive list of projects
|
||||
const projects = computed(() => page.props.projects.data);
|
||||
|
||||
// Breadcrumbs
|
||||
const breadcrumbs: BreadcrumbItem[] = [
|
||||
{ title: 'Dashbord', href: '/dashboard' },
|
||||
{ title: 'Prosjekter', href: '/smartdok/projects' },
|
||||
];
|
||||
|
||||
// Pagination meta
|
||||
const currentPage = computed(() => page.props.projects.current_page);
|
||||
const lastPage = computed(() => page.props.projects.last_page);
|
||||
|
||||
const prevPage = computed(() =>
|
||||
currentPage.value > 1 ? currentPage.value - 1 : 1
|
||||
);
|
||||
const nextPage = computed(() =>
|
||||
currentPage.value < lastPage.value ? currentPage.value + 1 : lastPage.value
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Prosjekter" />
|
||||
<AppLayout :breadcrumbs="breadcrumbs">
|
||||
<!-- Header + Create-button -->
|
||||
<div class="mb-6 flex items-center justify-between p-6">
|
||||
<h3 class="scroll-m-20 text-2xl font-extrabold tracking-tight lg:text-3xl">
|
||||
Prosjekter
|
||||
</h3>
|
||||
<Link :href="route('smartdok.projects.create')">
|
||||
<Button variant="outline">
|
||||
<Plus class="mr-2 h-4 w-4" />
|
||||
Opprett
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<!-- Table -->
|
||||
<div class="px-6 overflow-auto">
|
||||
<Table>
|
||||
<TableCaption>En liste over prosjekter.</TableCaption>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Prosjektnavn</TableHead>
|
||||
<TableHead>Prosjektnummer</TableHead>
|
||||
<TableHead class="text-right">Handlinger</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow
|
||||
v-for="project in projects"
|
||||
:key="project.id"
|
||||
>
|
||||
<TableCell class="font-medium">
|
||||
{{ project.project_name }}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{{ project.project_number }}
|
||||
</TableCell>
|
||||
<TableCell class="text-right">
|
||||
<ProjectDropdown :project="project" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<!-- Pagination controls -->
|
||||
<div class="flex items-center justify-between p-6">
|
||||
<div class="text-sm text-gray-600">
|
||||
Side {{ currentPage }} av {{ lastPage }} ·
|
||||
Totalt {{ page.props.projects.total }} prosjekter
|
||||
</div>
|
||||
<div class="space-x-2">
|
||||
<Link
|
||||
:href="route('smartdok.projects.index', { page: prevPage })"
|
||||
>
|
||||
<Button variant="outline" :disabled="currentPage === 1">
|
||||
Forrige
|
||||
</Button>
|
||||
</Link>
|
||||
<Link
|
||||
:href="route('smartdok.projects.index', { page: nextPage })"
|
||||
>
|
||||
<Button variant="outline" :disabled="currentPage === lastPage">
|
||||
Neste
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,96 @@
|
||||
<script setup lang="ts">
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { MoreHorizontal } from 'lucide-vue-next';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogTrigger,
|
||||
AlertDialogContent,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogCancel,
|
||||
AlertDialogAction,
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import { Link } from '@inertiajs/vue3';
|
||||
|
||||
defineProps<{
|
||||
project: {
|
||||
id: number
|
||||
}
|
||||
}>();
|
||||
|
||||
function copy(id: number) {
|
||||
navigator.clipboard.writeText(id.toString());
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="ghost" class="w-8 h-8 p-0">
|
||||
<span class="sr-only">Åpne meny</span>
|
||||
<MoreHorizontal class="w-4 h-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Handlinger</DropdownMenuLabel>
|
||||
<DropdownMenuItem @click="copy(project.id)">
|
||||
Kopier ID
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem as-child>
|
||||
<Link :href="route('smartdok.projects.show', project.id)">
|
||||
Vis prosjekt
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem as-child>
|
||||
<Link :href="route('smartdok.projects.edit', project.id)">
|
||||
Rediger
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<DropdownMenuItem
|
||||
className="text-red-600 rounded-sm hover:!bg-zinc-800 cursor-pointer flex items-center py-1 px-2"
|
||||
:onSelect="(e) => e.preventDefault()"
|
||||
>Slett</DropdownMenuItem>
|
||||
</AlertDialogTrigger>
|
||||
|
||||
<!-- Confirmation dialog -->
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Er du sikker på at du vil slette dette prosjektet?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
Denne handlingen kan ikke angres.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Avbryt</AlertDialogCancel>
|
||||
<AlertDialogAction as-child>
|
||||
<Link
|
||||
method="delete"
|
||||
:href="route('smartdok.projects.destroy', project.id)"
|
||||
class="text-red-600"
|
||||
as="button"
|
||||
>
|
||||
Slett
|
||||
</Link>
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</template>
|
||||
@@ -0,0 +1,103 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import AppLayout from '@/layouts/AppLayout.vue';
|
||||
import { type BreadcrumbItem } from '@/types';
|
||||
import { Head, Link, usePage } from '@inertiajs/vue3';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Label } from '@/components/ui/label';
|
||||
|
||||
interface Profile {
|
||||
id: string
|
||||
username: string
|
||||
name: string
|
||||
};
|
||||
|
||||
interface Department {
|
||||
id: number
|
||||
name: string
|
||||
};
|
||||
|
||||
interface Project {
|
||||
id: number
|
||||
project_name: string
|
||||
project_number: string
|
||||
profiles: Profile[]
|
||||
departments: Department[]
|
||||
};
|
||||
|
||||
const page = usePage<{ project: Project }>();
|
||||
|
||||
const project = computed(() => page.props.project);
|
||||
|
||||
const breadcrumbs = computed<BreadcrumbItem[]>(() => [
|
||||
{ title: 'Dashbord', href: '/dashboard' },
|
||||
{ title: 'Prosjekter', href: '/smartdok/projects' },
|
||||
{
|
||||
title: project.value.project_name,
|
||||
href: route('smartdok.projects.show', project.value.id),
|
||||
},
|
||||
]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Vis prosjekt" />
|
||||
<AppLayout :breadcrumbs="breadcrumbs">
|
||||
<div class="p-6 space-y-8">
|
||||
<!-- Heading + actions -->
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="scroll-m-20 text-2xl font-extrabold tracking-tight lg:text-3xl">
|
||||
Vis prosjekt
|
||||
</h3>
|
||||
<div class="flex space-x-2">
|
||||
<Link :href="route('smartdok.projects.index')">
|
||||
<Button variant="outline">Tilbake</Button>
|
||||
</Link>
|
||||
<Link :href="route('smartdok.projects.edit', project.id)">
|
||||
<Button>Rediger</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Project details -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<Label for="id" className="font-semibold">ID</Label>
|
||||
<p id="id" class="mt-1 text-base">
|
||||
{{ project.id }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<Label for="project_name" className="font-semibold">Prosjektnavn</Label>
|
||||
<p id="project_name" class="mt-1 text-base">
|
||||
{{ project.project_name }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<Label for="project_number" className="font-semibold">Prosjektnummer</Label>
|
||||
<p id="project_number" class="mt-1 text-base">
|
||||
{{ project.project_number }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tilknyttede brukere -->
|
||||
<div>
|
||||
<Label className="font-semibold">Brukere</Label>
|
||||
<ul class="list-disc list-inside mt-2">
|
||||
<li v-for="p in project.profiles" :key="p.id">
|
||||
{{ p.name }} ({{ p.username }})
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Tilknyttede avdelinger -->
|
||||
<div>
|
||||
<Label className="font-semibold">Avdelinger</Label>
|
||||
<ul class="list-disc list-inside mt-2">
|
||||
<li v-for="d in project.departments" :key="d.id">
|
||||
{{ d.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
Reference in New Issue
Block a user