53 lines
1.4 KiB
TypeScript
53 lines
1.4 KiB
TypeScript
import type { FC } from "react";
|
|
|
|
import { Text } from "@mantine/core";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
import type { InvestmentResourceMeta } from "@/shared/api";
|
|
|
|
import { formatSnapshotTime } from "@/shared/lib";
|
|
|
|
// Owns the "when did the source last answer" line and the two notices that
|
|
// always travel with it. Surfaces keep their own busy indicator: a list card
|
|
// shows a muted line, a page header a progress bar — that is a product call.
|
|
type SourceSyncStatusProps = {
|
|
errorText?: null | string;
|
|
lastAttempt?: InvestmentResourceMeta["lastAttempt"];
|
|
lastSuccessfulAt?: null | string;
|
|
stale?: boolean;
|
|
};
|
|
|
|
const SourceSyncStatus: FC<SourceSyncStatusProps> = (props) => {
|
|
const { t } = useTranslation();
|
|
|
|
const attempt = props.lastAttempt;
|
|
|
|
const attemptText = attempt && attempt.state !== "none"
|
|
? t(`investment.attempt.${attempt.state}`)
|
|
: null;
|
|
|
|
return (
|
|
<>
|
|
{!!props.lastSuccessfulAt && (
|
|
<Text c="dimmed" size="xs">
|
|
{t("investment.sourceTime", {
|
|
date: formatSnapshotTime(props.lastSuccessfulAt),
|
|
})}
|
|
</Text>
|
|
)}
|
|
|
|
{!!props.stale && <Text size="xs">{t("investment.stale")}</Text>}
|
|
|
|
{!!attemptText && (
|
|
<Text role="status" size="xs">
|
|
{attemptText}
|
|
</Text>
|
|
)}
|
|
|
|
{!!props.errorText && <Text role="status">{props.errorText}</Text>}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export { SourceSyncStatus, type SourceSyncStatusProps };
|