Files
frontend/src/features/instrument-details/ui/InstrumentSection.view.tsx
T

83 lines
1.9 KiB
TypeScript

import {
Alert,
Button,
Group,
Paper,
Skeleton,
Stack,
Text,
Title,
} from "@mantine/core";
import type { FC, PropsWithChildren, ReactNode } from "react";
import { useTranslation } from "react-i18next";
import { LoadingSkeleton } from "@/shared/ui";
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<{
title: string;
state: SectionState;
controls?: ReactNode;
large?: boolean;
embedded?: boolean;
}>;
const InstrumentSection: FC<InstrumentSectionProps> = (props) => {
const { t } = useTranslation();
return (
<Paper
component="section"
className={props.embedded ? classes.embeddedSection : classes.section}
withBorder={!props.embedded}
>
<Group justify="space-between" mb="md">
<Title order={2} size="h3">
{props.title}
</Title>
{props.controls}
</Group>
{props.state.refreshing ? (
<Text role="status" size="xs" c="dimmed">
{t("accounts.refreshing")}
</Text>
) : null}
{props.state.error ? (
<Alert color="orange" mb="sm" role="alert">
<Group justify="space-between">
<Text size="sm">
{props.state.hasData
? t("accounts.refreshError")
: t("stock.sectionError")}
</Text>
<Button size="xs" variant="default" onClick={props.state.retry}>
{t("accounts.retry")}
</Button>
</Group>
</Alert>
) : null}
{props.state.loading ? (
<LoadingSkeleton
label={t("stock.loadingSection", { section: props.title })}
>
<Stack>
<Skeleton
h={
props.large
? CHART_SKELETON_HEIGHT_PX
: SECTION_SKELETON_HEIGHT_PX
}
/>
<Skeleton h={14} w="60%" />
</Stack>
</LoadingSkeleton>
) : (
props.children
)}
</Paper>
);
};
export { InstrumentSection };