import Button from "@/components/Low/Button"; import useUsers from "@/hooks/useUsers"; import { Type as UserType, User } from "@/interfaces/user"; import axios from "axios"; import { uniqBy } from "lodash"; import { useEffect, useState } from "react"; import { toast } from "react-toastify"; import { useFilePicker } from "use-file-picker"; import readXlsxFile from "read-excel-file"; import Modal from "@/components/Modal"; import { BsQuestionCircleFill } from "react-icons/bs"; import { PermissionType } from "@/interfaces/permissions"; const EMAIL_REGEX = new RegExp( /^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/ ); type Type = Exclude const USER_TYPE_LABELS: {[key in Type]: string} = { student: "Student", teacher: "Teacher", corporate: "Corporate", }; const USER_TYPE_PERMISSIONS: { [key in Type]: { perm: PermissionType | undefined; list: Type[] }; } = { student: { perm: "createCodeStudent", list: [], }, teacher: { perm: "createCodeTeacher", list: [], }, corporate: { perm: "createCodeCorporate", list: ["student", "teacher"], }, }; export default function BatchCreateUser({ user }: { user: User }) { const [infos, setInfos] = useState< { email: string; name: string; passport_id:string, type: Type, demographicInformation: { country: string, passport_id:string, phone: string } }[] >([]); const [isLoading, setIsLoading] = useState(false); const [type, setType] = useState("student"); const [showHelp, setShowHelp] = useState(false); const { users } = useUsers(); const { openFilePicker, filesContent, clear } = useFilePicker({ accept: ".xlsx", multiple: false, readAs: "ArrayBuffer", }); useEffect(() => { if (filesContent.length > 0) { const file = filesContent[0]; readXlsxFile(file.content).then((rows) => { try { const information = uniqBy( rows .map((row) => { const [ firstName, lastName, country, passport_id, email, phone ] = row as string[]; return EMAIL_REGEX.test(email.toString().trim()) ? { email: email.toString().trim().toLowerCase(), name: `${firstName ?? ""} ${lastName ?? ""}`.trim().toLowerCase(), type: type, passport_id: passport_id?.toString().trim() || undefined, demographicInformation: { country: country, passport_id: passport_id?.toString().trim() || undefined, phone, } } : undefined; }) .filter((x) => !!x) as typeof infos, (x) => x.email ); if (information.length === 0) { toast.error( "Please upload an Excel file containing user information, one per line! All already registered e-mails have also been ignored!" ); return clear(); } setInfos(information); } catch { toast.error( "Please upload an Excel file containing user information, one per line! All already registered e-mails have also been ignored!" ); return clear(); } }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [filesContent]); const makeUsers = async () => { const newUsers = infos.filter( (x) => !users.map((u) => u.email).includes(x.email) ); const confirmed = confirm( `You are about to add ${newUsers.length}, are you sure you want to continue?` ) if (!confirmed) return; if (newUsers.length > 0) { setIsLoading(true); Promise.all(newUsers.map((user) => { return axios.post("/api/make_user", user) })).finally(() => { return clear(); }) } setIsLoading(false); setInfos([]); }; return ( <> setShowHelp(false)} title="Excel File Format" >
Please upload an Excel file with the following format:
First Name Last Name Country Passport/National ID E-mail Phone Number
Notes:
  • - All incorrect e-mails will be ignored;
  • - All already registered e-mails will be ignored;
  • - You may have a header row with the format above, however, it is not necessary;
  • - All of the e-mails in the file will receive an e-mail to join EnCoach with the role selected below.
setShowHelp(true)} >
{user && ( )}
); }