feat: version history as 10th feature flag, richer upgrade prompts, close unguarded photo-import tab (v0.80.0)
Recipe version history is now gated like the other 9 per-tier features (enabled by default, locked-vs-hidden treatment via isFeatureAvailableAnyTier). UpgradeDialog now shows a tagline + concrete bullet list per feature instead of one generic sentence. Also closes a real gap: the AI-generate dialog's Photo tab hit /api/v1/ai/import-photo directly with no tier check in the UI (server route was already correctly gated) — a locked-out user could fill it in and hit a dead-end error instead of an upgrade prompt. Now threaded through the same lock/hide props as the dedicated PhotoImportButton. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,12 +2,17 @@ import { NextRequest, NextResponse } from "next/server";
|
||||
import { db, recipes, recipeIngredients, recipeSteps, recipeSnapshots } from "@epicure/db";
|
||||
import { eq, and, max, desc } from "@epicure/db";
|
||||
import { requireSessionOrApiKey } from "@/lib/api-auth";
|
||||
import { requireFeatureEnabledResponse } from "@/lib/feature-flags";
|
||||
|
||||
type Params = { params: Promise<{ id: string; versionId: string }> };
|
||||
|
||||
export async function GET(req: NextRequest, { params }: Params) {
|
||||
const { session, response } = await requireSessionOrApiKey(req, { rateLimit: { limit: 60, windowSeconds: 60 } });
|
||||
if (response) return response;
|
||||
|
||||
const featureDenied = await requireFeatureEnabledResponse(session!.user.id, "version_history");
|
||||
if (featureDenied) return featureDenied;
|
||||
|
||||
const { id, versionId } = await params;
|
||||
|
||||
// Verify ownership
|
||||
@@ -31,6 +36,10 @@ export async function GET(req: NextRequest, { params }: Params) {
|
||||
export async function POST(req: NextRequest, { params }: Params) {
|
||||
const { session, response } = await requireSessionOrApiKey(req, { rateLimit: { limit: 60, windowSeconds: 60 } });
|
||||
if (response) return response;
|
||||
|
||||
const featureDenied = await requireFeatureEnabledResponse(session!.user.id, "version_history");
|
||||
if (featureDenied) return featureDenied;
|
||||
|
||||
const { id, versionId } = await params;
|
||||
|
||||
const body = await req.json() as { action?: string };
|
||||
|
||||
@@ -2,12 +2,17 @@ import { NextRequest, NextResponse } from "next/server";
|
||||
import { db, recipes, recipeSnapshots } from "@epicure/db";
|
||||
import { eq, and, desc } from "@epicure/db";
|
||||
import { requireSessionOrApiKey } from "@/lib/api-auth";
|
||||
import { requireFeatureEnabledResponse } from "@/lib/feature-flags";
|
||||
|
||||
type Params = { params: Promise<{ id: string }> };
|
||||
|
||||
export async function GET(req: NextRequest, { params }: Params) {
|
||||
const { session, response } = await requireSessionOrApiKey(req, { rateLimit: { limit: 60, windowSeconds: 60 } });
|
||||
if (response) return response;
|
||||
|
||||
const featureDenied = await requireFeatureEnabledResponse(session!.user.id, "version_history");
|
||||
if (featureDenied) return featureDenied;
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
// Verify ownership
|
||||
|
||||
Reference in New Issue
Block a user