GdzieWjade/src/components/ReportCard.tsx
2026-10-03 18:22:27 +02:00

68 lines
2.7 KiB
TypeScript

import type { ReactNode } from 'react';
import { useI18n, type Key } from '../lib/i18n';
import { usePhoto } from '../lib/usePhoto';
import type { UserReport } from '../lib/types';
import { Icon, VettingSummary } from './ui';
interface Props {
report: UserReport;
/** Queue view: the place is the heading and the claim sits below it. Place view: the claim is the heading. */
placeName?: string | undefined;
headingLevel?: 'h2' | 'h3';
/** Show the full automatic assessment (city panel) instead of the short tags. */
detailed?: boolean;
children?: ReactNode;
}
const STATUS_TAG = {
pending: 'bg-base-lighter text-ink',
accepted: 'bg-success-dark text-white',
rejected: 'bg-error-dark text-white',
} as const;
/** One layout for every user report, with or without a photo, in the place view and in the city inbox. */
export function ReportCard({ report: r, placeName, headingLevel = 'h3', detailed = false, children }: Props) {
const { t, date } = useI18n();
const photo = usePhoto(r.photoId);
const Heading = headingLevel;
const claim = (
<>
{t(`rep.attr.${r.attr}` as Key)}: <strong>{typeof r.value === 'number' ? `${r.value} ${t('unit.cm')}` : t(`rep.${r.value}` as Key)}</strong>
</>
);
const status = r.status ?? 'pending';
return (
<article className="kbb-rcard">
<div className={`kbb-rcard__media ${photo ? '' : 'is-empty'}`}>
{photo ? (
<img src={photo} alt={t('rep.photo.alt')} />
) : (
<>
<Icon name="visibility_off" size={4} />
<span>{t('vet.flag.no-photo')}</span>
</>
)}
</div>
<div className="kbb-rcard__body">
<div className="kbb-rcard__top">
<Heading className="kbb-rcard__title">{placeName ?? claim}</Heading>
<span className={`usa-tag ${STATUS_TAG[status]}`}>{t(status === 'pending' ? 'detail.reports.pending' : (`dash.queue.status.${status}` as Key))}</span>
</div>
{placeName && <p className="kbb-rcard__claim">{claim}</p>}
<p className="kbb-rcard__meta">
{date(r.createdAt.slice(0, 10))}
{r.demo && <span className="usa-tag bg-ink text-white margin-left-1">{t('detail.reports.demo')}</span>}
</p>
{r.measure && (
<p className="kbb-rcard__line">
{t(`vet.measure.${r.measure.kind}` as Key)}: <strong>{r.measure.value} {r.measure.unit === 'cm' ? 'cm' : '%'}</strong> ({t(`vet.method.${r.measure.method}` as Key)})
</p>
)}
{r.note && <p className="kbb-rcard__note">{r.note}</p>}
<VettingSummary v={r.vetting} detailed={detailed} />
{children && <div className="kbb-rcard__actions">{children}</div>}
</div>
</article>
);
}