Skip to content

Commit

Permalink
create region crud
Browse files Browse the repository at this point in the history
  • Loading branch information
Janderson Souza Matias authored and Janderson Souza Matias committed Nov 27, 2023
1 parent aaebfe3 commit 1cede63
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 56 deletions.
10 changes: 10 additions & 0 deletions src/i18n/langs/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const enTranslation = {
actions: 'Actions',
activate: 'Activate',
deactivate: 'Deactivate',
save: 'Save',
edit: 'Edit',
view: 'View',
delete: 'Delete',
Expand Down Expand Up @@ -190,6 +191,15 @@ const enTranslation = {
language: {
title: 'Change language',
},
region: {
title: 'Regions',
new: 'New region',
edit: 'Edit',
total_schools: 'Total school: {{ value }}',
form: {
name: 'Name',
},
},
},
},
};
Expand Down
50 changes: 31 additions & 19 deletions src/pages/Dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import { useEffect, useState } from 'react';
import { Box, Button, Center, Flex, HStack, Select, Spinner, Text, VStack, useBreakpointValue } from '@chakra-ui/react';
import { IDashboard, ISchool, ITeachingPractices } from '@/types';
import { IDashboard, IRegion, ISchool, ITeachingPractices } from '@/types';
import DashboardService from '@/services/dashboard';
import Loader from '@/components/Base/Loader';
import { CardValue } from './components/CardValue';
import { SpeedometerGraph } from './components/SpeedometerGraph';
import { DoughnutGraph } from './components/DoughnutGraph';
import { BarGraph } from './components/BarGraph';
import { HorizontalBar } from './components/HorizontalBar';
import { REGIONS } from '@/common/constants';
import { useUserContext } from '@/contexts/UserContext';
import { ROLES } from '@/common/user';
import SelectDistrict from '@/components/SelectDistrict';
import { useTranslation } from 'react-i18next';
import RegionService from '@/services/region';

