From 40455520eb90d99b46b723aecf2817189adb9ed9 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 11:26:07 -0400 Subject: [PATCH 01/23] fix: update exports from components folder, add ShareList --- src/components/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/index.js b/src/components/index.js index b1b83c6..8c3c8c0 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -1,6 +1,7 @@ export * from './ListItem'; export * from './SingleList'; export * from './AddItems'; +export * from './ShareList'; export * from './TextInputElement'; export * from './RadioInputElement'; export * from './ConfirmDialog'; From 7e4e609ef235c99e1379f2d54a05ce2afe064d79 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 11:28:29 -0400 Subject: [PATCH 02/23] feat: update imports, add MUI Box component --- src/views/ManageList.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/views/ManageList.jsx b/src/views/ManageList.jsx index f9857ea..4adfc4c 100644 --- a/src/views/ManageList.jsx +++ b/src/views/ManageList.jsx @@ -1,14 +1,14 @@ -import { AddItems } from '../components/AddItems'; -import { ShareList } from '../components/ShareList'; import { useEnsureListPath } from '../hooks/useEnsureListPath'; +import Box from '@mui/material/Box'; +import { AddItems, ShareList } from '../components'; export function ManageList({ items }) { // Redirect to home if no list path is null if (useEnsureListPath()) return <>; return ( -
+ -
+ ); } From 7fa8bf140368d2e38fa0b2f775de69c2b72906df Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 11:35:48 -0400 Subject: [PATCH 03/23] feat: use MUI Button component for sign in and sign out buttons --- src/hooks/useAuth.jsx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/hooks/useAuth.jsx b/src/hooks/useAuth.jsx index d8d7b51..71ae0f3 100644 --- a/src/hooks/useAuth.jsx +++ b/src/hooks/useAuth.jsx @@ -2,6 +2,8 @@ import { useEffect, useState } from 'react'; import { auth } from '../api/config.js'; import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth'; import { addUserToDatabase } from '../api/firebase.js'; +import { Button } from '@mui/material'; +import { buttonStyle } from '../components/SingleList.jsx'; /** * A button that signs the user in using Google OAuth. When clicked, @@ -9,21 +11,28 @@ import { addUserToDatabase } from '../api/firebase.js'; * After the user signs in through the popup, it closes and the user becomes signed in. */ export const SignInButton = () => ( - + ); /** * A button that signs the user out of the app using Firebase Auth. */ export const SignOutButton = () => ( - + ); /** From e3d20e4b739a5bddd2e5f8ed6523c3397735b3f7 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:00:10 -0400 Subject: [PATCH 04/23] fix: update buttonStyle import --- src/hooks/useAuth.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useAuth.jsx b/src/hooks/useAuth.jsx index 71ae0f3..1282ff2 100644 --- a/src/hooks/useAuth.jsx +++ b/src/hooks/useAuth.jsx @@ -3,7 +3,7 @@ import { auth } from '../api/config.js'; import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth'; import { addUserToDatabase } from '../api/firebase.js'; import { Button } from '@mui/material'; -import { buttonStyle } from '../components/SingleList.jsx'; +import { buttonStyle } from '../views/Home.jsx'; /** * A button that signs the user in using Google OAuth. When clicked, From 86fe281daf430940ed3cdb6acd1a24d4d3b1266e Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:01:03 -0400 Subject: [PATCH 05/23] fix: remove comments --- src/views/Layout.jsx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/views/Layout.jsx b/src/views/Layout.jsx index ff58ad7..346b030 100644 --- a/src/views/Layout.jsx +++ b/src/views/Layout.jsx @@ -1,18 +1,9 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ import { Outlet, NavLink } from 'react-router-dom'; import { useAuth, SignInButton, SignOutButton } from '../hooks/useAuth'; -// import { Home, List, ManageList } from '../views'; import './Layout.css'; -/** - * TODO: The links defined in this file don't work! - * - * Instead of anchor element, they should use a component - * from `react-router-dom` to navigate to the routes - * defined in `App.jsx`. - */ - export function Layout() { const { user } = useAuth(); From 9d8b167b207f8716fd8d6235a4a7726ec5bff328 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:02:54 -0400 Subject: [PATCH 06/23] feat: add MUI components and update labels to be more friendly --- src/views/Home.jsx | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/views/Home.jsx b/src/views/Home.jsx index dc3219b..005bb02 100644 --- a/src/views/Home.jsx +++ b/src/views/Home.jsx @@ -1,8 +1,9 @@ +import { Fragment } from 'react'; import { useNavigate } from 'react-router-dom'; import { createList } from '../api'; import { toast } from 'react-toastify'; import { useImportance } from '../hooks'; -import { ButtonGroup, Button } from '@mui/material'; +import { Divider, Button, List as UnorderedList } from '@mui/material'; import { SingleList, TextInputElement } from '../components'; import './Home.css'; @@ -11,6 +12,15 @@ export const buttonStyle = { fontSize: '1.5rem', }; +export const buttonWithTopMarginStyle = { + ...buttonStyle, + marginTop: '0.5rem', +}; + +const dividerStyle = { + borderColor: 'primary.main', +}; + export function Home({ data, setListPath, userId, userEmail }) { const { sortedLists, setImportantList, isListImportant } = useImportance(data); @@ -46,32 +56,32 @@ export function Home({ data, setListPath, userId, userEmail }) {
- -
    - - {sortedLists.map((item, index) => { - return ( + + {sortedLists.map((item, index) => { + return ( + - ); - })} - -
+ + + ); + })} + ); } From fe85941bdac887bf3539681aede6dd6da09943da Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:04:59 -0400 Subject: [PATCH 07/23] feat: add MUI components and minor custom styling --- src/components/AddItems.jsx | 57 ++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/src/components/AddItems.jsx b/src/components/AddItems.jsx index 7b0d01a..27ec253 100644 --- a/src/components/AddItems.jsx +++ b/src/components/AddItems.jsx @@ -1,9 +1,16 @@ import { useCallback } from 'react'; -import { normalizeItemName } from '../utils'; import { useStateWithStorage } from '../hooks'; import { addItem } from '../api'; +import { normalizeItemName } from '../utils'; import { RadioInputElement, TextInputElement } from './index.js'; import { toast } from 'react-toastify'; +import { Box, Button, FormControl, RadioGroup } from '@mui/material'; +import { buttonStyle } from '../views'; + +const radioGroupStyle = { + mx: 1, + justifyContent: 'space-between', +}; const daysUntilPurchaseOptions = { Soon: 7, @@ -59,27 +66,43 @@ export function AddItems({ items }) { ); return ( -
-
+ + + + + {Object.entries(daysUntilPurchaseOptions).map(([key, value]) => ( + + ))} + + - {Object.entries(daysUntilPurchaseOptions).map(([key, value]) => ( - - ))} - - -
+ + + ); } From 7358af1934208d8f69751757595b9488c2e61362 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:08:17 -0400 Subject: [PATCH 08/23] feat: use TextField component instead of input and use Typography component instead of label tag; change color of elements --- src/components/TextInputElement.jsx | 43 +++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/components/TextInputElement.jsx b/src/components/TextInputElement.jsx index f76414c..b0f373e 100644 --- a/src/components/TextInputElement.jsx +++ b/src/components/TextInputElement.jsx @@ -1,3 +1,30 @@ +import { TextField, Typography } from '@mui/material'; +import { typographyStyle } from './ConfirmDialog'; + +const textFieldStyle = { + '& .MuiInputBase-input': { + fontSize: '1.7rem', + color: 'white', + borderColor: 'white', + }, + '& .MuiInputBase-input::placeholder': { + color: 'white', + fontSize: '1.5rem', + letterSpacing: '0.1rem', + }, + '& .MuiOutlinedInput-root': { + '& fieldset': { + borderColor: 'primary.main', // Set the border color to primary.main + }, + '&:hover fieldset': { + borderColor: 'primary.main', // Set border color on hover + }, + '&.Mui-focused fieldset': { + borderColor: 'primary.main', // Set border color when focused + }, + }, +}; + export function TextInputElement({ label, type, @@ -8,14 +35,26 @@ export function TextInputElement({ }) { return ( <> - + + {label} +
-
From f0d4eb1eaacf7013e2466236380ff398910228e9 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:15:06 -0400 Subject: [PATCH 09/23] feat: ConfirmDialog exports typography style --- src/components/ConfirmDialog.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ConfirmDialog.jsx b/src/components/ConfirmDialog.jsx index 69eb804..f4447da 100644 --- a/src/components/ConfirmDialog.jsx +++ b/src/components/ConfirmDialog.jsx @@ -8,7 +8,7 @@ import { Button, } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; -import { buttonStyle } from './SingleList'; +import { buttonStyle } from '../views'; import './ConfirmDialog.css'; // MUI's Dialog already comes with built-in focus management and accessibility features. @@ -23,7 +23,7 @@ const dialogStyle = { backgroundColor: 'rgb(20, 20, 20)', }; -const typographyStyle = { +export const typographyStyle = { padding: '1em', color: 'white', }; From 76e3090648fc69c0e20a269489edb8d0505617f9 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:16:41 -0400 Subject: [PATCH 10/23] feat: add MUI components and minor custom styling --- src/components/RadioInputElement.jsx | 40 ++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/components/RadioInputElement.jsx b/src/components/RadioInputElement.jsx index 3a38645..d12bc3d 100644 --- a/src/components/RadioInputElement.jsx +++ b/src/components/RadioInputElement.jsx @@ -1,15 +1,33 @@ +import { Radio, Tooltip, FormControlLabel } from '@mui/material'; +import { tooltipStyle } from './DeleteIconWithTooltip'; + +const radioStyle = { + color: 'white', + m: 2, + my: 3, +}; + export const RadioInputElement = ({ label, id, value, required }) => { return ( - <> - - -
- + + } + label={ + {`${value} days from today`}

} + arrow + > + {label} +
+ } + /> ); }; From f41fd520ba59bb874c17fc6f2a3543715e0d1b6f Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:18:41 -0400 Subject: [PATCH 11/23] feat: add MUI components --- src/components/ShareList.jsx | 30 ++++++++++++++++++++++-------- src/components/SingleList.css | 1 + 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/components/ShareList.jsx b/src/components/ShareList.jsx index 26f7801..e4bf5b7 100644 --- a/src/components/ShareList.jsx +++ b/src/components/ShareList.jsx @@ -1,7 +1,9 @@ -import { shareList } from '../api'; import { useStateWithStorage, useAuth } from '../hooks'; -import { TextInputElement } from './index.js'; +import { shareList } from '../api'; import { toast } from 'react-toastify'; +import { Box, Button } from '@mui/material'; +import { TextInputElement } from './index.js'; +import { buttonWithTopMarginStyle } from '../views/Home'; export function ShareList() { const [listPath] = useStateWithStorage('tcl-shopping-list-path', null); @@ -39,17 +41,29 @@ export function ShareList() { }; return ( -
-
+ + - - -
+ + + ); } diff --git a/src/components/SingleList.css b/src/components/SingleList.css index d6be38f..70c61be 100644 --- a/src/components/SingleList.css +++ b/src/components/SingleList.css @@ -1,6 +1,7 @@ .SingleList { align-items: baseline; display: flex; + width: inherit; flex-direction: row; align-items: center; font-size: 1.2em; From 13c9e46a4a6e9e846c734f250eabff4ad773922d Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:21:51 -0400 Subject: [PATCH 12/23] feat: update SingleList component - update imports; - add MUI components; - add Tooltips. --- src/components/SingleList.jsx | 80 ++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/src/components/SingleList.jsx b/src/components/SingleList.jsx index f8e8ae7..d6de756 100644 --- a/src/components/SingleList.jsx +++ b/src/components/SingleList.jsx @@ -1,13 +1,18 @@ -import { useNavigate } from 'react-router-dom'; import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import { toast } from 'react-toastify'; -import { PushPin, PushPinOutlined } from '@mui/icons-material'; -import { Tooltip, IconButton, Button } from '@mui/material'; import { deleteList } from '../api'; -import { useAuth } from '../hooks'; -import { useConfirmDialog } from '../hooks/useConfirmDialog'; -import { ConfirmDialog } from './ConfirmDialog'; -import { tooltipStyle, DeleteIconWithTooltip } from './DeleteIconWithTooltip'; +import { useAuth, useConfirmDialog } from '../hooks'; +import { tooltipStyle, DeleteIconWithTooltip, ConfirmDialog } from './index'; +import { PushPin, PushPinOutlined } from '@mui/icons-material'; +import { + Tooltip, + ListItemIcon, + Button, + ListItem, + ListItemButton, +} from '@mui/material'; +import { buttonStyle } from '../views'; import './SingleList.css'; const deletionResponse = { @@ -15,12 +20,6 @@ const deletionResponse = { soft: `List removed from user view.`, }; -export const buttonStyle = { - color: 'white', - width: '15em', - fontSize: '1.5rem', -}; - export function SingleList({ item, setListPath, @@ -69,7 +68,7 @@ export function SingleList({ handleDelete, title: `Are you sure you want to delete ${name}?`, setOpen: isOpen, - open: open, + open, }; const importantStatusLabel = isImportant ? 'Unpin list' : 'Pin list'; @@ -77,38 +76,41 @@ export function SingleList({ return ( <> {open && } -
  • setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} + secondaryAction={ + + } > - {importantStatusLabel}

    } - placement="left" - arrow - > - + {importantStatusLabel}

    } + placement="left" + arrow > - {isImportant ? ( - - ) : ( - - )} -
    -
    - - - - -
  • + ); } From 4c88cf1373a0f93ff7625f8c684dade054e06fcd Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:24:31 -0400 Subject: [PATCH 13/23] feat: update List component - add MUI components, such as Paper and Typography; - add minor custom styling to MUI Paper; - update input placeholder and label. --- src/views/List.jsx | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/views/List.jsx b/src/views/List.jsx index 3fc72db..82138a9 100644 --- a/src/views/List.jsx +++ b/src/views/List.jsx @@ -1,9 +1,15 @@ import React, { useState } from 'react'; import { useEnsureListPath, useUrgency } from '../hooks'; import { getUrgency } from '../utils/urgencyUtils'; -import { List as UnorderedList } from '@mui/material'; +import { List as UnorderedList, Paper, Typography } from '@mui/material'; import { ListItem, AddItems, TextInputElement } from '../components'; +const paperStyle = { + bgcolor: 'var(--color-gray-dark)', + color: 'white', + p: '1rem', +}; + // React.memo is needed to prevent unnecessary re-renders of the List component // when the props (data and listPath) haven't changed, // optimizing performance by avoiding re-computation of expensive @@ -29,26 +35,32 @@ export const List = React.memo(function List({ data, listPath }) { ); return ( - <> + {!data?.length ? ( <> -

    Welcome to {listName}!

    -

    Ready to add your first item? Start adding below!

    + + Welcome to {listName}! + + + Ready to add your first item? Start adding below! + ) : ( <> -

    {listName}

    + + {listName} +
    event.preventDefault()}> @@ -66,6 +78,6 @@ export const List = React.memo(function List({ data, listPath }) { )} - +
    ); }); From 8a6c5e183e75b801329b84c84c6ab8c2745f5a5a Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:25:52 -0400 Subject: [PATCH 14/23] feat: update ListItem imports and remove redundant console log --- src/components/ListItem.jsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/components/ListItem.jsx b/src/components/ListItem.jsx index c1220a0..466b36f 100644 --- a/src/components/ListItem.jsx +++ b/src/components/ListItem.jsx @@ -3,8 +3,7 @@ import { updateItem, deleteItem } from '../api'; import { calculateDateNextPurchased, ONE_DAY_IN_MILLISECONDS } from '../utils'; import { toast } from 'react-toastify'; import { useConfirmDialog } from '../hooks/useConfirmDialog'; -import { ConfirmDialog } from './ConfirmDialog'; -import { DeleteIconWithTooltip, tooltipStyle } from './DeleteIconWithTooltip'; +import { DeleteIconWithTooltip, tooltipStyle, ConfirmDialog } from './index'; import { ListItem as MaterialListItem, Tooltip, @@ -39,12 +38,6 @@ const urgencyStatusStyle = { color: 'white', }; -const toolTipStyle = { - fontSize: '1.5rem', - marginBlockStart: '0', - marginBlockEnd: '0', -}; - const calculateIsPurchased = (dateLastPurchased) => { if (!dateLastPurchased) { return false; @@ -86,7 +79,6 @@ export function ListItem({ item, listPath, itemUrgencyStatus }) { }; const handleDeleteItem = async () => { - console.log('attempting item deletion'); try { await deleteItem(listPath, id); toast.success('Item deleted'); @@ -102,7 +94,7 @@ export function ListItem({ item, listPath, itemUrgencyStatus }) { handleDelete: handleDeleteItem, title: `Are you sure you want to delete ${name}?`, setOpen: isOpen, - open: open, + open, }; const tooltipTitle = isPurchased @@ -115,7 +107,7 @@ export function ListItem({ item, listPath, itemUrgencyStatus }) { {UrgencyStatusIcon && ( {itemUrgencyStatus}

    } + title={

    {itemUrgencyStatus}

    } placement="left" arrow > From d9f5cfed29d3a4a5bc88e0ecac3d4c09ef0da760 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:43:39 -0400 Subject: [PATCH 15/23] test: update labels in List test --- tests/List.test.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/List.test.jsx b/tests/List.test.jsx index 663f774..fdd226e 100644 --- a/tests/List.test.jsx +++ b/tests/List.test.jsx @@ -66,7 +66,7 @@ describe('List Component', () => { ); expect(screen.getByText('groceries')).toBeInTheDocument(); - expect(screen.getByLabelText('Search Item:')).toBeInTheDocument(); + expect(screen.getByLabelText('Search item:')).toBeInTheDocument(); mockShoppingListData.forEach((item) => { expect(screen.getByText(item.name)).toBeInTheDocument(); @@ -81,7 +81,7 @@ describe('List Component', () => { ); expect(screen.getByText('Welcome to groceries!')).toBeInTheDocument(); - expect(screen.getByLabelText('Item Name:')).toBeInTheDocument(); + expect(screen.getByLabelText('Add item:')).toBeInTheDocument(); expect(screen.getByLabelText('Soon')).toBeInTheDocument(); expect(screen.getByLabelText('Kind of soon')).toBeInTheDocument(); expect(screen.getByLabelText('Not soon')).toBeInTheDocument(); From 2d12b861e491fda2f140713a03f268d053cacb07 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Wed, 16 Oct 2024 16:44:16 -0400 Subject: [PATCH 16/23] test: update labels in ManageList test --- tests/ManageList.test.jsx | 4 ++-- tests/SingleList.test.jsx | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/ManageList.test.jsx b/tests/ManageList.test.jsx index 9609a9d..fa14008 100644 --- a/tests/ManageList.test.jsx +++ b/tests/ManageList.test.jsx @@ -26,7 +26,7 @@ describe('ManageList Component', () => { , ); - expect(screen.getByLabelText('Item Name:')).toBeInTheDocument(); + expect(screen.getByLabelText('Add item:')).toBeInTheDocument(); expect(screen.getByLabelText('Soon')).toBeInTheDocument(); expect(screen.getByLabelText('Kind of soon')).toBeInTheDocument(); expect(screen.getByLabelText('Not soon')).toBeInTheDocument(); @@ -41,6 +41,6 @@ describe('ManageList Component', () => { ); expect(screen.getByPlaceholderText('Enter email')).toBeInTheDocument(); - expect(screen.getByText('Invite User')).toBeInTheDocument(); + expect(screen.getByText('Share')).toBeInTheDocument(); }); }); diff --git a/tests/SingleList.test.jsx b/tests/SingleList.test.jsx index 26df4fb..0560ead 100644 --- a/tests/SingleList.test.jsx +++ b/tests/SingleList.test.jsx @@ -18,6 +18,11 @@ vi.mock('../src/hooks', () => ({ useAuth: () => ({ user: { uid: mockUser.uid, email: mockUser.email }, }), + useConfirmDialog: () => ({ + open: true, + isOpen: vi.fn(), + toggleDialog: vi.fn(), + }), })); describe('SingleList component', () => { From 560ba74c1d7669ff005b4146355dd181cbf9f016 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Thu, 17 Oct 2024 13:22:10 -0400 Subject: [PATCH 17/23] feat: introduce a collapsible box in List component that displays AddItems component if clicked --- src/components/AddItems.jsx | 2 +- src/views/List.jsx | 57 +++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/components/AddItems.jsx b/src/components/AddItems.jsx index 27ec253..f54e06f 100644 --- a/src/components/AddItems.jsx +++ b/src/components/AddItems.jsx @@ -66,7 +66,7 @@ export function AddItems({ items }) { ); return ( - + { + setShowAddItems((prev) => !prev); + }; + return ( {!data?.length ? ( @@ -55,34 +63,47 @@ export const List = React.memo(function List({ data, listPath }) { ) : ( <> - - {listName} - - + - - + + {listName} - -
    event.preventDefault()}> - - + +
    + {showAddItems && ( + + + + + + )} + + event.preventDefault()}> + + + {filteredItems.map((item) => { const itemUrgencyStatus = getUrgency(item.name, urgencyObject); From e8d4d2707d18344c6a2117c83dd2bf7197b287dd Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Thu, 17 Oct 2024 14:17:05 -0400 Subject: [PATCH 18/23] test: add a data-testid for New Item button for testing purposes --- src/views/List.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/List.jsx b/src/views/List.jsx index 4f114e4..39d38c1 100644 --- a/src/views/List.jsx +++ b/src/views/List.jsx @@ -75,6 +75,7 @@ export const List = React.memo(function List({ data, listPath }) { - + +
    + + + + + + - - {sortedLists.map((item, index) => { - return ( - - - - - ); - })} - -
    + + {sortedLists.map((item, index) => { + return ( + + + + + ); + })} + + +
    ); } diff --git a/src/views/List.jsx b/src/views/List.jsx index 39d38c1..0a0de19 100644 --- a/src/views/List.jsx +++ b/src/views/List.jsx @@ -13,12 +13,6 @@ import { import { ArrowDropDown, ArrowDropUp } from '@mui/icons-material'; import { ListItem, AddItems, TextInputElement } from '../components'; -const paperStyle = { - bgcolor: 'var(--color-gray-dark)', - color: 'white', - p: '1rem', -}; - // React.memo is needed to prevent unnecessary re-renders of the List component // when the props (data and listPath) haven't changed, // optimizing performance by avoiding re-computation of expensive @@ -49,7 +43,7 @@ export const List = React.memo(function List({ data, listPath }) { }; return ( - + {!data?.length ? ( <> @@ -87,23 +81,30 @@ export const List = React.memo(function List({ data, listPath }) {
    {showAddItems && ( - - - - - + + + + + + + )} - event.preventDefault()}> - - + + event.preventDefault()}> + + + {filteredItems.map((item) => { diff --git a/src/views/ManageList.jsx b/src/views/ManageList.jsx index 4adfc4c..3461002 100644 --- a/src/views/ManageList.jsx +++ b/src/views/ManageList.jsx @@ -1,14 +1,25 @@ import { useEnsureListPath } from '../hooks/useEnsureListPath'; -import Box from '@mui/material/Box'; +import { Box, Paper } from '@mui/material'; import { AddItems, ShareList } from '../components'; +import { darkPaperStyle, lightPaperStyle } from '../App'; export function ManageList({ items }) { // Redirect to home if no list path is null if (useEnsureListPath()) return <>; + return ( - - - - + + + + + + + + + + ); } diff --git a/tests/List.test.jsx b/tests/List.test.jsx index a9c2ada..c281b1b 100644 --- a/tests/List.test.jsx +++ b/tests/List.test.jsx @@ -84,7 +84,7 @@ describe('List Component', () => { ); expect(screen.getByText('groceries')).toBeInTheDocument(); - expect(screen.getByLabelText('Search item:')).toBeInTheDocument(); + expect(screen.getByLabelText('Search for item:')).toBeInTheDocument(); mockShoppingListData.forEach((item) => { expect(screen.getByText(item.name)).toBeInTheDocument(); From d6e08d868a7f0a7fce25e78085e05b02599f582d Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Fri, 18 Oct 2024 08:15:00 -0400 Subject: [PATCH 22/23] fix: import darkPaperStyle, lightPaperStyle from App --- src/views/List.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/List.jsx b/src/views/List.jsx index 0a0de19..98297d5 100644 --- a/src/views/List.jsx +++ b/src/views/List.jsx @@ -12,6 +12,7 @@ import { } from '@mui/material'; import { ArrowDropDown, ArrowDropUp } from '@mui/icons-material'; import { ListItem, AddItems, TextInputElement } from '../components'; +import { darkPaperStyle, lightPaperStyle } from '../App'; // React.memo is needed to prevent unnecessary re-renders of the List component // when the props (data and listPath) haven't changed, From d5443d71a232552c531911d4f47336237d5a79d2 Mon Sep 17 00:00:00 2001 From: Nika Kolesnikova Date: Sat, 19 Oct 2024 09:16:35 -0400 Subject: [PATCH 23/23] remove exported custom styles into a MUIStyles.js --- src/App.jsx | 18 ----------- src/components/AddItems.jsx | 2 +- src/components/ConfirmDialog.jsx | 7 +---- src/components/DeleteIconWithTooltip.jsx | 7 +---- src/components/ListItem.jsx | 2 +- src/components/MUIStyles.js | 38 ++++++++++++++++++++++++ src/components/RadioInputElement.jsx | 2 +- src/components/ShareList.jsx | 3 +- src/components/TextInputElement.jsx | 2 +- src/components/index.js | 1 + src/views/Home.jsx | 18 ++++------- src/views/List.jsx | 9 ++++-- 12 files changed, 59 insertions(+), 50 deletions(-) create mode 100644 src/components/MUIStyles.js diff --git a/src/App.jsx b/src/App.jsx index 3d678d3..05c9e6c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -8,24 +8,6 @@ import { useShoppingLists } from './api'; import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; -const paperStyle = { - color: 'white', - p: '1rem', -}; - -export const darkPaperStyle = { - ...paperStyle, - paddingBlockStart: '4rem', - paddingBlockEnd: '4rem', - background: `linear-gradient(45deg, rgba(117, 124, 232, 0.2) 0%, rgba(117, 124, 232, 0.05) 100%)`, // Pale blue gradient on top - backdropFilter: 'blur(2px)', -}; - -export const lightPaperStyle = { - ...paperStyle, - background: `rgba(117, 124, 232, 0.2)`, -}; - export function App() { /** * This custom hook takes the path of a shopping list diff --git a/src/components/AddItems.jsx b/src/components/AddItems.jsx index 27ec253..dea53de 100644 --- a/src/components/AddItems.jsx +++ b/src/components/AddItems.jsx @@ -5,7 +5,7 @@ import { normalizeItemName } from '../utils'; import { RadioInputElement, TextInputElement } from './index.js'; import { toast } from 'react-toastify'; import { Box, Button, FormControl, RadioGroup } from '@mui/material'; -import { buttonStyle } from '../views'; +import { buttonStyle } from './index'; const radioGroupStyle = { mx: 1, diff --git a/src/components/ConfirmDialog.jsx b/src/components/ConfirmDialog.jsx index f4447da..e9d8941 100644 --- a/src/components/ConfirmDialog.jsx +++ b/src/components/ConfirmDialog.jsx @@ -8,7 +8,7 @@ import { Button, } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; -import { buttonStyle } from '../views'; +import { buttonStyle } from './index'; import './ConfirmDialog.css'; // MUI's Dialog already comes with built-in focus management and accessibility features. @@ -23,11 +23,6 @@ const dialogStyle = { backgroundColor: 'rgb(20, 20, 20)', }; -export const typographyStyle = { - padding: '1em', - color: 'white', -}; - export function ConfirmDialog({ props }) { const { handleDelete, title, setOpen, open } = props; diff --git a/src/components/DeleteIconWithTooltip.jsx b/src/components/DeleteIconWithTooltip.jsx index 1d46c02..d88249a 100644 --- a/src/components/DeleteIconWithTooltip.jsx +++ b/src/components/DeleteIconWithTooltip.jsx @@ -1,11 +1,6 @@ import { DeleteOutlineOutlined } from '@mui/icons-material'; import { Tooltip, IconButton } from '@mui/material'; - -export const tooltipStyle = { - fontSize: '1.5rem', - marginBlockStart: '0', - marginBlockEnd: '0', -}; +import { tooltipStyle } from './MUIStyles'; export const DeleteIconWithTooltip = ({ ariaLabel, toggleDialog }) => { return ( diff --git a/src/components/ListItem.jsx b/src/components/ListItem.jsx index a71ebca..6660245 100644 --- a/src/components/ListItem.jsx +++ b/src/components/ListItem.jsx @@ -3,7 +3,7 @@ import { updateItem, deleteItem } from '../api'; import { calculateDateNextPurchased, ONE_DAY_IN_MILLISECONDS } from '../utils'; import { toast } from 'react-toastify'; import { useConfirmDialog } from '../hooks/useConfirmDialog'; -import { DeleteIconWithTooltip, tooltipStyle, ConfirmDialog } from './index'; +import { DeleteIconWithTooltip, ConfirmDialog, tooltipStyle } from './index'; import { ListItem as MaterialListItem, Tooltip, diff --git a/src/components/MUIStyles.js b/src/components/MUIStyles.js new file mode 100644 index 0000000..0fd879e --- /dev/null +++ b/src/components/MUIStyles.js @@ -0,0 +1,38 @@ +const paperStyle = { + color: 'white', + p: '1rem', +}; + +export const darkPaperStyle = { + ...paperStyle, + paddingBlockStart: '4rem', + paddingBlockEnd: '4rem', + background: `linear-gradient(45deg, rgba(117, 124, 232, 0.2) 0%, rgba(117, 124, 232, 0.05) 100%)`, // Pale blue gradient on top + backdropFilter: 'blur(2px)', +}; + +export const lightPaperStyle = { + ...paperStyle, + background: `rgba(117, 124, 232, 0.2)`, +}; + +export const tooltipStyle = { + fontSize: '1.5rem', + marginBlockStart: '0', + marginBlockEnd: '0', +}; + +export const buttonStyle = { + color: 'white', + fontSize: '1.5rem', +}; + +export const buttonWithTopMarginStyle = { + ...buttonStyle, + marginTop: '0.5rem', +}; + +export const typographyStyle = { + padding: '1em', + color: 'white', +}; diff --git a/src/components/RadioInputElement.jsx b/src/components/RadioInputElement.jsx index d12bc3d..7774364 100644 --- a/src/components/RadioInputElement.jsx +++ b/src/components/RadioInputElement.jsx @@ -1,5 +1,5 @@ import { Radio, Tooltip, FormControlLabel } from '@mui/material'; -import { tooltipStyle } from './DeleteIconWithTooltip'; +import { tooltipStyle } from './MUIStyles'; const radioStyle = { color: 'white', diff --git a/src/components/ShareList.jsx b/src/components/ShareList.jsx index 4588992..11fc6a9 100644 --- a/src/components/ShareList.jsx +++ b/src/components/ShareList.jsx @@ -2,8 +2,7 @@ import { useStateWithStorage, useAuth } from '../hooks'; import { shareList } from '../api'; import { toast } from 'react-toastify'; import { Box, Button } from '@mui/material'; -import { TextInputElement } from './index.js'; -import { buttonWithTopMarginStyle } from '../views/Home'; +import { TextInputElement, buttonWithTopMarginStyle } from './index.js'; export function ShareList() { const [listPath] = useStateWithStorage('tcl-shopping-list-path', null); diff --git a/src/components/TextInputElement.jsx b/src/components/TextInputElement.jsx index b0f373e..28d2c29 100644 --- a/src/components/TextInputElement.jsx +++ b/src/components/TextInputElement.jsx @@ -1,5 +1,5 @@ import { TextField, Typography } from '@mui/material'; -import { typographyStyle } from './ConfirmDialog'; +import { typographyStyle } from '../components/index'; const textFieldStyle = { '& .MuiInputBase-input': { diff --git a/src/components/index.js b/src/components/index.js index 8c3c8c0..11e0676 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -6,3 +6,4 @@ export * from './TextInputElement'; export * from './RadioInputElement'; export * from './ConfirmDialog'; export * from './DeleteIconWithTooltip'; +export * from './MUIStyles'; diff --git a/src/views/Home.jsx b/src/views/Home.jsx index 1570a78..064947a 100644 --- a/src/views/Home.jsx +++ b/src/views/Home.jsx @@ -10,20 +10,14 @@ import { Button, List as UnorderedList, } from '@mui/material'; -import { SingleList, TextInputElement } from '../components'; -import { lightPaperStyle, darkPaperStyle } from '../App'; +import { + SingleList, + TextInputElement, + lightPaperStyle, + darkPaperStyle, +} from '../components'; import './Home.css'; -export const buttonStyle = { - color: 'white', - fontSize: '1.5rem', -}; - -export const buttonWithTopMarginStyle = { - ...buttonStyle, - marginTop: '0.5rem', -}; - const dividerStyle = { borderColor: 'primary.main', }; diff --git a/src/views/List.jsx b/src/views/List.jsx index 98297d5..98d950b 100644 --- a/src/views/List.jsx +++ b/src/views/List.jsx @@ -11,8 +11,13 @@ import { Button, } from '@mui/material'; import { ArrowDropDown, ArrowDropUp } from '@mui/icons-material'; -import { ListItem, AddItems, TextInputElement } from '../components'; -import { darkPaperStyle, lightPaperStyle } from '../App'; +import { + ListItem, + AddItems, + TextInputElement, + darkPaperStyle, + lightPaperStyle, +} from '../components'; // React.memo is needed to prevent unnecessary re-renders of the List component // when the props (data and listPath) haven't changed,