115 lines
3.5 KiB
TypeScript
115 lines
3.5 KiB
TypeScript
import React, { useMemo, useState } from 'react';
|
|
import { useTradeNotification } from '../../contexts/TradeNotificationContext';
|
|
import { useNavigation } from '../../contexts/NavigationContext';
|
|
import { useAuth } from '../../contexts/AuthContext';
|
|
import { useVirtualTradingCore } from '@frontend/hooks/useVirtualTradingCore';
|
|
import NotificationListRow from './NotificationListRow';
|
|
import NotificationDetailScreen from './NotificationDetailScreen';
|
|
import VirtualTradeScreen from '../virtual/VirtualTradeScreen';
|
|
|
|
export default function NotificationsScreen() {
|
|
const {
|
|
notifyNav,
|
|
goNotifyList,
|
|
goNotifyDetail,
|
|
goNotifyTrade,
|
|
goVirtualDetail,
|
|
} = useNavigation();
|
|
const { sessionKey } = useAuth();
|
|
const {
|
|
allNotifications,
|
|
unreadCount,
|
|
markAsRead,
|
|
markAllAsRead,
|
|
deleteNotification,
|
|
deleteAllNotifications,
|
|
refreshHistory,
|
|
} = useTradeNotification();
|
|
const { summary, refreshPaperData } = useVirtualTradingCore({ settingsSessionKey: sessionKey });
|
|
|
|
const [refreshing, setRefreshing] = useState(false);
|
|
|
|
const selectedItem = useMemo(
|
|
() => allNotifications.find(n => n.id === notifyNav.notifyId) ?? null,
|
|
[allNotifications, notifyNav.notifyId],
|
|
);
|
|
|
|
const onRefresh = async () => {
|
|
setRefreshing(true);
|
|
await refreshHistory();
|
|
setRefreshing(false);
|
|
};
|
|
|
|
if (notifyNav.view === 'detail' && selectedItem) {
|
|
return (
|
|
<NotificationDetailScreen
|
|
item={selectedItem}
|
|
onBack={() => {
|
|
markAsRead(selectedItem.id);
|
|
goNotifyList();
|
|
}}
|
|
onTrade={side => goNotifyTrade(selectedItem.market, side)}
|
|
onGoVirtual={() => {
|
|
markAsRead(selectedItem.id);
|
|
goVirtualDetail(selectedItem.market);
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
|
|
if (notifyNav.view === 'trade' && notifyNav.market && notifyNav.tradeSide) {
|
|
return (
|
|
<VirtualTradeScreen
|
|
market={notifyNav.market}
|
|
side={notifyNav.tradeSide}
|
|
summary={summary}
|
|
onBack={goNotifyList}
|
|
onOrderDone={refreshPaperData}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="screen">
|
|
<header className="screen-header">
|
|
<h1 className="screen-title">알림 {unreadCount > 0 && `(${unreadCount})`}</h1>
|
|
<div style={{ display: 'flex', gap: 8 }}>
|
|
<button type="button" className="chip" onClick={() => void onRefresh()}>{refreshing ? '…' : '↻'}</button>
|
|
<button type="button" className="chip" onClick={markAllAsRead}>읽음</button>
|
|
</div>
|
|
</header>
|
|
|
|
{allNotifications.length === 0 ? (
|
|
<div className="empty-state">
|
|
<h3>알림 없음</h3>
|
|
<p>전략 조건 충족 시 알림이 표시됩니다</p>
|
|
</div>
|
|
) : (
|
|
<div className="stack-list" style={{ padding: '0 16px' }}>
|
|
{allNotifications.map(item => (
|
|
<NotificationListRow
|
|
key={item.id}
|
|
item={item}
|
|
onDetail={() => {
|
|
markAsRead(item.id);
|
|
goNotifyDetail(item.id, item.market);
|
|
}}
|
|
onTrade={side => {
|
|
markAsRead(item.id);
|
|
goNotifyTrade(item.market, side);
|
|
}}
|
|
onDelete={() => void deleteNotification(item.id)}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
{allNotifications.length > 0 && (
|
|
<div style={{ padding: 16, textAlign: 'center' }}>
|
|
<button type="button" className="btn-danger" onClick={() => void deleteAllNotifications()}>전체 삭제</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|