Skip to main content

Store Components

Store components enable bookstore owners to manage inventory, process sales, and showcase their businesses.

InventoryItemTile

A list tile displaying inventory item details with stock status indicators.

Usage

InventoryItemTile(
item: inventoryItem,
onTap: () => navigateToDetail(item.id),
)

Props

PropertyTypeRequiredDescription
itemInventoryItemYesInventory item with book, price, quantity, condition
onTapVoidCallbackYesCallback when tile is tapped

Anatomy

Leading

  • Thumbnail: 50x70px book cover
  • Fallback: Gray surface with book icon

Title

  • Book title (2-line max with ellipsis)
  • Style: AppTypography.bookTitle

Subtitle

  • Authors: Comma-separated, 1-line max
  • Price: Dollar format with 2 decimals, bold
  • Stock Badge: Colored badge with quantity or "Out of stock"
  • Condition Badge: Shows condition if not new

Trailing

  • Chevron right icon

Stock Status Logic

final isLowStock = item.quantity < 3;
final isOutOfStock = item.quantity == 0;

Status Colors

  • Out of Stock: Error container color (red theme)
  • Low Stock: Orange background at 0.2 alpha, orange text
  • In Stock: Primary container color

Condition Labels

Enum mapping via BookCondition:

  • new: "New"
  • like_new: "Like New"
  • good: "Good"
  • fair: "Fair"

Condition Badge (only shown if not new):

  • Tertiary container background
  • Small badge (12px font)
  • Displayed next to stock badge

Styling

  • Padding: 16px horizontal, 6px vertical
  • Border radius: 12px
  • Elevation: 2
  • Background: White

Features

  • Stock Indicators: Visual warnings for low/out-of-stock items
  • Condition Display: Clearly shows used book condition
  • Tappable: Opens inventory detail page

InventoryCard

For grid layouts, inventory items can use a card format similar to BookCard.

Implementation Pattern

Card(
child: Column(
children: [
// Book cover
Expanded(child: CoverImage()),
// Details
Padding(
child: Column(
children: [
Text(item.book.title),
Text('\$${item.priceInDollars}'),
StockBadge(quantity: item.quantity),
],
),
),
],
),
)

POSPanel

The Point of Sale panel is implemented in POSPage for in-store transactions.

Usage Location

/Users/terryheath/Documents/bookwish_monorepo/app/lib/ui/pages/shop/pos_page.dart

Features

  • Barcode Scanning: Add items via ISBN scanner
  • Cart Management: Add/remove items from transaction
  • Payment Processing: Cash and card payments via Square
  • Receipt Generation: Email receipts to customers
  • Discount Application: Apply percentage or fixed discounts
  • Tax Calculation: Automatic tax calculation based on store settings

Key Components

Item Search

  • ISBN barcode scanner integration
  • Manual ISBN entry
  • Inventory item lookup

Cart Display

  • List of items with quantities
  • Running subtotal
  • Tax calculation
  • Total display

Checkout Actions

  • Process payment button
  • Clear cart button
  • Apply discount button

Integration

  • Uses Square payment integration
  • Connects to store's Square account
  • Records transaction in order history

StoreHeader (Web)

Header component for store websites (Next.js).

Usage

<StoreHeader store={store} />

Props

PropertyTypeRequiredDescription
storeStoreYesStore data with name, logo, slug, colors

Anatomy

Logo Section

  • Store logo (40x40px, rounded) or initial letter fallback
  • Store name in serif font (text-xl, bold)
  • Clickable to return to store home

Navigation

  • Browse Books link
  • Read With Us link (programs)
  • "Powered by BookWish" link

Styling

  • Position: Sticky top-0, z-10
  • Background: White with 95% opacity, backdrop blur
  • Border: Bottom border
  • Container: Max width 6xl (1152px), centered
  • Padding: 4 units (16px) all

Dynamic Branding

Uses CSS custom properties:

style={{
"--dynamic-primary": store.primaryColor || "#1a1a1a",
}}

Features

  • Sticky Header: Remains visible while scrolling
  • Responsive: Adapts to mobile/desktop
  • Brand Colors: Applies store's primary color

StoreFooter (Web)

Footer component for store websites (Next.js).

Usage

<StoreFooter store={store} />

Props

PropertyTypeRequiredDescription
storeStoreYesStore data with address, hours, phone

Anatomy

Store Info Column

  • Store name heading
  • Full address (if available)
  • Phone number (if available)

Hours Column (if store.hours exists)

  • Day-by-day hours display
  • Formatted as key-value pairs

Links Column

  • Get the BookWish App
  • Terms of Service
  • Privacy Policy

Bottom Bar

  • Copyright notice
  • "Powered by BookWish" link

