Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sc issue 22 #59

Merged
merged 11 commits into from
Apr 5, 2024
13 changes: 13 additions & 0 deletions public/sprite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 0 additions & 3 deletions src/api/useAuth.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ export const SignInButton = () => {
await getRedirectResult(auth);
} catch (redirectError) {
console.error('Error during redirect sign-in:', redirectError);
// TODO ADD TOAST ONCE COMPONENT COMMITTED
}
} else {
console.error('Error during popup sign-in:', error);
// TODO ADD TOAST ONCE COMPONENT COMMITTED
}
} finally {
setLoading(false);
Expand Down Expand Up @@ -70,7 +68,6 @@ export const SignOutButton = () => {
} catch (error) {
console.error('Error signing out:', error);
window.alert('Error signing out. Please try again.');
// TODO ADD TOAST ONCE COMPONENT IS COMPLETE
} finally {
setLoading(false);
}
Expand Down
102 changes: 70 additions & 32 deletions src/components/AddItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import TextInput from '../components/TextInput';
import Button from './Button';
import SelectInput from './SelectInput';
import { GoPlus } from 'react-icons/go';
import { useToast } from '../utils/hooks';
import Toast from './Toast';

export default function AddItem({ listPath, data }) {
const { toasts, addToast } = useToast();

const initialState = {
itemName: '',
daysUntilNextPurchase: '',
Expand All @@ -28,29 +32,58 @@ export default function AddItem({ listPath, data }) {
e.preventDefault();

const newItemName = itemValue.itemName.trim();

// Check that the user added the timeframe
if (itemValue.daysUntilNextPurchase === '') {
alert('Please select a timeframe to add item to list!');
addToast({
id: 'toastTimeframe',
message: 'Eeep, select a time frame to add an item to your list!',
iconName: 'warning',
color: 'orange',
});
return;
}
// Check if the itemName is empty
if (newItemName === '') {
alert(`Please name your item. Empty spaces don't count!`);
addToast({
id: 'toastEmptyName',
message: "Please name your item. Heh, empty spaces don't count!",
iconName: 'warning',
color: 'orange',
});
return;
}

// Check if the itemName already exists in the list
if (existingItem(newItemName)) {
alert('Uh oh, this item is already in your list!');
addToast({
id: 'toastExistingItem',
message: `All good, ${newItemName} is already in your list!`,
iconName: 'error',
color: 'red',
});
return;
}

try {
// adds item after checks pass
await addItem(listPath, itemValue);
alert(`${newItemName} added to list!`);
addToast({
id: 'toastItemAdded',
message: `Done! ${newItemName} added to list!`,
iconName: 'check',
color: 'blue',
});
setItemValue(initialState);
// alert(`Done! ${newItemName} added to list!`);
} catch (err) {
alert('Error adding item to database');
// alerts user something else went wrong
addToast({
id: 'toastItemAddErr',
message: `There was an error adding ${newItemName} to your list, please try again`,
iconName: 'error',
color: 'red',
});
console.error(err);
}
};

Expand All @@ -63,31 +96,36 @@ export default function AddItem({ listPath, data }) {
};

return (
<form
onSubmit={handleSubmit}
className="flex items-end flex-wrap gap-4 w-full"
>
<TextInput
label="Add item"
name="itemName"
placeholder="Add item to list"
onChange={handleInputChange}
value={itemValue.itemName}
/>
<SelectInput
label="Timeframe"
id="timeframe"
name="daysUntilNextPurchase"
value={itemValue.daysUntilNextPurchase}
onChange={handleInputChange}
/>
<Button
type="submit"
text="Add item"
bgColor="bg-tcl-blue"
textColor="text-white"
icon={<GoPlus size={19} />}
/>
</form>
<>
{toasts.map((toast) => (
<Toast key={toast.id} {...toast} />
))}
<form
onSubmit={handleSubmit}
className="flex items-end flex-wrap gap-4 w-full"
>
<TextInput
label="Add item"
name="itemName"
placeholder="Add item to list"
onChange={handleInputChange}
value={itemValue.itemName}
/>
<SelectInput
label="Timeframe"
id="timeframe"
name="daysUntilNextPurchase"
value={itemValue.daysUntilNextPurchase}
onChange={handleInputChange}
/>
<Button
type="submit"
text="Add item"
bgColor="bg-tcl-blue"
textColor="text-white"
icon={<GoPlus size={19} />}
/>
</form>
</>
);
}
43 changes: 33 additions & 10 deletions src/components/AddList.jsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,69 @@
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { GoPlus } from 'react-icons/go';
import { createList } from '../api';
import { useAuth } from '../api/useAuth.jsx';
import { useToast } from '../utils/hooks.js';
import Button from './Button.jsx';
import TextInput from './TextInput.jsx';
import { GoPlus } from 'react-icons/go';
import Toast from './Toast';

export default function AddList({ setListPath }) {
const [listName, setListName] = useState('');
const [message, setMessage] = useState('');
const navigate = useNavigate();
const { user } = useAuth();
const { toasts, addToast } = useToast();

const handleSubmit = async (e) => {
e.preventDefault();
try {
if (!listName) {
window.alert('Please enter a list name');
addToast({
id: 'noListName',
message: 'Please name your list',
iconName: 'warning',
color: 'orange',
});
return;
}
const newList = await createList(user.uid, user.email, listName);
const listPath = user.uid + '/' + listName;
// if list is created newList will be true else newList will be false
if (newList) {
setListName('');
setMessage(`Your list, ${listName}, was successfully created.`);
addToast({
id: 'newListCreated',
message: `Your list, ${listName}, was successfully created.`,
iconName: 'check',
color: 'blue',
});
setListPath(listPath);
setTimeout(() => {
navigate('/list');
}, 2000);
} else {
setMessage(`Your list, ${listName} was not created. Please try again.`);
addToast({
id: 'problemCreatingList',
message: `Eeep, ${listName} list was not created. Please try again.`,
iconName: 'error',
color: 'red',
});
}
} catch (err) {
console.error(err);
setMessage(
`An error occurred while creating your list, ${listName}: ${err.message}.`,
);
addToast({
id: 'errorCreatingList',
message: `An error occurred while creating your list, ${listName}: ${err.message}.`,
iconName: 'error',
color: 'red',
});
}
};
return (
<>
{toasts.map((toast) => (
<Toast key={toast.id} {...toast} />
))}
<form
onSubmit={handleSubmit}
className="flex items-end flex-wrap space-x-2"
Expand All @@ -52,13 +76,12 @@ export default function AddList({ setListPath }) {
/>
<Button
type="submit"
text="Add item"
text="Add list"
bgColor="bg-tcl-blue"
textColor="text-white"
icon={<GoPlus size={19} />}
/>
</form>
{message ? <p>{message}</p> : null}
</>
);
}
57 changes: 57 additions & 0 deletions src/components/ConfirmToast.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Svg from './Svg';

const ConfirmToast = ({
id,
message,
iconName,
color,
onConfirm,
onCancel,
}) => {
return (
<div className="fixed inset-0 flex items-center justify-center z-50">
<div
id={id}
className={`w-full max-w-xs p-4 mb-3 text-gray-500 bg-white rounded-lg shadow-xl border border-gray-100`}
role="alert"
>
<div className="flex items-center">
<div
className={`inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-${color}-500 bg-${color}-100 rounded-lg`}
>
<Svg className="w-4 h-4" aria-hidden="true" symbolId={iconName} />
<span className="sr-only">{iconName} icon</span>
</div>
<div className="ms-3 text-sm font-normal">
<span className="mb-1 text-sm font-semibold text-gray-900">
{message}
</span>
<div className="mb-2 text-sm font-normal">
Are you sure? This action is forever-eva-eva.
</div>
<div className="grid grid-cols-2 gap-2">
<div>
<button
onClick={onConfirm}
className={`inline-flex justify-center w-full px-2 py-1.5 text-xs font-medium text-center text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:ring-4 focus:outline-none focus:ring-blue-300`}
>
Delete
</button>
</div>
<div>
<button
onClick={onCancel}
className={`inline-flex justify-center w-full px-2 py-1.5 text-xs font-medium text-center text-gray-900 bg-white border border-gray-300 rounded-lg hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-gray-200`}
>
Cancel
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
};

export default ConfirmToast;
Loading
Loading