refactor(portfolio): 보유행/브로커섹션 추출 → PortfolioTab shell 축소
This commit is contained in:
@@ -1,11 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Loading from '../../../components/Loading';
|
import Loading from '../../../components/Loading';
|
||||||
import { formatNumber, formatPercent, toNumeric, profitColorClass } from '../stockUtils';
|
|
||||||
import PriceSessionBadge from './portfolio/PriceSessionBadge';
|
|
||||||
import AddHoldingForm from './portfolio/AddHoldingForm';
|
import AddHoldingForm from './portfolio/AddHoldingForm';
|
||||||
import PortfolioSummary from './portfolio/PortfolioSummary';
|
import PortfolioSummary from './portfolio/PortfolioSummary';
|
||||||
import AssetHistoryChart from './portfolio/AssetHistoryChart';
|
import AssetHistoryChart from './portfolio/AssetHistoryChart';
|
||||||
import CashPanel from './portfolio/CashPanel';
|
import CashPanel from './portfolio/CashPanel';
|
||||||
|
import BrokerSection from './portfolio/BrokerSection';
|
||||||
|
|
||||||
const PortfolioTab = ({ pf, asset, handleSell, handleSaveSnapshot }) => (
|
const PortfolioTab = ({ pf, asset, handleSell, handleSaveSnapshot }) => (
|
||||||
<>
|
<>
|
||||||
@@ -57,254 +56,9 @@ const PortfolioTab = ({ pf, asset, handleSell, handleSaveSnapshot }) => (
|
|||||||
<CashPanel pf={pf} />
|
<CashPanel pf={pf} />
|
||||||
|
|
||||||
{/* Broker cards stacked */}
|
{/* Broker cards stacked */}
|
||||||
{pf.brokerGroups.map(([broker, items]) => {
|
{pf.brokerGroups.map(([broker, items]) => (
|
||||||
const bSummary = pf.getBrokerSummary(items);
|
<BrokerSection key={broker} broker={broker} items={items} pf={pf} handleSell={handleSell} />
|
||||||
const color = pf.brokerColors[broker];
|
))}
|
||||||
return (
|
|
||||||
<section
|
|
||||||
key={broker}
|
|
||||||
className="stock-panel stock-panel--wide pf-broker-section"
|
|
||||||
style={{ borderColor: color?.border, background: color?.bg }}
|
|
||||||
>
|
|
||||||
<div className="stock-panel__head">
|
|
||||||
<div>
|
|
||||||
<p className="stock-panel__eyebrow" style={{ color: color?.border }}>
|
|
||||||
{broker}
|
|
||||||
</p>
|
|
||||||
<h3>{broker} 보유 현황</h3>
|
|
||||||
<p className="stock-panel__sub">
|
|
||||||
{items.length}종목 · 총 매입{' '}
|
|
||||||
{formatNumber(bSummary.totalBuy)} · 평가{' '}
|
|
||||||
{formatNumber(bSummary.totalEval)} · 손익{' '}
|
|
||||||
<span className={`stock-profit ${profitColorClass(bSummary.totalProfit)}`}>
|
|
||||||
{formatNumber(bSummary.totalProfit)} (
|
|
||||||
{formatPercent(bSummary.totalProfitRate)})
|
|
||||||
</span>
|
|
||||||
{(() => {
|
|
||||||
const bc = pf.cashList.find((c) => c.broker === broker);
|
|
||||||
return bc ? (
|
|
||||||
<span className="pf-cash-badge">
|
|
||||||
예수금 {formatNumber(bc.cash)}원
|
|
||||||
</span>
|
|
||||||
) : null;
|
|
||||||
})()}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="stock-holdings">
|
|
||||||
{items.map((item) => {
|
|
||||||
const profitAmt = item.profit_amount;
|
|
||||||
const profitRate = item.profit_rate;
|
|
||||||
const profitAmtN = toNumeric(profitAmt);
|
|
||||||
const profitRateN = toNumeric(profitRate);
|
|
||||||
const isEditing = pf.editingId === item.id;
|
|
||||||
const isDeleting = pf.deleteConfirmId === item.id;
|
|
||||||
const isSelling = pf.sellConfirmId === item.id;
|
|
||||||
const sellPrice = item.current_price ?? item.avg_price;
|
|
||||||
const saleAmount = sellPrice != null ? sellPrice * (item.quantity ?? 0) : null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={item.id} className="stock-holdings__item pf-item">
|
|
||||||
{isEditing ? (
|
|
||||||
<div className="pf-edit-row">
|
|
||||||
<div className="pf-edit-fields">
|
|
||||||
<label>
|
|
||||||
수량
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min={1}
|
|
||||||
value={pf.editForm.quantity ?? ''}
|
|
||||||
onChange={(e) =>
|
|
||||||
pf.setEditForm((p) => ({
|
|
||||||
...p,
|
|
||||||
quantity: Number(e.target.value),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
평균단가
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min={0}
|
|
||||||
value={pf.editForm.avg_price ?? ''}
|
|
||||||
onChange={(e) =>
|
|
||||||
pf.setEditForm((p) => ({
|
|
||||||
...p,
|
|
||||||
avg_price: Number(e.target.value),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
매입가
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min={0}
|
|
||||||
value={pf.editForm.purchase_price ?? ''}
|
|
||||||
onChange={(e) =>
|
|
||||||
pf.setEditForm((p) => ({
|
|
||||||
...p,
|
|
||||||
purchase_price: Number(e.target.value),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="pf-edit-actions">
|
|
||||||
<button
|
|
||||||
className="button primary small"
|
|
||||||
onClick={() => pf.handleEditSave(item.id)}
|
|
||||||
disabled={pf.editLoading}
|
|
||||||
>
|
|
||||||
{pf.editLoading ? '저장 중...' : '저장'}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="button ghost small"
|
|
||||||
onClick={() => pf.setEditingId(null)}
|
|
||||||
>
|
|
||||||
취소
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
<p className="stock-holdings__name">
|
|
||||||
{item.name ?? item.ticker ?? 'N/A'}
|
|
||||||
</p>
|
|
||||||
<span className="stock-holdings__code">
|
|
||||||
{item.ticker ?? ''}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="stock-holdings__metric">
|
|
||||||
<span>수량</span>
|
|
||||||
<strong>{formatNumber(item.quantity)}</strong>
|
|
||||||
</div>
|
|
||||||
<div className="stock-holdings__metric">
|
|
||||||
<span>평균단가</span>
|
|
||||||
<strong>{formatNumber(item.avg_price)}</strong>
|
|
||||||
</div>
|
|
||||||
<div className="stock-holdings__metric">
|
|
||||||
<span>매입가</span>
|
|
||||||
<strong>{formatNumber(item.purchase_price ?? item.avg_price)}</strong>
|
|
||||||
</div>
|
|
||||||
<div className="stock-holdings__metric">
|
|
||||||
<span>현재가</span>
|
|
||||||
<strong className={item.current_price == null ? 'pf-null-price' : ''}>
|
|
||||||
{item.current_price != null
|
|
||||||
? formatNumber(item.current_price)
|
|
||||||
: '조회 실패'}
|
|
||||||
<PriceSessionBadge
|
|
||||||
session={item.price_session}
|
|
||||||
asOf={item.price_as_of}
|
|
||||||
/>
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div className="stock-holdings__metric">
|
|
||||||
<span>평가금액</span>
|
|
||||||
<strong>
|
|
||||||
{item.current_price != null && item.quantity != null
|
|
||||||
? formatNumber(item.current_price * item.quantity)
|
|
||||||
: '-'}
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div className="stock-holdings__metric">
|
|
||||||
<span>수익률</span>
|
|
||||||
<strong className={`stock-profit ${profitColorClass(profitRateN)}`}>
|
|
||||||
{profitRate != null ? formatPercent(profitRate) : '-'}
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div className="stock-holdings__metric">
|
|
||||||
<span>평가손익</span>
|
|
||||||
<strong className={`stock-profit ${profitColorClass(profitAmtN)}`}>
|
|
||||||
{profitAmt != null ? formatNumber(profitAmt) : '-'}
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div className="pf-item-actions">
|
|
||||||
{!isSelling && !isDeleting && (
|
|
||||||
<button
|
|
||||||
className="button ghost small"
|
|
||||||
onClick={() => pf.handleEditStart(item)}
|
|
||||||
title="수정"
|
|
||||||
>
|
|
||||||
✏️
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
{isSelling ? (
|
|
||||||
<div className="pf-sell-confirm">
|
|
||||||
<span className="pf-sell-confirm__msg">
|
|
||||||
{item.current_price == null && (
|
|
||||||
<small className="pf-sell-confirm__warn">현재가 미조회 — 매입가 기준</small>
|
|
||||||
)}
|
|
||||||
{saleAmount != null
|
|
||||||
? `${formatNumber(saleAmount)}원 매도 후 예수금 반영`
|
|
||||||
: '매도 처리'}
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
className="button small pf-btn-sell"
|
|
||||||
onClick={() => handleSell(item)}
|
|
||||||
disabled={pf.sellLoading}
|
|
||||||
>
|
|
||||||
{pf.sellLoading ? '처리 중...' : '매도 확인'}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="button ghost small"
|
|
||||||
onClick={() => pf.setSellConfirmId(null)}
|
|
||||||
disabled={pf.sellLoading}
|
|
||||||
>
|
|
||||||
취소
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
) : isDeleting ? (
|
|
||||||
<>
|
|
||||||
<button
|
|
||||||
className="button ghost small pf-btn-danger"
|
|
||||||
onClick={() => pf.handleDelete(item.id)}
|
|
||||||
>
|
|
||||||
확인
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="button ghost small"
|
|
||||||
onClick={() => pf.setDeleteConfirmId(null)}
|
|
||||||
>
|
|
||||||
취소
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<button
|
|
||||||
className="button ghost small pf-btn-sell"
|
|
||||||
onClick={() => {
|
|
||||||
pf.setSellConfirmId(item.id);
|
|
||||||
pf.setDeleteConfirmId(null);
|
|
||||||
}}
|
|
||||||
title="매도"
|
|
||||||
>
|
|
||||||
매도
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="button ghost small"
|
|
||||||
onClick={() => {
|
|
||||||
pf.setDeleteConfirmId(item.id);
|
|
||||||
pf.setSellConfirmId(null);
|
|
||||||
}}
|
|
||||||
title="삭제"
|
|
||||||
>
|
|
||||||
🗑️
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
{pf.portfolioLoaded && pf.portfolioHoldings.length === 0 && !pf.portfolioError && (
|
{pf.portfolioLoaded && pf.portfolioHoldings.length === 0 && !pf.portfolioError && (
|
||||||
<section className="stock-panel stock-panel--wide">
|
<section className="stock-panel stock-panel--wide">
|
||||||
|
|||||||
48
src/pages/stock/components/portfolio/BrokerSection.jsx
Normal file
48
src/pages/stock/components/portfolio/BrokerSection.jsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { formatNumber, formatPercent, profitColorClass } from '../../stockUtils';
|
||||||
|
import HoldingRow from './HoldingRow';
|
||||||
|
|
||||||
|
const BrokerSection = ({ broker, items, pf, handleSell }) => {
|
||||||
|
const bSummary = pf.getBrokerSummary(items);
|
||||||
|
const color = pf.brokerColors[broker];
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
key={broker}
|
||||||
|
className="stock-panel stock-panel--wide pf-broker-section"
|
||||||
|
style={{ borderColor: color?.border, background: color?.bg }}
|
||||||
|
>
|
||||||
|
<div className="stock-panel__head">
|
||||||
|
<div>
|
||||||
|
<p className="stock-panel__eyebrow" style={{ color: color?.border }}>
|
||||||
|
{broker}
|
||||||
|
</p>
|
||||||
|
<h3>{broker} 보유 현황</h3>
|
||||||
|
<p className="stock-panel__sub">
|
||||||
|
{items.length}종목 · 총 매입{' '}
|
||||||
|
{formatNumber(bSummary.totalBuy)} · 평가{' '}
|
||||||
|
{formatNumber(bSummary.totalEval)} · 손익{' '}
|
||||||
|
<span className={`stock-profit ${profitColorClass(bSummary.totalProfit)}`}>
|
||||||
|
{formatNumber(bSummary.totalProfit)} (
|
||||||
|
{formatPercent(bSummary.totalProfitRate)})
|
||||||
|
</span>
|
||||||
|
{(() => {
|
||||||
|
const bc = pf.cashList.find((c) => c.broker === broker);
|
||||||
|
return bc ? (
|
||||||
|
<span className="pf-cash-badge">
|
||||||
|
예수금 {formatNumber(bc.cash)}원
|
||||||
|
</span>
|
||||||
|
) : null;
|
||||||
|
})()}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="stock-holdings">
|
||||||
|
{items.map((item) => (
|
||||||
|
<HoldingRow key={item.id} item={item} pf={pf} handleSell={handleSell} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BrokerSection;
|
||||||
215
src/pages/stock/components/portfolio/HoldingRow.jsx
Normal file
215
src/pages/stock/components/portfolio/HoldingRow.jsx
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { formatNumber, formatPercent, toNumeric, profitColorClass } from '../../stockUtils';
|
||||||
|
import PriceSessionBadge from './PriceSessionBadge';
|
||||||
|
|
||||||
|
const HoldingRow = ({ item, pf, handleSell }) => {
|
||||||
|
const profitAmt = item.profit_amount;
|
||||||
|
const profitRate = item.profit_rate;
|
||||||
|
const profitAmtN = toNumeric(profitAmt);
|
||||||
|
const profitRateN = toNumeric(profitRate);
|
||||||
|
const isEditing = pf.editingId === item.id;
|
||||||
|
const isDeleting = pf.deleteConfirmId === item.id;
|
||||||
|
const isSelling = pf.sellConfirmId === item.id;
|
||||||
|
const sellPrice = item.current_price ?? item.avg_price;
|
||||||
|
const saleAmount = sellPrice != null ? sellPrice * (item.quantity ?? 0) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={item.id} className="stock-holdings__item pf-item">
|
||||||
|
{isEditing ? (
|
||||||
|
<div className="pf-edit-row">
|
||||||
|
<div className="pf-edit-fields">
|
||||||
|
<label>
|
||||||
|
수량
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min={1}
|
||||||
|
value={pf.editForm.quantity ?? ''}
|
||||||
|
onChange={(e) =>
|
||||||
|
pf.setEditForm((p) => ({
|
||||||
|
...p,
|
||||||
|
quantity: Number(e.target.value),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
평균단가
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min={0}
|
||||||
|
value={pf.editForm.avg_price ?? ''}
|
||||||
|
onChange={(e) =>
|
||||||
|
pf.setEditForm((p) => ({
|
||||||
|
...p,
|
||||||
|
avg_price: Number(e.target.value),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
매입가
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min={0}
|
||||||
|
value={pf.editForm.purchase_price ?? ''}
|
||||||
|
onChange={(e) =>
|
||||||
|
pf.setEditForm((p) => ({
|
||||||
|
...p,
|
||||||
|
purchase_price: Number(e.target.value),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="pf-edit-actions">
|
||||||
|
<button
|
||||||
|
className="button primary small"
|
||||||
|
onClick={() => pf.handleEditSave(item.id)}
|
||||||
|
disabled={pf.editLoading}
|
||||||
|
>
|
||||||
|
{pf.editLoading ? '저장 중...' : '저장'}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="button ghost small"
|
||||||
|
onClick={() => pf.setEditingId(null)}
|
||||||
|
>
|
||||||
|
취소
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<p className="stock-holdings__name">
|
||||||
|
{item.name ?? item.ticker ?? 'N/A'}
|
||||||
|
</p>
|
||||||
|
<span className="stock-holdings__code">
|
||||||
|
{item.ticker ?? ''}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="stock-holdings__metric">
|
||||||
|
<span>수량</span>
|
||||||
|
<strong>{formatNumber(item.quantity)}</strong>
|
||||||
|
</div>
|
||||||
|
<div className="stock-holdings__metric">
|
||||||
|
<span>평균단가</span>
|
||||||
|
<strong>{formatNumber(item.avg_price)}</strong>
|
||||||
|
</div>
|
||||||
|
<div className="stock-holdings__metric">
|
||||||
|
<span>매입가</span>
|
||||||
|
<strong>{formatNumber(item.purchase_price ?? item.avg_price)}</strong>
|
||||||
|
</div>
|
||||||
|
<div className="stock-holdings__metric">
|
||||||
|
<span>현재가</span>
|
||||||
|
<strong className={item.current_price == null ? 'pf-null-price' : ''}>
|
||||||
|
{item.current_price != null
|
||||||
|
? formatNumber(item.current_price)
|
||||||
|
: '조회 실패'}
|
||||||
|
<PriceSessionBadge
|
||||||
|
session={item.price_session}
|
||||||
|
asOf={item.price_as_of}
|
||||||
|
/>
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div className="stock-holdings__metric">
|
||||||
|
<span>평가금액</span>
|
||||||
|
<strong>
|
||||||
|
{item.current_price != null && item.quantity != null
|
||||||
|
? formatNumber(item.current_price * item.quantity)
|
||||||
|
: '-'}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div className="stock-holdings__metric">
|
||||||
|
<span>수익률</span>
|
||||||
|
<strong className={`stock-profit ${profitColorClass(profitRateN)}`}>
|
||||||
|
{profitRate != null ? formatPercent(profitRate) : '-'}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div className="stock-holdings__metric">
|
||||||
|
<span>평가손익</span>
|
||||||
|
<strong className={`stock-profit ${profitColorClass(profitAmtN)}`}>
|
||||||
|
{profitAmt != null ? formatNumber(profitAmt) : '-'}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div className="pf-item-actions">
|
||||||
|
{!isSelling && !isDeleting && (
|
||||||
|
<button
|
||||||
|
className="button ghost small"
|
||||||
|
onClick={() => pf.handleEditStart(item)}
|
||||||
|
title="수정"
|
||||||
|
>
|
||||||
|
✏️
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{isSelling ? (
|
||||||
|
<div className="pf-sell-confirm">
|
||||||
|
<span className="pf-sell-confirm__msg">
|
||||||
|
{item.current_price == null && (
|
||||||
|
<small className="pf-sell-confirm__warn">현재가 미조회 — 매입가 기준</small>
|
||||||
|
)}
|
||||||
|
{saleAmount != null
|
||||||
|
? `${formatNumber(saleAmount)}원 매도 후 예수금 반영`
|
||||||
|
: '매도 처리'}
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
className="button small pf-btn-sell"
|
||||||
|
onClick={() => handleSell(item)}
|
||||||
|
disabled={pf.sellLoading}
|
||||||
|
>
|
||||||
|
{pf.sellLoading ? '처리 중...' : '매도 확인'}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="button ghost small"
|
||||||
|
onClick={() => pf.setSellConfirmId(null)}
|
||||||
|
disabled={pf.sellLoading}
|
||||||
|
>
|
||||||
|
취소
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : isDeleting ? (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
className="button ghost small pf-btn-danger"
|
||||||
|
onClick={() => pf.handleDelete(item.id)}
|
||||||
|
>
|
||||||
|
확인
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="button ghost small"
|
||||||
|
onClick={() => pf.setDeleteConfirmId(null)}
|
||||||
|
>
|
||||||
|
취소
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
className="button ghost small pf-btn-sell"
|
||||||
|
onClick={() => {
|
||||||
|
pf.setSellConfirmId(item.id);
|
||||||
|
pf.setDeleteConfirmId(null);
|
||||||
|
}}
|
||||||
|
title="매도"
|
||||||
|
>
|
||||||
|
매도
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="button ghost small"
|
||||||
|
onClick={() => {
|
||||||
|
pf.setDeleteConfirmId(item.id);
|
||||||
|
pf.setSellConfirmId(null);
|
||||||
|
}}
|
||||||
|
title="삭제"
|
||||||
|
>
|
||||||
|
🗑️
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HoldingRow;
|
||||||
Reference in New Issue
Block a user