feat: push+email notifications, recipe notes, fork/clone, pantry-aware lists, GDPR export
Five S-sized items from HANDOFF.md's new-features backlog, all wiring up previously-orphaned infra: - createNotification now sends web push + email for every notification type (follow/comment/reply/reaction/rating/mention), not just comments - Personal recipe notes: private per-user notes on any viewable recipe (recipeNotes table had zero API/UI before this) - Recipe fork/clone: deep-copies a viewable recipe into your own library as a private draft, linked via recipeVariations, respects tier quota - Pantry-aware shopping lists: meal-plan-generated lists now subtract on-hand pantry quantities (ingredientId match, falling back to normalized name match) and flag partial/ambiguous matches instead of guessing - GDPR data export: downloadable JSON of a user's own content and activity across every relevant table, secrets/internal tables excluded New migrations 0025 (unique index for recipe-notes upsert) and 0026 (shopping_list_items.in_pantry) generated, left unapplied like 0023/0024. Verified with typecheck, lint, and a full local `docker build`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,19 @@
|
||||
"reply": "{name} replied to your comment",
|
||||
"reaction": "{name} reacted to your comment",
|
||||
"rating": "{name} rated your recipe",
|
||||
"mention": "{name} mentioned you in a comment"
|
||||
"mention": "{name} mentioned you in a comment",
|
||||
"detail": {
|
||||
"comment": "{name} commented on your recipe \"{title}\"",
|
||||
"rating": "{name} rated your recipe \"{title}\" {stars} stars"
|
||||
},
|
||||
"pushTitle": {
|
||||
"follow": "New follower",
|
||||
"comment": "New comment",
|
||||
"reply": "New reply",
|
||||
"reaction": "New reaction",
|
||||
"rating": "New rating",
|
||||
"mention": "You were mentioned"
|
||||
}
|
||||
},
|
||||
"recipe": {
|
||||
"byAuthor": "by {name}",
|
||||
@@ -81,6 +93,11 @@
|
||||
"pairingBulkSuccess": "{count} recipes generated — find them in your library",
|
||||
"pairingDialogTitle": "Complete the meal",
|
||||
"pairingDialogDescription": "AI-suggested dishes that pair well with this recipe. Generate any of them as a new recipe.",
|
||||
"forkTooltip": "Fork this recipe",
|
||||
"forked": "Recipe forked to your library",
|
||||
"forkFailed": "Failed to fork recipe",
|
||||
"forkLimitReached": "Recipe limit reached for your tier",
|
||||
"forkedFrom": "Forked from {title}",
|
||||
"pairingFindingLabel": "Finding perfect pairings…",
|
||||
"pairingSuggestButton": "Suggest pairings",
|
||||
"pairingRegenerate": "Regenerate",
|
||||
@@ -508,6 +525,15 @@
|
||||
"tagLabel": "Tag",
|
||||
"clearFilters": "Clear filters"
|
||||
},
|
||||
"recipeNotes": {
|
||||
"title": "Your private notes",
|
||||
"visibilityHint": "Only visible to you — never shared with the recipe's author or anyone else.",
|
||||
"placeholder": "e.g. I used less salt than the recipe calls for, great with rice instead of pasta…",
|
||||
"save": "Save",
|
||||
"saving": "Saving…",
|
||||
"saved": "Note saved",
|
||||
"saveFailed": "Failed to save note"
|
||||
},
|
||||
"recipeForm": {
|
||||
"titleLabel": "Title *",
|
||||
"titleRequired": "Title is required",
|
||||
@@ -690,6 +716,7 @@
|
||||
"copiedToClipboard": "List copied to clipboard",
|
||||
"exportBuildFailed": "Could not build export",
|
||||
"instacartNotConfigured": "Instacart isn't configured yet",
|
||||
"alreadyInPantry": "Already in pantry",
|
||||
"items": "{checked}/{total} items",
|
||||
"itemsChecked": "{checked}/{total} items checked",
|
||||
"fromMealPlan": " · From meal plan",
|
||||
@@ -872,6 +899,9 @@
|
||||
"changePasswordButton": "Change password",
|
||||
"passwordChanged": "Password changed successfully.",
|
||||
"passwordChangeFailed": "Failed to change password.",
|
||||
"downloadData": "Download my data",
|
||||
"downloadDataDescription": "Get a JSON export of all the personal data Epicure holds about you — your profile, recipes, activity, and settings.",
|
||||
"downloadDataButton": "Download my data",
|
||||
"webhookCreateFailed": "Failed to create webhook",
|
||||
"webhookDeleteFailed": "Failed to delete webhook",
|
||||
"webhookUpdateFailed": "Failed to update webhook",
|
||||
|
||||
Reference in New Issue
Block a user