fix: flatten store location cards
This commit is contained in:
parent
737aa6d66e
commit
4b98740a7b
@ -87,8 +87,8 @@ export default function ManageStores() {
|
|||||||
<section className="manage-section">
|
<section className="manage-section">
|
||||||
<h2>Store Locations ({householdStores.length})</h2>
|
<h2>Store Locations ({householdStores.length})</h2>
|
||||||
<p className="manage-stores-help">
|
<p className="manage-stores-help">
|
||||||
Stores and locations are private to this household. Each location has its own zones,
|
Stores are private to this household. Locations define map-specific zones, item
|
||||||
item defaults, and shopping order.
|
placement, and shopping order.
|
||||||
</p>
|
</p>
|
||||||
{householdStores.length === 0 ? (
|
{householdStores.length === 0 ? (
|
||||||
<p className="empty-message">No store locations added yet.</p>
|
<p className="empty-message">No store locations added yet.</p>
|
||||||
@ -96,45 +96,55 @@ export default function ManageStores() {
|
|||||||
<div className="stores-list">
|
<div className="stores-list">
|
||||||
{groupedStores.map((storeGroup) => (
|
{groupedStores.map((storeGroup) => (
|
||||||
<div key={storeGroup.household_store_id} className="store-card">
|
<div key={storeGroup.household_store_id} className="store-card">
|
||||||
<div className="store-info">
|
<div className="store-card-header">
|
||||||
<h3>{storeGroup.name}</h3>
|
<div className="store-info">
|
||||||
|
<h3>{storeGroup.name}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<StoreLocationManager
|
||||||
|
householdId={activeHousehold.id}
|
||||||
|
storeGroup={storeGroup}
|
||||||
|
allLocationCount={householdStores.length}
|
||||||
|
canManage={isAdmin}
|
||||||
|
refreshAfterStoreChange={refreshAfterStoreChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StoreLocationManager
|
|
||||||
householdId={activeHousehold.id}
|
|
||||||
storeGroup={storeGroup}
|
|
||||||
allLocationCount={householdStores.length}
|
|
||||||
canManage={isAdmin}
|
|
||||||
refreshAfterStoreChange={refreshAfterStoreChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="store-location-list">
|
<div className="store-location-list">
|
||||||
{storeGroup.locations.map((location) => (
|
{storeGroup.locations.map((location) => {
|
||||||
<div key={location.id} className="store-location-row">
|
const label = locationLabel(location);
|
||||||
<div className="store-info">
|
const showLocationName =
|
||||||
<strong>{locationLabel(location)}</strong>
|
storeGroup.locations.length > 1 || label !== storeGroup.name;
|
||||||
{location.address ? (
|
|
||||||
<p className="store-location">{location.address}</p>
|
return (
|
||||||
) : null}
|
<div key={location.id} className="store-location-row">
|
||||||
{location.is_default ? (
|
<div className="store-info store-location-copy">
|
||||||
<p className="store-location">Default shopping location</p>
|
{showLocationName ? <strong>{label}</strong> : null}
|
||||||
) : null}
|
{location.address ? (
|
||||||
|
<p className="store-location">{location.address}</p>
|
||||||
|
) : null}
|
||||||
|
{location.is_default ? (
|
||||||
|
<p className="store-location">Default location</p>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="store-location-controls">
|
||||||
|
<StoreZoneManager
|
||||||
|
householdId={activeHousehold.id}
|
||||||
|
location={location}
|
||||||
|
canManage={isAdmin}
|
||||||
|
refreshActiveZones={refreshZones}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StoreAvailableItemsManager
|
||||||
|
householdId={activeHousehold.id}
|
||||||
|
store={location}
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
<StoreZoneManager
|
})}
|
||||||
householdId={activeHousehold.id}
|
|
||||||
location={location}
|
|
||||||
canManage={isAdmin}
|
|
||||||
refreshActiveZones={refreshZones}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<StoreAvailableItemsManager
|
|
||||||
householdId={activeHousehold.id}
|
|
||||||
store={location}
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -50,11 +50,11 @@
|
|||||||
background: var(--background);
|
background: var(--background);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 1.25rem;
|
padding: 1rem;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.store-card:hover {
|
.store-card:hover {
|
||||||
@ -62,16 +62,23 @@
|
|||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.store-card-header {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
gap: 0.75rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.store-info h3 {
|
.store-info h3 {
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
margin: 0 0 0.5rem 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.store-location {
|
.store-location {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-size: 0.9rem;
|
font-size: 0.85rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,17 +97,37 @@
|
|||||||
.store-location-list {
|
.store-location-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 0.65rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.store-location-row {
|
.store-location-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.55rem;
|
||||||
|
padding-top: 0.65rem;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-location-row:first-child {
|
||||||
|
padding-top: 0;
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-location-copy {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.12rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-location-copy strong {
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 0.94rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-location-controls {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) auto;
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
gap: 0.75rem;
|
gap: 0.5rem;
|
||||||
padding: 1rem;
|
|
||||||
border: 1px solid var(--border);
|
|
||||||
border-radius: 8px;
|
|
||||||
background: var(--card-bg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.store-location-manager-trigger,
|
.store-location-manager-trigger,
|
||||||
@ -108,9 +135,8 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.store-location-row > .store-zone-manager-trigger,
|
.store-card-header > .store-location-manager-trigger {
|
||||||
.store-location-row > .store-available-items-trigger {
|
width: auto;
|
||||||
grid-column: 1 / -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.store-items-modal-toolbar.store-management-create-row {
|
.store-items-modal-toolbar.store-management-create-row {
|
||||||
@ -283,13 +309,18 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.store-location-row,
|
.store-card-header,
|
||||||
|
.store-location-controls,
|
||||||
.store-items-modal-toolbar.store-management-create-row,
|
.store-items-modal-toolbar.store-management-create-row,
|
||||||
.store-items-modal-toolbar.store-location-create-row,
|
.store-items-modal-toolbar.store-location-create-row,
|
||||||
.store-management-row {
|
.store-management-row {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.store-card-header > .store-location-manager-trigger {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.store-management-order {
|
.store-management-order {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,6 +107,9 @@ test("manage stores opens a modal to edit and delete household store items", asy
|
|||||||
|
|
||||||
const storeCard = page.locator(".store-card").filter({ hasText: "Costco" });
|
const storeCard = page.locator(".store-card").filter({ hasText: "Costco" });
|
||||||
await expect(storeCard).toBeVisible();
|
await expect(storeCard).toBeVisible();
|
||||||
|
await expect(storeCard.getByText("Costco", { exact: true })).toHaveCount(1);
|
||||||
|
await expect(storeCard.getByText("Default location")).toBeVisible();
|
||||||
|
await expect(storeCard.getByText("Default shopping location")).toHaveCount(0);
|
||||||
await expect(storeCard.getByRole("button", { name: "Manage Items" })).toBeVisible();
|
await expect(storeCard.getByRole("button", { name: "Manage Items" })).toBeVisible();
|
||||||
|
|
||||||
await storeCard.getByRole("button", { name: "Manage Items" }).click();
|
await storeCard.getByRole("button", { name: "Manage Items" }).click();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user