Added the ability for a user to select their preferred topics

This commit is contained in:
Tiago Ribeiro
2024-02-13 11:39:19 +00:00
parent f643430068
commit c0c9d22864
4 changed files with 171 additions and 13 deletions

View File

@@ -0,0 +1,70 @@
import topics from "@/resources/topics";
import {useState} from "react";
import {BsArrowLeft, BsArrowRight} from "react-icons/bs";
import Button from "../Low/Button";
import Modal from "../Modal";
interface Props {
isOpen: boolean;
initialTopics: string[];
onClose: VoidFunction;
selectTopics: (topics: string[]) => void;
}
export default function TopicModal({isOpen, initialTopics, onClose, selectTopics}: Props) {
const [selectedTopics, setSelectedTopics] = useState([...initialTopics]);
return (
<Modal isOpen={isOpen} onClose={onClose} title="Preferred Topics">
<div className="flex flex-col w-full h-full gap-4 mt-4">
<div className="w-full h-full grid grid-cols-2 -md:gap-1 gap-4">
<div className="flex flex-col gap-2">
<span className="border-b border-b-neutral-400/30">Available Topics</span>
<div className=" max-h-[500px] overflow-y-scroll scrollbar-hide">
{topics
.filter((x) => !selectedTopics.includes(x))
.map((x) => (
<div key={x} className="odd:bg-mti-purple-ultralight/40 p-2 flex justify-between items-center">
<span>{x}</span>
<button
onClick={() => setSelectedTopics((prev) => [...prev, x])}
className="border border-mti-purple-light cursor-pointer p-2 rounded-lg bg-white drop-shadow transition ease-in-out duration-300 hover:bg-mti-purple hover:text-white">
<BsArrowRight />
</button>
</div>
))}
</div>
</div>
<div className="flex flex-col gap-2">
<span className="border-b border-b-neutral-400/30">Preferred Topics ({selectedTopics.length || "All"})</span>
<div className=" max-h-[500px] overflow-y-scroll scrollbar-hide">
{selectedTopics.map((x) => (
<div key={x} className="odd:bg-mti-purple-ultralight/40 p-2 flex justify-between items-center text-right">
<button
onClick={() => setSelectedTopics((prev) => [...prev.filter((y) => y !== x)])}
className="border border-mti-purple-light cursor-pointer p-2 rounded-lg bg-white drop-shadow transition ease-in-out duration-300 hover:bg-mti-purple hover:text-white">
<BsArrowLeft />
</button>
<span>{x}</span>
</div>
))}
</div>
</div>
</div>
<div className="w-full flex gap-4 items-center justify-end">
<Button variant="outline" color="rose" className="w-full max-w-[200px]" onClick={onClose}>
Close
</Button>
<Button
className="w-full max-w-[200px]"
onClick={() => {
selectTopics(selectedTopics);
onClose();
}}>
Save
</Button>
</div>
</div>
</Modal>
);
}

View File

