Initial commit of testapi
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
<script setup lang="ts">
|
||||
import AppLayout from '@/layouts/AppLayout.vue';
|
||||
import { type BreadcrumbItem } from '@/types';
|
||||
import { Head, Link, useForm } from '@inertiajs/vue3';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Plus } from 'lucide-vue-next';
|
||||
|
||||
const form = useForm({
|
||||
username: '',
|
||||
name: '',
|
||||
});
|
||||
|
||||
const breadcrumbs: BreadcrumbItem[] = [
|
||||
{ title: 'Dashbord', href: '/dashboard' },
|
||||
{ title: 'Brukere', href: '/smartdok/profiles' },
|
||||
{ title: 'Opprett', href: '/smartdok/profiles/create' },
|
||||
];
|
||||
|
||||
function submit() {
|
||||
form.post(route('smartdok.profiles.store'), {
|
||||
onSuccess: () => {
|
||||
// Optionally reset or navigate; Inertia will handle redirect
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Opprett bruker" />
|
||||
<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 bruker
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<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">
|
||||
<!-- Brukernavn -->
|
||||
<div>
|
||||
<Label for="username">Brukernavn:</Label>
|
||||
<Input
|
||||
id="username"
|
||||
v-model="form.username"
|
||||
type="text"
|
||||
placeholder="Skriv inn brukernavn"
|
||||
class="mt-2"
|
||||
/>
|
||||
<p v-if="form.errors.username" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.username }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Navn -->
|
||||
<div>
|
||||
<Label for="name">Navn:</Label>
|
||||
<Input
|
||||
id="name"
|
||||
v-model="form.name"
|
||||
type="text"
|
||||
placeholder="Skriv inn fullt navn"
|
||||
class="mt-2"
|
||||
/>
|
||||
<p v-if="form.errors.name" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.name }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Actions -->
|
||||
<div class="flex items-center justify-end space-x-4">
|
||||
<Link href="/smartdok/profiles">
|
||||
<Button variant="outline">
|
||||
Avbryt
|
||||
</Button>
|
||||
</Link>
|
||||
<Button type="submit" :disabled="form.processing">
|
||||
Opprett
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,99 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import AppLayout from '@/layouts/AppLayout.vue';
|
||||
import { type BreadcrumbItem } from '@/types';
|
||||
import { Head, Link, usePage, useForm } from '@inertiajs/vue3';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
|
||||
interface Profile {
|
||||
id: string
|
||||
username: string
|
||||
name: string
|
||||
};
|
||||
|
||||
// Grab the Inertia page props
|
||||
const page = usePage<{ profile: Profile }>();
|
||||
|
||||
// Reactive profile object
|
||||
const profile = computed(() => page.props.profile);
|
||||
|
||||
// Setup the form with existing values
|
||||
const form = useForm({
|
||||
username: profile.value.username,
|
||||
name: profile.value.name,
|
||||
});
|
||||
|
||||
const breadcrumbs: BreadcrumbItem[] = [
|
||||
{ title: 'Dashbord', href: '/dashboard' },
|
||||
{ title: 'Brukere', href: '/smartdok/profiles' },
|
||||
{ title: 'Rediger', href: route('smartdok.profiles.edit', profile.value.id) },
|
||||
];
|
||||
|
||||
function submit() {
|
||||
form.put(
|
||||
route('smartdok.profiles.update', profile.value.id),
|
||||
{ onSuccess: () => {/* Inertia redirect back to index */} }
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Rediger bruker" />
|
||||
|
||||
<AppLayout :breadcrumbs="breadcrumbs">
|
||||
<div class="p-6 space-y-8">
|
||||
<!-- Header and actions -->
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="scroll-m-20 text-2xl font-extrabold tracking-tight lg:text-3xl">
|
||||
Rediger bruker
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center items-center">
|
||||
<!-- Edit form -->
|
||||
<form @submit.prevent="submit" class="space-y-6 min-w-2xl lg:min-w-3xl xl:min-w-4xl">
|
||||
<div>
|
||||
<Label for="username">Brukernavn:</Label>
|
||||
<Input
|
||||
id="username"
|
||||
v-model="form.username"
|
||||
type="text"
|
||||
placeholder="Skriv inn brukernavn"
|
||||
class="mt-2"
|
||||
/>
|
||||
<p v-if="form.errors.username" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.username }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label for="name">Navn:</Label>
|
||||
<Input
|
||||
id="name"
|
||||
v-model="form.name"
|
||||
type="text"
|
||||
placeholder="Skriv inn fullt navn"
|
||||
class="mt-2"
|
||||
/>
|
||||
<p v-if="form.errors.name" class="mt-1 text-sm text-red-600">
|
||||
{{ form.errors.name }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- Actions -->
|
||||
<div class="flex items-center justify-end space-x-4">
|
||||
<Link :href="route('smartdok.profiles.index')">
|
||||
<Button variant="outline">
|
||||
Avbryt
|
||||
</Button>
|
||||
</Link>
|
||||
<Button type="submit" :disabled="form.processing">
|
||||
Oppdater
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,110 @@
|
||||
<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 UserProfileDropdown from './UserProfileDropdown.vue';
|
||||
|
||||
interface Profile {
|
||||
id: string
|
||||
username: string
|
||||
name: string
|
||||
};
|
||||
|
||||
const page = usePage<{
|
||||
profiles: {
|
||||
data: Profile[]
|
||||
current_page: number
|
||||
last_page: number
|
||||
per_page: number
|
||||
total: number
|
||||
}
|
||||
}>();
|
||||
|
||||
// Reactive list of profiles
|
||||
const profiles = computed(() => page.props.profiles.data);
|
||||
|
||||
const breadcrumbs: BreadcrumbItem[] = [
|
||||
{ title: 'Dashbord', href: '/dashboard' },
|
||||
{ title: 'Brukere', href: '/smartdok/profiles' },
|
||||
];
|
||||
|
||||
// pagination meta
|
||||
const currentPage = computed(() => page.props.profiles.current_page);
|
||||
const lastPage = computed(() => page.props.profiles.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="Brukere" />
|
||||
<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">
|
||||
Brukere
|
||||
</h3>
|
||||
<Link :href="route('smartdok.profiles.create')">
|
||||
<Button variant="outline">
|
||||
<Plus class="mr-2 h-4 w-4" />
|
||||
Opprett
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<div class="px-6 overflow-auto">
|
||||
<Table>
|
||||
<TableCaption>En liste over brukere.</TableCaption>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Brukernavn</TableHead>
|
||||
<TableHead>Navn</TableHead>
|
||||
<TableHead class="text-right">Handlinger</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow v-for="profile in profiles" :key="profile.id">
|
||||
<TableCell class="font-medium">{{ profile.username }}</TableCell>
|
||||
<TableCell>{{ profile.name }}</TableCell>
|
||||
<TableCell class="text-right">
|
||||
<UserProfileDropdown :profile="profile" />
|
||||
</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.profiles.total }} brukere
|
||||
</div>
|
||||
<div class="space-x-2">
|
||||
<Link :href="route('smartdok.profiles.index', { page: prevPage })">
|
||||
<Button variant="outline" :disabled="currentPage === 1">
|
||||
Forrige
|
||||
</Button>
|
||||
</Link>
|
||||
<Link :href="route('smartdok.profiles.index', { page: nextPage })">
|
||||
<Button variant="outline" :disabled="currentPage === lastPage">
|
||||
Neste
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,72 @@
|
||||
<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
|
||||
};
|
||||
|
||||
// Grab the Inertia page props
|
||||
const page = usePage<{ profile: Profile }>();
|
||||
|
||||
// Reactive profile object
|
||||
const profile = computed(() => page.props.profile);
|
||||
|
||||
// Breadcrumbs: Dashbord > Brukere > [username]
|
||||
const breadcrumbs: BreadcrumbItem[] = [
|
||||
{ title: 'Dashbord', href: '/dashboard' },
|
||||
{ title: 'Brukere', href: '/smartdok/profiles' },
|
||||
{ title: profile.value.username, href: route('smartdok.profiles.show', profile.value.id) },
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Vis bruker" />
|
||||
|
||||
<AppLayout :breadcrumbs="breadcrumbs">
|
||||
<div class="p-6 space-y-8">
|
||||
<!-- Heading and action buttons -->
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="scroll-m-20 text-2xl font-extrabold tracking-tight lg:text-3xl">
|
||||
Vis bruker
|
||||
</h3>
|
||||
<div class="flex space-x-2">
|
||||
<Link :href="route('smartdok.profiles.index')">
|
||||
<Button variant="outline">Tilbake</Button>
|
||||
</Link>
|
||||
<Link :href="route('smartdok.profiles.edit', profile.id)">
|
||||
<Button>Rediger</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Profile details -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<Label for="username">ID</Label>
|
||||
<p id="username" class="mt-1 text-base">
|
||||
{{ profile.id }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<Label for="username">Brukernavn</Label>
|
||||
<p id="username" class="mt-1 text-base">
|
||||
{{ profile.username }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<Label for="name">Navn</Label>
|
||||
<p id="name" class="mt-1 text-base">
|
||||
{{ profile.name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,92 @@
|
||||
<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<{
|
||||
profile: {
|
||||
id: string
|
||||
}
|
||||
}>();
|
||||
|
||||
function copy(id: string) {
|
||||
navigator.clipboard.writeText(id);
|
||||
}
|
||||
</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(profile.id)">
|
||||
Kopier ID
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem as-child>
|
||||
<Link :href="route('smartdok.profiles.show', profile.id)">Vis profil</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem as-child>
|
||||
<Link :href="route('smartdok.profiles.edit', profile.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 denne brukeren?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
Denne handlingen kan ikke angres.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Avbryt</AlertDialogCancel>
|
||||
<AlertDialogAction as-child>
|
||||
<Link
|
||||
method="delete"
|
||||
:href="route('smartdok.profiles.destroy', profile.id)"
|
||||
class="text-red-600"
|
||||
as="button"
|
||||
>
|
||||
Slett
|
||||
</Link>
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</template>
|
||||
Reference in New Issue
Block a user