lesion 1 year ago
parent
commit
cdc2a04ff6
8 changed files with 83 additions and 67 deletions
  1. 4 0
      TODO.md
  2. 2 2
      app/router.options.js
  3. 8 6
      components/cosetta.vue
  4. 27 25
      components/footer.vue
  5. 4 5
      components/upload.vue
  6. 20 15
      pages/c/[cosetta].vue
  7. 9 6
      pages/index.vue
  8. 9 8
      server/controller.js

+ 4 - 0
TODO.md

@@ -0,0 +1,4 @@
+[ ] attach db connection / setup on nuxt listen hook
+[x] card @ homepage
+[ ] pagination / search @ homepage
+[ ] carousel in detail

+ 2 - 2
app/router.options.js

@@ -1,3 +1,3 @@
 export default {
-    scrollBehavior: () => ({ left: 0, top: 0, behavior: 'smooth' })
-}
+  scrollBehavior: () => ({ left: 0, top: 0, behavior: 'smooth' })
+}

+ 8 - 6
components/cosetta.vue

@@ -7,16 +7,18 @@ const { cosetta } = defineProps({
 })
 </script>
 <template>
-  <div class="rounded overflow-hidden shadow-lg">
+  <div class="rounded overflow-hidden shadow-lg flex flex-col justify-between">
     <img class="object-cover w-full h-48" :src="`src/public/${cosetta.images[0]}`" alt="Mountain">
-    <div class="px-6 py-4">
+    <div class="px-6 py-4 grow">
       <nuxt-link :to="`/c/${cosetta.uuid}`">
-        <h2 class="text-pink-500 card-title hover:underline uppercase mb-2" v-text='cosetta.name' />
+        <h2 class="text-pink-500 card-title hover:underline uppercase mb-2 line-clamp-2" v-text='cosetta.name' />
       </nuxt-link>
-      <p class="text-gray-700 text-base line-clamp-2" v-text='cosetta.description' />
+      <p class="text-gray-700 text-base line-clamp-3" v-text='cosetta.description' />
     </div>
     <div class="px-6 pt-4 pb-2">
-      <span v-for='tag in cosetta.tags' :key='tag' class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2" v-text='tag'/>
+      <span v-for='tag in cosetta.tags' :key='tag'
+        class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2"
+        v-text='tag' />
     </div>
   </div>
-</template>
+</template>

+ 27 - 25
components/footer.vue

@@ -1,29 +1,31 @@
 <template>
-<footer class="container mx-auto bg-white py-8 border-t border-gray-400">
+  <footer class="container mx-auto bg-white py-8 border-t border-gray-400">
     <div class="container flex px-3 py-8 ">
-        <div class="w-full mx-auto flex flex-wrap">
-            <div class="flex w-full lg:w-1/2 ">
-                <div class="px-3 md:px-0">
-                    <h4 class="font-bold text-xl text-gray-900">Cosette</h4>
-                    <p class="py-4">
-                      Liberati delle tue cosette
-                    </p>
-                </div>
-            </div>
-            <div class="flex w-full lg:w-1/2 lg:justify-end lg:text-right">
-                <div class="px-3 md:px-0">
-                    <h3 class="font-bold text-xl text-gray-900">Links</h3>
-                    <ul class="list-reset items-center pt-3">
-                        <li>
-                            <a class="inline-block no-underline hover:text-black hover:underline py-1" href="https://it.hackmeeting.org">it.hackmeeting.org</a>
-                        </li>
-                        <li>
-                            <a class="inline-block no-underline hover:text-black hover:underline py-1" href="https://autistici.org/underscore">underscore_TO hacklab</a>
-                        </li>
-                    </ul>
-                </div>
-            </div>
+      <div class="w-full mx-auto flex flex-wrap">
+        <div class="flex w-full lg:w-1/2 ">
+          <div class="px-3 md:px-0">
+            <h4 class="font-bold text-xl text-gray-900">Cosette</h4>
+            <p class="py-4">
+              Liberati delle tue cosette
+            </p>
+          </div>
         </div>
+        <div class="flex w-full lg:w-1/2 lg:justify-end lg:text-right">
+          <div class="px-3 md:px-0">
+            <h3 class="font-bold text-xl text-gray-900">Links</h3>
+            <ul class="list-reset items-center pt-3">
+              <li>
+                <a class="inline-block no-underline hover:text-black hover:underline py-1"
+                  href="https://it.hackmeeting.org">it.hackmeeting.org</a>
+              </li>
+              <li>
+                <a class="inline-block no-underline hover:text-black hover:underline py-1"
+                  href="https://autistici.org/underscore">underscore_TO hacklab</a>
+              </li>
+            </ul>
+          </div>
+        </div>
+      </div>
     </div>
-</footer>
-</template>
+  </footer>
+</template>

+ 4 - 5
components/upload.vue

@@ -2,7 +2,6 @@
   <div class="modal" id="my-modal">
     <div class="modal-box">
       <h3 class="font-bold text-lg uppercase">Aggiungo una cosetta</h3>
-      <p class="py-4">Ziobilly</p>
       <form action="/api/cosette" method="post" enctype="multipart/form-data">
         <label class="label">
           <span class="label-text">Che roba è?</span>
@@ -18,12 +17,12 @@
         <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>
 
         <label class="label">
           <span class="label-text">Tag</span>
         </label>
-        <input type="text" name='tags' placeholder="Tags" class="input input-bordered w-full" /><br/>
+        <input type="text" name='tags' placeholder="Tags" class="input input-bordered w-full" /><br />
 
 
         <label class="label">
@@ -38,5 +37,5 @@
         </div>
       </form>
     </div>
-  </div>  
-</template>
+  </div>
+</template>