@@ -24,6 +24,7 @@ export interface StudentUser extends BasicUser {
type: "student";
preferredGender?: InstructorGender;
demographicInformation?: DemographicInformation;
preferredTopics?: string[];
}
export interface TeacherUser extends BasicUser {
@@ -52,6 +53,7 @@ export interface DeveloperUser extends BasicUser {
type: "developer";
preferredGender?: InstructorGender;
demographicInformation?: DemographicInformation;
preferredTopics?: string[];
}
export interface CorporateInformation {

View File

@@ -16,7 +16,7 @@ import {CorporateUser, EmploymentStatus, EMPLOYMENT_STATUS, Gender, User} from "
import CountrySelect from "@/components/Low/CountrySelect";
import {shouldRedirectHome} from "@/utils/navigation.disabled";
import moment from "moment";
import {BsCamera} from "react-icons/bs";
import {BsCamera, BsQuestionCircleFill} from "react-icons/bs";
import {USER_TYPE_LABELS} from "@/resources/user";
import useGroups from "@/hooks/useGroups";
import useUsers from "@/hooks/useUsers";
@@ -31,6 +31,8 @@ import ModuleLevelSelector from "@/components/Medium/ModuleLevelSelector";
import Select from "@/components/Low/Select";
import {InstructorGender} from "@/interfaces/exam";
import {capitalize} from "lodash";
import TopicModal from "@/components/Medium/TopicModal";
import {v4} from "uuid";
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
@@ -90,6 +92,9 @@ function UserProfile({user, mutateUser}: Props) {
const [preferredGender, setPreferredGender] = useState<InstructorGender | undefined>(
user.type === "student" || user.type === "developer" ? user.preferredGender || "varied" : undefined,
);
const [preferredTopics, setPreferredTopics] = useState<string[] | undefined>(
user.type === "student" || user.type === "developer" ? user.preferredTopics : undefined,
);
const [position, setPosition] = useState<string | undefined>(user.type === "corporate" ? user.demographicInformation?.position : undefined);
const [corporateInformation, setCorporateInformation] = useState(user.type === "corporate" ? user.corporateInformation : undefined);
@@ -99,6 +104,8 @@ function UserProfile({user, mutateUser}: Props) {
);
const [timezone, setTimezone] = useState<string>(user.demographicInformation?.timezone || moment.tz.guess());
const [isPreferredTopicsOpen, setIsPreferredTopicsOpen] = useState(false);
const {groups} = useGroups();
const {users} = useUsers();
@@ -156,6 +163,7 @@ function UserProfile({user, mutateUser}: Props) {
profilePicture,
desiredLevels,
preferredGender,
preferredTopics,
demographicInformation: {
phone,
country,
@@ -350,6 +358,7 @@ function UserProfile({user, mutateUser}: Props) {
{preferredGender && ["developer", "student"].includes(user.type) && (
<>
<Divider />
<DoubleColumnRow>
<div className="flex flex-col gap-3 w-full">
<label className="font-normal text-base text-mti-gray-dim">Speaking Instructor&apos;s Gender</label>
<Select
@@ -362,6 +371,28 @@ function UserProfile({user, mutateUser}: Props) {
]}
/>
</div>
<div className="flex flex-col gap-4 w-full">
<label className="font-normal text-base text-mti-gray-dim flex gap-2 items-center">
Preferred Topics{" "}
<span
className="tooltip"
data-tip="These topics will be considered for speaking and writing modules, aiming to include at least one exercise containing of the these in the selected exams.">
<BsQuestionCircleFill />
</span>
</label>
<Button className="w-full" variant="outline" onClick={() => setIsPreferredTopicsOpen(true)}>
Select Topics ({preferredTopics?.length || "All"} selected)
</Button>
</div>
</DoubleColumnRow>
<TopicModal
key={v4()}
isOpen={isPreferredTopicsOpen}
onClose={() => setIsPreferredTopicsOpen(false)}
selectTopics={setPreferredTopics}
initialTopics={preferredTopics || []}
/>
</>
)}

55
src/resources/topics.ts Normal file
View File

@@ -0,0 +1,55 @@
const topics = [
"Education",
"Technology",
"Environment",
"Health and Fitness",
"Globalization",
"Engineering",
"Work and Careers",
"Travel and Tourism",
"Culture and Traditions",
"Social Issues",
"Arts and Entertainment",
"Climate Change",
"Social Media",
"Sustainable Development",
"Health Care",
"Immigration",
"Artificial Intelligence",
"Consumerism",
"Online Shopping",
"Energy",
"Oil and Gas",
"Poverty and Inequality",
"Cultural Diversity",
"Democracy and Governance",
"Mental Health",
"Ethics and Morality",
"Population Growth",
"Science and Innovation",
"Poverty Alleviation",
"Cybersecurity and Privacy",
"Human Rights",
"Social Justice",
"Food and Agriculture",
"Cyberbullying and Online Safety",
"Linguistic Diversity",
"Urbanization",
"Artificial Intelligence in Education",
"Youth Empowerment",
"Disaster Management",
"Mental Health Stigma",
"Internet Censorship",
"Sustainable Fashion",
"Indigenous Rights",
"Water Scarcity",
"Social Entrepreneurship",
"Privacy in the Digital Age",
"Sustainable Transportation",
"Gender Equality",
"Automation and Job Displacement",
"Digital Divide",
"Education Inequality",
];
export default topics;