From 53ffaa852953dcd282570202090edafde44914a1 Mon Sep 17 00:00:00 2001 From: Victor-oss Date: Sun, 10 Dec 2023 22:38:54 -0300 Subject: [PATCH] =?UTF-8?q?(#51)=20Refatora=C3=A7=C3=A3o=20do=20estilo=20d?= =?UTF-8?q?a=20US=2052=20e=20refatora=C3=A7=C3=A3o=20do=20c=C3=B3digo=20pa?= =?UTF-8?q?ra=20diminuir=20n=C3=BAmero=20de=20requisi=C3=A7=C3=B5es=20por?= =?UTF-8?q?=20minuto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/controllers/classPlanController.ts | 28 +- frontend/package-lock.json | 50 ++- frontend/src/components/Header.tsx | 8 +- frontend/src/index.css | 31 +- frontend/src/pages/Authentication/SignIn.tsx | 20 +- frontend/src/pages/ClassPlans.tsx | 60 ++- frontend/src/pages/Drill.tsx | 164 ++++---- frontend/src/pages/ViewPlan.tsx | 360 ++++++++---------- frontend/yarn.lock | 177 ++------- 9 files changed, 405 insertions(+), 493 deletions(-) diff --git a/backend/src/controllers/classPlanController.ts b/backend/src/controllers/classPlanController.ts index 86505d9..72facfd 100644 --- a/backend/src/controllers/classPlanController.ts +++ b/backend/src/controllers/classPlanController.ts @@ -40,14 +40,9 @@ export default class classPlanController { where: { userId: userId, }, - include: { - user: { - select: { - id: true, - email: true, - name: true, - }, - }, + select: { + id: true, + title: true, }, }) res.status(200).json(classPlan) @@ -62,14 +57,12 @@ export default class classPlanController { where: { id: id, }, - include: { - user: { - select: { - id: true, - email: true, - name: true, - }, - }, + select: { + id: true, + title: true, + goals: true, + observations: true, + userId: true, }, }) res.status(200).json(classPlan) @@ -82,7 +75,7 @@ export default class classPlanController { try { const { id } = req.params - const classPlan = await prisma.classPlan.deleteMany({ + const classPlan = await prisma.classPlan.delete({ where: { id }, }) @@ -92,6 +85,7 @@ export default class classPlanController { res.status(500).json({ errors: { server: "Server error" } }) } } + updateById = async (req: Request, res: Response) => { try { const id = req.params.id diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3d5d101..c326979 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,6 +12,7 @@ "apexcharts": "^3.41.0", "axios": "^1.6.2", "headlessui": "^0.0.0", + "html2canvas": "^1.4.1", "jsvectormap": "^1.5.3", "match-sorter": "^6.3.1", "react": "^18.2.0", @@ -24,6 +25,7 @@ "sort-by": "^0.0.2" }, "devDependencies": { + "@iconify/react": "^4.1.1", "@types/react": "^18.2.17", "@types/react-dom": "^18.2.7", "@vitejs/plugin-react": "^4.0.3", @@ -758,6 +760,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/@iconify/react/-/react-4.1.1.tgz", "integrity": "sha512-jed14EjvKjee8mc0eoscGxlg7mSQRkwQG3iX3cPBCO7UlOjz0DtlvTqxqEcHUJGh+z1VJ31Yhu5B9PxfO0zbdg==", + "dev": true, "dependencies": { "@iconify/types": "^2.0.0" }, @@ -771,7 +774,8 @@ "node_modules/@iconify/types": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", - "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==" + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", @@ -1276,6 +1280,14 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -1500,6 +1512,14 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -1943,6 +1963,18 @@ "resolved": "https://registry.npmjs.org/headlessui/-/headlessui-0.0.0.tgz", "integrity": "sha512-CHvacVPbl8AqIg2sBNKySUmumu7o15jSrCaTrIh9GW2Eq4y/krCN/vZFOsKCwlrhWQbO4267a8xvvP8bs+qREQ==" }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3188,6 +3220,14 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -3281,6 +3321,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/vite": { "version": "4.4.7", "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz", diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx index 406b651..516a6b4 100644 --- a/frontend/src/components/Header.tsx +++ b/frontend/src/components/Header.tsx @@ -1,7 +1,6 @@ -import { Link } from 'react-router-dom'; import { Icon } from '@iconify/react/dist/iconify.js'; -const Header = (props: { path: string; hasReturnArrow: boolean }) => { +const Header = (props: { hasReturnArrow: boolean, changeScreenFunction: () => void }) => { const logout = () => { localStorage.removeItem('token'); localStorage.removeItem('user'); @@ -15,14 +14,15 @@ const Header = (props: { path: string; hasReturnArrow: boolean }) => { >
{props.hasReturnArrow ? ( - + ) : (
)} diff --git a/frontend/src/index.css b/frontend/src/index.css index dd6834e..ba6b752 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -301,7 +301,7 @@ span.flatpickr-weekday, } .buttonsPanel { - width: 100vw; + width: 100%; display: grid; grid-template-columns: repeat(auto-fit, minmax(330px, 330px)); grid-gap: 20px; @@ -355,12 +355,25 @@ span.flatpickr-weekday, padding-right: 10px; } +.titleLayoutClassPLan { + display: flex; + flex-direction: row; + margin: auto; + width: 90%; +} + .contentDrill{ display: flex; justify-content: space-between; padding: 0px 15px; } +.contentClassPlan{ + display: flex; + flex-direction: column; + align-items: center; +} + #drillGraphicContainer{ margin-top: 5px; height: 406px; @@ -390,15 +403,19 @@ span.flatpickr-weekday, background-color: #494949; padding: 15px; border-radius: 20px; - height: 300px; + min-height: 300px; width: 350px; + box-sizing: content-box; + height: fit-content; } -.pClassPlan { - color: white; +.pClassPlan{ + margin: 10px auto; background-color: #494949; padding: 15px; border-radius: 20px; + min-height: 300px; + box-sizing: content-box; height: fit-content; width: 90%; } @@ -423,15 +440,13 @@ span.flatpickr-weekday, border: '1px solid black'; } -.textAreaDrill { +/* .textAreaDrill { background-color: #494949; border-radius: 20px; height: 300px; - width: 250px; - height: 300px; width: 350px; padding: 15px; -} +} */ .drillButtonsPanel { width: 100%; diff --git a/frontend/src/pages/Authentication/SignIn.tsx b/frontend/src/pages/Authentication/SignIn.tsx index 6836977..4f8dfb4 100644 --- a/frontend/src/pages/Authentication/SignIn.tsx +++ b/frontend/src/pages/Authentication/SignIn.tsx @@ -7,10 +7,12 @@ import { Icon } from '@iconify/react/dist/iconify.js'; import '../../index.css'; import Logo from '../../images/logoBeachTennisCoordimate.png'; import { Link } from 'react-router-dom'; +import ClassPlanService from '../../service/classPlanService'; const SignIn = () => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); + const classPlan = new ClassPlanService(); const handleSignIn = async () => { try { @@ -25,11 +27,19 @@ const SignIn = () => { if (data.status === 200) { localStorage.setItem('token', data.data.token); console.log(data.data); - localStorage.setItem('user', JSON.stringify(data.data)); - toast.success('Login realizado com sucesso!'); - setTimeout(() => { - window.location.href = '/'; - }, 3000); + const data_user = JSON.stringify(data.data); + localStorage.setItem('user', data_user); + try{ + const user_id = String(JSON.parse(data_user).id); + let userClassPlans = await classPlan.getManyById(user_id as string); + localStorage.setItem('userClassPlans', JSON.stringify(userClassPlans.data)); + toast.success('Login realizado com sucesso!'); + setTimeout(() => { + window.location.href = '/'; + }, 3000); + } catch (error){ + + } } return; } diff --git a/frontend/src/pages/ClassPlans.tsx b/frontend/src/pages/ClassPlans.tsx index 74ed2ef..16b9c5b 100644 --- a/frontend/src/pages/ClassPlans.tsx +++ b/frontend/src/pages/ClassPlans.tsx @@ -1,13 +1,14 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import '../index.css'; import { Icon } from '@iconify/react'; import { toast, ToastContainer } from 'react-toastify'; import ClassPlanService from '../service/classPlanService'; -import { Link } from 'react-router-dom'; import Header from '../components/Header'; +import DrillService from '../service/drillService'; const ClassPlans = () => { - const [classPlans, setClassPlans] = useState([]); + const userClassPlans = localStorage.getItem('userClassPlans'); + const [classPlans, setClassPlans] = useState(JSON.parse(userClassPlans ? userClassPlans : '')); const userString = localStorage.getItem('user'); const [deletedItem, setDeletedItem] = useState(''); const [deletedItemTitle, setDeletedItemTitle] = useState(''); @@ -20,13 +21,11 @@ const ClassPlans = () => { id = ''; } - useEffect(() => { - loadPlans(); - }, []); - const [title, setTitle] = useState(''); const [visible, setVisible] = useState(false); const classPlan = new ClassPlanService(); + const drill = new DrillService(); + let data = { id: '', title: title, @@ -34,12 +33,6 @@ const ClassPlans = () => { observations: '', userId: id, }; - const [plans, setPlans] = useState([data]); - - async function loadPlans() { - const response = await classPlan.get('/'); - setPlans(response.data); - } const addClassPlan = () => { setVisible(true); @@ -58,7 +51,8 @@ const ClassPlans = () => { else if (title.length < 5) toast.warning('O título deve ter no mínimo 5 caracteres'); else { - await classPlan.save(data); + let newClassPlanData = await classPlan.save(data); + setClassPlans((prevArray) => [...prevArray, newClassPlanData.data]); toast.success('Plano de aula cadastrado com sucesso'); closeNewItemPanel(); setTitle(''); @@ -82,6 +76,7 @@ const ClassPlans = () => { const handleDeleteClassPlan = async () => { try { await classPlan.remove(deletedItem); + setClassPlans((prevItems) => prevItems.filter((item) => item.id != deletedItem)); toast.success('Plano de aula excluído com sucesso'); closeDeleteItemPanel(); setDeletedItem(''); @@ -91,26 +86,28 @@ const ClassPlans = () => { return; }; - useEffect(() => { - if (id != '') { - classPlan - .getManyById(id as string) - .then((response) => { - setClassPlans(response.data); - }) - .catch(() => { - setClassPlans([]); - }); + const redirectToViewPlan = async (selectedId : string) => { + try { + const response = await classPlan.getById(selectedId); + localStorage.setItem('selectedClassPlan', JSON.stringify(response.data)); + const drillsClassPlan = await drill.getManyByClassPlanId(selectedId); + const drillData = drillsClassPlan.data; + localStorage.setItem('drillsSelectedClassPlan', JSON.stringify(drillData)); + setTimeout(() => { + window.location.href = `/plano-aula/${selectedId}`; + }, 3000); + } catch(error){ + toast.error('Erro ao buscar informações do plano'); } - }, [classPlan, id]); - console.log(classPlans); - return ( + } + + return( <> } /> -
+
{}} hasReturnArrow={false}>

