64 lines
2.4 KiB
TypeScript
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>
|
|
);
|
|
}
|