Skip to content

Commit

Permalink
Merge pull request #23 from fga-eps-mds/feat#66/subject-access
Browse files Browse the repository at this point in the history
[TEST] Increase test coverage on web (fga-eps-mds/2024.2-ARANDU-DOC#71)
  • Loading branch information
gabrielm2q authored Feb 2, 2025
2 parents cd56abb + b07ed8e commit 23d9dae
Show file tree
Hide file tree
Showing 7 changed files with 446 additions and 82 deletions.
96 changes: 22 additions & 74 deletions src/app/subjects/[...pointId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,26 @@ import {
import Popup from '@/components/ui/popup';
import { SubjectForm } from '@/components/forms/subject.form';
import { toast } from 'sonner';
import { updateSubject, addSubject, handleSubjectAction, handleRemoveSubject, handleMenuOpen, fetchSubjects, handleMenuClose } from './subject.functions';

export default function SubjectPage({
params,
}: {
readonly params: { pointId: string };
}) {
const fetchSubjects = async (): Promise<Subject[]> => {
let subjects: Subject[];

if (params.pointId == "admin") {
subjects = await GetSubjects();
} else {

subjects = await GetSubjectsByUserId(params.pointId);
}
subjects.sort((a, b) => a.order - b.order);
setListSubjects(subjects);
setFilteredSubjects(subjects);
return subjects;
};
const [listSubjects, setListSubjects] = useState<Subject[]>([]);
const [filteredSubjects, setFilteredSubjects] = useState<Subject[]>([]);

const {
data = [],
isLoading,
error,
} = useQuery<Subject[], Error>({
queryKey: ['subjects', params.pointId],
queryFn: fetchSubjects,
queryFn: () => fetchSubjects(params, setListSubjects, setFilteredSubjects), // Corrigido: Chamando a função corretamente com uma função anônima
});

const [listSubjects, setListSubjects] = useState<Subject[]>([]);
const [filteredSubjects, setFilteredSubjects] = useState<Subject[]>([]);
const [searchQuery, setSearchQuery] = useState<string>('');

const [selectedSubject, setSelectedSubject] = useState<Subject | null>(null);
Expand All @@ -81,50 +69,6 @@ export default function SubjectPage({
}
}, [searchQuery, listSubjects]);


const handleMenuOpen = (
event: React.MouseEvent<HTMLButtonElement>,
subject: Subject,
) => {
setAnchorEl(event.currentTarget);
setSelectedSubject(subject);
};

const handleMenuClose = () => {
setAnchorEl(null);
};

const handleSubjectAction = (action: string) => {
if (action === 'editar') setEditionDialogOpen(true);
if (action === 'excluir') setExclusionDialogOpen(true);
};

const addSubject = (subject: Subject) => {
setListSubjects(
[...listSubjects, subject].sort((a, b) => a.order - b.order),
);
};

const updateSubject = (subject: Subject) => {
setListSubjects(
listSubjects.map((s) => (s._id === subject._id ? subject : s)),
);
};

const handleRemoveSubject = async (subject: Subject) => {
const response = await deleteSubjects({
id: subject._id,
token: JSON.parse(localStorage.getItem('token')!),
});
if (response.data) {
toast.success('Disciplina excluída com sucesso!');
setListSubjects(listSubjects.filter((s) => s._id !== subject._id));
setExclusionDialogOpen(false);
} else {
toast.error('Erro ao excluir disciplina. Tente novamente mais tarde!');
}
};

if (isLoading) {
return <CircularProgress />;
}
Expand All @@ -133,7 +77,8 @@ export default function SubjectPage({
return <Typography>Error fetching subjects</Typography>;
}

return (

const SubjectPage = (
<Box
sx={{
padding: 2,
Expand All @@ -146,16 +91,15 @@ export default function SubjectPage({
<Box sx={{ width: '100%', maxWidth: 800, marginBottom: 2 }}>
<SearchBar value={searchQuery} onChange={setSearchQuery} />
</Box>
<Box sx={{ width: '100%', maxWidth: 800 }}><SubjectTable
subjects={filteredSubjects}
anchorEl={anchorEl}
onMenuClick={(event, subject) => handleMenuOpen(event, subject, setAnchorEl, setSelectedSubject)}
onMenuClose={() => handleMenuClose(setAnchorEl)}
onSubjectAction={(action) => handleSubjectAction(action, setEditionDialogOpen, setExclusionDialogOpen)}
/></Box>


<Box sx={{ width: '100%', maxWidth: 800, marginBottom: 2 }}>
<SubjectTable
subjects={filteredSubjects}
anchorEl={anchorEl}
onMenuClick={handleMenuOpen}
onMenuClose={handleMenuClose}
onSubjectAction={handleSubjectAction}
/>
</Box>

<ButtonRed onClick={() => setCreateDialogOpen(true)}>
Nova Disciplina
Expand All @@ -167,10 +111,11 @@ export default function SubjectPage({
title="Editar Disciplina"
>
<SubjectForm
callback={updateSubject}
callback={(subject: Subject) => updateSubject(subject, listSubjects, setListSubjects)}
subject={selectedSubject!}
setDialog={setEditionDialogOpen}
/>

</Popup>

<Popup
Expand All @@ -179,7 +124,7 @@ export default function SubjectPage({
title="Criar Nova Disciplina"
>
<SubjectForm
callback={addSubject}
callback={(subject: Subject) => addSubject(subject, listSubjects, setListSubjects)}
setDialog={setCreateDialogOpen}
/>
</Popup>
Expand All @@ -199,13 +144,16 @@ export default function SubjectPage({
Cancelar
</Button>
<Button
onClick={() => handleRemoveSubject(selectedSubject!)}
onClick={() => handleRemoveSubject(selectedSubject!, listSubjects, setListSubjects, setExclusionDialogOpen)}
color="primary"
>
Confirmar
</Button>
</DialogActions>
</Dialog>
</Box>
</Box >
);

return SubjectPage

}
96 changes: 96 additions & 0 deletions src/app/subjects/[...pointId]/subject.functions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// subjectFunctions.ts
import { Subject } from '@/lib/interfaces/subjetc.interface';
import { deleteSubjects, GetSubjects, GetSubjectsByUserId } from '@/services/studioMaker.service';
import { toast } from 'sonner';

export const updateSubject = (subject: Subject, listSubjects: Subject[], setListSubjects: React.Dispatch<React.SetStateAction<Subject[]>>) => {
// Verificar se listSubjects não é undefined ou null
if (listSubjects && Array.isArray(listSubjects)) {
setListSubjects(
listSubjects.map((s) => (s._id === subject._id ? subject : s)),
);
}
};

export const addSubject = (
subject: Subject,
listSubjects: Subject[],
setListSubjects: React.Dispatch<React.SetStateAction<Subject[]>>
) => {
// Verificar se listSubjects não é undefined ou null
if (listSubjects && Array.isArray(listSubjects)) {
setListSubjects(
[...listSubjects, subject].sort((a, b) => a.order - b.order),
);
}
};

export const handleSubjectAction = (
action: string,
setEditionDialogOpen: React.Dispatch<React.SetStateAction<boolean>>,
setExclusionDialogOpen: React.Dispatch<React.SetStateAction<boolean>>
) => {
if (action === 'editar') {
setEditionDialogOpen(true);
}
if (action === 'excluir') {
setExclusionDialogOpen(true);
}
};

export const handleRemoveSubject = async (
subject: Subject,
listSubjects: Subject[],
setListSubjects: React.Dispatch<React.SetStateAction<Subject[]>>,
setExclusionDialogOpen: React.Dispatch<React.SetStateAction<boolean>>
) => {
const response = await deleteSubjects({
id: subject._id,
token: JSON.parse(localStorage.getItem('token')!),
});
if (response.data) {
toast.success('Disciplina excluída com sucesso!');
setListSubjects(listSubjects.filter((s) => s._id !== subject._id));
setExclusionDialogOpen(false);
} else {
toast.error('Erro ao excluir disciplina. Tente novamente mais tarde!');
}
};

export const handleMenuOpen = (
event: React.MouseEvent<HTMLButtonElement>,
subject: Subject,
setAnchorEl: React.Dispatch<React.SetStateAction<null | HTMLElement>>,
setSelectedSubject: React.Dispatch<React.SetStateAction<Subject | null>>
) => {
setAnchorEl(event.currentTarget);
setSelectedSubject(subject);
};

export const fetchSubjects = async (
params: { pointId: string },
setListSubjects: React.Dispatch<React.SetStateAction<Subject[]>>,
setFilteredSubjects: React.Dispatch<React.SetStateAction<Subject[]>>
): Promise<Subject[]> => {
let subjects: Subject[];

// Verifica qual função chamar baseado no pointId
if (params.pointId == "admin") {
subjects = await GetSubjects(); // Busca todas as disciplinas
} else {
subjects = await GetSubjectsByUserId(params.pointId); // Busca as disciplinas pelo userId
}

// Ordena os subjects pelo campo 'order'
subjects.sort((a, b) => a.order - b.order);

// Atualiza os estados com as disciplinas ordenadas
setListSubjects(subjects);
setFilteredSubjects(subjects);

return subjects;
};

export const handleMenuClose = (setAnchorEl: React.Dispatch<React.SetStateAction<null | HTMLElement>>,) => {
setAnchorEl(null);
};
1 change: 1 addition & 0 deletions src/components/admin/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ value, onChange }) => {
variant="outlined"
fullWidth
value={value}
role="searchbox"
onChange={(e) => onChange(e.target.value)}
InputProps={{
startAdornment: (
Expand Down
3 changes: 2 additions & 1 deletion src/components/tables/subject.table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ const SubjectTable: React.FC<SubjectTableProps> = ({



return <MrtTableContainer table={table} />;
return <MrtTableContainer table={table}
role="table" />;
};

export default SubjectTable;
2 changes: 1 addition & 1 deletion test/app/services/studioMaker.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('Serviço de Jornadas e Trilhas', () => {
expect(studioMakerApi.get).toHaveBeenCalledWith(`/points/user/${userId}`);
});

test('Deve falhar ao buscar pontos de partida do usuário', async () => {
it('Deve falhar ao buscar pontos de partida do usuário', async () => {
const userId = '321';
(studioMakerApi.get as jest.Mock).mockRejectedValue(
new Error('Falha ao buscar pontos de partida do usuário'),
Expand Down
Loading

0 comments on commit 23d9dae

Please sign in to comment.