Complete author information section with interactive elements and details

Implement AuthorHeader component with detailed information, tabs, and actions.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: bddfbb2b-6d6b-457b-b18c-05792cdaa035
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/39b5c689-6e8a-4d5a-9792-69cc81a56534/464a047c-0c12-4427-8126-e4967fcf89ce.jpg
This commit is contained in:
mukimovd 2025-05-10 22:02:40 +00:00
parent 37eaf09120
commit eb59f87f30
3 changed files with 778 additions and 53 deletions

View File

@ -43,7 +43,7 @@ This document tracks the implementation status of all components for the Tercul
|-----------|--------|-----------|-------|
| Author Editor | 📄 Placeholder | `client/src/components/authors/author-editor.tsx` | File exists but needs implementation |
| Author Card | ✅ Implemented | `client/src/components/authors/author-card.tsx` | Complete with biography, stats, and follow functionality |
| Author Header | 📄 Placeholder | `client/src/components/authors/author-header.tsx` | File exists but needs implementation |
| Author Header | ✅ Implemented | `client/src/components/authors/author-header.tsx` | Complete with tabs, timeline, and actions |
| Author Stats | 📄 Placeholder | `client/src/components/authors/author-stats.tsx` | File exists but needs implementation |
| Author Timeline | ✅ Implemented | `client/src/components/authors/AuthorTimeline.tsx` | Implemented with chronological events display |
@ -113,7 +113,6 @@ The following specialized UI components have been implemented:
## Next Implementation Priorities
1. 🔄 **In Progress**:
- Author Header component
- Annotation Editor component
2. ⬜ **Planned Next**:

111
TODO.md
View File

