From e57910d274a4f03039b4595a523fcf45e11812db Mon Sep 17 00:00:00 2001 From: Movix <178902026+MysticSaba-max@users.noreply.github.com> Date: Sun, 10 May 2026 16:39:13 +0200 Subject: [PATCH] =?UTF-8?q?j'ai=20oubli=C3=A9=20de=20supprim=C3=A9=20les?= =?UTF-8?q?=20fichiers=20code=20morts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/AdminLogin.tsx | 252 ------------- src/components/CommentItem.tsx | 557 ---------------------------- src/components/CommentSection.tsx | 423 --------------------- src/components/ReactionBar.tsx | 106 ------ src/config/firebase.ts | 42 --- src/services/adminService.ts | 191 ---------- src/services/commentService.ts | 396 -------------------- src/services/logService.ts | 119 ------ src/services/notificationService.ts | 260 ------------- src/types/Comment.ts | 43 --- 10 files changed, 2389 deletions(-) delete mode 100644 src/components/AdminLogin.tsx delete mode 100644 src/components/CommentItem.tsx delete mode 100644 src/components/CommentSection.tsx delete mode 100644 src/components/ReactionBar.tsx delete mode 100644 src/config/firebase.ts delete mode 100644 src/services/adminService.ts delete mode 100644 src/services/commentService.ts delete mode 100644 src/services/logService.ts delete mode 100644 src/services/notificationService.ts delete mode 100644 src/types/Comment.ts diff --git a/src/components/AdminLogin.tsx b/src/components/AdminLogin.tsx deleted file mode 100644 index ce6d149..0000000 --- a/src/components/AdminLogin.tsx +++ /dev/null @@ -1,252 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { useTranslation } from 'react-i18next'; -import { verifyAdminCode, isAdminAuthenticated, logoutAdmin } from '../services/adminService'; -import { Lock, Unlock, LogOut } from 'lucide-react'; -import { checkDiscordMembership } from '../utils/discord'; -import { DISCORD_CONFIG } from '../config/discord'; - -interface AdminLoginProps { - onAdminStatusChange?: (isAdmin: boolean) => void; -} - -const AdminLogin: React.FC = ({ onAdminStatusChange }) => { - const { t } = useTranslation(); - const [isOpen, setIsOpen] = useState(false); - const [adminCode, setAdminCode] = useState(''); - const [isAdmin, setIsAdmin] = useState(false); - const [isLoading, setIsLoading] = useState(false); - const [isLoggingOut, setIsLoggingOut] = useState(false); - const [error, setError] = useState(''); - - // Check if user is already authenticated as admin - useEffect(() => { - // Ignorer la vérification si on est en train de se déconnecter - if (isLoggingOut) return; - - const checkAdminStatus = async () => { - console.log("Vérification du statut admin au chargement"); - - // Check if authenticated via Discord - const isDiscordAuth = localStorage.getItem('discord_auth') === 'true'; - if (isDiscordAuth) { - try { - const discordUser = JSON.parse(localStorage.getItem('discord_user') || '{}'); - - // Si l'utilisateur est déjà identifié comme admin via Discord, conserver son statut - if (discordUser.isAdmin) { - console.log("User is already admin via Discord role (cached)"); - setIsAdmin(true); - if (onAdminStatusChange) { - onAdminStatusChange(true); - } - return; - } - - // Check if we need to refresh the role info - const lastCheck = parseInt(localStorage.getItem('discord_last_check') || '0'); - const now = Date.now(); - const needsRefresh = now - lastCheck > (DISCORD_CONFIG.CACHE_DURATION * 1000); - - if (needsRefresh) { - console.log("Refreshing Discord roles..."); - const accessToken = localStorage.getItem('discord_token'); - if (accessToken) { - const membershipData = await checkDiscordMembership(accessToken); - - // Ne pas modifier l'état si on est rate limited et qu'on n'a pas de données valides - if (membershipData.isRateLimited && !membershipData.isAdmin) { - console.log("Rate limited, preserving current admin status"); - return; - } - - const isDiscordAdmin = membershipData.isAdmin; - - // Update the user info in localStorage - const updatedUser = { - ...discordUser, - roles: membershipData.roles, - isAdmin: isDiscordAdmin - }; - localStorage.setItem('discord_user', JSON.stringify(updatedUser)); - localStorage.setItem('discord_last_check', now.toString()); - - if (isDiscordAdmin) { - console.log("User is admin via Discord role (fresh check)"); - setIsAdmin(true); - if (onAdminStatusChange) { - onAdminStatusChange(true); - } - return; - } - } - } - } catch (error) { - console.error("Error checking Discord admin status:", error); - // En cas d'erreur, on conserve le statut admin actuel si l'utilisateur l'était déjà - if (isAdmin) { - console.log("Error during Discord check, preserving admin status"); - return; - } - } - } - - // Fallback to traditional admin authentication - const adminStatus = await isAdminAuthenticated(); - console.log(`Statut admin traditionnel: ${adminStatus}`); - setIsAdmin(adminStatus); - if (onAdminStatusChange) { - onAdminStatusChange(adminStatus); - } - }; - - checkAdminStatus(); - }, [onAdminStatusChange, isLoggingOut, isAdmin]); - - const handleAdminLogin = async () => { - if (!adminCode.trim()) { - setError(t('admin.enterAdminCode')); - return; - } - - setIsLoading(true); - setError(''); - - try { - console.log(`Tentative de connexion avec le code: ${adminCode}`); - const isValid = await verifyAdminCode(adminCode); - console.log(`Résultat de la vérification: ${isValid}`); - - if (isValid) { - setIsAdmin(true); - setIsOpen(false); - setAdminCode(''); - if (onAdminStatusChange) { - onAdminStatusChange(true); - } - } else { - setError(t('admin.invalidAdminCode')); - } - } catch (err) { - console.error('Erreur complète:', err); - setError(t('admin.codeVerificationError')); - } finally { - setIsLoading(false); - } - }; - - const handleLogout = async () => { - setIsLoggingOut(true); - - try { - await logoutAdmin(); - // Attendre un court instant pour s'assurer que le localStorage est bien mis à jour - setTimeout(() => { - setIsAdmin(false); - if (onAdminStatusChange) { - onAdminStatusChange(false); - } - setIsLoggingOut(false); - }, 100); - } catch (error) { - console.error('Erreur lors de la déconnexion:', error); - setIsLoggingOut(false); - } - }; - - const handleKeyPress = (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { - handleAdminLogin(); - } - }; - - // Vérifier si on doit afficher le bouton Admin basé sur les rôles Discord - const shouldShowAdminButton = () => { - // Si déjà authentifié comme admin, on affiche toujours le bouton - if (isAdmin) return true; - - // Vérifier l'authentification Discord - const isDiscordAuth = localStorage.getItem('discord_auth') === 'true'; - if (isDiscordAuth) { - try { - const discordUser = JSON.parse(localStorage.getItem('discord_user') || '{}'); - return discordUser.isAdmin || false; - } catch { - return false; - } - } - - // Si l'utilisateur n'est pas connecté via Discord, ne pas afficher le bouton - return false; - }; - - // Si on ne doit pas afficher le bouton, retourner null - if (!shouldShowAdminButton()) { - return null; - } - - return ( -
- {isAdmin ? ( - - ) : ( - - )} - - {isOpen && !isAdmin && ( -
-

{t('admin.adminLogin')}

-
-
- setAdminCode(e.target.value)} - onKeyPress={handleKeyPress} - placeholder={t('admin.adminCode')} - className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white focus:outline-none focus:ring-2 focus:ring-blue-500" - autoFocus - /> -
- {error &&

{error}

} - -
-
- )} -
- ); -}; - -export default AdminLogin; diff --git a/src/components/CommentItem.tsx b/src/components/CommentItem.tsx deleted file mode 100644 index 1ce02bb..0000000 --- a/src/components/CommentItem.tsx +++ /dev/null @@ -1,557 +0,0 @@ -import React, { useState, useEffect, useRef } from 'react'; -import { useTranslation } from 'react-i18next'; -import { Comment, COMMENT_LENGTH_LIMITS } from '../types/Comment'; -import { ThumbsUp, ThumbsDown, Reply, Trash2, Send, Clock } from 'lucide-react'; -import { likeComment, dislikeComment, deleteComment, addComment, reactWithEmoji } from '../services/commentService'; -import { format } from 'date-fns'; -import { fr } from 'date-fns/locale'; -import EmojiPicker from './EmojiPicker'; -import ReactionBar from './ReactionBar'; -import { addReplyNotification } from '../services/notificationService'; -import ReactMarkdown from 'react-markdown'; -import { safeRemarkGfm } from '../utils/markdownPlugins'; -import remarkEmoji from 'remark-emoji'; -import MarkdownToolbar from './MarkdownToolbar'; - -// Définition de la limite de caractères pour les réponses -const MAX_REPLY_LENGTH = COMMENT_LENGTH_LIMITS.REPLY; - -const markdownComponents = { - p: ({ children }: any) =>

