Skip to content
This repository has been archived by the owner on May 17, 2024. It is now read-only.

Jordi/feature/89 fe integrate the students list filters hf #121

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b7957cc
filter students roles
Dar-ya218 Apr 2, 2024
22bcf41
filter
Dar-ya218 Apr 3, 2024
980fba3
filter done
Dar-ya218 Apr 7, 2024
bf063e4
Merge branch 'hotfix-filtering' into feature/89-fe-integrate-the-stud…
Dar-ya218 Apr 7, 2024
3df2c29
add rules
Dar-ya218 Apr 9, 2024
e48f74d
role filtering
Dar-ya218 Apr 9, 2024
8790354
fix FetchStudentsList
Dar-ya218 Apr 15, 2024
2bd6194
change
Dar-ya218 Apr 17, 2024
cd58a5f
Merge branch 'main' of https://github.com/IT-Academy-BCN/ita-profiles…
Dar-ya218 Apr 17, 2024
38a8953
fix eslint
Dar-ya218 Apr 17, 2024
24a4730
hot fix
Dar-ya218 Apr 17, 2024
25a2780
fix checkbox
Dar-ya218 Apr 17, 2024
3c81469
test
Dar-ya218 Apr 17, 2024
9b49975
fix test TS
Dar-ya218 Apr 17, 2024
99c5ed6
test
Dar-ya218 Apr 22, 2024
04213ed
update
llopFilms Apr 24, 2024
0285189
Merge branch 'main' of https://github.com/IT-Academy-BCN/ita-profiles…
Dar-ya218 Apr 24, 2024
1997f40
Merge branch 'feature/89-fe-integrate-the-students-list-filters-hf' o…
Dar-ya218 Apr 24, 2024
105f387
add context filters
Dar-ya218 Apr 24, 2024
53a930e
Student Interface Layout
Dar-ya218 Apr 24, 2024
956f95c
Implement Student Filters Context
Dar-ya218 Apr 24, 2024
6def488
fillters role done
Dar-ya218 Apr 27, 2024
1cdacc7
fix
Dar-ya218 Apr 27, 2024
2c4b8b4
small fix
Dar-ya218 Apr 27, 2024
8dc5918
test
Dar-ya218 Apr 27, 2024
8897ef9
Implement Error Handling
Dar-ya218 Apr 27, 2024
e4d2408
fix test
Dar-ya218 Apr 27, 2024
e718986
fix test
Dar-ya218 Apr 28, 2024
f77febf
test
Dar-ya218 Apr 28, 2024
b1562ea
fix checks
Dar-ya218 Apr 28, 2024
2110e9c
fix
Dar-ya218 Apr 28, 2024
5ee6dad
Refactor StudentFilters dependency
Dar-ya218 Apr 28, 2024
ace9652
layout children
Dar-ya218 Apr 28, 2024
4448ed0
fix: lint passed as property children error
jordimorillo Apr 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"@hookform/resolvers": "3.3.2",
"@reduxjs/toolkit": "1.9.7",
"axios": "1.6.2",
"axios-mock-adapter": "^1.22.0",
"classnames": "2.5.1",
"i18next": "23.6.0",
"i18next-browser-languagedetector": "7.1.0",
Expand All @@ -29,8 +28,8 @@
},
"devDependencies": {
"@tailwindcss/typography": "0.5.10",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "14.2.2",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.2.2",
"@types/js-cookie": "3.0.6",
"@types/react": "18.2.15",
"@types/react-dom": "18.2.7",
Expand All @@ -39,6 +38,7 @@
"@vitejs/plugin-react-swc": "3.6.0",
"@vitest/coverage-v8": "1.4.0",
"autoprefixer": "10.4.16",
"axios-mock-adapter": "^1.22.0",
"daisyui": "4.4.2",
"eslint": "8.56.0",
"eslint-config-airbnb": "19.0.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import axios from 'axios';
// eslint-disable-next-line import/no-extraneous-dependencies
import MockAdapter from 'axios-mock-adapter';
import { FetchStudentsListHome } from '../../../api/FetchStudentsList';

const mockAxios = new MockAdapter(axios);

describe('FetchStudentsListHome function', () => {
afterEach(() => {
mockAxios.reset();
});

it('should fetch student list for home', async () => {
const selectedRoles = ['role1', 'role2'];

const expectedUrl = 'https://itaperfils.eurecatacademy.org/api/v1/student/list/for-home?specialization=role1,role2';

const mockData = [{ id: 1, name: 'Student 1' }, { id: 2, name: 'Student 2' }];

mockAxios.onGet(expectedUrl).reply(200, mockData);

const result = await FetchStudentsListHome(selectedRoles);

expect(result).toEqual(mockData);
});

it('should handle errors', async () => {
const selectedRoles: string[] = [];

const expectedUrl = 'https://itaperfils.eurecatacademy.org/api/v1/student/list/for-home';

mockAxios.onGet(expectedUrl).reply(500);

await expect(FetchStudentsListHome(selectedRoles)).rejects.toThrow();
});
});
31 changes: 21 additions & 10 deletions src/api/FetchStudentsList.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import axios from 'axios'
import { IStudentList } from '../interfaces/interfaces'
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars
import axios, { AxiosError } from 'axios';
import { IStudentList } from '../interfaces/interfaces';

// eslint-disable-next-line consistent-return
export const FetchStudentsListHome = async () => {
export const FetchStudentsListHome = async (selectedRoles:Array<string>= []) => {

try {
const response = await axios.get<IStudentList[]>(
'https://itaperfils.eurecatacademy.org/api/v1/student/list/for-home',
)
return response.data
} catch (e) {
let queryParams = '';

// Construir la cadena de consulta para roles seleccionados
if (selectedRoles.length > 0) {
queryParams += `specialization=${selectedRoles.join(',')}`;
}

// Construir la URL completa con la cadena de consulta
const url = `https://itaperfils.eurecatacademy.org/api/v1/student/list/for-home${queryParams ? `?${queryParams}` : ''}`;

const response = await axios.get<IStudentList[]>(url);
return response.data;
// @ts-expect-error throws AxiosError exception
} catch (e: AxiosError) {
// eslint-disable-next-line no-console
console.error(e)
throw new DOMException(e.message, 'ConnectionFailed');
}
}
};
22 changes: 13 additions & 9 deletions src/components/landing/Landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@ import UserNavbar from '../userNavBar/UserNavbar'
import StudentDetailsLayout from '../studentDetail/StudentDetailsLayout'
import StudentsLayout from '../students/StudentsLayout'
import StudentFiltersLayout from '../studentFilters/StudentFiltersLayout'
import { StudentFiltersProvider } from '../../context/StudentFiltersContext'


const Landing = () => (
<div className="flex h-screen">
<MenuNavbar />
<div className="flex w-full md:w-[calc(100%-176px)] flex-col gap-3 p-2.5 md:p-2 md:pb-8 md:pr-14">
<UserNavbar />
<div className="flex h-[90vh] gap-10">
<div className="flex flex-1 w-auto h-full rounded-xl bg-white p-10">
<StudentFiltersLayout />
<StudentsLayout />
</div>
<StudentDetailsLayout />
</div>
<StudentFiltersProvider>
<div className="flex h-[90vh] gap-10">
<div className="flex flex-1 w-auto h-full rounded-xl bg-white p-10">
<StudentFiltersLayout />
<StudentsLayout />
</div>
<StudentDetailsLayout />
</div>
</StudentFiltersProvider>
</div>
</div>
)
);

