fixing stuff
Some checks failed
Mindforge Web Build and Deploy (internal) / Build Mindforge Web Image (push) Failing after 1m57s
Mindforge Web Build and Deploy (internal) / Deploy Mindforge Web (internal) (push) Has been skipped
Mindforge API Build and Deploy / Build Mindforge API Image (push) Successful in 2m11s
Mindforge API Build and Deploy / Deploy Mindforge API (internal) (push) Successful in 8s

This commit is contained in:
2026-06-11 19:34:52 -03:00
parent 82dda0395d
commit b29ae991c8
8 changed files with 155 additions and 16 deletions

View File

@@ -100,6 +100,8 @@ export function SpacedReviewComponent() {
const [error, setError] = useState<string | null>(null);
const [selectedStatuses, setSelectedStatuses] = useState<FlashcardRagStatus[]>(['Red', 'Amber', 'Green', 'Grey']);
const [selectedLibraryIds, setSelectedLibraryIds] = useState<number[]>([]);
const [selectedSubjects, setSelectedSubjects] = useState<string[]>([]);
const [selectedSubSubjects, setSelectedSubSubjects] = useState<string[]>([]);
const [startingSession, setStartingSession] = useState(false);
const [sessionCards, setSessionCards] = useState<FlashcardCard[]>([]);
const [sessionLibraries, setSessionLibraries] = useState<FlashcardRagLibrary[]>([]);
@@ -161,6 +163,49 @@ export function SpacedReviewComponent() {
};
}, []);
const startSession = async () => {
if (selectedStatuses.length === 0) {
setError('Selecione ao menos um status para iniciar a revisao.');
return;
}
if (selectedLibraryIds.length === 0) {
setError('Selecione ao menos um arquivo para iniciar a revisao.');
return;
}
if (selectedRagLibraries.length === 0) {
setError('Nenhum arquivo encontrado com os filtros atuais. Ajuste os status ou os arquivos selecionados.');
return;
}
setStartingSession(true);
setError(null);
try {
const ragByLibraryId = new Map(selectedRagLibraries.map((library) => [library.libraryId, library]));
const libraryIds = Array.from(new Set(selectedRagLibraries.map((library) => library.libraryId)));
const response = await MindforgeApiService.createFlashcardReviewSession({ libraryIds });
const allowedLibraryIds = new Set(libraryIds);
const filteredCards = response.cards.filter((card) => allowedLibraryIds.has(card.libraryId));
const orderedCards = orderCardsForSession(filteredCards, ragByLibraryId);
if (orderedCards.length === 0) {
setError('Os filtros selecionados nao retornaram cards para revisar.');
return;
}
setSessionLibraries(selectedRagLibraries);
setSessionCards(orderedCards);
setCurrentIndex(0);
setShowAnswer(false);
} catch (err: any) {
setError(err?.message || 'Falha ao iniciar revisao espacada.');
} finally {
setStartingSession(false);
}
};
const allRagLibraries = useMemo(() => {
if (!dashboard) {
return [];
@@ -210,6 +255,64 @@ export function SpacedReviewComponent() {
setSelectedLibraryIds([...selectedLibraryIds, libraryId]);
};
const toggleSubject = (subject: string) => {
if (selectedSubjects.includes(subject)) {
setSelectedSubjects(selectedSubjects.filter((s) => s !== subject));
const subjectGroup = dashboard?.subjects.find((s) => s.subject === subject);
if (subjectGroup) {
const libraryIdsToRemove = subjectGroup.subSubjects.flatMap((ss) =>
ss.libraries.map((lib) => lib.libraryId));
setSelectedLibraryIds((current) => current.filter((id) => !libraryIdsToRemove.includes(id)));
const subSubjectKeysToRemove = subjectGroup.subSubjects.map((ss) => `${subject}::${ss.subSubject}`);
setSelectedSubSubjects((current) => current.filter((key) => !subSubjectKeysToRemove.includes(key)));
}
return;
}
setSelectedSubjects([...selectedSubjects, subject]);
const subjectGroup = dashboard?.subjects.find((s) => s.subject === subject);
if (subjectGroup) {
const libraryIdsToAdd = subjectGroup.subSubjects.flatMap((ss) =>
ss.libraries.map((lib) => lib.libraryId));
setSelectedLibraryIds((current) => [...new Set([...current, ...libraryIdsToAdd])]);
const subSubjectKeysToAdd = subjectGroup.subSubjects.map((ss) => `${subject}::${ss.subSubject}`);
setSelectedSubSubjects((current) => [...new Set([...current, ...subSubjectKeysToAdd])]);
}
};
const toggleSubSubject = (subject: string, subSubject: string) => {
const key = `${subject}::${subSubject}`;
if (selectedSubSubjects.includes(key)) {
setSelectedSubSubjects(selectedSubSubjects.filter((k) => k !== key));
const subjectGroup = dashboard?.subjects.find((s) => s.subject === subject);
const subSubjectGroup = subjectGroup?.subSubjects.find((ss) => ss.subSubject === subSubject);
if (subSubjectGroup) {
const libraryIdsToRemove = subSubjectGroup.libraries.map((lib) => lib.libraryId);
setSelectedLibraryIds((current) => current.filter((id) => !libraryIdsToRemove.includes(id)));
}
const parentSubjectStillSelected = selectedSubSubjects.some((k) =>
k.startsWith(`${subject}::`) && k !== key);
if (!parentSubjectStillSelected) {
setSelectedSubjects((current) => current.filter((s) => s !== subject));
}
return;
}
setSelectedSubSubjects([...selectedSubSubjects, key]);
const subjectGroup = dashboard?.subjects.find((s) => s.subject === subject);
const subSubjectGroup = subjectGroup?.subSubjects.find((ss) => ss.subSubject === subSubject);
if (subSubjectGroup) {
const libraryIdsToAdd = subSubjectGroup.libraries.map((lib) => lib.libraryId);
setSelectedLibraryIds((current) => [...new Set([...current, ...libraryIdsToAdd])]);
}
const allSubSubjects = subjectGroup?.subSubjects.map((ss) => `${subject}::${ss.subSubject}`) || [];
const allSelected = allSubSubjects.every((k) =>
k === key || selectedSubSubjects.includes(k));
if (allSelected && subject && !selectedSubjects.includes(subject)) {
setSelectedSubjects((current) => [...current, subject]);
}
};
const startSession = async () => {
if (selectedStatuses.length === 0) {
setError('Selecione ao menos um status para iniciar a revisao.');
@@ -335,7 +438,14 @@ export function SpacedReviewComponent() {
{dashboard.subjects.map((subjectGroup) => (
<section key={subjectGroup.subject} className="spaced-review-subject">
<header className="spaced-review-subject-header">
<h3>{subjectGroup.subject}</h3>
<label className="spaced-review-subject-toggle">
<input
type="checkbox"
checked={selectedSubjects.includes(subjectGroup.subject)}
onChange={() => toggleSubject(subjectGroup.subject)}
/>
<h3>{subjectGroup.subject}</h3>
</label>
<p>{summaryText(
subjectGroup.summary.activeCount,
subjectGroup.summary.greenPercentage,
@@ -352,7 +462,14 @@ export function SpacedReviewComponent() {
{subjectGroup.subSubjects.map((subSubjectGroup) => (
<div key={`${subjectGroup.subject}::${subSubjectGroup.subSubject}`} className="spaced-review-subsubject-block">
<div className="spaced-review-subsubject-header">
<strong>{subSubjectGroup.subSubject}</strong>
<label className="spaced-review-subsubject-toggle">
<input
type="checkbox"
checked={selectedSubSubjects.includes(`${subjectGroup.subject}::${subSubjectGroup.subSubject}`)}
onChange={() => toggleSubSubject(subjectGroup.subject, subSubjectGroup.subSubject)}
/>
<strong>{subSubjectGroup.subSubject}</strong>
</label>
<span>{summaryText(
subSubjectGroup.summary.activeCount,
subSubjectGroup.summary.greenPercentage,