diff --git a/app/[locale]/admin/page.tsx b/app/[locale]/admin/page.tsx index 2627aba..fb8eb9c 100644 --- a/app/[locale]/admin/page.tsx +++ b/app/[locale]/admin/page.tsx @@ -24,6 +24,12 @@ import { updateCheatsheet, deleteCheatsheet } from '@/lib/actions/cheatsheetActions'; +import { + getPrompts, + createPrompt, + updatePrompt, + deletePrompt +} from '@/lib/actions/promptActions'; import { ShieldAlert, Plus, @@ -48,7 +54,8 @@ import { Link as LinkIcon, FolderTree, Tag, - Terminal + Terminal, + Sparkles } from 'lucide-react'; import { YoutubeIcon as Youtube } from '@/components/icons/YoutubeIcon'; @@ -89,7 +96,7 @@ function parseNotesText(text: string) { export default function AdminPage() { const t = useTranslations('admin'); - const [activeTab, setActiveTab] = useState<'dashboard' | 'lessons' | 'cheatsheets' | 'categories' | 'users' | 'settings' | 'messages'>('dashboard'); + const [activeTab, setActiveTab] = useState<'dashboard' | 'lessons' | 'cheatsheets' | 'prompts' | 'categories' | 'users' | 'settings' | 'messages'>('dashboard'); // Stats const [stats, setStats] = useState({ totalLessons: 0, totalViews: 0, totalDownloads: 0, totalMessages: 0 }); @@ -117,6 +124,17 @@ export default function AdminPage() { ]); const [savingCheat, setSavingCheat] = useState(false); + // Prompts State + const [promptsList, setPromptsList] = useState([]); + const [isPromptFormOpen, setIsPromptFormOpen] = useState(false); + const [editingPromptId, setEditingPromptId] = useState(null); + const [promptTitle, setPromptTitle] = useState(''); + const [promptCategory, setPromptCategory] = useState('System Architecture'); + const [promptDesc, setPromptDesc] = useState(''); + const [promptContent, setPromptContent] = useState(''); + const [promptTagsText, setPromptTagsText] = useState('Next.js, System Prompt'); + const [savingPrompt, setSavingPrompt] = useState(false); + // Lesson Form Modal State (Create or Edit) const [isFormOpen, setIsFormOpen] = useState(false); const [editingLessonId, setEditingLessonId] = useState(null); @@ -186,6 +204,9 @@ export default function AdminPage() { } else if (activeTab === 'cheatsheets') { const sheets = await getCheatsheets(); setCheatsheetsList(sheets); + } else if (activeTab === 'prompts') { + const prs = await getPrompts(); + setPromptsList(prs); } else if (activeTab === 'categories') { const cats = await getCategories(); setCategoriesList(cats); @@ -330,6 +351,74 @@ export default function AdminPage() { } }; + // Prompt Handlers + const handleOpenPromptCreate = () => { + setEditingPromptId(null); + setPromptTitle(''); + setPromptCategory('System Architecture'); + setPromptDesc(''); + setPromptContent(''); + setPromptTagsText('Next.js, System Prompt'); + setIsPromptFormOpen(true); + }; + + const handleOpenPromptEdit = (prompt: any) => { + setEditingPromptId(prompt.id); + setPromptTitle(prompt.title); + setPromptCategory(prompt.category); + setPromptDesc(prompt.description); + setPromptContent(prompt.content); + setPromptTagsText(prompt.tags ? prompt.tags.join(', ') : ''); + setIsPromptFormOpen(true); + }; + + const handleSavePrompt = async (e: React.FormEvent) => { + e.preventDefault(); + setSavingPrompt(true); + + const tags = promptTagsText.split(',').map((t) => t.trim()).filter((t) => t.length > 0); + + let res; + if (editingPromptId) { + res = await updatePrompt(editingPromptId, { + title: promptTitle, + category: promptCategory, + description: promptDesc, + content: promptContent, + tags, + }); + } else { + res = await createPrompt({ + title: promptTitle, + category: promptCategory, + description: promptDesc, + content: promptContent, + tags, + }); + } + + setSavingPrompt(false); + + if (res.success) { + showAlert('success', editingPromptId ? 'Prompt updated successfully!' : 'New prompt created successfully!'); + setIsPromptFormOpen(false); + getPrompts().then(setPromptsList); + } else { + showAlert('error', res.error || 'Failed to save prompt'); + } + }; + + const handleDeletePrompt = async (id: string, title: string) => { + if (!confirm(`Are you sure you want to delete prompt "${title}"?`)) return; + const res = await deletePrompt(id); + if (res.success) { + showAlert('success', `Prompt "${title}" deleted`); + getPrompts().then(setPromptsList); + } else { + showAlert('error', res.error || 'Failed to delete prompt'); + } + }; + // Cheatsheet Handlers const handleOpenCheatCreate = () => { setEditingCheatId(null); @@ -526,6 +615,18 @@ export default function AdminPage() { Cheatsheets + + + + +
+ {promptsList.map((prompt) => ( +
+
+
+ + {prompt.category} + +

{prompt.title}

+

{prompt.description}

+
+ +
+ + + +
+
+ +
+ {prompt.content} +
+
+ ))} +
+ + )} + + {/* TAB 5: CATEGORIES CRUD */} {activeTab === 'categories' && (
@@ -899,7 +1055,7 @@ export default function AdminPage() {
)} - {/* TAB 5: USERS / ADMINS */} + {/* TAB 6: USERS / ADMINS */} {activeTab === 'users' && (
{/* Create User Form */} @@ -971,7 +1127,7 @@ export default function AdminPage() {
)} - {/* TAB 6: SETTINGS */} + {/* TAB 7: SETTINGS */} {activeTab === 'settings' && (

@@ -1033,7 +1189,7 @@ export default function AdminPage() { )} - {/* TAB 7: MESSAGES */} + {/* TAB 8: MESSAGES */} {activeTab === 'messages' && (

Viewer Contact Messages ({messages.length})

@@ -1063,6 +1219,103 @@ export default function AdminPage() { + {/* CREATE / EDIT PROMPT FORM MODAL */} + {isPromptFormOpen && ( +
+
+
+

+ + {editingPromptId ? 'Edit AI Prompt' : 'Create New AI Prompt'} +

+ +
+ +
+
+
+ + setPromptTitle(e.target.value)} + placeholder="Full-Stack Next.js Architect" + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-4 py-2 text-xs text-white focus:outline-none" + /> +
+ +
+ + setPromptCategory(e.target.value)} + placeholder="System Architecture / UI Design" + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-4 py-2 text-xs text-white focus:outline-none" + /> +
+
+ +
+ +