'use client'; import React, { useState, useEffect, useRef, useCallback } from 'react'; import { createPortal } from 'react-dom'; import Link from 'next/link'; import { usePathname, useRouter } from 'next/navigation'; import { Document, Page, pdfjs } from 'react-pdf'; import { Home, User, FileCheck2, PenTool, BookOpen, Mail, Users, LogOut, FileText, Clock, Calendar, HelpCircle, ArrowRight, FlaskConical, X, ZoomIn, ZoomOut, ImageIcon, Search, Book, ChevronDown, ChevronLeft, ChevronRight, ExternalLink, Sparkles, Bell, CheckCircle2, } from 'lucide-react'; import 'react-pdf/dist/Page/TextLayer.css'; import 'react-pdf/dist/Page/AnnotationLayer.css'; pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`; // Base URL for publications redirection const PUBLICATIONS_BASE_URL = 'https://ichai.net'; export interface Category { id: string; name: string; } // Default standard domains matching focus areas and slugs const DEFAULT_RESEARCH_FIELDS: Category[] = [ { id: 'ai_ethics', name: 'AI Ethics & Responsible AI' }, { id: 'digital_wellbeing', name: 'Digital Wellbeing' }, { id: 'online_safety', name: 'Online Safety' }, { id: 'education', name: 'Education & Learning' }, { id: 'psychology', name: 'Psychology & Behaviour' }, { id: 'child_dev', name: 'Child Development' }, { id: 'big_tech', name: 'Big Tech & Responsible AI Governance' }, { id: 'neuroscience', name: 'Neuroscience & Attention' }, { id: 'public_policy', name: 'Public Policy & Regulation' }, { id: 'machine_learning_safety', name: 'Machine Learning Safety & Alignment' }, { id: 'human_computer_interaction', name: 'Human-Computer Interaction (HCI)' }, ]; /** * Mapping the PDF section headings to your exact DEFAULT_RESEARCH_FIELDS category IDs */ const PDF_HEADING_TO_CATEGORY_ID: Record = { 'digital discipline': 'digital_wellbeing', 'self-regulation': 'digital_wellbeing', 'digital wellbeing': 'digital_wellbeing', 'social media': 'psychology', 'digital behaviour': 'psychology', 'digital behavior': 'psychology', 'children, young people': 'child_dev', 'young people & technology': 'child_dev', 'online safety': 'online_safety', 'artificial intelligence & human behaviour': 'machine_learning_safety', 'artificial intelligence & human behavior': 'machine_learning_safety', 'psychology, neuroscience': 'neuroscience', 'neuroscience & attention': 'neuroscience', 'human-aligned intelligence': 'ai_ethics', 'responsible ai': 'ai_ethics', 'ai ethics': 'ai_ethics', 'policy, governance': 'public_policy', 'public policy': 'public_policy', 'governance & standards': 'big_tech', }; function extractCategorySlugFromHref(urlStr: string): string | null { try { const parsed = new URL(urlStr, 'https://dummy.local'); const cat = parsed.searchParams.get('category'); if (cat) return cat.trim(); const match = urlStr.match(/category[=/]([a-zA-Z0-9_-]+)/i); if (match && match[1]) return match[1].trim(); } catch { const match = urlStr.match(/category[=/]([a-zA-Z0-9_-]+)/i); if (match && match[1]) return match[1].trim(); } return null; } function detectCategoryFromElement(targetEl: HTMLElement): string | null { const pageContainer = targetEl.closest('.react-pdf__Page') || targetEl.closest('.textLayer'); if (!pageContainer) return null; const allSpans = Array.from(pageContainer.querySelectorAll('.textLayer span')); const clickedIdx = allSpans.findIndex((s) => s === targetEl || s.contains(targetEl)); const searchSpans = clickedIdx !== -1 ? allSpans.slice(0, clickedIdx + 1).reverse() : allSpans.reverse(); for (const span of searchSpans) { const text = (span.textContent || '').trim().toLowerCase(); if (!text) continue; for (const field of DEFAULT_RESEARCH_FIELDS) { if (text.includes(field.id) || text.includes(field.name.toLowerCase())) { return field.id; } } for (const [key, categoryId] of Object.entries(PDF_HEADING_TO_CATEGORY_ID)) { if (text.includes(key)) { return categoryId; } } } return null; } interface PublicationRouteItem { title: string; path: string; } const PUBLICATION_LINKS: PublicationRouteItem[] = [ { title: 'Overview', path: '/publications/' }, { title: 'Policy Papers', path: '/publications/policy-papers/' }, { title: 'Advisory Notes', path: '/publications/advisory-notes/' }, { title: 'Discussions Papers', path: '/publications/discussion-papers/' }, { title: 'Interpretive Guidelines', path: '/publications/interpretive-guidance/' }, ]; interface KnowledgeQuestion { id?: number; title: string; page: number; illustrationImage?: string; hasIllustration?: boolean; } interface KnowledgeCategory { category: string; questions: KnowledgeQuestion[]; } interface NavItem { label: string; href: string; icon: React.ElementType; badge?: number; action?: 'pdf' | 'knowledge_guide' | 'coming_soon'; pdfUrl?: string; pdfTitle?: string; illustrationImage?: string; onSubmitRedirect?: string; } interface PdfModalProps { pdfUrl: string; title: string; illustrationImage?: string; onSubmitRedirect?: string; onOpenKnowledgeGuide?: () => void; onOpenPdf?: (url: string, title: string) => void; onClose: () => void; } const KNOWLEDGE_BASE: KnowledgeCategory[] = [ { category: '1. Getting Started', questions: [ { id: 1, title: 'What is ICHAI?', page: 1 }, { id: 2, title: 'Why Was ICHAI Created?', page: 2 }, { id: 3, title: 'What is Human-Aligned Intelligence?', page: 7 }, { id: 4, title: 'What is Digital Discipline?', page: 13 }, { id: 5, title: 'What is the purpose of ICHAI?', page: 20 }, { id: 6, title: 'Who can register with ICHAI?', page: 21 }, { id: 7, title: 'Is ICHAI available worldwide?', page: 21 }, { id: 8, title: 'How do I create an account?', page: 22, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/8.webp' }, { id: 9, title: 'Is registration free?', page: 22 }, { id: 10, title: 'How do I verify my email address?', page: 23, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/10.webp' }, { id: 11, title: 'What happens after registration?', page: 24, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/11.webp' }, { id: 12, title: 'Can I register multiple organisations?', page: 25, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/12.webp' }, { id: 13, title: 'Can individuals register?', page: 25, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/13.webp' }, { id: 14, title: 'Which browsers are supported?', page: 26 }, { id: 15, title: 'Is there an ICHAI mobile app?', page: 26 }, ], }, { category: '2. Registering Your Organisation', questions: [ { id: 16, title: 'Which organisation types can register?', page: 27, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/16.webp' }, { id: 17, title: 'What sectors are supported?', page: 28, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/17.webp' }, { id: 18, title: 'What documents are required?', page: 29, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/18.webp' }, { id: 19, title: 'How long does verification take?', page: 29 }, { id: 20, title: 'Why was my organisation not approved?', page: 30 }, { id: 21, title: 'Can I edit my organisation profile?', page: 32, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/21.webp' }, { id: 22, title: 'Can I change organisation details later?', page: 33, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/22.webp' }, { id: 23, title: 'Can I upload my organisation logo?', page: 34, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/23.webp' }, { id: 24, title: 'Can I register multiple branches?', page: 35, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/24.webp' }, { id: 25, title: 'Can one organisation have multiple administrators?', page: 36, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/25.webp' }, ], }, { category: '3. Verification & Secure Status', questions: [ { id: 26, title: 'What does "Verified & Secured" mean?', page: 36, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/26.webp' }, { id: 27, title: 'How do I become verified?', page: 39, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/27.webp' }, { id: 28, title: 'What are the benefits of verification?', page: 39 }, { id: 29, title: 'Does verification expire?', page: 39 }, { id: 30, title: 'How do I renew verification?', page: 41, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/30.webp' }, { id: 31, title: 'Can verification be revoked?', page: 41 }, { id: 32, title: 'How do people verify an organisation?', page: 43, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/32.webp' }, { id: 33, title: 'What is the verification badge?', page: 44, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/33.webp' }, { id: 34, title: 'Can parents verify schools?', page: 45, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/34.webp' }, { id: 35, title: 'Can employers, clients and partners verify companies?', page: 45, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/35.webp' }, ], }, { category: '4. Anti-SMUB Testâ„¢', questions: [ { id: 36, title: 'What is the Anti-SMUB Testâ„¢?', page: 47, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/36.webp' }, { id: 37, title: 'What does SMUB mean?', page: 48, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/37.webp' }, { id: 38, title: 'Who should take the test?', page: 49, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/38.webp' }, { id: 39, title: 'Where do you take the test and how long does it take?', page: 50, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/39.webp' }, { id: 40, title: 'Is there a time limit?', page: 51, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/40.webp' }, { id: 41, title: 'Can I pause the assessment?', page: 51, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/41.webp' }, { id: 42, title: 'Can I retake the assessment?', page: 52 }, { id: 43, title: 'How are scores calculated?', page: 53, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/43.webp' }, { id: 44, title: 'What is a good score?', page: 54, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/44.webp' }, { id: 45, title: 'Is the assessment scientifically based?', page: 55, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/45.webp' }, { id: 46, title: 'Can children take it?', page: 56, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/46.webp' }, { id: 47, title: 'Can organisations customise assessments?', page: 56, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/47.webp' }, ], }, { category: '16. Support', questions: [ { id: 222, title: 'How do I contact support?', page: 211, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/222.webp' }, { id: 223, title: 'What are support hours?', page: 212, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/223.webp' }, { id: 224, title: 'How do I submit a ticket?', page: 212, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/224.webp' }, { id: 225, title: 'How do I report a bug?', page: 213, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/225.webp' }, { id: 226, title: 'How do I request a feature?', page: 214, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/226.webp' }, { id: 227, title: 'Where can I find tutorials?', page: 215, hasIllustration: true, illustrationImage: 'https://ichai.net/converted-illustration/227.webp' }, ], }, ]; function parseIllustrationNumber(urlOrStr: string): number | null { if (!urlOrStr) return null; const match = urlOrStr.match(/(\d+)\.webp/i) || urlOrStr.match(/(\d+)$/); return match ? parseInt(match[1], 10) : null; } function findQuestion(target: { id?: number; page?: number; title?: string }) { return KNOWLEDGE_BASE.flatMap((c) => c.questions).find((q) => { if (target.id && q.id === target.id) return true; if (target.page && q.page === target.page) return true; if (target.title && q.title.toLowerCase() === target.title.toLowerCase()) return true; return false; }); } /** * Modern, high-conversion "Coming Soon" Modal for Events & Opportunities */ function ComingSoonModal({ onClose }: { onClose: () => void }) { const [email, setEmail] = useState(''); const [subscribed, setSubscribed] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!email || !email.includes('@')) return; setIsSubmitting(true); // Simulate lightweight opt-in acknowledgment setTimeout(() => { setIsSubmitting(false); setSubscribed(true); }, 600); }; return createPortal(
e.stopPropagation()} > {/* Glow Effects */}
{/* Close Button */} {/* Header Badge */}
Coming Soon
Q4 Focus Initiative
{/* Title & Description */}

Events & Research Opportunities

We are preparing our global roundtable symposiums, peer review summits, and collaborative fellowship calls for contributors and partner institutions.

{/* Feature Preview Cards */}
Symposiums

Quarterly virtual briefings with ethics panels and scholars.

Grants & Calls

Collaborative research openings and publication grants.

{/* Notification Subscription Form */} {/*
{subscribed ? (
You're on the priority list! We will notify you upon launch.
) : (
setEmail(e.target.value)} placeholder="Enter your academic or work email" required className="w-full pl-9 pr-3 py-2.5 bg-slate-900/90 border border-white/10 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:border-blue-500 transition" />
)}
*/}
, document.body ); } function PublicationsListModal({ onClose }: { onClose: () => void }) { const handleRedirect = (path: string) => { const fullUrl = `${PUBLICATIONS_BASE_URL.replace(/\/$/, '')}${path}`; window.open(fullUrl, '_blank', 'noopener,noreferrer'); }; return createPortal(
e.stopPropagation()} >

Publications

{PUBLICATION_LINKS.map((item) => ( ))}
, document.body ); } function PdfViewerModal({ pdfUrl, title, illustrationImage, onSubmitRedirect = '/research-contributor/research/add/', onOpenKnowledgeGuide, onOpenPdf, onClose, }: PdfModalProps) { const router = useRouter(); const [mounted, setMounted] = useState(false); const [numPages, setNumPages] = useState(null); const [pdfScale, setPdfScale] = useState(1.15); const [showIllustration, setShowIllustration] = useState(false); const [showPublicationsPopup, setShowPublicationsPopup] = useState(false); const scrollContainerRef = useRef(null); const isResearchAndPublicationPdf = title.toLowerCase().includes('research & publication') || title.toLowerCase().includes('research and publication') || pdfUrl.toLowerCase().includes('ichai-research-and-publications.pdf'); useEffect(() => { setMounted(true); const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') { if (showPublicationsPopup) { setShowPublicationsPopup(false); } else if (showIllustration) { setShowIllustration(false); } else { onClose(); } } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [showPublicationsPopup, showIllustration, onClose]); useEffect(() => { if (!scrollContainerRef.current) return; const container = scrollContainerRef.current; const highlightActionSpans = () => { const items = container.querySelectorAll('.textLayer span, .annotationLayer a'); items.forEach((item) => { const text = item.textContent?.toLowerCase() || ''; if ( item.tagName.toLowerCase() === 'a' || text.includes('explore') || text.includes('view') || text.includes('browse') || text.includes('submit') || text.includes('contribute') || text.includes('research') || text.includes('knowledge') || text.includes('support') || text.includes('publication') ) { (item as HTMLElement).style.cursor = 'pointer'; } }); }; const observer = new MutationObserver(highlightActionSpans); observer.observe(container, { childList: true, subtree: true }); highlightActionSpans(); return () => observer.disconnect(); }, [numPages, pdfScale]); const handleContainerClick = (e: React.MouseEvent) => { const target = e.target as HTMLElement; const anchor = target.closest('a'); if (anchor && anchor.href) { const href = anchor.href; const explicitCatSlug = extractCategorySlugFromHref(href); if (explicitCatSlug) { e.preventDefault(); e.stopPropagation(); onClose(); if (href.includes('/add') || href.includes('/add/') || href.includes('contribute')) { router.push(`/research-contributor/research/add/?category=${encodeURIComponent(explicitCatSlug)}`); } else { router.push(`/research-contributor/research/?category=${encodeURIComponent(explicitCatSlug)}`); } return; } } let combinedText = (target.textContent || '').trim(); if (target.parentElement) { combinedText += ' ' + (target.parentElement.textContent || ''); } const upper = combinedText.toUpperCase().replace(/\s+/g, ' '); if ( isResearchAndPublicationPdf && (upper.includes('VIEW PUBLICATIONS') || upper.includes('VIEW PUBLICATION') || upper.includes('PUBLICATIONS LIST')) ) { e.preventDefault(); e.stopPropagation(); setShowPublicationsPopup(true); return; } if ( upper.includes('EXPLORE RELATED RESEARCH') || upper.includes('EXPLORE RESEARCH') || upper.includes('VIEW RESEARCH') ) { e.preventDefault(); e.stopPropagation(); const detectedCatId = detectCategoryFromElement(target); const queryParam = detectedCatId ? `?category=${encodeURIComponent(detectedCatId)}` : ''; onClose(); router.push(`/research-contributor/research/${queryParam}`); return; } if ( upper.includes('CONTRIBUTE RESEARCH') || upper.includes('CONTRIBUTE TO THE LIBRARY') || upper.includes('SUBMIT RESEARCH') ) { e.preventDefault(); e.stopPropagation(); const detectedCatId = detectCategoryFromElement(target); const baseSubmit = onSubmitRedirect || '/research-contributor/research/add/'; const queryParam = detectedCatId ? `?category=${encodeURIComponent(detectedCatId)}` : ''; onClose(); router.push(`${baseSubmit.replace(/\/$/, '')}/${queryParam}`); return; } if ( upper.includes('VISIT THE KNOWLEDGE CENTRE') || upper.includes('HELP & SUPPORT') || upper.includes('KNOWLEDGE CENTRE') ) { if (onOpenKnowledgeGuide) { e.preventDefault(); e.stopPropagation(); onOpenKnowledgeGuide(); return; } } if (upper.includes('EXPLORE RESEARCH & PUBLICATIONS') || (upper.includes('EXPLORE') && upper.includes('PUBLICATIONS'))) { if (onOpenPdf) { e.preventDefault(); e.stopPropagation(); onOpenPdf( '/documents/contributor/ichai-research-and-publications.pdf', 'ICHAI Research & Publications' ); return; } } if (upper.includes('EXPLORE DIGITAL DISCIPLINE') || upper.includes('DIGITAL DISCIPLINEL') || upper.includes('DIGITAL DISCIPLINE')) { if (onOpenPdf) { e.preventDefault(); e.stopPropagation(); onOpenPdf( '/documents/contributor/ichai-digital-discipline.pdf', 'ICHAI Digital Discipline Framework' ); return; } } if (upper.includes('EXPLORE ANTI-SMUB') || upper.includes('ANTI-SMUB')) { if (onOpenPdf) { e.preventDefault(); e.stopPropagation(); onOpenPdf( '/documents/contributor/ichai-anti-smub.pdf', 'Anti-SMUB Assessment' ); return; } } if (upper.includes('EXPLORE HUMAN-ALIGNED INTELLIGENCE') || upper.includes('HUMAN-ALIGNED INTELLIGENCE')) { if (onOpenPdf) { e.preventDefault(); e.stopPropagation(); onOpenPdf( '/documents/contributor/ichai-human-aligned-intelligence.pdf', 'Human-Aligned Intelligence' ); return; } } if (upper.includes('EXPLORE POLICY & STANDARDS') || upper.includes('POLICY & STANDARDS')) { if (onOpenPdf) { e.preventDefault(); e.stopPropagation(); onOpenPdf( '/documents/contributor/ichai-policy-and-standards.pdf', 'Policy & Standards' ); return; } } if (upper.includes('VIEW RESEARCH TOOLS') || upper.includes('RESEARCH TOOLS')) { if (onOpenPdf) { e.preventDefault(); e.stopPropagation(); onOpenPdf( '/documents/contributor/ichai-research-tools.pdf', 'Research Tools & Templates' ); return; } } if (upper.includes('BROWSE RECOMMENDED RESOURCES') || upper.includes('RECOMMENDED RESOURCES')) { if (onOpenPdf) { e.preventDefault(); e.stopPropagation(); onOpenPdf( '/documents/contributor/ichai-recommended-resources.pdf', 'Recommended External Resources' ); return; } } }; if (!mounted) return null; return createPortal(
e.stopPropagation()} >

{title}

{isResearchAndPublicationPdf && ( )} {illustrationImage && ( )}
{Math.round(pdfScale * 100)}%
setNumPages(pagesCount)} loading={
Loading document...
} error={
Failed to load PDF document.
} className="flex flex-col items-center gap-6 w-full" > {numPages && Array.from(new Array(numPages), (_, index) => (
))}
{showPublicationsPopup && ( setShowPublicationsPopup(false)} /> )} {showIllustration && illustrationImage && (
setShowIllustration(false)} >
e.stopPropagation()} >

Research Submission Process Illustration

Research Submission Process
)}
, document.body ); } function KnowledgeGuideModal({ pdfUrl, onClose, }: { pdfUrl: string; onClose: () => void; }) { const [mounted, setMounted] = useState(false); const [pdfDocument, setPdfDocument] = useState(null); const [numPages, setNumPages] = useState(null); const [pageNumber, setPageNumber] = useState(1); const [pdfScale, setPdfScale] = useState(1.0); const [searchQuery, setSearchQuery] = useState(''); const [openCategories, setOpenCategories] = useState>({ '1. Getting Started': true, }); const [activeQuestionTitle, setActiveQuestionTitle] = useState('What is ICHAI?'); const [illustrationModalOpen, setIllustrationModalOpen] = useState(false); const [currentIllustrationSrc, setCurrentIllustrationSrc] = useState(null); const [currentIllustrationTitle, setCurrentIllustrationTitle] = useState(''); const [currentIllustrationSubtitle, setCurrentIllustrationSubtitle] = useState(''); const [currentQuestionId, setCurrentQuestionId] = useState(undefined); const pdfContainerRef = useRef(null); const activeItemRef = useRef(null); const ensureCategoryOpen = (page: number, questionTitle?: string) => { const matchedCategory = KNOWLEDGE_BASE.find((cat) => cat.questions.some( (q) => q.page === page || (questionTitle && q.title === questionTitle) ) ); if (matchedCategory) { setOpenCategories((prev) => ({ ...prev, [matchedCategory.category]: true, })); } }; useEffect(() => { setMounted(true); const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') { if (illustrationModalOpen) { setIllustrationModalOpen(false); } else { onClose(); } } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [illustrationModalOpen, onClose]); const safePdfUrl = encodeURI(pdfUrl); const onDocumentLoadSuccess = (pdf: any) => { setPdfDocument(pdf); setNumPages(pdf.numPages); }; const toggleCategory = (catTitle: string) => { setOpenCategories((prev) => ({ ...prev, [catTitle]: !prev[catTitle], })); }; const extractPageIllustrationLink = async (targetPage: number): Promise => { if (!pdfDocument) return null; try { const page = await pdfDocument.getPage(targetPage); const annotations = await page.getAnnotations(); for (const annot of annotations) { if (annot.subtype === 'Link' && annot.url) { return annot.url; } } } catch (err) { console.error('Failed to inspect PDF link annotations:', err); } return null; }; const openIllustration = async (params: { pageNo: number; questionId?: number; title?: string; subtitle?: string; imageSrc?: string; }) => { const { pageNo, questionId, title, subtitle, imageSrc } = params; let finalImageSrc = imageSrc; if (!finalImageSrc) { const extractedUrl = await extractPageIllustrationLink(pageNo); if (extractedUrl) { finalImageSrc = extractedUrl; } } const parsedIdFromSrc = finalImageSrc ? parseIllustrationNumber(finalImageSrc) : null; const foundQuestion = findQuestion({ id: questionId || parsedIdFromSrc || undefined, page: pageNo, title, }); const qId = questionId || parsedIdFromSrc || foundQuestion?.id; const resolvedImageSrc = finalImageSrc || foundQuestion?.illustrationImage || (qId ? `https://ichai.net/converted-illustration/${qId}.webp` : null); const pageTitle = title || (foundQuestion ? `${foundQuestion.id}. ${foundQuestion.title}` : `Page ${pageNo} Illustration`); const pageSubtitle = subtitle || `Visual reference guide from Page ${pageNo} of the Knowledge Centre.`; setCurrentQuestionId(qId || undefined); setCurrentIllustrationTitle(pageTitle); setCurrentIllustrationSubtitle(pageSubtitle); setCurrentIllustrationSrc(resolvedImageSrc); ensureCategoryOpen(pageNo, title); setIllustrationModalOpen(true); }; const handleQuestionClick = (question: KnowledgeQuestion, catName: string) => { setActiveQuestionTitle(question.title); setOpenCategories((prev) => ({ ...prev, [catName]: true })); setPageNumber(question.page); }; const changePage = (offset: number) => { const target = Math.min(Math.max(pageNumber + offset, 1), numPages || 1); setPageNumber(target); ensureCategoryOpen(target); }; const handlePdfContainerClick = async (e: React.MouseEvent) => { const target = e.target as HTMLElement; const anchor = target.closest('a'); const textContent = (target.innerText || target.textContent || '').trim(); if (anchor && anchor.href) { e.preventDefault(); e.stopPropagation(); openIllustration({ pageNo: pageNumber, imageSrc: anchor.href, title: `Page ${pageNumber} Illustration`, }); return; } if ( textContent.toUpperCase().includes('VIEW ILLUSTRATION') || textContent.toUpperCase().includes('ILLUSTRATION') ) { e.preventDefault(); e.stopPropagation(); openIllustration({ pageNo: pageNumber }); } }; const filteredKnowledgeBase = KNOWLEDGE_BASE.map((section) => { const isCatMatch = section.category.toLowerCase().includes(searchQuery.toLowerCase()); const matchedQuestions = section.questions.filter((q) => q.title.toLowerCase().includes(searchQuery.toLowerCase()) ); if (isCatMatch) return section; if (matchedQuestions.length > 0) { return { ...section, questions: matchedQuestions }; } return null; }).filter(Boolean) as typeof KNOWLEDGE_BASE; if (!mounted) return null; return createPortal(

