feat: Integrate content library features, allowing users to save and select blocks within the lesson editor.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { cmsApi, Lesson, Block, GradingCategory, LibraryBlock, api } from "@/lib/api";
|
import { cmsApi, Lesson, Block, GradingCategory, LibraryBlock } from "@/lib/api";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import DescriptionBlock from "@/components/blocks/DescriptionBlock";
|
import DescriptionBlock from "@/components/blocks/DescriptionBlock";
|
||||||
import MediaBlock from "@/components/blocks/MediaBlock";
|
import MediaBlock from "@/components/blocks/MediaBlock";
|
||||||
@@ -218,6 +218,39 @@ export default function LessonEditor({ params }: { params: { id: string; lessonI
|
|||||||
setBlocks(newBlocks);
|
setBlocks(newBlocks);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Content Libraries functions
|
||||||
|
const handleSaveToLibrary = async (name: string, description: string, tags: string[]) => {
|
||||||
|
if (!blockToSave) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await cmsApi.createLibraryBlock({
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
block_type: blockToSave.type,
|
||||||
|
block_data: blockToSave,
|
||||||
|
tags,
|
||||||
|
});
|
||||||
|
alert('¡Bloque guardado en la biblioteca exitosamente!');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error saving to library:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectFromLibrary = (libraryBlock: LibraryBlock) => {
|
||||||
|
// Create a new block from the library block
|
||||||
|
const newBlock: Block = {
|
||||||
|
...libraryBlock.block_data,
|
||||||
|
id: Math.random().toString(36).substr(2, 9), // New unique ID
|
||||||
|
};
|
||||||
|
setBlocks([...blocks, newBlock]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openSaveToLibraryModal = (block: Block) => {
|
||||||
|
setBlockToSave(block);
|
||||||
|
setIsSaveToLibraryModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleSummarize = async () => {
|
const handleSummarize = async () => {
|
||||||
if (!lesson) return;
|
if (!lesson) return;
|
||||||
@@ -779,6 +812,15 @@ export default function LessonEditor({ params }: { params: { id: string; lessonI
|
|||||||
<span className="text-2xl group-hover:scale-110 transition-transform">{isGeneratingQuiz ? '⏳' : '✨'}</span>
|
<span className="text-2xl group-hover:scale-110 transition-transform">{isGeneratingQuiz ? '⏳' : '✨'}</span>
|
||||||
<span className="text-[10px] font-black uppercase tracking-widest text-indigo-400">{isGeneratingQuiz ? 'Building...' : 'AI Builder'}</span>
|
<span className="text-[10px] font-black uppercase tracking-widest text-indigo-400">{isGeneratingQuiz ? 'Building...' : 'AI Builder'}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Browse Library */}
|
||||||
|
<button
|
||||||
|
onClick={() => setIsLibraryPanelOpen(true)}
|
||||||
|
className="flex flex-col items-center gap-2 p-6 bg-gradient-to-b from-emerald-500/20 to-teal-500/20 border border-emerald-500/30 hover:border-emerald-500/60 rounded-3xl transition-all group w-36"
|
||||||
|
>
|
||||||
|
<Library className="w-6 h-6 text-emerald-400 group-hover:scale-110 transition-transform" />
|
||||||
|
<span className="text-[10px] font-black uppercase tracking-widest text-emerald-400">Library</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -854,6 +896,25 @@ export default function LessonEditor({ params }: { params: { id: string; lessonI
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
{/* Content Libraries Modals */}
|
||||||
|
{blockToSave && (
|
||||||
|
<SaveToLibraryModal
|
||||||
|
block={blockToSave}
|
||||||
|
isOpen={isSaveToLibraryModalOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsSaveToLibraryModalOpen(false);
|
||||||
|
setBlockToSave(null);
|
||||||
|
}}
|
||||||
|
onSave={handleSaveToLibrary}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<LibraryPanel
|
||||||
|
isOpen={isLibraryPanelOpen}
|
||||||
|
onClose={() => setIsLibraryPanelOpen(false)}
|
||||||
|
onSelectBlock={handleSelectFromLibrary}
|
||||||
|
/>
|
||||||
</div >
|
</div >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default function LibraryPanel({ isOpen, onClose, onSelectBlock }: Library
|
|||||||
const loadBlocks = async () => {
|
const loadBlocks = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const data = await api.listLibraryBlocks();
|
const data = await cmsApi.listLibraryBlocks();
|
||||||
setBlocks(data);
|
setBlocks(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading library blocks:', error);
|
console.error('Error loading library blocks:', error);
|
||||||
@@ -68,7 +68,7 @@ export default function LibraryPanel({ isOpen, onClose, onSelectBlock }: Library
|
|||||||
const handleUseBlock = async (block: LibraryBlock) => {
|
const handleUseBlock = async (block: LibraryBlock) => {
|
||||||
try {
|
try {
|
||||||
// Increment usage counter
|
// Increment usage counter
|
||||||
await api.incrementBlockUsage(block.id);
|
await cmsApi.incrementBlockUsage(block.id);
|
||||||
onSelectBlock(block);
|
onSelectBlock(block);
|
||||||
onClose();
|
onClose();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -81,7 +81,7 @@ export default function LibraryPanel({ isOpen, onClose, onSelectBlock }: Library
|
|||||||
if (!confirm('¿Estás seguro de eliminar este bloque de la biblioteca?')) return;
|
if (!confirm('¿Estás seguro de eliminar este bloque de la biblioteca?')) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await api.deleteLibraryBlock(blockId);
|
await cmsApi.deleteLibraryBlock(blockId);
|
||||||
setBlocks(blocks.filter(b => b.id !== blockId));
|
setBlocks(blocks.filter(b => b.id !== blockId));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting block:', error);
|
console.error('Error deleting block:', error);
|
||||||
|
|||||||
Reference in New Issue
Block a user