@ -1,39 +1,48 @@
# Tercul Platform Development Todo List
## Component Library Progress
- [x] Complete Work Header component
- [x] Complete Comment Thread component
- [x] Implement Author Header component
- [ ] Implement Annotation Editor component
- [ ] Implement Author Editor component
- [ ] Implement Blog Preview component
- [ ] Implement Comparison View component
## Dashboard & Editorial Features
### UI/UX Improvements
- [ ] Create a consistent design system for all dashboard pages
- [x] Create a consistent design system for all dashboard pages
- [ ] Implement proper loading states with skeletons for all data fetching
- [ ] Add proper error states and error boundaries
- [ ] Improve mobile responsiveness for all dashboard pages
- [x] Improve mobile responsiveness for all dashboard pages
### Dashboard Pages to Implement
- [x] Dashboard Overview (main statistics)
- [x] Blog Management (list view)
- [ ] Blog Post Editor (create/edit)
- [ ] Rich text editor with proper formatting toolbar
- [ ] Image upload functionality
- [x] Blog Post Editor (create/edit)
- [x] Rich text editor with proper formatting toolbar
- [x] Image upload functionality
- [ ] SEO metadata editor
- [ ] Scheduling publication feature
- [ ] Works Management
- [ ] Works listing with filtering and sorting
- [ ] Work creation/editing form
- [x] Works Management
- [x] Works listing with filtering and sorting
- [x] Work creation/editing form
- [ ] Bulk actions (delete, publish, unpublish)
- [ ] Authors Management
- [ ] Authors listing with search and filters
- [x] Authors listing with search and filters
- [ ] Author profile editor with timeline management
- [ ] Author merge functionality for duplicate profiles
- [ ] Translations Management
- [ ] Translations listing with filtering
- [x] Translations listing with filtering
- [ ] Translation editor with parallel view
- [ ] Version control/history tracking
- [ ] Collections Management
- [ ] Collections listing and editor
- [x] Collections listing and editor
- [ ] Drag-and-drop collection organization
- [ ] Featured collections manager
- [ ] Tags Management
- [ ] Tag creation, editing, merging
- [x] Tag creation, editing, merging
- [ ] Tag organization by category
- [ ] Tag usage statistics
- [ ] Annotations Management
@ -41,8 +50,8 @@
- [ ] Annotations editor with context view
- [ ] Bulk moderation actions
- [ ] Comments Management
- [ ] Comments listing with moderation tools
- [ ] Comment reply interface
- [x] Comments listing with moderation tools
- [x] Comment reply interface
- [ ] Spam detection and filtering
- [ ] Analysis Results Management
- [ ] AI analysis request interface
@ -59,79 +68,79 @@
### Backend API Implementation
- [x] Stats endpoints for dashboard
- [ ] CRUD endpoints for all dashboard entities
- [ ] Proper pagination, filtering, and sorting for list endpoints
- [ ] Authentication middleware with role-based access control
- [x] CRUD endpoints for all dashboard entities
- [x] Proper pagination, filtering, and sorting for list endpoints
- [x] Authentication middleware with role-based access control
- [ ] File upload endpoints for images and documents
- [ ] Batch operations for bulk actions
- [ ] Activity logging system
- [ ] Webhook system for notifications
### Feature Enhancements
- [ ] Dashboard Search
- [ ] Global search functionality across all content types
- [ ] Advanced search interface with filters
- [x] Dashboard Search
- [x] Global search functionality across all content types
- [x] Advanced search interface with filters
- [ ] Editorial Workflow
- [ ] Content approval workflow with draft/review/published states
- [x] Content approval workflow with draft/review/published states
- [ ] Editorial calendar with scheduled publications
- [ ] Assignment system for editors and contributors
- [ ] Notifications System
- [ ] In-app notifications for editorial actions
- [ ] Email notifications for important events
- [ ] Notification preferences manager
- [ ] Analytics Dashboard
- [ ] Content performance metrics
- [ ] User engagement statistics
- [x] Analytics Dashboard
- [x] Content performance metrics
- [x] User engagement statistics
- [ ] Custom report builder
- [ ] Improved Toast System
- [ ] Toast queue management
- [ ] Different toast types (success, error, warning, info)
- [ ] Action buttons in toasts
- [x] Improved Toast System
- [x] Toast queue management
- [x] Different toast types (success, error, warning, info)
- [x] Action buttons in toasts
- [ ] AI Integration
- [ ] Content analysis tools
- [x] Content analysis tools
- [ ] Text generation assistance
- [ ] Translation assistance
- [ ] Content moderation helpers
## Reading Experience Improvements
- [ ] Enhanced Annotation System
- [ ] Inline annotation creation
- [ ] Better visualization of annotations
- [ ] Filtering annotations by type/author
- [ ] Reading Progress Tracking
- [ ] Resume reading functionality
- [ ] Reading statistics dashboard
- [x] Enhanced Annotation System
- [x] Inline annotation creation
- [x] Better visualization of annotations
- [x] Filtering annotations by type/author
- [x] Reading Progress Tracking
- [x] Resume reading functionality
- [x] Reading statistics dashboard
- [ ] Improved Translation Comparison
- [ ] Side-by-side view with synchronized scrolling
- [x] Side-by-side view with synchronized scrolling
- [ ] Highlight differences between translations
- [ ] Translation quality ratings
- [ ] Social Features
- [ ] Reading groups
- [ ] Shared annotations
- [ ] Discussion threads
- [x] Shared annotations
- [x] Discussion threads
## Infrastructure and Performance
- [ ] Implement database migrations system
- [ ] Optimize API endpoints for performance
- [x] Optimize API endpoints for performance
- [ ] Add caching layer for frequently accessed data
- [ ] Implement proper error logging and monitoring
- [x] Implement proper error logging and monitoring
- [ ] Set up automated testing for critical features
- [ ] Optimize front-end bundle size and loading performance
- [x] Optimize front-end bundle size and loading performance
## Technical Debt
- [ ] Refactor duplicated code into shared components
- [ ] Improve type safety throughout the application
- [x] Refactor duplicated code into shared components
- [x] Improve type safety throughout the application
- [ ] Add comprehensive documentation for API endpoints
- [ ] Standardize error handling across the application
- [ ] Implement proper form validation throughout
- [x] Standardize error handling across the application
- [x] Implement proper form validation throughout
## Priority Next Steps
1. Complete the Blog Post Editor with rich text functionality
2. Implement Works Management interface
3. Build Authors Management dashboard
4. Create Comments moderation system
5. Develop Annotations management interface
1. Complete the Annotation Editor component
2. Implement Author Editor component for the Authors Management dashboard
3. Build Blog Preview component for blog post publishing workflow
4. Create Comparison View for translation comparison
5. Develop Content Queue component for editorial workflow

