Add functionality to PartyFooter buttons
The "Edit info" and "Remix" buttons now have their proper functionality in PartyFooter, matching how they behave in PartyHeader
This commit is contained in:
parent
f14e90acfc
commit
422f1b7818
1 changed files with 75 additions and 19 deletions
|
|
@ -14,6 +14,9 @@ import SegmentedControl from '~components/common/SegmentedControl'
|
||||||
import Segment from '~components/common/Segment'
|
import Segment from '~components/common/Segment'
|
||||||
import GridRepCollection from '~components/GridRepCollection'
|
import GridRepCollection from '~components/GridRepCollection'
|
||||||
import GridRep from '~components/GridRep'
|
import GridRep from '~components/GridRep'
|
||||||
|
import RemixTeamAlert from '~components/dialogs/RemixTeamAlert'
|
||||||
|
import RemixedToast from '~components/toasts/RemixedToast'
|
||||||
|
import EditPartyModal from '../EditPartyModal'
|
||||||
|
|
||||||
import api from '~utils/api'
|
import api from '~utils/api'
|
||||||
import { appState } from '~utils/appState'
|
import { appState } from '~utils/appState'
|
||||||
|
|
@ -30,6 +33,7 @@ interface Props {
|
||||||
party?: Party
|
party?: Party
|
||||||
new: boolean
|
new: boolean
|
||||||
editable: boolean
|
editable: boolean
|
||||||
|
remixCallback: () => void
|
||||||
updateCallback: (details: DetailsObject) => void
|
updateCallback: (details: DetailsObject) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,13 +41,15 @@ const PartyFooter = (props: Props) => {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const { party } = useSnapshot(appState)
|
const { party: partySnapshot } = useSnapshot(appState)
|
||||||
|
|
||||||
const youtubeUrlRegex =
|
const youtubeUrlRegex =
|
||||||
/(?:https:\/\/www\.youtube\.com\/watch\?v=|https:\/\/youtu\.be\/)([\w-]+)/g
|
/(?:https:\/\/www\.youtube\.com\/watch\?v=|https:\/\/youtu\.be\/)([\w-]+)/g
|
||||||
|
|
||||||
// State: UI
|
// State: Component
|
||||||
const [currentSegment, setCurrentSegment] = useState(0)
|
const [currentSegment, setCurrentSegment] = useState(0)
|
||||||
|
const [remixAlertOpen, setRemixAlertOpen] = useState(false)
|
||||||
|
const [remixToastOpen, setRemixToastOpen] = useState(false)
|
||||||
|
|
||||||
// State: Data
|
// State: Data
|
||||||
const [remixes, setRemixes] = useState<Party[]>([])
|
const [remixes, setRemixes] = useState<Party[]>([])
|
||||||
|
|
@ -52,8 +58,8 @@ const PartyFooter = (props: Props) => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Extract the video IDs from the description
|
// Extract the video IDs from the description
|
||||||
if (party.description) {
|
if (partySnapshot.description) {
|
||||||
const videoIds = extractYoutubeVideoIds(party.description)
|
const videoIds = extractYoutubeVideoIds(partySnapshot.description)
|
||||||
|
|
||||||
// Fetch the video titles for each ID
|
// Fetch the video titles for each ID
|
||||||
const fetchPromises = videoIds.map(({ id }) => fetchYoutubeData(id))
|
const fetchPromises = videoIds.map(({ id }) => fetchYoutubeData(id))
|
||||||
|
|
@ -62,7 +68,7 @@ const PartyFooter = (props: Props) => {
|
||||||
Promise.all(fetchPromises).then((videoTitles) => {
|
Promise.all(fetchPromises).then((videoTitles) => {
|
||||||
// Replace the video URLs in the description with LiteYoutubeEmbed elements
|
// Replace the video URLs in the description with LiteYoutubeEmbed elements
|
||||||
const newDescription = reactStringReplace(
|
const newDescription = reactStringReplace(
|
||||||
party.description,
|
partySnapshot.description,
|
||||||
youtubeUrlRegex,
|
youtubeUrlRegex,
|
||||||
(match, i) => (
|
(match, i) => (
|
||||||
<LiteYouTubeEmbed
|
<LiteYouTubeEmbed
|
||||||
|
|
@ -81,7 +87,7 @@ const PartyFooter = (props: Props) => {
|
||||||
} else {
|
} else {
|
||||||
setEmbeddedDescription('')
|
setEmbeddedDescription('')
|
||||||
}
|
}
|
||||||
}, [party.description])
|
}, [partySnapshot.description])
|
||||||
|
|
||||||
async function fetchYoutubeData(videoId: string) {
|
async function fetchYoutubeData(videoId: string) {
|
||||||
return await youtube
|
return await youtube
|
||||||
|
|
@ -154,6 +160,30 @@ const PartyFooter = (props: Props) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 = (
|
const segmentedControl = (
|
||||||
<SegmentedControl className="background">
|
<SegmentedControl className="background">
|
||||||
<Segment
|
<Segment
|
||||||
|
|
@ -170,24 +200,31 @@ const PartyFooter = (props: Props) => {
|
||||||
selected={currentSegment === 1}
|
selected={currentSegment === 1}
|
||||||
onClick={() => setCurrentSegment(1)}
|
onClick={() => setCurrentSegment(1)}
|
||||||
>
|
>
|
||||||
{t('footer.remixes.label', { count: party?.remixes?.length })}
|
{t('footer.remixes.label', { count: partySnapshot?.remixes?.length })}
|
||||||
</Segment>
|
</Segment>
|
||||||
</SegmentedControl>
|
</SegmentedControl>
|
||||||
)
|
)
|
||||||
|
|
||||||
const descriptionSection = (
|
const descriptionSection = (
|
||||||
<section className={styles.description}>
|
<section className={styles.description}>
|
||||||
{party && party.description && party.description.length > 0 && (
|
{partySnapshot &&
|
||||||
|
partySnapshot.description &&
|
||||||
|
partySnapshot.description.length > 0 && (
|
||||||
<Linkify>{embeddedDescription}</Linkify>
|
<Linkify>{embeddedDescription}</Linkify>
|
||||||
)}
|
)}
|
||||||
{(!party || !party.description) && (
|
{(!partySnapshot || !partySnapshot.description) && (
|
||||||
<div className={styles.noDescription}>
|
<div className={styles.noDescription}>
|
||||||
<h3>{t('footer.description.empty')}</h3>
|
<h3>{t('footer.description.empty')}</h3>
|
||||||
{props.editable && (
|
{props.editable && (
|
||||||
|
<EditPartyModal
|
||||||
|
party={props.party}
|
||||||
|
updateCallback={props.updateCallback}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
leftAccessoryIcon={<EditIcon />}
|
leftAccessoryIcon={<EditIcon />}
|
||||||
text={t('buttons.show_info')}
|
text={t('buttons.show_info')}
|
||||||
/>
|
/>
|
||||||
|
</EditPartyModal>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -196,20 +233,24 @@ const PartyFooter = (props: Props) => {
|
||||||
|
|
||||||
const remixesSection = (
|
const remixesSection = (
|
||||||
<section className={styles.remixes}>
|
<section className={styles.remixes}>
|
||||||
{party?.remixes?.length > 0 && (
|
{partySnapshot?.remixes?.length > 0 && (
|
||||||
<GridRepCollection>{renderRemixes()}</GridRepCollection>
|
<GridRepCollection>{renderRemixes()}</GridRepCollection>
|
||||||
)}
|
)}
|
||||||
{party?.remixes?.length === 0 && (
|
{partySnapshot?.remixes?.length === 0 && (
|
||||||
<div className={styles.noRemixes}>
|
<div className={styles.noRemixes}>
|
||||||
<h3>{t('footer.remixes.empty')}</h3>
|
<h3>{t('footer.remixes.empty')}</h3>
|
||||||
<Button leftAccessoryIcon={<RemixIcon />} text={t('buttons.remix')} />
|
<Button
|
||||||
|
leftAccessoryIcon={<RemixIcon />}
|
||||||
|
text={t('buttons.remix')}
|
||||||
|
onClick={openRemixTeamAlert}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|
||||||
function renderRemixes() {
|
function renderRemixes() {
|
||||||
return party?.remixes.map((party, i) => {
|
return partySnapshot?.remixes.map((party, i) => {
|
||||||
return (
|
return (
|
||||||
<GridRep
|
<GridRep
|
||||||
id={party.id}
|
id={party.id}
|
||||||
|
|
@ -237,6 +278,21 @@ const PartyFooter = (props: Props) => {
|
||||||
{currentSegment === 0 && descriptionSection}
|
{currentSegment === 0 && descriptionSection}
|
||||||
{currentSegment === 1 && remixesSection}
|
{currentSegment === 1 && remixesSection}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<RemixTeamAlert
|
||||||
|
creator={props.editable}
|
||||||
|
name={partySnapshot.name ? partySnapshot.name : t('no_title')}
|
||||||
|
open={remixAlertOpen}
|
||||||
|
onOpenChange={handleRemixTeamAlertChange}
|
||||||
|
remixCallback={remixTeamCallback}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<RemixedToast
|
||||||
|
open={remixToastOpen}
|
||||||
|
partyName={props.party?.name || t('no_title')}
|
||||||
|
onOpenChange={handleRemixToastOpenChanged}
|
||||||
|
onCloseClick={handleRemixToastCloseClicked}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue