diff --git a/frontend/src/components/CommentCard.jsx b/frontend/src/components/CommentCard.jsx index 4f80a0b..1057275 100644 --- a/frontend/src/components/CommentCard.jsx +++ b/frontend/src/components/CommentCard.jsx @@ -4,6 +4,7 @@ import { Spinner, Alert } from '@patternfly/react-core'; import { getDaysSince, formatDate } from '../utils/dateUtils'; import { fetchCommentReactions } from '../services/api'; import Reactions from './Reactions'; +import UserAvatar from './UserAvatar'; const CommentCard = ({ comment }) => { const daysSince = getDaysSince(comment.created_at); @@ -56,30 +57,40 @@ const CommentCard = ({ comment }) => {
- {comment.user?.avatar_url && ( - {comment.user.login} - )} -
-
- {comment.user?.login || 'Unknown'} -
-
- {formatDate(comment.created_at)} ({daysSince} days ago) + > + +
+ {comment.user.login || 'Unknown'} +
+ + ) : ( +
+ +
+ {comment.user?.login || 'Unknown'} +
+ )} +
+ {formatDate(comment.created_at)} ({daysSince} days ago)
diff --git a/frontend/src/components/IssueCard.jsx b/frontend/src/components/IssueCard.jsx index 975d1a4..1a37d72 100644 --- a/frontend/src/components/IssueCard.jsx +++ b/frontend/src/components/IssueCard.jsx @@ -31,6 +31,7 @@ import { } from '../services/api'; import CommentCard from './CommentCard'; import Reactions from './Reactions'; +import UserAvatar from './UserAvatar'; import labelsCache, { clearLabelsCache } from '../utils/labelsCache'; import milestonesCache from '../utils/milestonesCache'; @@ -566,52 +567,51 @@ const IssueCard = ({ issue, onMilestoneChange }) => { marginBottom: '0rem', display: 'flex', alignItems: 'flex-start', + justifyContent: 'space-between', gap: '0.5rem', padding: '0.75rem', }} > - {issue.user?.avatar_url && ( - - {issue.user.login} + {issue.user?.html_url ? ( + - - )} -
-
- {issue.user?.html_url ? ( - + > + +
{issue.user.login || 'Unknown'} - - ) : ( - issue.user?.login || 'Unknown' - )} -
-
- {formatDate(issue.created_at)} ({daysSince} days ago) -
+
+ + ) : ( +
+ +
+ {issue.user?.login || 'Unknown'} +
+
+ )} {issue.assignees && issue.assignees.length > 0 && (
{ gap: '0.25rem', }} > - {assignee.avatar_url && ( - - {assignee.login} - - )} + { ))}
)} +
+ {formatDate(issue.created_at)} ({daysSince} days ago) +
{ flexDirection: 'column', alignItems: 'flex-end', gap: '0.5rem', - maxWidth: '50%', + flexShrink: 0, }} > {/* Milestone control */} diff --git a/frontend/src/components/UserAvatar.jsx b/frontend/src/components/UserAvatar.jsx new file mode 100644 index 0000000..a46b3a5 --- /dev/null +++ b/frontend/src/components/UserAvatar.jsx @@ -0,0 +1,61 @@ +// ai-generated: Cursor +import React from 'react'; + +const UserAvatar = ({ user, size = 32, showName = false }) => { + if (!user?.avatar_url) { + return null; + } + + const avatarImage = ( + {user.login + ); + + const username = user.login || 'Unknown'; + + // If showName is true, we need to return just the avatar + // The username will be handled separately in the parent to allow proper layout + // This maintains backward compatibility for cases where showName is false + if (showName) { + // Just return the linked avatar - username will be in parent + if (user.html_url) { + return ( + + {avatarImage} + + ); + } + return avatarImage; + } + + // If showName is false, just return the avatar (for backward compatibility) + if (user.html_url) { + return ( + + {avatarImage} + + ); + } + + return avatarImage; +}; + +export default UserAvatar;