daily-examples/custom/fitness-demo/pages/index.js

178 lines
4.8 KiB
JavaScript

import React, { useState, useCallback } from 'react';
import { CallProvider } from '@custom/shared/contexts/CallProvider';
import { MediaDeviceProvider } from '@custom/shared/contexts/MediaDeviceProvider';
import { ParticipantsProvider } from '@custom/shared/contexts/ParticipantsProvider';
import { TracksProvider } from '@custom/shared/contexts/TracksProvider';
import { UIStateProvider } from '@custom/shared/contexts/UIStateProvider';
import { WaitingRoomProvider } from '@custom/shared/contexts/WaitingRoomProvider';
import getDemoProps from '@custom/shared/lib/demoProps';
import PropTypes from 'prop-types';
import App from '../components/App';
import Intro from '../components/Prejoin/Intro';
import NotConfigured from '../components/Prejoin/NotConfigured';
/**
* Index page
* ---
* - Checks configuration variables are set in local env
* - Optionally obtain a meeting token from Daily REST API (./pages/api/token)
* - Set call owner status
* - Finally, renders the main application loop
*/
export default function Index({
domain,
isConfigured = false,
subscribeToTracksAutomatically = true,
asides,
modals,
customTrayComponent,
customAppComponent,
}) {
const [roomName, setRoomName] = useState();
const [fetching, setFetching] = useState(false);
const [error, setError] = useState();
const [fetchingToken, setFetchingToken] = useState(false);
const [token, setToken] = useState();
const [tokenError, setTokenError] = useState();
const getMeetingToken = useCallback(async (room, isOwner = false) => {
if (!room) return false;
setFetchingToken(true);
// Fetch token from serverside method (provided by Next)
const res = await fetch('/api/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ roomName: room, isOwner }),
});
const resJson = await res.json();
if (!resJson?.token) {
setTokenError(resJson?.error || true);
setFetchingToken(false);
return false;
}
console.log(`🪙 Token received`);
setFetchingToken(false);
setToken(resJson.token);
// Setting room name will change ready state
setRoomName(room);
return true;
}, []);
const createRoom = async (room, duration, privacy) => {
setError(false);
setFetching(true);
console.log(`🚪 Creating a new class...`);
// Create a room server side (using Next JS serverless)
const res = await fetch('/api/createRoom', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
roomName: room,
expiryMinutes: Number(duration),
privacy: !privacy ? 'private': 'public'
}),
});
const resJson = await res.json();
if (resJson.name) {
setFetching(false);
await getMeetingToken(resJson.name, true);
return;
}
setError(resJson.error || 'An unknown error occured');
setFetching(false);
}
const isReady = !!(isConfigured && roomName);
if (!isReady) {
return (
<main>
{(() => {
if (!isConfigured) return <NotConfigured />;
return (
<Intro
tokenError={tokenError}
fetching={fetching}
error={error}
room={roomName}
domain={domain}
onJoin={(room, type, duration = 60, privacy = 'public') =>
type === 'join' ? setRoomName(room): createRoom(room, duration, privacy)
}
/>
);
})()}
<style jsx>{`
height: 100vh;
display: grid;
align-items: center;
justify-content: center;
`}</style>
</main>
);
}
/**
* Main call UI
*/
return (
<UIStateProvider
asides={asides}
modals={modals}
customTrayComponent={customTrayComponent}
>
<CallProvider
domain={domain}
room={roomName}
token={token}
subscribeToTracksAutomatically={subscribeToTracksAutomatically}
>
<ParticipantsProvider>
<TracksProvider>
<MediaDeviceProvider>
<WaitingRoomProvider>
{customAppComponent || <App />}
</WaitingRoomProvider>
</MediaDeviceProvider>
</TracksProvider>
</ParticipantsProvider>
</CallProvider>
</UIStateProvider>
);
}
Index.propTypes = {
isConfigured: PropTypes.bool.isRequired,
domain: PropTypes.string,
asides: PropTypes.arrayOf(PropTypes.func),
modals: PropTypes.arrayOf(PropTypes.func),
customTrayComponent: PropTypes.node,
customAppComponent: PropTypes.node,
subscribeToTracksAutomatically: PropTypes.bool,
};
export async function getStaticProps() {
const defaultProps = getDemoProps();
return {
props: defaultProps,
};
}