VIBN Frontend for Coolify deployment
This commit is contained in:
120
app/api/vision/update/route.ts
Normal file
120
app/api/vision/update/route.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { adminDb } from "@/lib/firebase/admin";
|
||||
import { getAuth } from "firebase-admin/auth";
|
||||
|
||||
interface VisionBoardUpdate {
|
||||
vision?: {
|
||||
problemSolving?: string;
|
||||
changeCreated?: string;
|
||||
};
|
||||
targetUser?: {
|
||||
who?: string;
|
||||
whereTheyHangOut?: string;
|
||||
};
|
||||
needs?: {
|
||||
problemSolved?: string;
|
||||
benefitProvided?: string;
|
||||
};
|
||||
product?: {
|
||||
description?: string;
|
||||
differentiation?: string;
|
||||
};
|
||||
validationGoals?: {
|
||||
firstUser?: string;
|
||||
pathTo10Users?: string;
|
||||
pricing?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authHeader = request.headers.get("authorization");
|
||||
if (!authHeader?.startsWith("Bearer ")) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const token = authHeader.split("Bearer ")[1];
|
||||
const decodedToken = await getAuth().verifyIdToken(token);
|
||||
const userId = decodedToken.uid;
|
||||
|
||||
const { projectId, updates } = (await request.json()) as {
|
||||
projectId: string;
|
||||
updates: VisionBoardUpdate;
|
||||
};
|
||||
|
||||
if (!projectId || !updates) {
|
||||
return NextResponse.json(
|
||||
{ error: "Missing projectId or updates" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Verify user has access to this project
|
||||
const projectRef = adminDb.collection("projects").doc(projectId);
|
||||
const projectSnap = await projectRef.get();
|
||||
|
||||
if (!projectSnap.exists) {
|
||||
return NextResponse.json({ error: "Project not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
const projectData = projectSnap.data();
|
||||
if (projectData?.userId !== userId) {
|
||||
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||||
}
|
||||
|
||||
// Update vision board
|
||||
const visionRef = projectRef.collection("visionBoard").doc("current");
|
||||
const visionSnap = await visionRef.get();
|
||||
|
||||
const now = new Date();
|
||||
|
||||
if (visionSnap.exists()) {
|
||||
// Merge updates
|
||||
const currentData = visionSnap.data();
|
||||
const mergedData = {
|
||||
...currentData,
|
||||
...updates,
|
||||
vision: { ...currentData?.vision, ...updates.vision },
|
||||
targetUser: { ...currentData?.targetUser, ...updates.targetUser },
|
||||
needs: { ...currentData?.needs, ...updates.needs },
|
||||
product: { ...currentData?.product, ...updates.product },
|
||||
validationGoals: {
|
||||
...currentData?.validationGoals,
|
||||
...updates.validationGoals,
|
||||
},
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
await visionRef.update(mergedData);
|
||||
return NextResponse.json({ success: true, data: mergedData });
|
||||
} else {
|
||||
// Create new vision board
|
||||
const newData = {
|
||||
vision: updates.vision || { problemSolving: "", changeCreated: "" },
|
||||
targetUser: updates.targetUser || { who: "", whereTheyHangOut: "" },
|
||||
needs: updates.needs || { problemSolved: "", benefitProvided: "" },
|
||||
product: updates.product || { description: "", differentiation: "" },
|
||||
validationGoals: updates.validationGoals || {
|
||||
firstUser: "",
|
||||
pathTo10Users: "",
|
||||
pricing: "",
|
||||
},
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
await visionRef.set(newData);
|
||||
return NextResponse.json({ success: true, data: newData });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Vision board update error:", error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: "Failed to update vision board",
|
||||
details: error instanceof Error ? error.message : String(error),
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user