Skip to content

Commit

Permalink
members
Browse files Browse the repository at this point in the history
  • Loading branch information
Fyrlex committed Dec 5, 2023
1 parent 99e9c11 commit 08811d7
Show file tree
Hide file tree
Showing 8 changed files with 379 additions and 27 deletions.
16 changes: 16 additions & 0 deletions components/MemberCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { FC } from 'react';
import { IMember } from '../src/models/Member.js';

const MemberCard: FC<{ member: IMember; }> = ({ member }) => {
return (
<div className='group bg-red-500 rounded-md shadow-lg p-4 w-72 h-72 text-xl'>
<p><span className='font-bold'>Naam:</span> {member.name}</p>
<p><span className='font-bold'>E-mail:</span> {member.email}</p>
<p><span className='font-bold'>Lidnummer:</span> {member.memberId}</p>
<p><span className='font-bold'>Betaalwijze:</span> {member.paymentMethod}</p>
<p><span className='font-bold'>LDC:</span> {member.ldc}</p>
</div>
);
};

export default MemberCard;
223 changes: 223 additions & 0 deletions pages/admin/leden/create.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
import { withIronSessionSsr } from 'iron-session/next';
import { NextPage } from 'next';
import { BaseSyntheticEvent, useState } from 'react';
import { FieldValues, useForm } from 'react-hook-form';
import Layout from '../../../components/Layout';
import { useMetaData } from '../../../lib/hooks/useMetaData';
import { AdminProps } from '../../../src/types/index';
import { ironOptions } from '../../../src/util/ironConfig';
import { useRouter } from 'next/router';
import Toast, { clearMessage } from '../../../components/Toast';

const AdminCreateMembers: NextPage<{ user: { email: string, has2faEnabled: boolean; }; }> = ({ user }) => {
const { register, handleSubmit, formState: { errors } } = useForm();

const [message, setMessage] = useState<{
type: 'success' | 'error' | 'info';
text: string;
}>({ type: 'success', text: '' });

const router = useRouter();

const onSubmit = async (data: FieldValues, event?: BaseSyntheticEvent): Promise<void> => {
event?.preventDefault();

try {
const req = await fetch('/api/members', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: data.name,
email: data.email,
paymentMethod: data.paymentmethod,
memberId: data.memberid,
ldc: data.ldc,
}),
}).catch(e => {
console.log(e);
setMessage({
type: 'error',
text: 'Er was een fout bij het maken van het product.',
});
});

if (req && req.ok) {
setMessage({
type: 'success',
text: 'Lid succesvol aangemaakt!',
});

await router.push('/admin/leden');
}
} catch (error) {
console.error(error);
setMessage({
type: 'error',
text: 'Er is een onverwachte fout opgetreden.',
});

clearMessage(setMessage);
}
};

return (
<>
{useMetaData(
'Aesculapia Admin | Webshop',
'Aesculapia Admin | Webshop',
'/admin',
)}
<Layout>
<div className='container relative mb-8'>
<div className='top-10 left-14 sm:left-20'>
<div className='flex flex-wrap w-56 sm:w-96'>
<h1 className='text-5xl pb-2 font-bold text-black'>
Maak een lid.
</h1>
<p className='text-xl text-black'>
Maak een product om op de webshop te verkopen.
</p>
</div>
<div className='flex flex-wrap h-auto text-xl mt-3'>
<form
onSubmit={handleSubmit((data, event) => onSubmit(data, event))}
>
<div className='flex flex-wrap -mx-3'>
<div className='w-full md:w-1/2 px-3 mb-6 md:mb-0'>
<label
className='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'
htmlFor='grid-member-name'
>
Naam lid
</label>
<input
className='appearance-none block w-full bg-gray-200 text-gray-700 border border-slate-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white'
id='grid-member-name'
type='text'
placeholder='Bob Johnson'
minLength={1}
maxLength={64}
required
{...register('name', { required: true })}
/>
</div>
<div className='w-full md:w-1/2 px-3 mb-6 md:mb-0'>
<label
className='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'
htmlFor='grid-member-price'
>
Email
</label>
<input
className='appearance-none block w-full bg-gray-200 text-gray-700 border border-slate-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white'
id='grid-member-price'
type='text'
placeholder='[email protected]'
required
{...register('email', { required: true })}
/>
</div>
</div>
<div className='flex flex-wrap -mx-3 mb-2'>
<div className='w-full md:w-1/3 px-3 mb-6 md:mb-0'>
<label
className='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'
htmlFor='grid-image-url'
>
Betaalwijze
</label>
<input
className='appearance-none block w-96 bg-gray-200 text-gray-700 border border-slate-500 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500'
id='grid-image-url'
type='text'
placeholder='bancontact, cash'
minLength={1}
maxLength={1024}
required
{...register('paymentmethod', { required: true })}
/>
</div>
</div>
<div className='flex flex-wrap -mx-3 mb-6'>
<div className='w-full md:w-1/2 px-3 mb-6 md:mb-0'>
<label
className='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'
htmlFor='grid-lidnummer'
>
Lidnummer
</label>
<input
className='appearance-none block w-full bg-gray-200 text-gray-700 border-slate-500 rounded py-3 px-4 mb-3 leading-tight border-2 focus:border-rose-500 focus:bg-white'
id='grid-lidnummer'
type='text'
placeholder='#12345'
required
{...register('memberid', { required: true })}
/>
</div>
<div className='w-full md:w-1/2 px-3 mb-6 md:mb-0'>
<label
className='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2'
htmlFor='grid-ldc'
>
LDC
</label>
<input
className='appearance-none block w-full bg-gray-200 text-gray-700 border-slate-500 rounded py-3 px-4 mb-3 leading-tight border-2 focus:border-rose-500 focus:bg-white'
id='grid-ldc'
type='text'
placeholder='A1232452'
required
{...register('ldc', { required: true })}
/>
</div>
</div>
<div className='pb-9'>
<button className='h-10 px-5 text-red-100 transition-colors duration-150 bg-red-700 rounded-lg focus:shadow-outline hover:bg-red-800'>
<input
className='cursor-pointer'
type='submit'
value='Maak'
></input>
</button>
</div>
</form>
</div>
</div>
</div>
{message.text !== '' && (
<Toast
type={message.type}
title={message.type[0].toUpperCase() + message.type.slice(1)}
description={message.text}
/>
)}
</Layout>
</>
);
};

