initial commit - LeDiscord plateforme des copains

This commit is contained in:
EvanChal
2025-08-21 00:28:21 +02:00
commit b7a84a53aa
93 changed files with 16247 additions and 0 deletions

View File

@@ -0,0 +1,178 @@
<template>
<div class="video-player-container">
<div class="relative">
<!-- Video.js Player -->
<video
ref="videoPlayer"
class="video-js vjs-default-skin vjs-big-play-centered w-full rounded-lg"
controls
preload="auto"
:poster="posterUrl"
data-setup="{}"
>
<source :src="videoUrl" type="video/mp4" />
<p class="vjs-no-js">
Pour voir cette vidéo, activez JavaScript et considérez passer à un navigateur web qui
<a href="https://videojs.com/html5-video-support/" target="_blank">supporte la vidéo HTML5</a>.
</p>
</video>
</div>
<!-- Video Stats -->
<div class="mt-4 flex items-center justify-between text-sm text-gray-600">
<div class="flex items-center space-x-4">
<span class="flex items-center">
<Eye class="w-4 h-4 mr-1" />
{{ viewsCount }} vue{{ viewsCount > 1 ? 's' : '' }}
</span>
<span class="flex items-center">
<Clock class="w-4 h-4 mr-1" />
{{ formatDuration(duration) }}
</span>
</div>
<div class="flex items-center space-x-2">
<button
@click="toggleLike"
class="flex items-center space-x-1 px-3 py-1 rounded-full transition-colors"
:class="isLiked ? 'bg-red-100 text-red-600' : 'bg-gray-100 text-gray-600 hover:bg-gray-200'"
>
<Heart :class="isLiked ? 'fill-current' : ''" class="w-4 h-4" />
<span>{{ likesCount }}</span>
</button>
<button
@click="toggleComments"
class="flex items-center space-x-1 px-3 py-1 rounded-full bg-gray-100 text-gray-600 hover:bg-gray-200 transition-colors"
>
<MessageSquare class="w-4 h-4" />
<span>{{ commentsCount }}</span>
</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, watch, computed } from 'vue'
import videojs from 'video.js'
import 'video.js/dist/video-js.css'
import { Eye, Clock, Heart, MessageSquare } from 'lucide-vue-next'
import { getMediaUrl } from '@/utils/axios'
const props = defineProps({
src: {
type: String,
required: true
},
poster: {
type: String,
default: null
},
title: {
type: String,
default: ''
},
description: {
type: String,
default: ''
},
duration: {
type: Number,
default: 0
},
viewsCount: {
type: Number,
default: 0
},
likesCount: {
type: Number,
default: 0
},
commentsCount: {
type: Number,
default: 0
},
isLiked: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['like', 'toggle-comments'])
const videoPlayer = ref(null)
const player = ref(null)
// Computed properties pour les URLs
const videoUrl = computed(() => getMediaUrl(props.src))
const posterUrl = computed(() => getMediaUrl(props.poster))
function formatDuration(seconds) {
if (!seconds) return '--:--'
const minutes = Math.floor(seconds / 60)
const remainingSeconds = seconds % 60
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
}
function toggleLike() {
emit('like')
}
function toggleComments() {
emit('toggle-comments')
}
onMounted(() => {
if (videoPlayer.value) {
player.value = videojs(videoPlayer.value, {
controls: true,
fluid: true,
responsive: true,
playbackRates: [0.5, 0.75, 1, 1.25, 1.5, 2],
controlBar: {
children: [
'playToggle',
'volumePanel',
'currentTimeDisplay',
'timeDivider',
'durationDisplay',
'progressControl',
'playbackRateMenuButton',
'fullscreenToggle'
]
}
})
// Error handling
player.value.on('error', (error) => {
console.error('Video.js error:', error)
})
}
})
onBeforeUnmount(() => {
if (player.value) {
player.value.dispose()
}
})
// Watch for src changes to reload video
watch(() => props.src, () => {
if (player.value && videoUrl.value) {
player.value.src({ src: videoUrl.value, type: 'video/mp4' })
player.value.load()
}
})
</script>
<style scoped>
.video-js {
aspect-ratio: 16/9;
}
.video-js .vjs-big-play-button {
display: none;
}
</style>