0% found this document useful (0 votes)
10 views4 pages

Nuxt4 NuxtUI FullProject

This document outlines a full project using Nuxt 4 and Nuxt UI to create a product and category catalog, detailing both frontend and backend components. It includes configuration settings, frontend page structures, and backend API routes for managing products and categories. The project demonstrates the use of reactive components, API interaction, and data storage in a simple web application.

Uploaded by

Teodor Petrovic
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views4 pages

Nuxt4 NuxtUI FullProject

This document outlines a full project using Nuxt 4 and Nuxt UI to create a product and category catalog, detailing both frontend and backend components. It includes configuration settings, frontend page structures, and backend API routes for managing products and categories. The project demonstrates the use of reactive components, API interaction, and data storage in a simple web application.

Uploaded by

Teodor Petrovic
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Nuxt 4 + Nuxt UI Frontend + Backend API (Full Project)

This Word document includes both frontend pages and backend API server routes for a
simple product & category catalog built with Nuxt 4 and Nuxt UI.

Frontend: nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/ui'],
nitro: {
storage: {
db: {
driver: 'fs',
base: './data',
},
},
},
})

Frontend: app.vue
<script setup lang="ts"></script>

<template>
<UApp>
<div class="min-h-screen flex flex-col">
<UHeader>
<template #left>
<NuxtLink to="/" class="font-semibold">Catalog
Demo</NuxtLink>
</template>
<template #right>
<div class="flex items-center gap-3">
<NuxtLink to="/products"
class="hover:underline">Products</NuxtLink>
<NuxtLink to="/categories"
class="hover:underline">Categories</NuxtLink>
</div>
</template>
</UHeader>
<UContainer class="py-6 flex-1">
<NuxtPage />
</UContainer>
<footer class="py-8 text-center text-sm opacity-70">Nuxt 4 + Nuxt
UI demo</footer>
</div>
</UApp>
</template>
Frontend: pages/products/index.vue
<script setup lang="ts">
import { useCatalogApi } from '@/composables/useCatalogApi'
import ProductCard from '@/components/ProductCard.vue'

const { fetchProducts } = useCatalogApi()


const products = ref([])

onMounted(async () => {
products.value = await fetchProducts()
})
</script>

<template>
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-bold">Products</h1>
<UButton to="/products/create">New product</UButton>
</div>

<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">


<ProductCard v-for="p in products" :key="p.id" :product="p" />
</div>
</template>

Frontend: components/ProductForm.vue
<script setup lang="ts">
import type { Category, Product } from '@/types'
import { useCatalogApi } from '@/composables/useCatalogApi'

const emit = defineEmits<{ (e: 'submit', value: Omit<Product, 'id'>):


void }>()
const { fetchCategories } = useCatalogApi()
const categories = ref([])

onMounted(async () => {
categories.value = await fetchCategories()
})

const state = reactive<Omit<Product, 'id'>>({


name: '',
price: 0,
categoryId: undefined,
description: '',
})
</script>

<template>
<UForm @submit.prevent="() => emit('submit', state)">
<UFormField label="Name"><UInput v-model="state.name"
/></UFormField>
<UFormField label="Price"><UInput v-model.number="state.price"
type="number" step="0.01" /></UFormField>
<UFormField label="Category">
<USelect v-model="state.categoryId" :options="categories.map(c =>
({ label: c.name, value: c.id }))" />
</UFormField>
<UFormField label="Description"><UTextarea v-
model="state.description" /></UFormField>
<UButton type="submit">Create</UButton>
</UForm>
</template>

Backend: server/api/categories/index.ts
import { v4 as uuid } from 'uuid'
import type { Category } from '~/types'

export default defineEventHandler(async (event) => {


const storage = useStorage('db:categories.json')
const method = getMethod(event)

if (method === 'GET') {


return (await storage.getItem<Category[]>('categories')) || []
}

if (method === 'POST') {


const body = await readBody<Omit<Category, 'id'>>(event)
const categories = (await
storage.getItem<Category[]>('categories')) || []
const newCategory = { id: uuid(), ...body }
categories.push(newCategory)
await storage.setItem('categories', categories)
return newCategory
}
})

Backend: server/api/products/index.ts
import { v4 as uuid } from 'uuid'
import type { Product } from '~/types'

export default defineEventHandler(async (event) => {


const storage = useStorage('db:products.json')
const method = getMethod(event)

if (method === 'GET') {


return (await storage.getItem<Product[]>('products')) || []
}
if (method === 'POST') {
const body = await readBody<Omit<Product, 'id'>>(event)
const products = (await storage.getItem<Product[]>('products')) ||
[]
const newProduct = { id: uuid(), ...body }
products.push(newProduct)
await storage.setItem('products', products)
return newProduct
}
})

You might also like