ci siamo quasi dai

This commit is contained in:
lesion 2022-08-12 18:23:03 +02:00
parent db1b50700f
commit 504f15edac
14 changed files with 121 additions and 65 deletions

View file

@ -10,11 +10,6 @@ Make sure to install the dependencies:
# yarn # yarn
yarn install yarn install
# npm
npm install
# pnpm
pnpm install --shamefully-hoist
``` ```
## Development Server ## Development Server
@ -22,7 +17,7 @@ pnpm install --shamefully-hoist
Start the development server on http://localhost:3000 Start the development server on http://localhost:3000
```bash ```bash
npm run dev yarn dev
``` ```
## Production ## Production
@ -30,13 +25,13 @@ npm run dev
Build the application for production: Build the application for production:
```bash ```bash
npm run build yarn build
``` ```
Locally preview production build: Locally preview production build:
```bash ```bash
npm run preview yarn preview
``` ```
Checkout the [deployment documentation](https://v3.nuxtjs.org/guide/deploy/presets) for more information. Checkout the [deployment documentation](https://v3.nuxtjs.org/guide/deploy/presets) for more information.

View file

@ -2,7 +2,7 @@
<div> <div>
<NuxtLayout> <NuxtLayout>
<Header/> <Header/>
<Hero v-show="$route.name === 'index'"/> <Hero v-if="$route.name === 'index'"/>
<NuxtPage/> <NuxtPage/>
<Footer/> <Footer/>
</NuxtLayout> </NuxtLayout>

5
components.d.ts vendored
View file

@ -8,11 +8,6 @@ export {}
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
export interface GlobalComponents { export interface GlobalComponents {
'IconIc:baselineAdd': typeof import('~icons/ic/baseline-add')['default'] 'IconIc:baselineAdd': typeof import('~icons/ic/baseline-add')['default']
'IconMaterialSymbols:add': typeof import('~icons/material-symbols/add')['default']
'IconSimpleIcons:add': typeof import('~icons/simple-icons/add')['default']
'IconSimpleIcons:addthis': typeof import('~icons/simple-icons/addthis')['default']
'IconSimpleIcons:nuxtdotjs': typeof import('~icons/simple-icons/nuxtdotjs')['default']
'IconSimpleIcons:plus': typeof import('~icons/simple-icons/plus')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
} }

View file

@ -7,13 +7,13 @@ const { cosetta } = defineProps({
}) })
</script> </script>
<template> <template>
<div class="w-full md:w-1/3 xl:w-1/4 p-6 flex flex-col"> <div class="w-full md:w-1/3 xl:w-1/4 p-6 flex flex-col">
<nuxt-link :to="`/c/${cosetta.name}`"> <nuxt-link :to="`/c/${cosetta.uuid}`">
<img class="hover:grow hover:shadow-lg" src="https://images.unsplash.com/photo-1555982105-d25af4182e4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&h=400&q=80"> <img class="hover:grow hover:shadow-lg" :src="`src/public/${cosetta.images[0]}`">
<div class="pt-3 flex items-center justify-between"> <div class="pt-3 flex items-center justify-between">
<p class=" text-black font-bold uppercase" v-text='cosetta.name'></p> <p class=" text-black font-bold uppercase" v-text='cosetta.name'></p>
</div> </div>
<p class="pt-1 text-gray-700 text-sm" v-text='cosetta.description'></p> <p class="pt-1 text-gray-700 text-sm" v-text='cosetta.description'></p>
</nuxt-link> </nuxt-link>
</div> </div>
</template> </template>

View file

