Skip to content

Commit

Permalink
CRUD of coaches
Browse files Browse the repository at this point in the history
  • Loading branch information
Janderson Souza Matias authored and Janderson Souza Matias committed Feb 5, 2024
1 parent aa06b74 commit 4934ad9
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 47 deletions.
5 changes: 5 additions & 0 deletions src/components/Navbar/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export const MenuItems = [
label: 'schools',
route: `/${import.meta.env.VITE_COUNTRY}/admin/schools`,
},
{
icon: 'user',
label: 'coaches',
route: `/${import.meta.env.VITE_COUNTRY}/admin/coaches`,
},
{
icon: 'calender',
label: 'coaches-over-time',
Expand Down
3 changes: 2 additions & 1 deletion src/components/Table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ const Table: React.FC<Props> = ({ columns, data, filters, topSession }) => {
data.filter((item) => {
for (let index = 0; index < props.length; index++) {
const prop = props[index];
if (!(item[prop] as string).includes(filter[prop])) return false;
console.log(item[prop], filter[prop]);
if (!(`${item[prop]}`.toLocaleUpperCase() as string).includes(filter[prop])) return false;
}
return true;
}),
Expand Down
23 changes: 23 additions & 0 deletions src/i18n/langs/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const enTranslation = {
activate: 'Activate',
deactivate: 'Deactivate',
total_items: 'Total items: ',
'view-details': 'View details',
save: 'Save',
edit: 'Edit',
view: 'View',
Expand Down Expand Up @@ -42,6 +43,7 @@ const enTranslation = {
settings: 'Settings',
dashboard: 'Dashboard',
questionnaire: 'QUESTIONNAIRE',
coaches: 'Coaches',
'teaching-practices': 'Teaching practices',
'coaching-sessions': 'Coaching sessions',
data: 'DATA',
Expand Down Expand Up @@ -151,6 +153,27 @@ const enTranslation = {
},
},

coaches: {
'new-coach': 'New coach',
'update-coach': 'Update coach',

name: 'Name',
surname: 'Surname',
email: 'Email',
phone: 'Phone',

'full-name': 'Full name',
'total-teacher-coached': 'Total teacher coached',

'delete-title': 'Confirm deletion',
'delete-detail': 'Are you sure you want to delete this coach?',
'detail-title': 'Coach details',

school: 'School name',
teacher: 'Teacher name',
'session-date': 'Session date',
},

'coach-over-time': {
filters: {
region: 'Region',
Expand Down
24 changes: 24 additions & 0 deletions src/i18n/langs/np.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const npTranslation = {
activate: 'सक्रिय गर्नुहोस्',
deactivate: 'निष्क्रिय गर्नुहोस्',
total_items: 'कुल वस्तुहरू: ',
'view-details': 'विवरण हेर्नुहोस्',
save: 'बचत गर्नुहोस्',
edit: 'सम्पादन गर्नुहोस्',
view: 'हेर्नुहोस्',
Expand Down Expand Up @@ -41,6 +42,7 @@ const npTranslation = {
dashboard: 'मुख्य पृष्ठ',
questionnaire: 'प्रश्नावली',
'teaching-practices': 'शिक्षण अभ्यासहरू',
coaches: 'प्रशिक्षकहरू',
data: 'डाटा',
syncs: 'अपलोड र डाउनलोड',
logout: 'एपबाट लगआउट गर्नुहोस्',
Expand Down Expand Up @@ -147,6 +149,28 @@ const npTranslation = {
emis: 'एमिस नम्बर',
},
},

coaches: {
'new-coach': 'नयाँ प्रशिक्षक',
'update-coach': 'प्रशिक्षक अपडेट गर्नुहोस्',

name: 'नाम',
surname: 'थर',
email: 'इमेल',
phone: 'फोन',

'full-name': 'पूरा नाम',
'total-teacher-coached': 'कुल शिक्षक प्रशिक्षित',

'delete-title': 'मेटाउने पुष्टि',
'delete-detail': 'के तपाईं यो प्रशिक्षकलाई मेटाउन निश्चित हुनुहुन्छ?',
'detail-title': 'प्रशिक्षक विवरण',

school: 'स्कूलको नाम',
teacher: 'शिक्षकको नाम',
'session-date': 'सत्र मिति',
},

'coach-over-time': {
filters: {
school: 'विद्यालय',
Expand Down
76 changes: 76 additions & 0 deletions src/pages/Coaches/CoachDetail/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { ICoach } from '@/types';
import {
Button,
Drawer,
DrawerOverlay,
DrawerContent,
DrawerCloseButton,
DrawerHeader,
DrawerBody,
DrawerFooter,
VStack,
Text,
HStack,
Divider,
} from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';

type Props = {
isOpen: boolean;
coach?: ICoach;
onClose: () => void;
};

const CoachDetail: React.FC<Props> = ({ isOpen, coach, onClose }) => {
const { t } = useTranslation();

return (
<Drawer isOpen={isOpen} placement="right" onClose={onClose} size="md">
<DrawerOverlay />
<DrawerContent roundedLeft={14}>
<DrawerCloseButton mt={2} color="Primary.$200" />

<DrawerHeader>{t('coaches.detail-title')}</DrawerHeader>

<DrawerBody>
<VStack w="full" alignItems="start">
<Divider mb="12px" />

<Text>{`${coach?.name} ${coach?.surname}`}</Text>
<Text>{`${coach?.email || '-'}`}</Text>

<Divider mt="12px" />

<HStack w="full" bg="#eee" p={'8px'}>
<Text fontWeight="bold" flex={1}>
{t('coaches.school')}
</Text>
<Text fontWeight="bold" flex={1}>
{t('coaches.teacher')}
</Text>
<Text fontWeight="bold" flex={1}>
{t('coaches.session-date')}
</Text>
</HStack>

{coach?.sessions?.map((session, index) => (
<HStack key={session.id} w="full" px="8px" py="4px" bg={index % 2 ? '#f5f5f5' : '#fff'}>
<Text flex={1}>{session.school.name}</Text>
<Text flex={1}>{session.teacher.name}</Text>
<Text flex={1}>{new Date(session.created_at || '').toLocaleDateString()}</Text>
</HStack>
))}
</VStack>
</DrawerBody>

<DrawerFooter mt="auto">
<Button variant="outline" mr={'auto'} onClick={onClose}>
{t('common.cancel')}
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
);
};

export default CoachDetail;
95 changes: 66 additions & 29 deletions src/pages/Coaches/CoachForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import {
DrawerBody,
DrawerFooter,
} from '@chakra-ui/react';
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';

type Props = {
isOpen: boolean;
Expand All @@ -23,48 +25,83 @@ type Props = {
onSubmit: (coach: Partial<ICoach>) => void;
};

const CoachForm: React.FC<Props> = ({ isOpen, isSubmitting, coachToEdit, onClose, onSubmit }) => {
const CoachForm: React.FC<Props> = ({ isOpen, coachToEdit, onClose, onSubmit }) => {
const { t } = useTranslation();
const {
register,
handleSubmit,
resetField,
formState: { errors },
} = useForm();

useEffect(() => {
if (coachToEdit) {
resetField('name');
resetField('surname');
}
}, [coachToEdit]);

return (
<Drawer isOpen={isOpen} placement="right" onClose={onClose} size="md">
<DrawerOverlay />
<DrawerContent roundedLeft={14}>
<form onSubmit={handleSubmit(onSubmit)} style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
<DrawerCloseButton mt={2} color="Primary.$200" />
{isOpen && (
<form onSubmit={handleSubmit(onSubmit)} style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
<DrawerCloseButton mt={2} color="Primary.$200" />

<DrawerHeader>{t(coachToEdit ? 'coaches.update-coach' : 'coaches.new-coach')}</DrawerHeader>

<DrawerBody>
<FormControl isInvalid={!!errors.name}>
<FormLabel htmlFor="name">{t('coaches.name')}</FormLabel>
<Input id="name" defaultValue={coachToEdit?.name} {...register('name', { required: true })} />
<FormErrorMessage>
{errors.name && errors.name.type === 'required' && 'Name is required'}
</FormErrorMessage>
</FormControl>

<FormControl mt="16px" isInvalid={!!errors.surname}>
<FormLabel htmlFor="surname">{t('coaches.surname')}</FormLabel>
<Input id="surname" defaultValue={coachToEdit?.surname} {...register('surname', { required: true })} />
<FormErrorMessage>
{errors.surname && errors.surname.type === 'required' && 'Surname is required'}
</FormErrorMessage>
</FormControl>

<DrawerHeader>{coachToEdit ? 'Update teacher' : 'New Teacher'}</DrawerHeader>
<FormControl mt="16px" isInvalid={!!errors.email}>
<FormLabel htmlFor="email">{t('coaches.email')}</FormLabel>
<Input
id="email"
type="email"
defaultValue={coachToEdit?.email}
{...register('email', { required: true })}
/>
<FormErrorMessage>
{errors.email && errors.email.type === 'required' && 'Email is required'}
</FormErrorMessage>
</FormControl>

<DrawerBody>
<FormControl isInvalid={!!errors.name}>
<FormLabel htmlFor="name">Nome</FormLabel>
<Input id="name" defaultValue={coachToEdit?.name} {...register('name', { required: true })} />
<FormErrorMessage>
{errors.name && errors.name.type === 'required' && 'Name is required'}
</FormErrorMessage>
</FormControl>
<FormControl mt="16px" isInvalid={!!errors.surname}>
<FormLabel htmlFor="surname">Surname</FormLabel>
<Input id="surname" defaultValue={coachToEdit?.surname} {...register('surname', { required: true })} />
<FormErrorMessage>
{errors.surname && errors.surname.type === 'required' && 'Surname is required'}
</FormErrorMessage>
</FormControl>
</DrawerBody>
<FormControl mt="16px">
<FormLabel htmlFor="phone">{t('coaches.phone')}</FormLabel>
<Input
id="phone"
type="tel"
defaultValue={coachToEdit?.phone}
{...register('phone', { required: false })}
/>
</FormControl>
</DrawerBody>

<DrawerFooter mt="auto">
<Button colorScheme="blue" mr={3} type="submit">
Save
</Button>
<Button variant="outline" mr={'auto'} onClick={onClose}>
Cancel
</Button>
</DrawerFooter>
</form>
<DrawerFooter mt="auto">
<Button colorScheme="blue" mr={3} type="submit">
{t('common.save')}
</Button>
<Button variant="outline" mr={'auto'} onClick={onClose}>
{t('common.cancel')}
</Button>
</DrawerFooter>
</form>
)}
</DrawerContent>
</Drawer>
);
Expand Down
24 changes: 13 additions & 11 deletions src/pages/Coaches/CoachList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,27 @@ import Icon from '@/components/Base/Icon';
import { useTranslation } from 'react-i18next';

type Props = {
coachs: ICoach[];
coaches: ICoach[];
handleEdit: (coach: ICoach) => void;
handleDelete: (coach: ICoach) => void;
handleView: (coach: ICoach) => void;
};

const CoachList: React.FC<Props> = ({ coachs, handleDelete, handleEdit }) => {
const CoachList: React.FC<Props> = ({ coaches, handleDelete, handleEdit, handleView }) => {
const { t } = useTranslation();

return (
<Table
data={coachs}
data={coaches}
filters={[{ label: t('coaches.full-name'), prop: 'name' }]}
columns={[
{
renderColumn: (item: ICoach) => item.name,
title: 'Name',
renderColumn: (item: ICoach) => `${item.name} ${item.surname}`,
title: t('coaches.full-name'),
},
{
renderColumn: (item: ICoach) => item.surname,
title: 'Surname',
},
{
renderColumn: (item: ICoach) => item.coachSchools?.length || '0',
title: 'Schools count',
renderColumn: (item: ICoach) => `${item.sessions?.length}`,
title: t('coaches.total-teacher-coached'),
},
{
renderColumn: (item: ICoach) => (
Expand All @@ -37,6 +35,10 @@ const CoachList: React.FC<Props> = ({ coachs, handleDelete, handleEdit }) => {
<Icon name="ellipsis-v" size={16} />
</MenuButton>
<MenuList>
<MenuItem gap="8px" alignItems="center" onClick={() => handleView(item)}>
<Icon name="eye" />
{t('common.view-details')}
</MenuItem>
<MenuItem gap="8px" alignItems="center" onClick={() => handleEdit(item)}>
<Icon name="pen" />
{t('common.edit')}
Expand Down
Loading

0 comments on commit 4934ad9

Please sign in to comment.