Development Plan
Development Plan
Implementation plan for zpreorder (Issue #500) and Email Notifications (Issue #501).
Phase 1: Foundation
1.1 Admin API Endpoints
Add authenticated API endpoints to the main site for admin access:
| Endpoint | Purpose |
|---|---|
POST /api/admin/notify/list | List notify subscriptions (filterable) |
POST /api/admin/reservations/list | List reservations (filterable) |
POST /api/admin/notify/[id]/status | Update subscription status |
POST /api/admin/reservations/[id]/status | Update reservation status |
POST /api/admin/stats | Get summary statistics |
1.2 Duplicate Handling for Notify
Update notify-signup function to handle duplicates silently:
// Current behavior: Return error for duplicates
// New behavior: Return success (silent duplicate handling)
const isSubscribed = await isEmailSubscribed(productSlug, email);
if (isSubscribed) {
// Don't create duplicate, but return success
return {
statusCode: 200,
body: JSON.stringify({ success: true, message: '登録完了' }),
};
}
Rationale: Users may not remember if they’ve signed up. Silent success provides better UX.
Phase 2: Sub-App MVP
2.1 Project Setup
# Create sub-package
mkdir -p sub-packages/zpreorder
cd sub-packages/zpreorder
# Initialize with Next.js
pnpm create next-app . --typescript --tailwind --app --no-src-dir
2.2 Core Pages
| Page | Features |
|---|---|
Dashboard (/) | Summary stats, recent activity |
Notify List (/notify) | Table, filtering, bulk actions |
Reservations (/reservations) | Table, status management, notes |
Products (/products) | Per-product stats, quick links |
2.3 API Client
Dual-mode client supporting mock and remote data:
// lib/api-client.ts
export const apiClient = {
notify: {
list: (filter?: NotifyFilter) => fetchData('/notify/list', filter),
updateStatus: (id: string, status: string) => postData(`/notify/${id}/status`, { status }),
},
reservations: {
list: (filter?: ReservationFilter) => fetchData('/reservations/list', filter),
updateStatus: (id: string, status: string, notes?: string) =>
postData(`/reservations/${id}/status`, { status, notes }),
},
stats: () => fetchData('/stats'),
};
Phase 3: Email Integration (Issue #501)
3.1 Auto-Reply Emails
Registration confirmation emails (mocked initially):
| Event | Email Content |
|---|---|
| Notify signup | ”入荷通知の登録を受け付けました” |
| Reservation | ”予約を受け付けました (予約ID: xxx)“ |
3.2 Product Available Notification
Manual trigger from admin dashboard:
- Select product in admin UI
- Click “入荷通知を送信”
- Confirm subscriber count
- Send emails in batches
- Mark subscriptions as “notified”
:::note Mock Implementation Email sending will be mocked during initial development. Console logs will show what would be sent. Real SendGrid integration comes later. :::
Implementation Order
graph TD
A[1.1 Admin API Endpoints] --> C[2.1 Sub-App Setup]
B[1.2 Duplicate Handling] --> C
C --> D[2.2 Core Pages]
D --> E[2.3 API Client Integration]
E --> F[3.1 Auto-Reply Mocked]
F --> G[3.2 Product Notification Mocked]
G --> H[Real Email Integration]
Testing Strategy
Unit Tests
- API client mock/remote switching
- Data transformation functions
- Filter logic
E2E Tests
- Dashboard loads and displays stats
- Notify list filtering works
- Status updates persist (mock mode)
Environment Variables
# In sub-packages/zpreorder/.env for remote mode
VITE_BLOB_API_URL=https://preview--takazudomodular.netlify.app/api/admin
VITE_PREORDER_API_TOKEN=xxx