diff options
| author | Santo Cariotti <santo@dcariotti.me> | 2022-10-04 22:31:35 +0200 | 
|---|---|---|
| committer | Santo Cariotti <santo@dcariotti.me> | 2022-10-04 22:31:35 +0200 | 
| commit | 36b5f74414413e7270d47f52df387697698aeeaf (patch) | |
| tree | 050fc93827ca595a198bb2618dd817eeac845423 | |
| parent | 8806bb5f857502eec2ad9132757458d714fff442 (diff) | |
Add pagination
| -rw-r--r-- | components/ModelForm.vue | 2 | ||||
| -rw-r--r-- | components/Pagination.vue | 35 | ||||
| -rw-r--r-- | pages/index.vue | 16 | ||||
| -rw-r--r-- | pages/search.vue | 14 | ||||
| -rw-r--r-- | pages/user/_id.vue | 19 | ||||
| -rw-r--r-- | store/users.js | 6 | 
6 files changed, 83 insertions, 9 deletions
| diff --git a/components/ModelForm.vue b/components/ModelForm.vue index d59a5ae..f7b622c 100644 --- a/components/ModelForm.vue +++ b/components/ModelForm.vue @@ -248,6 +248,8 @@ export default {              this.$toast.error(response.data.error);            }          }); +      } else { +        this.$toast.error("Fill all the required fields");        }        event.preventDefault();      }, diff --git a/components/Pagination.vue b/components/Pagination.vue new file mode 100644 index 0000000..053d7cf --- /dev/null +++ b/components/Pagination.vue @@ -0,0 +1,35 @@ +<template lang="pug"> +  .mt-10.text-center +    nav.isolate.inline-flex.-space-x-px.rounded-md.shadow-sm(aria-label="Pagination") +      a.relative.inline-flex.items-center.rounded-l-md.border.border-gray-300.bg-white.px-2.py-2.text-sm.font-medium.text-gray-500( +        :href="(page == 0) ? '#' : '/?page='+incrPage(-1)" +        :class="{'hover:bg-gray-50 focus:z-20': true, 'cursor-not-allowed opacity-20': page < 1}" +      ) +        span.sr-only Previous +        svg.h-5.w-5(xmlns="http://www.w3.org/2000/svg", viewbox="0 0 20 20", fill="currentColor", aria-hidden="true") +          path(fill-rule="evenodd", d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z", clip-rule="evenodd") +      a.relative.z-10.inline-flex.items-center.border.border-gray-300.px-4.py-2.text-sm.font-medium.text-gray-500.bg-white( +        :href="'/?page='+(i-1)" aria-current="page" +        :class="{'focus:z-20': true, 'bg-green-50 text-green-600 border-green-500': page == (i-1)}" +        v-for="i in pages" +      ) {{ i-1 }} +      a.relative.inline-flex.items-center.rounded-r-md.border.border-gray-300.bg-white.px-2.py-2.text-sm.font-medium.text-gray-500( +        :href="(page == (pages-1)) ? '#' : '/?page='+incrPage(1)" +        :class="{'hover:bg-gray-50 focus:z-20': true, 'cursor-not-allowed opacity-20': page == (pages-1)}" +      ) +        span.sr-only Next +        svg.h-5.w-5(xmlns="http://www.w3.org/2000/svg", viewbox="0 0 20 20", fill="currentColor", aria-hidden="true") +          path(fill-rule="evenodd", d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z", clip-rule="evenodd") +  </template> + +<script> +export default { +  name: "Pagination", +  props: ["page", "pages"], +  methods: { +    incrPage(value) { +      return Number(this.page) + value; +    }, +  }, +}; +</script> diff --git a/pages/index.vue b/pages/index.vue index 27c157a..5884e7c 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -19,11 +19,13 @@            :key="model.id"            :model="model"          ) +      pagination(:page="page" :pages="pages" v-if="count")  </template>  <script>  import ModelLoading from "@/components/ModelLoading.vue";  import ModelBoxCard from "@/components/ModelBoxCard.vue"; +import Pagination from "@/components/Pagination.vue";  import { mapGetters } from "vuex"; @@ -36,14 +38,24 @@ export default {    components: {      "model-loading": ModelLoading,      "model-box-card": ModelBoxCard, +    pagination: Pagination, +  }, +  data() { +    return { +      page: 0, +      pages: 0, +    };    },    computed: {      ...mapGetters(["isLoading"]),      ...mapGetters("auth", ["isLogged"]), -    ...mapGetters("models", ["models"]), +    ...mapGetters("models", ["models", "count"]),    },    created() { -    this.$store.dispatch("models/getModels"); +    this.page = this.$route.query.page ?? 0; +    this.$store.dispatch("models/getModels", this.page).then(() => { +      this.pages = Math.ceil(this.count / 20); +    });    },  };  </script> diff --git a/pages/search.vue b/pages/search.vue index 1c09e3b..6f448af 100644 --- a/pages/search.vue +++ b/pages/search.vue @@ -21,11 +21,13 @@            :key="model.id"            :model="model"          ) +      pagination(:page="page" :pages="pages" v-if="count")  </template>  <script>  import ModelLoading from "@/components/ModelLoading.vue";  import ModelBoxCard from "@/components/ModelBoxCard.vue"; +import Pagination from "@/components/Pagination.vue";  import { mapGetters } from "vuex"; @@ -40,20 +42,28 @@ export default {    data() {      return {        q: "", +      page: 0, +      pages: 0,      };    },    components: {      "model-loading": ModelLoading,      "model-box-card": ModelBoxCard, +    pagination: Pagination,    },    computed: {      ...mapGetters(["isLoading"]),      ...mapGetters("auth", ["isLogged"]), -    ...mapGetters("models", ["models"]), +    ...mapGetters("models", ["models", "count"]),    },    created() {      this.q = this.$route.query["q"]; -    this.$store.dispatch("models/filter", { q: this.q }); +    this.page = this.$route.query.page ?? 0; +    this.$store +      .dispatch("models/filter", { q: this.q, page: this.page }) +      .then(() => { +        this.pages = Math.ceil(this.count / 20); +      });    },  };  </script> diff --git a/pages/user/_id.vue b/pages/user/_id.vue index a43a7c8..797f2c0 100644 --- a/pages/user/_id.vue +++ b/pages/user/_id.vue @@ -19,6 +19,7 @@              :key="model.id"              :model="model"            ) +        pagination(:page="page" :pages="pages" v-if="count")        h4.text-lg(v-else class="dark:text-white") No models found  </template> @@ -28,6 +29,7 @@ import UserAvatar from "@/components/UserAvatar.vue";  import FilePreview from "@/components/FilePreview.vue";  import ModelLoading from "@/components/ModelLoading.vue";  import ModelBoxCard from "@/components/ModelBoxCard.vue"; +import Pagination from "@/components/Pagination.vue";  import { mapGetters } from "vuex"; @@ -39,6 +41,9 @@ export default {        id: 0,        user: {},        models: [], +      count: 0, +      page: 0, +      pages: 0,      };    },    head() { @@ -51,12 +56,14 @@ export default {      "file-preview": FilePreview,      "model-loading": ModelLoading,      "model-box-card": ModelBoxCard, +    pagination: Pagination,    },    computed: {      ...mapGetters(["isLoading"]),    },    created() {      this.id = this.$route.params.id; +    this.page = this.$route.query.page ?? 0;      this.$store.dispatch("users/findById", this.id).then((response) => {        if (response.status != 200) { @@ -66,9 +73,15 @@ export default {        }      }); -    this.$store.dispatch("users/findModels", this.id).then((response) => { -      if (response.status == 200) this.models = response.data.results; -    }); +    this.$store +      .dispatch("users/findModels", { id: this.id, page: this.page }) +      .then((response) => { +        if (response.status == 200) { +          this.models = response.data.results; +          this.count = response.data.count; +          this.pages = Math.ceil(this.count / 20); +        } +      });    },  };  </script> diff --git a/store/users.js b/store/users.js index cf1ca86..90e4dad 100644 --- a/store/users.js +++ b/store/users.js @@ -39,12 +39,14 @@ export const actions = {      return res;    },    // Search user models -  async findModels({ commit }, id) { +  async findModels({ commit }, data) {      commit("loadingStatus", true, { root: true });      let res = { status: 0, data: null };      let api = this.$config.api; +    const id = data.id; +    const page = data.page ? data.page : 0; -    await fetch(`${api}/v1/users/${id}/models`, { +    await fetch(`${api}/v1/users/${id}/models?page=${page}`, {        headers: {          "Content-Type": "application/json",        }, | 
