Skip to content

[Web] Menu editor — food item list, availability toggle, and add/edit modal #184

Description

@zakkiyyat

Overview

Build the Menu Editor page inside the restaurant dashboard. This is the primary tool restaurant owners use to manage their food items day-to-day: adding new dishes, editing details, toggling availability, and reviewing what customers see.

Dependencies: Issue #181 (Food Item API) and Issue #182 (Upload pipeline).


Figma Reference

📐 Figma: [Menu editor — item list, add/edit modal, availability toggle, empty state — placeholder, link to be added by design lead]


Route

```
/dashboard/menu
```

Protected — requires authenticated user with an active restaurant.


Page Layout

Header

  • Page title "Menu"
  • "Add item" button (opens modal)
  • Item count badge

Item List (table or card grid — follow Figma)

Columns:

Column Notes
Image thumbnail 48 × 48 px, fallback placeholder if no image
Name
Category
Price Formatted as currency (e.g. $12.50) — divide cents by 100 for display
Availability Toggle switch — calls PATCH immediately on change
Actions Edit (opens modal), Delete (confirmation prompt)
  • List is sorted by category, then name
  • Show empty state illustration + "Add your first item" CTA when the list is empty

Add / Edit Modal

Triggered by "Add item" button or row edit action.

Fields:

  • Name (required)
  • Description (optional, textarea)
  • Price (required, number input — user enters dollars, store as cents)
  • Category (text input with autocomplete from existing categories in this restaurant)
  • Dietary tags (multi-select from `DietaryTag` enum)
  • Images (up to 5, using the `ImageUploader` component from the onboarding issue)

File Structure

```
apps/web/app/dashboard/menu/
page.tsx
MenuItemTable.tsx
MenuItemModal.tsx # Add / edit form in a modal
AvailabilityToggle.tsx # Inline toggle with optimistic update
```


Acceptance Criteria

  • Item list fetches from `GET /api/restaurants/:id/food-items?includeUnavailable=true` (owners see all items)
  • Availability toggle calls `PATCH /api/restaurants/:id/food-items/:itemId` with `{ isAvailable: boolean }` immediately on change (optimistic UI — revert on error)
  • Add modal validates all fields with Zod before submitting; shows inline field errors
  • Edit modal pre-fills all existing values
  • Price input accepts dollars (e.g. `12.50`) and converts to cents before sending to API
  • Price is displayed as formatted currency in the table
  • Deleting an item shows a confirmation dialog ("Are you sure? This will hide the item from customers.")
  • After successful add/edit/delete, the list refreshes without a full page reload
  • Image uploads in the modal use `POST /api/upload` immediately on file selection; show previews
  • Modal closes and resets form state on cancel
  • All actions show loading states; error messages are shown inline (not as browser alerts)
  • The page is responsive and usable on tablet-sized screens (≥ 768 px)

State Management

Use React Query (or SWR) for list fetching and cache invalidation after mutations. Do not use a global store for this page.


API Calls

Action Endpoint
Fetch items `GET /api/restaurants/:id/food-items?includeUnavailable=true`
Create item `POST /api/restaurants/:id/food-items`
Update item `PATCH /api/restaurants/:id/food-items/:itemId`
Delete item `DELETE /api/restaurants/:id/food-items/:itemId`
Upload image `POST /api/upload`

Out of Scope

  • Item customisation / modifiers (Sprint 4)
  • Bulk operations beyond availability toggle (Sprint 6)
  • CSV export (Sprint 6)

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official Campaigncomplex~3–4 day effortsprint-1Sprint 1: Restaurant & Menu FoundationwebWeb dashboard (Next.js)

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions