diff --git a/.gitignore b/.gitignore
index a9d8fc7..24cdedf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,4 @@
npm-debug.log*
yarn-debug.log*
-yarn-error.log*
-
-/public/question-bank.docx
\ No newline at end of file
+yarn-error.log*
\ No newline at end of file
diff --git a/src/App.tsx b/src/App.tsx
index 9e5f59f..46fa3e1 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -9,6 +9,7 @@ import Authentication from './pages/Authentication.tsx';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from './resources/Firebase.js';
import Strings from './resources/Strings.ts';
+import Stringify from './pages/Stringify.tsx';
const theme = extendTheme({});
@@ -53,6 +54,7 @@ function App() {
background='var(--joy-palette-primary-100)'
/>
} />
+ } />
diff --git a/src/pages/QuestionBank.tsx b/src/pages/QuestionBank.tsx
index e17b803..9171f0c 100644
--- a/src/pages/QuestionBank.tsx
+++ b/src/pages/QuestionBank.tsx
@@ -1,6 +1,5 @@
import React, { ReactNode, useCallback, useEffect, useState } from "react";
import "./QuestionBank.css";
-import JSZip from "jszip";
import { DOMParser } from "@xmldom/xmldom";
import useDocumentTitle from "../hooks/useDocumentTitle.ts";
import { Alert, Button, CircularProgress, Link, Typography } from "@mui/joy";
@@ -8,17 +7,10 @@ import { onAuthStateChanged, sendEmailVerification } from "firebase/auth";
import { auth } from "../resources/Firebase.js";
import Paths from '../resources/Paths.ts';
-const str2xml = (str: string) => {
- if (str.charCodeAt(0) === 65279) {
- str = str.slice(1);
- }
- return new DOMParser().parseFromString(str, "text/xml");
-};
-
-const getParagraphs = async (file: File) => {
- const zip = new JSZip();
- const content = await zip.loadAsync(file);
- const xml = str2xml(await content.file("word/document.xml")?.async("text") as string);
+const parseQuestionBank = async (questionBank: string) => {
+ if (questionBank.charCodeAt(0) === 65279)
+ questionBank = questionBank.slice(1);
+ const xml = new DOMParser().parseFromString(questionBank, "text/xml");
const paragraphsXml = xml.getElementsByTagName("w:p");
const paragraphs: string[] = [];
const stack: number[] = [];
@@ -84,7 +76,7 @@ const QuestionBank: React.FC = ({ }) => {
useDocumentTitle('My Answers');
/* verification */
- const [isSendingVerificationEmail, setIsSendingVerificationEmail] = useState(false);
+ const [isSendingVerificationEmail, setIsSendingVerificationEmail] = useState(true);
const [sentVerificationEmail, setSentVerificationEmail] = useState(false);
const [errorSendingVerificationEmail, setErrorSendingVerificationEmail] = useState(false);
const [resendCount, setResendCount] = useState(0);
@@ -131,7 +123,8 @@ const QuestionBank: React.FC = ({ }) => {
{
);
/* subscription */
- const [subscriptionChecked, setSubscriptionChecked] = useState(false);
- const [subscriptionWillRenew, setSubscriptionWillRenew] = useState();
+ const [subscriptionPortalUrl, setSubscriptionPortalUrl] = useState(null);
+ const [subscriptionCancelAtPeriodEnd, setSubscriptionCancelAtPeriodEnd] = useState();
const [subscriptionExpiryDate, setSubscriptionExpiryDate] = useState();
+ const [questionBank, setQuestionBank] = useState([]);
+
const checkSubscription = useCallback(async () => {
try {
const response = await fetch(Paths.Serverless + '?user-uid=' + auth.currentUser?.uid);
if (response.status === 200) {
- const timestamp = await response.text();
+ const data = JSON.parse(await response.text());
+
+ setSubscriptionPortalUrl(data['url']);
+
+ setSubscriptionCancelAtPeriodEnd(data['cancel_at_period_end']);
+
+ const timestamp = data['current_period_end'];
const timestampInt = parseInt(timestamp, 10);
- setSubscriptionChecked(true);
setSubscriptionExpiryDate(new Date(timestampInt * 1000));
+
+ setQuestionBank(await parseQuestionBank(data['question-bank']));
}
} catch (error) {
- setSubscriptionChecked(true);
console.error(error);
}
- }, [setSubscriptionChecked, setSubscriptionExpiryDate]);
+ }, [setSubscriptionPortalUrl, setSubscriptionCancelAtPeriodEnd, setSubscriptionExpiryDate, setQuestionBank]);
useEffect(() => {
checkSubscription();
}, [checkSubscription]);
+ const subscriptionWasChecked = subscriptionPortalUrl !== null
const hasSubscriptionExpired = subscriptionExpiryDate && (subscriptionExpiryDate < new Date(Date.now()));
- const willSubscriptionExpireThisWeek = !subscriptionWillRenew && subscriptionExpiryDate && (subscriptionExpiryDate < new Date(Date.now() + (7 * 86400000)));
-
- /* parse data */
- const [paragraphs, setParagraphs] = useState([]);
-
- const onFileUpload = useCallback(async () => {
- try {
- const response = await fetch('/question-bank.docx');
- const blob = await response.blob();
- const file = new File([blob], 'question-bank.docx', { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
- const paragraphs = await getParagraphs(file);
- setParagraphs(paragraphs);
- } catch (error) {
- console.error(error);
- }
- }, []);
-
- useEffect(() => {
- onFileUpload();
- }, [onFileUpload]);
+ const willSubscriptionExpireThisWeek = !subscriptionCancelAtPeriodEnd && subscriptionExpiryDate && (subscriptionExpiryDate < new Date(Date.now() + (7 * 86400000)));
return (
{!emailVerified && (
-
-
- Please verify your email address using the link we've sent you.{" "}
- {resendVerificationEmail}
+
+
+ Please verify your email address using the link we've sent you. {resendVerificationEmail}
)}
{subscriptionExpiryDate && (
<>
-
- Your subscription {hasSubscriptionExpired ? 'expired' : (subscriptionWillRenew ? 'will renew' : 'will expire')} at {
+
+ Your subscription {hasSubscriptionExpired ? 'expired' : (subscriptionCancelAtPeriodEnd ? 'will expire' : 'will renew')} at {
subscriptionExpiryDate && (
subscriptionExpiryDate.toLocaleString('en-GB', {
hour: 'numeric',
@@ -234,16 +210,15 @@ const QuestionBank: React.FC = ({ }) => {
month: 'long',
year: 'numeric'
}))
- }.
- {subscriptionWillRenew && Cancel Renewal.}
+ }. {subscriptionPortalUrl && <> { window.location.href = subscriptionPortalUrl }}>{subscriptionCancelAtPeriodEnd ? 'Renew' : 'Cancel Renewal'}.>}
- {paragraphs.map((paragraph, index) => (
+ {questionBank.map((paragraph, index) => (
{paragraph}
))}
>
)}
- {subscriptionChecked
+ {subscriptionWasChecked
? (!subscriptionExpiryDate || hasSubscriptionExpired) &&