- Add toastify css to front - Bump kwaadpepper/image-resizer with fit option - Enhance news picture size to 770x770
130 lines
3.7 KiB
Vue
130 lines
3.7 KiB
Vue
<template>
|
|
<div class="max-w-screen-2xl mx-auto">
|
|
<div
|
|
v-if="newsList.length"
|
|
class="flex flex-col gap-0 mt-24"
|
|
>
|
|
<template
|
|
v-for="(news, newsIndex) of newsList"
|
|
:key="newsIndex"
|
|
>
|
|
<div
|
|
v-html="news"
|
|
class="flex flex-wrap flex-row my-3 sm:my-0 sm:even:flex-row sm:odd:flex-row-reverse"
|
|
/>
|
|
</template>
|
|
</div>
|
|
<div
|
|
v-else
|
|
class="text-left"
|
|
>
|
|
{{ __("No news for the moment") }}
|
|
</div>
|
|
<div class="flex justify-center mt-12 mb-48">
|
|
<button
|
|
v-if="!noMorePosts"
|
|
:disabled="loading"
|
|
class="button brown inline-flex items-center px-4 my-2 mt-6 mr-4 text-sm text-white"
|
|
@click.prevent="loadNextPage"
|
|
>
|
|
<FontAwesomeIcon
|
|
v-if="loading"
|
|
icon="fa-solid fa-cog"
|
|
:spin="true"
|
|
/>
|
|
{{ __("Load more posts") }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import axios from "axios";
|
|
import parseLaravelErrorMessages from "./../../modules/parseLaravelErrorMessages";
|
|
import route from "./../../modules/route";
|
|
import toast from "./../../modules/toast";
|
|
import trans from "./../../modules/trans";
|
|
import { defineComponent } from "vue";
|
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
|
|
|
export default defineComponent({
|
|
name: "NewsInfiniteLoaderComponent",
|
|
mixins: [route, trans, toast, parseLaravelErrorMessages],
|
|
mounted() {
|
|
this.loadActu();
|
|
},
|
|
data(): {
|
|
pagination: number;
|
|
loading: boolean;
|
|
noMorePosts: boolean;
|
|
newsList: string[];
|
|
currentPage: number;
|
|
} {
|
|
return {
|
|
pagination: 15,
|
|
loading: false,
|
|
noMorePosts: false,
|
|
newsList: [],
|
|
currentPage: 1,
|
|
};
|
|
},
|
|
methods: {
|
|
loadNextPage(): void {
|
|
this.currentPage = this.currentPage + 1;
|
|
this.loadActu();
|
|
},
|
|
loadActu(): void {
|
|
const newsPaginateRoute = this.route("news.index", {
|
|
page: this.currentPage,
|
|
});
|
|
if (!newsPaginateRoute) {
|
|
throw Error("Undefined route 'news.index'");
|
|
}
|
|
this.loading = true;
|
|
axios
|
|
.get(newsPaginateRoute)
|
|
.then((response) => {
|
|
if (response.data.length < this.pagination) {
|
|
this.noMorePosts = true;
|
|
}
|
|
for (const news of response.data) {
|
|
this.newsList.push(this.base64decode(String(news)));
|
|
}
|
|
})
|
|
.then(() => (this.loading = false))
|
|
.catch((e) => {
|
|
console.log(e);
|
|
let message = this.__("http-statuses.0");
|
|
if (e.response.status === 422) {
|
|
message =
|
|
this.parseValidationErrors(e.response?.data?.errors ?? {}) ||
|
|
message;
|
|
if (window.vueDebug) {
|
|
console.warn(e.response.data.errors);
|
|
}
|
|
} else if (e.response.status === 419) {
|
|
// * CSRF TOKEN MISMATCH (On ne pourrais plus faire d'appels AJAX sans recharger la page)
|
|
setTimeout(() => window.location.reload(), 2000);
|
|
} else if (e.response.status === 403) {
|
|
// * Access denied
|
|
setTimeout(() => window.location.reload(), 2000);
|
|
} else {
|
|
if (window.vueDebug) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
this.errorNotify(this.__(`http-statuses.${e.response.status}`));
|
|
this.errorNotify(message);
|
|
});
|
|
},
|
|
base64decode(str: string): string {
|
|
let decode = atob(str).replace(
|
|
"/[\x80-\uffff]/g",
|
|
(m) => `%${m.charCodeAt(0).toString(16).padStart(2, "0")}`
|
|
);
|
|
return decodeURIComponent(decode);
|
|
},
|
|
},
|
|
components: { FontAwesomeIcon },
|
|
});
|
|
</script>
|