Public Access
Target fields on the admin hints page. The dashboard shows the four automatic hints after admin hints when their condition is true, using data Core already serves. HintText renders **bold** and safe links (app path or https) as React elements, never HTML, in hints and news. Auto-close without tick hides for this session, X for 7 days, tick + X for good.
43 lines
1.9 KiB
React
43 lines
1.9 KiB
React
import {useId} from 'react';
|
|
import {useTranslation} from 'react-i18next';
|
|
import {Megaphone, X} from 'lucide-react';
|
|
|
|
import {Button} from '@/components/ui/button';
|
|
import {Card} from '@/components/ui/card';
|
|
import {cn} from '@/lib/utils';
|
|
import HintText from './HintText.jsx';
|
|
import {hintText} from '../utils/hints.js';
|
|
|
|
export default function HintCard({hint, hideForever, onHideForeverChange, onClose, onAccept, className}) {
|
|
const {t, i18n} = useTranslation();
|
|
const checkboxId = useId();
|
|
|
|
return (
|
|
<Card role="status" className={cn('gap-3 p-4 shadow-lg', className)}>
|
|
<div className="flex items-start gap-3">
|
|
<Megaphone className="mt-0.5 size-5 shrink-0 text-primary"/>
|
|
<p className="flex-1 whitespace-pre-line break-words text-sm">
|
|
<HintText text={hint.text ?? hintText(hint, i18n.language)}/>
|
|
</p>
|
|
{hint.kind === 'DISMISS' && (
|
|
<Button type="button" variant="ghost" size="icon" className="-mr-2 -mt-2 size-8"
|
|
aria-label={t('HINT.CLOSE')} onClick={onClose}>
|
|
<X/>
|
|
</Button>
|
|
)}
|
|
</div>
|
|
<div className="flex items-center justify-end gap-2">
|
|
{hint.kind === 'DISMISS' ? (
|
|
<label htmlFor={checkboxId} className="flex items-center gap-2 text-xs text-muted-foreground">
|
|
<input id={checkboxId} type="checkbox" className="accent-primary" checked={hideForever}
|
|
onChange={(event) => onHideForeverChange(event.target.checked)}/>
|
|
{t('HINT.DO_NOT_SHOW_AGAIN')}
|
|
</label>
|
|
) : (
|
|
<Button type="button" size="sm" onClick={onAccept}>{t('HINT.OK')}</Button>
|
|
)}
|
|
</div>
|
|
</Card>
|
|
);
|
|
}
|