Display event previews
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
eabab437a7
commit
8527384479
|
@ -38,7 +38,8 @@ const Announcement: React.FC<IAnnouncement> = ({ announcement, addReaction, remo
|
||||||
year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'}
|
year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'}
|
||||||
month='short'
|
month='short'
|
||||||
day='2-digit'
|
day='2-digit'
|
||||||
hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'}
|
hour={skipTime ? undefined : '2-digit'}
|
||||||
|
minute={skipTime ? undefined : '2-digit'}
|
||||||
/>
|
/>
|
||||||
{' '}
|
{' '}
|
||||||
-
|
-
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import { FormattedDate, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { useAppSelector } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
import Icon from './icon';
|
||||||
|
import { Button, HStack, Stack, Text } from './ui';
|
||||||
|
import VerificationBadge from './verification_badge';
|
||||||
|
|
||||||
|
import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/types/entities';
|
||||||
|
|
||||||
|
interface IEventPreview {
|
||||||
|
status: StatusEntity,
|
||||||
|
}
|
||||||
|
|
||||||
|
const EventPreview: React.FC<IEventPreview> = ({ status }) => {
|
||||||
|
const me = useAppSelector((state) => state.me);
|
||||||
|
|
||||||
|
const account = status.account as AccountEntity;
|
||||||
|
const event = status.event!;
|
||||||
|
|
||||||
|
const banner = status.media_attachments?.find(({ description }) => description === 'Banner');
|
||||||
|
|
||||||
|
const renderDate = useCallback(() => {
|
||||||
|
if (!event.start_time) return null;
|
||||||
|
|
||||||
|
const startDate = new Date(event.start_time);
|
||||||
|
|
||||||
|
let date;
|
||||||
|
|
||||||
|
if (event.end_time) {
|
||||||
|
const endDate = new Date(event.end_time);
|
||||||
|
|
||||||
|
const sameDay = startDate.getDate() === endDate.getDate() && startDate.getMonth() === endDate.getMonth() && startDate.getFullYear() === endDate.getFullYear();
|
||||||
|
|
||||||
|
if (sameDay) {
|
||||||
|
date = (
|
||||||
|
<>
|
||||||
|
<FormattedDate value={event.start_time} year='2-digit' month='short' day='2-digit' weekday='short' hour='2-digit' minute='2-digit' />
|
||||||
|
{' - '}
|
||||||
|
<FormattedDate value={event.end_time} hour='2-digit' minute='2-digit' />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
date = (
|
||||||
|
<>
|
||||||
|
<FormattedDate value={event.start_time} year='2-digit' month='short' day='2-digit' weekday='short' />
|
||||||
|
{' - '}
|
||||||
|
<FormattedDate value={event.end_time} year='2-digit' month='short' day='2-digit' weekday='short' />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
date = (
|
||||||
|
<FormattedDate value={event.start_time} year='2-digit' month='short' day='2-digit' weekday='short' hour='2-digit' minute='2-digit' />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<HStack alignItems='center' space={1}>
|
||||||
|
<Icon src={require('@tabler/icons/calendar.svg')} />
|
||||||
|
<span>{date}</span>
|
||||||
|
</HStack>
|
||||||
|
);
|
||||||
|
}, [event.start_time, event.end_time]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='rounded-lg bg-gray-100 dark:bg-primary-800 shadow-xl relative overflow-hidden'>
|
||||||
|
<div className='absolute top-28 right-3'>
|
||||||
|
{account.id === me ? (
|
||||||
|
<Button
|
||||||
|
size='sm'
|
||||||
|
theme='secondary'
|
||||||
|
to={`/@${account.acct}/events/${status.id}`}
|
||||||
|
>
|
||||||
|
<FormattedMessage id='event.manage' defaultMessage='Manage' />
|
||||||
|
</Button>
|
||||||
|
) : event.join_state === 'accept' ? (
|
||||||
|
<Button
|
||||||
|
size='sm'
|
||||||
|
theme='secondary'
|
||||||
|
icon={require('@tabler/icons/check.svg')}
|
||||||
|
>
|
||||||
|
<FormattedMessage id='event.join_state.accept' defaultMessage='Going' />
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
size='sm'
|
||||||
|
theme='primary'
|
||||||
|
>
|
||||||
|
<FormattedMessage id='event.join_state.empty' defaultMessage='Participate' />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className='bg-primary-200 dark:bg-gray-600 h-40'>
|
||||||
|
{banner && <img className='h-full w-full object-cover' src={banner.url} alt={banner.url} />}
|
||||||
|
</div>
|
||||||
|
<Stack className='p-2.5' space={2}>
|
||||||
|
<Text weight='semibold'>{event.name}</Text>
|
||||||
|
|
||||||
|
<div className='flex gap-y-1 gap-x-2 flex-wrap text-gray-700 dark:text-gray-600'>
|
||||||
|
<HStack alignItems='center' space={1}>
|
||||||
|
<Icon src={require('@tabler/icons/user.svg')} />
|
||||||
|
<span>
|
||||||
|
<span dangerouslySetInnerHTML={{ __html: account.display_name_html }} />
|
||||||
|
{account.verified && <VerificationBadge />}
|
||||||
|
</span>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{renderDate()}
|
||||||
|
|
||||||
|
{event.location && (
|
||||||
|
<HStack alignItems='center' space={1}>
|
||||||
|
<Icon src={require('@tabler/icons/map-pin.svg')} />
|
||||||
|
<span>
|
||||||
|
{event.location.get('name')}
|
||||||
|
</span>
|
||||||
|
</HStack>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EventPreview;
|
|
@ -14,6 +14,7 @@ import QuotedStatus from 'soapbox/features/status/containers/quoted_status_conta
|
||||||
import { useAppDispatch, useSettings } from 'soapbox/hooks';
|
import { useAppDispatch, useSettings } from 'soapbox/hooks';
|
||||||
import { defaultMediaVisibility, textForScreenReader, getActualStatus } from 'soapbox/utils/status';
|
import { defaultMediaVisibility, textForScreenReader, getActualStatus } from 'soapbox/utils/status';
|
||||||
|
|
||||||
|
import EventPreview from './event-preview';
|
||||||
import StatusActionBar from './status-action-bar';
|
import StatusActionBar from './status-action-bar';
|
||||||
import StatusMedia from './status-media';
|
import StatusMedia from './status-media';
|
||||||
import StatusReplyMentions from './status-reply-mentions';
|
import StatusReplyMentions from './status-reply-mentions';
|
||||||
|
@ -360,6 +361,8 @@ const Status: React.FC<IStatus> = (props) => {
|
||||||
hoverable={hoverable}
|
hoverable={hoverable}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{actualStatus.event ? <EventPreview status={actualStatus} /> : (
|
||||||
|
<>
|
||||||
<StatusContent
|
<StatusContent
|
||||||
status={actualStatus}
|
status={actualStatus}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
|
@ -377,6 +380,8 @@ const Status: React.FC<IStatus> = (props) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{quote}
|
{quote}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{!hideActionBar && (
|
{!hideActionBar && (
|
||||||
<div className='pt-4'>
|
<div className='pt-4'>
|
||||||
|
|
Loading…
Reference in New Issue