Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/APIFunctions/MembershipPayment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ApiResponse } from './ApiResponses';
import { BASE_API_URL } from '../Enums';

export async function verifyMembershipFromDb(token, confirmationCode) {
let status = new ApiResponse();
try {
const url = new URL('/api/MembershipPayment/verifyMembership', BASE_API_URL);
const res = await fetch(url.href, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({ confirmationCode })
});
if (res.ok) {
const result = await res.json();
status.responseData = result;
} else {
status.error = true;
}
} catch (err) {
status.error = true;
status.responseData = err;
}
return status;
}
21 changes: 21 additions & 0 deletions src/Pages/Profile/MemberView/Profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getUserById } from '../../../APIFunctions/User';
import ChangePasswordModal from './ChangePassword';
import DeleteAccountModal from './DeleteAccountModal';
import GetApiKeyModal from './GetApiKeyModal';
import VerifyMembershipModal from './VerifyMembershipModal';
import { membershipState, membershipStateToString } from '../../../Enums';
import { useSCE } from '../../../Components/context/SceContext';

Expand Down Expand Up @@ -53,6 +54,14 @@ export default function Profile() {
<span className="tracking-wide text-lg">{response.firstName} {response.lastName}</span>
</div>
<div className="flex flex-col sm:flex-row gap-4">
<button
className="btn btn-success"
onClick={() =>
document.getElementById('verify-membership-modal').showModal()
}
>
Verify Membership
</button>
<button
className="btn btn-primary"
onClick={() =>
Expand Down Expand Up @@ -110,6 +119,18 @@ export default function Profile() {
</div>
</div>
</div>
<VerifyMembershipModal
bannerCallback={(message, color, delay = 3000) => {
setBannerMessage(message);
setBannerColor(color);
setTimeout(() => {
setBannerMessage('');
setBannerColor('');
}, delay);
}}
accessLevel={response.accessLevel}
onVerificationSuccess={getUserFromApi}
/>
<ChangePasswordModal
bannerCallback={(message, color, delay = 3000) => {
setBannerMessage(message);
Expand Down
99 changes: 99 additions & 0 deletions src/Pages/Profile/MemberView/VerifyMembershipModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React, { useEffect, useState } from 'react';
import { useSCE } from '../../../Components/context/SceContext';
import { verifyMembershipFromDb } from '../../../APIFunctions/MembershipPayment';

export default function VerifyMembershipModal(props) {
const { bannerCallback = (message, color) => { }, confirmClassAddons, accessLevel, onVerificationSuccess = () => {} } = props;
const [confirmationCode, setConfirmationCode] = useState('');
const { user } = useSCE();

const INPUT_CLASS_NAME = 'indent-2 block w-full rounded-md border-0 py-1.5 bg-white text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6';

async function verifyMembership() {
const apiResponse = await verifyMembershipFromDb(
user.token,
confirmationCode,
);
if (apiResponse.error) {
bannerCallback('Unable to verify membership. Please try again later.');
return;
}
bannerCallback('Congrats, you confirmed your membership!');
setConfirmationCode('');
document.getElementById('verify-membership-modal').close();
onVerificationSuccess();
}

return (<>
<dialog id="verify-membership-modal" className="modal modal-bottom sm:modal-middle">
<div className="modal-box">
<h3 className="font-bold text-lg">Verify Membership</h3>
{accessLevel > 0 ? (
<>
<p className="text-sm text-gray-500 mt-2">
You are already verified!!!
</p>
<div className="modal-action">
<form method="dialog">
<div className="px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6">
<button
className="btn inline-flex w-full justify-center rounded-md px-3 py-2 text-sm font-semibold shadow-sm ring-1 ring-inset sm:w-auto"
>
Close
</button>
</div>
</form>
</div>
</>
) : (
<>
<p className="text-sm text-gray-500 mt-2">
Please enter the confirmation code you received via email.
</p>
<label htmlFor="confirmation-code" className="block text-sm font-medium leading-6 mt-2">
Confirmation Code
</label>
<div className="mt-2">
<input
value={confirmationCode}
id="confirmation-code"
name="confirmation-code"
type="text"
placeholder="Enter confirmation code"
onChange={(e) => {
setConfirmationCode(e.target.value);
}}
className={INPUT_CLASS_NAME}
/>
</div>

<div className="modal-action">
<form method="dialog">
<div className="px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6">
<button
disabled={!confirmationCode}
onClick={() => {
verifyMembership();
}}
className={`btn inline-flex w-full justify-center rounded-md px-3 py-2 text-sm font-semibold text-white shadow-sm ${confirmClassAddons} sm:ml-3 sm:w-auto`}
>
Verify
</button>
<button
onClick={() => {
setConfirmationCode('');
}}
className="btn mt-3 inline-flex w-full justify-center rounded-md px-3 py-2 text-sm font-semibold shadow-sm ring-1 ring-inset sm:mt-0 sm:w-auto"
>
Cancel
</button>
</div>
</form>
</div>
</>
)}
</div>
</dialog>
</>
);
}