@ -13,7 +13,7 @@
<div class="hidden md:flex md:items-center md:w-auto w-full order-3 md:order-1" id="menu"> <div class="hidden md:flex md:items-center md:w-auto w-full order-3 md:order-1" id="menu">
<nav> <nav>
<ul class="md:flex items-center justify-between text-base text-gray-700 pt-4 md:pt-0"> <ul class="md:flex items-center justify-between text-base text-gray-700 pt-4 md:pt-0">
<li><a class="inline-block no-underline hover:text-black hover:underline py-2 px-4" href="#about">Ho una cosetta di cui liberarmi</a></li> <li><a class="inline-block no-underline hover:text-black hover:underline py-2 px-4" href="/">Ho una cosetta di cui liberarmi</a></li>
</ul> </ul>
</nav> </nav>
</div> </div>
@ -23,9 +23,9 @@
<div class="order-2 md:order-3 flex items-center" id="nav-content"> <div class="order-2 md:order-3 flex items-center" id="nav-content">
<a class="flex items-center tracking-wide no-underline hover:no-underline font-bold text-gray-800 text-xl " href="#"> <nuxt-link class="flex items-center tracking-wide no-underline hover:no-underline font-bold text-gray-800 text-xl " href="/">
COSETTE COSETTE
</a> </nuxt-link>
<!-- <a class="pl-3 inline-block no-underline hover:text-black" href="#"> <!-- <a class="pl-3 inline-block no-underline hover:text-black" href="#">
<svg class="fill-current hover:text-black" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <svg class="fill-current hover:text-black" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M21,7H7.462L5.91,3.586C5.748,3.229,5.392,3,5,3H2v2h2.356L9.09,15.414C9.252,15.771,9.608,16,10,16h8 c0.4,0,0.762-0.238,0.919-0.606l3-7c0.133-0.309,0.101-0.663-0.084-0.944C21.649,7.169,21.336,7,21,7z M17.341,14h-6.697L8.371,9 h11.112L17.341,14z" /> <path d="M21,7H7.462L5.91,3.586C5.748,3.229,5.392,3,5,3H2v2h2.356L9.09,15.414C9.252,15.771,9.608,16,10,16h8 c0.4,0,0.762-0.238,0.919-0.606l3-7c0.133-0.309,0.101-0.663-0.084-0.944C21.649,7.169,21.336,7,21,7z M17.341,14h-6.697L8.371,9 h11.112L17.341,14z" />

View file

@ -1,35 +1,40 @@
<script setup>
let cosetta = {}
function add () {
const ret = $fetch('/api/cosette', { method: 'post', body: cosetta })
console.error(ret)
}
</script>
<template> <template>
<div class="modal" id="my-modal"> <div class="modal" id="my-modal">
<div class="modal-box"> <div class="modal-box">
<h3 class="font-bold text-lg">Aggiungi una cosetta!</h3> <h3 class="font-bold text-lg uppercase">Aggiungo una cosetta</h3>
<p class="py-4">Ziobilly</p> <p class="py-4">Ziobilly</p>
<form action="/api/cosette" method="post" enctype="multipart/form-data"> <form action="/api/cosette" method="post" enctype="multipart/form-data">
<label class="label"> <label class="label">
<span class="label-text-alt">Alt label</span> <span class="label-text">Che roba è?</span>
</label>
<input type="text" name='name' placeholder="Nome" class="input input-bordered w-full" />
<label class="label">
<span class="label-text-alt">Metti il nome, modello, qualsiasi cosa che possa aiutare ad identificarmi</span>
</label> </label>
<input type="text" v-model='cosetta.name' name='name' placeholder="Name" class="input input-bordered w-full max-w-xs" />
<input type="file" name='imgs' />
<label class="label"> <label class="label">
<span class="label-text-alt">Description</span> <span class="label-text-alt">Descrizione</span>
</label> </label>
<textarea v-model='cosetta.description' name='description' class='textarea'></textarea> <textarea name='description' class='input input-bordered w-full'></textarea>
<label class="label">
<span class="label-text-alt">In che stato è? Dove l'hai trovato? </span>
</label>
<label class="label">
<span class="label-text">Tag</span>
</label>
<input type="text" name='tags' placeholder="Tags" class="input input-bordered w-full" /><br/>
<label class="label">
<span class="label-text">Immagini</span>
</label>
<input class='w-full input input-bordered' type="file" name='imgs' />
<div class="modal-action"> <div class="modal-action">
<button class='btn btn-success' type='submit'>Add</button> <a href="#" class="btn">Annulla</a>
<!-- <a @click='add' class='btn btn-success'>Add</a> --> <button class='btn btn-success' type='submit'>Aggiungi</button>
<a href="#" class="btn">Close!</a>
</div> </div>
</form> </form>
</div> </div>

