'use client'; import React, { useState, useEffect, useRef } from 'react'; import { useSearchParams } from 'next/navigation'; import { motion, AnimatePresence } from 'framer-motion'; import { ArrowLeft, Save, Eye, Plus, X, Bold, Italic, Code, Image, Link, Type, List, ListOrdered, Quote, Hash, Loader2, Upload, Check } from 'lucide-react'; interface Project { id: string; title: string; description: string; content?: string; category: string; difficulty?: string; tags?: string[]; featured: boolean; published: boolean; github?: string; live?: string; image?: string; createdAt: string; updatedAt: string; } export default function EditorPage() { const searchParams = useSearchParams(); const projectId = searchParams.get('id'); const contentRef = useRef(null); const [project, setProject] = useState(null); const [isAuthenticated, setIsAuthenticated] = useState(false); const [isLoading, setIsLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); const [isCreating, setIsCreating] = useState(!projectId); const [showPreview, setShowPreview] = useState(false); // Form state const [formData, setFormData] = useState({ title: '', description: '', content: '', category: 'web', difficulty: 'beginner', tags: [] as string[], featured: false, published: false, github: '', live: '', image: '' }); // Check authentication and load project useEffect(() => { const init = async () => { try { // Check auth const authStatus = sessionStorage.getItem('admin_authenticated'); const sessionToken = sessionStorage.getItem('admin_session_token'); console.log('Editor Auth check:', { authStatus, hasSessionToken: !!sessionToken, projectId }); if (authStatus === 'true' && sessionToken) { console.log('User is authenticated'); setIsAuthenticated(true); // Load project if editing if (projectId) { console.log('Loading project with ID:', projectId); await loadProject(projectId); } else { console.log('Creating new project'); setIsCreating(true); } } else { console.log('User not authenticated'); setIsAuthenticated(false); } } catch (error) { console.error('Error in init:', error); setIsAuthenticated(false); } finally { setIsLoading(false); } }; init(); }, [projectId]); const loadProject = async (id: string) => { try { console.log('Fetching projects...'); const response = await fetch('/api/projects'); if (response.ok) { const data = await response.json(); console.log('Projects loaded:', data); const foundProject = data.projects.find((p: Project) => p.id.toString() === id); console.log('Found project:', foundProject); if (foundProject) { setProject(foundProject); setFormData({ title: foundProject.title || '', description: foundProject.description || '', content: foundProject.content || '', category: foundProject.category || 'web', difficulty: foundProject.difficulty || 'beginner', tags: foundProject.tags || [], featured: foundProject.featured || false, published: foundProject.published || false, github: foundProject.github || '', live: foundProject.live || '', image: foundProject.image || '' }); console.log('Form data set:', formData); } else { console.log('Project not found with ID:', id); } } else { console.error('Failed to fetch projects:', response.status); } } catch (error) { console.error('Error loading project:', error); } }; const handleSave = async () => { try { setIsSaving(true); const url = projectId ? `/api/projects/${projectId}` : '/api/projects'; const method = projectId ? 'PUT' : 'POST'; console.log('Saving project:', { url, method, formData }); const response = await fetch(url, { method, headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(formData) }); if (response.ok) { const savedProject = await response.json(); console.log('Project saved:', savedProject); // Show success and redirect setTimeout(() => { window.location.href = '/manage'; }, 1000); } else { console.error('Error saving project:', response.status); alert('Error saving project'); } } catch (error) { console.error('Error saving project:', error); alert('Error saving project'); } finally { setIsSaving(false); } }; const handleInputChange = (field: string, value: any) => { setFormData(prev => ({ ...prev, [field]: value })); }; const handleTagsChange = (tagsString: string) => { const tags = tagsString.split(',').map(tag => tag.trim()).filter(tag => tag); setFormData(prev => ({ ...prev, tags })); }; // Rich text editor functions const insertFormatting = (format: string) => { const content = contentRef.current; if (!content) return; const selection = window.getSelection(); if (!selection || selection.rangeCount === 0) return; const range = selection.getRangeAt(0); let newText = ''; switch (format) { case 'bold': newText = `**${selection.toString() || 'bold text'}**`; break; case 'italic': newText = `*${selection.toString() || 'italic text'}*`; break; case 'code': newText = `\`${selection.toString() || 'code'}\``; break; case 'h1': newText = `# ${selection.toString() || 'Heading 1'}`; break; case 'h2': newText = `## ${selection.toString() || 'Heading 2'}`; break; case 'h3': newText = `### ${selection.toString() || 'Heading 3'}`; break; case 'list': newText = `- ${selection.toString() || 'List item'}`; break; case 'orderedList': newText = `1. ${selection.toString() || 'List item'}`; break; case 'quote': newText = `> ${selection.toString() || 'Quote'}`; break; case 'link': const url = prompt('Enter URL:'); if (url) { newText = `[${selection.toString() || 'link text'}](${url})`; } break; case 'image': const imageUrl = prompt('Enter image URL:'); if (imageUrl) { newText = `![${selection.toString() || 'alt text'}](${imageUrl})`; } break; } if (newText) { range.deleteContents(); range.insertNode(document.createTextNode(newText)); // Update form data setFormData(prev => ({ ...prev, content: content.textContent || '' })); } }; if (isLoading) { return (

Loading editor...

); } if (!isAuthenticated) { return (

Access Denied

You need to be logged in to access the editor.

); } return (
{/* Header */}

{isCreating ? 'Create New Project' : `Edit: ${formData.title || 'Untitled'}`}

{/* Editor Content */}
{/* Main Editor */}
{/* Project Title */} handleInputChange('title', e.target.value)} className="w-full text-3xl font-bold bg-white/10 text-white placeholder-white/50 focus:outline-none p-4 rounded-lg border border-white/20 focus:ring-2 focus:ring-blue-500" placeholder="Enter project title..." /> {/* Rich Text Toolbar */}
{/* Content Editor */}

Content

{ const target = e.target as HTMLDivElement; setFormData(prev => ({ ...prev, content: target.textContent || '' })); }} suppressContentEditableWarning={true} > {formData.content || 'Start writing your project content...'}

Supports Markdown formatting. Use the toolbar above or type directly.

{/* Description */}

Description