import Link from "next/link"; import type { LexicalEntry } from "@/lib/types"; import { entriesBySynset, senseById, synsetById } from "@/lib/lexicon"; import { REL_LABEL } from "@/lib/format"; import { WordLink } from "@/components/WordLink"; import { IdChip, LangBadge, PosBadge } from "./ui"; /** * Dictionary entry card (SRS §8.1.2). When `showIds` is false (Visitor * tier) internal IDs and ILI codes are hidden and relations are shown * by target word form only. */ export function EntryCard({ entry, showIds, compact = false, detailPage = false, }: { entry: LexicalEntry; showIds: boolean; compact?: boolean; /** True on `/word/[id]` — hides the redundant self-link control. */ detailPage?: boolean; }) { const firstSynset = entry.senses[0] ? synsetById.get(entry.senses[0].synset) : undefined; const previewDefinition = firstSynset?.definition?.text; const cardClassName = "rounded-2xl border border-slate-200 bg-white p-5 shadow-sm transition hover:shadow-md"; const header = (
{detailPage ? (

{entry.lemma}

) : ( {entry.lemma} )} {showIds ? : null} {entry.senses.length > 1 ? ( {entry.senses.length} senses (polysemous) ) : null} {!detailPage ? ( Show Details → ) : null}
); const senseSections = (
{entry.senses.map((sense, idx) => { const synset = synsetById.get(sense.synset); const synonyms = (entriesBySynset.get(sense.synset) ?? []).filter( (e) => e.id !== entry.id ); return (
Sense {idx + 1} {showIds ? ( <> {synset ? ( ILI {synset.ili} ) : null} ) : null}
{synset?.definition ? (

{" "} {synset.definition.text}

) : (

No definition recorded for this concept yet.

)} {synonyms.length > 0 ? (

Synonyms:{" "} {synonyms.slice(0, 8).map((s, i) => ( {i > 0 ? ", " : ""} {s.lemma} ))} {synonyms.length > 8 ? ` +${synonyms.length - 8} more` : ""}

) : null} {!compact && sense.relations && sense.relations.length > 0 ? (

Sense relations

    {sense.relations.map((rel, i) => { const target = senseById.get(rel.target); return (
  • {REL_LABEL[rel.relType] ?? rel.relType} {target ? ( {target.entry.lemma} ) : ( external sense )} {showIds ? : null}
  • ); })}
) : null} {!compact && synset?.relations && synset.relations.length > 0 ? (

Synset relations

    {synset.relations.map((rel, i) => { const targetSynset = synsetById.get(rel.target); const targetWords = entriesBySynset.get(rel.target) ?? []; return (
  • {REL_LABEL[rel.relType] ?? rel.relType} {targetWords.length > 0 ? ( targetWords.slice(0, 4).map((w, j) => ( {w.lemma} {j < Math.min(targetWords.length, 4) - 1 ? "," : ""} )) ) : ( (lexical gap) )} {showIds ? ( ) : null} {targetSynset?.definition && !compact ? ( {targetSynset.definition.text.slice(0, 90)} {targetSynset.definition.text.length > 90 ? "…" : ""} ) : null}
  • ); })}
) : null}
); })}
); if (compact && !detailPage) { return ( {header} {previewDefinition ? (

{previewDefinition}

) : (

No definition recorded — open for full entry.

)}
); } return (
{header} {senseSections}
); }