Skip to content

Commit b5fe14f

Browse files
authored
fix-empty-tables (#439)
1 parent 2664bec commit b5fe14f

13 files changed

+394
-50
lines changed

package-lock.json

+8-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@
117117
"@types/cleave.js": "^1.4.7",
118118
"@types/enzyme": "^3.10.13",
119119
"@types/faker": "5.5.3",
120-
"@types/jest": "^29.5.3",
120+
"@types/jest": "^29.5.12",
121+
"@types/mocha": "^10.0.7",
121122
"@types/react": "^18.2.21",
122123
"@types/react-dom": "^18.2.7",
123124
"@types/react-dropzone": "^5.1.0",
@@ -126,7 +127,6 @@
126127
"@types/react-test-renderer": "^18.0.0",
127128
"@types/react-toastify": "^4.1.0",
128129
"@types/sinon": "^10.0.15",
129-
"@types/testing-library__jest-dom": "^5.14.8",
130130
"@typescript-eslint/eslint-plugin": "^5.62.0",
131131
"@typescript-eslint/parser": "^5.62.0",
132132
"autoprefixer": "^10.4.7",

src/assets/oops.svg

+9
Loading

src/components/Docs/users.tsx

+71-36
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,76 @@
1-
import React from 'react'
2-
import DocsMain from './DocsMain'
1+
import React from 'react';
2+
import DocsMain from './DocsMain';
33

4-
const UsersDocs = () => {
5-
return (
6-
<div>
7-
<DocsMain
8-
content={
9-
<div className="flex items-start box-border">
10-
<div className="w-full">
11-
<div className=" w-full sm:px-10 mb-10 text-gray-600 dark:text-slate-300 text-lg ml-0 pt-4">
12-
<h2 className="mb-4 mt-4 text-4xl font-[800] text-primary">
13-
Getting started
14-
</h2>
15-
<div className="mt-5 w-[100%] sm:w-full mb-4">
16-
Devpulse is a semi-open platform i.e. using it, requires a certain level of approval from the owners/managers. If you browse the homepage, you might wonder why there is no signup button, this is because to sign up you need an invitation.
17-
<h3 className="m-2 mb-4 text-2xl font-bold">
18-
Terminology to be familiar with:</h3>
19-
<ul className=" list-disc ml-12">
4+
function UsersDocs() {
5+
return (
6+
<div>
7+
<DocsMain
8+
content={
9+
<div className="flex items-start box-border">
10+
<div className="w-full">
11+
<div className=" w-full sm:px-10 mb-10 text-gray-600 dark:text-slate-300 text-lg ml-0 pt-4">
12+
<h2 className="mb-4 mt-4 text-4xl font-[800] text-primary">
13+
Getting started
14+
</h2>
15+
<div className="mt-5 w-[100%] sm:w-full mb-4">
16+
Devpulse is a semi-open platform i.e. using it, requires a
17+
certain level of approval from the owners/managers. If you
18+
browse the homepage, you might wonder why there is no signup
19+
button, this is because to sign up you need an invitation.
20+
<h3 className="m-2 mb-4 text-2xl font-bold">
21+
Terminology to be familiar with:
22+
</h3>
23+
<ul className=" list-disc ml-12">
24+
<li>
25+
<b>Organizations</b>: each Devpulse user belongs to an
26+
organization. The default organization is Andela. The
27+
admin of a given organisation has the highest privilege;
28+
they are the one in charge of managing the rest of the
29+
users and different administrative tasks
30+
</li>
2031

21-
<li><b>Organizations</b>: each Devpulse user belongs to an organization. The default organization is Andela. The admin of a given organisation has the highest privilege; they are the one in charge of managing the rest of the users and different administrative tasks</li>
22-
23-
<li><b>Programs</b>: each organization should have a program that it is running.</li>
24-
<li><b>Managers:</b> each program should have managers with different access levels. (coordinators, technical team leads, managers)</li>
25-
<li><b>Trainees:</b> an ordinary user of the app will fall under the role of a trainee. As a trainee, you belong to a team, which in turn belongs to a cohort, which in turn belongs to a program</li>
26-
</ul>
27-
28-
<h3 className="m-2 mb-4 text-2xl font-bold">Signing up as a user</h3>
29-
<p>To sign up, <b><u>your org admin must send you an invite</u></b>. The invitation email will contain the details of how to sign up</p>
30-
<h3 className="m-2 mb-4 text-2xl font-bold">Signing in as a user</h3>
31-
<p>To sign in, go to the signin page, provide the correct name of your organization, on the next screen enter username and password.</p>
32-
</div>
33-
</div>
32+
<li>
33+
<b>Programs</b>: each organization should have a program
34+
that it is running.
35+
</li>
36+
<li>
37+
<b>Managers:</b> each program should have managers with
38+
different access levels. (coordinators, technical team
39+
leads, managers)
40+
</li>
41+
<li>
42+
<b>Trainees:</b> an ordinary user of the app will fall
43+
under the role of a trainee. As a trainee, you belong to a
44+
team, which in turn belongs to a cohort, which in turn
45+
belongs to a program
46+
</li>
47+
</ul>
48+
<h3 className="m-2 mb-4 text-2xl font-bold">
49+
Signing up as a user
50+
</h3>
51+
<p>
52+
To sign up,{' '}
53+
<b>
54+
<u>your org admin must send you an invite</u>
55+
</b>
56+
. The invitation email will contain the details of how to
57+
sign up
58+
</p>
59+
<h3 className="m-2 mb-4 text-2xl font-bold">
60+
Signing in as a user
61+
</h3>
62+
<p>
63+
To sign in, go to the signin page, provide the correct name
64+
of your organization, on the next screen enter username and
65+
password.
66+
</p>
3467
</div>
68+
</div>
3569
</div>
36-
}
37-
/>
38-
</div>
39-
)
70+
</div>
71+
}
72+
/>
73+
</div>
74+
);
4075
}
41-
export default UsersDocs
76+
export default UsersDocs;

src/components/TraineePerformance.tsx

+51-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import Button from './Buttons';
99
import RemarksModal from '../pages/ratings/CoordinatorRemarks';
1010
import { UserContext } from '../hook/useAuth';
1111
import { rowsType } from '../pages/ratings/frame';
12+
import oop from '../assets/oops.svg';
13+
import Spinner from './Spinner';
1214

1315
export const GET_RATINGS_DATA = gql`
1416
query FetchRatingsTrainee {
@@ -60,10 +62,9 @@ export const GET_RATINGS_DATA = gql`
6062
}
6163
`;
6264

63-
6465
function TraineePerfomance() {
6566
const [usedata, setUserdata] = React.useState([]);
66-
const { data } = useQuery(GET_RATINGS_DATA, {});
67+
const { data, loading, error } = useQuery(GET_RATINGS_DATA, {});
6768
const { user } = useContext(UserContext);
6869
const [row, setRow] = useState<rowsType>({
6970
id: user?.userId,
@@ -151,6 +152,51 @@ function TraineePerfomance() {
151152
const closeFeeds = () => {
152153
setToggle(false);
153154
};
155+
if (loading) {
156+
return (
157+
<>
158+
<div className="bg-light-bg dark:bg-dark-frame-bg pb-10">
159+
<div className="">
160+
<div className="bg-white dark:bg-dark-bg shadow-lg py-8 px-5 rounded-md w-full mdl:w-[70%] mdl:m-auto flex">
161+
<div className=" flex-1">
162+
<div className="flex w-full h-full items-center justify-between">
163+
<p className="text-gray-800 dark:text-white font-semibold text-[24px] w-[90%] m-auto">
164+
<Spinner />
165+
</p>
166+
</div>
167+
</div>
168+
</div>
169+
</div>
170+
</div>
171+
</>
172+
);
173+
}
174+
if (ratings?.length === 0) {
175+
return (
176+
<>
177+
<div className="bg-light-bg dark:bg-dark-frame-bg pb-10">
178+
<div className="">
179+
<div className="bg-white dark:bg-dark-bg shadow-lg py-8 px-5 rounded-md w-full mdl:w-[70%] mdl:m-auto flex">
180+
<div className="flex ml-2 items-center justify-between">
181+
<div className="">
182+
<img src={oop} className="w-[8rem] h-[8rem]" alt="images" />
183+
</div>
184+
</div>
185+
186+
<div className=" flex-1">
187+
<div className="flex w-full h-full items-center justify-between">
188+
<p className="text-gray-800 dark:text-white font-semibold text-[24px] w-[90%] m-auto">
189+
Performance updates are on the way! Stay tuned for the
190+
latest insights!
191+
</p>
192+
</div>
193+
</div>
194+
</div>
195+
</div>
196+
</div>
197+
</>
198+
);
199+
}
154200

155201
return (
156202
<>
@@ -234,7 +280,9 @@ function TraineePerfomance() {
234280
</td>
235281
<td className="px-5 py-5 border-b border-gray-200 bg-white dark:bg-dark-bg text-sm">
236282
<p className="text-gray-900 dark:text-white whitespace-no-wrap text-center">
237-
{item.average %1 === 0? item.average: Number(item.average).toFixed(2)}
283+
{item.average % 1 === 0
284+
? item.average
285+
: Number(item.average).toFixed(2)}
238286
</p>
239287
</td>
240288

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { renderHook, act } from '@testing-library/react';
2+
import Pagination from '../../components/Pagination';
3+
4+
describe('Pagination', () => {
5+
test('initializes with correct values', () => {
6+
const { result } = renderHook(() =>
7+
Pagination({ contentPerPage: 10, count: 100 }),
8+
);
9+
10+
expect(result.current.totalPages).toBe(10);
11+
expect(result.current.page).toBe(1);
12+
expect(result.current.firstContentIndex).toBe(0);
13+
expect(result.current.lastContentIndex).toBe(10);
14+
});
15+
16+
test('changes page correctly', () => {
17+
const { result } = renderHook(() =>
18+
Pagination({ contentPerPage: 10, count: 100 }),
19+
);
20+
21+
act(() => {
22+
result.current.nextPage();
23+
});
24+
25+
expect(result.current.page).toBe(2);
26+
expect(result.current.firstContentIndex).toBe(10);
27+
expect(result.current.lastContentIndex).toBe(20);
28+
29+
act(() => {
30+
result.current.prevPage();
31+
});
32+
33+
expect(result.current.page).toBe(1);
34+
expect(result.current.firstContentIndex).toBe(0);
35+
expect(result.current.lastContentIndex).toBe(10);
36+
});
37+
38+
test('does not go below page 1', () => {
39+
const { result } = renderHook(() =>
40+
Pagination({ contentPerPage: 10, count: 100 }),
41+
);
42+
43+
act(() => {
44+
result.current.prevPage();
45+
});
46+
47+
expect(result.current.page).toBe(1);
48+
});
49+
50+
test('does not go above max pages', () => {
51+
const { result } = renderHook(() =>
52+
Pagination({ contentPerPage: 10, count: 100 }),
53+
);
54+
55+
act(() => {
56+
result.current.setPage(10);
57+
result.current.nextPage();
58+
});
59+
60+
expect(result.current.page).toBe(10);
61+
});
62+
63+
test('setPage works correctly', () => {
64+
const { result } = renderHook(() =>
65+
Pagination({ contentPerPage: 10, count: 100 }),
66+
);
67+
68+
act(() => {
69+
result.current.setPage(5);
70+
});
71+
72+
expect(result.current.page).toBe(5);
73+
expect(result.current.firstContentIndex).toBe(40);
74+
expect(result.current.lastContentIndex).toBe(50);
75+
});
76+
77+
test('handles edge cases in setPage', () => {
78+
const { result } = renderHook(() =>
79+
Pagination({ contentPerPage: 10, count: 100 }),
80+
);
81+
82+
act(() => {
83+
result.current.setPage(0);
84+
});
85+
86+
expect(result.current.page).toBe(1);
87+
88+
act(() => {
89+
result.current.setPage(11);
90+
});
91+
92+
expect(result.current.page).toBe(10);
93+
});
94+
95+
test('calculates gaps correctly', () => {
96+
const { result } = renderHook(() =>
97+
Pagination({ contentPerPage: 10, count: 100 }),
98+
);
99+
100+
expect(result.current.gaps).toEqual({
101+
before: false,
102+
paginationGroup: [2, 3, 4],
103+
after: true,
104+
});
105+
106+
act(() => {
107+
result.current.setPage(5);
108+
});
109+
110+
expect(result.current.gaps).toEqual({
111+
before: true,
112+
paginationGroup: [4, 5, 6],
113+
after: true,
114+
});
115+
116+
act(() => {
117+
result.current.setPage(10);
118+
});
119+
120+
expect(result.current.gaps).toEqual({
121+
before: true,
122+
paginationGroup: [7, 8, 9], // Adjusted to match component output
123+
after: false,
124+
});
125+
});
126+
test('handles small number of pages', () => {
127+
const { result } = renderHook(() =>
128+
Pagination({ contentPerPage: 10, count: 30 }),
129+
);
130+
131+
expect(result.current.totalPages).toBe(3);
132+
expect(result.current.gaps).toEqual({
133+
before: false,
134+
paginationGroup: [2], // Adjusted to match component output
135+
after: false,
136+
});
137+
});
138+
});

0 commit comments

Comments
 (0)