jam-cloud/jam-ui/src/components/sessions/JKSession.js

207 lines
6.9 KiB
JavaScript

import React, { useEffect } from 'react';
import { useAuth } from '../../context/UserAuth';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUserLatencies } from '../../store/features/latencySlice';
import { toast } from 'react-toastify';
import { useTranslation } from 'react-i18next';
import { useResponsive } from '@farfetch/react-context-responsive';
import PropTypes from 'prop-types';
import { Row, Col, Button, UncontrolledTooltip } from 'reactstrap';
import jkCustomUrlScheme from '../../helpers/jkCustomUrlScheme';
import JKUserLatencyBadge from '../profile/JKUserLatencyBadge';
import JKSessionUser from './JKSessionUser';
import useNativeAppCheck from '../../hooks/useNativeAppCheck';
import { useNativeApp } from '../../context/NativeAppContext';
import EnterIcon from '../../icons/enter.svg';
import JKInstrumentIcon from '../profile/JKInstrumentIcon';
function JKSession({ session }) {
const { currentUser } = useAuth();
const dispatch = useDispatch();
const { t } = useTranslation();
const { greaterThan } = useResponsive();
const { setNativeAppUnavailable } = useNativeApp();
useEffect(() => {
const participantIds = session.participants.map(p => p.user.id);
const options = { currentUserId: currentUser.id, participantIds };
dispatch(fetchUserLatencies(options));
}, [session.id]);
const sessionDescription = session => {
if (session.description) {
return session.description;
} else if (session.musician_access && !session.approval_required) {
return t('list.descriptions.public_open_session', { ns: 'sessions' });
} else if (session.musician_access && session.approval_required) {
return t('list.descriptions.private_session', { ns: 'sessions' });
} else if (!session.musician_access && !session.approval_required) {
return t('list.descriptions.rsvp_session', { ns: 'sessions' });
}
};
const invitedNote = session => {
if (session.invitations.find(i => i.receiver_id === currentUser.id)) {
return t('list.notes.invited', { ns: 'sessions' });
}
};
const hasFriendNote = session => {
if (session.participants.find(p => p.user.is_friend)) {
return t('list.notes.has_friend', { ns: 'sessions' });
}
};
const musicianRowStyle = {
height: '40px',
flexWrap: 'wrap',
overflow: 'hidden',
alignItems: 'center',
};
return (
<>
{greaterThan.sm ? (
<tr key={session.id}>
<td>
<div>
<u>
<small>
<strong>{invitedNote(session)}</strong>
</small>
</u>
</div>
<div>
<u>
<small>{hasFriendNote(session)}</small>
</u>
</div>
<div>{sessionDescription(session)}</div>
</td>
<td>
{session.participants.map(participant => (
<Row style={musicianRowStyle} key={participant.id}>
<Col>
<JKSessionUser user={participant.user} />
</Col>
</Row>
))}
</td>
<td className="text-center">
{session.participants.map(participant => (
<Row key={participant.id} style={musicianRowStyle}>
<Col>
<JKUserLatencyBadge key={participant.id} user={participant.user} showBadgeOnly={true} />
</Col>
</Row>
))}
</td>
<td>
{session.participants.map(participant => (
<Row style={musicianRowStyle} key={participant.id} data-testid={`Participant${participant.id}Tracks`}>
<Col>
{participant.tracks.map(track => (
<span key={track.id} className="mr-1 mb-1" title={track.instrment}>
<a id={`Participant${participant.id}Track${track.id}Instrument`} data-testid={`Track${track.id}Instrument`}>
{/* <InstrumentIcon track={track} /> */}
<JKInstrumentIcon instrumentId={track.instrument_id} instrumentName={track.instrument} />
</a>
<UncontrolledTooltip placement="top" target={`Participant${participant.id}Track${track.id}Instrument`}>
{track.instrument}
</UncontrolledTooltip>
</span>
))}
</Col>
</Row>
))}
</td>
<td className="text-center">
<JoinSessionButton session={session} />
</td>
</tr>
) : (
<Row>
<Col>
<div>
<u>
<small>
<strong>{invitedNote(session)}</strong>
</small>
</u>
</div>
<div>
<u>
<small>{hasFriendNote(session)}</small>
</u>
</div>
<div>{sessionDescription(session)}</div>
<div className="d-flex flex-row justify-content-between mt-3">
<div className="ml-2 ms-2">
<h5>{t('list.header.musicians', { ns: 'sessions' })}</h5>
</div>
<div className="ml-2 ms-2">
<strong>{t('list.header.latency', { ns: 'sessions' })}</strong>
</div>
</div>
<div>
{session.participants.map(participant => (
<JKSessionUser key={participant.id} user={participant.user} />
))}
</div>
<div className="mt-4 d-flex flex-row justify-content-center">
<JoinSessionButton session={session} />
</div>
</Col>
</Row>
)}
</>
);
}
function JoinSessionButton({ session }) {
const isNativeAppAvailable = useNativeAppCheck();
const { setNativeAppUnavailable } = useNativeApp();
const { t } = useTranslation();
async function joinSession(e) {
e.preventDefault();
if (session.musician_access && session.approval_required) {
toast.info(t('list.alerts.join_request_sent', { ns: 'sessions' }));
} else {
try {
await isNativeAppAvailable();
const q = `joinSessionId~${session.id}`;
const urlScheme = jkCustomUrlScheme('findSession', q);
window.open(urlScheme, '_blank');
return;
} catch (error) {
setNativeAppUnavailable(true);
}
}
}
return (
<div>
<Button
data-testid="joinBtn"
color="primary"
onClick={joinSession}
className="btn-join btn-sm mr-1 mb-1 pt-1 pb-1 pl-1 pr-1"
style={{ cursor: 'pointer' }}
>
<img src={EnterIcon} alt="enter" className="mr-1" width={20} />
</Button>
<div>
<a href="#" onClick={joinSession}>Join Session</a>
</div>
</div>
);
}
JKSession.propTypes = { session: PropTypes.object.isRequired };
export default JKSession;