From c02a73cc6771a057749d1c1966359c7aa6edb6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borja=20Mart=C3=AD?= Date: Tue, 2 Apr 2024 19:50:45 +0200 Subject: [PATCH 1/8] brought first version of Confirm and Delete components --- src/components/Confirm.jsx | 54 ++++++++++++++++++++++++++++++++++++++ src/components/Delete.jsx | 54 ++++++++++++++++++++++++++++++++++++++ src/views/Layout.jsx | 2 ++ 3 files changed, 110 insertions(+) create mode 100644 src/components/Confirm.jsx create mode 100644 src/components/Delete.jsx diff --git a/src/components/Confirm.jsx b/src/components/Confirm.jsx new file mode 100644 index 0000000..d32f675 --- /dev/null +++ b/src/components/Confirm.jsx @@ -0,0 +1,54 @@ +import { useEffect, useRef } from 'react'; + +const Confirm = ({ open, onClose, onConfirm, children, title, loading }) => { + const confirmRef = useRef(null); + const cancelRef = useRef(null); + + // Opens/closes modal depending on open state + useEffect(() => { + const { current: el } = confirmRef; + if (open) { + el.showModal(); + cancelRef.current.focus(); + } else el.close(); + }, [open]); + + return ( + +
+
+

{title}

+
+ + {loading ? ( +
+
+
+ ) : ( + <> + {children} +
+ + +
+ + )} +
+
+ ); +}; + +export default Confirm; diff --git a/src/components/Delete.jsx b/src/components/Delete.jsx new file mode 100644 index 0000000..20ed355 --- /dev/null +++ b/src/components/Delete.jsx @@ -0,0 +1,54 @@ +import { useParams, useRouter } from 'next/navigation'; +import { useState } from 'react'; +import Confirm from '@/components/ui/confirm-comp'; + +const RemoveStudent = ({ studentId, studentEmail }) => { + const params = useParams(); + const router = useRouter(); + const [isConfirmOpen, setIsConfirmOpen] = useState(false); + const [isSubmitted, setIsSubmitted] = useState(false); + + const openConfirm = () => { + setIsConfirmOpen(true); + }; + const closeConfirm = () => { + setIsConfirmOpen(false); + }; + + const handleRemoveStudent = async () => { + setIsSubmitted(true); + const submit = await fetch(`/api/courses/${params.course}`, { + method: 'PUT', + headers: { + 'Content-type': 'application/json', + }, + body: JSON.stringify({ + updateType: 'removeStudent', + studentId: studentId, + }), + }); + router.refresh(); + }; + + return ( + <> + + + ¿Seguro que quieres echar a {studentEmail}? + + + ); +}; + +export default RemoveStudent; diff --git a/src/views/Layout.jsx b/src/views/Layout.jsx index d93bb44..d6a1f5a 100644 --- a/src/views/Layout.jsx +++ b/src/views/Layout.jsx @@ -2,6 +2,8 @@ import { Outlet } from 'react-router-dom'; import { auth } from '../api/config.js'; import { SignIn, useAuth } from '../api/useAuth.jsx'; import { NavBar } from '../components/NavBar/NavBar.jsx'; +import { useState } from 'react'; +import Loading from '../components/Loading'; import Groceries from '../assets/groceries.png'; export function Layout({ lists, listPath }) { From 4f82b6e85b8556148bc7b108301c0039f76830dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borja=20Mart=C3=AD?= Date: Wed, 3 Apr 2024 15:12:24 +0200 Subject: [PATCH 2/8] added new DeleteItem, DeleteList, and Confirm components to substitute alert-based confirm when deleting lists or items. fixed Loading component background color, Layout's main height, and ListButtons gap --- src/components/Confirm.jsx | 25 +++++++++------- src/components/Delete.jsx | 54 ---------------------------------- src/components/DeleteItem.jsx | 45 ++++++++++++++++++++++++++++ src/components/DeleteList.jsx | 48 ++++++++++++++++++++++++++++++ src/components/ListButtons.jsx | 2 +- src/components/ListItem.jsx | 21 ++----------- src/components/Loading.css | 2 +- src/components/SingleList.jsx | 40 +++++-------------------- src/components/index.js | 3 ++ src/views/Layout.jsx | 5 +--- 10 files changed, 123 insertions(+), 122 deletions(-) delete mode 100644 src/components/Delete.jsx create mode 100644 src/components/DeleteItem.jsx create mode 100644 src/components/DeleteList.jsx diff --git a/src/components/Confirm.jsx b/src/components/Confirm.jsx index d32f675..404edd5 100644 --- a/src/components/Confirm.jsx +++ b/src/components/Confirm.jsx @@ -1,4 +1,5 @@ import { useEffect, useRef } from 'react'; +import Loading from './Loading'; const Confirm = ({ open, onClose, onConfirm, children, title, loading }) => { const confirmRef = useRef(null); @@ -14,33 +15,35 @@ const Confirm = ({ open, onClose, onConfirm, children, title, loading }) => { }, [open]); return ( - -
-
-

{title}

-
+ +
+

{title}

{loading ? ( -
-
-
+ ) : ( <> {children} -
+
diff --git a/src/components/Delete.jsx b/src/components/Delete.jsx deleted file mode 100644 index 20ed355..0000000 --- a/src/components/Delete.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import { useParams, useRouter } from 'next/navigation'; -import { useState } from 'react'; -import Confirm from '@/components/ui/confirm-comp'; - -const RemoveStudent = ({ studentId, studentEmail }) => { - const params = useParams(); - const router = useRouter(); - const [isConfirmOpen, setIsConfirmOpen] = useState(false); - const [isSubmitted, setIsSubmitted] = useState(false); - - const openConfirm = () => { - setIsConfirmOpen(true); - }; - const closeConfirm = () => { - setIsConfirmOpen(false); - }; - - const handleRemoveStudent = async () => { - setIsSubmitted(true); - const submit = await fetch(`/api/courses/${params.course}`, { - method: 'PUT', - headers: { - 'Content-type': 'application/json', - }, - body: JSON.stringify({ - updateType: 'removeStudent', - studentId: studentId, - }), - }); - router.refresh(); - }; - - return ( - <> - - - ¿Seguro que quieres echar a {studentEmail}? - - - ); -}; - -export default RemoveStudent; diff --git a/src/components/DeleteItem.jsx b/src/components/DeleteItem.jsx new file mode 100644 index 0000000..85c4017 --- /dev/null +++ b/src/components/DeleteItem.jsx @@ -0,0 +1,45 @@ +import { useState } from 'react'; +import { deleteItem } from '../api/firebase'; +import Confirm from './Confirm'; + +const DeleteItem = ({ itemName, listPath, itemId }) => { + const [isConfirmOpen, setIsConfirmOpen] = useState(false); + const [isSubmitted, setIsSubmitted] = useState(false); + + const handleDelete = (listPath, itemId) => { + setIsSubmitted(true); + deleteItem(listPath, itemId); + return; + }; + + const openConfirm = () => { + setIsConfirmOpen(true); + }; + const closeConfirm = () => { + setIsConfirmOpen(false); + }; + + return ( + <> + + handleDelete(listPath, itemId)} + open={isConfirmOpen} + loading={isSubmitted} + > + {`Do you really want to delete ${itemName.toUpperCase()} from this list?`} + + + ); +}; + +export default DeleteItem; diff --git a/src/components/DeleteList.jsx b/src/components/DeleteList.jsx new file mode 100644 index 0000000..b178157 --- /dev/null +++ b/src/components/DeleteList.jsx @@ -0,0 +1,48 @@ +import { useState } from 'react'; +import { deleteList } from '../api/firebase'; +import Confirm from './Confirm'; + +const DeleteList = ({ user, email, listPath, listName, setListPath }) => { + const [isConfirmOpen, setIsConfirmOpen] = useState(false); + const [isSubmitted, setIsSubmitted] = useState(false); + + const handleDelete = (user, email, listPath, listName) => { + setIsSubmitted(true); + deleteList(user, email, listPath, listName); + setListPath(''); + return; + }; + + const openConfirm = () => { + setIsConfirmOpen(true); + }; + const closeConfirm = () => { + setIsConfirmOpen(false); + }; + + return ( + <> + + handleDelete(user, email, listPath, listName)} + open={isConfirmOpen} + loading={isSubmitted} + > + {listPath.includes(user) + ? `Do you really want to delete ${listName.toUpperCase()} list?` + : `Do you really want to stop using ${listName.toUpperCase()} list?`} + + + ); +}; + +export default DeleteList; diff --git a/src/components/ListButtons.jsx b/src/components/ListButtons.jsx index 56bb1bb..25c9b7a 100644 --- a/src/components/ListButtons.jsx +++ b/src/components/ListButtons.jsx @@ -19,7 +19,7 @@ const ListButtons = (props) => { }; return ( -
+
+
); diff --git a/src/components/Loading.css b/src/components/Loading.css index fa20fbe..fbfb7fc 100644 --- a/src/components/Loading.css +++ b/src/components/Loading.css @@ -18,7 +18,7 @@ .spinner { width: 5rem; /* 1 */ padding: 0.5rem; /* 2 */ - background: var(--color-accent); /* 3 */ + background: #6966a8; /* 3 */ aspect-ratio: 1; border-radius: 50%; diff --git a/src/components/SingleList.jsx b/src/components/SingleList.jsx index 645681f..d459689 100644 --- a/src/components/SingleList.jsx +++ b/src/components/SingleList.jsx @@ -1,5 +1,5 @@ import { useNavigate } from 'react-router-dom'; -import { deleteList } from '../api/firebase'; +import DeleteList from './DeleteList'; export function SingleList({ userEmail, name, path, setListPath, userId }) { const navigate = useNavigate(); @@ -8,29 +8,6 @@ export function SingleList({ userEmail, name, path, setListPath, userId }) { navigate(`/list/${path}`); } - function handleDelete(user, email, listPath, listName) { - if (listPath.includes(user)) { - if ( - window.confirm( - `Do you really want to delete ${listName.toUpperCase()} list?`, - ) - ) { - deleteList(user, email, listPath, listName); - setListPath(''); - } - return; - } - if ( - window.confirm( - `Do you really want to stop using ${listName.toUpperCase()} list?`, - ) - ) { - deleteList(user, email, listPath, listName); - setListPath(''); - } - return; - } - return (
  • - +
  • ); } diff --git a/src/components/index.js b/src/components/index.js index 5499a34..c79d746 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -5,3 +5,6 @@ export * from './SearchList'; export * from './Loading'; export * from './ButtonWithIcon'; export * from './ErrorMessage'; +export * from './DeleteList'; +export * from './Confirm'; +export * from './DeleteItem'; diff --git a/src/views/Layout.jsx b/src/views/Layout.jsx index 5d4baaf..dfaa0e9 100644 --- a/src/views/Layout.jsx +++ b/src/views/Layout.jsx @@ -1,9 +1,6 @@ import { Outlet } from 'react-router-dom'; -import { auth } from '../api/config.js'; import { SignIn, useAuth } from '../api/useAuth.jsx'; import { NavBar } from '../components/NavBar/NavBar.jsx'; -import { useState } from 'react'; -import Loading from '../components/Loading'; import Groceries from '../assets/groceries.png'; export function Layout({ lists, listPath }) { @@ -16,7 +13,7 @@ export function Layout({ lists, listPath }) { return (
    -
    +
    {!!user ? ( ) : ( From 1150e2679d5ba9d474d534eddec0656e3d46d2b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borja=20Mart=C3=AD?= Date: Wed, 3 Apr 2024 15:26:02 +0200 Subject: [PATCH 3/8] fixed hover behavior on buttons from List and ManageList views --- src/components/ListButtons.jsx | 19 +++++++++---------- src/views/ManageList.jsx | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/components/ListButtons.jsx b/src/components/ListButtons.jsx index 25c9b7a..8f2dc89 100644 --- a/src/components/ListButtons.jsx +++ b/src/components/ListButtons.jsx @@ -3,9 +3,10 @@ const ListButtons = (props) => { const navigate = useNavigate(); const buttonVariants = { - purple: 'flex items-center justify-center rounded-md bg-lightPurple', + purple: + 'text-base sm:text-lg text-offWhite flex items-center justify-center rounded-md bg-lightPurple transition ease-in-out hover:bg-hoverPurple', white: - 'flex items-center justify-center rounded-md bg-lightGrey border text-darkPurple', + 'text-base sm:text-lg text-darkPurple flex items-center justify-center rounded-md bg-lightGrey border text-darkPurple transition ease-in-out hover:bg-hoverPurple hover:text-offWhite', }; const iconVariants = { @@ -14,8 +15,8 @@ const ListButtons = (props) => { }; const textVariants = { - purple: 'text-base sm:text-lg text-offWhite font-poppins', - white: 'text-base sm:text-lg text-darkPurple font-poppins', + purple: 'font-poppins', + white: ' font-poppins', }; return ( @@ -24,19 +25,17 @@ const ListButtons = (props) => { className={`sm:col-span-2 px-4 py-2 gap-6 shadow-lg ${buttonVariants[props.colorAdd]}`} onClick={() => navigate('/manage-list')} > - + - Add item + Add item
    ); diff --git a/src/views/ManageList.jsx b/src/views/ManageList.jsx index 4cea064..f96aa7e 100644 --- a/src/views/ManageList.jsx +++ b/src/views/ManageList.jsx @@ -179,7 +179,7 @@ export function ManageList({ data, listPath, userId, userEmail }) { >