Email:
{userDetails.email || 'N/A'}
diff --git a/app/author/[id]/page.tsx b/app/author/[id]/page.tsx
index 5b29b5957..95c7aef67 100644
--- a/app/author/[id]/page.tsx
+++ b/app/author/[id]/page.tsx
@@ -1,6 +1,6 @@
'use client';
-import { use, useTransition } from 'react';
+import { use, useTransition, useState } from 'react';
import { useAuthorAchievements, useAuthorInfo, useAuthorSummaryStats } from '@/hooks/useAuthor';
import { useUser } from '@/contexts/UserContext';
import { Card } from '@/components/ui/Card';
@@ -18,6 +18,10 @@ import AuthorProfile from './components/AuthorProfile';
import { useAuthorPublications } from '@/hooks/usePublications';
import { transformPublicationToFeedEntry } from '@/types/publication';
import PinnedFundraise from './components/PinnedFundraise';
+import { BookOpen } from 'lucide-react';
+import { Button } from '@/components/ui/Button';
+import { toast } from 'react-hot-toast';
+import { AddPublicationsModal } from '@/components/modals/AddPublicationsModal';
function toNumberOrNull(value: any): number | null {
if (value === '' || value === null || value === undefined) return null;
@@ -90,8 +94,18 @@ const TAB_TO_CONTRIBUTION_TYPE: Record
= {
bounties: 'BOUNTY',
};
-function AuthorTabs({ authorId, userId }: { authorId: number; userId?: number }) {
+function AuthorTabs({
+ authorId,
+ isOwnProfile,
+ userId,
+}: {
+ authorId: number;
+ isOwnProfile: boolean;
+ userId?: number;
+}) {
const [isPending, startTransition] = useTransition();
+ const [isAddPublicationsModalOpen, setIsAddPublicationsModalOpen] = useState(false);
+ const [isRefreshing, setIsRefreshing] = useState(false);
const tabs = [
{ id: 'contributions', label: 'Overview' },
{ id: 'publications', label: 'Publications' },
@@ -126,10 +140,20 @@ function AuthorTabs({ authorId, userId }: { authorId: number; userId?: number })
hasMore: hasMorePublications,
loadMore: loadMorePublications,
isLoadingMore: isLoadingMorePublications,
+ refresh: refreshPublications,
} = useAuthorPublications({
authorId,
});
+ const handleRefreshPublications = async () => {
+ setIsRefreshing(true);
+ try {
+ await refreshPublications();
+ } finally {
+ setIsRefreshing(false);
+ }
+ };
+
const handleTabChange = (tabId: string) => {
startTransition(() => {
const params = new URLSearchParams(searchParams);
@@ -143,7 +167,6 @@ function AuthorTabs({ authorId, userId }: { authorId: number; userId?: number })
if (publicationsError) {
return Error: {publicationsError.message}
;
}
-
// Filter out invalid publications
const validPublications = publications.filter((publication) => {
try {
@@ -157,15 +180,28 @@ function AuthorTabs({ authorId, userId }: { authorId: number; userId?: number })
return (
+ {/* Add Publications Button - only show for own profile */}
+ {isOwnProfile && validPublications.length > 0 && (
+
+
+
+ )}
+
transformPublicationToFeedEntry(publication)
)
}
- isLoading={isPending || isPublicationsLoading}
+ isLoading={isPending || isPublicationsLoading || isRefreshing}
hasMore={hasMorePublications}
loadMore={loadMorePublications}
showBountyFooter={false}
@@ -173,7 +209,26 @@ function AuthorTabs({ authorId, userId }: { authorId: number; userId?: number })
isLoadingMore={isLoadingMorePublications}
showBountySupportAndCTAButtons={false}
showBountyDeadline={false}
- noEntriesElement={}
+ noEntriesElement={
+ isOwnProfile ? (
+
+
+
No publications yet
+
+ Add your published papers to showcase your research contributions.
+
+
+
+ ) : (
+
+ )
+ }
maxLength={150}
/>
@@ -229,6 +284,16 @@ function AuthorTabs({ authorId, userId }: { authorId: number; userId?: number })
className="border-b"
/>
{renderTabContent()}
+
+ {/* Add Publications Modal */}
+ setIsAddPublicationsModalOpen(false)}
+ onPublicationsAdded={() => {
+ toast.success('Publications added successfully!');
+ handleRefreshPublications(); // Use the wrapper function
+ }}
+ />
);
}
@@ -239,6 +304,7 @@ export default function AuthorProfilePage({ params }: { params: Promise<{ id: st
const authorId = toNumberOrNull(resolvedParams.id);
const [{ author: user, isLoading, error }, refetchAuthorInfo] = useAuthorInfo(authorId);
const { user: currentUser } = useUser();
+
// Determine if current user is a hub editor
const isHubEditor = !!currentUser?.authorProfile?.isHubEditor;
const [{ achievements, isLoading: isAchievementsLoading, error: achievementsError }] =
@@ -304,7 +370,11 @@ export default function AuthorProfilePage({ params }: { params: Promise<{ id: st
)}
>
);
}
diff --git a/components/modals/AddPublicationsModal.tsx b/components/modals/AddPublicationsModal.tsx
new file mode 100644
index 000000000..9b82f20fe
--- /dev/null
+++ b/components/modals/AddPublicationsModal.tsx
@@ -0,0 +1,97 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import { BookOpen } from 'lucide-react';
+import { BaseModal } from '@/components/ui/BaseModal';
+import { AddPublicationsForm, STEP } from './Verification/AddPublicationsForm';
+
+interface AddPublicationsModalProps {
+ isOpen: boolean;
+ onClose: () => void;
+ onPublicationsAdded?: () => void;
+}
+
+export function AddPublicationsModal({
+ isOpen,
+ onClose,
+ onPublicationsAdded,
+}: AddPublicationsModalProps) {
+ const [currentStep, setCurrentStep] = useState