export default Landing
export default Landing;
143 changes: 82 additions & 61 deletions src/components/studentFilters/StudentFiltersContent.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import axios from 'axios'
import { useEffect, useState } from 'react'
import axios from 'axios';
import React, { useContext, useEffect, useMemo, useState } from 'react';
import { StudentFiltersContext } from '../../context/StudentFiltersContext';

const StudentFiltersContent: React.FC = () => {
const [roles, setRoles] = useState<string[]>([])
const [development, setDevelopment] = useState<string[]>([])
const StudentFiltersProvider: React.FC = () => {
const [roles, setRoles] = useState<string[]>([]);
const [development, setDevelopment] = useState<string[]>([]);

const urlRoles =
'https://itaperfils.eurecatacademy.org/api/v1/specialization/list'
const urlDevelopment =
'https://itaperfils.eurecatacademy.org/api/v1/development/list'
const context = useContext(StudentFiltersContext);

if (!context) {
throw new Error('StudentFiltersContext must be provided');
}

const { selectedRoles, addRole, removeRole } = context;

const value = useMemo(() => ({
selectedRoles,
addRole,
removeRole,
}), [selectedRoles, addRole, removeRole]);

const urlRoles = 'https://itaperfils.eurecatacademy.org/api/v1/specialization/list';
const urlDevelopment = 'https://itaperfils.eurecatacademy.org/api/v1/development/list';

const fetchData = (
url: string,
Expand All @@ -17,67 +30,75 @@ const StudentFiltersContent: React.FC = () => {
axios
.get(url)
.then((response) => {
setData(response.data)
setData(response.data);
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error(error)
})
}
throw new Error(error);
});
};

