Source: react/flashcardShare.js

import React, { useState, useEffect } from 'react';
import { Button, TextField, Typography, List, ListItem, IconButton, Avatar, ThemeProvider, createTheme } from '@mui/material';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import SendIcon from '@mui/icons-material/Send';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import { useParams } from 'react-router-dom';
import FlashcardRepo from '../repositories/FlashcardRepo';
import { useNavigate } from "react-router-dom";
/**
 * @class FlashcardShare
 * @classdesc FlashcardShare - A functional React component for displaying flashcards in a shareable format.
 * It includes functionalities like viewing flashcards, flipping cards, navigating between cards,
 * and saving cards to user's collection.
 * 
 * @returns {React.Component} A component displaying flashcards and associated actions.
 */
function FlashcardShare() {
    const { setId, flashcardId } = useParams();
    const [cards, setCards] = useState([]);
    const [selectedCard, setSelectedCard] = useState(null);
    const [isFlipped, setIsFlipped] = useState(false);
    const [comment, setComment] = useState('');
    const [comments, setComments] = useState([]);
    const [userImage, setUserImage] = useState(null);
    const userId = FlashcardRepo.getCurrentUid();
    const navigate = useNavigate();
    console.log("flashcard", flashcardId)
    /**
      * @memberof FlashcardShare
      * @function useEffect
      * @description useEffect hook for fetching flashcards from the repository when the component mounts.
      */
    useEffect(() => {
        const fetchFlashcards = async () => {
            try {
                const flashcardData = await FlashcardRepo.getFlashcardItems(flashcardId);
                const flashcardsArray = Object.keys(flashcardData).map(key => {
                    return {
                        term: flashcardData[key].term,
                        definition: flashcardData[key].definition,
                        flashcardId: key,
                    };
                });
                setCards(flashcardsArray);
            } catch (error) {
                console.error("Failed to fetch flashcards:", error);
            }
        };
        const fetchComments = async () => {
            try {
                const commentsData = await FlashcardRepo.getCommentsWithUserData(flashcardId);
                console.log("fetching comments", commentsData);

                // Convert Firebase Timestamp to Date objects
                const formattedComments = commentsData.map(comment => ({
                    ...comment,
                    date: comment.date.toDate()  // This converts the Timestamp to a Date object
                }));

                setComments(formattedComments);
            } catch (error) {
                console.error("Failed to fetch comments:", error);
            }
        };

        const fetchCurrentUserImage = async () => {
            const uid = await FlashcardRepo.getCurrentUid();
            console.log("uid", uid);
            try {

                const currentUserImg = await FlashcardRepo.getUserImageURLByUid(userId);

                setUserImage(currentUserImg);
            } catch (error) {
                console.error("Error fetching current user image:", error);
            }
        };
        fetchComments();
        fetchCurrentUserImage();
        fetchFlashcards();
    }, [setId]);

    const fetchComments = async () => {
        try {
            const commentsData = await FlashcardRepo.getCommentsWithUserData(flashcardId);
            console.log("fetching comments", commentsData);

            // Convert Firebase Timestamp to Date objects
            const formattedComments = commentsData.map(comment => ({
                ...comment,
                date: comment.date.toDate()  // This converts the Timestamp to a Date object
            }));

            setComments(formattedComments);
        } catch (error) {
            console.error("Failed to fetch comments:", error);
        }
    };

    const handleSendComment = async () => {
        if (comment) {
            try {
                const newComment = {
                    content: comment,
                    uid: userId,
                    date: new Date(),
                };
                await FlashcardRepo.addComment(flashcardId, newComment);

                setComment("");
                await fetchComments();
            } catch (error) {
                console.error("Failed to send comment:", error);
            }
        }
    };
    /**
       * @memberof FlashcardShare
       * @function selectCard
       * @description Selects a flashcard to display.
       * @param {Object} card - The flashcard object to be displayed.
       */
    const selectCard = (card) => {
        setSelectedCard(card);
    };
    /**
       * @memberof FlashcardShare
       * @function handleNextCard
       * @description Navigates to the next flashcard.
       */
    const handleNextCard = () => {
        const currentIndex = cards.indexOf(selectedCard);
        if (currentIndex < cards.length - 1) {
            setSelectedCard(cards[currentIndex + 1]);
        }
    };
    /**
       * @memberof FlashcardShare
       * @function handlePrevCard
       * @description Navigates to the previous flashcard.
       */
    const handlePrevCard = () => {
        const currentIndex = cards.indexOf(selectedCard);
        if (currentIndex > 0) {
            setSelectedCard(cards[currentIndex - 1]);
        }
    };
    /**
       * @memberof FlashcardShare
       * @function toggleFlip
       * @description Toggles the flip state of the flashcard.
       */
    const toggleFlip = () => {
        setIsFlipped(!isFlipped);
    };
    /**
  * @memberof FlashcardShare
  * @function handleSaveToMyFlashcards
  * @description Saves the flashcard set to the user's collection.
  */
    const handleSaveToMyFlashcards = async () => {
        if (flashcardId) {
            try {
                const newFlashcardSetId = await FlashcardRepo.copyFlashcards(flashcardId, userId);
                navigate(`/flashcard-ui/${newFlashcardSetId}`);
                console.log("New flashcard set created with ID:", newFlashcardSetId);
            } catch (error) {
                console.error("Error saving to my flashcards:", error);
            }
        }
    };
    const theme = createTheme({
        palette: {
            primary: { main: '#007aff' },
            secondary: { main: '#ff2d55' },
        },
        typography: {
            fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif",
        },
    });

    return (
        <ThemeProvider theme={theme}>
            <div style={{
                display: "flex", flexDirection: "column", height: "100vh",
                backgroundColor: '#f9f9f9', padding: '20px'
            }}>
                <div style={{ flex: 1, display: "flex", flexDirection: "row", justifyContent: "space-between", marginBottom: '20px' }}>
                    <List style={{
                        width: "30%", borderRight: "1px solid #e0e0e0",
                        borderRadius: '8px', overflow: 'hidden', boxShadow: '0px 0px 15px rgba(0,0,0,0.1)'
                    }}>
                        {cards.map((card, index) => (
                            <ListItem button key={index} onClick={() => selectCard(card)}>
                                {card.term}
                            </ListItem>
                        ))}
                    </List>

                    <div style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", marginLeft: '20px' }}>
                        <Typography variant="h6">
                            {selectedCard ? `${cards.indexOf(selectedCard) + 1}/${cards.length}` : ""}
                        </Typography>
                        <div style={{
                            display: "flex", alignItems: "center", width: "80%", justifyContent: "space-between",
                            marginTop: '20px', borderRadius: '8px', padding: '10px', backgroundColor: '#fff', boxShadow: '0px 0px 15px rgba(0,0,0,0.1)'
                        }}>
                            <IconButton onClick={handlePrevCard}>
                                <ArrowBackIcon />
                            </IconButton>
                            <div
                                style={{
                                    flex: 1,
                                    height: "150px",
                                    border: "1px solid #e0e0e0",
                                    borderRadius: '8px',
                                    transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
                                    transition: 'transform 0.6s',
                                    transformStyle: 'preserve-3d',
                                    position: 'relative'
                                }}
                                onClick={toggleFlip}
                            >

                                <div
                                    style={{
                                        position: 'absolute',
                                        width: '100%',
                                        height: '100%',
                                        display: 'flex',
                                        justifyContent: 'center',
                                        alignItems: 'center',
                                        backfaceVisibility: 'hidden',
                                    }}
                                >
                                    {selectedCard && !isFlipped && selectedCard.term}
                                </div>

                                <div
                                    style={{
                                        position: 'absolute',
                                        width: '100%',
                                        height: '100%',
                                        display: 'flex',
                                        justifyContent: 'center',
                                        alignItems: 'center',
                                        backfaceVisibility: 'hidden',
                                        transform: 'rotateY(180deg)'
                                    }}
                                >
                                    {selectedCard && isFlipped && selectedCard.definition}
                                </div>
                            </div>
                            <IconButton onClick={handleNextCard}>
                                <ArrowForwardIcon />
                            </IconButton>
                        </div>
                        <Button
                            variant="outlined"
                            style={{
                                marginTop: '10px',
                                backgroundColor: '#4f97e0',
                                color: 'white'
                            }}
                            onClick={handleSaveToMyFlashcards}
                        >
                            save to my flashcard
                        </Button>
                    </div>
                </div>

                <div style={{ flex: 1, overflowY: 'auto', maxHeight: 'calc(30% - 60px)', backgroundColor: '#fff', borderRadius: '8px', padding: '10px', boxShadow: '0px 0px 15px rgba(0,0,0,0.1)' }}>
                    {comments.map((comment, index) => (
                        <div key={index} style={{
                            display: "flex", alignItems: "center", justifyContent: "space-between", padding: "10px", borderBottom: '1px solid #e0e0e0'
                        }}>
                            <div style={{ display: 'flex', alignItems: 'center' }}>
                                <Avatar src={comment.imageURL} />
                                <Typography variant="body1" style={{ marginLeft: "10px", fontWeight: 'bold' }}>
                                    {comment.username}
                                </Typography>
                                <Typography variant="body1" style={{ marginLeft: "10px" }}>
                                    {comment.content}
                                </Typography>
                            </div>
                            <div style={{ display: 'flex', alignItems: 'center' }}>
                                <Typography variant="body2" style={{ marginRight: "10px" }}>
                                    {comment.date.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}
                                </Typography>

                            </div>
                        </div>
                    ))}
                </div>
                <div style={{ height: '60px', backgroundColor: '#fff', borderRadius: '8px', padding: '10px', boxShadow: '0px 0px 15px rgba(0,0,0,0.1)' }}>
                    <div style={{ display: "flex", alignItems: "center", }}>
                        <Avatar src={userImage} />
                        <TextField fullWidth label="Add a comment" variant="outlined" value={comment} onChange={(e) => setComment(e.target.value)} />
                        <IconButton onClick={handleSendComment}>
                            <SendIcon />
                        </IconButton>
                    </div>
                </div>

            </div>

        </ThemeProvider>
    );
}

export default FlashcardShare;