Skip to content

Commit fdbed55

Browse files
authored
Merge pull request #57 from the-collab-lab/hm-loading-bug-fix
Loading state bug fix and minor style adjustments
2 parents b80f2e4 + 32e36d7 commit fdbed55

File tree

8 files changed

+63
-47
lines changed

8 files changed

+63
-47
lines changed

src/App.jsx

+1-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import Login from './views/Login';
88

99
export function App() {
1010
const [isModalOpen, setIsModalOpen] = useState(false);
11-
const [isLoading, setIsLoading] = useState(false);
1211

1312
/**
1413
* This custom hook takes the path of a shopping list
@@ -43,7 +42,7 @@ export function App() {
4342
* This custom hook takes our token and fetches the data for our list.
4443
* Check ./api/firestore.js for its implementation.
4544
*/
46-
const data = useShoppingListData(listPath);
45+
const { data, isLoading } = useShoppingListData(listPath);
4746

4847
const handleShareModalClick = () => {
4948
console.log('isModalOpen', isModalOpen);
@@ -65,7 +64,6 @@ export function App() {
6564
setListPath={setListPath}
6665
isModalOpen={isModalOpen}
6766
handleShareModalClick={handleShareModalClick}
68-
setIsLoading={setIsLoading}
6967
/>
7068
}
7169
/>
@@ -77,7 +75,6 @@ export function App() {
7775
listPath={listPath}
7876
listName={listName}
7977
isLoading={isLoading}
80-
setIsLoading={setIsLoading}
8178
/>
8279
}
8380
/>

src/api/firebase.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,15 @@ export function useShoppingListData(listPath) {
6262
/** @type {import('firebase/firestore').DocumentData[]} */
6363
const initialState = [];
6464
const [data, setData] = useState(initialState);
65+
const [isLoading, setIsLoading] = useState(true);
6566

6667
useEffect(() => {
67-
if (!listPath) return;
68+
if (!listPath) {
69+
setIsLoading(false);
70+
return;
71+
}
6872

73+
setIsLoading(true);
6974
// When we get a listPath, we use it to subscribe to real-time updates
7075
// from Firestore.
7176
return onSnapshot(collection(db, listPath, 'items'), (snapshot) => {
@@ -84,11 +89,12 @@ export function useShoppingListData(listPath) {
8489

8590
// Update our React state with the new data.
8691
setData(nextData);
92+
setIsLoading(false);
8793
});
8894
}, [listPath]);
8995

9096
// Return the data so it can be used by our React components.
91-
return data;
97+
return { data, isLoading };
9298
}
9399

94100
/**

src/components/CreateShoppingList.jsx

+8-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { createList } from '../api/firebase';
33
import { useNavigate } from 'react-router-dom';
44
import toast from 'react-hot-toast';
55
import { Input } from './ui/input';
6+
import { ListPlus } from 'lucide-react';
67

78
export default function CreateShoppingList({ user, setListPath }) {
89
const [listName, setListName] = useState('');
@@ -28,20 +29,24 @@ export default function CreateShoppingList({ user, setListPath }) {
2829
onSubmit={handleSubmit}
2930
className="relative w-full flex items-center justify-center gap-4 max-w-lg mx-auto "
3031
>
31-
<div className="flex flex-col w-full max-w-xs ">
32-
<label htmlFor="shoppingList" className="text-sm font-light ">
32+
<div className="flex flex-col w-full max-w-xs relative">
33+
<label htmlFor="shoppingList" className="text-sm font-light pb-2">
3334
Create a new list
3435
</label>
3536
<Input
3637
className="border-[1px] rounded-[5px] text-[1em] h-[3rem] pl-10 focus-visible:outline-none focus:ring-1 focus:ring-primary-green text-black dark:text-white bg-white dark:bg-bg-black"
3738
id="shoppingList"
3839
type="text"
3940
value={listName}
41+
placeholder="Enter your list name..."
4042
onChange={(e) => setListName(e.target.value)}
4143
required
4244
/>
45+
<span className="absolute inset-y-0 left-0 top-7 flex items-center pl-3 pointer-events-none">
46+
<ListPlus className="h-5 w-5 text-grey" />
47+
</span>
4348
</div>
44-
<div className="flex pt-5">
49+
<div className="flex pt-5 mt-2">
4550
<button
4651
type="submit"
4752
className="bg-light-green hover:bg-light-green dark:bg-primary-green dark:hover:bg-primary-green hover:bg-opacity-75 dark:hover:bg-opacity-75 text-black font-bold h-[3rem] px-5 rounded-[5px] flex items-center space-x-2"

src/components/ListItem.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export function ListItem({
117117
<Dialog open={isOpen} onOpenChange={() => handleOpenModal(id)}>
118118
<DialogTrigger asChild>
119119
<Button className="bg-transparent hover:bg-transparent p-0">
120-
<Pencil className="w-5 h-5 md:w-6 md:h-6 text-light-grey hover:text-opacity-75 dark:text-emerald-500 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125" />
120+
<Pencil className="w-5 h-5 text-light-grey hover:text-opacity-75 dark:text-emerald-500 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125" />
121121
</Button>
122122
</DialogTrigger>
123123
<DialogContent>
@@ -146,7 +146,7 @@ export function ListItem({
146146
id={id}
147147
onClick={() => setIsAlertOpen(true)}
148148
>
149-
<Trash2 className="w-5 h-5 md:w-6 md:h-6 text-gray-600 hover:text-opacity-75 dark:text-emerald-500 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125" />
149+
<Trash2 className="w-5 h-5 text-gray-600 hover:text-opacity-75 dark:text-emerald-500 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125" />
150150
</Button>
151151
</AlertDialogTrigger>
152152
<AlertDialogContent className="p-6 sm:p-10">

src/components/SearchBar.jsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ export function SearchBar({ allData, setDisplayData, setSearch, search }) {
1414
};
1515

1616
return (
17-
<form className="relative w-full -top-[3px]">
18-
<label htmlFor="shoppingList" className="text-sm font-light">
17+
<form className="relative w-full">
18+
<label htmlFor="shoppingList" className="text-sm font-light pb-2">
1919
Filter lists
2020
</label>
2121
<Input
@@ -24,9 +24,9 @@ export function SearchBar({ allData, setDisplayData, setSearch, search }) {
2424
value={search}
2525
placeholder="Search..."
2626
onChange={handleInputChange}
27-
className="border-[1px] rounded-[5px] text-[1em] h-[3rem] pl-10 focus-visible:outline-none focus:ring-1 focus:ring-primary-green text-black dark:text-white bg-white dark:bg-bg-black"
27+
className="border-[1px] rounded-[5px] mt-2 text-[1em] h-[3rem] pl-10 focus-visible:outline-none focus:ring-1 focus:ring-primary-green text-black dark:text-white bg-white dark:bg-bg-black"
2828
/>
29-
<span className="absolute inset-y-0 left-0 top-6 flex items-center pl-3 pointer-events-none">
29+
<span className="absolute inset-y-0 left-0 top-8 flex items-center pl-3 pointer-events-none">
3030
<ListFilter className="h-5 w-5 text-grey" />
3131
</span>
3232
</form>

src/components/SingleList.jsx

+13-7
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ export function SingleList({
3131
setListPath,
3232
handleShareModalClick,
3333
setSelectedItem,
34-
setIsLoading,
3534
}) {
3635
const [isAlertOpen, setIsAlertOpen] = useState(false);
3736
const [collectionId, setCollectionId] = useState('');
37+
const [shouldNavigate, setShouldNavigate] = useState(false);
3838
const singleListPath = path.split('/')[0];
3939
const email = getAuth().currentUser.email;
4040

@@ -44,10 +44,16 @@ export function SingleList({
4444

4545
const navigate = useNavigate();
4646

47+
useEffect(() => {
48+
if (shouldNavigate) {
49+
navigate('/list');
50+
setShouldNavigate(false);
51+
}
52+
}, [shouldNavigate]);
53+
4754
function handleClick() {
48-
setIsLoading(true);
4955
setListPath(path);
50-
navigate(`/list`);
56+
setShouldNavigate(true);
5157
}
5258

5359
const handleShareClick = () => {
@@ -83,7 +89,7 @@ export function SingleList({
8389
aria-label="Share list"
8490
className="text-green-500 hover:text-green-500 dark:text-ruby-pink dark:hover:text-primary-pink hover:text-opacity-80 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125"
8591
>
86-
<FaShareNodes className="w-5 h-5 md:w-6 md:h-6" />
92+
<FaShareNodes className="w-5 h-5" />
8793
</button>
8894
) : (
8995
<TooltipProvider>
@@ -94,7 +100,7 @@ export function SingleList({
94100
type="button"
95101
onClick={() => setIsAlertOpen(true)}
96102
>
97-
<FaShareNodes className="w-5 h-5 md:w-6 md:h-6 text-gray-500" />
103+
<FaShareNodes className="w-5 h-5 text-gray-500" />
98104
</Button>
99105
</TooltipTrigger>
100106
<TooltipContent>
@@ -111,7 +117,7 @@ export function SingleList({
111117
type="button"
112118
onClick={() => setIsAlertOpen(true)}
113119
>
114-
<Trash2 className="w-5 h-5 md:w-6 md:h-6 text-primary-pink hover:text-opacity-75 dark:text-emerald-500 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125" />
120+
<Trash2 className="w-5 h-5 text-primary-pink hover:text-opacity-75 dark:text-emerald-500 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125" />
115121
</Button>
116122
</AlertDialogTrigger>
117123
<AlertDialogContent>
@@ -149,7 +155,7 @@ export function SingleList({
149155
type="button"
150156
onClick={() => setIsAlertOpen(true)}
151157
>
152-
<Trash2 className="text-gray-500" />
158+
<Trash2 className="w-5 h-5 text-gray-500" />
153159
</Button>
154160
</TooltipTrigger>
155161
<TooltipContent>

src/views/Home.jsx

-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ export function Home({
99
setListPath,
1010
isModalOpen,
1111
handleShareModalClick,
12-
setIsLoading,
1312
}) {
1413
const [selectedItem, setSelectedItem] = useState('');
1514

@@ -55,7 +54,6 @@ export function Home({
5554
setListPath={setListPath}
5655
handleShareModalClick={handleShareModalClick}
5756
setSelectedItem={setSelectedItem}
58-
setIsLoading={setIsLoading}
5957
/>
6058
))}
6159
</ul>

src/views/List.jsx

+27-23
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,16 @@ import {
1414
} from '@/components/ui/dialog';
1515
import { Button } from '@/components/ui/button';
1616
import { SquarePlus } from 'lucide-react';
17+
import { useNavigate } from 'react-router-dom';
1718

18-
export function List({ data, listPath, listName, isLoading, setIsLoading }) {
19+
export function List({ data, listPath, listName, isLoading }) {
1920
const [search, setSearch] = useState('');
2021
const [allData, setAllData] = useState([]);
2122
const [displayData, setDisplayData] = useState([]);
2223
const [isOpen, setIsOpen] = useState(false);
2324
const [openItemId, setOpenItemId] = useState(null);
24-
const [noData, setNoData] = useState(false);
2525

2626
useEffect(() => {
27-
setIsLoading(true);
2827
const arrayWithIndicator = data.map((item) => ({
2928
...item,
3029
indicator: getIndicator(item),
@@ -34,19 +33,6 @@ export function List({ data, listPath, listName, isLoading, setIsLoading }) {
3433
setDisplayData(urgencyData);
3534
}, [data]);
3635

37-
useEffect(() => {
38-
if (displayData.length > 1) {
39-
setIsLoading(false);
40-
}
41-
}, [displayData]);
42-
43-
setTimeout(() => {
44-
if (data.length === 0) {
45-
setIsLoading(false);
46-
setNoData(true);
47-
}
48-
}, 2000);
49-
5036
const handleAddModal = () => {
5137
if (search.length > 0) {
5238
setDisplayData(allData);
@@ -60,20 +46,38 @@ export function List({ data, listPath, listName, isLoading, setIsLoading }) {
6046
setOpenItemId((prevId) => (prevId === id ? null : id));
6147
};
6248

49+
const navigate = useNavigate();
50+
51+
function handleClick() {
52+
navigate('/');
53+
}
54+
6355
return (
6456
<>
65-
{listPath === '' ? (
66-
<div className="flex flex-col space-y-10 justify-center items-center">
57+
{listPath === '' || !listPath ? (
58+
<div className="flex flex-col space-y-10 justify-center items-center gap-3">
6759
<div className="relative inline-block">
6860
<h1 className="font-[montserrat] text-3xl font-bold text-gray">
6961
<span className="relative inline-block">No list selected</span>
7062
</h1>
7163
<img
72-
src="/img/underline.png"
64+
src="/img/ruby-underline.png"
65+
alt="Description"
66+
className="absolute bottom-[-12px] -right-3 w-14 h-3 dark:hidden"
67+
/>
68+
<img
69+
src="/img/light-pink-underline.png"
7370
alt="Description"
74-
className="absolute bottom-[-12px] -right-3 w-14 h-3"
71+
className="absolute bottom-[-12px] -right-3 w-14 h-3 hidden dark:block"
7572
/>
7673
</div>
74+
<Button
75+
onClick={handleClick}
76+
className="bg-ruby-pink text-white rounded-xl dark:bg-primary-green dark:text-black w-full hover:bg-ruby-pink dark:hover:bg-primary-green hover:bg-opacity-75 dark:hover:bg-opacity-75 text-sm md:text-base font-semibold max-w-[250px]"
77+
>
78+
<SquarePlus className="h-5 w-5 md:w-6 md:h-6 mr-2" />
79+
Let&#39;s get you started!
80+
</Button>
7781
</div>
7882
) : (
7983
<div className="flex flex-col space-y-10 justify-center items-center">
@@ -104,7 +108,7 @@ export function List({ data, listPath, listName, isLoading, setIsLoading }) {
104108
<Dialog open={isOpen} onOpenChange={handleAddModal}>
105109
<DialogTrigger asChild className="items-start mt-[19px]">
106110
<Button className="bg-transparen hover:bg-transparen p-0">
107-
<SquarePlus className="h-10 w-10 text-primary-green dark:text-primary-pink transition-opacity hover:opacity-75" />
111+
<SquarePlus className="h-10 w-10 mt-2 text-primary-green dark:text-primary-pink transition-opacity hover:opacity-75" />
108112
</Button>
109113
</DialogTrigger>
110114
<DialogContent>
@@ -165,13 +169,13 @@ export function List({ data, listPath, listName, isLoading, setIsLoading }) {
165169
))}
166170
</ul>
167171
)}
168-
{!isLoading && noData && displayData.length === 0 && (
172+
{!isLoading && data.length === 0 && (
169173
<div className="flex flex-col justify-center items-center gap-4 w-full mx-auto">
170174
<p className="text-grey text-center">
171175
Your list is empty. Start adding some items now!
172176
</p>
173177
<Button
174-
className="bg-primary-pink text-white rounded-xl dark:bg-primary-green dark:text-black w-full hover:bg-primary-pink hover:bg-opacity-75 text-sm font-semibold max-w-[150px]"
178+
className="bg-primary-pink text-white rounded-xl dark:bg-primary-green dark:text-black w-full hover:bg-primary-pink dark:hover:bg-primary-green hover:bg-opacity-75 dark:hover:bg-opacity-75 text-sm font-semibold max-w-[150px]"
175179
id="addFirstItem"
176180
onClick={() => setIsOpen((prev) => !prev)}
177181
>

0 commit comments

Comments
 (0)