{children}

, - strong: ({ children }: any) => {children}, - em: ({ children }: any) => {children}, - code: ({ children, className }: any) => { - const isBlock = className?.includes('language-'); - return isBlock ? ( -
-        {children}
-      
- ) : ( - {children} - ); - }, - pre: ({ children }: any) => <>{children}, - a: ({ href, children }: any) => ( - - {children} - - ), - ul: ({ children }: any) => , - ol: ({ children }: any) =>
    {children}
, - blockquote: ({ children }: any) => ( -
{children}
- ), - del: ({ children }: any) => {children}, - // Bloquer les images et headings dans les commentaires - img: () => null, - h1: ({ children }: any) =>

{children}

, - h2: ({ children }: any) =>

{children}

, - h3: ({ children }: any) =>

{children}

, - h4: ({ children }: any) =>

{children}

, - h5: ({ children }: any) =>

{children}

, - h6: ({ children }: any) =>

{children}

, -}; - -const remarkPlugins = safeRemarkGfm ? [safeRemarkGfm, remarkEmoji] : [remarkEmoji]; -const REPLY_COOLDOWN_TIME = 15; // Cooldown plus court pour les réponses (15 secondes) - -interface CommentItemProps { - comment: Comment; - currentUserId: string | null; - contentId: string; - contentType: 'movie' | 'series'; - refreshComments: () => void; - isAdmin?: boolean; -} - -const CommentItem: React.FC = ({ - comment, - currentUserId, - contentId, - contentType, - refreshComments, - isAdmin = false -}) => { - const { t } = useTranslation(); - const [isReplying, setIsReplying] = useState(false); - const [replyContent, setReplyContent] = useState(''); - const [isExpanded, setIsExpanded] = useState(false); - const [likeAnimation, setLikeAnimation] = useState(false); - const [dislikeAnimation, setDislikeAnimation] = useState(false); - const [replyCooldown, setReplyCooldown] = useState(0); - const [isLoadingReply, setIsLoadingReply] = useState(false); - const replyTextareaRef = useRef(null); - - // Gérer le cooldown des réponses - useEffect(() => { - if (replyCooldown <= 0) return; - - const timer = setInterval(() => { - setReplyCooldown(prev => Math.max(0, prev - 1)); - }, 1000); - - return () => clearInterval(timer); - }, [replyCooldown]); - - // Vérification du cooldown au chargement - useEffect(() => { - const lastReplyTime = localStorage.getItem('lastReplyTime'); - if (lastReplyTime && !isAdmin) { - const timeElapsed = Math.floor((Date.now() - parseInt(lastReplyTime)) / 1000); - const remainingTime = REPLY_COOLDOWN_TIME - timeElapsed; - if (remainingTime > 0) { - setReplyCooldown(remainingTime); - } - } - }, [isAdmin]); - - const startReplyCooldown = () => { - // Les admins n'ont pas de cooldown - if (isAdmin) return; - - setReplyCooldown(REPLY_COOLDOWN_TIME); - localStorage.setItem('lastReplyTime', Date.now().toString()); - }; - - const handleLike = async () => { - if (!currentUserId) return; - - try { - // Animation effect - setLikeAnimation(true); - setTimeout(() => setLikeAnimation(false), 500); - - await likeComment(comment.id, currentUserId); - refreshComments(); - } catch (error) { - console.error('Error liking comment:', error); - } - }; - - const handleDislike = async () => { - if (!currentUserId) return; - - try { - // Animation effect - setDislikeAnimation(true); - setTimeout(() => setDislikeAnimation(false), 500); - - await dislikeComment(comment.id, currentUserId); - refreshComments(); - } catch (error) { - console.error('Error disliking comment:', error); - } - }; - - const handleDelete = async () => { - if (window.confirm(t('comments.deleteConfirm'))) { - try { - await deleteComment(comment.id, currentUserId || undefined, isAdmin); - refreshComments(); - } catch (error) { - console.error('Error deleting comment:', error); - } - } - }; - - const handleReply = async () => { - if (!currentUserId || !replyContent.trim() || (replyCooldown > 0 && !isAdmin) || isLoadingReply) return; - - try { - setIsLoadingReply(true); - - // Get user details from localStorage - let username = t('comments.defaultUser'); - let userAvatar = 'https://as2.ftcdn.net/v2/jpg/05/89/93/27/1000_F_589932782_vQAEAZhHnq1QCGu5ikwrYaQD0Mmurm0N.webp'; - - const isDiscordAuth = localStorage.getItem('discord_auth') === 'true'; - const isGoogleAuth = localStorage.getItem('google_auth') === 'true'; - - if (isDiscordAuth) { - const userInfoStr = localStorage.getItem('discord_user'); - if (userInfoStr) { - const userInfo = JSON.parse(userInfoStr); - username = userInfo.username; - userAvatar = userInfo.avatar; - } - } else if (isGoogleAuth) { - const userInfoStr = localStorage.getItem('google_user'); - if (userInfoStr) { - const userInfo = JSON.parse(userInfoStr); - username = userInfo.name; - userAvatar = userInfo.picture; - } - } - - // Ajouter le commentaire - const replyId = await addComment( - contentId, - contentType, - currentUserId, - username, - userAvatar, - replyContent, - comment.id, - isAdmin // Transmettre le statut admin - ); - - // Démarrer le cooldown pour les réponses si pas admin - startReplyCooldown(); - - setReplyContent(''); - setIsReplying(false); - - // Mettre à jour les commentaires - refreshComments(); - - // Ajouter une notification - await addReplyNotification( - comment.id, - replyId, - replyContent, - currentUserId, - username - ); - } catch (error) { - console.error('Error adding reply:', error); - } finally { - setIsLoadingReply(false); - } - }; - - const handleEmojiInsert = (emoji: string) => { - setReplyContent(prev => { - if (prev.length + emoji.length <= MAX_REPLY_LENGTH) { - return prev + emoji; - } - return prev; - }); - }; - - const handleReaction = async (emoji: string) => { - if (!currentUserId) return; - - try { - await reactWithEmoji(comment.id, emoji, currentUserId); - refreshComments(); - } catch (error) { - console.error('Error reacting to comment:', error); - } - }; - - const formatDate = (date: Date) => { - try { - // Format différent pour les petits écrans (détecté via CSS media query) - const isMobile = window.innerWidth < 640; - if (isMobile) { - return format(date, 'dd/MM/yy HH:mm', { locale: fr }); - } - return format(date, 'dd MMMM yyyy à HH:mm', { locale: fr }); - } catch (error) { - return t('comments.unknownDate'); - } - }; - - const formatCooldownTime = (seconds: number) => { - if (seconds < 60) { - return `${seconds}s`; - } - const minutes = Math.floor(seconds / 60); - const remainingSeconds = seconds % 60; - return `${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`; - }; - - const isLikedByCurrentUser = currentUserId && comment.likedBy && comment.likedBy.includes(currentUserId); - const isDislikedByCurrentUser = currentUserId && comment.dislikedBy && comment.dislikedBy.includes(currentUserId); - // Un utilisateur peut supprimer son propre commentaire ou si c'est un admin - const canDeleteComment = (currentUserId && currentUserId === comment.userId) || isAdmin; - - return ( -
-
- {comment.username} -
-
-
-

{comment.username}

- {comment.isAdmin && ( - - ADMIN - - )} -
- {formatDate(comment.createdAt)} -
-
- - {comment.content} - -
- - - -
- - - - - {currentUserId && ( - - )} - - {canDeleteComment && ( - - )} -
- - {isReplying && ( -
-
-