const DashboardPage: React.FC = () => {
const { user } = useUserContext();
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [dashboard, setDashboard] = useState<IDashboard>();
const [region, setRegion] = useState(user?.region);
const [regions, setRegions] = useState<IRegion[]>();
const [regionId, setRegionId] = useState(user?.region_id);
const [district, setDistrict] = useState(user?.district);
const [schoolName, setSchoolName] = useState<string>();
const [schoolList, setSchoolList] = useState<ISchool[]>([]);
Expand All @@ -29,11 +30,18 @@ const DashboardPage: React.FC = () => {
useEffect(() => {
if (!loading) {
setLoading(true);

if (!regions) {
RegionService.getRegions().then(setRegions);
}

let schoolId: string | undefined;

if (schoolName) {
schoolId = schoolList.find((school) => school.name === schoolName)?.id;
}
DashboardService.getData(region, district, schoolId).then((data) => {

DashboardService.getData(regionId, district, schoolId).then((data) => {
const { schools, ...dash } = data;
if (schools) {
setSchoolList(schools);
Expand All @@ -43,10 +51,10 @@ const DashboardPage: React.FC = () => {
setLoading(false);
});
}
}, [region, district, schoolName]);
}, [regionId, district, schoolName]);

const handleRegion = (newRegion: string) => {
setRegion(newRegion);
const handleRegion = (regionId: string) => {
setRegionId(regionId);
setSchoolList([]);
setSchoolName(undefined);
setDistrict(undefined);
Expand All @@ -62,17 +70,21 @@ const DashboardPage: React.FC = () => {
<VStack mx="auto" minH="100vh" maxW="1200px" position="relative" overflow="scroll" alignItems="flex-start" p="56px">
<Flex flexDir={isMobile ? 'column' : 'row'} w="full">
<VStack alignItems="start" mb="12px" mr="12px" minW={250}>
<Text fontWeight="600">{t('dashboard.filters.region')}</Text>
{user?.role === ROLES.admin ? (
<Select placeholder="..." onChange={(e) => handleRegion(e.target.value)} value={region}>
{REGIONS.map((region) => (
<option key={region} value={region}>
{region}
</option>
))}
</Select>
) : (
<Text>{region}</Text>
{regions && (
<>
<Text fontWeight="600">{t('dashboard.filters.region')}</Text>
{user?.role === ROLES.admin ? (
<Select placeholder="..." onChange={(e) => handleRegion(e.target.value)} value={regionId}>
{regions?.map((region) => (
<option key={region.id} value={region.id}>
{region.name}
</option>
))}
</Select>
) : (
<Text>{regions?.find((region) => region.id === regionId)?.name}</Text>
)}
</>
)}
</VStack>

Expand All @@ -81,7 +93,7 @@ const DashboardPage: React.FC = () => {
{user?.role === ROLES.admin || user?.role === ROLES['region-analyst'] ? (
<SelectDistrict
role={user.role}
region={region}
region={regionId}
onChange={(e) => handleDistrict(e.target.value)}
value={district}
/>
Expand Down
71 changes: 71 additions & 0 deletions src/pages/Settings/Regions/Form/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useEffect } from 'react';
import { Props } from './types';
import { Controller, useForm } from 'react-hook-form';
import {
Input,
Button,
Drawer,
FormLabel,
DrawerBody,
DrawerFooter,
DrawerHeader,
DrawerContent,
DrawerOverlay,
DrawerCloseButton,
} from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';

const RegionForm: React.FC<Props> = ({ defaultValues, handleSubmitForm, handleClose }) => {
const { t } = useTranslation();
const {
reset,
control,
handleSubmit,
formState: { isLoading },
} = useForm({ defaultValues });

useEffect(() => {
reset(defaultValues);
}, [defaultValues]);

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

<DrawerHeader>
{defaultValues && 'id' in defaultValues ? t('settings.tabs.region.edit') : t('settings.tabs.region.new')}
</DrawerHeader>

<DrawerBody>
<FormLabel htmlFor="name">{t('settings.tabs.region.form.name')}</FormLabel>
<Controller
rules={{ required: true }}
control={control}
name="name"
render={({ field, fieldState }) => (
<Input id="name" {...field} value={field.value} isInvalid={!!fieldState.error} />
)}
/>
</DrawerBody>

<DrawerFooter mt="auto">
<Button colorScheme="blue" mr={3} type="submit" isLoading={isLoading}>
{t('common.save')}
</Button>
<Button variant="outline" mr={'auto'} onClick={handleClose} isLoading={isLoading}>
{t('common.cancel')}
</Button>
</DrawerFooter>
</form>
</DrawerContent>
</Drawer>
);
};

export default RegionForm;
8 changes: 8 additions & 0 deletions src/pages/Settings/Regions/Form/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IUser } from '@/types';
import { SubmitHandler } from 'react-hook-form';

export type Props = {
defaultValues: IUser;
handleClose: () => void;
handleSubmitForm: SubmitHandler<IUser>;
};
113 changes: 113 additions & 0 deletions src/pages/Settings/Regions/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { useCallback, useContext, useEffect, useState } from 'react';
import Icon from '@/components/Base/Icon';
import Loader from '@/components/Base/Loader';
import Menu from '@/components/Menu';
import { IRegion, IUser } from '@/types';
import { Center, HStack, Text, VStack, useTheme } from '@chakra-ui/react';
import RegionForm from './Form';
import { SubmitHandler } from 'react-hook-form';
import { UserContext } from '@/contexts/UserContext';
import { toast } from 'react-toastify';
import { useTranslation } from 'react-i18next';
import RegionService from '@/services/region';

const Regions = () => {
const theme = useTheme();
const { t } = useTranslation();
const { user } = useContext(UserContext);
const [currentRegion, setCurrentRegion] = useState<IRegion>();
const [regions, setRegions] = useState({
isLoading: true,
data: [] as IRegion[],
});

const refreshRegions = useCallback(() => {
RegionService.getRegions().then((regions) => setRegions({ isLoading: false, data: regions }));
}, []);

useEffect(() => {
refreshRegions();
}, [refreshRegions]);

const handleSubmitRegion: SubmitHandler<IRegion> = async (region) => {
try {
setRegions({ isLoading: true, data: [] });
if ('id' in region) {
await RegionService.updateRegion(region.id, region);
} else {
await RegionService.saveRegion(region);
}
} catch (err) {
toast.error('An error as ocurred on management of user');
}

setCurrentRegion(undefined);
refreshRegions();
};

const menuOptions = [
{
label: t('settings.tabs.region.edit'),
handleClick: (user: IUser) => setCurrentRegion(user),
},
];

return (
<>
{currentRegion && (
<RegionForm
handleClose={() => setCurrentRegion(undefined)}
defaultValues={currentRegion as IUser}
handleSubmitForm={handleSubmitRegion}
/>
)}

<VStack alignItems={'flex-start'} width={'454px'} pl={'24px'}>
<Text fontWeight={600} fontSize={'20px'}>
{t('settings.tabs.region.title')}
</Text>

{regions.isLoading ? (
<Center minW={'400px'} h={'400px'}>
<Loader />
</Center>
) : (
<>
{regions.data.map((currentUser) => (
<HStack
justifyContent={'space-between'}
borderBottom={'1px solid'}
borderColor={'Gray.$400'}
key={currentUser.id}
py={'12px'}
px={'16px'}
w={'100%'}
>
<HStack>
<Center w={'40px'} h={'40px'} borderRadius={'50%'} background={'Blue.$200'}>
<Icon name={'user'} />
</Center>
<VStack justifyContent="center" gap={0} alignItems="flex-start">
<Text>{currentUser.name}</Text>
<Text fontSize={'12px'}>
{t('settings.tabs.region.total_schools', { value: currentUser.schoolsCount })}
</Text>
</VStack>
</HStack>

{currentUser.id !== user?.id && <Menu items={menuOptions} currentItem={currentUser} />}
</HStack>
))}

<HStack px={'16px'} py={'12px'} cursor={'pointer'} onClick={() => setCurrentRegion({} as any)}>
<Icon name={'plus'} color={theme.colors.Primary['$200']} />
<Text color={'Primary.$200'}>{t('settings.tabs.region.new')}</Text>
</HStack>
</>
)}
</VStack>
</>
);
};

export default Regions;
Loading

0 comments on commit 1cede63

Please sign in to comment.