finsignal-feed-explore 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/NewsFeed.d.ts +3 -1
- package/dist/NewsFeed.js +69 -12
- package/package.json +1 -1
package/dist/NewsFeed.d.ts
CHANGED
|
@@ -41,5 +41,7 @@ export interface FeedListProps {
|
|
|
41
41
|
items?: FeedItem[];
|
|
42
42
|
onItemClick?: (item: FeedItem) => void;
|
|
43
43
|
className?: string;
|
|
44
|
+
feedApiUrl?: string;
|
|
45
|
+
useMockData?: boolean;
|
|
44
46
|
}
|
|
45
|
-
export declare function FeedList({ feedType, items, onItemClick, className }: FeedListProps): import("react/jsx-runtime").JSX.Element;
|
|
47
|
+
export declare function FeedList({ feedType, items: itemsProp, onItemClick, className, feedApiUrl, useMockData }: FeedListProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/NewsFeed.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import * as React from 'react';
|
|
2
12
|
import { NewsSnippet } from './snippets/NewsSnippet';
|
|
3
13
|
import './newsfeed.css';
|
|
4
14
|
// Моковые данные в формате FinSignal Feed
|
|
@@ -178,7 +188,41 @@ function formatTimeAgo(dateString) {
|
|
|
178
188
|
return `${Math.floor(diff / 3600)} ч назад`;
|
|
179
189
|
return `${Math.floor(diff / 86400)} дн назад`;
|
|
180
190
|
}
|
|
181
|
-
export function FeedList({ feedType = 'trending', items
|
|
191
|
+
export function FeedList({ feedType = 'trending', items: itemsProp, onItemClick, className = '', feedApiUrl = 'https://explore-gateway.changesandbox.ru', useMockData = false }) {
|
|
192
|
+
const [items, setItems] = React.useState(itemsProp || mockFeedItems);
|
|
193
|
+
const [loading, setLoading] = React.useState(false);
|
|
194
|
+
const [error, setError] = React.useState(null);
|
|
195
|
+
// Загрузка новостей с API
|
|
196
|
+
React.useEffect(() => {
|
|
197
|
+
if (useMockData || itemsProp) {
|
|
198
|
+
setItems(itemsProp || mockFeedItems);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const fetchNews = () => __awaiter(this, void 0, void 0, function* () {
|
|
202
|
+
setLoading(true);
|
|
203
|
+
setError(null);
|
|
204
|
+
try {
|
|
205
|
+
const response = yield fetch(`${feedApiUrl}/api/feed/${feedType}`);
|
|
206
|
+
if (!response.ok) {
|
|
207
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
208
|
+
}
|
|
209
|
+
const data = yield response.json();
|
|
210
|
+
// Преобразуем данные из API в формат FeedItem
|
|
211
|
+
const newsItems = data.items || data;
|
|
212
|
+
setItems(newsItems);
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
console.error('Error fetching news:', err);
|
|
216
|
+
setError(err instanceof Error ? err.message : 'Failed to fetch news');
|
|
217
|
+
// Fallback на моки при ошибке
|
|
218
|
+
setItems(mockFeedItems);
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
setLoading(false);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
fetchNews();
|
|
225
|
+
}, [feedApiUrl, feedType, useMockData, itemsProp]);
|
|
182
226
|
const getTypeLabel = (type) => {
|
|
183
227
|
const labels = {
|
|
184
228
|
signal: 'Сигнал',
|
|
@@ -203,15 +247,28 @@ export function FeedList({ feedType = 'trending', items = mockFeedItems, onItemC
|
|
|
203
247
|
};
|
|
204
248
|
return colors[type] || colors.post;
|
|
205
249
|
};
|
|
206
|
-
return (
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
250
|
+
return (_jsxs("div", { className: `feed-list ${className}`, children: [loading && (_jsx("div", { style: {
|
|
251
|
+
textAlign: 'center',
|
|
252
|
+
padding: '20px',
|
|
253
|
+
color: '#6b7280',
|
|
254
|
+
fontSize: '14px'
|
|
255
|
+
}, children: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u043D\u043E\u0432\u043E\u0441\u0442\u0435\u0439..." })), error && !loading && (_jsxs("div", { style: {
|
|
256
|
+
padding: '16px',
|
|
257
|
+
backgroundColor: '#fef2f2',
|
|
258
|
+
border: '1px solid #fecaca',
|
|
259
|
+
borderRadius: '8px',
|
|
260
|
+
color: '#991b1b',
|
|
261
|
+
fontSize: '14px',
|
|
262
|
+
marginBottom: '12px'
|
|
263
|
+
}, children: ["\u041E\u0448\u0438\u0431\u043A\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438: ", error, ". \u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0442\u0435\u0441\u0442\u043E\u0432\u044B\u0435 \u043D\u043E\u0432\u043E\u0441\u0442\u0438."] })), !loading && items.map((item) => {
|
|
264
|
+
var _a, _b, _c, _d;
|
|
265
|
+
// Рендерим news items через NewsSnippet
|
|
266
|
+
if (item.type === 'news' && item.title && item.body) {
|
|
267
|
+
return (_jsx(NewsSnippet, { id: item.content_id, title: item.title, content: item.body, recommendation: (_a = item.metadata.news) === null || _a === void 0 ? void 0 : _a.recommendation, stocks: (_b = item.metadata.news) === null || _b === void 0 ? void 0 : _b.stocks, onPress: () => onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item), draggable: true, onDragStart: () => {
|
|
268
|
+
console.log('Dragging news:', item.title);
|
|
269
|
+
} }, item.content_id));
|
|
270
|
+
}
|
|
271
|
+
// Для остальных типов оставляем обычный рендеринг
|
|
272
|
+
return (_jsxs("div", { className: "feed-item", onClick: () => onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item), children: [_jsxs("div", { className: "feed-item-header", children: [_jsx("span", { className: "feed-type-badge", style: { backgroundColor: getTypeColor(item.type) }, children: getTypeLabel(item.type) }), _jsx("span", { className: "feed-time", children: formatTimeAgo(item.created_at) })] }), item.title && _jsx("h3", { className: "feed-title", children: item.title }), item.body && _jsx("p", { className: "feed-body", children: item.body }), item.metadata.signal && (_jsxs("div", { className: "feed-signal-metrics", children: [_jsxs("div", { className: "signal-stock", children: [_jsx("span", { className: "signal-symbol", children: item.metadata.signal.symbol }), _jsx("span", { className: "signal-company", children: item.metadata.signal.companyName })] }), _jsxs("div", { className: "signal-prices", children: [_jsxs("div", { className: "signal-price-item", children: [_jsx("span", { className: "label", children: "Entry:" }), _jsx("span", { className: "value", children: item.metadata.signal.metrics.entry })] }), _jsxs("div", { className: "signal-price-item", children: [_jsx("span", { className: "label", children: "TP:" }), _jsx("span", { className: "value green", children: item.metadata.signal.metrics.takeProfit })] }), _jsxs("div", { className: "signal-price-item", children: [_jsx("span", { className: "label", children: "SL:" }), _jsx("span", { className: "value red", children: item.metadata.signal.metrics.stopLoss })] })] })] })), ((_c = item.metadata.news) === null || _c === void 0 ? void 0 : _c.stocks) && (_jsx("div", { className: "feed-stocks", children: item.metadata.news.stocks.map((stock, idx) => (_jsxs("div", { className: "stock-card", children: [_jsx("span", { className: "stock-symbol", children: stock.symbol }), _jsx("span", { className: "stock-price", children: stock.price }), _jsx("span", { className: `stock-change ${stock.changeType}`, children: stock.change })] }, idx))) })), ((_d = item.metadata.ai_categorization) === null || _d === void 0 ? void 0 : _d.tags) && (_jsx("div", { className: "feed-tags", children: item.metadata.ai_categorization.tags.map((tag, idx) => (_jsxs("span", { className: "feed-tag", children: ["#", tag] }, idx))) }))] }, item.content_id));
|
|
273
|
+
})] }));
|
|
217
274
|
}
|