From 2e75350284df9cc61163e15f79d3d51779a4862a Mon Sep 17 00:00:00 2001 From: VnszinN Date: Mon, 18 Aug 2025 00:26:59 -0300 Subject: [PATCH 1/6] fix: adjust modal responsiviness / feat: add toast when exceeding max value --- .../src/pages/depositos/depositos.module.scss | 148 +++++-- frontend/src/pages/depositos/index.jsx | 399 ++++++++++-------- 2 files changed, 343 insertions(+), 204 deletions(-) diff --git a/frontend/src/pages/depositos/depositos.module.scss b/frontend/src/pages/depositos/depositos.module.scss index 652702d..5d85556 100644 --- a/frontend/src/pages/depositos/depositos.module.scss +++ b/frontend/src/pages/depositos/depositos.module.scss @@ -1,5 +1,6 @@ .body { min-height: 75dvh; + h1 { margin: 5% 0% 0% 3%; } @@ -11,7 +12,7 @@ justify-content: center; align-items: center; margin-top: 7%; - + p { margin: auto; color: black; @@ -22,7 +23,11 @@ padding-top: 5%; } -.infoSection p, .btnRegisterDeposit, .modalBody label, .modalImagePreviewContainer p, .modalSubmit { +.infoSection p, +.btnRegisterDeposit, +.modalBody label, +.modalImagePreviewContainer p, +.modalSubmit { font-family: 'Tankindred', sans-serif; } @@ -34,7 +39,8 @@ width: 40%; } -.btnRegisterDeposit, .pointFullError { +.btnRegisterDeposit, +.pointFullError { margin: 5% 0% 3% 0%; } @@ -53,9 +59,9 @@ border-radius: 10px; background-color: #F1F1F1; padding: 20px; - position: absolute; - top: 50%; - left: 50%; + position: absolute; + top: 50%; + left: 50%; transform: translate(-50%, -50%); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25); } @@ -130,45 +136,113 @@ margin-top: 2%; } +@media(max-width:1340px) { + .modalBody { + width: 50%; + padding: 3% + } + + .modalClose { + margin-bottom: -9%; + } +} + +@media(max-width:1115px) { + .modalForm label { + font-size: 17px; + } + + .modalForm div label { + font-size: 15px; + } + +} + +@media (max-width: 1035px) { + .infoSection { + max-width: 100%; + padding: 2% 5%; + margin-top: 4%; + } + + .modalSubmit { + display: flex; + text-align: center; + justify-content: center; + margin-right: 5%; + font-size: 80%; + min-width: 25px; + padding: 2%; + } +} + +@media(max-width:870px) { + .modalForm div label { + font-size: 13px; + } + +} + @media (max-width: 768px) { - .modalBody { - width: 90%; - padding: 15px; - } + .modalBody { + width: 80%; + padding: 5% 5%; + justify-content: center; + align-items: center; + } - .modalInputSpongeAmount { - width: 100%; - font-size: 1rem; - } + .modalForm { + width: 100%; + justify-content: center; + align-items: center; + } - .modalLabelInputImage { - width: 100%; - height: 20dvh; - font-size: 0.9rem; - } + .modalForm div label { + min-width: 90%; + } - .modalImagePreviewContainer { - width: 100%; + .modalForm div { + min-width: 70%; + } - img { - max-width: 80%; + .modalInputSpongeAmount { + margin-left: 0%; + width: 100%; + font-size: 1rem; } - button { - font-size: 0.9rem; - padding: 2%; + .modalLabelInputImage { + width: 100%; + height: 20dvh; + font-size: 0.9rem; } - } - .modalSubmit { - width: 100%; - font-size: 1rem; - padding: 10px; - } + .modalInputImage { + width: 90%; + } - .modalForm label, - .modalImagePreviewContainer p { - font-size: 1rem; - text-align: center; - } + .modalImagePreviewContainer { + width: 100%; + + img { + max-width: 80%; + } + + button { + font-size: 0.9rem; + padding: 2%; + } + } + + .modalSubmit { + display: flex; + width: 50%; + margin-left: 5%; + font-size: 1rem; + } } + +.modalForm label, +.modalImagePreviewContainer p { + font-size: 1rem; +} \ No newline at end of file diff --git a/frontend/src/pages/depositos/index.jsx b/frontend/src/pages/depositos/index.jsx index 4819731..de04757 100644 --- a/frontend/src/pages/depositos/index.jsx +++ b/frontend/src/pages/depositos/index.jsx @@ -2,182 +2,247 @@ import { useEffect, useState } from "react"; import { useNavigate, useParams } from "react-router-dom"; import Header from "../../components/Header"; import Footer from "../../components/Footer"; -import depositos from './depositos.module.scss' +import depositos from "./depositos.module.scss"; import { MdClose } from "react-icons/md"; -import api from "../../api.js" -import { toast } from "react-toastify" +import api from "../../api.js"; +import { toast } from "react-toastify"; import { useLocation } from "react-router-dom"; const Depositos = () => { - - const { id: idUrl } = useParams(); - const loc = useLocation(); - - let id = null; - - if (loc.state?.id) { - id = loc.state.id; // prioridade para o que veio no state - } else { - id = idUrl; // se não tiver no state, pega da URL - } - - console.log(id) - - const [pointData, setPointData] = useState({ - name: "", - location: "", - amountSponges: 0, - capacitySponges: 0, - isInactive: 0 - }) - const [depositAmount, setDepositAmount] = useState(0); - const [, setImageURL] = useState(""); - const [preview, setPreview] = useState(null); - const [imageFile, setImageFile] = useState(null); // arquivo real - const [modalRegisterDeposit, setModalRegisterDeposit] = useState(false); - - const nav = useNavigate(); - - const handleClose = () => { - setImageURL(null); - setPreview(null); - setDepositAmount(0); - setModalRegisterDeposit(false); - } - - const handleImageUpload = (event) => { - const file = event.target.files[0]; - if (file) { - setImageFile(file); // guarda o arquivo real - setPreview(URL.createObjectURL(file)); // gera preview - } - } - - const handleImageDeletion = () => { - setPreview(null); - setImageURL(null); - } - - async function getCollectionPointData() { - try { - let req = await api.get(`/collectionPoint/${id}`); - - if(req.status == 200) { - setPointData({ - name: req.data.name, - location: req.data.location, - amountSponges: req.data.amountSponges, - capacitySponges: req.data.capacitySponges, - isInactive: req.data.isInactive - }) - } - } catch(error) { - - console.log(error); - if(error.response){ - setTimeout(()=>{ - toast.error(error.response.data.message); - },1000); - }else{ - setTimeout(()=>{ - toast.error('Servidor não respondeu. Verifique sua conexão ou tente mais tarde.'); - },1000); - } - } + const { id: idUrl } = useParams(); + const loc = useLocation(); + + let id = null; + + if (loc.state?.id) { + id = loc.state.id; // prioridade para o que veio no state + } else { + id = idUrl; // se não tiver no state, pega da URL + } + + console.log(id); + + const [pointData, setPointData] = useState({ + name: "", + location: "", + amountSponges: 0, + capacitySponges: 0, + isInactive: 0, + }); + const [depositAmount, setDepositAmount] = useState(0); + const [, setImageURL] = useState(""); + const [preview, setPreview] = useState(null); + const [imageFile, setImageFile] = useState(null); // arquivo real + const [modalRegisterDeposit, setModalRegisterDeposit] = useState(false); + + const nav = useNavigate(); + + const handleClose = () => { + setImageURL(null); + setPreview(null); + setDepositAmount(0); + setModalRegisterDeposit(false); + }; + + const handleImageUpload = (event) => { + const file = event.target.files[0]; + if (file) { + setImageFile(file); // guarda o arquivo real + setPreview(URL.createObjectURL(file)); // gera preview } - - const handleSubmit = () => { - if(depositAmount >= 1) { - registerDeposit(); - } else toast.error("Insira um valor de depósito válido!") + }; + + const handleImageDeletion = () => { + setPreview(null); + setImageURL(null); + }; + + async function getCollectionPointData() { + try { + let req = await api.get(`/collectionPoint/${id}`); + + if (req.status == 200) { + setPointData({ + name: req.data.name, + location: req.data.location, + amountSponges: req.data.amountSponges, + capacitySponges: req.data.capacitySponges, + isInactive: req.data.isInactive, + }); + } + } catch (error) { + console.log(error); + if (error.response) { + setTimeout(() => { + toast.error(error.response.data.message); + }, 1000); + } else { + setTimeout(() => { + toast.error( + "Servidor não respondeu. Verifique sua conexão ou tente mais tarde." + ); + }, 1000); + } } - - async function registerDeposit() { - const formData = new FormData(); - formData.append("depositData", JSON.stringify({ amountSponges: depositAmount })); - formData.append('comprovante', imageFile); - - try { - - let req = await api.post(`/deposit/${id}`, formData ); - - if(req.status == 201){ - toast.success("Depósito registrado com sucesso!"); - setTimeout(() => { - nav('/home'); - }, 2000) - } - } catch(error) { - if(error.response){ - setTimeout(()=>{ - toast.error(error.response.data.message); - },1000); - }else{ - setTimeout(()=>{ - toast.error('Servidor não respondeu. Verifique sua conexão ou tente mais tarde.'); - },1000); - } - - } + } + + const handleSubmit = () => { + if (depositAmount >= 1) { + registerDeposit(); + } else toast.error("Insira um valor de depósito válido!"); + }; + + async function registerDeposit() { + const formData = new FormData(); + formData.append( + "depositData", + JSON.stringify({ amountSponges: depositAmount }) + ); + formData.append("comprovante", imageFile); + + try { + let req = await api.post(`/deposit/${id}`, formData); + + if (req.status == 201) { + toast.success("Depósito registrado com sucesso!"); + setTimeout(() => { + nav("/home"); + }, 2000); + } + } catch (error) { + if (error.response) { + setTimeout(() => { + toast.error(error.response.data.message); + }, 1000); + } else { + setTimeout(() => { + toast.error( + "Servidor não respondeu. Verifique sua conexão ou tente mais tarde." + ); + }, 1000); + } } - - useEffect(() => { - getCollectionPointData(); - },[]) - - return ( - <> -
-
-

Ponto de Coleta: {pointData.name}

-
+ } + + const validDigits = (text) => { + return text.replace(/[^0-9,]/g, ""); + }; + + useEffect(() => { + getCollectionPointData(); + }, []); + + return ( + <> +
+
+

Ponto de Coleta: {pointData.name}

+
+
+

Este ponto de coleta está localizado em {pointData.location}.

+

+ Obs: Lembre-se de conferir se este é realmente o ponto de coleta + que você está. +

+ +

+ Situação: {pointData.isInactive ? "Inativo" : "Ativo"} +

+
+ + {pointData.amountSponges == pointData.capacitySponges ? ( +

+ Este ponto de coleta está cheio! +

+ ) : ( + + )} +
+
+ + {modalRegisterDeposit && ( +
+
+
+ + + + { + const num = validDigits(event.target.value); + const maxValue = + pointData.capacitySponges - pointData.amountSponges; + + if (num > maxValue) { + // setDepositAmount(maxValue); + toast.error( + "Depósito inválido, pois ultrapassará o limite de esponjas." + ); + } else { + setDepositAmount(num); + } + }} + > + + {preview ? ( +
+

Pré-visualização:

+ Pré-visualização + + +
+ ) : (
-

Este ponto de coleta está localizado em {pointData.location}.

-

Obs: Lembre-se de conferir se este é realmente o ponto de coleta que você está.

- -

Situação: {pointData.isInactive ? "Inativo" : "Ativo"}

+ + handleImageUpload(event)} + >
- - {pointData.amountSponges == pointData.capacitySponges ? ( -

Este ponto de coleta está cheio!

- ) : ( - - )} -
+ )} + + + +
+ )} - {modalRegisterDeposit && -
-
-
- - - - setDepositAmount(event.target.value)}> - - {preview ? ( -
-

Pré-visualização:

- Pré-visualização - - -
- ) : ( -
- - handleImageUpload(event)}> -
- )} - - -
-
-
- } - -