Part of the quiet-user-feedback change; docs and specs land in their own repositories.
105 lines
2.6 KiB
TypeScript
105 lines
2.6 KiB
TypeScript
import type { FC } from "react";
|
||
|
||
import { Alert, Group, Stack, Text } from "@mantine/core";
|
||
import { useTranslation } from "react-i18next";
|
||
|
||
import {
|
||
InstrumentMetric,
|
||
InstrumentMetrics,
|
||
InstrumentSection as StockSection,
|
||
} from "@/features/instrument-details";
|
||
|
||
import type { StockPageVm } from "../StockPage.vm";
|
||
|
||
const compactMetricFormatter = new Intl.NumberFormat("ru-RU", {
|
||
maximumFractionDigits: 2,
|
||
notation: "compact",
|
||
});
|
||
|
||
const metricFormatter = new Intl.NumberFormat("ru-RU", {
|
||
maximumFractionDigits: 2,
|
||
notation: "standard",
|
||
});
|
||
|
||
type StockCompanyProps = Pick<StockPageVm, "company" | "companyState"> & {
|
||
stock: NonNullable<StockPageVm["stock"]>;
|
||
};
|
||
|
||
const StockCompany: FC<StockCompanyProps> = (props) => {
|
||
const { stock } = props;
|
||
const { t } = useTranslation();
|
||
let companyMetricsContent;
|
||
|
||
if (props.company) {
|
||
if (props.company.metrics.length > 0) {
|
||
companyMetricsContent = (
|
||
<InstrumentMetrics>
|
||
{props.company.metrics.map((metric) => {
|
||
const label = [t(`stock.metrics.${metric.key}`), metric.period].filter(Boolean).join(" · ");
|
||
const formatter = metric.unit === "money" ? compactMetricFormatter : metricFormatter;
|
||
const value = `${formatter.format(metric.value)} ${metricUnit(metric, t("stock.currencyUnknown"))}`;
|
||
|
||
return (
|
||
<InstrumentMetric key={metric.key} label={label} value={value} />
|
||
);
|
||
})}
|
||
</InstrumentMetrics>
|
||
);
|
||
}
|
||
else {
|
||
companyMetricsContent = <Text c="dimmed">{t("stock.noFundamentals")}</Text>;
|
||
}
|
||
}
|
||
|
||
return (
|
||
<StockSection
|
||
embedded
|
||
state={props.companyState}
|
||
title={t("stock.company")}
|
||
>
|
||
<Group gap="xl" mb="md">
|
||
{!!stock.sector && (
|
||
<Text size="sm">
|
||
{t("stock.sector")}:{" "}
|
||
{t(`stock.sectors.${stock.sector}`, {
|
||
defaultValue: stock.sector,
|
||
})}
|
||
</Text>
|
||
)}
|
||
|
||
{stock.lot !== null && <Text size="sm">{t("stock.lot", { value: stock.lot })}</Text>}
|
||
</Group>
|
||
|
||
{!!props.company && (
|
||
<Stack gap="lg">
|
||
{props.company.unavailable.length > 0 && (
|
||
<Alert aria-live="polite" color="orange" role="status">
|
||
<Text size="sm">{t("stock.partialCompany")}</Text>
|
||
</Alert>
|
||
)}
|
||
|
||
{companyMetricsContent}
|
||
|
||
<Text c="dimmed" size="xs">
|
||
{t("stock.periodNote")}
|
||
</Text>
|
||
</Stack>
|
||
)}
|
||
</StockSection>
|
||
);
|
||
};
|
||
|
||
function metricUnit(
|
||
metric: NonNullable<StockPageVm["company"]>["metrics"][number],
|
||
unknownCurrency: string,
|
||
) {
|
||
if (metric.unit === "money")
|
||
return metric.currency === "RUB"
|
||
? "₽"
|
||
: (metric.currency ?? unknownCurrency);
|
||
|
||
return metric.unit === "percent" ? "%" : "×";
|
||
}
|
||
|
||
export { StockCompany };
|