diff --git a/COMPONENT-IMPLEMENTATION-TRACKER.md b/COMPONENT-IMPLEMENTATION-TRACKER.md index f42140c..3070cb3 100644 --- a/COMPONENT-IMPLEMENTATION-TRACKER.md +++ b/COMPONENT-IMPLEMENTATION-TRACKER.md @@ -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**: diff --git a/TODO.md b/TODO.md index b9692c2..f432af0 100644 --- a/TODO.md +++ b/TODO.md @@ -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 diff --git a/client/src/components/authors/author-header.tsx b/client/src/components/authors/author-header.tsx index e69de29..d7bf6ed 100644 --- a/client/src/components/authors/author-header.tsx +++ b/client/src/components/authors/author-header.tsx @@ -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 + * 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, + VariantProps { + /** + * 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("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 ( +
+
+
+
+ {/* Author portrait */} +
+ + + + {author.name.split(' ').map(n => n[0]).join('').substring(0, 2)} + + +
+ + {/* Author info */} +
+
+
+ {/* Author name and featured badge */} +
+

+ {author.name} +

+ + {author.isFeatured && ( + + Featured + + )} +
+ + {/* Author metadata */} +
+ {author.era && ( +
+ + {author.era} +
+ )} + + {lifespan && ( +
+ + {lifespan} +
+ )} + + {author.nationality && ( +
+ + {author.nationality} +
+ )} + + {author.location && ( +
+ + {author.location} +
+ )} +
+ + {/* Author genres */} + {author.genres && author.genres.length > 0 && variant !== "minimal" && ( +
+ {author.genres.slice(0, maxGenres).map((genre, index) => ( + + {genre} + + ))} + + {author.genres.length > maxGenres && ( + + +{author.genres.length - maxGenres} more + + )} +
+ )} +
+ + {/* Stats and actions */} + {(showActions || (showWorksCount && typeof author.works === 'number')) && ( +
+ {/* Desktop actions */} + {showActions && variant !== "minimal" && ( +
+ {showFollowButton && ( + + )} + + {canEdit && ( + + )} + + {showShareButton && ( + + )} + + {author.url && ( + + )} +
+ )} + + {/* Stats */} +
+ + {typeof author.works === 'number' && showWorksCount && ( + + +
+ + {author.works} + works +
+
+ +

{author.works} literary works

+
+
+ )} + + {typeof author.followers === 'number' && ( + + +
+ + {author.followers} + followers +
+
+ +

{author.followers} followers

+
+
+ )} + + {author.stats?.likes && ( + + +
+ + {author.stats.likes} +
+
+ +

{author.stats.likes} total likes across all works

+
+
+ )} +
+
+ + {/* Mobile actions */} + {showActions && variant !== "minimal" && ( +
+ {showFollowButton && ( + + )} + + {canEdit && ( + + )} + + {showShareButton && ( + + )} +
+ )} +
+ )} +
+
+
+ + {/* Tabs navigation for detailed view */} + {variant === "detailed" && ( + + + Overview + {timelineEvents && timelineEvents.length > 0 && ( + Timeline + )} + {author.influences && author.influences.length > 0 && ( + Influences + )} + Works + + + + {/* Author bio */} + {displayBio && ( +
+

+ {displayBio} +

+ + {hasLongBio && ( + + )} +
+ )} + + {/* Quick facts section */} + {variant === "detailed" && ( +
+

+ + Quick Facts +

+
+ {author.nationality && ( +
+

Nationality

+

{author.nationality}

+
+ )} + {author.birthYear && ( +
+

Born

+

{author.birthYear}{author.location ? `, ${author.location}` : ''}

+
+ )} + {author.deathYear && ( +
+

Died

+

{author.deathYear}

+
+ )} + {author.era && ( +
+

Literary Era

+

{author.era}

+
+ )} + {author.genres && author.genres.length > 0 && ( +
+

Notable Genres

+
+ {author.genres.map((genre, i) => ( + + {genre} + + ))} +
+
+ )} +
+
+ )} +
+ + {timelineEvents && timelineEvents.length > 0 && ( + +
+ {timelineEvents.length > 0 ? ( +
+ {/* Timeline line */} +
+ + {/* Events */} +
+ {timelineEvents + .sort((a, b) => a.year - b.year) + .map((event) => ( +
+ {/* Year indicator */} +
+ +
+ + {/* Event details */} +
+
+

+ {event.title} +

+ + {event.year} + +
+ {event.description && ( +

+ {event.description} +

+ )} +
+
+ ))} +
+
+ ) : ( +
+ No timeline events available. +
+ )} +
+
+ )} + + {author.influences && author.influences.length > 0 && ( + +
+

Literary Influences

+

+ The authors and thinkers who shaped {author.name}'s writing style, + philosophy, and literary approach. +

+
+ {author.influences.map((influence, i) => ( + + {influence} + + ))} +
+
+
+ )} + + +
+ Works will be loaded here. This tab serves as a placeholder for the works listing. +
+
+
+ )} +
+
+
+ ); +} + +export default AuthorHeader; \ No newline at end of file