Skip to content

Commit

Permalink
Teahcer list show, add teacher and delete teacher
Browse files Browse the repository at this point in the history
  • Loading branch information
Imon committed Nov 13, 2022
1 parent e07c6fa commit 90ac1f5
Show file tree
Hide file tree
Showing 16 changed files with 426 additions and 2 deletions.
43 changes: 43 additions & 0 deletions front-end-app/src/actions/TeacherAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import axios, { AxiosResponse } from 'axios';
import ApiServicePath from 'enums/ApiServicePath';
import UserResponse from 'interfaces/auth/UserResponse';
import ITeacher from 'interfaces/Teacher';

export const createTeacher = async (
teacher: ITeacher,
): Promise<AxiosResponse<UserResponse>> => {
return axios.post(
`${process.env.REACT_APP_SERVICE_API}/${ApiServicePath.Teacher}`,
teacher,
);
};

export const getTeachers = async (): Promise<AxiosResponse<ITeacher[]>> => {
return axios.get(
`${process.env.REACT_APP_SERVICE_API}/${ApiServicePath.Teacher}`,
);
};
export const getTeacher = async (
id: string,
): Promise<AxiosResponse<UserResponse>> => {
return axios.get(
`${process.env.REACT_APP_SERVICE_API}/${ApiServicePath.Teacher}/${id}`,
);
};

export const updateTeacher = async (
id: string,
): Promise<AxiosResponse<UserResponse>> => {
return axios.patch(
`${process.env.REACT_APP_SERVICE_API}/${ApiServicePath.Teacher}/${id}`,
);
};

export const deleteTeacher = async (
id: string,
): Promise<AxiosResponse<UserResponse>> => {
return axios.delete(
`${process.env.REACT_APP_SERVICE_API}/${ApiServicePath.Teacher}/${id}`,
);
};
6 changes: 6 additions & 0 deletions front-end-app/src/assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@
@import url('./module/utilities.css');
@import url('./module/forms.css'); */
@import url('./module/font-awesome.css');

.ant-table-thead > tr > th, .ant-table-tbody > tr > td, .ant-table tfoot > tr > th, .ant-table tfoot > tr > td {
position: relative;
padding: 5px 16px !important;
overflow-wrap: break-word;
}
68 changes: 68 additions & 0 deletions front-end-app/src/components/teacher/TeacherForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { Button, Card, CardBody, Input } from '@material-tailwind/react';
import ITeacher from 'interfaces/Teacher';
import { Dispatch, FC, SetStateAction } from 'react';

interface Props {
teacher: ITeacher;
onSubmitForm: () => void;
setTeacher: Dispatch<SetStateAction<ITeacher>>;
isLoading: boolean;
}

const TeacherForm: FC<Props> = ({
teacher,
setTeacher,
onSubmitForm,
isLoading,
}) => {
const onChange = (e: React.FormEvent<HTMLInputElement>) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const event = e as unknown as any;
setTeacher({ ...teacher, [event.target.name]: event.target.value });
};
const isValidForm = teacher.phone && teacher.name && teacher.email;
return (
<Card className="">
<h1 className="text-center">Teacher Form</h1>
<CardBody className="flex w-full flex-col gap-3">
<Input
label="Teacher Name"
type="text"
value={teacher.name}
name="name"
onChange={onChange}
required
/>
<Input
label="Teacher Email"
value={teacher.email}
name="email"
type="email"
onChange={onChange}
required
/>
<Input
label="Teacher Phone"
value={teacher.phone}
name="phone"
type="text"
onChange={onChange}
required
/>

<div className="text-center">
<Button
size="sm"
type="button"
onClick={onSubmitForm}
disabled={!isValidForm || isLoading}
>
Submit
</Button>
</div>
</CardBody>
</Card>
);
};
export default TeacherForm;
87 changes: 87 additions & 0 deletions front-end-app/src/components/teacher/TeacherList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Card, CardBody, IconButton } from '@material-tailwind/react';
import { deleteTeacher } from 'actions/TeacherAction';
import NubTable from 'components/common/table/NubTable';
import actionTypes from 'context/actionTypes';
import { useAppContext } from 'context/appContext';
import EntityName from 'enums/EntityName';
import ITeacher from 'interfaces/Teacher';
import { FC, useEffect, useMemo, useState } from 'react';
import { useMutation } from 'react-query';
import { toastSuccess } from 'services/ToasterServices';
import { httpErrorDisplay } from 'services/UtilsService';

interface Props {
data: ITeacher[];
}