useEffect(() => {
fetchData(urlRoles, setRoles)
}, [urlRoles])
fetchData(urlRoles, setRoles);
fetchData(urlDevelopment, setDevelopment);
}, [urlRoles, urlDevelopment]);

useEffect(() => {
fetchData(urlDevelopment, setDevelopment)
}, [urlDevelopment])
const toggleRole = (role: string) => {
if (selectedRoles.includes(role)) {
removeRole(role);
} else {
addRole(role);
}
};

return (
<div className="w-40 flex flex-col gap-16 flex:none">
<h3 className="text-2xl font-bold text-black-3">Filtros</h3>
<div className="flex flex-col gap-8">
<div className="flex flex-col gap-2">
<h4 className="font-bold">Roles</h4>
<div>
{roles.map((role) => (
<label
key={role}
className="label cursor-pointer justify-start p-1"
htmlFor="roleInput"
>
<input
id="roleInput"
type="checkbox"
className="border-gray-500 checkbox-primary checkbox mr-2 rounded-md border-2"
/>
<span>{role}</span>
</label>
))}
<StudentFiltersContext.Provider value={value}>
<div className="w-40 flex flex-col gap-16 flex:none">
<h3 className="text-2xl font-bold text-black-3">Filtros</h3>
<div className="flex flex-col gap-8">
<div className="flex flex-col gap-2">
<h4 className="font-bold">Roles</h4>
<div>
{roles.map((role) => (
<label
key={role}
className="label cursor-pointer justify-start p-1"
htmlFor={`roleInput-${role}`}
>
<input
id={`roleInput-${role}`}
type="checkbox"
className="border-gray-500 checkbox-primary checkbox mr-2 rounded-md border-2"
checked={selectedRoles.includes(role)}
onChange={() => toggleRole(role)}
/>
<span>{role}</span>
</label>
))}
</div>
</div>
</div>
<div className="flex flex-col gap-2">
<h4 className="font-bold">Desarrollo</h4>
<div>
{development.map((role) => (
<label
key={role}
className="label cursor-pointer justify-start p-1"
htmlFor="developmentInput"
>
<input
type="checkbox"
id="developmentInput"
className="border-gray-500 checkbox-primary checkbox mr-2 rounded-md border-2"
/>
<span>{role}</span>
</label>
))}
<div className="flex flex-col gap-2">
<h4 className="font-bold">Desarrollo</h4>
<div>
{development.map((tag) => (
<label
key={tag}
className="label cursor-pointer justify-start p-1"
htmlFor="developmentInput"
>
<input
type="checkbox"
id={`developmentInput-${tag}`}
className="border-gray-500 checkbox-primary checkbox mr-2 rounded-md border-2"
/>
<span>{tag}</span>
</label>
))}
</div>
</div>
</div>
</div>
</div>
)
}
</StudentFiltersContext.Provider>
);
};

export default StudentFiltersContent
export default StudentFiltersProvider;
2 changes: 1 addition & 1 deletion src/components/studentFilters/StudentFiltersLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import StudentFiltersContent from './StudentFiltersContent'

const StudentFiltersLayout: React.FC = () => (
<div className="hidden flex-col md:flex">
<StudentFiltersContent />
<StudentFiltersContent/>
</div>
)

Expand Down
Loading
Loading