Files
frontend/src/features/instrument-details/ui/InstrumentSection.view.tsx
T
ksv741 5b30bb802a feat: add quiet reading with rare confirmations
Part of the quiet-user-feedback change; docs and specs land in their own repositories.
2026-10-06 07:01:58 +03:00

90 lines
1.8 KiB
TypeScript

import type { FC, PropsWithChildren, ReactNode } from "react";
import {
Alert,
Group,
Paper,
Skeleton,
Stack,
Text,
Title,
} from "@mantine/core";
import { LoadingSkeleton } from "@wealthledger/ui";
import { useTranslation } from "react-i18next";
import type { SectionState } from "../model/section";
import classes from "./InstrumentDetails.module.css";
const CHART_SKELETON_HEIGHT_PX = 280;
const SECTION_SKELETON_HEIGHT_PX = 65;
type InstrumentSectionProps = PropsWithChildren<{
controls?: ReactNode;
embedded?: boolean;
large?: boolean;
state: SectionState;
title: string;
}>;
const InstrumentSection: FC<InstrumentSectionProps> = (props) => {
const { t } = useTranslation();
const sectionClassName = props.embedded
? classes.embeddedSection
: classes.section;
const skeletonHeight = props.large
? CHART_SKELETON_HEIGHT_PX
: SECTION_SKELETON_HEIGHT_PX;
let sectionContent;
if (props.state.loading) {
sectionContent = (
<LoadingSkeleton
label={t("stock.loadingSection", { section: props.title })}
>
<Stack>
<Skeleton h={skeletonHeight} />
<Skeleton h={14} w="60%" />
</Stack>
</LoadingSkeleton>
);
}
else {
sectionContent = (
props.children
);
}
return (
<Paper
className={sectionClassName}
component="section"
withBorder={!props.embedded}
>
<Group justify="space-between" mb="md">
<Title order={2} size="h3">
{props.title}
</Title>
{props.controls}
</Group>
{!!props.state.partial && <Text role="status">{t("investment.partial")}</Text>}
{!!(props.state.error && !props.state.hasData) && (
<Alert aria-live="polite" color="orange" mb="sm" role="status">
<Text size="sm">{t("stock.sectionError")}</Text>
</Alert>
)}
{sectionContent}
</Paper>
);
};
export { InstrumentSection };