134 lines
4.0 KiB
TypeScript
134 lines
4.0 KiB
TypeScript
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
import { MemoryRouter } from "react-router";
|
|
import type { BrokerageEvent } from "@/entities/brokerage-event";
|
|
import { RecentEvents } from "./RecentEvents.view";
|
|
|
|
const syntheticEvent = {
|
|
type: "coupon",
|
|
date: "2026-10-15",
|
|
dateKind: "event",
|
|
figi: null,
|
|
instrumentUid: null,
|
|
ticker: "DEMO",
|
|
displayName: "Учебные облигации",
|
|
projectedAmount: { currency: "RUB", value: "850.50" },
|
|
} satisfies BrokerageEvent;
|
|
|
|
const eventsPath = "/accounts/storybook-account/events";
|
|
|
|
const meta = {
|
|
title: "Product/RecentEvents",
|
|
component: RecentEvents,
|
|
tags: ["autodocs"],
|
|
argTypes: {
|
|
events: { control: false },
|
|
},
|
|
decorators: [
|
|
(Story) => (
|
|
<MemoryRouter initialEntries={["/accounts/storybook-account"]}>
|
|
<Story />
|
|
</MemoryRouter>
|
|
),
|
|
],
|
|
parameters: {
|
|
docs: {
|
|
description: {
|
|
component:
|
|
"Раздел ближайших событий на странице счёта WealthLedger. Раздел самостоятельно отображает загрузку, ошибку, отсутствие событий и полученные данные. Все события и суммы вымышлены. Ссылка на календарь меняет только локальный маршрут MemoryRouter; сам календарь в этой истории не отображается.",
|
|
},
|
|
},
|
|
},
|
|
args: {
|
|
events: {
|
|
state: "loaded",
|
|
to: eventsPath,
|
|
items: [
|
|
syntheticEvent,
|
|
{
|
|
...syntheticEvent,
|
|
type: "dividend",
|
|
date: "2026-11-01",
|
|
dateKind: "registry",
|
|
ticker: "EXAMPLE",
|
|
displayName: "Учебные технологии",
|
|
projectedAmount: { currency: "RUB", value: "1200" },
|
|
},
|
|
],
|
|
},
|
|
},
|
|
} satisfies Meta<typeof RecentEvents>;
|
|
|
|
export default meta;
|
|
|
|
type Story = StoryObj<typeof meta>;
|
|
|
|
export const Loaded: Story = {
|
|
name: "События получены",
|
|
parameters: {
|
|
docs: {
|
|
description: {
|
|
story:
|
|
"Предстоящие купоны и дивиденды показываются с ожидаемой суммой. Это прогноз событий, а не подтверждение получения дохода.",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
export const Loading: Story = {
|
|
name: "Загрузка раздела",
|
|
args: { events: { state: "loading", to: eventsPath } },
|
|
parameters: {
|
|
docs: {
|
|
description: {
|
|
story:
|
|
"Локальный skeleton занимает место строк событий и имеет доступное обозначение загрузки. Остальные разделы страницы могут оставаться доступными.",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
export const Failed: Story = {
|
|
name: "Ошибка получения событий",
|
|
args: { events: { state: "error", to: eventsPath } },
|
|
parameters: {
|
|
docs: {
|
|
description: {
|
|
story:
|
|
"Ошибка ограничена разделом событий. Сохраняется переход к полному календарю; недоступные события не выдаются за пустой список.",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
export const Empty: Story = {
|
|
name: "Нет ближайших событий",
|
|
args: { events: { state: "empty", to: eventsPath } },
|
|
parameters: {
|
|
docs: {
|
|
description: {
|
|
story:
|
|
"Успешно полученный пустой результат объясняется отдельным сообщением и сохраняет переход к календарю.",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
export const MissingAmount: Story = {
|
|
name: "Событие без ожидаемой суммы",
|
|
args: {
|
|
events: {
|
|
state: "loaded",
|
|
to: eventsPath,
|
|
items: [{ ...syntheticEvent, projectedAmount: null }],
|
|
},
|
|
},
|
|
parameters: {
|
|
docs: {
|
|
description: {
|
|
story:
|
|
"Событие остаётся видимым при неизвестной ожидаемой сумме. Отсутствие оценки не подменяется нулевой выплатой.",
|
|
},
|
|
},
|
|
},
|
|
};
|