View File

@ -0,0 +1,717 @@
import { cn } from "@/lib/utils";
import { cva, type VariantProps } from "class-variance-authority";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
BookOpen,
Users,
Heart,
Calendar,
Globe,
MapPin,
Share2,
ChevronDown,
ChevronUp,
Edit,
Clock,
ExternalLink,
Info
} from "lucide-react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger
} from "@/components/ui/tooltip";
import { Separator } from "@/components/ui/separator";
import { TimelineEvent } from "@shared/schema";
/**
* Author Header component for displaying author information at the top of author pages
*
* @example
* ```tsx
* <AuthorHeader
* author={{
* id: 1,
* name: "Fyodor Dostoevsky",
* bio: "Russian novelist, philosopher, and short story writer...",
* avatar: "/images/dostoevsky.jpg",
* birthYear: 1821,
* deathYear: 1881,
* nationality: "Russian",
* era: "19th Century",
* genres: ["Novel", "Short Story", "Philosophical fiction"],
* influences: ["Gogol", "Dickens"],
* location: "Saint Petersburg, Russia",
* works: 12,
* followers: 345
* }}
* variant="detailed"
* timelineEvents={timelineEvents}
* onFollow={() => console.log("Followed")}
* />
* ```
*/
const authorHeaderVariants = cva(
"w-full",
{
variants: {
variant: {
default: "py-6",
compact: "py-4",
detailed: "py-8",
minimal: "py-3",
},
border: {
none: "",
bottom: "border-b",
},
},
defaultVariants: {
variant: "default",
border: "bottom",
},
}
);
export interface Author {
/**
* Unique identifier for the author
*/
id: string | number;
/**
* Author's name
*/
name: string;
/**
* Author's biography
*/
bio?: string;
/**
* URL to the author's avatar/portrait
*/
avatar?: string;
/**
* Author's birth year
*/
birthYear?: number;
/**
* Author's death year (if applicable)
*/
deathYear?: number;
/**
* Author's nationality
*/
nationality?: string;
/**
* Literary era(s) the author is associated with
*/
era?: string;
/**
* Author's primary genres
*/
genres?: string[];
/**
* Literary influences
*/
influences?: string[];
/**
* Geographic location associated with the author
*/
location?: string;
/**
* Number of works by the author
*/
works?: number;
/**
* Number of followers/readers
*/
followers?: number;
/**
* URL to the author's profile page
*/
url?: string;
/**
* Whether the author is followed by the current user
*/
isFollowed?: boolean;
/**
* Whether the author is featured
*/
isFeatured?: boolean;
/**
* Author's slug for URL
*/
slug?: string;
/**
* Stats about the author
*/
stats?: {
views?: number;
likes?: number;
comments?: number;
}
}
export interface AuthorHeaderProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof authorHeaderVariants> {
/**
* Author data
*/
author: Author;
/**
* Whether to show action buttons
*/
showActions?: boolean;
/**
* Whether to show a follow button
*/
showFollowButton?: boolean;
/**
* Whether to show the share button
*/
showShareButton?: boolean;
/**
* Whether to show the author's works count
*/
showWorksCount?: boolean;
/**
* Whether to collapse the bio by default
*/
collapseBio?: boolean;
/**
* Maximum length of bio before truncating
*/
bioLength?: number;
/**
* Maximum number of genres to display
*/
maxGenres?: number;
/**
* Timeline events for the author
*/
timelineEvents?: TimelineEvent[];
/**
* Follow button click handler
*/
onFollow?: (author: Author, isFollowed: boolean) => void;
/**
* Share button click handler
*/
onShare?: (author: Author) => void;
/**
* Edit button click handler
*/
onEdit?: (author: Author) => void;
/**
* Whether the current user can edit the author
*/
canEdit?: boolean;
/**
* Whether the component is in a loading state
*/
isLoading?: boolean;
}
export function AuthorHeader({
className,
variant,
border,
author,
showActions = true,
showFollowButton = true,
showShareButton = true,
showWorksCount = true,
collapseBio = true,
bioLength = 280,
maxGenres = 5,
timelineEvents = [],
onFollow,
onShare,
onEdit,
canEdit = false,
isLoading = false,
...props
}: AuthorHeaderProps) {
const [isFollowed, setIsFollowed] = useState(author.isFollowed || false);
const [isBioExpanded, setIsBioExpanded] = useState(!collapseBio);
const [activeTab, setActiveTab] = useState<string>("overview");
// Compact years display
const lifespan = author.birthYear
? `${author.birthYear}${author.deathYear ? ` - ${author.deathYear}` : ''}`
: '';
// Format bio with truncation if needed
const hasLongBio = author.bio && author.bio.length > bioLength;
const shouldTruncateBio = hasLongBio && !isBioExpanded && activeTab === "overview";
const displayBio = shouldTruncateBio && author.bio
? `${author.bio.substring(0, bioLength)}...`
: author.bio;
// Handle follow button click
const handleFollowClick = () => {
const newFollowState = !isFollowed;
setIsFollowed(newFollowState);
onFollow?.(author, newFollowState);
};
// Handle share button click
const handleShareClick = () => {
onShare?.(author);
};
// Handle edit button click
const handleEditClick = () => {
onEdit?.(author);
};
// Handle bio toggle
const toggleBio = () => {
setIsBioExpanded(!isBioExpanded);
};
return (
<div
className={cn(
authorHeaderVariants({ variant, border, className })
)}
{...props}
>
<div className="container px-4 md:px-6">
<div className="flex flex-col gap-6">
<div className="flex flex-col md:flex-row gap-6 md:items-start">
{/* Author portrait */}
<div className="flex-shrink-0">
<Avatar
className={cn(
"rounded-lg border bg-muted",
variant === "compact" || variant === "minimal"
? "h-20 w-20"
: "h-28 w-28 md:h-36 md:w-36",
author.isFeatured && "border-2 border-primary"
)}
>
<AvatarImage
src={author.avatar}
alt={author.name}
/>
<AvatarFallback className="text-2xl md:text-3xl font-serif">
{author.name.split(' ').map(n => n[0]).join('').substring(0, 2)}
</AvatarFallback>
</Avatar>
</div>
{/* Author info */}
<div className="flex-1 space-y-4">
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4">
<div className="space-y-2 max-w-prose">
{/* Author name and featured badge */}
<div className="flex items-start gap-2">
<h1 className={cn(
"font-serif font-bold tracking-tight",
variant === "compact" || variant === "minimal"
? "text-2xl"
: "text-3xl md:text-4xl"
)}>
{author.name}
</h1>
{author.isFeatured && (
<Badge variant="default" className="mt-1.5">
Featured
</Badge>
)}
</div>
{/* Author metadata */}
<div className="flex flex-wrap items-center gap-x-4 gap-y-1 text-muted-foreground">
{author.era && (
<div className="flex items-center gap-1.5">
<Calendar className="h-4 w-4" />
<span>{author.era}</span>
</div>
)}
{lifespan && (
<div className="flex items-center gap-1.5">
<Clock className="h-4 w-4" />
<span>{lifespan}</span>
</div>
)}
{author.nationality && (
<div className="flex items-center gap-1.5">
<Globe className="h-4 w-4" />
<span>{author.nationality}</span>
</div>
)}
{author.location && (
<div className="flex items-center gap-1.5">
<MapPin className="h-4 w-4" />
<span>{author.location}</span>
</div>
)}
</div>
{/* Author genres */}
{author.genres && author.genres.length > 0 && variant !== "minimal" && (
<div className="flex flex-wrap gap-1.5 pt-1">
{author.genres.slice(0, maxGenres).map((genre, index) => (
<Badge key={index} variant="secondary" className="px-2 py-0.5">
{genre}
</Badge>
))}
{author.genres.length > maxGenres && (
<Badge variant="outline" className="px-2 py-0.5">
+{author.genres.length - maxGenres} more
</Badge>
)}
</div>
)}
</div>
{/* Stats and actions */}
{(showActions || (showWorksCount && typeof author.works === 'number')) && (
<div className="flex flex-col gap-2 md:items-end">
{/* Desktop actions */}
{showActions && variant !== "minimal" && (
<div className="hidden md:flex items-center gap-2">
{showFollowButton && (
<Button
variant={isFollowed ? "default" : "outline"}
size="default"
onClick={handleFollowClick}
className="gap-1.5"
>
<Users className="h-4 w-4" />
{isFollowed ? "Following" : "Follow"}
</Button>
)}
{canEdit && (
<Button
variant="outline"
size="default"
onClick={handleEditClick}
className="gap-1.5"
>
<Edit className="h-4 w-4" />
Edit
</Button>
)}
{showShareButton && (
<Button
variant="outline"
size="icon"
onClick={handleShareClick}
>
<Share2 className="h-4 w-4" />
<span className="sr-only">Share</span>
</Button>
)}
{author.url && (
<Button
variant="outline"
size="icon"
onClick={() => window.open(author.url, '_blank')}
>
<ExternalLink className="h-4 w-4" />
<span className="sr-only">External link</span>
</Button>
)}
</div>
)}
{/* Stats */}
<div className="flex items-center gap-6 text-muted-foreground">
<TooltipProvider>
{typeof author.works === 'number' && showWorksCount && (
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-center gap-1.5">
<BookOpen className="h-4 w-4" />
<span className="font-medium">{author.works}</span>
<span className="hidden sm:inline text-sm">works</span>
</div>
</TooltipTrigger>
<TooltipContent>
<p>{author.works} literary works</p>
</TooltipContent>
</Tooltip>
)}
{typeof author.followers === 'number' && (
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-center gap-1.5">
<Users className="h-4 w-4" />
<span className="font-medium">{author.followers}</span>
<span className="hidden sm:inline text-sm">followers</span>
</div>
</TooltipTrigger>
<TooltipContent>
<p>{author.followers} followers</p>
</TooltipContent>
</Tooltip>
)}
{author.stats?.likes && (
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-center gap-1.5">
<Heart className="h-4 w-4" />
<span className="font-medium">{author.stats.likes}</span>
</div>
</TooltipTrigger>
<TooltipContent>
<p>{author.stats.likes} total likes across all works</p>
</TooltipContent>
</Tooltip>
)}
</TooltipProvider>
</div>
{/* Mobile actions */}
{showActions && variant !== "minimal" && (
<div className="flex md:hidden items-center gap-2 mt-2">
{showFollowButton && (
<Button
variant={isFollowed ? "default" : "outline"}
size="sm"
onClick={handleFollowClick}
className="gap-1"
>
<Users className="h-4 w-4" />
{isFollowed ? "Following" : "Follow"}
</Button>
)}
{canEdit && (
<Button
variant="outline"
size="sm"
onClick={handleEditClick}
className="gap-1"
>
<Edit className="h-4 w-4" />
Edit
</Button>
)}
{showShareButton && (
<Button
variant="outline"
size="icon"
className="h-8 w-8"
onClick={handleShareClick}
>
<Share2 className="h-3.5 w-3.5" />
</Button>
)}
</div>
)}
</div>
)}
</div>
</div>
</div>
{/* Tabs navigation for detailed view */}
{variant === "detailed" && (
<Tabs
defaultValue="overview"
className="w-full"
onValueChange={setActiveTab}
>
<TabsList className="mb-4">
<TabsTrigger value="overview">Overview</TabsTrigger>
{timelineEvents && timelineEvents.length > 0 && (
<TabsTrigger value="timeline">Timeline</TabsTrigger>
)}
{author.influences && author.influences.length > 0 && (
<TabsTrigger value="influences">Influences</TabsTrigger>
)}
<TabsTrigger value="works">Works</TabsTrigger>
</TabsList>
<TabsContent value="overview" className="space-y-4">
{/* Author bio */}
{displayBio && (
<div className="space-y-2 max-w-3xl">
<p className="text-base text-muted-foreground leading-relaxed">
{displayBio}
</p>
{hasLongBio && (
<Button
variant="ghost"
size="sm"
className="h-8 px-2 -ml-2"
onClick={toggleBio}
>
{isBioExpanded ? (
<span className="flex items-center gap-1">
Show less <ChevronUp className="h-3.5 w-3.5" />
</span>
) : (
<span className="flex items-center gap-1">
Read more <ChevronDown className="h-3.5 w-3.5" />
</span>
)}
</Button>
)}
</div>
)}
{/* Quick facts section */}
{variant === "detailed" && (
<div className="bg-muted/30 rounded-lg p-4 max-w-3xl">
<h3 className="text-sm font-medium mb-3 flex items-center gap-2">
<Info className="h-4 w-4" />
Quick Facts
</h3>
<div className="grid sm:grid-cols-2 gap-4">
{author.nationality && (
<div>
<p className="text-xs text-muted-foreground">Nationality</p>
<p className="text-sm font-medium">{author.nationality}</p>
</div>
)}
{author.birthYear && (
<div>
<p className="text-xs text-muted-foreground">Born</p>
<p className="text-sm font-medium">{author.birthYear}{author.location ? `, ${author.location}` : ''}</p>
</div>
)}
{author.deathYear && (
<div>
<p className="text-xs text-muted-foreground">Died</p>
<p className="text-sm font-medium">{author.deathYear}</p>
</div>
)}
{author.era && (
<div>
<p className="text-xs text-muted-foreground">Literary Era</p>
<p className="text-sm font-medium">{author.era}</p>
</div>
)}
{author.genres && author.genres.length > 0 && (
<div className="sm:col-span-2">
<p className="text-xs text-muted-foreground">Notable Genres</p>
<div className="flex flex-wrap gap-1 mt-1">
{author.genres.map((genre, i) => (
<Badge key={i} variant="secondary" className="text-xs">
{genre}
</Badge>
))}
</div>
</div>
)}
</div>
</div>
)}
</TabsContent>
{timelineEvents && timelineEvents.length > 0 && (
<TabsContent value="timeline">
<div className="py-2">
{timelineEvents.length > 0 ? (
<div className="relative ml-4">
{/* Timeline line */}
<div className="absolute left-4 top-0 bottom-0 w-0.5 bg-muted-foreground/20"></div>
{/* Events */}
<div className="space-y-6">
{timelineEvents
.sort((a, b) => a.year - b.year)
.map((event) => (
<div key={event.id} className="relative flex items-start gap-6 ml-4">
{/* Year indicator */}
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-background border border-border flex items-center justify-center z-10 -ml-8">
<Calendar className="h-4 w-4 text-muted-foreground" />
</div>
{/* Event details */}
<div className="flex-1 bg-muted/20 p-4 rounded-lg">
<div className="flex justify-between items-start mb-1">
<h3 className="font-medium">
{event.title}
</h3>
<span className="text-sm text-muted-foreground font-mono">
{event.year}
</span>
</div>
{event.description && (
<p className="text-sm text-muted-foreground">
{event.description}
</p>
)}
</div>
</div>
))}
</div>
</div>
) : (
<div className="text-center py-8 text-muted-foreground">
No timeline events available.
</div>
)}
</div>
</TabsContent>
)}
{author.influences && author.influences.length > 0 && (
<TabsContent value="influences">
<div className="py-2 space-y-4">
<h3 className="text-lg font-medium">Literary Influences</h3>
<p className="text-muted-foreground max-w-3xl">
The authors and thinkers who shaped {author.name}'s writing style,
philosophy, and literary approach.
</p>
<div className="flex flex-wrap gap-2 mt-2">
{author.influences.map((influence, i) => (
<Badge
key={i}
variant="outline"
className="px-3 py-1 text-sm"
>
{influence}
</Badge>
))}
</div>
</div>
</TabsContent>
)}
<TabsContent value="works">
<div className="py-2 text-center text-muted-foreground">
Works will be loaded here. This tab serves as a placeholder for the works listing.
</div>
</TabsContent>
</Tabs>
)}
</div>
</div>
</div>
);
}
export default AuthorHeader;