import React, { useState, useRef, useEffect } from "react"; import { Box, Link, Typography, Avatar, Grid, SxProps, Tooltip, IconButton, } from "@mui/material"; import { Card, CardContent, Divider, useTheme } from "@mui/material"; import DeleteIcon from "@mui/icons-material/Delete"; import { useMediaQuery } from "@mui/material"; import { Candidate, CandidateAI } from "types/types"; import { CopyBubble } from "components/CopyBubble"; import { rest } from "lodash"; import { AIBanner } from "components/ui/AIBanner"; import { useAuth } from "hooks/AuthContext"; import { DeleteConfirmation } from "../DeleteConfirmation"; interface CandidateInfoProps { candidate: Candidate; sx?: SxProps; action?: string; elevation?: number; variant?: "minimal" | "small" | "normal" | undefined; } const CandidateInfo: React.FC = ( props: CandidateInfoProps ) => { const { candidate } = props; const { user, apiClient } = useAuth(); const { sx, action = "", elevation = 1, variant = "normal" } = props; const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("md")) || variant === "minimal"; const ai: CandidateAI | null = "isAI" in candidate ? (candidate as CandidateAI) : null; const isAdmin = user?.isAdmin; // State for description expansion const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false); const [shouldShowMoreButton, setShouldShowMoreButton] = useState(false); const descriptionRef = useRef(null); // Check if description needs truncation useEffect(() => { if (descriptionRef.current && candidate.description) { const element = descriptionRef.current; // Check if the scrollHeight is greater than clientHeight (meaning content is truncated) setShouldShowMoreButton(element.scrollHeight > element.clientHeight); } }, [candidate.description]); const deleteCandidate = async (candidateId: string | undefined) => { if (candidateId) { await apiClient.deleteCandidate(candidateId); } }; if (!candidate) { return No user loaded.; } return ( {ai && } .MuiTypography-root": { m: 0 }, }} > {action !== "" && ( {action} )} {action === "" && ( {candidate.fullName} )} {`/u/${candidate.username}`} { event.stopPropagation(); }} tooltip="Copy link" content={`${window.location.origin}/u/{candidate.username}`} /> {!isMobile && variant === "normal" && ( {candidate.description} {shouldShowMoreButton && ( { e.preventDefault(); e.stopPropagation(); setIsDescriptionExpanded(!isDescriptionExpanded); }} sx={{ color: theme.palette.primary.main, textDecoration: "none", cursor: "pointer", fontSize: "0.725rem", fontWeight: 500, mt: 0.5, display: "block", "&:hover": { textDecoration: "underline", }, }} > [{isDescriptionExpanded ? "less" : "more"}] )} )} {variant !== "small" && variant !== "minimal" && ( <> {candidate.location && ( Location: {candidate.location.city},{" "} {candidate.location.state || candidate.location.country} )} {candidate.email && ( Email: {candidate.email} )} {candidate.phone && ( Phone: {candidate.phone} )} )} {isAdmin && ai && ( { e.stopPropagation(); deleteCandidate(candidate.id); }} > )} ); }; export { CandidateInfo };