Skip to content

Feat/profile#334

Merged
motirebuma merged 10 commits intomainfrom
feat/profile
Apr 23, 2026
Merged

Feat/profile#334
motirebuma merged 10 commits intomainfrom
feat/profile

Conversation

@motirebuma
Copy link
Copy Markdown
Collaborator

  • Fixed the profile section on the post detail page to correctly redirect to the user profile or avatar editing page.
  • Improved the UI of the profile avatar in the navbar.
  • Refined the UI for post avatars.
  • Updated the avatar UI in the discussion section of posts.
  • Designed the Your Profile section, allowing users to edit their avatar and view their personal information.
  • Completed the UI for the Settings and Privacy page.
  • Implemented the dark mode functionality.

Copilot AI review requested due to automatic review settings April 23, 2026 04:53
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
quotevote Ready Ready Preview, Comment Apr 23, 2026 4:53am

@motirebuma motirebuma merged commit b3cf4a7 into main Apr 23, 2026
8 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades profile/avatar handling across the frontend (including deterministic default avatars), introduces/finishes dark mode support with theme preference persistence, and refactors the Settings & Privacy UI into a unified page.

Changes:

  • Added DisplayAvatar + avatar parsing utilities to support avataaars qualities objects/JSON/URLs and a deterministic default avatar.
  • Implemented dark mode styling and theme preference support (types, GraphQL mutation selection, theme context integration, CSS variables).
  • Refactored profile/follow UI and the Settings page, updating affected components and tests.

Reviewed changes

Copilot reviewed 45 out of 45 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
quotevote-frontend/src/types/store.ts Updates _followingId to an array type for store user data.
quotevote-frontend/src/types/settings.ts Adds themePreference and updates _followingId typing for settings user data.
quotevote-frontend/src/types/profile.ts Removes profileUserId from UserFollowDisplayProps.
quotevote-frontend/src/types/postChat.ts Broadens avatar typing to support object-based avatar payloads.
quotevote-frontend/src/store/useAppStore.ts Updates updateFollowing to accept string[] and persist it in the store.
quotevote-frontend/src/lib/avatar.ts Adds avatar utilities: deterministic default qualities, URL builder, and parser.
quotevote-frontend/src/lib/auth.ts Changes login to use user from response rather than decoding JWT client-side.
quotevote-frontend/src/graphql/mutations.ts Requests themePreference from updateUser.
quotevote-frontend/src/context/ThemeContext.tsx Applies/removes dark class on <html> when theme mode changes.
quotevote-frontend/src/components/UserPosts/PostCard.tsx Swaps to DisplayAvatar for creator avatar rendering.
quotevote-frontend/src/components/Sidebar/Sidebar.tsx Uses DisplayAvatar and theme-aware text colors.
quotevote-frontend/src/components/RequestInviteDialog.tsx Uses theme tokens (text-foreground, text-muted-foreground) for dark mode.
quotevote-frontend/src/components/Profile/UserFollowDisplay.tsx Replaces legacy avatar component with DisplayAvatar.
quotevote-frontend/src/components/Profile/ProfileView.tsx Adjusts activity filter toggle behavior (select-all/isolate/reset logic).
quotevote-frontend/src/components/Profile/ProfileHeader.tsx Uses DisplayAvatar and adjusts following detection logic.
quotevote-frontend/src/components/Profile/ProfileAvatar.tsx Uses DisplayAvatar and maps named sizes to pixel sizes.
quotevote-frontend/src/components/Profile/FollowInfo.tsx Removes unused profileUserId plumbing.
quotevote-frontend/src/components/PostChat/PostChatReactions.tsx Updates reaction icon colors to theme tokens.
quotevote-frontend/src/components/PostChat/PostChatMessage.tsx Uses DisplayAvatar and theme-aware bubble styling.
quotevote-frontend/src/components/PostActions/PostActionCard.tsx Uses DisplayAvatar and passes avatar through as object/string.
quotevote-frontend/src/components/Post/PostCard.tsx Uses DisplayAvatar for author display in post cards.
quotevote-frontend/src/components/Post/Post.tsx Replaces mixed Avatar/avataaars rendering with DisplayAvatar.
quotevote-frontend/src/components/Navbars/NavSearch.tsx Updates placeholder and colors to support dark mode.
quotevote-frontend/src/components/Navbars/MainNavBar.tsx Uses DisplayAvatar and cleans up avatar/name handling.
quotevote-frontend/src/components/DisplayAvatar.tsx New component: renders avatar URL or deterministic default cartoon as <img>.
quotevote-frontend/src/components/CustomButtons/FollowButton.tsx Updates optimistic follow handling for _followingId as string[].
quotevote-frontend/src/components/BuddyList/BuddyItemList.tsx Uses theme-aware text colors.
quotevote-frontend/src/components/Avatar.tsx Marks avataaars.io images as unoptimized when using Next <Image>.
quotevote-frontend/src/app/layout.tsx Wraps app with ThemeContextProvider and adds pre-paint theme class script.
quotevote-frontend/src/app/globals.css Reworks CSS variables and adds a dark theme palette; binds Tailwind theme tokens to vars.
quotevote-frontend/src/app/dashboard/settings/SettingsPageClient.tsx Refactors settings into unified form + avatar link + theme toggle + sign out.
quotevote-frontend/src/app/dashboard/profile/[username]/avatar/page.tsx Reuses shared buildAvatarUrl from lib/avatar.
quotevote-frontend/src/app/dashboard/layout.tsx Applies theme tokens across dashboard chrome; uses DisplayAvatar.
quotevote-frontend/src/app/dashboard/explore/ExploreContent.tsx Shows alternate logo rendering for dark mode.
quotevote-frontend/src/tests/components/UserPosts/PostCard.test.tsx Updates avatar assertions to match DisplayAvatar behavior (img + alt text).
quotevote-frontend/src/tests/components/Sidebar.test.tsx Updates avatar alt-text expectations for DisplayAvatar.
quotevote-frontend/src/tests/components/Profile/UserFollowDisplay.test.tsx Updates mocks/assertions for DisplayAvatar.
quotevote-frontend/src/tests/components/Profile/ProfileAvatar.test.tsx Updates mocks/assertions and adds coverage for size mapping + username passing.
quotevote-frontend/src/tests/components/Profile/FollowInfo.test.tsx Updates _followingId test data to array format.
quotevote-frontend/src/tests/components/Profile/FollowButton.test.tsx Updates expectations for updateFollowing array signature.
quotevote-frontend/src/tests/components/PostChat/PostChatMessage.test.tsx Updates mock to DisplayAvatar.
quotevote-frontend/src/tests/components/PostActions/PostActionCard.test.tsx Updates mock to DisplayAvatar.
quotevote-frontend/src/tests/components/CustomButtons.test.tsx Updates _followingId initial state in tests to array format.
quotevote-frontend/src/tests/app/dashboard/settings/page.test.tsx Updates tests for new unified settings page UI + dark mode toggle.
quotevote-frontend/next.config.ts Adds avataaars.io image remote pattern.
Comments suppressed due to low confidence (1)

