diff --git a/quotevote-backend/app/server.ts b/quotevote-backend/app/server.ts index 451b4fd0..831914f8 100644 --- a/quotevote-backend/app/server.ts +++ b/quotevote-backend/app/server.ts @@ -73,7 +73,7 @@ async function startServer() { issuer: String message: String } - + scalar JSON type PortableState { @@ -85,7 +85,7 @@ async function startServer() { version: String collections: [JSON] } - + input ActivityEventInput { type: String! payload: JSON! diff --git a/quotevote-frontend/src/__tests__/components/settings/SettingsContent.test.tsx b/quotevote-frontend/src/__tests__/components/settings/SettingsContent.test.tsx index 50fd3e30..a47102ab 100644 --- a/quotevote-frontend/src/__tests__/components/settings/SettingsContent.test.tsx +++ b/quotevote-frontend/src/__tests__/components/settings/SettingsContent.test.tsx @@ -255,22 +255,6 @@ describe('SettingsContent', () => { expect(screen.getByText('Save')).toBeInTheDocument() }) - it('renders Manage Invites button for admin users', () => { - mockUseAppStore.mockImplementation((selector: (state: Record) => unknown) => { - const state = { - user: { - data: { ...mockUserData, admin: true }, - loading: false, - }, - setUserData: jest.fn(), - logout: jest.fn(), - } - return selector(state) - }) - - renderComponent() - expect(screen.getByText('Manage Invites')).toBeInTheDocument() - }) it('renders Forgot Password link', () => { renderComponent() diff --git a/quotevote-frontend/src/app/dashboard/explore/ExploreContent.tsx b/quotevote-frontend/src/app/dashboard/explore/ExploreContent.tsx index 35c87c55..a086ff61 100644 --- a/quotevote-frontend/src/app/dashboard/explore/ExploreContent.tsx +++ b/quotevote-frontend/src/app/dashboard/explore/ExploreContent.tsx @@ -3,7 +3,7 @@ import { useState, useCallback } from 'react' import { useRouter, useSearchParams } from 'next/navigation' import Image from 'next/image' -import { Dialog, DialogContent } from '@/components/ui/dialog' +import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog' import PaginatedPostsList from '@/components/Post/PaginatedPostsList' import { useAppStore } from '@/store' import SearchGuestSections from '@/components/SearchContainer/SearchGuestSections' @@ -224,6 +224,7 @@ export default function ExploreContent() { {/* Create Quote Dialog */} + Create Quote diff --git a/quotevote-frontend/src/app/dashboard/layout.tsx b/quotevote-frontend/src/app/dashboard/layout.tsx index c05236dc..5e99526c 100644 --- a/quotevote-frontend/src/app/dashboard/layout.tsx +++ b/quotevote-frontend/src/app/dashboard/layout.tsx @@ -14,7 +14,6 @@ import { User, Settings2, ShieldCheck, - Mail, LogOut, ChevronDown, } from 'lucide-react'; @@ -42,7 +41,7 @@ import { DropdownMenuItem, DropdownMenuSeparator, } from '@/components/ui/dropdown-menu'; -import { Dialog, DialogContent } from '@/components/ui/dialog'; +import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog'; import { SubmitPost } from '@/components/SubmitPost/SubmitPost'; /* ------------------------------------------------------------------ */ @@ -53,7 +52,6 @@ const NAV_PAGES = [ { path: '/dashboard/profile', page: 'profile' }, { path: '/dashboard/notifications', page: 'notifications' }, { path: '/dashboard/settings', page: 'settings' }, - { path: '/dashboard/manage-invites', page: 'manage-invites' }, { path: '/dashboard/control-panel', page: 'control-panel' }, ] as const; @@ -321,15 +319,6 @@ export default function DashboardLayout({

Manage your account

- router.push('/dashboard/manage-invites')} className="cursor-pointer rounded-lg gap-3 py-2.5 px-3"> -
- -
-
-

Manage Invites

-

Invite friends to join

-
-
{isAdmin && ( router.push('/dashboard/control-panel')} className="cursor-pointer rounded-lg gap-3 py-2.5 px-3">
@@ -514,6 +503,7 @@ export default function DashboardLayout({ + Create Quote diff --git a/quotevote-frontend/src/app/dashboard/notifications/NotificationsPageContent.tsx b/quotevote-frontend/src/app/dashboard/notifications/NotificationsPageContent.tsx index ecaaf679..6ccec152 100644 --- a/quotevote-frontend/src/app/dashboard/notifications/NotificationsPageContent.tsx +++ b/quotevote-frontend/src/app/dashboard/notifications/NotificationsPageContent.tsx @@ -10,7 +10,7 @@ import { Skeleton } from '@/components/ui/skeleton'; import type { Notification } from '@/types/notification'; export function NotificationsPageContent() { - const userId = useAppStore((state) => state.user.data.id); + const userId = useAppStore((state) => (state.user.data._id || state.user.data.id) as string | undefined); const { loading, data, refetch, error } = useQuery(GET_NOTIFICATIONS, { skip: !userId, diff --git a/quotevote-frontend/src/app/dashboard/settings/SettingsPageClient.tsx b/quotevote-frontend/src/app/dashboard/settings/SettingsPageClient.tsx index 8635ff97..6bc9ef75 100644 --- a/quotevote-frontend/src/app/dashboard/settings/SettingsPageClient.tsx +++ b/quotevote-frontend/src/app/dashboard/settings/SettingsPageClient.tsx @@ -56,7 +56,6 @@ export default function SettingsPageClient() { const email = userData?.email ?? '' const name = userData?.name ?? '' const userId = userData?.id ?? userData?._id ?? '' - const isAdmin = Boolean(userData?.admin) const [localDarkMode, setLocalDarkMode] = useState(isDarkMode) const [originalDarkMode, setOriginalDarkMode] = useState(isDarkMode) @@ -100,20 +99,22 @@ export default function SettingsPageClient() { try { const result = await updateUser({ variables: { user: userInput } }) - if (result.data?.updateUser) { - const avatarValue = - typeof userData?.avatar === 'string' - ? userData.avatar - : (userData?.avatar as { url?: string } | undefined)?.url + const updated = result.data?.updateUser + if (updated) { setUserData({ ...userData, - avatar: avatarValue, - ...otherValues, + ...updated, + avatar: userData?.avatar as string | undefined, themePreference: localDarkMode ? 'dark' : 'light', }) setOriginalDarkMode(localDarkMode) toast.success('Settings saved successfully') - form.reset({ ...otherValues, password: '' }) + form.reset({ + name: updated.name ?? otherValues.name, + username: updated.username ?? otherValues.username, + email: updated.email ?? otherValues.email, + password: '', + }) } } catch (err) { const message = err instanceof Error ? err.message : 'Failed to save settings' @@ -289,16 +290,7 @@ export default function SettingsPageClient() { Sign Out - {isAdmin && ( - - )} +
- {admin && ( - - )} - - -
+ + + e.preventDefault()} + > + {/* Search input */} +
setInputValue(e.target.value)} - className="mb-2" + onKeyDown={handleKeyDown} + className="h-8 border-0 p-0 text-sm shadow-none focus-visible:ring-0" /> -
- {filteredOptions.length === 0 ? ( -
- No options found. -
- ) : ( -
- {filteredOptions.map((option) => ( -
+ + {/* Options list */} +
+ {filteredOptions.length === 0 ? ( +

+ {inputValue ? 'No matching groups.' : 'No groups yet. Type a name to create one.'} +

+ ) : ( + filteredOptions.map((option) => ( + - ))} -
- )} -
+ + )} + + )) + )}
- - +
+ + {error && errorMessage && (

{errorMessage}

)}
) } - diff --git a/quotevote-frontend/src/graphql/mutations.ts b/quotevote-frontend/src/graphql/mutations.ts index 9305c053..12ffdc8f 100644 --- a/quotevote-frontend/src/graphql/mutations.ts +++ b/quotevote-frontend/src/graphql/mutations.ts @@ -610,7 +610,6 @@ export const UPDATE_USER = gql` mutation updateUser($user: UserInput!) { updateUser(user: $user) { _id - id username email name @@ -618,8 +617,6 @@ export const UPDATE_USER = gql` admin accountStatus themePreference - created - updated } } ` diff --git a/quotevote-frontend/src/types/notification.ts b/quotevote-frontend/src/types/notification.ts index d7799b5d..2c164a66 100644 --- a/quotevote-frontend/src/types/notification.ts +++ b/quotevote-frontend/src/types/notification.ts @@ -5,10 +5,7 @@ export interface NotificationUser { _id: string; name: string; - avatar?: { - url?: string; - [key: string]: unknown; - }; + avatar?: string | Record; username: string; contributorBadge?: boolean; }