View file

@ -1,14 +1,35 @@
<script setup> <script setup>
const route = useRoute() const route = useRoute()
// qui devo prendere cosetta const { cosetta, comments } = await $fetch(`/api/cosetta/${route.params.cosetta}`)
const cosette = await $fetch(`/api/cosetta/${$route.params.cosetta.id}`)
const comment = { cosetta_uuid: route.params.cosetta, message: '' }
const addComment = () => $fetch(`/api/comment`, { method: 'POST', body: { ...comment } })
</script> </script>
<template> <template>
<section class="bg-white py-8"> <section class="bg-white py-8">
<div class="container mx-auto flex items-center flex-wrap pt-4 pb-12">
ciao - {{ $route.params.cosetta }} <div class="container mx-auto pt-4 pb-12">
<img v-if='cosetta.images' :src="`/src/public/${cosetta.images[0]}`"/>
<h3 class='uppercase mt-4 font-bold text-xl'>{{cosetta.name}}</h3><br/>
<p class='pt-1 text-gray-700 text-xl'>{{cosetta.description}}</p>
<span class="badge mr-1" v-for='(tag, idx) in cosetta.tags' :key='idx' v-text='tag'></span>
</div>
<div class="container mx-auto">
<p class="font-bold text-xl uppercase">chiacchiere</p>
<div class='form-control'>
<div class='input-group'>
<input v-model='comment.message' class="input input-bordered w-full text-sm" @keypress:enter="addComment"/>
<button class="btn btn-success" @click='addComment'>Invia</button>
</div>
<div class='mt-2' v-for='comment in comments' :key='comment.uuid'>
<span class="label-text-alt" v-text='comment.updatedAt'/>
<div class="alert" v-text='comment.message'/>
</div>
</div>
</div> </div>
</section> </section>
</template> </template>

View file

@ -10,7 +10,7 @@ const cosette = await $fetch('/api/cosette')
<div class="container mx-auto flex items-center flex-wrap pt-4 pb-12"> <div class="container mx-auto flex items-center flex-wrap pt-4 pb-12">
<nav id="store" class="w-full z-30 top-0 px-6 py-1"> <nav id="store" class="w-full z-30 top-0 px-6 py-1">
<div class="w-full container mx-auto flex flex-wrap items-center justify-between mt-0 px-2 py-3"> <div class="w-full container mx-auto flex flex-wrap items-center justify-between mt-0 px-2 py-3">
<a class="uppercase tracking-wide no-underline hover:no-underline font-bold text-yellow text-xl " href="https://it.hackmeeting.org">Hackmeeting 0x19</a> <a class="uppercase tracking-wide no-underline hover:no-underline font-bold text-yellow text-xl" href="https://it.hackmeeting.org">Hackmeeting 0x19</a>
<div class="flex items-center" id="store-nav-content"> <div class="flex items-center" id="store-nav-content">
<a class="pl-3 inline-block no-underline hover:text-black modal-button" href="#my-modal"> <a class="pl-3 inline-block no-underline hover:text-black modal-button" href="#my-modal">
<Icon-ic:baseline-add/> <Icon-ic:baseline-add/>

View file

@ -0,0 +1,12 @@
import { addComment } from '../controller'
import { useBody } from 'h3'
export default defineEventHandler(async (event) => {
try {
const body = await useBody(event)
addComment(body)
return { success: true }
} catch (e) {
return { success: false, reason: e.message }
}
})

View file

@ -0,0 +1,9 @@
import { getComments } from '../../controller'
export default defineEventHandler(event => {
try {
return getComments(event.context.params.cosetta_uuid)
} catch (e) {
return { success: false, reason: e.message }
}
})

View file

@ -1,6 +1,5 @@
import { get } from '../../controller' import { get } from '../../controller'
export default defineEventHandler(event => { export default defineEventHandler(event => {
console.error(event) return get(event.context.params.uuid)
return get(event.context.params.name)
}) })

View file

@ -1,6 +1,5 @@
import { getAll } from '../controller' import { getAll } from '../controller'
export default defineEventHandler(event => { export default defineEventHandler(event => {
console.error(event) return getAll()
return getAll() })
})

