feat: improve learning and platform operations
This commit is contained in:
@@ -42,6 +42,7 @@ const CourseModal: React.FC<{
|
||||
const [title, setTitle] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
const [category, setCategory] = useState('');
|
||||
const [status, setStatus] = useState<Course['status']>('draft');
|
||||
const [thumbnailPreview, setThumbnailPreview] = useState<string>('');
|
||||
const [instructor, setInstructor] = useState('Mário Morgado');
|
||||
const [instructorRole, setInstructorRole] = useState('Especialista em Performance');
|
||||
@@ -76,6 +77,7 @@ const CourseModal: React.FC<{
|
||||
setTitle(initialData.title);
|
||||
setDescription(initialData.description);
|
||||
setCategory(initialData.category);
|
||||
setStatus(initialData.status || 'published');
|
||||
setThumbnailPreview(initialData.thumbnail);
|
||||
setInstructor(initialData.instructor || 'Mário Morgado');
|
||||
setInstructorRole(initialData.instructorRole || 'Especialista em Performance');
|
||||
@@ -86,6 +88,7 @@ const CourseModal: React.FC<{
|
||||
setTitle('');
|
||||
setDescription('');
|
||||
setCategory(CATEGORIES[0]);
|
||||
setStatus('draft');
|
||||
setThumbnailPreview('');
|
||||
setInstructor('Mário Morgado');
|
||||
setInstructorRole('Especialista em Performance');
|
||||
@@ -187,6 +190,7 @@ const CourseModal: React.FC<{
|
||||
title,
|
||||
description,
|
||||
category: category || CATEGORIES[0],
|
||||
status,
|
||||
thumbnail: thumbnailPreview || 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?auto=format&fit=crop&w=800&q=80',
|
||||
duration: durationStr,
|
||||
instructor,
|
||||
@@ -198,8 +202,8 @@ const CourseModal: React.FC<{
|
||||
attachments: attachments
|
||||
});
|
||||
onClose();
|
||||
} catch {
|
||||
alert('We could not save this course. Confirm that you are still signed in and that all asset URLs are valid.');
|
||||
} catch (error) {
|
||||
alert(error instanceof Error ? error.message : 'Não foi possível salvar este curso.');
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
@@ -275,6 +279,14 @@ const CourseModal: React.FC<{
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="text-xs text-gray-400 uppercase font-bold tracking-wider mb-1 block">Publicação</label>
|
||||
<select value={status} onChange={(e) => setStatus(e.target.value as Course['status'])} className="w-full bg-black/50 text-white border border-white/10 rounded-xl px-3 py-2.5 text-xs focus:outline-none focus:border-orange-500/50">
|
||||
<option value="draft" className="bg-zinc-900">Salvar como rascunho</option>
|
||||
<option value="published" className="bg-zinc-900">Publicar agora</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="text-xs text-gray-400 uppercase font-bold tracking-wider mb-1 block">Instrutor</label>
|
||||
<input
|
||||
@@ -507,7 +519,7 @@ const CourseModal: React.FC<{
|
||||
disabled={isSubmitting}
|
||||
className="w-full bg-orange-500 hover:bg-orange-600 text-white font-extrabold text-base py-4 rounded-2xl active:scale-95 transition-all shadow-lg shadow-orange-500/25"
|
||||
>
|
||||
{isSubmitting ? 'Salvando...' : (initialData ? 'Salvar Alterações no Curso' : 'Publicar Curso & Materiais')}
|
||||
{isSubmitting ? 'Salvando...' : status === 'draft' ? 'Salvar como Rascunho' : (initialData ? 'Salvar e Publicar Curso' : 'Publicar Curso & Materiais')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -532,21 +544,18 @@ export const ManageCourses: React.FC = () => {
|
||||
|
||||
const loadData = async () => {
|
||||
setLoading(true);
|
||||
const data = await getManagedCourses();
|
||||
setCourses(data);
|
||||
const analyticsResponse = await instructorApi.analytics();
|
||||
setAnalytics(analyticsResponse.data);
|
||||
|
||||
// Load all comments
|
||||
const commentsAccumulator: {comment: Comment, courseTitle: string}[] = [];
|
||||
for (const c of data) {
|
||||
const courseComments = await getComments(c.id);
|
||||
courseComments.forEach(comm => {
|
||||
commentsAccumulator.push({ comment: comm, courseTitle: c.title });
|
||||
});
|
||||
try {
|
||||
const data = await getManagedCourses();
|
||||
setCourses(data);
|
||||
const analyticsResponse = await instructorApi.analytics();
|
||||
setAnalytics(analyticsResponse.data);
|
||||
const commentLists = await Promise.all(data.map(async (course) => ({ course, comments: await getComments(course.id) })));
|
||||
setAllComments(commentLists.flatMap(({ course, comments }) => comments.map((comment) => ({ comment, courseTitle: course.title }))));
|
||||
} catch {
|
||||
showToast('Não foi possível carregar o painel do instrutor.', 'error');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
setAllComments(commentsAccumulator);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -713,6 +722,7 @@ export const ManageCourses: React.FC = () => {
|
||||
<div className="absolute top-3 left-3 bg-black/70 backdrop-blur-md px-2.5 py-1 rounded-[980px] text-caption font-semibold uppercase tracking-caption text-white border border-white/10">
|
||||
{course.category}
|
||||
</div>
|
||||
{course.status === 'draft' && <div className="absolute top-3 right-3 bg-amber-500/20 backdrop-blur-md px-2.5 py-1 rounded-[980px] text-caption font-semibold uppercase tracking-caption text-amber-300 border border-amber-500/30">Rascunho</div>}
|
||||
</div>
|
||||
|
||||
{/* Body */}
|
||||
|
||||
Reference in New Issue
Block a user