diff --git a/backend/src/controllers/ContactController.js b/backend/src/controllers/ContactController.js index a5fdf57..a50ba0b 100644 --- a/backend/src/controllers/ContactController.js +++ b/backend/src/controllers/ContactController.js @@ -61,14 +61,18 @@ exports.store = async (req, res) => { exports.show = async (req, res) => { const { contactId } = req.params; - const { id, name, number, extraInfo } = await Contact.findByPk(contactId, { - include: [{ model: ContactCustomField, as: "extraInfo" }], - }); + const { id, name, number, email, extraInfo } = await Contact.findByPk( + contactId, + { + include: [{ model: ContactCustomField, as: "extraInfo" }], + } + ); res.status(200).json({ id, name, number, + email, extraInfo, }); }; @@ -93,3 +97,23 @@ exports.update = async (req, res) => { res.status(200).json(contact); }; + +exports.delete = async (req, res) => { + const io = getIO(); + const { contactId } = req.params; + + const contact = await Contact.findByPk(contactId); + + if (!contact) { + return res.status(400).json({ error: "No contact found with this ID" }); + } + + await contact.destroy(); + + io.emit("contact", { + action: "delete", + contactId: contactId, + }); + + res.status(200).json({ message: "Contact deleted" }); +}; diff --git a/backend/src/routes/contacts.js b/backend/src/routes/contacts.js index 74255d7..64aff36 100644 --- a/backend/src/routes/contacts.js +++ b/backend/src/routes/contacts.js @@ -13,4 +13,6 @@ routes.post("/contacts", isAuth, ContactController.store); routes.put("/contacts/:contactId", isAuth, ContactController.update); +routes.delete("/contacts/:contactId", isAuth, ContactController.delete); + module.exports = routes; diff --git a/frontend/package.json b/frontend/package.json index 4916b2b..c9e0c07 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,7 +22,6 @@ "react-modal-image": "^2.5.0", "react-router-dom": "^5.2.0", "react-scripts": "3.4.1", - "shortid": "^2.2.15", "socket.io-client": "^2.3.0" }, "scripts": { diff --git a/frontend/src/components/ConfirmationModal/ConfirmationModal.js b/frontend/src/components/ConfirmationModal/ConfirmationModal.js new file mode 100644 index 0000000..1a48158 --- /dev/null +++ b/frontend/src/components/ConfirmationModal/ConfirmationModal.js @@ -0,0 +1,43 @@ +import React from "react"; +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import Typography from "@material-ui/core/Typography"; + +const ConfirmationModal = ({ title, children, open, setOpen, onConfirm }) => { + return ( + setOpen(false)} + aria-labelledby="confirm-dialog" + > + {title} + + {children} + + + + + + + ); +}; + +export default ConfirmationModal; diff --git a/frontend/src/components/Navbar/DefaultNavbar.js b/frontend/src/components/Navbar/DefaultNavbar.js deleted file mode 100644 index abb42f2..0000000 --- a/frontend/src/components/Navbar/DefaultNavbar.js +++ /dev/null @@ -1,37 +0,0 @@ -import React from "react"; - -import { Navbar, Nav, Container } from "react-bootstrap"; -import { LinkContainer } from "react-router-bootstrap"; - -const LogedinNavbar = () => { - return ( -
- - - - EconoWhatsBot - - - - - - Login - - - Signup - - - - -
- ); -}; - -export default LogedinNavbar; diff --git a/frontend/src/components/Navbar/LogedinNavbar.js b/frontend/src/components/Navbar/LogedinNavbar.js deleted file mode 100644 index cecdf77..0000000 --- a/frontend/src/components/Navbar/LogedinNavbar.js +++ /dev/null @@ -1,52 +0,0 @@ -import React from "react"; -import { useHistory } from "react-router-dom"; -import { Navbar, Nav, Container } from "react-bootstrap"; -import { LinkContainer } from "react-router-bootstrap"; -import "./Navbar.css"; - -const DefaultNavbar = () => { - const username = localStorage.getItem("username"); - const history = useHistory(); - - const handleLogout = e => { - e.preventDefault(); - localStorage.removeItem("token"); - localStorage.removeItem("userName"); - localStorage.removeItem("userId"); - history.push("/"); - }; - - return ( -
- - - - EconoWhatsBot - - - - - - Logado como: {username} - - - Logout - - - - -
- ); -}; - -export default DefaultNavbar; diff --git a/frontend/src/components/Navbar/Navbar.css b/frontend/src/components/Navbar/Navbar.css deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/pages/Contacts/ContactModal.js b/frontend/src/pages/Contacts/ContactModal.js index c44888c..2bd89fa 100644 --- a/frontend/src/pages/Contacts/ContactModal.js +++ b/frontend/src/pages/Contacts/ContactModal.js @@ -12,6 +12,8 @@ import DialogTitle from "@material-ui/core/DialogTitle"; import Typography from "@material-ui/core/Typography"; import IconButton from "@material-ui/core/IconButton"; import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import { green } from "@material-ui/core/colors"; import { makeStyles } from "@material-ui/core/styles"; @@ -34,6 +36,20 @@ const useStyles = makeStyles(theme => ({ justifyContent: "center", alignItems: "center", }, + + btnWrapper: { + // margin: theme.spacing(1), + position: "relative", + }, + + buttonProgress: { + color: green[500], + position: "absolute", + top: "50%", + left: "50%", + marginTop: -12, + marginLeft: -12, + }, })); const ContactModal = ({ @@ -82,17 +98,12 @@ const ContactModal = ({ handleClose(); }; - console.log(contact); - console.log("id", contactId); - return (
@@ -117,7 +128,7 @@ const ContactModal = ({ }) => ( <> - Adicionar contato + {contactId ? "Editar contato" : "Adicionar contato"} @@ -215,11 +226,28 @@ const ContactModal = ({ - - diff --git a/frontend/src/pages/Contacts/ContactsList.js b/frontend/src/pages/Contacts/ContactsList.js index ab9de31..eea5e08 100644 --- a/frontend/src/pages/Contacts/ContactsList.js +++ b/frontend/src/pages/Contacts/ContactsList.js @@ -25,6 +25,9 @@ import EditIcon from "@material-ui/icons/Edit"; import PaginationActions from "./PaginationActions"; import api from "../../util/api"; import ContactModal from "./ContactModal"; +import ContactsSekeleton from "./ContactsSekeleton"; + +import ConfirmationModal from "../../components/ConfirmationModal/ConfirmationModal"; const useStyles = makeStyles(theme => ({ mainContainer: { @@ -68,7 +71,7 @@ const Contacts = () => { const classes = useStyles(); const token = localStorage.getItem("token"); - const userId = localStorage.getItem("userId"); + // const userId = localStorage.getItem("userId"); const [loading, setLoading] = useState(true); const [page, setPage] = useState(0); @@ -80,6 +83,9 @@ const Contacts = () => { const [modalOpen, setModalOpen] = useState(false); + const [deletingContact, setDeletingContact] = useState(null); + const [confirmOpen, setConfirmOpen] = useState(false); + useEffect(() => { setLoading(true); const delayDebounceFn = setTimeout(() => { @@ -108,6 +114,10 @@ const Contacts = () => { if (data.action === "update" || data.action === "create") { updateContacts(data.contact); } + + if (data.action === "delete") { + deleteContact(data.contactId); + } }); return () => { @@ -128,6 +138,18 @@ const Contacts = () => { }); }; + const deleteContact = contactId => { + setContacts(prevState => { + const contactIndex = prevState.findIndex(c => c.id === +contactId); + + if (contactIndex === -1) return prevState; + + const aux = [...prevState]; + aux.splice(contactIndex, 1); + return aux; + }); + }; + const handleChangePage = (event, newPage) => { setPage(newPage); }; @@ -156,6 +178,11 @@ const Contacts = () => { setModalOpen(true); }; + const handleDeleteContact = async contactId => { + await api.delete(`/contacts/${contactId}`); + setDeletingContact(null); + }; + return ( { aria-labelledby="form-dialog-title" contactId={selectedContactId} > + handleDeleteContact(deletingContact.id)} + > + Tem certeza que deseja deletar este contato? Todos os tickets + relacionados serĂ£o perdidos. +
Contatos @@ -204,27 +240,40 @@ const Contacts = () => { - {contacts.map(contact => ( - - - {} - - {contact.name} - {contact.number} - {contact.updatedAt} - - hadleEditContact(contact.id)} - > - - - - - - - - ))} + {loading ? ( + + ) : ( + <> + {contacts.map(contact => ( + + + {} + + {contact.name} + {contact.number} + {contact.email} + + hadleEditContact(contact.id)} + > + + + + { + setConfirmOpen(true); + setDeletingContact(contact); + }} + > + + + + + ))} + + )} diff --git a/frontend/src/pages/Contacts/ContactsSekeleton.js b/frontend/src/pages/Contacts/ContactsSekeleton.js new file mode 100644 index 0000000..fc5ffe6 --- /dev/null +++ b/frontend/src/pages/Contacts/ContactsSekeleton.js @@ -0,0 +1,163 @@ +import React from "react"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Skeleton from "@material-ui/lab/Skeleton"; + +const ContactsSekeleton = () => { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default ContactsSekeleton; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index e0fd2c7..74a2684 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -7372,11 +7372,6 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== -nanoid@^2.1.0: - version "2.1.11" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" - integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -9954,13 +9949,6 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shortid@^2.2.15: - version "2.2.15" - resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.15.tgz#2b902eaa93a69b11120373cd42a1f1fe4437c122" - integrity sha512-5EaCy2mx2Jgc/Fdn9uuDuNIIfWBpzY4XIlhoqtXF6qsf+/+SGZ+FxDdX/ZsMZiWupIWNqAEmiNY4RC+LSmCeOw== - dependencies: - nanoid "^2.1.0" - side-channel@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947"