Merged PR 132: Explorer start

Explorer start
This commit is contained in:
Dominic Villemure
2024-08-29 23:38:00 +00:00
3 changed files with 133 additions and 82 deletions

View File

@@ -1,21 +1,20 @@
<template> <template>
<div class="bg-white shadow-lg rounded-lg overflow-hidden transition-all duration-300 ease-in-out py4"> <div class="bg-white shadow-lg rounded-lg overflow-hidden transition-all duration-300 ease-in-out py4">
<div class="flex justify-between items-center mb-2"> <div class="flex justify-between items-center mb-2">
<h3 class="text-lg font-bold p-3">{{ video.title }}</h3> <h3 class="text-lg font-bold p-3">{{ content.title }}</h3>
<v-btn icon class="ml-2" variant="plain">
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</div> </div>
<img :src="video.thumbnail" alt="video thumbnail" class="w-full "> <img v-if="content.urls !== null" :src="content.urls" alt="thumbnail" class="w-full ">
<div class="p-3"> <div class="p-3">
<p class="text-gray-600 mb-4">{{ video.description }}</p> <p class="text-gray-600 mb-4">{{ content.description }}</p>
<div class="flex items-center"> <div class="flex items-center">
<img :src="video.profileImage" alt="profile image" class="w-10 h-10 rounded-full"> <router-link class="capitalize px-2" :to="`/@${props.content.createdByName}`">
<img :src="content.createdByPortraitUrl" alt="profile image" class="w-10 h-10 rounded-full">
</router-link>
<div class="ml-4"> <div class="ml-4">
<h4 class="text-md font-bold">{{ video.name }}</h4> <h4 class="text-md font-bold">{{ content.name }}</h4>
<div class="text-gray-600 text-sm"> <div class="text-gray-600 text-sm">
<span>{{ video.vues }} vues</span> - <span>{{ content.reactions.length }} reactions</span> -
<span>{{ video.timeAgo }} ago</span> <span>{{ time_ago(content.createdAt) }}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -26,8 +25,10 @@
<script setup> <script setup>
defineProps({ import {time_ago} from "@/internal_time_ago.js";
video: {
const props = defineProps({
content: {
type: Object, type: Object,
required: true required: true
} }

View File

@@ -1,12 +1,62 @@
<script setup> <script setup>
import { ref, computed } from 'vue'; import {ref, computed, onMounted, onBeforeUnmount, onBeforeMount} from 'vue';
import videosData from './videos.json'; import videosData from './videos.json';
import ExplorerCard from '@/views/explorer/ExplorerCard.vue'; import ExplorerCard from '@/views/explorer/ExplorerCard.vue';
import {useClient} from "@/plugins/api.js";
const client = useClient();
const contentCount = ref(0);
const pageSize = ref(10);
const isSmallScreen = ref(false);
const errorMessage = ref()
// Données // Données
const mostViewedVideos = videosData.mostViewedVideos; const mostReactedContent = ref([]);
const mostBoughtVideos = videosData.mostBoughtVideos; const mostBoughtVideos = videosData.mostBoughtVideos;
let last_id = null
const updateScreenSize = () => {
isSmallScreen.value = window.matchMedia('(max-width: 600px)').matches;
};
const fetchContents = async () => {
try {
let uri = `/api/contents/featured/?page_size=${pageSize.value}`;
if (last_id !== null) uri = uri + `&last_id=${last_id}`
const response = await client.get(uri);
console.log(response.data);
if (response.status >= 200 && response.status < 300) {
contentCount.value = response.data.length;
if (contentCount.value > 0) {
mostReactedContent.value.push(...response.data)
const [last_content] = response.data.slice(-1)
last_id = last_content.id
}
}
} catch (error) {
console.error("Failed to fetch posts", error);
}
};
onBeforeMount(async () => {
await fetchContents();
})
onMounted(() => {
updateScreenSize();
window.addEventListener('resize', updateScreenSize);
});
onBeforeUnmount(async () => {
window.removeEventListener('resize', updateScreenSize);
});
// État pour contrôler la plage actuelle des vidéos affichées // État pour contrôler la plage actuelle des vidéos affichées
const currentRangeViewed = ref(0); const currentRangeViewed = ref(0);
const currentRangeBought = ref(0); const currentRangeBought = ref(0);
@@ -19,7 +69,7 @@ const selectedTimeRangeBought = ref('24h'); // Plage de temps sélectionnée pou
// Fonction pour passer à l'ensemble suivant de vidéos (Most Viewed) // Fonction pour passer à l'ensemble suivant de vidéos (Most Viewed)
const nextRowViewed = () => { const nextRowViewed = () => {
if (currentRangeViewed.value + videosPerRowViewed.value < mostViewedVideos.length) { if (currentRangeViewed.value + videosPerRowViewed.value < mostReactedContent.value.length) {
currentRangeViewed.value += videosPerRowViewed.value; currentRangeViewed.value += videosPerRowViewed.value;
} }
}; };
@@ -48,8 +98,8 @@ const previousRowBought = () => {
// Fonction pour basculer entre l'affichage de 4 et 8 vidéos (Most Viewed) // Fonction pour basculer entre l'affichage de 4 et 8 vidéos (Most Viewed)
const toggleVideoDisplayViewed = () => { const toggleVideoDisplayViewed = () => {
if (videosPerRowViewed.value === 4) { if (videosPerRowViewed.value === 4) {
if (currentRangeViewed.value + videosPerRowViewed.value >= mostViewedVideos.length) { if (currentRangeViewed.value + videosPerRowViewed.value >= mostReactedContent.length) {
currentRangeViewed.value = Math.max(mostViewedVideos.length - 8, 0); currentRangeViewed.value = Math.max(mostReactedContent.length - 8, 0);
} }
videosPerRowViewed.value = 8; videosPerRowViewed.value = 8;
} else { } else {
@@ -101,21 +151,21 @@ const chevronIconBought = computed(() => {
<div class="container mx-auto py-4"> <div class="container mx-auto py-4">
<!-- Section Most Viewed avec boutons de sélection de la plage de temps --> <!-- Section Most Viewed avec boutons de sélection de la plage de temps -->
<div class="flex justify-between items-center mb-4"> <div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-bold">Most Viewed</h2> <h2 class="text-2xl font-bold">Most Reacted</h2>
<div class="flex space-x-4"> <!-- <div class="flex space-x-4">-->
<v-btn variant="outlined" small @click="changeTimeRangeViewed('24h')" :class="{'v-btn--active': selectedTimeRangeViewed === '24h'}"> <!-- <v-btn variant="outlined" small @click="changeTimeRangeViewed('24h')" :class="{'v-btn&#45;&#45;active': selectedTimeRangeViewed === '24h'}">-->
<v-icon left>mdi-timer</v-icon> 24h <!-- <v-icon left>mdi-timer</v-icon> 24h-->
</v-btn> <!-- </v-btn>-->
<v-btn variant="outlined" small @click="changeTimeRangeViewed('72h')" :class="{'v-btn--active': selectedTimeRangeViewed === '72h'}"> <!-- <v-btn variant="outlined" small @click="changeTimeRangeViewed('72h')" :class="{'v-btn&#45;&#45;active': selectedTimeRangeViewed === '72h'}">-->
<v-icon left>mdi-timer-sand</v-icon> 72h <!-- <v-icon left>mdi-timer-sand</v-icon> 72h-->
</v-btn> <!-- </v-btn>-->
<v-btn variant="outlined" small @click="changeTimeRangeViewed('week')" :class="{'v-btn--active': selectedTimeRangeViewed === 'week'}"> <!-- <v-btn variant="outlined" small @click="changeTimeRangeViewed('week')" :class="{'v-btn&#45;&#45;active': selectedTimeRangeViewed === 'week'}">-->
<v-icon left>mdi-calendar-week</v-icon> Semaine <!-- <v-icon left>mdi-calendar-week</v-icon> Semaine-->
</v-btn> <!-- </v-btn>-->
<v-btn variant="outlined" small @click="changeTimeRangeViewed('month')" :class="{'v-btn--active': selectedTimeRangeViewed === 'month'}"> <!-- <v-btn variant="outlined" small @click="changeTimeRangeViewed('month')" :class="{'v-btn&#45;&#45;active': selectedTimeRangeViewed === 'month'}">-->
<v-icon left>mdi-calendar-month</v-icon> Mois <!-- <v-icon left>mdi-calendar-month</v-icon> Mois-->
</v-btn> <!-- </v-btn>-->
</div> <!-- </div>-->
</div> </div>
<!-- Liste des vidéos les plus vues --> <!-- Liste des vidéos les plus vues -->
@@ -123,9 +173,9 @@ const chevronIconBought = computed(() => {
<div class="relative overflow-hidden"> <div class="relative overflow-hidden">
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 mb-8"> <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 mb-8">
<ExplorerCard <ExplorerCard
v-for="(video, index) in mostViewedVideos.slice(currentRangeViewed, currentRangeViewed + videosPerRowViewed)" v-for="(content, index) in mostReactedContent.slice(currentRangeViewed, currentRangeViewed + videosPerRowViewed)"
:key="video.id" :key="content.id"
:video="video" :content="content"
/> />
</div> </div>
</div> </div>
@@ -135,7 +185,7 @@ const chevronIconBought = computed(() => {
<v-icon>mdi-arrow-up-circle-outline</v-icon> <v-icon>mdi-arrow-up-circle-outline</v-icon>
</v-btn> </v-btn>
<!-- Bouton pour naviguer vers l'ensemble suivant de vidéos (Most Viewed) --> <!-- Bouton pour naviguer vers l'ensemble suivant de vidéos (Most Viewed) -->
<v-btn @click="nextRowViewed" :disabled="currentRangeViewed + videosPerRowViewed.value >= mostViewedVideos.length"> <v-btn @click="nextRowViewed" :disabled="currentRangeViewed + videosPerRowViewed.value >= mostReactedContent.length">
<v-icon>mdi-arrow-down-circle-outline</v-icon> <v-icon>mdi-arrow-down-circle-outline</v-icon>
</v-btn> </v-btn>
</div> </div>
@@ -149,56 +199,56 @@ const chevronIconBought = computed(() => {
</div> </div>
<!-- Ligne de séparation --> <!-- Ligne de séparation -->
<hr class="my-8"/> <!-- <hr class="my-8"/>-->
<!-- Section Most Bought avec boutons de sélection de la plage de temps --> <!-- Section Most Bought avec boutons de sélection de la plage de temps -->
<div class="flex justify-between items-center mb-4"> <!-- <div class="flex justify-between items-center mb-4">-->
<h2 class="text-2xl font-bold">Most Bought</h2> <!-- <h2 class="text-2xl font-bold">Most Bought</h2>-->
<div class="flex space-x-4"> <!-- <div class="flex space-x-4">-->
<v-btn variant="outlined" small @click="changeTimeRangeBought('24h')" :class="{'v-btn--active': selectedTimeRangeBought === '24h'}"> <!-- <v-btn variant="outlined" small @click="changeTimeRangeBought('24h')" :class="{'v-btn&#45;&#45;active': selectedTimeRangeBought === '24h'}">-->
<v-icon left>mdi-timer</v-icon> 24h <!-- <v-icon left>mdi-timer</v-icon> 24h-->
</v-btn> <!-- </v-btn>-->
<v-btn variant="outlined" small @click="changeTimeRangeBought('72h')" :class="{'v-btn--active': selectedTimeRangeBought === '72h'}"> <!-- <v-btn variant="outlined" small @click="changeTimeRangeBought('72h')" :class="{'v-btn&#45;&#45;active': selectedTimeRangeBought === '72h'}">-->
<v-icon left>mdi-timer-sand</v-icon> 72h <!-- <v-icon left>mdi-timer-sand</v-icon> 72h-->
</v-btn> <!-- </v-btn>-->
<v-btn variant="outlined" small @click="changeTimeRangeBought('week')" :class="{'v-btn--active': selectedTimeRangeBought === 'week'}"> <!-- <v-btn variant="outlined" small @click="changeTimeRangeBought('week')" :class="{'v-btn&#45;&#45;active': selectedTimeRangeBought === 'week'}">-->
<v-icon left>mdi-calendar-week</v-icon> Semaine <!-- <v-icon left>mdi-calendar-week</v-icon> Semaine-->
</v-btn> <!-- </v-btn>-->
<v-btn variant="outlined" small @click="changeTimeRangeBought('month')" :class="{'v-btn--active': selectedTimeRangeBought === 'month'}"> <!-- <v-btn variant="outlined" small @click="changeTimeRangeBought('month')" :class="{'v-btn&#45;&#45;active': selectedTimeRangeBought === 'month'}">-->
<v-icon left>mdi-calendar-month</v-icon> Mois <!-- <v-icon left>mdi-calendar-month</v-icon> Mois-->
</v-btn> <!-- </v-btn>-->
</div> <!-- </div>-->
</div> <!-- </div>-->
<!-- Liste des vidéos les plus achetées --> <!-- Liste des vidéos les plus achetées -->
<div class="flex flex-row"> <!-- <div class="flex flex-row">-->
<div class="relative overflow-hidden"> <!-- <div class="relative overflow-hidden">-->
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 mb-8"> <!-- <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 mb-8">-->
<ExplorerCard <!-- <ExplorerCard-->
v-for="(video, index) in mostBoughtVideos.slice(currentRangeBought, currentRangeBought + videosPerRowBought)" <!-- v-for="(video, index) in mostBoughtVideos.slice(currentRangeBought, currentRangeBought + videosPerRowBought)"-->
:key="video.id" <!-- :key="video.id"-->
:video="video" <!-- :video="video"-->
/> <!-- />-->
</div> <!-- </div>-->
</div> <!-- </div>-->
<div class="flex flex-col justify-center px-2"> <!-- <div class="flex flex-col justify-center px-2">-->
<!-- Bouton pour naviguer vers l'ensemble précédent de vidéos (Most Bought) --> <!-- &lt;!&ndash; Bouton pour naviguer vers l'ensemble précédent de vidéos (Most Bought) &ndash;&gt;-->
<v-btn @click="previousRowBought" :disabled="currentRangeBought === 0" class="mb-2"> <!-- <v-btn @click="previousRowBought" :disabled="currentRangeBought === 0" class="mb-2">-->
<v-icon>mdi-arrow-up-circle-outline</v-icon> <!-- <v-icon>mdi-arrow-up-circle-outline</v-icon>-->
</v-btn> <!-- </v-btn>-->
<!-- Bouton pour naviguer vers l'ensemble suivant de vidéos (Most Bought) --> <!-- &lt;!&ndash; Bouton pour naviguer vers l'ensemble suivant de vidéos (Most Bought) &ndash;&gt;-->
<v-btn @click="nextRowBought" :disabled="currentRangeBought + videosPerRowBought.value >= mostBoughtVideos.length"> <!-- <v-btn @click="nextRowBought" :disabled="currentRangeBought + videosPerRowBought.value >= mostBoughtVideos.length">-->
<v-icon>mdi-arrow-down-circle-outline</v-icon> <!-- <v-icon>mdi-arrow-down-circle-outline</v-icon>-->
</v-btn> <!-- </v-btn>-->
</div> <!-- </div>-->
</div> <!-- </div>-->
<!-- Chevron pour basculer entre l'affichage de 4 et 8 vidéos (Most Bought) --> <!-- &lt;!&ndash; Chevron pour basculer entre l'affichage de 4 et 8 vidéos (Most Bought) &ndash;&gt;-->
<div class="flex justify-center mt-4"> <!-- <div class="flex justify-center mt-4">-->
<v-btn icon @click="toggleVideoDisplayBought"> <!-- <v-btn icon @click="toggleVideoDisplayBought">-->
<v-icon>{{ chevronIconBought }}</v-icon> <!-- <v-icon>{{ chevronIconBought }}</v-icon>-->
</v-btn> <!-- </v-btn>-->
</div> <!-- </div>-->
</div> </div>
</template> </template>

View File

@@ -21,7 +21,7 @@ const updateScreenSize = () => {
const fetchContents = async ({done}) => { const fetchContents = async ({done}) => {
try { try {
let uri = `/api/contents/all/?page_size=${pageSize.value}`; let uri = `/api/contents/followed/?page_size=${pageSize.value}`;
if (last_id !== null) uri = uri + `&last_id=${last_id}` if (last_id !== null) uri = uri + `&last_id=${last_id}`
const response = await client.get(uri); const response = await client.get(uri);