// eslint-disable-next-line require-await
export const getServerSideProps = withIronSessionSsr(async function ({ req, resolvedUrl }): Promise<AdminProps> {
const user = req?.session.user;

if (!user) {
return {
props: {
user: { email: '', has2faEnabled: false, completed2fa: false },
},
redirect: {
destination: `/admin/login?from=${encodeURIComponent(resolvedUrl)}`,
permanent: false,
},
};
}

return {
props: { user: req.session.user },
};
}, ironOptions);

export default AdminCreateMembers;
81 changes: 81 additions & 0 deletions pages/admin/leden/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { withIronSessionSsr } from 'iron-session/next';
import { NextPage } from 'next';
import { ironOptions } from '../../../src/util/ironConfig';
import { AdminProps } from '../../../src/types/index';
import Layout from '../../../components/Layout';
import { useMetaData } from '../../../lib/hooks/useMetaData';
import ErrorPage from '../../../components/Error';
import { IMember, MemberDocument } from '../../../src/models/Member';
import MemberCard from '../../../components/MemberCard';

interface Props {
data: (IMember & { _id: string; })[];
}

const AdminMembersIndex: NextPage<Props> = ({ data }) => {
return (
<>
{useMetaData('Leden', 'Leden', '/admin/leden')}
<Layout>
{!data && <ErrorPage />}
{data && (
<div className='container mb-12'>
<div className='my-2'>
<h1 className='text-5xl font-bold mb-5'>Leden</h1>
<button className='h-10 px-5 text-red-100 transition-colors duration-150 bg-red-700 rounded-lg focus:shadow-outline hover:bg-red-900' onClick={(): void => { window.location.href = '/admin/leden/create'; }}>
Lid toevoegen
</button>
</div>
<div className='grid grid-cols-1 place-items-center gap-7 sm:grid-cols-2 md:grid-cols-3'>
{data.map((member, i) => {
return (
<MemberCard
member={member}
key={i}
/>
);
})}
</div>
</div>
)}
</Layout>
</>
);
};

export const getServerSideProps = withIronSessionSsr(async function ({ req, res, resolvedUrl }): Promise<AdminProps<MemberDocument>> {
const user = req?.session.user;

res?.setHeader(
'Cache-Control',
'public, s-maxage=10, stale-while-revalidate=59',
);

const request = await fetch(`${process.env.NEXT_PUBLIC_DOMAIN}/api/members`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});

const data = await request.json();

if (!user) {
return {
props: {
user: { email: '', has2faEnabled: false, completed2fa: false },
},
redirect: {
destination: `/admin/login?from=${encodeURIComponent(resolvedUrl)}`,
permanent: false,
},
};
}

return {
props: {
user: req.session.user,
data: data.data,
},
};
}, ironOptions);

export default AdminMembersIndex;
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,5 @@ export default withIronSessionApiRoute(async function createMember(
data: member,
});
} break;

case 'POST': {
if (!Authentication.authenticate(AuthorityLevel.ADMIN, req)) {
res.status(StatusCodes.FORBIDDEN).json({
error: true,
message: getReasonPhrase(StatusCodes.FORBIDDEN),
data: null,
});

return;
}

const member = await Member.create(req.body);

res.status(StatusCodes.CREATED).json({
error: false,
message: getReasonPhrase(StatusCodes.CREATED),
data: member,
});
} break;
}
}, ironOptions);
8 changes: 8 additions & 0 deletions pages/api/member/index.ts → pages/api/members/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ export default withIronSessionApiRoute(async function createMember(
res: NextApiResponse<ResponseData<MemberDocument | MemberDocument[]>>,
): Promise<void> {
switch (req.method) {
case 'GET': {
res.status(StatusCodes.OK).json({
error: false,
message: getReasonPhrase(StatusCodes.OK),
data: await Member.find({ ...req.query }),
});

} break;
case 'POST': {
if (!Authentication.authenticate(AuthorityLevel.ADMIN, req)) {
res.status(StatusCodes.FORBIDDEN).json({
Expand Down
Loading

0 comments on commit 08811d7

Please sign in to comment.