Started trying out reading Excel files

This commit is contained in:
Tiago Ribeiro
2024-01-11 13:55:37 +00:00
parent fd1af3efee
commit f79857fabe
8 changed files with 213 additions and 29 deletions

View File

@@ -13,6 +13,7 @@ import ReactDatePicker from "react-datepicker";
import {toast} from "react-toastify";
import ShortUniqueId from "short-unique-id";
import {useFilePicker} from "use-file-picker";
import readXlsxFile from "read-excel-file";
export default function BatchCodeGenerator({user}: {user: User}) {
const [emails, setEmails] = useState<string[]>([]);
@@ -24,8 +25,9 @@ export default function BatchCodeGenerator({user}: {user: User}) {
const {users} = useUsers();
const {openFilePicker, filesContent} = useFilePicker({
accept: ".txt",
accept: ".xlsx",
multiple: false,
readAs: "ArrayBuffer",
});
useEffect(() => {
@@ -41,18 +43,21 @@ export default function BatchCodeGenerator({user}: {user: User}) {
useEffect(() => {
if (filesContent.length > 0) {
const file = filesContent[0];
const emails = file.content
.split("\n")
.map((x) => x.trim())
.filter((x) => new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/).test(x))
.filter((x) => !users.map((u) => u.email).includes(x));
readXlsxFile(file.content).then((rows) => {
console.log(rows);
});
// const emails = file.content
// .split("\n")
// .map((x) => x.trim())
// .filter((x) => new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/).test(x))
// .filter((x) => !users.map((u) => u.email).includes(x));
if (emails.length === 0) {
toast.error("Please upload a .txt file containing e-mails, one per line! All already registered e-mails have also been ignored!");
return;
}
// if (emails.length === 0) {
// toast.error("Please upload a .txt file containing e-mails, one per line! All already registered e-mails have also been ignored!");
// return;
// }
setEmails([...new Set(emails)]);
// setEmails([...new Set(emails)]);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [filesContent]);
@@ -63,7 +68,7 @@ export default function BatchCodeGenerator({user}: {user: User}) {
setIsLoading(true);
axios
.post("/api/code", {type, codes, emails, expiryDate})
.post("/api/code", {type, codes, infos: emails.map((x) => ({email: x})), expiryDate})
.then(({data, status}) => {
if (data.ok) {
toast.success(`Successfully generated ${capitalize(type)} codes and they have been notified by e-mail!`, {toastId: "success"});

View File

@@ -10,16 +10,20 @@ import {KeyedMutator} from "swr";
interface Props {
queryCode?: string;
defaultEmail?: string;
defaultInformation?: {
email: string;
name: string;
passport_id?: string;
};
isLoading: boolean;
setIsLoading: (isLoading: boolean) => void;
mutateUser: KeyedMutator<User>;
sendEmailVerification: typeof sendEmailVerification;
}
export default function RegisterIndividual({queryCode, defaultEmail, isLoading, setIsLoading, mutateUser, sendEmailVerification}: Props) {
const [name, setName] = useState("");
const [email, setEmail] = useState(defaultEmail || "");
export default function RegisterIndividual({queryCode, defaultInformation, isLoading, setIsLoading, mutateUser, sendEmailVerification}: Props) {
const [name, setName] = useState(defaultInformation?.name || "");
const [email, setEmail] = useState(defaultInformation?.email || "");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [code, setCode] = useState(queryCode || "");
@@ -48,6 +52,7 @@ export default function RegisterIndividual({queryCode, defaultEmail, isLoading,
password,
type: "individual",
code,
passport_id: defaultInformation?.passport_id,
profilePicture: "/defaultAvatar.png",
})
.then((response) => {
@@ -73,14 +78,14 @@ export default function RegisterIndividual({queryCode, defaultEmail, isLoading,
return (
<form className="flex flex-col items-center gap-6 w-full" onSubmit={register}>
<Input type="text" name="name" onChange={(e) => setName(e)} placeholder="Enter your name" defaultValue={name} required />
<Input type="text" name="name" onChange={(e) => setName(e)} placeholder="Enter your name" value={name} required />
<Input
type="email"
name="email"
onChange={(e) => setEmail(e)}
placeholder="Enter email address"
value={email}
disabled={!!defaultEmail}
disabled={!!defaultInformation?.email}
required
/>
<Input

View File

@@ -19,7 +19,12 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
return;
}
const {type, codes, emails, expiryDate} = req.body as {type: Type; codes: string[]; emails?: string[]; expiryDate: null | Date};
const {type, codes, infos, expiryDate} = req.body as {
type: Type;
codes: string[];
infos?: {email: string; name: string; passport_id: string}[];
expiryDate: null | Date;
};
const permission = PERMISSIONS.generateCode[type];
if (!permission.includes(req.session.user.type)) {
@@ -47,8 +52,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const codeRef = doc(db, "codes", code);
await setDoc(codeRef, {type, code, creator: req.session.user!.id, expiryDate});
if (emails && emails.length > index) {
await setDoc(codeRef, {email: emails[index]}, {merge: true});
if (infos && infos.length > index) {
const {email, name, passport_id} = infos[index];
await setDoc(codeRef, {email, name, passport_id}, {merge: true});
const transport = prepareMailer();
const mailOptions = prepareMailOptions(
@@ -56,7 +62,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
type,
code,
},
[emails[index]],
[email],
"EnCoach Registration",
"main",
);

View File

@@ -37,8 +37,9 @@ async function register(req: NextApiRequest, res: NextApiResponse) {
}
async function registerIndividual(req: NextApiRequest, res: NextApiResponse) {
const {email, password, code} = req.body as {
const {email, passport_id, password, code} = req.body as {
email: string;
passport_id?: string;
password: string;
code?: string;
};
@@ -67,6 +68,7 @@ async function registerIndividual(req: NextApiRequest, res: NextApiResponse) {
focus: "academic",
type: email.endsWith("@ecrop.dev") ? "developer" : codeData ? codeData.type : "student",
subscriptionExpirationDate: codeData ? codeData.expiryDate : moment().subtract(1, "days").toISOString(),
...(passport_id ? {demographicInformation: {passport_id}} : {}),
registrationDate: new Date(),
status: code ? "active" : "paymentDue",
};

View File

@@ -23,12 +23,18 @@ export const getServerSideProps = (context: any) => {
export default function Register({code: queryCode}: {code: string}) {
const [defaultEmail, setDefaultEmail] = useState<string>();
const [defaultName, setDefaultName] = useState<string>();
const [passport_id, setPassportID] = useState<string>();
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (queryCode) {
(async () => {
axios.get<{email?: string}>(`/api/code/${queryCode}`).then((result) => setDefaultEmail(result.data.email));
axios.get<{email?: string; name?: string; passport_id?: string}>(`/api/code/${queryCode}`).then((result) => {
setDefaultEmail(result.data.email);
setDefaultName(result.data.name);
setPassportID(result.data.passport_id);
});
})();
}
}, [queryCode]);
@@ -95,7 +101,9 @@ export default function Register({code: queryCode}: {code: string}) {
mutateUser={mutateUser}
sendEmailVerification={sendEmailVerification}
queryCode={queryCode}
defaultEmail={defaultEmail}
defaultInformation={
defaultEmail && defaultName ? {email: defaultEmail, name: defaultName, passport_id} : undefined
}
/>
</Tab.Panel>
<Tab.Panel>