2022-11-26 13:15:58 -08:00
|
|
|
import React, { useCallback, useState } from 'react';
|
|
|
|
import { Link } from 'react-router-dom';
|
|
|
|
import ReactSwipeableViews from 'react-swipeable-views';
|
|
|
|
|
|
|
|
import EventPreview from 'soapbox/components/event-preview';
|
|
|
|
import { Card, Icon } from 'soapbox/components/ui';
|
|
|
|
import { useAppSelector } from 'soapbox/hooks';
|
|
|
|
import { makeGetStatus } from 'soapbox/selectors';
|
|
|
|
|
|
|
|
import PlaceholderEventPreview from '../../placeholder/components/placeholder-event-preview';
|
|
|
|
|
|
|
|
import type { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
|
|
|
|
|
|
|
const Event = ({ id }: { id: string }) => {
|
|
|
|
const getStatus = useCallback(makeGetStatus(), []);
|
|
|
|
const status = useAppSelector(state => getStatus(state, { id }));
|
|
|
|
|
|
|
|
if (!status) return null;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Link
|
|
|
|
className='w-full px-1'
|
|
|
|
to={`/@${status.getIn(['account', 'acct'])}/events/${status.id}`}
|
|
|
|
>
|
2022-11-27 14:29:45 -08:00
|
|
|
<EventPreview status={status} floatingAction={false} />
|
2022-11-26 13:15:58 -08:00
|
|
|
</Link>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
interface IEventCarousel {
|
|
|
|
statusIds: ImmutableOrderedSet<string>
|
|
|
|
isLoading?: boolean | null
|
|
|
|
emptyMessage: React.ReactNode
|
|
|
|
}
|
|
|
|
|
|
|
|
const EventCarousel: React.FC<IEventCarousel> = ({ statusIds, isLoading, emptyMessage }) => {
|
|
|
|
const [index, setIndex] = useState(0);
|
|
|
|
|
|
|
|
const handleChangeIndex = (index: number) => {
|
|
|
|
setIndex(index % statusIds.size);
|
|
|
|
};
|
|
|
|
|
|
|
|
if (statusIds.size === 0) {
|
2022-11-27 15:46:32 -08:00
|
|
|
if (isLoading) {
|
|
|
|
return <PlaceholderEventPreview />;
|
|
|
|
}
|
|
|
|
|
2022-11-26 13:15:58 -08:00
|
|
|
return (
|
|
|
|
<Card variant='rounded' size='lg'>
|
|
|
|
{emptyMessage}
|
|
|
|
</Card>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<div className='relative -mx-1'>
|
|
|
|
{index !== 0 && (
|
2023-02-01 14:13:42 -08:00
|
|
|
<div className='absolute left-3 top-1/2 z-10 -mt-4'>
|
2022-11-26 13:15:58 -08:00
|
|
|
<button
|
|
|
|
onClick={() => handleChangeIndex(index - 1)}
|
2023-02-01 14:13:42 -08:00
|
|
|
className='flex h-8 w-8 items-center justify-center rounded-full bg-white/50 backdrop-blur dark:bg-gray-900/50'
|
2022-11-26 13:15:58 -08:00
|
|
|
>
|
2023-02-01 14:13:42 -08:00
|
|
|
<Icon src={require('@tabler/icons/chevron-left.svg')} className='h-6 w-6 text-black dark:text-white' />
|
2022-11-26 13:15:58 -08:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
<ReactSwipeableViews animateHeight index={index} onChangeIndex={handleChangeIndex}>
|
|
|
|
{statusIds.map(statusId => <Event key={statusId} id={statusId} />)}
|
|
|
|
</ReactSwipeableViews>
|
|
|
|
{index !== statusIds.size - 1 && (
|
2023-02-01 14:13:42 -08:00
|
|
|
<div className='absolute right-3 top-1/2 z-10 -mt-4'>
|
2022-11-26 13:15:58 -08:00
|
|
|
<button
|
|
|
|
onClick={() => handleChangeIndex(index + 1)}
|
2023-02-01 14:13:42 -08:00
|
|
|
className='flex h-8 w-8 items-center justify-center rounded-full bg-white/50 backdrop-blur dark:bg-gray-900/50'
|
2022-11-26 13:15:58 -08:00
|
|
|
>
|
2023-02-01 14:13:42 -08:00
|
|
|
<Icon src={require('@tabler/icons/chevron-right.svg')} className='h-6 w-6 text-black dark:text-white' />
|
2022-11-26 13:15:58 -08:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default EventCarousel;
|