From 50091682469f7c2eea72b66ba85eaa707ffd8354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A8=B8=EB=8B=88=ED=8E=98=EB=8B=88?= Date: Thu, 16 Apr 2026 22:51:13 +0900 Subject: [PATCH] feat: transaction modal - add per-unit price label + total amount field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename '가격' → '1주당 가격' - Add '총 금액' field with auto-calculation - Price ↔ Total synced via quantity --- frontend/src/app/portfolio/[id]/page.tsx | 62 ++++++++++++++++++------ 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/portfolio/[id]/page.tsx b/frontend/src/app/portfolio/[id]/page.tsx index 8e6063b..465d5e1 100644 --- a/frontend/src/app/portfolio/[id]/page.tsx +++ b/frontend/src/app/portfolio/[id]/page.tsx @@ -128,6 +128,7 @@ export default function PortfolioDetailPage() { tx_type: 'buy', quantity: '', price: '', + totalAmount: '', executed_at: '', memo: '', }); @@ -251,7 +252,7 @@ export default function PortfolioDetailPage() { memo: txForm.memo || null, }); setTxModalOpen(false); - setTxForm({ ticker: '', tx_type: 'buy', quantity: '', price: '', executed_at: '', memo: '' }); + setTxForm({ ticker: '', tx_type: 'buy', quantity: '', price: '', totalAmount: '', executed_at: '', memo: '' }); setTxManualTicker(false); await Promise.all([fetchPortfolio(), fetchTransactions()]); } catch (err) { @@ -826,27 +827,60 @@ export default function PortfolioDetailPage() { +
+ + { + const qty = e.target.value; + const updates: Partial = { quantity: qty }; + // Recalculate total if price exists + if (txForm.price && qty) { + updates.totalAmount = String(Math.round(parseFloat(txForm.price) * parseInt(qty, 10))); + } + setTxForm({ ...txForm, ...updates }); + }} + /> +
- - setTxForm({ ...txForm, quantity: e.target.value })} - /> -
-
- + setTxForm({ ...txForm, price: e.target.value })} + onChange={(e) => { + const price = e.target.value; + const updates: Partial = { price }; + if (price && txForm.quantity) { + updates.totalAmount = String(Math.round(parseFloat(price) * parseInt(txForm.quantity, 10))); + } + setTxForm({ ...txForm, ...updates }); + }} + /> +
+
+ + { + const total = e.target.value; + const updates: Partial = { totalAmount: total }; + if (total && txForm.quantity && parseInt(txForm.quantity, 10) > 0) { + updates.price = String(Math.round(parseFloat(total) / parseInt(txForm.quantity, 10))); + } + setTxForm({ ...txForm, ...updates }); + }} />