'use client' import React, { useEffect, useState } from 'react' import { useRouter } from 'next/navigation' import { useSnapshot } from 'valtio' import { useTranslations } from 'next-intl' import clonedeep from 'lodash.clonedeep' import DOMPurify from 'dompurify' import Button from '~components/common/Button' import SegmentedControl from '~components/common/SegmentedControl' import Segment from '~components/common/Segment' import GridRepCollection from '~components/reps/GridRepCollection' import GridRep from '~components/reps/GridRep' import RemixTeamAlert from '~components/dialogs/RemixTeamAlert' import RemixedToast from '~components/toasts/RemixedToast' import EditPartyModal from '../EditPartyModal' import api from '~utils/api' import { appState } from '~utils/appState' import { youtube } from '~utils/youtube' import type { DetailsObject } from '~types' import RemixIcon from '~public/icons/Remix.svg' import EditIcon from '~public/icons/Edit.svg' import styles from './index.module.scss' import Editor from '~components/common/Editor' // Props interface Props { party?: Party new: boolean editable: boolean raidGroups: RaidGroup[] remixCallback: () => void updateCallback: (details: DetailsObject) => Promise } const PartyFooter = (props: Props) => { const t = useTranslations('common') const router = useRouter() const { party: partySnapshot } = useSnapshot(appState) const youtubeUrlRegex = /(?:https:\/\/www\.youtube\.com\/watch\?v=|https:\/\/youtu\.be\/)([\w-]+)/g // State: Component const [currentSegment, setCurrentSegment] = useState(0) const [detailsOpen, setDetailsOpen] = useState(false) const [remixAlertOpen, setRemixAlertOpen] = useState(false) const [remixToastOpen, setRemixToastOpen] = useState(false) // State: Data const [remixes, setRemixes] = useState([]) const [sanitizedDescription, setSanitizedDescription] = useState('') useEffect(() => { if (partySnapshot.description) { const purified = DOMPurify.sanitize(partySnapshot.description) setSanitizedDescription(purified) } else { setSanitizedDescription('') } }, [partySnapshot.description]) // Extract the video IDs from the description // const videoIds = extractYoutubeVideoIds(partySnapshot.description) // Fetch the video titles for each ID // const fetchPromises = videoIds.map(({ id }) => fetchYoutubeData(id)) // // Wait for all the video titles to be fetched // Promise.all(fetchPromises).then((videoTitles) => { // // Replace the video URLs in the description with LiteYoutubeEmbed elements // const newDescription = reactStringReplace( // partySnapshot.description, // youtubeUrlRegex, // (match, i) => ( // // ) // ) // Update the state with the new description async function fetchYoutubeData(videoId: string) { return await youtube .getVideoById(videoId, { maxResults: 1 }) .then((data) => data.items[0].snippet.localized.title) } // Methods: Navigation function goTo(shortcode?: string) { if (shortcode) router.push(`/p/${shortcode}`) } function extractYoutubeVideoIds(text: string) { // Initialize an array to store the video IDs const videoIds = [] // Use the regular expression to find all the Youtube URLs in the text let match while ((match = youtubeUrlRegex.exec(text)) !== null) { // Extract the video ID from the URL const videoId = match[1] // Add the video ID to the array, along with the character position of the URL videoIds.push({ id: videoId, url: match[0], position: match.index, }) } // Return the array of video IDs return videoIds } // Methods: Favorites function toggleFavorite(teamId: string, favorited: boolean) { if (favorited) unsaveFavorite(teamId) else saveFavorite(teamId) } function saveFavorite(teamId: string) { api.saveTeam({ id: teamId }).then((response) => { if (response.status == 201) { const index = remixes.findIndex((p) => p.id === teamId) const party = remixes[index] party.favorited = true let clonedParties = clonedeep(remixes) clonedParties[index] = party setRemixes(clonedParties) } }) } function unsaveFavorite(teamId: string) { api.unsaveTeam({ id: teamId }).then((response) => { if (response.status == 200) { const index = remixes.findIndex((p) => p.id === teamId) const party = remixes[index] party.favorited = false let clonedParties = clonedeep(remixes) clonedParties[index] = party setRemixes(clonedParties) } }) } // Actions: Edit info function handleDetailsOpenChange(open: boolean) { setDetailsOpen(open) } // Actions: Remix team function remixTeamCallback() { setRemixToastOpen(true) props.remixCallback() } // Alerts: Remix team function openRemixTeamAlert() { setRemixAlertOpen(true) } function handleRemixTeamAlertChange(open: boolean) { setRemixAlertOpen(open) } // Toasts: Remix team function handleRemixToastOpenChanged(open: boolean) { setRemixToastOpen(!open) } function handleRemixToastCloseClicked() { setRemixToastOpen(false) } const segmentedControl = ( setCurrentSegment(0)} > {t('footer.description.label')} setCurrentSegment(1)} > {t('footer.remixes.label', { count: partySnapshot?.remixes?.length })} ) const descriptionSection = ( <> {props.party && props.party.description && props.party.description.length > 0 && ( )} {(!partySnapshot || !partySnapshot.description) && (

{t('footer.description.empty')}

{props.editable && (
)} ) const remixesSection = (
{partySnapshot?.remixes?.length > 0 && ( {renderRemixes()} )} {partySnapshot?.remixes?.length === 0 && (

{t('footer.remixes.empty')}

)}
) function renderRemixes() { return partySnapshot?.remixes.map((party, i) => { return ( ) }) } return ( <>
{segmentedControl} {currentSegment === 0 && descriptionSection} {currentSegment === 1 && remixesSection}
) } export default PartyFooter