Styling

  • Background: Dark gray (gray-900)
  • Text Color: Light gray (gray-400)
  • Headings: White
  • Grid: 3 columns on desktop, stacked on mobile
  • Padding: 12 units (48px) vertical, 4 units horizontal
  • Top Margin: 16 units (64px)

Features

  • Responsive Grid: Adapts to screen size
  • Optional Sections: Only shows hours if available
  • Brand Links: Links back to main BookWish app

StoreProgramCard (Web)

Program cards for clubs and challenges on store websites.

ClubCard

Displays book club information with current reading.

Anatomy

  • Cover Image: 80x80px rounded, or icon fallback
  • Club Name: Semibold heading
  • Description: 2-line clamp
  • Member Count: Small text with person icon
  • Current Book Section (if available):
    • "Currently Reading" label
    • Book cover thumbnail (40x56px)
    • Book title and authors
  • Join Button: "Join in App" CTA

ChallengeCard

Displays reading challenge information with status.

Anatomy

  • Challenge Name: Semibold heading
  • Status Badge: Active/Upcoming/Ended with color coding
  • Book Count: Small text
  • Description: 2-line clamp
  • Date Range: Start and end dates
  • Participant Count: Small text
  • Join Button: "Join in App" CTA

Status Logic

const isActive = now >= startDate && now <= endDate;
const isUpcoming = now < startDate;

Status Colors

  • Active: Green background, green text
  • Upcoming: Amber background, dark text
  • Ended: Gray background, gray text

Styling

  • Card: White background, border, rounded-xl
  • Padding: 5 units (20px)
  • Hover: Shadow-md on hover
  • Border: Subtle parchment color (#E0D7C8)

App Integration

Both cards link to BookWish app:

const appLink = `${config.mainAppUrl}/club/${club.id}`;
const appLink = `${config.mainAppUrl}/challenge/${challenge.id}`;

InventoryTable

Used in inventory management page for tabular display.

Implementation

Grid/list view of InventoryItemTile components in InventoryPage.

Columns (Conceptual)

  • Book thumbnail
  • Title/Author
  • Price
  • Quantity
  • Condition
  • Actions

Features

  • Sorting: By title, price, quantity
  • Filtering: By condition, stock status
  • Bulk Actions: Select multiple items
  • Quick Edit: Inline quantity updates

Location

/Users/terryheath/Documents/bookwish_monorepo/app/lib/ui/pages/shop/inventory_page.dart

StoreSetup Components

Store setup flow components for onboarding.

StoreSetupPage

Located at: /Users/terryheath/Documents/bookwish_monorepo/app/lib/ui/pages/shop/store_setup_page.dart

Setup Steps

  1. Store name and description
  2. Address information
  3. Hours of operation
  4. Payment integration (Square)
  5. Website customization

HoursEditor

Component for editing store hours.

Located at: /Users/terryheath/Documents/bookwish_monorepo/app/lib/ui/components/hours_editor.dart

Features

  • Day Selection: Toggle each day of week
  • Time Range: Start and end time pickers
  • Closed Days: Mark days as closed
  • Copy Hours: Copy to multiple days

StoreChip

Small chip component for displaying store information.

Located at: /Users/terryheath/Documents/bookwish_monorepo/app/lib/ui/components/store_chip.dart

Usage

Display store name with icon in search results or references.

Common Patterns

Price Formatting

// Flutter
final priceInDollars = priceCents / 100;
'\$${priceInDollars.toStringAsFixed(2)}'

// TypeScript (Web)
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(cents / 100)

Stock Status Colors

Consistent color scheme:

  • Error/Out of Stock: Red/error container
  • Warning/Low Stock: Orange/amber
  • Success/In Stock: Green/primary container

Condition Display

Only show condition badge when condition !== 'new'

Mobile App

  • Tap inventory item → Detail page
  • Detail page → Edit mode
  • POS page → Process transaction

Web

  • Book card → Book detail page
  • Store header → Store pages
  • CTA buttons → Open BookWish app

Typography

Flutter Components

  • Book Title: AppTypography.bookTitle
  • Price: AppTypography.cardLabel with bold weight
  • Badge Text: 12px font size
  • Metadata: AppTypography.caption

Web Components

  • Headings: Semibold, various sizes
  • Body: Default sans-serif
  • Store Name: Serif font for branding
  • Labels: Uppercase tracking for small text

Color Palette

Flutter

  • Primary: AppColors.inkBlue
  • Success: AppColors.forestGreen
  • Warning: Colors.orange
  • Error: AppColors.error / AppColors.coralSpine
  • Surface: Colors.white
  • Background: AppColors.parchment

Web

  • Primary: Store-specific via --store-primary CSS variable
  • Dark: #233548 (ink blue)
  • Accent: #FFC857 (amber)
  • Background: White
  • Border: #E0D7C8 (parchment)
  • Footer: gray-900