fix: resolve frontend audit findings
Frontend security / security (push) Successful in 10s
Frontend verify / verify (push) Successful in 4m57s
Conventional commits / commits (pull_request) Successful in 28s
Frontend security / security (pull_request) Successful in 10s
Frontend verify / verify (pull_request) Successful in 5m10s
Frontend security / security (push) Successful in 10s
Frontend verify / verify (push) Successful in 4m57s
Conventional commits / commits (pull_request) Successful in 28s
Frontend security / security (pull_request) Successful in 10s
Frontend verify / verify (pull_request) Successful in 5m10s
Repair investment recovery, draft preservation, date validation, currency presentation, accessibility, and route error recovery. Correct Docker and dependency checks and consume explicit income roles.
This commit is contained in:
Vendored
+96
-15
@@ -1124,9 +1124,41 @@ export interface components {
|
||||
instruments: components["schemas"]["IncomeInstrumentDto"][];
|
||||
entries: components["schemas"]["IncomeAnalyticsEntryDto"][];
|
||||
};
|
||||
IncomeDependencyDto: {
|
||||
dataRevision: string;
|
||||
stateVersion: string;
|
||||
unavailableReason?: string;
|
||||
coverage?: components["schemas"]["InvestmentCoverageDto"];
|
||||
resourceKey: string;
|
||||
/** @enum {string} */
|
||||
availability: "missing" | "partial" | "complete";
|
||||
/** @enum {string} */
|
||||
freshness: "unknown" | "fresh" | "stale";
|
||||
/** Format: date-time */
|
||||
lastSuccessfulAt: string | null;
|
||||
sync: components["schemas"]["InvestmentSyncDto"];
|
||||
/** @enum {string} */
|
||||
role: "selected" | "previous" | "year";
|
||||
};
|
||||
IncomeAnalyticsMetaDto: {
|
||||
dataRevision: string;
|
||||
stateVersion: string;
|
||||
unavailableReason?: string;
|
||||
coverage?: components["schemas"]["InvestmentCoverageDto"];
|
||||
resourceKey: string;
|
||||
/** @enum {string} */
|
||||
availability: "missing" | "partial" | "complete";
|
||||
/** @enum {string} */
|
||||
freshness: "unknown" | "fresh" | "stale";
|
||||
/** Format: date-time */
|
||||
lastSuccessfulAt: string | null;
|
||||
sync: components["schemas"]["InvestmentSyncDto"];
|
||||
/** @description Dependencies identified by role, not array order or resourceKey. A missing role is unavailable. */
|
||||
dependencies: components["schemas"]["IncomeDependencyDto"][];
|
||||
};
|
||||
IncomeAnalyticsResourceDto: {
|
||||
data: components["schemas"]["IncomeAnalyticsDto"] | null;
|
||||
meta: components["schemas"]["InvestmentResourceMetaDto"];
|
||||
meta: components["schemas"]["IncomeAnalyticsMetaDto"];
|
||||
};
|
||||
UpcomingEventDto: {
|
||||
account?: components["schemas"]["AccountReferenceDto"];
|
||||
@@ -1515,20 +1547,50 @@ export interface components {
|
||||
PutTbankConnectionDto: {
|
||||
token: string;
|
||||
};
|
||||
IncomeInvestmentScreenDto: {
|
||||
accountId: string;
|
||||
/**
|
||||
* @description discriminator enum property added by openapi-typescript
|
||||
* @enum {string}
|
||||
*/
|
||||
screen: "income";
|
||||
/**
|
||||
* Format: date
|
||||
* @description Inclusive start calendar date in Europe/Moscow (YYYY-MM-DD). Supply both from and to, or neither for the current Moscow month.
|
||||
*/
|
||||
from?: string;
|
||||
/**
|
||||
* Format: date
|
||||
* @description Inclusive end calendar date in Europe/Moscow (YYYY-MM-DD). Supply both from and to, or neither. Timestamp queries use the start of the following Moscow day as the exclusive end, capped at now.
|
||||
*/
|
||||
to?: string;
|
||||
};
|
||||
EventsInvestmentScreenDto: {
|
||||
accountId: string;
|
||||
/**
|
||||
* @description discriminator enum property added by openapi-typescript
|
||||
* @enum {string}
|
||||
*/
|
||||
screen: "events";
|
||||
/**
|
||||
* Format: date
|
||||
* @description Inclusive UTC calendar start date (YYYY-MM-DD). May be supplied independently; defaults to today in UTC.
|
||||
*/
|
||||
from?: string;
|
||||
/**
|
||||
* Format: date
|
||||
* @description Inclusive UTC calendar end date (YYYY-MM-DD). May be supplied independently; defaults to 30 days after from. Timestamp queries use the start of the following UTC day as the exclusive end.
|
||||
*/
|
||||
to?: string;
|
||||
};
|
||||
SyncCandleRangeDto: {
|
||||
/** Format: date-time */
|
||||
from: string;
|
||||
/** Format: date-time */
|
||||
to: string;
|
||||
};
|
||||
InvestmentScreenDto: {
|
||||
/** @enum {string} */
|
||||
screen: "accounts" | "account" | "operations" | "income" | "events" | "stocks" | "bonds" | "stock" | "bond";
|
||||
TimestampInvestmentScreenDto: {
|
||||
accountId?: string;
|
||||
/** Format: date-time */
|
||||
from?: string;
|
||||
/** Format: date-time */
|
||||
to?: string;
|
||||
/** Format: uuid */
|
||||
instrumentUid?: string;
|
||||
query?: string;
|
||||
@@ -1537,11 +1599,26 @@ export interface components {
|
||||
candleRange?: components["schemas"]["SyncCandleRangeDto"];
|
||||
categories?: ("trade" | "income" | "tax" | "fee" | "transfer" | "other")[];
|
||||
limit?: number;
|
||||
/**
|
||||
* @description discriminator enum property added by openapi-typescript
|
||||
* @enum {string}
|
||||
*/
|
||||
screen: "accounts" | "account" | "operations" | "stocks" | "bonds" | "stock" | "bond";
|
||||
/**
|
||||
* Format: date-time
|
||||
* @description Start instant for operations.
|
||||
*/
|
||||
from?: string;
|
||||
/**
|
||||
* Format: date-time
|
||||
* @description End instant for operations.
|
||||
*/
|
||||
to?: string;
|
||||
};
|
||||
TbankSyncAcceptedDto: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
scope: components["schemas"]["InvestmentScreenDto"];
|
||||
scope: components["schemas"]["IncomeInvestmentScreenDto"] | components["schemas"]["EventsInvestmentScreenDto"] | components["schemas"]["TimestampInvestmentScreenDto"];
|
||||
/** Format: date-time */
|
||||
now: string;
|
||||
};
|
||||
@@ -1553,7 +1630,7 @@ export interface components {
|
||||
TbankSyncStatusDto: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
scope: components["schemas"]["InvestmentScreenDto"] | null;
|
||||
scope: (components["schemas"]["IncomeInvestmentScreenDto"] | components["schemas"]["EventsInvestmentScreenDto"] | components["schemas"]["TimestampInvestmentScreenDto"]) | null;
|
||||
/** Format: date-time */
|
||||
now: string;
|
||||
/** @enum {string} */
|
||||
@@ -3525,7 +3602,9 @@ export interface operations {
|
||||
parameters: {
|
||||
query?: {
|
||||
sync?: "observe";
|
||||
/** @description Inclusive calendar date in Europe/Moscow. Supply both from/to or neither. */
|
||||
from?: string;
|
||||
/** @description Inclusive calendar date in Europe/Moscow, no later than today. Supply both from/to or neither. */
|
||||
to?: string;
|
||||
};
|
||||
header?: never;
|
||||
@@ -3661,7 +3740,9 @@ export interface operations {
|
||||
parameters: {
|
||||
query?: {
|
||||
sync?: "observe";
|
||||
/** @description Inclusive calendar date in Europe/Moscow. Supply both from/to or neither. */
|
||||
from?: string;
|
||||
/** @description Inclusive calendar date in Europe/Moscow, no later than today. Supply both from/to or neither. */
|
||||
to?: string;
|
||||
};
|
||||
header?: never;
|
||||
@@ -3731,9 +3812,9 @@ export interface operations {
|
||||
parameters: {
|
||||
query?: {
|
||||
sync?: "observe";
|
||||
/** @description Inclusive start date (YYYY-MM-DD). Defaults to today in UTC. */
|
||||
/** @description Inclusive UTC calendar start date (YYYY-MM-DD). May be supplied independently; defaults to today in UTC. */
|
||||
from?: string;
|
||||
/** @description Inclusive end date (YYYY-MM-DD). Defaults to 30 days after from. */
|
||||
/** @description Inclusive UTC calendar end date (YYYY-MM-DD). May be supplied independently; defaults to 30 days after from. Timestamp queries use the start of the following UTC day as the exclusive end. */
|
||||
to?: string;
|
||||
};
|
||||
header?: never;
|
||||
@@ -3801,9 +3882,9 @@ export interface operations {
|
||||
parameters: {
|
||||
query?: {
|
||||
sync?: "observe";
|
||||
/** @description Inclusive start date (YYYY-MM-DD). Defaults to today in UTC. */
|
||||
/** @description Inclusive UTC calendar start date (YYYY-MM-DD). May be supplied independently; defaults to today in UTC. */
|
||||
from?: string;
|
||||
/** @description Inclusive end date (YYYY-MM-DD). Defaults to 30 days after from. */
|
||||
/** @description Inclusive UTC calendar end date (YYYY-MM-DD). May be supplied independently; defaults to 30 days after from. Timestamp queries use the start of the following UTC day as the exclusive end. */
|
||||
to?: string;
|
||||
};
|
||||
header?: never;
|
||||
@@ -5160,7 +5241,7 @@ export interface operations {
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["InvestmentScreenDto"];
|
||||
"application/json": components["schemas"]["IncomeInvestmentScreenDto"] | components["schemas"]["EventsInvestmentScreenDto"] | components["schemas"]["TimestampInvestmentScreenDto"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
} from "@tanstack/react-query";
|
||||
import { useEffect } from "react";
|
||||
import { useAuthenticatedQuery } from "./authenticated-query";
|
||||
import { getAuthenticatedSessionSnapshot } from "./client";
|
||||
import type { components } from "./generated/schema";
|
||||
import { apiErrorCode } from "./problem-details";
|
||||
|
||||
@@ -107,8 +108,14 @@ function useResourceQuery<T extends Resource, E, K extends QueryKey>(
|
||||
}, [client, group, query.error]);
|
||||
const observe = async (expectedStateVersion?: string) => {
|
||||
const queryFn = guarded;
|
||||
if (typeof queryFn !== "function") return;
|
||||
await client.cancelQueries({ queryKey: options.queryKey, exact: true });
|
||||
if (
|
||||
!query.isEnabled ||
|
||||
!getAuthenticatedSessionSnapshot() ||
|
||||
typeof queryFn !== "function"
|
||||
)
|
||||
return;
|
||||
// Cancellation is synchronous; start the replacement in the same boundary.
|
||||
void client.cancelQueries({ queryKey: options.queryKey, exact: true });
|
||||
return client.fetchQuery({
|
||||
...options,
|
||||
staleTime: 0,
|
||||
@@ -144,7 +151,11 @@ function useResourceQuery<T extends Resource, E, K extends QueryKey>(
|
||||
},
|
||||
});
|
||||
};
|
||||
return { ...unwrapResourceResult(query), observe };
|
||||
return {
|
||||
...unwrapResourceResult(query),
|
||||
queryKey: options.queryKey,
|
||||
observe,
|
||||
};
|
||||
}
|
||||
|
||||
export { invalidateResourceAccess, unwrapResourceResult, useResourceQuery };
|
||||
|
||||
@@ -2668,6 +2668,7 @@
|
||||
"name": "from",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Inclusive calendar date in Europe/Moscow. Supply both from/to or neither.",
|
||||
"schema": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
@@ -2677,6 +2678,7 @@
|
||||
"name": "to",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Inclusive calendar date in Europe/Moscow, no later than today. Supply both from/to or neither.",
|
||||
"schema": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
@@ -2878,6 +2880,7 @@
|
||||
"name": "from",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Inclusive calendar date in Europe/Moscow. Supply both from/to or neither.",
|
||||
"schema": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
@@ -2887,6 +2890,7 @@
|
||||
"name": "to",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Inclusive calendar date in Europe/Moscow, no later than today. Supply both from/to or neither.",
|
||||
"schema": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
@@ -2984,7 +2988,7 @@
|
||||
"name": "from",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Inclusive start date (YYYY-MM-DD). Defaults to today in UTC.",
|
||||
"description": "Inclusive UTC calendar start date (YYYY-MM-DD). May be supplied independently; defaults to today in UTC.",
|
||||
"schema": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
@@ -2994,7 +2998,7 @@
|
||||
"name": "to",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Inclusive end date (YYYY-MM-DD). Defaults to 30 days after from.",
|
||||
"description": "Inclusive UTC calendar end date (YYYY-MM-DD). May be supplied independently; defaults to 30 days after from. Timestamp queries use the start of the following UTC day as the exclusive end.",
|
||||
"schema": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
@@ -3100,7 +3104,7 @@
|
||||
"name": "from",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Inclusive start date (YYYY-MM-DD). Defaults to today in UTC.",
|
||||
"description": "Inclusive UTC calendar start date (YYYY-MM-DD). May be supplied independently; defaults to today in UTC.",
|
||||
"schema": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
@@ -3110,7 +3114,7 @@
|
||||
"name": "to",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Inclusive end date (YYYY-MM-DD). Defaults to 30 days after from.",
|
||||
"description": "Inclusive UTC calendar end date (YYYY-MM-DD). May be supplied independently; defaults to 30 days after from. Timestamp queries use the start of the following UTC day as the exclusive end.",
|
||||
"schema": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
@@ -5001,7 +5005,31 @@
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/InvestmentScreenDto"
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/IncomeInvestmentScreenDto"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/EventsInvestmentScreenDto"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/TimestampInvestmentScreenDto"
|
||||
}
|
||||
],
|
||||
"discriminator": {
|
||||
"propertyName": "screen",
|
||||
"mapping": {
|
||||
"income": "#/components/schemas/IncomeInvestmentScreenDto",
|
||||
"events": "#/components/schemas/EventsInvestmentScreenDto",
|
||||
"accounts": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"account": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"operations": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"stocks": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"bonds": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"stock": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"bond": "#/components/schemas/TimestampInvestmentScreenDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6878,6 +6906,129 @@
|
||||
"entries"
|
||||
]
|
||||
},
|
||||
"IncomeDependencyDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dataRevision": {
|
||||
"type": "string"
|
||||
},
|
||||
"stateVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"unavailableReason": {
|
||||
"type": "string"
|
||||
},
|
||||
"coverage": {
|
||||
"$ref": "#/components/schemas/InvestmentCoverageDto"
|
||||
},
|
||||
"resourceKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"availability": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"missing",
|
||||
"partial",
|
||||
"complete"
|
||||
]
|
||||
},
|
||||
"freshness": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"unknown",
|
||||
"fresh",
|
||||
"stale"
|
||||
]
|
||||
},
|
||||
"lastSuccessfulAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"sync": {
|
||||
"$ref": "#/components/schemas/InvestmentSyncDto"
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"selected",
|
||||
"previous",
|
||||
"year"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dataRevision",
|
||||
"stateVersion",
|
||||
"resourceKey",
|
||||
"availability",
|
||||
"freshness",
|
||||
"lastSuccessfulAt",
|
||||
"sync",
|
||||
"role"
|
||||
]
|
||||
},
|
||||
"IncomeAnalyticsMetaDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dataRevision": {
|
||||
"type": "string"
|
||||
},
|
||||
"stateVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"unavailableReason": {
|
||||
"type": "string"
|
||||
},
|
||||
"coverage": {
|
||||
"$ref": "#/components/schemas/InvestmentCoverageDto"
|
||||
},
|
||||
"resourceKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"availability": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"missing",
|
||||
"partial",
|
||||
"complete"
|
||||
]
|
||||
},
|
||||
"freshness": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"unknown",
|
||||
"fresh",
|
||||
"stale"
|
||||
]
|
||||
},
|
||||
"lastSuccessfulAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"sync": {
|
||||
"$ref": "#/components/schemas/InvestmentSyncDto"
|
||||
},
|
||||
"dependencies": {
|
||||
"description": "Dependencies identified by role, not array order or resourceKey. A missing role is unavailable.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/IncomeDependencyDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dataRevision",
|
||||
"stateVersion",
|
||||
"resourceKey",
|
||||
"availability",
|
||||
"freshness",
|
||||
"lastSuccessfulAt",
|
||||
"sync",
|
||||
"dependencies"
|
||||
]
|
||||
},
|
||||
"IncomeAnalyticsResourceDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6891,7 +7042,7 @@
|
||||
]
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/components/schemas/InvestmentResourceMetaDto"
|
||||
"$ref": "#/components/schemas/IncomeAnalyticsMetaDto"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -8677,6 +8828,62 @@
|
||||
"token"
|
||||
]
|
||||
},
|
||||
"IncomeInvestmentScreenDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountId": {
|
||||
"type": "string"
|
||||
},
|
||||
"screen": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"income"
|
||||
]
|
||||
},
|
||||
"from": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Inclusive start calendar date in Europe/Moscow (YYYY-MM-DD). Supply both from and to, or neither for the current Moscow month."
|
||||
},
|
||||
"to": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Inclusive end calendar date in Europe/Moscow (YYYY-MM-DD). Supply both from and to, or neither. Timestamp queries use the start of the following Moscow day as the exclusive end, capped at now."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"accountId",
|
||||
"screen"
|
||||
]
|
||||
},
|
||||
"EventsInvestmentScreenDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accountId": {
|
||||
"type": "string"
|
||||
},
|
||||
"screen": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"events"
|
||||
]
|
||||
},
|
||||
"from": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Inclusive UTC calendar start date (YYYY-MM-DD). May be supplied independently; defaults to today in UTC."
|
||||
},
|
||||
"to": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Inclusive UTC calendar end date (YYYY-MM-DD). May be supplied independently; defaults to 30 days after from. Timestamp queries use the start of the following UTC day as the exclusive end."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"accountId",
|
||||
"screen"
|
||||
]
|
||||
},
|
||||
"SyncCandleRangeDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -8694,34 +8901,12 @@
|
||||
"to"
|
||||
]
|
||||
},
|
||||
"InvestmentScreenDto": {
|
||||
"TimestampInvestmentScreenDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"screen": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"accounts",
|
||||
"account",
|
||||
"operations",
|
||||
"income",
|
||||
"events",
|
||||
"stocks",
|
||||
"bonds",
|
||||
"stock",
|
||||
"bond"
|
||||
]
|
||||
},
|
||||
"accountId": {
|
||||
"type": "string"
|
||||
},
|
||||
"from": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"to": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"instrumentUid": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
@@ -8759,6 +8944,28 @@
|
||||
"type": "number",
|
||||
"minimum": 1,
|
||||
"maximum": 1000
|
||||
},
|
||||
"screen": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"accounts",
|
||||
"account",
|
||||
"operations",
|
||||
"stocks",
|
||||
"bonds",
|
||||
"stock",
|
||||
"bond"
|
||||
]
|
||||
},
|
||||
"from": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Start instant for operations."
|
||||
},
|
||||
"to": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "End instant for operations."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -8773,7 +8980,31 @@
|
||||
"format": "uuid"
|
||||
},
|
||||
"scope": {
|
||||
"$ref": "#/components/schemas/InvestmentScreenDto"
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/IncomeInvestmentScreenDto"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/EventsInvestmentScreenDto"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/TimestampInvestmentScreenDto"
|
||||
}
|
||||
],
|
||||
"discriminator": {
|
||||
"propertyName": "screen",
|
||||
"mapping": {
|
||||
"income": "#/components/schemas/IncomeInvestmentScreenDto",
|
||||
"events": "#/components/schemas/EventsInvestmentScreenDto",
|
||||
"accounts": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"account": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"operations": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"stocks": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"bonds": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"stock": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"bond": "#/components/schemas/TimestampInvestmentScreenDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"now": {
|
||||
"type": "string",
|
||||
@@ -8813,13 +9044,32 @@
|
||||
"format": "uuid"
|
||||
},
|
||||
"scope": {
|
||||
"nullable": true,
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/InvestmentScreenDto"
|
||||
"$ref": "#/components/schemas/IncomeInvestmentScreenDto"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/EventsInvestmentScreenDto"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/TimestampInvestmentScreenDto"
|
||||
}
|
||||
]
|
||||
],
|
||||
"discriminator": {
|
||||
"propertyName": "screen",
|
||||
"mapping": {
|
||||
"income": "#/components/schemas/IncomeInvestmentScreenDto",
|
||||
"events": "#/components/schemas/EventsInvestmentScreenDto",
|
||||
"accounts": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"account": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"operations": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"stocks": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"bonds": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"stock": "#/components/schemas/TimestampInvestmentScreenDto",
|
||||
"bond": "#/components/schemas/TimestampInvestmentScreenDto"
|
||||
}
|
||||
},
|
||||
"nullable": true
|
||||
},
|
||||
"now": {
|
||||
"type": "string",
|
||||
|
||||
@@ -269,6 +269,7 @@ const ru = {
|
||||
},
|
||||
},
|
||||
stock: {
|
||||
currencyUnknown: "валюта неизвестна",
|
||||
searchTitle: "Акции",
|
||||
searchSubtitle:
|
||||
"Найдите компанию, изучите цену и дивиденды, посмотрите свою историю владения.",
|
||||
@@ -636,6 +637,7 @@ const ru = {
|
||||
comparisonPending: "Период сравнения ещё не загружен полностью.",
|
||||
comparisonFailed:
|
||||
"Не удалось загрузить период сравнения. Повторите обновление.",
|
||||
previousUnavailable: "Сравнение с предыдущим периодом недоступно.",
|
||||
yearUnavailable: "Сравнение с годом ранее недоступно.",
|
||||
difference: "Разница",
|
||||
total: "Итого",
|
||||
@@ -659,6 +661,10 @@ const ru = {
|
||||
},
|
||||
settings: { title: "Настройки" },
|
||||
tbank: {
|
||||
close: "Закрыть",
|
||||
refreshError:
|
||||
"Не удалось обновить статус подключения. Показаны последние полученные данные.",
|
||||
refreshing: "Обновляем статус подключения…",
|
||||
title: "T-Bank Invest",
|
||||
disconnected: "Не подключено",
|
||||
connected: "Подключено с {{date}}",
|
||||
@@ -683,6 +689,7 @@ const ru = {
|
||||
title: "Не удалось открыть страницу",
|
||||
text: "Перейдите в безопасный раздел и попробуйте снова.",
|
||||
action: "Продолжить",
|
||||
reload: "Перезагрузить страницу",
|
||||
},
|
||||
states: {
|
||||
loadingTitle: "Загрузка",
|
||||
|
||||
@@ -177,6 +177,33 @@ const meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
export const Colors: Story = { name: "Цвета", render: () => <ColorsView /> };
|
||||
export const SecondaryText: Story = {
|
||||
name: "Вторичный текст",
|
||||
render: () => (
|
||||
<SimpleGrid cols={{ base: 1, sm: 2 }}>
|
||||
{[
|
||||
"var(--wl-color-surface)",
|
||||
"var(--wl-color-canvas)",
|
||||
"var(--wl-color-subtle)",
|
||||
...Object.keys(designTokens.color.palettes)
|
||||
.filter((palette) => palette !== "dark")
|
||||
.flatMap((palette) => [
|
||||
`var(--mantine-color-${palette}-0)`,
|
||||
`color-mix(in srgb, var(--mantine-color-${palette}-0) 45%, var(--wl-color-surface))`,
|
||||
]),
|
||||
].map((background) => (
|
||||
<Paper key={background} p="md" withBorder style={{ background }}>
|
||||
<Text size="sm" c="dimmed">
|
||||
22.09.2026 · Синтетические данные
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed">
|
||||
Не удалось обновить данные. Сохранён предыдущий результат.
|
||||
</Text>
|
||||
</Paper>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
),
|
||||
};
|
||||
export const Typography: Story = {
|
||||
name: "Типографика",
|
||||
render: () => <TypographyView />,
|
||||
|
||||
@@ -9,16 +9,21 @@ function luminance(color: string) {
|
||||
);
|
||||
return channels[0] * 0.2126 + channels[1] * 0.7152 + channels[2] * 0.0722;
|
||||
}
|
||||
describe("financial text contrast", () => {
|
||||
it.each(["positive", "negative"] as const)(
|
||||
"keeps %s readable on journal, position and tinted card surfaces",
|
||||
describe("semantic text contrast", () => {
|
||||
it.each(["positive", "negative", "muted"] as const)(
|
||||
"keeps %s readable on canvas, white, subtle and tinted surfaces",
|
||||
(tone) => {
|
||||
const role = tokens.color.roles[tone];
|
||||
const palettes = tokens.color.palettes;
|
||||
const foreground =
|
||||
palettes[role.color as keyof typeof palettes][role.shade];
|
||||
const surfaces = [
|
||||
"#ffffff",
|
||||
palettes.gray[0],
|
||||
palettes.gray[2],
|
||||
...Object.entries(palettes)
|
||||
.filter(([name]) => name !== "dark")
|
||||
.map(([, palette]) => palette[0]),
|
||||
...Object.entries(palettes)
|
||||
.filter(([name]) => name !== "dark")
|
||||
.map(
|
||||
|
||||
Reference in New Issue
Block a user