View file

@ -1,5 +1,5 @@
import { add } from '../controller' import { add } from '../controller'
import { useBody, callHandler } from 'h3' import { useBody, callHandler, sendRedirect } from 'h3'
import { uploadService } from '../services/upload-service' import { uploadService } from '../services/upload-service'
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
@ -7,9 +7,9 @@ export default defineEventHandler(async (event) => {
const handler = uploadService().generateHandler() const handler = uploadService().generateHandler()
await callHandler(handler, event.req, event.res) await callHandler(handler, event.req, event.res)
const body = await useBody(event) const body = await useBody(event)
body.imgs = [event.req.file?.filename?] body.imgs = [event.req.file?.filename]
add(body) add(body)
return { success: true } sendRedirect(event, '/')
} catch (e) { } catch (e) {
return { success: false, reason: e.message } return { success: false, reason: e.message }
} }

View file

@ -4,32 +4,53 @@ const db = new Database('./cosette.db')
function load () { function load () {
db.pragma('journal_mode = WAL') db.pragma('journal_mode = WAL')
db.exec('CREATE TABLE IF NOT EXISTS cosette (uuid TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT, tags TEXT, images TEXT)') db.exec('CREATE TABLE IF NOT EXISTS cosette (uuid TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT, tags TEXT, images TEXT, updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP)')
db.exec('CREATE TABLE IF NOT EXISTS chan (uuid TEXT PRIMARY KEY, cosetta_uuid REFERENCES cosette(uuid), message TEXT, updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP)')
} }
// load() // load()
export function add (cosetta) { export function add (cosetta) {
const q = db.prepare('INSERT INTO cosette (uuid, name, description, tags, images) VALUES(:uuid, :name, :description, :tags, :imgs)') const q = db.prepare('INSERT INTO cosette (uuid, name, description, tags, images) VALUES(:uuid, :name, :description, :tags, :imgs)')
cosetta.uuid = v4() cosetta.uuid = v4()
cosetta.tags = JSON.stringify(cosetta.tags) cosetta.tags = JSON.stringify(cosetta.tags.split(',').map(t => t.toLowerCase().trim()))
cosetta.imgs = JSON.stringify(cosetta.imgs) cosetta.imgs = JSON.stringify(cosetta.imgs)
q.run(cosetta) q.run(cosetta)
return cosetta return cosetta
} }
export function get (uuid) { export function get (uuid) {
const q = db.prepare('SELECT * from cosette WHERE uuid = ?') let q = db.prepare('SELECT * from cosette WHERE uuid = ?')
console.error('sono dentro cosetta e cerco ', uuid) const cosetta = q.get(uuid)
q.get(uuid) cosetta.tags = cosetta.tags ? JSON.parse(cosetta.tags) : []
cosetta.images = cosetta.images ? JSON.parse(cosetta.images) : []
q = db.prepare('SELECT message, updatedAt FROM chan WHERE cosetta_uuid = ? ORDER BY updatedAt desc')
const comments = q.all(uuid)
return { cosetta, comments }
} }
export function getAll (limit=0, offset=0, tags=[], search='') { export function getAll (limit=0, offset=0, tags=[], search='') {
const q = db.prepare('SELECT * FROM cosette') const q = db.prepare('SELECT * FROM cosette')
const ret = q.all() const ret = q.all()
return ret.map(r => { return ret.map(r => {
r.tags = JSON.parse(r.tags) r.tags = r.tags ? JSON.parse(r.tags) : []
r.imgs = JSON.parse(r.imgs) r.images = r.images ? JSON.parse(r.images) : []
return r return r
}) })
} }
export function addComment (comment) {
console.error('sono dentro addComment', comment)
const q = db.prepare('INSERT INTO chan (uuid, cosetta_uuid, message) VALUES(:uuid, :cosetta_uuid, :message)')
comment.uuid = v4()
console.error(comment)
q.run(comment)
return comment
}
export function getComments (cosetta_uuid) {
const q = db.prepare('SELECT * from chan WHERE cosetta_uuid = ?')
return q.all(cosetta_uuid)
}