feat: implement remaining TODO.md feature ideas + fix mobile headers
Implements the six previously-unscoped feature ideas plus a mobile layout fix reported via screenshot: - Mobile: Recipes/Collections/Pantry/Meal Plan/Shopping Lists headers now stack and wrap instead of clipping buttons on narrow viewports. - Recipe diff/compare view: word/list diff against any past version, next to Restore in version history. - Shared meal plans & shopping lists: new shoppingListMembers/ mealPlanMembers tables (viewer/editor roles, mirrors collectionMembers), share dialogs, membership-checked routes. - PDF cookbook export: /print/collection/[id] renders a whole collection with page breaks, using the existing print-CSS pattern instead of adding a PDF rendering dependency. - Grocery delivery handoff: shopping lists can copy-as-text (works today) or send to Instacart once INSTACART_API_KEY is configured (stub adapter — real API needs a partner agreement). - Personalized "For You" feed tab: ranks public recipes by tag/ dietary overlap with the user's favorited/highly-rated history. - PWA: added manifest.json + icons on top of the existing service worker so the app is installable; cook-mode pages were already cached for offline use. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,9 +20,11 @@ type Item = {
|
||||
export function ShoppingListView({
|
||||
listId,
|
||||
initialItems,
|
||||
readOnly = false,
|
||||
}: {
|
||||
listId: string;
|
||||
initialItems: Item[];
|
||||
readOnly?: boolean;
|
||||
}) {
|
||||
const t = useTranslations("mealPlan");
|
||||
const tShopping = useTranslations("shoppingLists");
|
||||
@@ -54,6 +56,7 @@ export function ShoppingListView({
|
||||
}
|
||||
|
||||
async function toggleItem(item: Item) {
|
||||
if (readOnly) return;
|
||||
const next = !item.checked;
|
||||
setItems((prev) => prev.map((i) => i.id === item.id ? { ...i, checked: next } : i));
|
||||
await fetch(`/api/v1/shopping-lists/${listId}/items/${item.id}`, {
|
||||
@@ -97,7 +100,8 @@ export function ShoppingListView({
|
||||
<button
|
||||
key={item.id}
|
||||
onClick={() => toggleItem(item)}
|
||||
className="w-full flex items-center gap-3 px-4 py-3 hover:bg-muted/30 text-left transition-colors"
|
||||
disabled={readOnly}
|
||||
className="w-full flex items-center gap-3 px-4 py-3 hover:bg-muted/30 text-left transition-colors disabled:cursor-default disabled:hover:bg-transparent"
|
||||
>
|
||||
<div className={cn(
|
||||
"h-5 w-5 rounded border-2 flex items-center justify-center shrink-0 transition-colors",
|
||||
|
||||
Reference in New Issue
Block a user