carousel + upload multiplo + form validation
This commit is contained in:
parent
3472b11168
commit
0377942842
6 changed files with 71 additions and 50 deletions
11
TODO.md
11
TODO.md
|
@ -1,10 +1,13 @@
|
||||||
|
|
||||||
- [x] attach db connection / setup on nuxt listen hook
|
- [x] attach db connection / setup on nuxt listen hook
|
||||||
- [ ] carousel in detail (o un modo per avere piu' immagini per un oggetto)
|
- [x] filtrare i file dell'input type file del form per mostrare solo mimetype image/*
|
||||||
- [ ] filtrare i file dell'input type file del form per mostrare solo mimetype image/*
|
- [x] carousel in detail (o un modo per avere piu' immagini per un oggetto)
|
||||||
|
- [x] stringo la pagina dei dettagli
|
||||||
- [x] next / prev in page
|
- [x] next / prev in page
|
||||||
|
- [ ] i tag da trimmare ed eliminare se son vuoti
|
||||||
|
- [ ] un load per next / prev
|
||||||
- [ ] favicon (solo perche' senza ci mette un sacco a fare il load)
|
- [ ] favicon (solo perche' senza ci mette un sacco a fare il load)
|
||||||
- [ ] form validation
|
- [x] form validation
|
||||||
- [ ] api rate (mi sa di no perche' tutti usciremo con lo stesso ip)
|
|
||||||
- [ ] ci vuole un modo per segnare che un oggetto e' stato preso!
|
- [ ] ci vuole un modo per segnare che un oggetto e' stato preso!
|
||||||
|
- [ ] api rate (mi sa di no perche' tutti usciremo con lo stesso ip)
|
||||||
- [ ] mail in lista
|
- [ ] mail in lista
|
||||||
|
|
13
components/carousel.vue
Normal file
13
components/carousel.vue
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<script setup>
|
||||||
|
// piccolo carosello da mettere in alto alle pagine delle cosette
|
||||||
|
|
||||||
|
const { images } = defineProps(['images'])
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class='carousel max-h-100 bg-neutral'>
|
||||||
|
<div v-for='image in images' class='carousel-item' :key='image'>
|
||||||
|
<img class='carousel-center object-contain' :src="`/${image}`">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -8,35 +8,38 @@
|
||||||
<label for='name' class="label label-text pb-0">Che roba è?</label>
|
<label for='name' class="label label-text pb-0">Che roba è?</label>
|
||||||
<input type="text" name='name' id='name' placeholder="Nome" required autocomplete='off'
|
<input type="text" name='name' id='name' placeholder="Nome" required autocomplete='off'
|
||||||
class="input secondary peer input-bordered invalid:border-orange-300 w-full" />
|
class="input secondary peer input-bordered invalid:border-orange-300 w-full" />
|
||||||
<label class="label label-text-alt peer-invalid:text-orange-500 transition pt-0">Metti il nome
|
<label class="label label-text-alt peer-invalid:text-orange-500 transition pt-0" for='name'>Metti il nome
|
||||||
della cosetta, il modello, una sigla</label>
|
della cosetta, il modello, una sigla</label>
|
||||||
|
|
||||||
<!-- DESCRIPTION -->
|
<!-- DESCRIPTION -->
|
||||||
<label for="description" class="label label-text pb-0">Descrizione</label>
|
<label for="description" class="label label-text pb-0">Descrizione</label>
|
||||||
<textarea name='description' id='description'
|
<textarea name='description' id='description'
|
||||||
class='textarea input-bordered w-full peer invalid:border-orange-300' required></textarea>
|
class='textarea input-bordered w-full peer invalid:border-orange-300' required></textarea>
|
||||||
<label class="label label-text-alt peer-invalid:text-orange-500 pt-0">In che stato è? Dove l'hai
|
<label class="label label-text-alt peer-valid:text-grey-300 peer-invalid:text-orange-500 pt-0"
|
||||||
|
for='description'>In che stato è?
|
||||||
|
Dove l'hai
|
||||||
trovato? Insomma dacci una corposa descrizione.</label>
|
trovato? Insomma dacci una corposa descrizione.</label>
|
||||||
|
|
||||||
|
<!-- TAG -->
|
||||||
<label class="label label-text pb-0">Tag</label>
|
<label class="label label-text pb-0">Tag</label>
|
||||||
<input type="text" name='tags' placeholder="Tags" class="input input-bordered w-full" />
|
<input type="text" name='tags' placeholder="Tags" class="input input-bordered w-full" />
|
||||||
<label class="label label-text-alt pt-0">Delle parole chiavi per venirne a capo, separate da virgole (no non si
|
<label class="label label-text-alt pt-0">Delle parole chiavi per venirne a capo, separate da virgole (no non si
|
||||||
autocompleta)</label>
|
autocompleta)</label>
|
||||||
|
|
||||||
|
|
||||||
<label for='images' class="label label-text pb-0">Immagini</label>
|
<label for='images' class="label label-text mt-3 pb-0">Immagini - massimo 10 </label>
|
||||||
<input class='text-sm text-grey-500
|
<input class='text-sm text-grey-500
|
||||||
file:mr-5 file:py-2 file:px-6
|
file:mr-5 file:py-2 file:px-6
|
||||||
file:rounded-full file:border-0
|
file:rounded-md file:border-0
|
||||||
file:text-sm file:font-medium
|
file:text-sm file:font-medium
|
||||||
file:bg-blue-50 file:text-blue-700
|
file:bg-blue-50 file:text-blue-700
|
||||||
hover:file:cursor-pointer hover:file:bg-amber-50
|
hover:file:cursor-pointer hover:file:bg-amber-50
|
||||||
hover:file:text-amber-700' type="file" name='images' accept="image/*" multiple />
|
hover:file:text-orange-700' required type="file" name='images' accept="image/*" multiple />
|
||||||
|
|
||||||
|
|
||||||
<div class="modal-action">
|
<div class="modal-action divider mt-10">
|
||||||
<a href="#" class="btn">Annulla</a>
|
<a href="#" class="btn">Annulla</a>
|
||||||
<button class='btn btn-success' type='submit'>Aggiungi</button>
|
<button class='btn btn-primary' type='submit'>Aggiungi</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,42 +1,42 @@
|
||||||
import { Server } from 'socket.io'
|
import { Server } from 'socket.io'
|
||||||
|
|
||||||
export default (_, nuxt) => {
|
export default (_, nuxt) => {
|
||||||
nuxt.hook('listen', server => {
|
nuxt.hook('listen', server => {
|
||||||
const io = new Server(server)
|
const io = new Server(server)
|
||||||
|
|
||||||
nuxt.hook('close', () => io.close())
|
nuxt.hook('close', () => io.close())
|
||||||
|
|
||||||
io.on('connection', (socket) => {
|
io.on('connection', (socket) => {
|
||||||
console.log('Connection', socket.id)
|
console.log('Connection', socket.id)
|
||||||
|
})
|
||||||
|
|
||||||
|
io.on('connect', (socket) => {
|
||||||
|
socket.emit('message', `welcome ${socket.id}`)
|
||||||
|
socket.broadcast.emit('message', `${socket.id} joined`)
|
||||||
|
|
||||||
|
socket.on('joinRoom', (room) => {
|
||||||
|
socket.join(room)
|
||||||
|
socket.emit('message', `joinRoom ${room}`)
|
||||||
|
socket.broadcast.to(room).emit('message', `${socket.id} joined ${room}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('newComment',
|
||||||
|
function comment(message, room) {
|
||||||
|
console.log('new comment received: %s', message)
|
||||||
|
socket.broadcast.to(room).emit('newComment', { message })
|
||||||
})
|
})
|
||||||
|
|
||||||
io.on('connect', (socket) => {
|
socket.on('message',
|
||||||
socket.emit('message', `welcome ${socket.id}`)
|
function message(data) {
|
||||||
socket.broadcast.emit('message', `${socket.id} joined`)
|
console.log('message received: %s', data)
|
||||||
|
socket.broadcast.emit('message', { data })
|
||||||
|
})
|
||||||
|
|
||||||
socket.on('joinRoom', (room) => {
|
socket.on('disconnecting',
|
||||||
socket.join(room)
|
() => {
|
||||||
socket.emit('message', `joinRoom ${room}`)
|
console.log('disconnected', socket.id)
|
||||||
socket.broadcast.to(room).emit('message', `${socket.id} joined ${room}`)
|
socket.broadcast.emit('message', `${socket.id} left`)
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('newComment',
|
|
||||||
function comment(message, room) {
|
|
||||||
console.log('new comment received: %s', message)
|
|
||||||
socket.broadcast.to(room).emit('newComment', { message })
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('message',
|
|
||||||
function message(data) {
|
|
||||||
console.log('message received: %s', data)
|
|
||||||
socket.broadcast.emit('message', { data })
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on('disconnecting',
|
|
||||||
() => {
|
|
||||||
console.log('disconnected', socket.id)
|
|
||||||
socket.broadcast.emit('message', `${socket.id} left`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,22 +10,24 @@ const addComment = async () => {
|
||||||
comment.message = ''
|
comment.message = ''
|
||||||
const db_comment = await $fetch(`/api/comment/${ret.comment.uuid}`)
|
const db_comment = await $fetch(`/api/comment/${ret.comment.uuid}`)
|
||||||
comments.unshift(db_comment)
|
comments.unshift(db_comment)
|
||||||
$socket.emit("newComment", db_comment, route.params.cosetta )
|
|
||||||
|
// should we put this server-side?
|
||||||
|
$socket.emit("newComment", db_comment, route.params.cosetta)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
$socket.emit("joinRoom", route.params.cosetta)
|
$socket.emit("joinRoom", route.params.cosetta)
|
||||||
$socket.on("newComment", (newComment) => {
|
$socket.on("newComment", newComment => comments.unshift(newComment.message))
|
||||||
comments.unshift(newComment.message)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<section class="bg-white py-8">
|
<section class="bg-white py-8 mx-auto max-w-4xl">
|
||||||
|
|
||||||
|
<!-- CAROUSEL -->
|
||||||
|
<Carousel :images='cosetta.images' />
|
||||||
<div class="container mx-auto pt-4 pb-12">
|
<div class="container mx-auto pt-4 pb-12">
|
||||||
<img v-if='cosetta.images' :src="`/${cosetta.images[0]}`" />
|
<div class='carousel text-'></div>
|
||||||
<h2 class="text-pink-500 text-2xl card-title uppercase mb-2 divider" v-text='cosetta.name' />
|
<h2 class="text-pink-500 text-2xl card-title uppercase mb-2 divider" v-text='cosetta.name' />
|
||||||
<div class="px-6 pt-4 pb-2">
|
<div class="px-6 pt-4 pb-2">
|
||||||
<span v-for='tag in cosetta.tags' :key='tag'
|
<span v-for='tag in cosetta.tags' :key='tag'
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const uploadService = () => {
|
||||||
limits: {
|
limits: {
|
||||||
files: 10,
|
files: 10,
|
||||||
fieldNameSize: 400,
|
fieldNameSize: 400,
|
||||||
fileSize: 80 * 1024 * 1024,
|
fileSize: 800 * 1024 * 1024,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ export const uploadService = () => {
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
return multer(options).array('images', 5);
|
return multer(options).array('images', 10);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Upload error', e)
|
console.error('Upload error', e)
|
||||||
throw e;
|
throw e;
|
||||||
|
|
Loading…
Reference in a new issue