@@ -124,12 +121,11 @@ const ClassPlans = () => { classPlans.map((a) => { return (
- {redirectToViewPlan(a['id'])}} >

{a['title']}

- + { const listImages = [ @@ -53,35 +53,24 @@ const Drill = () => { [11, 30, seta_y_neg, 25], [12, 30, seta_y_pos, 25] ] - const { id } = useParams(); - const [title, setTitle] = useState(''); + const stringSelectedDrill = localStorage.getItem('selectedDrill'); + const selectedDrill = JSON.parse(stringSelectedDrill ? stringSelectedDrill : ''); + const stringDrillSelectedElements = localStorage.getItem('drillSelectedElements'); + const drillSelectedElements = JSON.parse(stringDrillSelectedElements ? stringDrillSelectedElements : ''); + const [title, setTitle] = useState(selectedDrill.title); const [imagemBase64, setimagemBase64] = useState(''); const [titleAux, setTitleAux] = useState(''); - const [description, setDescription] = useState(''); + const [description, setDescription] = useState(selectedDrill.description); const [descriptionAux, setDescriptionAux] = useState(''); - const [observations, setObservations] = useState(''); + const [observations, setObservations] = useState(selectedDrill.observations); const [observationsAux, setObservationsAux] = useState(''); const [titleNotEdited, setTitleNotEdited] = useState(true); const [descriptionNotEdited, setDescriptionNotEdited] = useState(true); const [observationsNotEdited, setObservationsNotEdited] = useState(true); const drill = new DrillService(); const drillElement = new DrillElementService(); - const [drillUpdated, setDrillUpdated] = useState({ - id: '', - title: '', - description: '', - observations: '', - image: '', - classPlanId: '', - }); const [newItems, setNewItems] = useState(Array<[string, number, number]>); - const [savedItems, setSavedItems] = useState([{ - id: 'id0', - index: 0, - left: 0, - top: 0 - }] - ); + const [savedItems, setSavedItems] = useState(drillSelectedElements); const [deletedSavedIds, setDeletedSavedIds] = useState([]); const [count, setCount] = useState(0); @@ -96,7 +85,6 @@ const Drill = () => { } } - const addDrillElement = (typeImage : number, width: number) => { setNewItems([...newItems, [String(count), typeImage, width]]); setCount(count + 1); @@ -107,25 +95,22 @@ const Drill = () => { } const deleteSavedItem = (idDeleted: string) => { - const node = document.getElementById(idDeleted); - if(node){ - node.style.display = 'none'; - setDeletedSavedIds((prevArray) => [...prevArray, idDeleted]); - } + setSavedItems((prevItems) => prevItems.filter((item) => item.id !== idDeleted)); + setDeletedSavedIds((prevArray) => [...prevArray, idDeleted]); } async function saveDrillState(){ - updateImagen() - let data = { - id: drillUpdated.id, - title: titleAux, - image: imagemBase64, - description: drillUpdated.description, - observations: drillUpdated.observations, - classPlanId: drillUpdated.classPlanId, - }; - console.log(data) - await drill.updateById(id as string, data); + updateImagen(); + // let data = { + // id: selectedDrill.id, + // title: titleAux, + // image: imagemBase64, + // description: selectedDrill.description, + // observations: selectedDrill.observations, + // classPlanId: selectedDrill.classPlanId, + // }; + // console.log(data) + // await drill.updateById(id as string, data); for(const [idNewItem, indexNewItem] of newItems){ try{ const element = document.getElementById(idNewItem); @@ -134,7 +119,7 @@ const Drill = () => { index: indexNewItem, top: parseInt(element.style.top.slice(0, -2)), left: parseInt(element.style.left.slice(0, -2)), - drillId: id + drillId: selectedDrill.id }; await drillElement.save(data); } @@ -152,7 +137,7 @@ const Drill = () => { index: savedItem.index, top: parseInt(element.style.top.slice(0, -2)), left: parseInt(element.style.left.slice(0, -2)), - drillId: id + drillId: selectedDrill.id }; await drillElement.updateById(savedItem.id, data); } @@ -170,48 +155,22 @@ const Drill = () => { } } toast.success('Atualizações no desenho do drill salvas com sucesso'); - setNewItems([]); const trash = document.getElementById('apagar'); if (trash) trash.style.visibility = 'hidden'; } - async function loadData() { - if (id != null) { - const response = await drill.getById(id); - setDrillUpdated(response.data); - } - } - console.log("id: " + id) - useEffect(() => { - loadData(); - setTitle(drillUpdated.title); - setDescription(drillUpdated.description); - setObservations(drillUpdated.observations); - - if (id != null) { - drillElement - .getManyByDrillId(id) - .then((response) => { - setSavedItems(response.data); - }) - .catch(() => { - setSavedItems([]); - }); - } - }, [drillUpdated]); - const startEditingTitle = () => { - setTitleAux(drillUpdated.title); + setTitleAux(title); setTitleNotEdited(false); }; const startEditingDescription = () => { - setDescriptionAux(drillUpdated.description); + setDescriptionAux(description); setDescriptionNotEdited(false); }; const startEditingObservations = () => { - setObservationsAux(drillUpdated.observations); + setObservationsAux(observations); setObservationsNotEdited(false); }; @@ -223,34 +182,38 @@ const Drill = () => { else { updateImagen() let data = { - id: drillUpdated.id, + id: selectedDrill.id, title: titleAux, image: imagemBase64, - description: drillUpdated.description, - observations: drillUpdated.observations, - classPlanId: drillUpdated.classPlanId, + description: description, + observations: observations, + classPlanId: selectedDrill.classPlanId, }; - await drill.updateById(id as string, data); + await drill.updateById(selectedDrill.id, data); + setTitle(titleAux); toast.success('Título atualizado com sucesso'); } } catch (error) { toast.error('Erro ao atualizar drill'); + } finally { + setTitleAux(''); + setTitleNotEdited(true); } - return; }; const finishEditingDescription = async () => { try { updateImagen() let data = { - id: drillUpdated.id, - title: drillUpdated.title, + id: selectedDrill.id, + title: title, description: descriptionAux, - observations: drillUpdated.observations, + observations: observations, image: imagemBase64, - classPlanId: drillUpdated.classPlanId, + classPlanId: selectedDrill.classPlanId, }; - await drill.updateById(id as string, data); + await drill.updateById(selectedDrill.id, data); + setDescription(descriptionAux) toast.success('Descrição atualizada com sucesso'); } catch (error) { toast.error('Erro ao atualizar drill'); @@ -258,7 +221,6 @@ const Drill = () => { setDescriptionAux(''); setDescriptionNotEdited(true); } - return; }; const finishEditingObservations = async () => { @@ -266,14 +228,15 @@ const Drill = () => { setObservationsAux(''); updateImagen() let data = { - id: drillUpdated.id, - title: drillUpdated.title, - description: drillUpdated.description, + id: selectedDrill.id, + title: title, + description: description, observations: observationsAux, image: imagemBase64, - classPlanId: drillUpdated.classPlanId, + classPlanId: selectedDrill.classPlanId, }; - await drill.updateById(id as string, data); + await drill.updateById(selectedDrill.id, data); + setObservations(observationsAux); toast.success('Observações atualizadas com sucesso'); } catch (error) { toast.error('Erro ao atualizar drill'); @@ -281,9 +244,25 @@ const Drill = () => { setObservationsAux(''); setObservationsNotEdited(true); } - return; }; + const redirectToViewPlan = async () => { + try { + console.log("Aqui 1"); + const classPlan = new ClassPlanService(); + const response = await classPlan.getById(selectedDrill.classPlanId); + localStorage.setItem('selectedClassPlan', JSON.stringify(response.data)); + const drillsClassPlan = await drill.getManyByClassPlanId(selectedDrill.classPlanId); + const drillData = drillsClassPlan.data; + localStorage.setItem('drillsSelectedClassPlan', JSON.stringify(drillData)); + setTimeout(() => { + window.location.href = `/plano-aula/${selectedDrill.classPlanId}`; + }, 3000); + } catch(error){ + toast.error('Erro ao buscar informações do plano'); + } + } + return ( <> { } />
{titleNotEdited ? ( @@ -363,7 +342,7 @@ const Drill = () => {

) : (