quotevote-frontend/src/lib/auth.ts:71

  • loginUser now destructures { token, user } from the /login response and returns user without any fallback. In this repo the TS backend login handler responds with accessToken/refreshToken (and optionally user) rather than token (see quotevote-backend/app/data/utils/authentication.ts), so this will treat successful logins as missing-token and/or set user to undefined. Update the client to support the backend response shape (and endpoint, if applicable) and ensure user is populated (e.g., use data.user when present, otherwise derive it from the token or fetch me).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +98 to 102
const avatarValue =
typeof userData?.avatar === 'string'
? userData.avatar
: (userData?.avatar as { url?: string } | undefined)?.url
setUserData({
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a successful updateUser mutation, the store update derives avatarValue from the previous userData.avatar (and assumes a { url } shape). This can wipe avatar qualities objects (or ignore the avatar returned by the mutation). Prefer using result.data.updateUser.avatar (and/or the full returned user object) when calling setUserData, preserving whatever avatar format the backend returns.

Copilot uses AI. Check for mistakes.
Comment on lines +79 to +82
const handleSignOut = useCallback(() => {
removeToken()
router.push('/auths/login')
}, [router])
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleSignOut removes the token but doesn’t clear the persisted Zustand user state. Because the store is persisted, the app can still render as “logged in” (stale user.data) after redirect. Call the store’s logout()/clearUserData() (and any other relevant resets) alongside removeToken().

Copilot uses AI. Check for mistakes.
Comment on lines +61 to 63
const [localDarkMode, setLocalDarkMode] = useState(isDarkMode)
const [originalDarkMode, setOriginalDarkMode] = useState(isDarkMode)

Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

localDarkMode/originalDarkMode are initialized from isDarkMode only once. If the ThemeContext later updates isDarkMode (e.g., when user.themePreference loads/syncs), the toggle state and dirty calculation can become out of sync with the actual theme. Add an effect to sync these state values when isDarkMode changes (or derive them directly instead of copying into local state).

Copilot uses AI. Check for mistakes.
Comment on lines 143 to 144
const followersCount = _followersId?.length || 0;
const followingCount = _followingId?.length || 0;
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

followersCount/followingCount are computed from _followersId/_followingId directly. This component already normalizes _followersId into followersArray to handle legacy string formats, but the counts will be wrong if either field is a string (string .length counts characters). Compute counts from the normalized arrays (and normalize _followingId similarly for followingCount).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants