Save ticker and last decision to DB; add order suggestion UI; upsert stocks with execution details; ensure analysis saves ticker
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -116,6 +116,15 @@ export default function StockDetail() {
|
|||||||
setDecision(null);
|
setDecision(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Ensure ticker is saved in DB before analysis
|
||||||
|
try {
|
||||||
|
const fd = new FormData();
|
||||||
|
fd.append("ticker", ticker);
|
||||||
|
await fetch("/api/stocks", { method: "POST", body: fd });
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Failed to ensure ticker saved:", e);
|
||||||
|
}
|
||||||
|
|
||||||
const res = await fetch("/api/analyze", {
|
const res = await fetch("/api/analyze", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
@@ -134,6 +143,18 @@ export default function StockDetail() {
|
|||||||
setAnalystReports(reports);
|
setAnalystReports(reports);
|
||||||
setDebateRounds(debates);
|
setDebateRounds(debates);
|
||||||
setDecision(data);
|
setDecision(data);
|
||||||
|
|
||||||
|
// Save last decision/explanation to DB
|
||||||
|
try {
|
||||||
|
const fd2 = new FormData();
|
||||||
|
fd2.append("ticker", ticker);
|
||||||
|
fd2.append("lastDecision", data.action ?? "");
|
||||||
|
fd2.append("lastExplanation", data.reasoning ?? "");
|
||||||
|
if (data.executionPlan) fd2.append("lastExecutionPlan", JSON.stringify(data.executionPlan));
|
||||||
|
await fetch("/api/stocks", { method: "POST", body: fd2 });
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Failed to save decision to DB:", e);
|
||||||
|
}
|
||||||
|
|
||||||
// Cache the results
|
// Cache the results
|
||||||
sessionStorage.setItem(cacheKey, JSON.stringify({
|
sessionStorage.setItem(cacheKey, JSON.stringify({
|
||||||
@@ -375,6 +396,23 @@ export default function StockDetail() {
|
|||||||
<div>Note: <span className="font-medium">{decision.executionPlan.note}</span></div>
|
<div>Note: <span className="font-medium">{decision.executionPlan.note}</span></div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Order suggestion summary */}
|
||||||
|
<div className="mt-3 bg-gray-50 rounded-lg p-3 border border-gray-200">
|
||||||
|
<h5 className="text-sm font-medium text-gray-800">Order Suggestion</h5>
|
||||||
|
<div className="text-sm text-gray-700 mt-2">
|
||||||
|
<div>
|
||||||
|
<span className="font-medium">{decision.action.toUpperCase()}</span>
|
||||||
|
{decision.executionPlan.amount} shares
|
||||||
|
{decision.executionPlan.takeProfit != null && (
|
||||||
|
<span> — Take profit: ${decision.executionPlan.takeProfit}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{decision.executionPlan.riskManagement?.maxLossPercent != null && (
|
||||||
|
<div className="text-xs text-gray-500">Risk: {decision.executionPlan.riskManagement.maxLossPercent}% max loss</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,8 +23,26 @@ export async function action({ request }: { request: Request }) {
|
|||||||
return Response.json({ success: true });
|
return Response.json({ success: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const stock = await db.stock.create({
|
// Optional fields to save/update
|
||||||
data: { ticker },
|
const lastDecision = formData.get("lastDecision")?.toString();
|
||||||
|
const lastExplanation = formData.get("lastExplanation")?.toString();
|
||||||
|
const lastExecutionPlan = formData.get("lastExecutionPlan")?.toString();
|
||||||
|
|
||||||
|
// Upsert the stock record so ticker is ensured and optional fields are saved
|
||||||
|
const stock = await db.stock.upsert({
|
||||||
|
where: { ticker },
|
||||||
|
update: {
|
||||||
|
lastDecision: lastDecision ?? undefined,
|
||||||
|
lastExplanation: lastExplanation ?? undefined,
|
||||||
|
lastExecutionPlan: lastExecutionPlan ?? undefined,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
ticker,
|
||||||
|
lastDecision: lastDecision ?? undefined,
|
||||||
|
lastExplanation: lastExplanation ?? undefined,
|
||||||
|
lastExecutionPlan: lastExecutionPlan ?? undefined,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return Response.json(stock);
|
return Response.json(stock);
|
||||||
}
|
}
|
||||||
@@ -9,9 +9,12 @@ datasource db {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Stock {
|
model Stock {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
ticker String @unique
|
ticker String @unique
|
||||||
notes String?
|
notes String?
|
||||||
createdAt DateTime @default(now())
|
lastDecision String?
|
||||||
updatedAt DateTime @updatedAt
|
lastExplanation String?
|
||||||
|
lastExecutionPlan String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user