Skip to content

Commit

Permalink
Ajout de la pagination sur la page /exploitations
Browse files Browse the repository at this point in the history
  • Loading branch information
jel-atolcd committed Aug 26, 2024
1 parent 037c32c commit fe03189
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 56 deletions.
6 changes: 4 additions & 2 deletions src/cartobio-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ export async function searchOperators ({ input, page, sort, order }) {
}

/**
* @param {number?} limit
* @param {number?} offset
* @return {Promise<AgenceBioNormalizedOperator[]>}
*/
export async function getUserOperators () {
const { data } = await apiClient.get(`/v2/operators`)
export async function getUserOperators (limit, offset) {
const { data } = await apiClient.get(`/v2/operators`, { params: { limit, offset } })

return data
}
Expand Down
52 changes: 52 additions & 0 deletions src/components/widgets/Pagination.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { mount } from '@vue/test-utils';
import { describe, it, expect } from 'vitest';
import Pagination from '@/components/widgets/Pagination.vue';

describe('Pagination.vue', () => {
const getWrapper = (page) =>
mount(Pagination, {
props: {
currentPage: page,
maxPage: 5,
},
});

it('renders correctly', () => {
const wrapper = getWrapper(1);
expect(wrapper.find('.fr-btns-group--pagination').exists()).toBe(true);
});

it('emits changePage event with correct value when select option is changed', async () => {
const wrapper = getWrapper(1);
const select = wrapper.find('select');
await select.setValue(3);
expect(wrapper.emitted().changePage[0]).toEqual([3]);
expect(select.element.value).toBe('3');
});

it('emits changePage event with correct value when previous button is clicked', async () => {
const wrapper = getWrapper(2);
const prevButton = wrapper.find('.pagination-page-previous');
await prevButton.trigger('click');
expect(wrapper.emitted().changePage[0]).toEqual([1]);
});

it('emits changePage event with correct value when next button is clicked', async () => {
const wrapper = getWrapper(2);
const nextButton = wrapper.find('.pagination-page-next');
await nextButton.trigger('click');
expect(wrapper.emitted().changePage[0]).toEqual([3]);
});

it('disables previous button on the first page', () => {
const wrapper = getWrapper(1);
const prevButton = wrapper.find('.pagination-page-previous');
expect(prevButton.attributes('disabled')).not.toBeUndefined();
});

it('disables next button on the last page', () => {
const wrapper = getWrapper(5);
const nextButton = wrapper.find('.pagination-page-next');
expect(nextButton.attributes('disabled')).not.toBeUndefined();
});
});
66 changes: 66 additions & 0 deletions src/components/widgets/Pagination.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<template>
<ul class="fr-btns-group fr-btns-group--center fr-btns-group--inline fr-btns-group--pagination">
<li>
<div class="fr-select-group fr-select-group--inline">
<select
class="fr-select"
id="search-results-page-selector"
name="page"
:value="currentPage"
@change="(event) => $emit('changePage', parseInt(event.target.value))"
>
<option value="" disabled hidden>Sélectionner un numéro de pagination</option>
<option :value="page" :key="page" v-for="page in maxPage">{{ page }}</option>
</select>
<label class="fr-label" for="search-results-page-selector"> sur {{ maxPage }} pages </label>
</div>
</li>
<li>
<button
class="fr-btn fr-btn--tertiary-no-outline fr-icon-arrow-left-s-line pagination-page-previous"
:disabled="maxPage < 2 || currentPage === 1"
@click="$emit('changePage', currentPage - 1)"
>
Page précédente
</button>
</li>
<li>
<button
class="fr-btn fr-btn--tertiary-no-outline fr-icon-arrow-right-s-line pagination-page-next"
:disabled="maxPage < 2 || currentPage === maxPage"
@click="$emit('changePage', currentPage + 1)"
>
Page suivante
</button>
</li>
</ul>
</template>

<script setup>
defineProps(['currentPage', 'maxPage']);
defineEmits('changePage');
</script>

<style scoped>
.fr-btns-group--pagination {
.fr-label, .fr-select {
font-size: inherit; /* reset size so as they are consistent */
}
.fr-btn {
margin: 0;
}
}
.fr-select-group--inline {
display: flex;
align-items: center;
select {
background-color: transparent;
box-shadow: none;
text-align: right;
width: 6rem; /* up to 3 digits, so 999 pages */
}
}
</style>
42 changes: 7 additions & 35 deletions src/pages/certification/exploitations/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -115,21 +115,11 @@ meta:
<tr>
<td class="results-total">{{ operators.length }} sur {{ pagination.total }} résultats</td>
<td colspan="3">
<ul class="fr-btns-group fr-btns-group--right fr-btns-group--inline fr-btns-group--pagination results-page-selector">
<li class="fr-mr-2v">
<div class="fr-select-group fr-select-group--inline">
<select class="fr-select" id="search-results-page-selector" name="page" :value="page" @change="$event => updateQuery({ page: $event.target.value })">
<option value="" disabled hidden>Sélectionner un numéro de pagination</option>
<option :value="page" :key="page" v-for="page in pagination.page_max">{{ page }}</option>
</select>
<label class="fr-label" for="search-results-page-selector">
sur {{ pagination.page_max }} pages
</label>
</div>
</li>
<li><button class="fr-btn fr-btn--tertiary-no-outline fr-icon-arrow-left-s-line pagination-page-previous" :disabled="!hasPagination || currentPage === 1" @click="updateQuery({ page: currentPage-1 })">Page précédente</button></li>
<li><button class="fr-btn fr-btn--tertiary-no-outline fr-icon-arrow-right-s-line pagination-page-next" :disabled="!hasPagination || currentPage === pagination.page_max" @click="updateQuery({ page: currentPage+1 })">Page suivante</button></li>
</ul>
<Pagination
:currentPage="currentPage"
:maxPage="pagination.page_max"
@changePage="updateQuery({ page: $event })"
/>
</td>
</tr>
</tfoot>
Expand Down Expand Up @@ -172,6 +162,7 @@ import { useUserStore } from '@/stores/user.js'
import { useOnline } from "@vueuse/core"
import { useCartoBioStorage } from "@/stores/storage.js"
import Conflict from "@/components/versions/Conflict.vue"
import Pagination from '@/components/widgets/Pagination.vue';
const props = defineProps({
search: {
Expand Down Expand Up @@ -229,7 +220,6 @@ const pagination = ref({
const showOptionalControl = computed(() => Boolean(searchInput.value))
const hasResults = computed(() => searchResults.value.length > 0)
const hasPagination = computed(() => searchResults.value.length && searchResults.value.length < pagination.value.total)
const sortAttribute = (sort) => {
if (sort !== sortOrder.value.sort) {
Expand Down Expand Up @@ -314,25 +304,7 @@ watch(() => route.query.search, (search) => {
}
.fr-btns-group--pagination {
.fr-label, .fr-select {
font-size: inherit; /* reset size so as they are consistent */
}
.fr-btn {
margin: 0;
}
}
.fr-select-group--inline {
display: flex;
align-items: center;
select {
background-color: transparent;
box-shadow: none;
text-align: right;
width: 6rem; /* up to 3 digits, so 999 pages */
}
justify-content: flex-end;
}
.fr-table table {
Expand Down
73 changes: 54 additions & 19 deletions src/pages/exploitations/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,26 @@ meta:
<div class="fr-container fr-my-5w">
<div class="fr-grid-row">
<div class="fr-col-12">
<h2 class="fr-h3">
Sélectionner mon exploitation
</h2>
<h2 class="fr-h3">Sélectionner mon exploitation</h2>

<section class="fr-grid-row fr-grid-row--gutters" v-if="hasOperators">
<div v-if="isLoading">
<Spinner>Chargement des données…</Spinner>
</div>

<section class="fr-grid-row fr-grid-row--gutters" v-if="!isLoading && hasOperators">
<article class="fr-col-12 fr-col-md-4" v-for="operator in operators" :key="operator.numeroBio">
<div class="fr-card fr-card--horizontal">
<div class="fr-card__body">
<div class="fr-card__content">
<h4 class="fr-card__title">{{ operator.nom }}</h4>
<div class="fr-card__desc">
<ul class="list-unstyled">
<li v-if="operator.commune"><strong>Siège</strong> : {{ operator.commune }} ({{ operator.departement }})</li>
<li v-if="operator.denominationCourante && operator.denominationCourante !== operator.nom"><b>Dénomination courante</b> : {{ operator.denominationCourante }}</li>
<li v-if="operator.commune">
<strong>Siège</strong> : {{ operator.commune }} ({{ operator.departement }})
</li>
<li v-if="operator.denominationCourante && operator.denominationCourante !== operator.nom">
<b>Dénomination courante</b> : {{ operator.denominationCourante }}
</li>
<li v-if="operator.siret"><b>SIRET</b> : {{ operator.siret }}</li>
<li v-if="operator.numeroPacage"><b>PACAGE</b> : {{ operator.numeroPacage }}</li>
<li><b>Numéro Bio</b> : {{ operator.numeroBio }}</li>
Expand All @@ -39,7 +45,7 @@ meta:
</div>

<div class="fr-card__footer">
<ul class="fr-btns-group fr-btns-group--inline-lg">
<ul class="fr-btns-group fr-btns-group--inline-lg">
<li>
<router-link class="fr-btn" :to="`/exploitations/${operator.numeroBio}`">
Voir cette exploitation
Expand All @@ -51,34 +57,63 @@ meta:
</div>
</article>
</section>

<Pagination
v-if="!isLoading && maxPage > 1"
:currentPage
:maxPage
@change-page="(page) => (currentPage = page)"
/>
</div>
</div>
</div>
</template>

<script setup>
import { computed, ref } from 'vue'
import { getUserOperators } from "@/cartobio-api.js"
import { useRouter } from "vue-router"
import { computed, onMounted, ref, watch } from 'vue';
import { getUserOperators } from '@/cartobio-api.js';
import { useRouter } from 'vue-router';
import Spinner from '@/components/widgets/Spinner.vue';
import Pagination from '@/components/widgets/Pagination.vue';
const router = useRouter()
const RESULTS_PER_PAGE = 10;
const res = await getUserOperators()
if (res.operators.length === 1) {
await router.push(`/exploitations/${res.operators[0].numeroBio}`)
}
const operators = ref(res.operators)
const router = useRouter();
const isLoading = ref(true);
const operators = ref([]);
const nbTotal = ref(0);
const currentPage = ref(1);
const hasOperators = computed(() => Boolean(operators.value.length));
const maxPage = computed(() => Math.ceil(nbTotal.value / RESULTS_PER_PAGE));
const hasOperators = computed(() => Boolean(operators.value.length))
watch(currentPage, () => loadOperators());
onMounted(() => {
loadOperators();
});
async function loadOperators() {
isLoading.value = true;
const res = await getUserOperators(RESULTS_PER_PAGE, (currentPage.value - 1) * RESULTS_PER_PAGE);
if (res.nbTotal === 1 && res.operators.length === 1) {
await router.push(`/exploitations/${res.operators[0].numeroBio}`);
}
operators.value = res.operators;
nbTotal.value = res.nbTotal;
isLoading.value = false;
}
</script>

<style scoped>
span[aria-selected="true"] {
span[aria-selected='true'] {
font-weight: bold;
}
.help span:not(:last-of-type)::after {
content: ", ";
content: ', ';
}
.list-unstyled {
Expand Down

0 comments on commit fe03189

Please sign in to comment.