+ 20 - 15
pages/c/[cosetta].vue

@@ -1,37 +1,42 @@
 <script setup>
-  const route = useRoute()
+const route = useRoute()
 
-  let { cosetta, comments } = reactive(await $fetch(`/api/cosetta/${route.params.cosetta}`))
+let { cosetta, comments } = reactive(await $fetch(`/api/cosetta/${route.params.cosetta}`))
 
-  const comment = reactive({ cosetta_uuid: route.params.cosetta, message: '' })
-  const addComment = async () => {
-    const ret = await $fetch(`/api/comment`, { method: 'POST', body: { ...comment } })
-    comment.message = ''
-    comments.unshift(ret.comment)
-  }
+const comment = reactive({ cosetta_uuid: route.params.cosetta, message: '' })
+const addComment = async () => {
+  const ret = await $fetch(`/api/comment`, { method: 'POST', body: { ...comment } })
+  comment.message = ''
+  comments.unshift(ret.comment)
+}
 
 </script>
 <template>
   <section class="bg-white py-8">
 
     <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>
+      <img v-if='cosetta.images' :src="`/src/public/${cosetta.images[0]}`" />
+      <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">
+        <span v-for='tag in cosetta.tags' :key='tag'
+          class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2"
+          v-text='tag' />
+      </div>
+      <p class='pt-1 text-gray-700 text-xl'>{{ cosetta.description }}</p>
+
     </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"/>
+          <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'/>
+          <span class="label-text-alt" v-text='comment.updatedAt' />
+          <div class="alert" v-text='comment.message' />
         </div>
       </div>
     </div>

+ 9 - 6
pages/index.vue

@@ -2,12 +2,12 @@
 const page = ref(0)
 let { data, refresh } = await useFetch(() => `/api/cosette?page=${page.value}`)
 
-function next () {
+function next() {
   page.value++
   refresh()
 }
 
-function prev () {
+function prev() {
   page.value--
   refresh()
 }
@@ -18,16 +18,19 @@ function prev () {
     <Upload />
     <Hero />
     <div class="container mx-auto flex items-center flex-wrap pt-4 pb-12 px-2">
-      <p>Ci sono <strong>{{data.details.count}}</strong> cosette in tutto, sei a pagina {{data.details.page+1}} di {{data.details.n_page}}. Se vuoi puoi</p>
-      <a class="text-orange-700 hover:underline flex" href="#my-modal"><Icon-ic:baseline-add/>  aggiungere una cosetta</a>
+      <p>Ci sono <strong>{{ data.details.count }}</strong> cosette in tutto, sei a pagina {{ data.details.page + 1 }} di
+        {{ data.details.n_page }}. Se vuoi puoi</p>
+      <a class="text-orange-700 hover:underline flex" href="#my-modal">
+        <Icon-ic:baseline-add /> aggiungere una cosetta
+      </a>
     </div>
     <div class='container mx-auto'>
       <nav>
         <button v-if='data.details.prev' @click='prev'>
-          <Icon-ic:baseline-chevron-left style='font-size: 40px'/>
+          <Icon-ic:baseline-chevron-left style='font-size: 40px' />
         </button>
         <button v-if='data.details.next' @click='next'>
-          <Icon-ic:baseline-chevron-right style='font-size: 40px'/>
+          <Icon-ic:baseline-chevron-right style='font-size: 40px' />
         </button>
       </nav>
 

+ 9 - 8
server/controller.js

@@ -2,7 +2,8 @@ import Database from 'better-sqlite3'
 import { v4 } from 'uuid'
 const db = new Database('./cosette.db')
 
-function load () {
+
+function load() {
   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, updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP)')
   db.exec('CREATE INDEX cosette_updated_at_index ON cosette (updatedAt)')
@@ -11,7 +12,7 @@ function load () {
 // TODO: da gestire in qualche modo all'avvio
 // 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)')
   cosetta.uuid = v4()
   cosetta.tags = JSON.stringify(cosetta.tags.split(',').map(t => t.toLowerCase().trim()))
@@ -20,7 +21,7 @@ export function add (cosetta) {
   return cosetta
 }
 
-export function get (uuid) {
+export function get(uuid) {
   let q = db.prepare('SELECT * from cosette WHERE uuid = ?')
   const cosetta = q.get(uuid)
   cosetta.tags = cosetta.tags ? JSON.parse(cosetta.tags) : []
@@ -32,7 +33,7 @@ export function get (uuid) {
   return { cosetta, comments }
 }
 
-export function getAll ({ page }) {
+export function getAll({ page }) {
   page = Number(page || 0)
   const perPage = 3
   let query = 'SELECT * FROM cosette ORDER BY updatedAt DESC LIMIT ? OFFSET ?'
@@ -46,18 +47,18 @@ export function getAll ({ page }) {
 
   const count = db.prepare('SELECT COUNT(*) count from cosette').get().count
 
-  return { cosette, details: { page, count, prev: page !== 0, next: count > perPage*(page+1), n_page: Math.ceil(count / perPage) } } 
+  return { cosette, details: { page, count, prev: page !== 0, next: count > perPage * (page + 1), n_page: Math.ceil(count / perPage) } }
 }
 
 
-export function addComment (comment) {
+export function addComment(comment) {
   const q = db.prepare('INSERT INTO chan (uuid, cosetta_uuid, message) VALUES(:uuid, :cosetta_uuid, :message)')
   comment.uuid = v4()
   q.run(comment)
   return comment
 }
 
-export function getComments (cosetta_uuid) {
+export function getComments(cosetta_uuid) {
   const q = db.prepare('SELECT * from chan WHERE cosetta_uuid = ?')
   return q.all(cosetta_uuid)
-}
+}