ICHAI Knowledge Centre & User Guide

Complete Handbook & Interactive Documentation

{numPages && (
{pageNumber} / {numPages}
)}
{Math.round(pdfScale * 100)}%
setSearchQuery(e.target.value)} placeholder="Filter chapters & questions..." className="w-full bg-slate-900 border border-white/10 text-white text-xs rounded-xl pl-8 pr-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 placeholder-slate-500 transition" />
{filteredKnowledgeBase.length > 0 ? ( filteredKnowledgeBase.map((sec) => { const isCurrentActiveCat = sec.questions.some( (q) => q.title === activeQuestionTitle || q.page === pageNumber ); const isOpen = openCategories[sec.category] ?? (searchQuery.trim().length > 0 || isCurrentActiveCat); return (
{isOpen && (
{sec.questions.map((q) => { const isSelected = activeQuestionTitle === q.title || pageNumber === q.page; return ( ); })}
)}
); }) ) : (
No matching subjects found for "{searchQuery}".
)}
Loading PDF document...
} error={

Failed to load PDF document.

} >
{illustrationModalOpen && ( { setPageNumber(selectedQ.page); ensureCategoryOpen(selectedQ.page, selectedQ.title); openIllustration({ pageNo: selectedQ.page, questionId: selectedQ.id, title: `${selectedQ.id}. ${selectedQ.title}`, imageSrc: selectedQ.illustrationImage, }); }} onClose={() => setIllustrationModalOpen(false)} /> )}
, document.body ); } function IllustrationImageLightboxModal({ imageSrc, fallbackPdfUrl, pageNumber, questionId, title, subtitle, onSelectQuestion, onClose, }: { imageSrc: string | null; fallbackPdfUrl: string; pageNumber: number; questionId?: number; title: string; subtitle: string; onSelectQuestion: (q: KnowledgeQuestion) => void; onClose: () => void; }) { const [imageError, setImageError] = useState(false); useEffect(() => { setImageError(false); }, [imageSrc, pageNumber, questionId]); const allIllustrationQuestions = KNOWLEDGE_BASE.flatMap((cat) => cat.questions) .filter((q) => q.hasIllustration) .sort((a, b) => (a.id || a.page) - (b.id || b.page)); const currentIndex = allIllustrationQuestions.findIndex( (q) => (questionId && q.id === questionId) || q.page === pageNumber ); const activeIdx = currentIndex === -1 ? 0 : currentIndex; const startIdx = Math.max(0, Math.min(activeIdx - 2, allIllustrationQuestions.length - 6)); const visibleIllustrations = allIllustrationQuestions.slice(startIdx, startIdx + 6); return createPortal(
{questionId && ( Illustration #{questionId} )} Page {pageNumber}

{title}

{subtitle}

{imageSrc && !imageError ? ( {title} setImageError(true)} className="w-full h-auto object-contain max-h-[72vh] rounded-xl" /> ) : (
)}
Related Diagrams: {visibleIllustrations.map((q) => { const isActive = (questionId && q.id === questionId) || q.page === pageNumber; return ( ); })}
, document.body ); } interface ContributorSidebarProps { activeItem?: string; memberId?: string; statusTitle?: string; sinceDate?: string; } export default function ContributorSidebar({ activeItem, memberId: initialMemberId, statusTitle: initialStatusTitle, sinceDate: initialSinceDate, }: ContributorSidebarProps) { const pathname = usePathname(); const router = useRouter(); // Modal states const [activePdfConfig, setActivePdfConfig] = useState<{ url: string; title: string; illustrationImage?: string; redirect?: string; } | null>(null); const [isKnowledgeGuideOpen, setIsKnowledgeGuideOpen] = useState(false); const [isComingSoonOpen, setIsComingSoonOpen] = useState(false); const [memberId, setMemberId] = useState(initialMemberId || ''); const [statusTitle, setStatusTitle] = useState(initialStatusTitle || 'Emerging Research Fellow'); const [sinceDate, setSinceDate] = useState(initialSinceDate || ''); const [unreadMessages, setUnreadMessages] = useState(0); const getAuthToken = useCallback(() => { if (typeof window === 'undefined') return null; return ( localStorage.getItem('contributorToken') || localStorage.getItem('ContributorToken') ); }, []); const fetchContributorDetails = useCallback(async () => { const token = getAuthToken(); if (!token) return; const baseUrl = process.env.NEXT_PUBLIC_API_URL || 'https://api.ichai.net'; const headers = { Accept: 'application/json', Authorization: `Bearer ${token}`, }; try { const meRes = await fetch(`${baseUrl}/contributor/me`, { headers }).catch(() => null); if (meRes && meRes.ok) { const meData = await meRes.json(); const user = meData.user; if (user) { if (user.member_id) setMemberId(user.member_id); if (user.created_at) { const date = new Date(user.created_at); setSinceDate( date.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric', }) ); } const cInfo = user.contributor_info || user.contributorInfo; if (cInfo?.application_status) { const status = cInfo.application_status.toLowerCase(); if (status === 'approved') { setStatusTitle('Verified Research Fellow'); } else if (status === 'pending') { setStatusTitle('Pending Review'); } else { setStatusTitle('Emerging Research Fellow'); } } } } const msgRes = await fetch(`${baseUrl}/contributor/messages`, { headers }).catch(() => null); if (msgRes && msgRes.ok) { const msgData = await msgRes.json(); const messagesList = Array.isArray(msgData) ? msgData : msgData.data || []; const unreadCount = messagesList.filter( (m: any) => m.sender_type === 'admin' && (m.is_read === false || m.is_read === 0) ).length; setUnreadMessages(unreadCount); } } catch (err) { console.warn('Error syncing contributor sidebar data:', err); } }, [getAuthToken]); useEffect(() => { const token = getAuthToken(); if (!token) { router.push('/contributor/login'); return; } fetchContributorDetails(); const interval = setInterval(fetchContributorDetails, 30000); return () => clearInterval(interval); }, [getAuthToken, router, fetchContributorDetails]); const MAIN_MENU: NavItem[] = [ { label: 'Dashboard', href: '/research-contributor', icon: Home }, { label: 'My Profile', href: '/research-contributor/profile', icon: User }, { label: 'My Submissions', href: '/research-contributor/research', icon: FileCheck2 }, { label: 'Submit Research', href: '/research-contributor/research/add', icon: PenTool }, { label: 'My Publications', href: '/research-contributor/publications', icon: BookOpen }, { label: 'Messages', href: '/research-contributor/messages', icon: Mail, badge: unreadMessages }, { label: 'Working Groups', href: '/research-contributor/working-groups', icon: Users }, ]; const RESOURCES_MENU: NavItem[] = [ { label: 'Contributor Guidelines', href: '/research-contributor/guidelines', icon: FileText, action: 'pdf', pdfUrl: '/documents/contributor/ichai-research-contributor-guidelines.pdf', pdfTitle: 'ICHAI Research Contributor Guidelines', illustrationImage: '/illutrations/research-submission-process.webp', onSubmitRedirect: '/research-contributor/research/add/', }, { label: 'ICHAI Resources', href: '/resources', icon: Clock, action: 'pdf', pdfUrl: '/documents/contributor/ichai-resources.pdf', pdfTitle: 'ICHAI Resources', }, { label: 'Events & Opportunities', href: '/events', icon: Calendar, action: 'coming_soon', }, { label: 'Help & Support', href: '/help-centre', icon: HelpCircle, action: 'knowledge_guide', }, ]; const handleActionClick = (item: NavItem, e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); if (item.action === 'coming_soon') { setIsComingSoonOpen(true); return; } if (item.action === 'knowledge_guide') { setActivePdfConfig(null); setIsKnowledgeGuideOpen(true); return; } setIsKnowledgeGuideOpen(false); setActivePdfConfig({ url: item.pdfUrl || '/documents/contributor/ichai-resources.pdf', title: item.pdfTitle || item.label, illustrationImage: item.illustrationImage, redirect: item.onSubmitRedirect, }); }; const handleLogout = async () => { const token = getAuthToken(); if (token) { try { const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'https://api.ichai.net'; await fetch(`${apiUrl}/contributor/logout`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', Authorization: `Bearer ${token}`, }, }); } catch (err) { console.error('Logout error:', err); } } if (typeof window !== 'undefined') { localStorage.removeItem('contributorToken'); localStorage.removeItem('ContributorToken'); localStorage.removeItem('contributionUser'); localStorage.removeItem('ciontributionUser'); localStorage.removeItem('contributorUser'); sessionStorage.removeItem('contributorToken'); sessionStorage.removeItem('ContributorToken'); sessionStorage.removeItem('contributionUser'); sessionStorage.removeItem('ciontributionUser'); document.cookie = 'contributorToken=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; max-age=0'; document.cookie = 'ContributorToken=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; max-age=0'; } router.push('/contributor/login'); }; const isNavActive = (item: NavItem) => { if (activeItem) { return activeItem.toLowerCase() === item.label.toLowerCase(); } if (pathname === item.href) return true; if (item.href === '/research-contributor' && (pathname === '/research-contributor' || pathname === '/')) { return true; } return pathname.startsWith(item.href) && item.href !== '/research-contributor'; }; return ( <> {/* 1. Continuous Scroll PDF Modal (Guidelines / Resources) */} {activePdfConfig && ( { setActivePdfConfig(null); setIsKnowledgeGuideOpen(true); }} onOpenPdf={(url, title) => { setActivePdfConfig({ url, title }); }} onClose={() => setActivePdfConfig(null)} /> )} {/* 2. Interactive Special Knowledge Centre Modal (Help & Support) */} {isKnowledgeGuideOpen && ( setIsKnowledgeGuideOpen(false)} /> )} {/* 3. Modern Coming Soon Modal (Events & Opportunities) */} {isComingSoonOpen && ( setIsComingSoonOpen(false)} /> )} ); }