micro/packages/web/src/components/header/header.tsx

109 lines
3.9 KiB
TypeScript

import { Button, ButtonStyle, Container, useAsync, useOnClickOutside } from '@ryanke/pandora';
import classNames from 'classnames';
import { Fragment, memo, useRef, useState } from 'react';
import { Crop } from 'react-feather';
import { useResendVerificationEmailMutation } from '../../generated/graphql';
import { useConfig } from '../../hooks/useConfig';
import { usePaths } from '../../hooks/usePaths';
import { useUser } from '../../hooks/useUser';
import { Input } from '../input/input';
import { Link } from '../link';
import { HeaderUser } from './header-user';
export const Header = memo(() => {
const user = useUser();
const paths = usePaths();
const config = useConfig();
const [showEmailInput, setShowEmailInput] = useState(false);
const emailInputRef = useRef<HTMLDivElement>(null);
const [email, setEmail] = useState('');
const [resent, setResent] = useState(false);
const classes = classNames(
'relative z-20 flex items-center justify-between h-16 my-auto transition',
paths.loading && 'pointer-events-none invisible'
);
useOnClickOutside(emailInputRef, () => {
if (email) return;
setShowEmailInput(false);
});
const [resendMutation] = useResendVerificationEmailMutation();
const [resendVerification, sendingVerification] = useAsync(async () => {
if (!user.data) return;
if (!user.data.email && !email) {
setShowEmailInput(true);
return;
}
const payload = !user.data.email && email ? { email } : null;
await resendMutation({
variables: {
data: payload,
},
});
setShowEmailInput(false);
setResent(true);
});
return (
<Fragment>
{user.data && !user.data.verifiedEmail && config.data?.requireEmails && (
<div className="bg-purple-500 py-2 text-white shadow-2xl">
<Container>
<span className="relative">
You must verify your email before you can upload files.{' '}
<button type="button" className="underline" onClick={resendVerification} disabled={sendingVerification}>
{resent ? 'Verification email sent' : 'Resend verification email'}
</button>
{showEmailInput && (
<div
className="absolute bg-dark-100 top-full mt-2 p-3 rounded max-w-md z-20 md:right-0 border border-dark-400"
ref={emailInputRef}
>
<h4 className="font-medium leading-6">Missing Email</h4>
<p className="text-gray-500 text-sm">
Your account was created before this instance required emails. To verify your account, please enter
the email you would like your account to be attached to and hit submit.
</p>
<div className="mt-3 flex gap-2 items-center">
<Input
value={email}
onChange={(event) => setEmail(event.target.value)}
className="flex-grow"
placeholder="Email"
disabled={sendingVerification}
/>
<Button onClick={resendVerification} className="w-auto">
Submit
</Button>
</div>
</div>
)}
</span>
</Container>
</div>
)}
<Container>
<nav className={classes}>
<div className="flex items-center">
<Link href={paths.home} className="flex">
<Crop className="mr-2 text-primary" /> micro
</Link>
</div>
<div className="flex items-center">
{user.data ? (
<HeaderUser userId={user.data.id} username={user.data.username} />
) : (
<Button style={ButtonStyle.Secondary} href={paths.login}>
Sign In
</Button>
)}
</div>
</nav>
</Container>
</Fragment>
);
});