add handling of no stores and fix app naming
All checks were successful
Build & Deploy Costco Grocery List / build (push) Successful in 11s
Build & Deploy Costco Grocery List / verify-images (push) Successful in 2s
Build & Deploy Costco Grocery List / deploy (push) Successful in 5s
Build & Deploy Costco Grocery List / notify (push) Successful in 1s
All checks were successful
Build & Deploy Costco Grocery List / build (push) Successful in 11s
Build & Deploy Costco Grocery List / verify-images (push) Successful in 2s
Build & Deploy Costco Grocery List / deploy (push) Successful in 5s
Build & Deploy Costco Grocery List / notify (push) Successful in 1s
This commit is contained in:
parent
e9b678c7be
commit
dfaab1dfcb
@ -1,12 +1,15 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Costco Grocery List</title>
|
<title>Grocery App</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
|
||||||
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
addItem,
|
addItem,
|
||||||
getClassification,
|
getClassification,
|
||||||
@ -30,13 +31,16 @@ import { findSimilarItems } from "../utils/stringSimilarity";
|
|||||||
|
|
||||||
|
|
||||||
export default function GroceryList() {
|
export default function GroceryList() {
|
||||||
|
const pageTitle = "Grocery List";
|
||||||
const { role: systemRole } = useContext(AuthContext);
|
const { role: systemRole } = useContext(AuthContext);
|
||||||
const { activeHousehold } = useContext(HouseholdContext);
|
const { activeHousehold } = useContext(HouseholdContext);
|
||||||
const { activeStore } = useContext(StoreContext);
|
const { activeStore, stores, loading: storeLoading } = useContext(StoreContext);
|
||||||
const { settings } = useContext(SettingsContext);
|
const { settings } = useContext(SettingsContext);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
// Get household role for permissions
|
// Get household role for permissions
|
||||||
const householdRole = activeHousehold?.role;
|
const householdRole = activeHousehold?.role;
|
||||||
|
const isHouseholdAdmin = householdRole === "admin";
|
||||||
|
|
||||||
// === State === //
|
// === State === //
|
||||||
const [items, setItems] = useState([]);
|
const [items, setItems] = useState([]);
|
||||||
@ -494,13 +498,68 @@ export default function GroceryList() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (!activeHousehold || !activeStore) {
|
if (!activeHousehold) {
|
||||||
return (
|
return (
|
||||||
<div className="glist-body">
|
<div className="glist-body">
|
||||||
<div className="glist-container">
|
<div className="glist-container">
|
||||||
<h1 className="glist-title">Costco Grocery List</h1>
|
<h1 className="glist-title">{pageTitle}</h1>
|
||||||
<p style={{ textAlign: 'center', marginTop: '2rem', color: 'var(--text-secondary)' }}>
|
<p style={{ textAlign: 'center', marginTop: '2rem', color: 'var(--text-secondary)' }}>
|
||||||
{!activeHousehold ? 'Loading households...' : 'Loading stores...'}
|
Loading households...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storeLoading) {
|
||||||
|
return (
|
||||||
|
<div className="glist-body">
|
||||||
|
<div className="glist-container">
|
||||||
|
<h1 className="glist-title">{pageTitle}</h1>
|
||||||
|
<p style={{ textAlign: 'center', marginTop: '2rem', color: 'var(--text-secondary)' }}>
|
||||||
|
Loading stores...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!storeLoading && stores.length === 0) {
|
||||||
|
return (
|
||||||
|
<div className="glist-body">
|
||||||
|
<div className="glist-container">
|
||||||
|
<h1 className="glist-title">{pageTitle}</h1>
|
||||||
|
<div className="glist-empty-state">
|
||||||
|
<h2 className="glist-empty-title">No stores found</h2>
|
||||||
|
<p className="glist-empty-text">
|
||||||
|
This household doesn’t have any stores yet.
|
||||||
|
</p>
|
||||||
|
{isHouseholdAdmin ? (
|
||||||
|
<button
|
||||||
|
className="btn-primary"
|
||||||
|
onClick={() => navigate("/manage?tab=stores")}
|
||||||
|
>
|
||||||
|
Go to Manage Stores
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<p className="glist-empty-text">
|
||||||
|
Please notify a household admin to add a store.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!activeStore) {
|
||||||
|
return (
|
||||||
|
<div className="glist-body">
|
||||||
|
<div className="glist-container">
|
||||||
|
<h1 className="glist-title">{pageTitle}</h1>
|
||||||
|
<StoreTabs />
|
||||||
|
<p style={{ textAlign: 'center', marginTop: '2rem', color: 'var(--text-secondary)' }}>
|
||||||
|
Loading stores...
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -511,7 +570,7 @@ export default function GroceryList() {
|
|||||||
return (
|
return (
|
||||||
<div className="glist-body">
|
<div className="glist-body">
|
||||||
<div className="glist-container">
|
<div className="glist-container">
|
||||||
<h1 className="glist-title">Costco Grocery List</h1>
|
<h1 className="glist-title">{pageTitle}</h1>
|
||||||
<StoreTabs />
|
<StoreTabs />
|
||||||
<p style={{ textAlign: 'center', marginTop: '2rem' }}>Loading grocery list...</p>
|
<p style={{ textAlign: 'center', marginTop: '2rem' }}>Loading grocery list...</p>
|
||||||
</div>
|
</div>
|
||||||
@ -523,7 +582,7 @@ export default function GroceryList() {
|
|||||||
return (
|
return (
|
||||||
<div className="glist-body">
|
<div className="glist-body">
|
||||||
<div className="glist-container">
|
<div className="glist-container">
|
||||||
<h1 className="glist-title">Costco Grocery List</h1>
|
<h1 className="glist-title">{pageTitle}</h1>
|
||||||
|
|
||||||
<StoreTabs />
|
<StoreTabs />
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { useContext, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
|
import { useSearchParams } from "react-router-dom";
|
||||||
import ManageHousehold from "../components/manage/ManageHousehold";
|
import ManageHousehold from "../components/manage/ManageHousehold";
|
||||||
import ManageStores from "../components/manage/ManageStores";
|
import ManageStores from "../components/manage/ManageStores";
|
||||||
import { HouseholdContext } from "../context/HouseholdContext";
|
import { HouseholdContext } from "../context/HouseholdContext";
|
||||||
@ -7,6 +8,14 @@ import "../styles/pages/Manage.css";
|
|||||||
export default function Manage() {
|
export default function Manage() {
|
||||||
const { activeHousehold } = useContext(HouseholdContext);
|
const { activeHousehold } = useContext(HouseholdContext);
|
||||||
const [activeTab, setActiveTab] = useState("household");
|
const [activeTab, setActiveTab] = useState("household");
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const tab = searchParams.get("tab");
|
||||||
|
if (tab === "household" || tab === "stores") {
|
||||||
|
setActiveTab(tab);
|
||||||
|
}
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
if (!activeHousehold) {
|
if (!activeHousehold) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -64,6 +64,31 @@
|
|||||||
padding-top: var(--spacing-md);
|
padding-top: var(--spacing-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Empty State */
|
||||||
|
.glist-empty-state {
|
||||||
|
margin: var(--spacing-xl) auto;
|
||||||
|
padding: var(--spacing-lg);
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-md);
|
||||||
|
max-width: 32rem;
|
||||||
|
border: var(--border-width-thin) dashed var(--color-border-medium);
|
||||||
|
border-radius: var(--border-radius-lg);
|
||||||
|
background: var(--color-bg-surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glist-empty-title {
|
||||||
|
font-size: var(--font-size-lg);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glist-empty-text {
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.glist-section-header .glist-section-title {
|
.glist-section-header .glist-section-title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user