Flatten store location cards #14
@ -87,8 +87,8 @@ export default function ManageStores() {
|
||||
<section className="manage-section">
|
||||
<h2>Store Locations ({householdStores.length})</h2>
|
||||
<p className="manage-stores-help">
|
||||
Stores and locations are private to this household. Each location has its own zones,
|
||||
item defaults, and shopping order.
|
||||
Stores are private to this household. Locations define map-specific zones, item
|
||||
placement, and shopping order.
|
||||
</p>
|
||||
{householdStores.length === 0 ? (
|
||||
<p className="empty-message">No store locations added yet.</p>
|
||||
@ -96,6 +96,7 @@ export default function ManageStores() {
|
||||
<div className="stores-list">
|
||||
{groupedStores.map((storeGroup) => (
|
||||
<div key={storeGroup.household_store_id} className="store-card">
|
||||
<div className="store-card-header">
|
||||
<div className="store-info">
|
||||
<h3>{storeGroup.name}</h3>
|
||||
</div>
|
||||
@ -107,20 +108,27 @@ export default function ManageStores() {
|
||||
canManage={isAdmin}
|
||||
refreshAfterStoreChange={refreshAfterStoreChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="store-location-list">
|
||||
{storeGroup.locations.map((location) => (
|
||||
{storeGroup.locations.map((location) => {
|
||||
const label = locationLabel(location);
|
||||
const showLocationName =
|
||||
storeGroup.locations.length > 1 || label !== storeGroup.name;
|
||||
|
||||
return (
|
||||
<div key={location.id} className="store-location-row">
|
||||
<div className="store-info">
|
||||
<strong>{locationLabel(location)}</strong>
|
||||
<div className="store-info store-location-copy">
|
||||
{showLocationName ? <strong>{label}</strong> : null}
|
||||
{location.address ? (
|
||||
<p className="store-location">{location.address}</p>
|
||||
) : null}
|
||||
{location.is_default ? (
|
||||
<p className="store-location">Default shopping location</p>
|
||||
<p className="store-location">Default location</p>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="store-location-controls">
|
||||
<StoreZoneManager
|
||||
householdId={activeHousehold.id}
|
||||
location={location}
|
||||
@ -134,7 +142,9 @@ export default function ManageStores() {
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@ -50,11 +50,11 @@
|
||||
background: var(--background);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 1.25rem;
|
||||
padding: 1rem;
|
||||
transition: all 0.2s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.store-card:hover {
|
||||
@ -62,16 +62,23 @@
|
||||
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 {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin: 0 0 0.5rem 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.store-location {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
font-size: 0.85rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -90,17 +97,37 @@
|
||||
.store-location-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
gap: 0.65rem;
|
||||
}
|
||||
|
||||
.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;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 0.75rem;
|
||||
padding: 1rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
background: var(--card-bg);
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.store-location-manager-trigger,
|
||||
@ -108,9 +135,8 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.store-location-row > .store-zone-manager-trigger,
|
||||
.store-location-row > .store-available-items-trigger {
|
||||
grid-column: 1 / -1;
|
||||
.store-card-header > .store-location-manager-trigger {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.store-items-modal-toolbar.store-management-create-row {
|
||||
@ -283,13 +309,18 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.store-location-row,
|
||||
.store-card-header,
|
||||
.store-location-controls,
|
||||
.store-items-modal-toolbar.store-management-create-row,
|
||||
.store-items-modal-toolbar.store-location-create-row,
|
||||
.store-management-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.store-card-header > .store-location-manager-trigger {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.store-management-order {
|
||||
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" });
|
||||
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 storeCard.getByRole("button", { name: "Manage Items" }).click();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user