const TeacherList: FC<Props> = ({ data }) => {
const appContext = useAppContext() as any;
const [teacherId, setTeacherId] = useState<string>('');
const { mutate: deleteMutate } = useMutation(
async () => {
return deleteTeacher(teacherId);
},
{
onSuccess: () => {
toastSuccess('Delete Successfully');
appContext.dispatch({
type: actionTypes.DELETE_TEACHER,
payload: teacherId,
});
setTeacherId('');
},
onError: (err) => {
httpErrorDisplay(err, EntityName.Teacher);
setTeacherId('');
},
},
);
useEffect(() => {
if (teacherId) {
deleteMutate();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [teacherId]);
const columns = useMemo(
() => [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Email',
dataIndex: 'email',
},
{
title: 'Phone',
dataIndex: 'phone',
},
{
title: 'Delete',
dataIndex: 'id',
render: (id: string) => (
<IconButton
size="sm"
color="red"
onClick={() => setTeacherId(id)}
disabled={id === teacherId}
>
<i className="fas fa-times" />
</IconButton>
),
},
],
// eslint-disable-next-line react-hooks/exhaustive-deps
[],
);

return (
<Card className="container">
<CardBody>
<h1 className="text-left">Teacher list</h1>
<NubTable data={data} columns={columns} />
</CardBody>
</Card>
);
};
export default TeacherList;
9 changes: 9 additions & 0 deletions front-end-app/src/context/actionTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,13 @@ export default {
CACHE_COURSES: 'CACHE_COURSES',
ADD_COURSE: 'ADD_COURSE',
DELETE_COURSE: 'DELETE_COURSE',
CACHE_TEACHERS: 'CACHE_TEACHERS',
ADD_TEACHER: 'ADD_TEACHER',
DELETE_TEACHER: 'DELETE_TEACHER',
CACHE_ROOMS: 'CACHE_ROOMS',
ADD_ROOM: 'ADD_ROOM',
DELETE_ROOM: 'DELETE_ROOM',
CACHE_BOOKINGS: 'CACHE_BOOKINGS',
ADD_BOOKING: 'ADD_BOOKING',
DELETE_BOOKING: 'DELETE_BOOKING',
};
35 changes: 35 additions & 0 deletions front-end-app/src/context/reducers/BookingReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import actionTypes from 'context/actionTypes';
/* eslint-disable import/no-mutable-exports */
export const bookingsInitialState: any = {
bookings: [],
};

export const bookingReducer = (
state = bookingsInitialState,
action: any = undefined,
) => {
switch (action.type) {
case actionTypes.CACHE_BOOKINGS: {
return {
...state,
bookings: action.payload,
};
}
case actionTypes.ADD_BOOKING: {
return {
...state,
bookings: [...[action.payload], ...state.bookings],
};
}
case actionTypes.DELETE_BOOKING: {
return {
...state,
bookings: [...state.bookings].filter(
(booking) => booking.id !== action.payload,
),
};
}
default:
return state;
}
};
33 changes: 33 additions & 0 deletions front-end-app/src/context/reducers/RoomReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import actionTypes from 'context/actionTypes';
/* eslint-disable import/no-mutable-exports */
export const roomsInitialState: any = {
rooms: [],
};

export const roomReducer = (
state = roomsInitialState,
action: any = undefined,
) => {
switch (action.type) {
case actionTypes.CACHE_ROOMS: {
return {
...state,
rooms: action.payload,
};
}
case actionTypes.ADD_ROOM: {
return {
...state,
rooms: [...[action.payload], ...state.rooms],
};
}
case actionTypes.DELETE_ROOM: {
return {
...state,
rooms: [...state.rooms].filter((room) => room.id !== action.payload),
};
}
default:
return state;
}
};
35 changes: 35 additions & 0 deletions front-end-app/src/context/reducers/TeacherReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import actionTypes from 'context/actionTypes';
/* eslint-disable import/no-mutable-exports */
export const teachersInitialState: any = {
teachers: [],
};

export const teacherReducer = (
state = teachersInitialState,
action: any = undefined,
) => {
switch (action.type) {
case actionTypes.CACHE_TEACHERS: {
return {
...state,
teachers: action.payload,
};
}
case actionTypes.ADD_TEACHER: {
return {
...state,
teachers: [...[action.payload], ...state.teachers],
};
}
case actionTypes.DELETE_TEACHER: {
return {
...state,
teachers: [...state.teachers].filter(
(teacher) => teacher.id !== action.payload,
),
};
}
default:
return state;
}
};
14 changes: 13 additions & 1 deletion front-end-app/src/context/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ import {
courseReducer,
coursesInitialState,
} from 'context/reducers/CourseReducer';
import { bookingReducer, bookingsInitialState } from './BookingReducer';
import { roomReducer, roomsInitialState } from './RoomReducer';
import { teacherReducer, teachersInitialState } from './TeacherReducer';
import { userInitialState, userReducer } from './userReducer';

export const initialState = {
...userInitialState,
...coursesInitialState,
...teachersInitialState,
...roomsInitialState,
...bookingsInitialState,
};

// TODO fix type
Expand All @@ -19,4 +25,10 @@ const combineReducers =
}
return state;
};
export default combineReducers(userReducer, courseReducer);
export default combineReducers(
userReducer,
courseReducer,
teacherReducer,
roomReducer,
bookingReducer,
);
3 changes: 3 additions & 0 deletions front-end-app/src/enums/ApiServicePath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ const BasePath = 'rest/api-service/';
const ApiServicePath = {
SignIn: `${BasePath}auth/sign-in`,
Course: `${BasePath}course`,
Teacher: `${BasePath}teacher`,
Room: `${BasePath}room`,
Booking: `${BasePath}booking`,
};
export default ApiServicePath;
3 changes: 3 additions & 0 deletions front-end-app/src/enums/EntityName.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
enum EntityName {
User = 'User',
Course = 'Course',
Teacher = 'Teacher',
Room = 'Room',
Booking = 'Booking',
}
export default EntityName;
2 changes: 1 addition & 1 deletion front-end-app/src/interfaces/Course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ interface ICourse {
credit: number;
department: Department;
semester?: number;
isAutoAssign?: boolean;
isAutoAssign: boolean;
}
export default ICourse;
7 changes: 7 additions & 0 deletions front-end-app/src/interfaces/Teacher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
interface ITeacher {
id: string;
name: string;
phone: string;
email: string;
}
export default ITeacher;
Loading

0 comments on commit 90ac1f5

Please sign in to comment.