Files
nuxt4-example/pages/index.vue
Tiemen van Olst 72d9f5e642 Added Docker
2025-09-09 08:52:28 +02:00

170 lines
5.3 KiB
Vue

<template>
<div class="min-h-screen bg-gray-50">
<div class="container mx-auto px-4 py-8">
<h1 class="text-4xl font-bold text-center mb-8 text-gray-800">
Nuxt 4 met Database
</h1>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<!-- Users Section -->
<div class="bg-white rounded-lg shadow-md p-6">
<h2 class="text-2xl font-semibold mb-4 text-gray-700">Gebruikers</h2>
<form @submit.prevent="createUser" class="mb-4">
<div class="space-y-3">
<input
v-model="newUser.name"
type="text"
placeholder="Naam"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required
/>
<input
v-model="newUser.email"
type="email"
placeholder="Email"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
required
/>
<button
type="submit"
class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 transition-colors"
>
Gebruiker Toevoegen
</button>
</div>
</form>
<div class="space-y-2">
<div
v-for="user in users"
:key="user.id"
class="p-3 bg-gray-50 rounded-md"
>
<h3 class="font-medium">{{ user.name }}</h3>
<p class="text-sm text-gray-600">{{ user.email }}</p>
<p class="text-xs text-gray-500">{{ user.posts.length }} posts</p>
</div>
</div>
</div>
<!-- Posts Section -->
<div class="bg-white rounded-lg shadow-md p-6">
<h2 class="text-2xl font-semibold mb-4 text-gray-700">Posts</h2>
<form @submit.prevent="createPost" class="mb-4">
<div class="space-y-3">
<input
v-model="newPost.title"
type="text"
placeholder="Titel"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
required
/>
<textarea
v-model="newPost.content"
placeholder="Inhoud"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
rows="3"
></textarea>
<select
v-model="newPost.authorId"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
required
>
<option value="">Selecteer auteur</option>
<option v-for="user in users" :key="user.id" :value="user.id">
{{ user.name }}
</option>
</select>
<button
type="submit"
class="w-full bg-green-500 text-white py-2 px-4 rounded-md hover:bg-green-600 transition-colors"
>
Post Toevoegen
</button>
</div>
</form>
<div class="space-y-3">
<div
v-for="post in posts"
:key="post.id"
class="p-4 bg-gray-50 rounded-md"
>
<h3 class="font-medium text-lg">{{ post.title }}</h3>
<p class="text-gray-600 mt-1">{{ post.content }}</p>
<div class="flex justify-between items-center mt-2 text-sm text-gray-500">
<span>Door: {{ post.author.name }}</span>
<span>{{ formatDate(post.createdAt) }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
// Reactive data
const users = ref([])
const posts = ref([])
const newUser = ref({ name: '', email: '' })
const newPost = ref({ title: '', content: '', authorId: '' })
// Fetch data on mount
onMounted(async () => {
await Promise.all([fetchUsers(), fetchPosts()])
})
// API functions
const fetchUsers = async () => {
try {
const data = await $fetch('/api/users')
users.value = data
} catch (error) {
console.error('Error fetching users:', error)
}
}
const fetchPosts = async () => {
try {
const data = await $fetch('/api/posts')
posts.value = data
} catch (error) {
console.error('Error fetching posts:', error)
}
}
const createUser = async () => {
try {
await $fetch('/api/users', {
method: 'POST',
body: newUser.value
})
newUser.value = { name: '', email: '' }
await fetchUsers()
} catch (error) {
console.error('Error creating user:', error)
}
}
const createPost = async () => {
try {
await $fetch('/api/posts', {
method: 'POST',
body: newPost.value
})
newPost.value = { title: '', content: '', authorId: '' }
await fetchPosts()
} catch (error) {
console.error('Error creating post:', error)
}
}
const formatDate = (dateString) => {
return new Date(dateString).toLocaleDateString('nl-NL')
}
</script>