153 lines
7.8 KiB
TypeScript
153 lines
7.8 KiB
TypeScript
import React, { useState } from 'react';
|
|
import type { ReactElement } from 'react';
|
|
import { ToastContainer, toast } from 'react-toastify';
|
|
import Head from 'next/head';
|
|
import BaseButton from '../components/BaseButton';
|
|
import CardBox from '../components/CardBox';
|
|
import SectionFullScreen from '../components/SectionFullScreen';
|
|
import LayoutGuest from '../layouts/Guest';
|
|
import { Field, Form, Formik } from 'formik';
|
|
import FormField from '../components/FormField';
|
|
import BaseDivider from '../components/BaseDivider';
|
|
import BaseButtons from '../components/BaseButtons';
|
|
import { useRouter } from 'next/router';
|
|
import { getPageTitle } from '../config';
|
|
import BaseIcon from '../components/BaseIcon';
|
|
import { mdiMusic, mdiContentCopy, mdiCheckDecagram } from '@mdi/js';
|
|
import Link from 'next/link';
|
|
|
|
import axios from "axios";
|
|
import jwt from 'jsonwebtoken';
|
|
|
|
export default function Register() {
|
|
const [loading, setLoading] = React.useState(false);
|
|
const [accessCode, setAccessCode] = useState<string | null>(null);
|
|
const router = useRouter();
|
|
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
|
|
|
|
const handleSubmit = async (value) => {
|
|
setLoading(true)
|
|
try {
|
|
const { data: token } = await axios.post('/auth/signup', value);
|
|
const decoded: any = jwt.decode(token);
|
|
|
|
if (decoded && decoded.user && decoded.user.accessCode) {
|
|
setAccessCode(decoded.user.accessCode);
|
|
notify('success', 'Account created! Here is your access code.');
|
|
} else {
|
|
await router.push('/login')
|
|
notify('success', 'Account created! Please login.')
|
|
}
|
|
setLoading(false)
|
|
} catch (error) {
|
|
setLoading(false)
|
|
console.log('error: ', error)
|
|
notify('error', 'Something went wrong. Try again')
|
|
}
|
|
};
|
|
|
|
const copyToClipboard = () => {
|
|
if (accessCode) {
|
|
navigator.clipboard.writeText(accessCode);
|
|
notify('info', 'Code copied to clipboard!');
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="bg-[#121212] min-h-screen">
|
|
<Head>
|
|
<title>{getPageTitle('Register')}</title>
|
|
</Head>
|
|
|
|
<SectionFullScreen bg='dark'>
|
|
<div className="flex flex-col items-center justify-center w-full px-4">
|
|
<div className="text-center mb-8">
|
|
<div className="flex items-center justify-center space-x-2 mb-2">
|
|
<BaseIcon path={mdiMusic} size={40} className="text-[#00E5FF]" />
|
|
<h2 className="text-4xl font-black text-white tracking-tighter uppercase italic">AI Music Studio</h2>
|
|
</div>
|
|
<p className="text-gray-400 font-bold">JOIN THE CREATIVE REVOLUTION</p>
|
|
</div>
|
|
|
|
{!accessCode ? (
|
|
<CardBox className='w-full md:w-3/5 lg:w-1/3 xl:w-1/4 bg-gray-900 border-gray-800 shadow-2xl'>
|
|
<Formik
|
|
initialValues={{
|
|
email: '',
|
|
password: '',
|
|
confirm: ''
|
|
}}
|
|
onSubmit={(values) => handleSubmit(values)}
|
|
>
|
|
<Form>
|
|
|
|
<FormField label='Email' help='Your creative identity'>
|
|
<Field type='email' name='email' className="bg-gray-800 border-gray-700 text-white focus:ring-[#00E5FF]" />
|
|
</FormField>
|
|
<FormField label='Password' help='Keep your studio secure'>
|
|
<Field type='password' name='password' className="bg-gray-800 border-gray-700 text-white focus:ring-[#00E5FF]" />
|
|
</FormField>
|
|
<FormField label='Confirm Password' help='Just to be sure'>
|
|
<Field type='password' name='confirm' className="bg-gray-800 border-gray-700 text-white focus:ring-[#00E5FF]" />
|
|
</FormField>
|
|
|
|
<BaseDivider className="border-gray-800" />
|
|
|
|
<BaseButtons>
|
|
<BaseButton
|
|
type='submit'
|
|
label={loading ? 'CREATING...' : 'GENERATE ACCESS CODE' }
|
|
color='info'
|
|
className="w-full py-4 font-black rounded-xl shadow-[0_0_15px_rgba(0,229,255,0.3)] hover:scale-105 transition-transform"
|
|
/>
|
|
</BaseButtons>
|
|
|
|
<div className="mt-8 text-center">
|
|
<p className="text-gray-400">
|
|
Already have a code?{' '}
|
|
<Link href="/login" className="text-[#00E5FF] font-black hover:underline">
|
|
Login Here
|
|
</Link>
|
|
</p>
|
|
</div>
|
|
</Form>
|
|
</Formik>
|
|
</CardBox>
|
|
) : (
|
|
<CardBox className='w-full md:w-3/5 lg:w-1/3 xl:w-1/4 bg-gray-900 border-gray-800 shadow-2xl text-center py-10'>
|
|
<BaseIcon path={mdiCheckDecagram} size={64} className="text-[#00E5FF] mx-auto mb-6" />
|
|
<h3 className="text-2xl font-black text-white mb-2 uppercase italic tracking-tighter">Your Access Code</h3>
|
|
<p className="text-gray-400 mb-8">Save this code. You'll need it to enter your studio.</p>
|
|
|
|
<div className="bg-black border border-gray-800 rounded-2xl p-8 mb-8 relative group cursor-pointer" onClick={copyToClipboard}>
|
|
<div className="text-5xl font-black text-white tracking-[0.2em] mb-4">{accessCode}</div>
|
|
<div className="text-[#00E5FF] flex items-center justify-center space-x-2 opacity-60 group-hover:opacity-100 transition-opacity">
|
|
<BaseIcon path={mdiContentCopy} size={20} />
|
|
<span className="text-sm font-bold uppercase">Click to Copy</span>
|
|
</div>
|
|
</div>
|
|
|
|
<BaseButtons className="flex-col space-y-4">
|
|
<BaseButton
|
|
href="/login"
|
|
label="ENTER STUDIO NOW"
|
|
color="info"
|
|
className="w-full py-4 font-black rounded-xl text-xl shadow-[0_0_20px_rgba(0,229,255,0.4)]"
|
|
/>
|
|
<Link href="/register" onClick={() => setAccessCode(null)} className="text-gray-500 hover:text-white font-bold transition-colors">
|
|
Create another account
|
|
</Link>
|
|
</BaseButtons>
|
|
</CardBox>
|
|
)}
|
|
</div>
|
|
</SectionFullScreen>
|
|
<ToastContainer theme="dark" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
Register.getLayout = function getLayout(page: ReactElement) {
|
|
return <LayoutGuest>{page}</LayoutGuest>;
|
|
};
|