daddy/client/src/components/ConferencePage/ConferencePage.tsx

140 lines
5.3 KiB
TypeScript

import React, { FunctionComponent, useEffect } from 'react';
import { Config } from '../../config';
import { useUserProfile } from '../../gql/queries/profile';
import { useConference } from '../../hooks/useConference';
import { Page } from '../Page';
import { Gravatar } from './Gravatar';
export interface ConferencePageProps {
}
const StatusHandRaised = 'hand-raised';
const StatusThumbsUp = 'thumbs-up';
const StatusThumbsDown = 'thumbs-down';
const StatusNoVote = 'no-vote';
export const ConferencePage:FunctionComponent<ConferencePageProps> = () => {
const { user } = useUserProfile();
const { uuid, data, setNickname, setEmail, ping, setStatus, forget } = useConference();
const currentStatus = data.statuses[uuid];
useEffect(() => {
if (!user.name && !user.email) return;
setNickname(user.name || user.email.split('@')[0]);
setEmail(user.email);
}, [user.name, user.email]);
useEffect(() => {
ping();
const intervalId = setInterval(() => ping(), Config.conferenceHeartbeatInterval + (Math.random() * Config.conferenceHeartbeatInterval/2));
return () => clearInterval(intervalId);
}, []);
const onStatusChange = (status: string) => {
setStatus(currentStatus === status ? '' : status);
};
return (
<Page title="Conference">
<div className="container is-fluid">
<section className="mt-5">
<h3 className="is-size-3">Mes actions</h3>
<div className="buttons has-addons">
<button
className={`button is-medium ${currentStatus === StatusHandRaised ? 'is-info is-selected' : ''}`}
onClick={onStatusChange.bind(null, StatusHandRaised)}>
<span className="icon">
<i className="fa fa-hand-paper"></i>
</span>
<span>Lever la main</span>
</button>
<button
className={`button is-medium ${currentStatus === StatusThumbsUp ? 'is-success is-selected' : ''}`}
onClick={onStatusChange.bind(null, StatusThumbsUp)}>
<span className="icon">
<i className="fa fa-thumbs-up"></i>
</span>
<span>Voter pour</span>
</button>
<button
className={`button is-medium ${currentStatus === StatusNoVote ? 'is-warning is-selected' : ''}`}
onClick={onStatusChange.bind(null, StatusNoVote)}>
<span className="icon">
<i className="fa fa-mitten"></i>
</span>
<span>Ne se prononce pas</span>
</button>
<button
className={`button is-medium ${currentStatus === StatusThumbsDown ? 'is-danger is-selected' : ''}`}
onClick={onStatusChange.bind(null, StatusThumbsDown)}>
<span className="icon">
<i className="fa fa-thumbs-down"></i>
</span>
<span>Voter contre</span>
</button>
</div>
<h3 className="is-size-3">Assemblée</h3>
<div className="columns mt-1 is-multiline">
<UserCard className="column is-narrow"
nickname={data.nicknames[uuid]}
status={currentStatus}
email={user.email} />
{
Object.keys(data.peers).map(p => {
const now = new Date();
const lastHeartBeat = new Date(data.peers[p]);
if (p === uuid) return null;
if (now.getTime() > lastHeartBeat.getTime() + Config.conferenceHeartbeatInterval*2) {
forget(p);
return null;
}
const nickname = data.nicknames[p] || '???';
const email = data.emails[p] || '';
return (
<UserCard key={`peer-${p}`} className="column is-narrow"
nickname={nickname}
status={data.statuses[p]}
email={email} />
)
})
}
</div>
</section>
</div>
</Page>
);
}
export interface UserCardProps {
nickname: string
email: string
className?: string
status: string
};
export const UserCard:FunctionComponent<UserCardProps> = ({ nickname, email, className, status }) => {
return (
<div className={className}>
<div className="box">
<div className="has-text-centered">
<div className="mb-1">
{ !status ? <span className="icon"><i className="far fa-2x fa-meh-blank"></i></span> : null }
{ status === StatusHandRaised ? <span className="icon has-text-info"><i className="fa fa-2x fa-hand-paper"></i></span> : null }
{ status === StatusThumbsUp ? <span className="icon has-text-success"><i className="fa fa-2x fa-thumbs-up"></i></span> : null }
{ status === StatusNoVote ? <span className="icon has-text-warning"><i className="fa fa-2x fa-mitten"></i></span> : null }
{ status === StatusThumbsDown ? <span className="icon has-text-danger"><i className="fa fa-2x fa-thumbs-down"></i></span> : null }
</div>
<figure className="image is-128x128 is-inline-block">
<Gravatar className="is-rounded" email={email} />
</figure>
<h4 className="is-size-4">{nickname}</h4>
</div>
</div>
</div>
);
};