ldc-wenn-dann-mit-respekt/resources/ts/fo/components/NewsInfiniteLoaderComponent.vue
Jérémy Munsch c1369ea508
Implements #18 News.index
- Add toastify css to front
- Bump kwaadpepper/image-resizer with fit option
- Enhance news picture size to 770x770
2023-06-09 11:00:40 +02:00

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>