diff --git a/apps/app/components/LectureForm/index.js b/apps/app/components/LectureForm/index.js index 248bc5ca..8ad564fc 100644 --- a/apps/app/components/LectureForm/index.js +++ b/apps/app/components/LectureForm/index.js @@ -52,16 +52,16 @@ export default function LectureForm({ id }) { const [ninjas, setNinjas] = useState([]); - let promise; + useEffect(() => { + let promise; - const fetchData = () => { - if (!promise) { - promise = Promise.all(events.map((event) => getNinjaEvents(event.id))); - } - return promise; - }; + const fetchData = () => { + if (!promise) { + promise = Promise.all(events.map((event) => getNinjaEvents(event.id))); + } + return promise; + }; - useEffect(() => { fetchData().then((responses) => { const allNinjas = responses.flatMap((response) => response.data); setNinjas( diff --git a/apps/app/components/Profile/index.tsx b/apps/app/components/Profile/index.tsx index caa8037a..74325380 100644 --- a/apps/app/components/Profile/index.tsx +++ b/apps/app/components/Profile/index.tsx @@ -6,7 +6,6 @@ import { Row, Space, Tabs, - Tag, Timeline, Typography, } from "antd"; @@ -20,14 +19,13 @@ import * as api from "bokkenjs"; import * as socials from "~/lib/social"; import { notifyError, notifyInfo } from "~/components/Notification"; import styles from "./style.module.css"; -import { EUser } from "bokkenjs"; - -import { BsFileEarmarkPersonFill } from "react-icons/bs"; - +import { EUser, getNinjasAsAdmin, updateGuardianAsAdmin } from "bokkenjs"; +import Link from "next/link"; import { getIcon } from "~/lib/utils"; const { TabPane } = Tabs; -const { Title } = Typography; + +const { Title, Text } = Typography; interface Props { id: string; @@ -39,65 +37,95 @@ function Profile({ id, role }: Props) { const [badges, setBadges] = useState([]); const [projects, setProjects] = useState([]); const [skills, setSkills] = useState([]); - const [date, setDate] = useState(""); + const [date, setDate] = useState(""); + const [guardian, setGuardians] = useState([]); useEffect(() => { - api - .getUserByRole({ id, role }) - .then((response) => setInfo(response.data)) - .catch((error) => { + const fetchUserByRole = async () => { + try { + const response = await api.getUserByRole({ id, role }); + setInfo(response.data); + } catch (error) { notifyError( "Ocorreu um erro", "Não foi possível obter os dados do utilizador" ); - }); + } + }; - if (role == EUser.Mentor) { - api - .getMentorSkills(id) - .then((response) => setSkills(response.data)) - .catch((error) => { - notifyError( - "Ocorreu um erro", - "Não foi possível obter os conhecimentos do mentor" - ); - }); - } else if (role == EUser.Ninja) { - api - .getNinjaBadges(id) - .then((response) => setBadges(response.data)) - .catch((error) => { - notifyError( - "Ocorreu um erro", - "Não foi possível obter os crachás do ninja" - ); - }); + const fetchMentorSkills = async () => { + try { + const response = await api.getMentorSkills(id); + setSkills(response.data); + } catch (error) { + notifyError( + "Ocorreu um erro", + "Não foi possível obter os conhecimentos do mentor" + ); + } + }; - api - .getNinjaFiles(id) - .then((response) => setProjects(response.data)) - .catch((error) => { - notifyError( - "Ocorreu um erro", - "Não foi possível obter os ficheiros do ninja" - ); - }); + const fetchNinjaBadges = async () => { + try { + const response = await api.getNinjaBadges(id); + setBadges(response.data); + } catch (error) { + notifyError( + "Ocorreu um erro", + "Não foi possível obter os crachás do ninja" + ); + } + }; - api - .getNinjaSkills(id) - .then((response) => setSkills(response.data)) - .catch((error) => { - notifyError( - "Ocorreu um erro", - "Não foi possível obter as linguagens do ninja" - ); - }); + const fetchNinjaFiles = async () => { + try { + const response = await api.getNinjaFiles(id); + setProjects(response.data); + } catch (error) { + notifyError( + "Ocorreu um erro", + "Não foi possível obter os ficheiros do ninja" + ); + } + }; + + const fetchNinjaSkills = async () => { + try { + const response = await api.getNinjaSkills(id); + setSkills(response.data); + } catch (error) { + notifyError( + "Ocorreu um erro", + "Não foi possível obter as linguagens do ninja" + ); + } + }; + + fetchUserByRole(); + + if (role === EUser.Mentor) { + fetchMentorSkills(); + } else if (role === EUser.Ninja) { + fetchNinjaBadges(); + fetchNinjaFiles(); + fetchNinjaSkills(); } }, [id, role]); useEffect(() => { - setDate(moment(info.since).format("DD/MM/YYYY")); - }, [info]); + if (info.since) { + setDate(moment(info.since).format("DD/MM/YYYY")); + } + }, [info.since]); + + useEffect(() => { + if (role === EUser.Ninja) { + api + .getGuardian(info.guardian_id) + .then((response: any) => setGuardians(response.data)) + .catch((error: any) => {}); + } + }, [info.guardian_id, role]); return ( <> @@ -115,32 +143,36 @@ function Profile({ id, role }: Props) { src={info?.photo} icon={} /> - - - - {info.first_name} {info.last_name} - - - - - <BsFileEarmarkPersonFill /> {role} - - - - Conta criada em: {date} - - - {"belt" in info && ( - - - - )} - - + + + {info.first_name} {info.last_name} + +

+ {role.charAt(0).toUpperCase() + role.slice(1)} + {role === EUser.Ninja && ( + <> + + de{" "} + + + {guardian.first_name} {guardian.last_name} + + + + + )} +

+

+ Conta criada em: {date} +

+

+ +

+

{info?.socials?.map((social: any) => - social?.name == "discord" || social?.name == "slack" ? ( - + social?.name === "discord" || social?.name === "slack" ? ( + {socials.ICONS[social.name as keyof typeof socials.URLS]} ) : ( @@ -150,32 +182,41 @@ function Profile({ id, role }: Props) { rel="noreferrer" href={`${ socials.URLS[social.name as keyof typeof socials.URLS] - }/${social.username}`} + }${social.username}`} > {socials.ICONS[social.name as keyof typeof socials.URLS]} ) )} - - - - {skills.map((s) => ( - - {getIcon(s.name)} {s.name} - +

+

+ {skills.map((s: any) => ( +

+ {getIcon(s.name)} +
))} - -
+

+ - }> - Registou-se na plataforma{" "} - {moment(info.since).locale("pt").fromNow()} - + + }> + Registou-se na plataforma{" "} + {moment(info.since).locale("pt").fromNow()} + + {role === EUser.Ninja && ( diff --git a/apps/app/components/Profile/style.module.css b/apps/app/components/Profile/style.module.css index 6eab341b..05f4bc8e 100644 --- a/apps/app/components/Profile/style.module.css +++ b/apps/app/components/Profile/style.module.css @@ -1,3 +1,3 @@ .capitalize { - text-transform: capitalize; -} + text-transform: capitalize; + } \ No newline at end of file diff --git a/apps/app/components/Register/index.tsx b/apps/app/components/Register/index.tsx index 677d5eb9..78f0a8a2 100644 --- a/apps/app/components/Register/index.tsx +++ b/apps/app/components/Register/index.tsx @@ -60,7 +60,6 @@ function Register({ cities }: any) { ]); const onFinish = (values: any) => { - console.log(values); setLoading(true); api .registerUser(values) diff --git a/apps/app/lib/social.tsx b/apps/app/lib/social.tsx index 31b1cfde..125388a1 100644 --- a/apps/app/lib/social.tsx +++ b/apps/app/lib/social.tsx @@ -5,7 +5,8 @@ import { FaSlack, FaTrello, } from "react-icons/fa"; -import { SiCodewars, SiScratch } from "react-icons/si"; +import { SiCodewars, SiScratch, SiSurveymonkey } from "react-icons/si"; +import { AiOutlineReddit } from "react-icons/ai"; export const ICONS = { scratch: , @@ -15,6 +16,8 @@ export const ICONS = { trello: , discord: , slack: , + lightbot: , + codemonkey: , }; export const URLS = { diff --git a/apps/app/lib/utils.tsx b/apps/app/lib/utils.tsx index 2db4b8d0..b7cd655b 100644 --- a/apps/app/lib/utils.tsx +++ b/apps/app/lib/utils.tsx @@ -1,8 +1,11 @@ import { SiCodewars, + SiCss3, SiDiscord, SiGithub, SiGitlab, + SiHtml5, + SiJavascript, SiPython, SiScratch, SiSlack, @@ -10,23 +13,29 @@ import { } from "react-icons/si"; export function getIcon(skill: string) { - if (skill.startsWith("Python")) { - return ; - } else if (skill.startsWith("Scratch")) { - return ; - } - switch (skill) { + case "Python": + return ; + case "Scratch": return ; case "Codewars": return ; + case "HTML/CSS/Javascript": + return ( + <> +
+ + + +
+ + ); + case "GitHub": return ; case "GitLab": return ; - case "Trello": - return ; case "Discord": return ; case "Slack": diff --git a/apps/app/pages/admin/guardians.tsx b/apps/app/pages/admin/guardians.tsx index 41556c1d..432daaf3 100644 --- a/apps/app/pages/admin/guardians.tsx +++ b/apps/app/pages/admin/guardians.tsx @@ -117,10 +117,15 @@ function Guardians() { .then((response: any) => { setGuardians( response.data.map((guardian: any) => { + const guardianData = { + id: guardian.id, + name: `${guardian.first_name} ${guardian.last_name}`, + }; return { ...guardian, name: `${guardian.first_name} ${guardian.last_name}`, key: guardian.id, + guardian: guardianData, }; }) ); @@ -296,9 +301,14 @@ function Guardians() { }, { title: "Nome", - dataIndex: "name", + dataIndex: "guardian", editable: false, ...getColumnSearchProps("name"), + render: (guardian: any) => ( + + {guardian.name} + + ), }, { title: "E-mail", diff --git a/apps/app/pages/admin/lectures/presences/index.tsx b/apps/app/pages/admin/lectures/presences/index.tsx index 7a399dc8..03e0e8c4 100644 --- a/apps/app/pages/admin/lectures/presences/index.tsx +++ b/apps/app/pages/admin/lectures/presences/index.tsx @@ -43,8 +43,6 @@ export default function Presences() { .updateLecture(lectureId, values) .then(() => { notifyInfo("Os dados da sessão foram atualizados com sucesso", ""); - - // Update the corresponding lecture in lectures state with the new data const updatedLectures = lectures.map((lecture) => { if (lecture.id === lectureId) { return { @@ -75,7 +73,7 @@ export default function Presences() { "Não foi possível atualizar os dados da sessão" ); }); - }, []); + }, [data, selectedLectures]); useEffect(() => { api @@ -121,26 +119,19 @@ export default function Presences() { }, [selectedEvent, lectures]); useEffect(() => { - generateData(); - }, [selectedLectures]); - - const generateData = () => { - const data: any[] = []; - - selectedLectures.map((lecture: any) => { + const data = selectedLectures.map((lecture: any) => { if (lecture.attendance == null) { lecture.attendance = "both_absent"; } - data.push({ + return { ninja: `${lecture.ninja.first_name} ${lecture.ninja.last_name}`, mentor: `${lecture.mentor.first_name} ${lecture.mentor.last_name}`, presences: `${lecture.attendance}`, key: lecture.id, - }); + }; }); - setData(data); - }; + }, [selectedLectures]); const handleEditButtonClick = () => { setEditButtonVisible(false); diff --git a/apps/app/pages/admin/mentors.tsx b/apps/app/pages/admin/mentors.tsx index b6e63c55..384d8245 100644 --- a/apps/app/pages/admin/mentors.tsx +++ b/apps/app/pages/admin/mentors.tsx @@ -28,7 +28,10 @@ interface Item { key: string; user_id: string; photo: any; - name: string; + mentor: { + id: string; + name: string; + }; email: string; birthday: string; mobile: string; @@ -118,10 +121,15 @@ function Mentors() { .then((response: any) => { setMentors( response.data.map((mentor: any) => { + const mentorData = { + id: mentor.id, + name: `${mentor.first_name} ${mentor.last_name}`, + }; return { ...mentor, name: `${mentor.first_name} ${mentor.last_name}`, key: mentor.id, + mentor: mentorData, }; }) ); @@ -297,9 +305,14 @@ function Mentors() { }, { title: "Nome", - dataIndex: "name", + dataIndex: "mentor", editable: false, ...getColumnSearchProps("name"), + render: (mentor: any) => ( + + {mentor.name} + + ), }, { title: "E-mail", diff --git a/apps/app/pages/admin/ninjas.tsx b/apps/app/pages/admin/ninjas.tsx index ec558c13..dfb983c9 100644 --- a/apps/app/pages/admin/ninjas.tsx +++ b/apps/app/pages/admin/ninjas.tsx @@ -30,7 +30,10 @@ const { Option } = Select; interface Item { key: string; photo: any; - name: string; + ninja: { + id: string; + name: string; + }; birthday: string; belt: string; guardian: { @@ -102,11 +105,15 @@ function Ninjas() { .then((response: any) => { setNinjas( response.data.map((ninja: any) => { + const ninjaData = { + id: ninja.id, + name: `${ninja?.first_name} ${ninja?.last_name}`, + }; return { ...ninja, - name: `${ninja.first_name} ${ninja.last_name}`, - key: ninja.id, + key: ninja?.id, guardian: buildGuardian(ninja.guardian), + ninja: ninjaData, }; }) ); @@ -128,7 +135,7 @@ function Ninjas() { const edit = (record: Partial & { key: React.Key }) => { form.setFieldsValue({ - name: "", + ninja: "", birthday: "", belt: "", guardian: "", @@ -180,7 +187,7 @@ function Ninjas() { setSearchText(""); }; - const getColumnSearchProps = (dataIndex: string): ColumnType => ({ + const getColumnSearchProps = (dataIndex: any): ColumnType => ({ filterDropdown: ({ setSelectedKeys, selectedKeys, @@ -269,7 +276,6 @@ function Ninjas() { return `Pesquisar por ${dataIndex}`; } }; - const columns = [ { title: "Foto", @@ -279,10 +285,16 @@ function Ninjas() { }, { title: "Nome", - dataIndex: "name", + dataIndex: "ninja", editable: false, ...getColumnSearchProps("name"), + render: (ninja: any) => ( + + {ninja.name} + + ), }, + { title: "Cinturão", dataIndex: "belt",