Files
jobtrackingapp/job-tracker-ui/src/components/ProFeatureNotice.tsx
T

64 lines
2.4 KiB
TypeScript

import React, { useState } from "react";
import CloseIcon from "@mui/icons-material/Close";
import { Alert, Button, IconButton, Stack, Typography } from "@mui/material";
import { useOptionalI18n } from "../i18n/I18nProvider";
import { useAccountPlan } from "../accountPlan";
type Props = {
featureKey: string;
title: string;
children: React.ReactNode;
};
function storageKey(featureKey: string) {
return `jobtracker.proNoticeDismissed.${featureKey}`;
}
export default function ProFeatureNotice({ featureKey, title, children }: Props) {
const i18n = useOptionalI18n();
const { plan, canUseAi } = useAccountPlan();
const aiUnavailable = plan === "pro" && !canUseAi;
const displayTitle = aiUnavailable ? i18n?.t("aiUnavailableTitle") ?? "AI assistance is unavailable" : title;
const [dismissed, setDismissed] = useState(() => {
if (typeof window === "undefined") return false;
try {
return window.sessionStorage.getItem(storageKey(featureKey)) === "true";
} catch {
return false;
}
});
if (dismissed) return null;
const dismiss = () => {
try {
window.sessionStorage.setItem(storageKey(featureKey), "true");
} catch {
// The notice can still be dismissed for this render when storage is unavailable.
}
setDismissed(true);
};
return (
<Alert
severity="info"
sx={{
display: "grid", gridTemplateColumns: "auto minmax(0, 1fr)",
"& .MuiAlert-message": { gridColumn: 2, gridRow: 1, minWidth: 0, overflow: "visible", overflowWrap: "anywhere" },
"& .MuiAlert-action": { gridColumn: 2, gridRow: 2, m: 0, p: 0, mt: 0.5, justifySelf: "start" },
}}
action={(
<Stack direction="row" spacing={0.5} alignItems="center">
<Button href="/settings" size="small">{aiUnavailable ? i18n?.t("aiUnavailableSettings") ?? "Review AI settings" : i18n?.t("proFeatureView") ?? "View Pro"}</Button>
<IconButton size="small" aria-label={i18n?.t("proFeatureDismiss", { title: displayTitle }) ?? `Dismiss ${displayTitle}`} onClick={dismiss}>
<CloseIcon fontSize="small" />
</IconButton>
</Stack>
)}
>
<Typography component="span" sx={{ fontWeight: 800 }}>{displayTitle}</Typography>{" "}
{aiUnavailable ? i18n?.t("aiUnavailableBody") ?? "You can continue editing manually. Review your AI settings and usage before trying again." : children}
</Alert>
);
}