'use client'; import { useState, useEffect, useRef } from 'react'; import { Dialog, DialogTitle, DialogContent, DialogActions, Button, TextField, FormControl, InputLabel, Select, MenuItem, FormControlLabel, Switch, Box, Typography, Tab, Tabs, Alert, Grid, Paper } from '@mui/material'; import { ImageUpload } from './image-upload'; import { SimpleRichEditor } from './simple-rich-editor'; interface Page { id?: string; title: string; slug: string; content: string; contentType: 'RICH_TEXT' | 'HTML' | 'MARKDOWN'; excerpt?: string; featuredImage?: string; seoTitle?: string; seoDescription?: string; status: 'DRAFT' | 'PUBLISHED' | 'ARCHIVED'; showInNavigation: boolean; showInFooter: boolean; navigationOrder?: number; footerOrder?: number; } interface PageEditorProps { open: boolean; onClose: () => void; page?: Page | null; onSave: () => void; } export function PageEditor({ open, onClose, page, onSave }: PageEditorProps) { const [formData, setFormData] = useState({ title: '', slug: '', content: '', contentType: 'RICH_TEXT', excerpt: '', featuredImage: '', seoTitle: '', seoDescription: '', status: 'DRAFT', showInNavigation: false, showInFooter: false, navigationOrder: undefined, footerOrder: undefined }); const [contentTab, setContentTab] = useState(0); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [imageUploadOpen, setImageUploadOpen] = useState(false); const editorRef = useRef(null); useEffect(() => { if (page) { setFormData({ ...page, excerpt: page.excerpt || '', featuredImage: page.featuredImage || '', seoTitle: page.seoTitle || '', seoDescription: page.seoDescription || '' }); } else { setFormData({ title: '', slug: '', content: '', contentType: 'RICH_TEXT', excerpt: '', featuredImage: '', seoTitle: '', seoDescription: '', status: 'DRAFT', showInNavigation: false, showInFooter: false, navigationOrder: undefined, footerOrder: undefined }); } setError(null); }, [page, open]); const generateSlug = (title: string) => { return title .toLowerCase() .replace(/[^\w\s-]/g, '') .replace(/\s+/g, '-') .replace(/-+/g, '-') .trim(); }; const handleTitleChange = (title: string) => { setFormData(prev => ({ ...prev, title, slug: prev.slug || generateSlug(title) })); }; const handleSubmit = async () => { if (!formData.title || !formData.slug || !formData.content) { setError('Title, slug, and content are required'); return; } setLoading(true); setError(null); try { const url = page ? `/api/admin/pages/${page.id}` : '/api/admin/pages'; const method = page ? 'PUT' : 'POST'; const response = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify(formData) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || 'Failed to save page'); } onSave(); } catch (error) { console.error('Error saving page:', error); setError(error instanceof Error ? error.message : 'Failed to save page'); } finally { setLoading(false); } }; const handleImageInsert = (imageUrl: string) => { if (formData.contentType === 'RICH_TEXT' && editorRef.current) { const editor = editorRef.current.getEditor(); editor.insertContent(``); } else if (formData.contentType === 'HTML') { const imageTag = ``; setFormData(prev => ({ ...prev, content: prev.content + imageTag })); } setImageUploadOpen(false); }; const renderContentEditor = () => { switch (formData.contentType) { case 'RICH_TEXT': return ( Rich Text Content setFormData(prev => ({ ...prev, content }))} height={800} /> ); case 'HTML': return ( HTML Content setFormData(prev => ({ ...prev, content: e.target.value }))} sx={{ fontFamily: 'monospace' }} /> ); case 'MARKDOWN': return ( Markdown Content setFormData(prev => ({ ...prev, content: e.target.value }))} sx={{ fontFamily: 'monospace' }} /> ); default: return null; } }; return ( <> {page ? 'Edit Page' : 'Create New Page'} {error && ( {error} )} setContentTab(newValue)}> {/* Content Tab */} {contentTab === 0 && ( handleTitleChange(e.target.value)} /> Content Type setFormData(prev => ({ ...prev, slug: e.target.value }))} helperText="This will be the URL path for your page" sx={{ mt: 2 }} /> setFormData(prev => ({ ...prev, excerpt: e.target.value }))} helperText="Brief description (optional)" sx={{ mt: 2 }} /> {renderContentEditor()} )} {/* Settings Tab */} {contentTab === 1 && ( Publication Status setFormData(prev => ({ ...prev, featuredImage: e.target.value }))} /> Display Options setFormData(prev => ({ ...prev, showInNavigation: e.target.checked }))} /> } label="Show in Navigation" /> {formData.showInNavigation && ( setFormData(prev => ({ ...prev, navigationOrder: parseInt(e.target.value) || undefined }))} sx={{ mt: 1, mb: 2 }} /> )} setFormData(prev => ({ ...prev, showInFooter: e.target.checked }))} /> } label="Show in Footer" /> {formData.showInFooter && ( setFormData(prev => ({ ...prev, footerOrder: parseInt(e.target.value) || undefined }))} sx={{ mt: 1 }} /> )} )} {/* SEO Tab */} {contentTab === 2 && ( setFormData(prev => ({ ...prev, seoTitle: e.target.value }))} helperText="Optimize for search engines (leave empty to use page title)" sx={{ mb: 2 }} /> setFormData(prev => ({ ...prev, seoDescription: e.target.value }))} helperText="Meta description for search engines (150-160 characters recommended)" /> )} setImageUploadOpen(false)} onImageSelect={handleImageInsert} /> ); }