From 00c05ecae59bbf8b268b8e3dad2ca111892c2ea0 Mon Sep 17 00:00:00 2001 From: Glen Date: Sat, 5 Oct 2024 20:43:46 +0530 Subject: [PATCH 01/12] base for vgroup --- public/locales/en/translation.json | 18 +- public/locales/fr/translation.json | 9 +- public/locales/hi/translation.json | 9 +- public/locales/sp/translation.json | 9 +- public/locales/zh/translation.json | 9 +- .../EventManagement/EventManagement.tsx | 58 ++- .../EventVolunteers.module.css | 260 +++++++++++ .../EventVolunteers/VolunteerContainer.tsx | 84 ++++ .../EventVolunteers/VolunteerGroups.tsx | 417 ++++++++++++++++++ src/screens/EventVolunteers/Volunteers.tsx | 406 +++++++++++++++++ .../OrganizationActionItems.tsx | 2 +- 11 files changed, 1241 insertions(+), 40 deletions(-) create mode 100644 src/screens/EventVolunteers/EventVolunteers.module.css create mode 100644 src/screens/EventVolunteers/VolunteerContainer.tsx create mode 100644 src/screens/EventVolunteers/VolunteerGroups.tsx create mode 100644 src/screens/EventVolunteers/Volunteers.tsx diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 8a668b03d8..ac2004ae3d 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -705,10 +705,11 @@ "title": "Event Management", "dashboard": "Dashboard", "registrants": "Registrants", - "eventActions": "Event Actions", - "eventAgendas": "Event Agendas", - "eventStats": "Event Statistics", - "to": "TO" + "actions": "Actions", + "agendas": "Agendas", + "statistics": "Statistics", + "to": "TO", + "volunteers": "Volunteers" }, "forgotPassword": { "title": "Talawa Forgot Password", @@ -1315,5 +1316,14 @@ }, "userPledges": { "title": "My Pledges" + }, + "eventVolunteers": { + "volunteers": "Volunteers", + "volunteerGroups": "Volunteer Groups", + "individuals": "Individuals", + "groups": "Groups", + "status": "Status", + "noVolunteers": "No Volunteers", + "noVolunteerGroups": "No Volunteer Groups" } } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 6f7332057b..60375a1d14 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -705,10 +705,11 @@ "title": "Gestion d'événements", "dashboard": "Tableau de bord", "registrants": "Inscrits", - "eventActions": "Actions d'événement", - "eventAgendas": "Ordres du jour des événements", - "eventStats": "Statistiques des événements", - "to": "À" + "actions": "Actions", + "agendas": "Ordres du jour", + "statistics": "Statistiques", + "to": "À", + "volunteers": "Bénévoles" }, "forgotPassword": { "title": "Talawa Mot de passe oublié", diff --git a/public/locales/hi/translation.json b/public/locales/hi/translation.json index 95d704daca..8df354e17b 100644 --- a/public/locales/hi/translation.json +++ b/public/locales/hi/translation.json @@ -705,10 +705,11 @@ "title": "इवेंट मैनेजमेंट", "dashboard": "डैशबोर्ड", "registrants": "कुलसचिव", - "eventActions": "घटना क्रियाएँ", - "eventAgendas": "इवेंट एजेंडा", - "eventStats": "घटना सांख्यिकी", - "to": "को" + "actions": "कार्य", + "agendas": "एजेंडे", + "statistics": "आँकड़े", + "to": "को", + "volunteers": "स्वयंसेवक" }, "forgotPassword": { "title": "तलावा पासवर्ड भूल गए", diff --git a/public/locales/sp/translation.json b/public/locales/sp/translation.json index bab46846a7..d5379c6199 100644 --- a/public/locales/sp/translation.json +++ b/public/locales/sp/translation.json @@ -706,10 +706,11 @@ "title": "Gestión de eventos", "dashboard": "Tablero", "registrants": "Inscritos", - "eventActions": "Acciones del evento", - "eventAgendas": "Agendas de eventos", - "eventStats": "Estadísticas del evento", - "to": "A" + "actions": "Acciones", + "agendas": "Agendas", + "statistics": "Estadísticas", + "to": "A", + "volunteers": "Voluntarios" }, "forgotPassword": { "title": "Talawa olvidó su contraseña", diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index 7f41c8baaf..446612aecc 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -705,10 +705,11 @@ "title": "事件管理", "dashboard": "仪表板", "registrants": "注册者", - "eventActions": "事件动作", - "eventAgendas": "活动议程", - "eventStats": "事件统计", - "to": "到" + "actions": "行动", + "agendas": "议程", + "statistics": "统计数据", + "to": "到", + "volunteers": "志愿者" }, "forgotPassword": { "title": "塔拉瓦 忘记密码", diff --git a/src/screens/EventManagement/EventManagement.tsx b/src/screens/EventManagement/EventManagement.tsx index 8a5b685855..a45721cb68 100644 --- a/src/screens/EventManagement/EventManagement.tsx +++ b/src/screens/EventManagement/EventManagement.tsx @@ -9,8 +9,10 @@ import { IoMdStats } from 'react-icons/io'; import EventAgendaItemsIcon from 'assets/svgs/agenda-items.svg?react'; import { useTranslation } from 'react-i18next'; import { Button, Dropdown } from 'react-bootstrap'; +import { IoIosHand } from 'react-icons/io'; import EventDashboard from 'components/EventManagement/Dashboard/EventDashboard'; import OrganizationActionItems from 'screens/OrganizationActionItems/OrganizationActionItems'; +import VolunteerContainer from 'screens/EventVolunteers/VolunteerContainer'; import EventAgendaItems from 'components/EventManagement/EventAgendaItems/EventAgendaItems'; import useLocalStorage from 'utils/useLocalstorage'; @@ -32,15 +34,19 @@ const eventDashboardTabs: { icon: , }, { - value: 'eventActions', + value: 'agendas', + icon: , + }, + { + value: 'actions', icon: , }, { - value: 'eventAgendas', - icon: , + value: 'volunteers', + icon: , }, { - value: 'eventStats', + value: 'statistics', icon: , }, ]; @@ -51,9 +57,10 @@ const eventDashboardTabs: { type TabOptions = | 'dashboard' | 'registrants' - | 'eventActions' - | 'eventAgendas' - | 'eventStats'; + | 'agendas' + | 'actions' + | 'volunteers' + | 'statistics'; /** * `EventManagement` component handles the display and navigation of different event management sections. @@ -124,13 +131,12 @@ const EventManagement = (): JSX.Element => { const translatedText = t(value); const className = selected - ? 'px-4 d-flex align-items-center shadow' - : 'text-secondary bg-white px-4 d-flex align-items-center rounded shadow'; + ? 'px-4 d-flex align-items-center rounded-3 shadow-sm' + : 'text-secondary bg-white px-4 d-flex align-items-center rounded-3 shadow-sm'; const props = { variant, className, style: { height: '2.5rem' }, - size: 'sm' as 'sm' | 'lg', onClick: () => setTab(value), 'data-testid': `${value}Btn`, }; @@ -145,9 +151,11 @@ const EventManagement = (): JSX.Element => { const handleBack = (): void => { /*istanbul ignore next*/ - userRole === 'USER' - ? navigate(`/user/events/${orgId}`) - : navigate(`/orgevents/${orgId}`); + if (userRole === 'USER') { + navigate(`/user/events/${orgId}`); + } else { + navigate(`/orgevents/${orgId}`); + } }; return ( @@ -158,7 +166,7 @@ const EventManagement = (): JSX.Element => { + + + + ); + }, + }, + ]; + + return ( +
+ {/* Header with search, filter and Create Button */} +
+
+ setSearchValue(e.target.value)} + onKeyUp={(e) => { + if (e.key === 'Enter') { + setSearchTerm(searchValue); + } else if (e.key === 'Backspace' && searchValue === '') { + setSearchTerm(''); + } + }} + data-testid="searchBy" + /> + +
+
+
+ + + + {tCommon('searchBy', { item: '' })} + + + setSearchBy('assignee')} + data-testid="assignee" + > + {t('assignee')} + + setSearchBy('category')} + data-testid="category" + > + {t('category')} + + + + + + + {tCommon('sort')} + + + setSortBy('dueDate_DESC')} + data-testid="dueDate_DESC" + > + {t('latestDueDate')} + + setSortBy('dueDate_ASC')} + data-testid="dueDate_ASC" + > + {t('earliestDueDate')} + + + + + + + {t('status')} + + + setStatus(null)} + data-testid="statusAll" + > + {tCommon('all')} + + setStatus(ItemStatus.Pending)} + data-testid="statusPending" + > + {tCommon('pending')} + + setStatus(ItemStatus.Completed)} + data-testid="statusCompleted" + > + {tCommon('completed')} + + + +
+
+ +
+
+
+ + {/* Table with Action Items */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noVolunteerGroups')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={actionItems.map((actionItem, index) => ({ + id: index + 1, + ...actionItem, + }))} + columns={columns} + isRowSelectable={() => false} + /> +
+ ); +} + +export default volunteerGroups; diff --git a/src/screens/EventVolunteers/Volunteers.tsx b/src/screens/EventVolunteers/Volunteers.tsx new file mode 100644 index 0000000000..ba2a6cabd1 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers.tsx @@ -0,0 +1,406 @@ +import React, { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useParams } from 'react-router-dom'; + +import { + Circle, + FilterAltOutlined, + Search, + Sort, + WarningAmberRounded, +} from '@mui/icons-material'; + +import { useQuery } from '@apollo/client'; +import { ACTION_ITEM_LIST } from 'GraphQl/Queries/Queries'; + +import type { InterfaceActionItemList } from 'utils/interfaces'; +import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { Chip, Stack } from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; +import styles from './EventVolunteers.module.css'; + +enum ItemStatus { + Pending = 'pending', + Completed = 'completed', + Late = 'late', +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component for managing and displaying action items within an organization. + * + * This component allows users to view, filter, sort, and create action items. It also handles fetching and displaying related data such as action item categories and members. + * + * @returns The rendered component. + */ +function volunteers(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Get the organization ID from URL parameters + const { orgId, eventId } = useParams(); + + if (!orgId) { + return ; + } + + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState<'dueDate_ASC' | 'dueDate_DESC' | null>( + null, + ); + const [status, setStatus] = useState(null); + const [searchBy] = useState<'assignee' | 'category'>('assignee'); + + /** + * Query to fetch action items for the organization based on filters and sorting. + */ + const { + data: actionItemsData, + loading: actionItemsLoading, + error: actionItemsError, + }: { + data: InterfaceActionItemList | undefined; + loading: boolean; + error?: Error | undefined; + } = useQuery(ACTION_ITEM_LIST, { + variables: { + organizationId: orgId, + eventId: eventId, + orderBy: sortBy, + where: { + assigneeName: searchBy === 'assignee' ? searchTerm : undefined, + categoryName: searchBy === 'category' ? searchTerm : undefined, + is_completed: + status === null ? undefined : status === ItemStatus.Completed, + }, + }, + }); + + const actionItems = useMemo( + () => actionItemsData?.actionItemsByOrganization || [], + [actionItemsData], + ); + + if (actionItemsLoading) { + return ; + } + + if (actionItemsError) { + return ( +
+ +
+ {tErrors('errorLoading', { entity: 'Action Items' })} +
+ {`${actionItemsError.message}`} +
+
+ ); + } + + const columns: GridColDef[] = [ + { + field: 'volunteer', + headerName: 'Volunteer', + flex: 1, + align: 'left', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.assignee; + return ( +
+ {image ? ( + Assignee + ) : ( +
+ +
+ )} + {params.row.assignee.firstName + ' ' + params.row.assignee.lastName} +
+ ); + }, + }, + { + field: 'status', + headerName: 'Status', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
+ {params.row.actionItemCategory?.name} +
+ ); + }, + }, + { + field: 'hours', + headerName: 'No. of Hours Volunteered', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + } + label={params.row.isCompleted ? 'Completed' : 'Pending'} + variant="outlined" + color="primary" + className={`${styles.chip} ${params.row.isCompleted ? styles.active : styles.pending}`} + /> + ); + }, + }, + { + field: 'actionItem', + headerName: 'Actions Completed', + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 1, + renderCell: (params: GridCellParams) => { + return ( +
{params.row.allotedHours ?? '-'}
+ ); + }, + }, + { + field: 'options', + headerName: 'Options', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + + + + ); + }, + }, + ]; + + return ( +
+ {/* Header with search, filter and Create Button */} +
+
+ setSearchValue(e.target.value)} + onKeyUp={(e) => { + if (e.key === 'Enter') { + setSearchTerm(searchValue); + } else if (e.key === 'Backspace' && searchValue === '') { + setSearchTerm(''); + } + }} + data-testid="searchBy" + /> + +
+
+
+ + + + {tCommon('sort')} + + + setSortBy('dueDate_DESC')} + data-testid="dueDate_DESC" + > + {t('latestDueDate')} + + setSortBy('dueDate_ASC')} + data-testid="dueDate_ASC" + > + {t('earliestDueDate')} + + + + + + + {t('status')} + + + setStatus(null)} + data-testid="statusAll" + > + {tCommon('all')} + + setStatus(ItemStatus.Pending)} + data-testid="statusPending" + > + {tCommon('pending')} + + setStatus(ItemStatus.Completed)} + data-testid="statusCompleted" + > + {tCommon('completed')} + + + +
+
+ +
+
+
+ + {/* Table with Action Items */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noVolunteers')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={actionItems.map((actionItem, index) => ({ + id: index + 1, + ...actionItem, + }))} + columns={columns} + isRowSelectable={() => false} + /> +
+ ); +} + +export default volunteers; diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx index ba48f212e0..c208af5cfa 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx @@ -353,7 +353,7 @@ function organizationActionItems(): JSX.Element { ]; return ( -
+
{/* Header with search, filter and Create Button */}
From d900c775b64de1c500f20e9f28670be0cd4a121f Mon Sep 17 00:00:00 2001 From: Glen Date: Sat, 19 Oct 2024 05:12:31 +0530 Subject: [PATCH 02/12] Volunteer Membership Screens in User/Admin Portal --- public/locales/en/translation.json | 63 ++- public/locales/fr/translation.json | 35 ++ public/locales/hi/translation.json | 35 ++ public/locales/sp/translation.json | 35 ++ public/locales/zh/translation.json | 35 ++ src/App.tsx | 5 + .../Mutations/EventVolunteerMutation.ts | 101 +++++ src/GraphQl/Queries/EventVolunteerQueries.ts | 115 +++++ src/GraphQl/Queries/PlugInQueries.ts | 47 +++ .../IconComponent/IconComponent.test.tsx | 4 + .../IconComponent/IconComponent.tsx | 10 + .../EventVolunteers.module.css | 8 +- .../EventVolunteers/Requests/Requests.tsx | 340 +++++++++++++++ .../EventVolunteers/VolunteerContainer.tsx | 40 +- .../VolunteerGroupDeleteModal.tsx | 100 +++++ .../VolunteerGroups/VolunteerGroupModal.tsx | 347 +++++++++++++++ .../VolunteerGroupViewModal.tsx | 235 +++++++++++ .../{ => VolunteerGroups}/VolunteerGroups.tsx | 257 +++++++----- .../Volunteers/VolunteerCreateModal.tsx | 151 +++++++ .../Volunteers/VolunteerDeleteModal.tsx | 103 +++++ .../Volunteers/VolunteerViewModal.tsx | 202 +++++++++ .../{ => Volunteers}/Volunteers.tsx | 221 ++++++---- .../FundCampaignPledge/FundCampaignPledge.tsx | 10 +- .../FundCampaignPledge/PledgeModal.tsx | 6 +- .../UserPortal/Campaigns/PledgeModal.tsx | 6 +- src/screens/UserPortal/Pledges/Pledges.tsx | 10 +- .../UserPortal/UserScreen/UserScreen.tsx | 1 + .../Volunteer/Invitations/Invitations.tsx | 301 +++++++++++++ .../UpcomingEvents/UpcomingEvents.tsx | 397 ++++++++++++++++++ .../Volunteer/VolunteerManagement.module.css | 138 ++++++ .../Volunteer/VolunteerManagement.tsx | 222 ++++++++++ src/state/reducers/userRoutersReducer.test.ts | 12 + src/state/reducers/userRoutesReducer.ts | 1 + src/utils/interfaces.ts | 131 ++++-- 34 files changed, 3477 insertions(+), 247 deletions(-) create mode 100644 src/GraphQl/Mutations/EventVolunteerMutation.ts create mode 100644 src/GraphQl/Queries/EventVolunteerQueries.ts create mode 100644 src/screens/EventVolunteers/Requests/Requests.tsx create mode 100644 src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx create mode 100644 src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx create mode 100644 src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx rename src/screens/EventVolunteers/{ => VolunteerGroups}/VolunteerGroups.tsx (61%) create mode 100644 src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx create mode 100644 src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx create mode 100644 src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx rename src/screens/EventVolunteers/{ => Volunteers}/Volunteers.tsx (65%) create mode 100644 src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx create mode 100644 src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx create mode 100644 src/screens/UserPortal/Volunteer/VolunteerManagement.module.css create mode 100644 src/screens/UserPortal/Volunteer/VolunteerManagement.tsx diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index ac2004ae3d..5203795f90 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1319,11 +1319,72 @@ }, "eventVolunteers": { "volunteers": "Volunteers", + "volunteer": "Volunteer", "volunteerGroups": "Volunteer Groups", "individuals": "Individuals", "groups": "Groups", "status": "Status", "noVolunteers": "No Volunteers", - "noVolunteerGroups": "No Volunteer Groups" + "noVolunteerGroups": "No Volunteer Groups", + "add": "Add", + "mostHoursVolunteered": "Most Hours Volunteered", + "leastHoursVolunteered": "Least Hours Volunteered", + "accepted": "Accepted", + "addVolunteer": "Add Volunteer", + "removeVolunteer": "Remove Volunteer", + "volunteerAdded": "Volunteer added successfully", + "volunteerRemoved": "Volunteer removed successfully", + "volunteerGroupCreated": "Volunteer group created successfully", + "volunteerGroupUpdated": "Volunteer group updated successfully", + "volunteerGroupDeleted": "Volunteer group deleted successfully", + "removeVolunteerMsg": "Are you sure you want to remove this Volunteer?", + "deleteVolunteerGroupMsg": "Are you sure you want to delete this Volunteer Group?", + "mostMembers": "Most Members", + "leastMembers": "Least Members", + "leader": "Leader", + "group": "Group", + "createGroup": "Create Group", + "updateGroup": "Update Group", + "deleteGroup": "Delete Group", + "volunteersRequired": "Volunteers Required", + "volunteerDetails": "Volunteer Details", + "hoursVolunteered": "Hours Volunteered", + "groupDetails": "Group Details", + "creator": "Creator", + "requests": "Requests", + "noRequests": "No Requests", + "latest": "Latest", + "earliest": "Earliest", + "requestAccepted": "Request accepted successfully", + "requestRejected": "Request rejected successfully" + }, + "userVolunteer": { + "title": "Volunteership", + "name": "Title", + "upcomingEvents": "Upcoming Events", + "requests": "Requests", + "invitations": "Invitations", + "groups": "Volunteer Groups", + "actions": "Actions", + "searchByName": "Search by Name", + "latestEndDate": "Latest End Date", + "earliestEndDate": "Earliest End Date", + "noEvents": "No Upcoming Events", + "volunteer": "Volunteer", + "volunteered": "Volunteered", + "join": "Join", + "joined": "Joined", + "searchByEventName": "Search by Event title", + "filter": "Filter", + "groupInvite": "Group Invite", + "individualInvite": "Individual Invite", + "noInvitations": "No Invitations", + "accept": "Accept", + "reject": "Reject", + "receivedLatest": "Received Latest", + "receivedEarliest": "Received Earliest", + "invitationAccepted": "Invitation accepted successfully", + "invitationRejected": "Invitation rejected successfully", + "volunteerSuccess": "Requested to volunteer successfully" } } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 60375a1d14..27986096ca 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -1316,5 +1316,40 @@ }, "userPledges": { "title": "Mes Promesses" + }, + "eventVolunteers": { + "volunteers": "Volontaires", + "volunteer": "Bénévole", + "volunteerGroups": "Groupes de bénévoles", + "individuals": "Individus", + "groups": "Groupes", + "status": "Statut", + "noVolunteers": "Pas de volontaires", + "noVolunteerGroups": "Pas de groupes de bénévoles", + "add": "Ajouter", + "mostHoursVolunteered": "Le plus d'heures bénévoles", + "leastHoursVolunteered": "Le moins d'heures bénévoles", + "accepted": "Accepté", + "addVolunteer": "Ajouter un bénévole", + "removeVolunteer": "Retirer un bénévole", + "volunteerAdded": "Bénévole ajouté avec succès", + "volunteerRemoved": "Bénévole retiré avec succès", + "volunteerGroupCreated": "Groupe de bénévoles créé avec succès", + "volunteerGroupUpdated": "Groupe de bénévoles mis à jour avec succès", + "volunteerGroupDeleted": "Groupe de bénévoles supprimé avec succès", + "removeVolunteerMsg": "Êtes-vous sûr de vouloir retirer ce bénévole?", + "deleteVolunteerGroupMsg": "Êtes-vous sûr de vouloir supprimer ce groupe de bénévoles?", + "mostMembers": "Le plus de membres", + "leastMembers": "Le moins de membres", + "leader": "Chef", + "group": "Groupe", + "createGroup": "Créer un groupe", + "updateGroup": "Mettre à jour le groupe", + "deleteGroup": "Supprimer le groupe", + "volunteersRequired": "Bénévoles requis", + "volunteerDetails": "Détails du bénévole", + "hoursVolunteered": "Heures de bénévolat", + "groupDetails": "Détails du groupe", + "creator": "Créateur" } } diff --git a/public/locales/hi/translation.json b/public/locales/hi/translation.json index 8df354e17b..17ee9ab0d4 100644 --- a/public/locales/hi/translation.json +++ b/public/locales/hi/translation.json @@ -1316,5 +1316,40 @@ }, "userPledges": { "title": "मेरी प्रतिज्ञाएँ" + }, + "eventVolunteers": { + "volunteers": "स्वयंसेवक", + "volunteer": "स्वयंसेवक", + "volunteerGroups": "स्वयंसेवक समूह", + "individuals": "व्यक्ति", + "groups": "समूह", + "status": "स्थिति", + "noVolunteers": "कोई स्वयंसेवक नहीं", + "noVolunteerGroups": "कोई स्वयंसेवक समूह नहीं", + "add": "जोड़ें", + "mostHoursVolunteered": "सबसे अधिक घंटे स्वेच्छा से", + "leastHoursVolunteered": "सबसे कम घंटे स्वेच्छा से", + "accepted": "स्वीकृत", + "addVolunteer": "स्वयंसेवक जोड़ें", + "removeVolunteer": "स्वयंसेवक हटाएं", + "volunteerAdded": "स्वयंसेवक सफलतापूर्वक जोड़ा गया", + "volunteerRemoved": "स्वयंसेवक सफलतापूर्वक हटाया गया", + "volunteerGroupCreated": "स्वयंसेवक समूह सफलतापूर्वक बनाया गया", + "volunteerGroupUpdated": "स्वयंसेवक समूह सफलतापूर्वक अपडेट किया गया", + "volunteerGroupDeleted": "स्वयंसेवक समूह सफलतापूर्वक हटाया गया", + "removeVolunteerMsg": "क्या आप इस स्वयंसेवक को हटाना चाहते हैं?", + "deleteVolunteerGroupMsg": "क्या आप इस स्वयंसेवक समूह को हटाना चाहते हैं?", + "mostMembers": "अधिकतम सदस्य", + "leastMembers": "न्यूनतम सदस्य", + "leader": "नेता", + "group": "समूह", + "createGroup": "समूह बनाएं", + "updateGroup": "समूह अपडेट करें", + "deleteGroup": "समूह हटाएं", + "volunteersRequired": "स्वयंसेवकों की आवश्यकता", + "volunteerDetails": "स्वयंसेवक विवरण", + "hoursVolunteered": "स्वेच्छा से दिए गए घंटे", + "groupDetails": "समूह विवरण", + "creator": "निर्माता" } } diff --git a/public/locales/sp/translation.json b/public/locales/sp/translation.json index d5379c6199..51202d9215 100644 --- a/public/locales/sp/translation.json +++ b/public/locales/sp/translation.json @@ -1317,5 +1317,40 @@ }, "userPledges": { "title": "Mis Promesas" + }, + "eventVolunteers": { + "volunteers": "Voluntarios", + "volunteer": "Voluntario", + "volunteerGroups": "Grupos de voluntarios", + "individuals": "Individuos", + "groups": "Grupos", + "status": "Estado", + "noVolunteers": "No hay voluntarios", + "noVolunteerGroups": "No hay grupos de voluntarios", + "add": "Añadir", + "mostHoursVolunteered": "Más horas voluntarias", + "leastHoursVolunteered": "Menos horas voluntarias", + "accepted": "Aceptado", + "addVolunteer": "Añadir voluntario", + "removeVolunteer": "Eliminar voluntario", + "volunteerAdded": "Voluntario añadido con éxito", + "volunteerRemoved": "Voluntario eliminado con éxito", + "volunteerGroupCreated": "Grupo de voluntarios creado con éxito", + "volunteerGroupUpdated": "Grupo de voluntarios actualizado con éxito", + "volunteerGroupDeleted": "Grupo de voluntarios eliminado con éxito", + "removeVolunteerMsg": "¿Estás seguro de que quieres eliminar este voluntario?", + "deleteVolunteerGroupMsg": "¿Estás seguro de que quieres eliminar este grupo de voluntarios?", + "mostMembers": "Más miembros", + "leastMembers": "Menos miembros", + "leader": "Líder", + "group": "Grupo", + "createGroup": "Crear grupo", + "updateGroup": "Actualizar grupo", + "deleteGroup": "Eliminar grupo", + "volunteersRequired": "Voluntarios requeridos", + "volunteerDetails": "Detalles del voluntario", + "hoursVolunteered": "Horas voluntarias", + "groupDetails": "Detalles del grupo", + "creator": "Creador" } } diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index 446612aecc..3bc8814f00 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -1316,5 +1316,40 @@ }, "userPledges": { "title": "我的承诺" + }, + "eventVolunteers": { + "volunteers": "志愿者", + "volunteer": "志愿者", + "volunteerGroups": "志愿者小组", + "individuals": "个人", + "groups": "小组", + "status": "状态", + "noVolunteers": "没有志愿者", + "noVolunteerGroups": "没有志愿者小组", + "add": "添加", + "mostHoursVolunteered": "最多志愿小时", + "leastHoursVolunteered": "最少志愿小时", + "accepted": "已接受", + "addVolunteer": "添加志愿者", + "removeVolunteer": "移除志愿者", + "volunteerAdded": "志愿者添加成功", + "volunteerRemoved": "志愿者移除成功", + "volunteerGroupCreated": "志愿者小组创建成功", + "volunteerGroupUpdated": "志愿者小组更新成功", + "volunteerGroupDeleted": "志愿者小组删除成功", + "removeVolunteerMsg": "您确定要移除此志愿者吗?", + "deleteVolunteerGroupMsg": "您确定要删除此志愿者小组吗?", + "mostMembers": "最多成员", + "leastMembers": "最少成员", + "leader": "领导", + "group": "小组", + "createGroup": "创建小组", + "updateGroup": "更新小组", + "deleteGroup": "删除小组", + "volunteersRequired": "需要志愿者", + "volunteerDetails": "志愿者详情", + "hoursVolunteered": "志愿小时", + "groupDetails": "小组详情", + "creator": "创建者" } } diff --git a/src/App.tsx b/src/App.tsx index d6e825006f..0530ad1fcc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -48,6 +48,7 @@ import UserScreen from 'screens/UserPortal/UserScreen/UserScreen'; import EventDashboardScreen from 'components/EventDashboardScreen/EventDashboardScreen'; import Campaigns from 'screens/UserPortal/Campaigns/Campaigns'; import Pledges from 'screens/UserPortal/Pledges/Pledges'; +import VolunteerManagement from 'screens/UserPortal/Volunteer/VolunteerManagement'; const { setItem } = useLocalStorage(); @@ -195,6 +196,10 @@ function app(): JSX.Element { } /> } /> } /> + } + /> }> > = { name: 'My Pledges', testId: 'Icon-Component-My-Pledges', }, + Volunteer: { + name: 'Volunteer', + testId: 'Icon-Component-Volunteer', + }, default: { name: 'default', testId: 'Icon-Component-DefaultIcon', diff --git a/src/components/IconComponent/IconComponent.tsx b/src/components/IconComponent/IconComponent.tsx index 4708dc7966..8430aca131 100644 --- a/src/components/IconComponent/IconComponent.tsx +++ b/src/components/IconComponent/IconComponent.tsx @@ -19,6 +19,7 @@ import PostsIcon from 'assets/svgs/posts.svg?react'; import SettingsIcon from 'assets/svgs/settings.svg?react'; import VenueIcon from 'assets/svgs/venues.svg?react'; import RequestsIcon from 'assets/svgs/requests.svg?react'; +import { MdOutlineVolunteerActivism } from 'react-icons/md'; import React from 'react'; @@ -133,6 +134,15 @@ const iconComponent = (props: InterfaceIconComponent): JSX.Element => { stroke={props.fill} /> ); + case 'Volunteer': + return ( + + ); default: return ( ; + } + + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState< + 'createdAt_ASC' | 'createdAt_DESC' | null + >(null); + + const [updateMembership] = useMutation(UPDATE_VOLUNTEER_MEMBERSHIP); + + const updateMembershipStatus = async ( + id: string, + status: 'accepted' | 'rejected', + ): Promise => { + try { + await updateMembership({ + variables: { + id: id, + status: status, + }, + }); + toast.success( + t( + status === 'accepted' ? 'requestAccepted' : 'requestRejected', + ) as string, + ); + refetchRequests(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + /** + * Query to fetch volunteer Membership requests for the event. + */ + const { + data: requestsData, + loading: requestsLoading, + error: requestsError, + refetch: refetchRequests, + }: { + data?: { + getVolunteerMembership: InterfaceVolunteerMembership[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(USER_VOLUNTEER_MEMBERSHIP, { + variables: { + where: { + eventId, + status: 'requested', + userName: searchTerm ? searchTerm : undefined, + }, + orderBy: sortBy ? sortBy : undefined, + }, + }); + + const requests = useMemo(() => { + if (!requestsData) return []; + return requestsData.getVolunteerMembership; + }, [requestsData]); + + // loads the requests when the component mounts + if (requestsLoading) return ; + if (requestsError) { + // Displays an error message if there is an issue loading the requests + return ( +
+
+ +
+ {tErrors('errorLoading', { entity: 'Volunteership Requests' })} +
+ {requestsError.message} +
+
+
+ ); + } + + const columns: GridColDef[] = [ + { + field: 'srNo', + headerName: 'Sr. No.', + flex: 1, + minWidth: 100, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return params.row.id; + }, + }, + { + field: 'volunteer', + headerName: 'Volunteer', + flex: 3, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.volunteer.user; + return ( +
+ {image ? ( + volunteer + ) : ( +
+ +
+ )} + {firstName + ' ' + lastName} +
+ ); + }, + }, + { + field: 'requestDate', + headerName: 'Request Date', + flex: 2, + minWidth: 150, + align: 'center', + headerAlign: 'center', + headerClassName: `${styles.tableHeader}`, + sortable: false, + renderCell: (params: GridCellParams) => { + return dayjs(params.row.createdAt).format('DD/MM/YYYY'); + }, + }, + { + field: 'options', + headerName: 'Options', + align: 'center', + flex: 2, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + + + ); + }, + }, + ]; + + return ( +
+ {/* Header with search, filter and Create Button */} +
+
+ setSearchValue(e.target.value)} + onKeyUp={(e) => { + if (e.key === 'Enter') { + setSearchTerm(searchValue); + } else if (e.key === 'Backspace' && searchValue === '') { + setSearchTerm(''); + } + }} + data-testid="searchBy" + /> + +
+
+
+ + + + {tCommon('sort')} + + + setSortBy('createdAt_DESC')} + data-testid="createdAt_DESC" + > + {t('latest')} + + setSortBy('createdAt_ASC')} + data-testid="createdAt_ASC" + > + {t('earliest')} + + + +
+
+
+ + {/* Table with Volunteer Membership Requests */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noRequests')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={requests.map((request, index) => ({ + id: index + 1, + ...request, + }))} + columns={columns} + isRowSelectable={() => false} + /> +
+ ); +} + +export default requests; diff --git a/src/screens/EventVolunteers/VolunteerContainer.tsx b/src/screens/EventVolunteers/VolunteerContainer.tsx index a2df5e9286..29c3e8fed1 100644 --- a/src/screens/EventVolunteers/VolunteerContainer.tsx +++ b/src/screens/EventVolunteers/VolunteerContainer.tsx @@ -3,8 +3,10 @@ import { useTranslation } from 'react-i18next'; import { Navigate, useParams } from 'react-router-dom'; import styles from './EventVolunteers.module.css'; import { HiUserGroup, HiUser } from 'react-icons/hi2'; -import Volunteers from './Volunteers'; -import VolunteerGroups from './VolunteerGroups'; +import Volunteers from './Volunteers/Volunteers'; +import VolunteerGroups from './VolunteerGroups/VolunteerGroups'; +import { FaRegFile } from 'react-icons/fa6'; +import Requests from './Requests/Requests'; /** * Container Component for Volunteer or VolunteerGroups as per selection. @@ -25,7 +27,7 @@ function volunteerContainer(): JSX.Element { return ; } - const [dataType, setDataType] = useState<'individual' | 'group'>( + const [dataType, setDataType] = useState<'individual' | 'group' | 'requests'>( 'individual', ); @@ -33,13 +35,15 @@ function volunteerContainer(): JSX.Element {
- {t(`${dataType === 'group' ? 'volunteerGroups' : 'volunteers'}`)} + {t( + `${dataType === 'group' ? 'volunteerGroups' : dataType === 'individual' ? 'volunteers' : 'requests'}`, + )}
setDataType('group')} @@ -72,11 +76,33 @@ function volunteerContainer(): JSX.Element { {t('groups')} + + setDataType('requests')} + checked={dataType === 'requests'} + /> +
- {dataType === 'individual' ? : } + {dataType === 'individual' ? ( + + ) : dataType === 'group' ? ( + + ) : ( + + )}
); } diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx new file mode 100644 index 0000000000..33132bfd33 --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx @@ -0,0 +1,100 @@ +import { Button, Modal } from 'react-bootstrap'; +import styles from '../EventVolunteers.module.css'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation } from '@apollo/client'; +import type { InterfaceVolunteerGroupInfo } from 'utils/interfaces'; +import { toast } from 'react-toastify'; +import { DELETE_VOLUNTEER_GROUP } from 'GraphQl/Mutations/EventVolunteerMutation'; + +export interface InterfaceDeleteVolunteerGroupModal { + isOpen: boolean; + hide: () => void; + group: InterfaceVolunteerGroupInfo | null; + refetchGroups: () => void; +} + +/** + * A modal dialog for confirming the deletion of a volunteer group. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param group - The volunteer group to be deleted. + * @param refetchGroups - Function to refetch the volunteer groups after deletion. + * + * @returns The rendered modal component. + * + * + * The `VolunteerGroupDeleteModal` component displays a confirmation dialog when a user attempts to delete a volunteer group. + * It allows the user to either confirm or cancel the deletion. + * On confirmation, the `deleteVolunteerGroup` mutation is called to remove the volunteer group from the database, + * and the `refetchGroups` function is invoked to update the list of volunteer groups. + * A success or error toast notification is shown based on the result of the deletion operation. + * + * The modal includes: + * - A header with a title and a close button. + * - A body with a message asking for confirmation. + * - A footer with "Yes" and "No" buttons to confirm or cancel the deletion. + * + * The `deleteVolunteerGroup` mutation is used to perform the deletion operation. + */ + +const VolunteerGroupDeleteModal: React.FC< + InterfaceDeleteVolunteerGroupModal +> = ({ isOpen, hide, group, refetchGroups }) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const [deleteVolunteerGroup] = useMutation(DELETE_VOLUNTEER_GROUP); + + const deleteHandler = async (): Promise => { + try { + await deleteVolunteerGroup({ + variables: { + id: group?._id, + }, + }); + refetchGroups(); + hide(); + toast.success(t('volunteerGroupDeleted')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + return ( + <> + + +

{t('deleteGroup')}

+ +
+ +

{t('deleteVolunteerGroupMsg')}

+
+ + + + +
+ + ); +}; +export default VolunteerGroupDeleteModal; diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx new file mode 100644 index 0000000000..99d4c1e2a5 --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx @@ -0,0 +1,347 @@ +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { + InterfaceCreateVolunteerGroup, + InterfaceUserInfo, + InterfaceVolunteerGroupInfo, +} from 'utils/interfaces'; +import styles from '../EventVolunteers.module.css'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { Autocomplete, FormControl, TextField } from '@mui/material'; + +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; +import { + CREATE_VOLUNTEER_GROUP, + // UPDATE_VOLUNTEER_GROUP, +} from 'GraphQl/Mutations/EventVolunteerMutation'; + +export interface InterfaceVolunteerGroupModal { + isOpen: boolean; + hide: () => void; + eventId: string; + orgId: string; + group: InterfaceVolunteerGroupInfo | null; + refetchGroups: () => void; + mode: 'create' | 'edit'; +} + +/** + * A modal dialog for creating or editing a volunteer group. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param eventId - The ID of the event associated with volunteer group. + * @param orgId - The ID of the organization associated with volunteer group. + * @param group - The volunteer group object to be edited. + * @param refetchGroups - Function to refetch the volunteer groups after creation or update. + * @param mode - The mode of the modal (create or edit). + * @returns The rendered modal component. + * + * The `VolunteerGroupModal` component displays a form within a modal dialog for creating or editing a Volunteer Group. + * It includes fields for entering the group name, description, volunteersRequired, and selecting volunteers/leaders. + * + * The modal includes: + * - A header with a title indicating the current mode (create or edit) and a close button. + * - A form with: + * - An input field for entering the group name. + * - A textarea for entering the group description. + * - A multi-select dropdown for selecting leader. + * - A multi-select dropdown for selecting volunteers. + * - An input field for entering the number of volunteers required. + * - A submit button to create or update the pledge. + * + * On form submission, the component either: + * - Calls `updatePledge` mutation to update an existing pledge, or + * - Calls `createPledge` mutation to create a new pledge. + * + * Success or error messages are displayed using toast notifications based on the result of the mutation. + */ + +const VolunteerGroupModal: React.FC = ({ + isOpen, + hide, + eventId, + orgId, + group, + refetchGroups, + mode, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const [formState, setFormState] = useState({ + name: group?.name ?? '', + description: group?.description ?? '', + leader: group?.leader ?? null, + volunteerUsers: group?.volunteers.map((volunteer) => volunteer.user) ?? [], + volunteersRequired: group?.volunteersRequired ?? null, + }); + const [members, setMembers] = useState([]); + + // const [updateVolunteerGroup] = useMutation(UPDATE_VOLUNTEER_GROUP); + const [createVolunteerGroup] = useMutation(CREATE_VOLUNTEER_GROUP); + + const { data: memberData } = useQuery(MEMBERS_LIST, { + variables: { id: orgId }, + }); + + useEffect(() => { + setFormState({ + name: group?.name ?? '', + description: group?.description ?? '', + leader: group?.leader ?? null, + volunteerUsers: + group?.volunteers.map((volunteer) => volunteer.user) ?? [], + volunteersRequired: group?.volunteersRequired ?? null, + }); + }, [group]); + + useEffect(() => { + if (memberData) { + setMembers(memberData.organizations[0].members); + } + }, [memberData]); + + const { name, description, leader, volunteerUsers, volunteersRequired } = + formState; + + /*istanbul ignore next*/ + const updateGroupHandler = useCallback( + async (e: ChangeEvent): Promise => { + e.preventDefault(); + + // const updatedFields: { + // [key: string]: number | string | string[] | undefined; + // } = {}; + // checks if there are changes to the pledge and adds them to the updatedFields object + // if (pledgeAmount !== pledge?.amount) { + // updatedFields.amount = pledgeAmount; + // } + // if (pledgeCurrency !== pledge?.currency) { + // updatedFields.currency = pledgeCurrency; + // } + // if (startDate !== dayjs(pledge?.startDate).format('YYYY-MM-DD')) { + // updatedFields.startDate = startDate; + // } + // if (endDate !== dayjs(pledge?.endDate).format('YYYY-MM-DD')) { + // updatedFields.endDate = endDate; + // } + // if (pledgeUsers !== pledge?.users) { + // updatedFields.users = pledgeUsers.map((user) => user._id); + // } + try { + // await updatePledge({ + // variables: { + // id: pledge?._id, + // ...updatedFields, + // }, + // }); + toast.success(t('volunteerGroupUpdated')); + refetchGroups(); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }, + [formState, group], + ); + + // Function to create a new volunteer group + const createGroupHandler = useCallback( + async (e: ChangeEvent): Promise => { + try { + e.preventDefault(); + await createVolunteerGroup({ + variables: { + data: { + eventId, + leaderId: leader?._id, + name, + description, + volunteersRequired, + volunteerUserIds: volunteerUsers.map((user) => user._id), + }, + }, + }); + + toast.success(t('volunteerGroupCreated')); + refetchGroups(); + setFormState({ + name: '', + description: '', + leader: null, + volunteerUsers: [], + volunteersRequired: null, + }); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }, + [formState, eventId], + ); + + return ( + + +

+ {t(mode === 'edit' ? 'updateGroup' : 'createGroup')} +

+ +
+ +
+ {/* Input field to enter the group name */} + + + + setFormState({ ...formState, name: e.target.value }) + } + /> + + + {/* Input field to enter the group description */} + + + + setFormState({ ...formState, description: e.target.value }) + } + /> + + + {/* A dropdown to select leader for volunteer group */} + + option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={(member: InterfaceUserInfo): string => + `${member.firstName} ${member.lastName}` + } + onChange={ + /*istanbul ignore next*/ + (_, newLeader): void => { + if (newLeader) { + setFormState({ + ...formState, + leader: newLeader, + volunteerUsers: [...volunteerUsers, newLeader], + }); + } else { + setFormState({ + ...formState, + leader: null, + volunteerUsers: volunteerUsers.filter( + (user) => user._id !== leader?._id, + ), + }); + } + } + } + renderInput={(params) => ( + + )} + /> + + + {/* A Multi-select dropdown to select more than one volunteer */} + + option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={(member: InterfaceUserInfo): string => + `${member.firstName} ${member.lastName}` + } + onChange={ + /*istanbul ignore next*/ + (_, newUsers): void => { + setFormState({ + ...formState, + volunteerUsers: newUsers, + }); + } + } + renderInput={(params) => ( + + )} + /> + + + + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + volunteersRequired: parseInt(e.target.value), + }); + } else if (e.target.value === '') { + setFormState({ + ...formState, + volunteersRequired: null, + }); + } + }} + /> + + + + {/* Button to submit the pledge form */} + +
+
+
+ ); +}; +export default VolunteerGroupModal; diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx new file mode 100644 index 0000000000..4454b8f66a --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx @@ -0,0 +1,235 @@ +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceVolunteerGroupInfo } from 'utils/interfaces'; +import styles from '../EventVolunteers.module.css'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { + FormControl, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, +} from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; + +export interface InterfaceVolunteerGroupViewModal { + isOpen: boolean; + hide: () => void; + group: InterfaceVolunteerGroupInfo; +} + +/** + * A modal dialog for viewing volunteer group information for an event. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param group - The volunteer group to display in the modal. + * + * @returns The rendered modal component. + * + * The `VolunteerGroupViewModal` component displays all the fields of a volunteer group in a modal dialog. + * + * The modal includes: + * - A header with a title and a close button. + * - fields for volunteer name, status, hours volunteered, groups, and assignments. + */ + +const VolunteerGroupViewModal: React.FC = ({ + isOpen, + hide, + group, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const { leader, creator, name, volunteersRequired, description, volunteers } = + group; + + return ( + + +

{t('groupDetails')}

+ +
+ +
+ {/* Group name & Volunteers Required */} + + + + + {description && ( + + + + )} + + {/* Input field to enter the group description */} + {description && ( + + + + + + )} + + + + {leader.image ? ( + Volunteer + ) : ( +
+ +
+ )} + + ), + }} + /> +
+ + + + {creator.image ? ( + Volunteer + ) : ( +
+ +
+ )} + + ), + }} + /> +
+
+ {/* Table for Associated Volunteers */} + {volunteers && volunteers.length > 0 && ( + + + Volunteers + + + + + + + Sr. No. + Name + + + + {volunteers.map((volunteer, index) => { + const { firstName, lastName } = volunteer.user; + return ( + + + {index + 1} + + + {firstName + ' ' + lastName} + + + ); + })} + +
+
+
+ )} +
+
+
+ ); +}; +export default VolunteerGroupViewModal; diff --git a/src/screens/EventVolunteers/VolunteerGroups.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx similarity index 61% rename from src/screens/EventVolunteers/VolunteerGroups.tsx rename to src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx index d485665b28..70cfbbd630 100644 --- a/src/screens/EventVolunteers/VolunteerGroups.tsx +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx @@ -1,34 +1,31 @@ -import React, { useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Button, Dropdown, Form } from 'react-bootstrap'; import { Navigate, useParams } from 'react-router-dom'; -import { - Circle, - FilterAltOutlined, - Search, - Sort, - WarningAmberRounded, -} from '@mui/icons-material'; +import { Search, Sort, WarningAmberRounded } from '@mui/icons-material'; import { useQuery } from '@apollo/client'; -import { ACTION_ITEM_LIST } from 'GraphQl/Queries/Queries'; -import type { InterfaceActionItemList } from 'utils/interfaces'; +import type { InterfaceVolunteerGroupInfo } from 'utils/interfaces'; import Loader from 'components/Loader/Loader'; import { DataGrid, type GridCellParams, type GridColDef, } from '@mui/x-data-grid'; -import { Chip, Stack } from '@mui/material'; +import { Stack } from '@mui/material'; import Avatar from 'components/Avatar/Avatar'; -import styles from './EventVolunteers.module.css'; +import styles from '../EventVolunteers.module.css'; +import { EVENT_VOLUNTEER_GROUP_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; +import VolunteerGroupModal from './VolunteerGroupModal'; +import VolunteerGroupDeleteModal from './VolunteerGroupDeleteModal'; +import VolunteerGroupViewModal from './VolunteerGroupViewModal'; -enum ItemStatus { - Pending = 'pending', - Completed = 'completed', - Late = 'late', +enum ModalState { + SAME = 'same', + DELETE = 'delete', + VIEW = 'view', } const dataGridStyle = { @@ -53,10 +50,8 @@ const dataGridStyle = { }; /** - * Component for managing and displaying action items within an organization. - * - * This component allows users to view, filter, sort, and create action items. It also handles fetching and displaying related data such as action item categories and members. - * + * Component for managing volunteer groups for an event. + * This component allows users to view, filter, sort, and create action items. It also provides a modal for creating and editing action items. * @returns The rendered component. */ function volunteerGroups(): JSX.Element { @@ -69,60 +64,86 @@ function volunteerGroups(): JSX.Element { // Get the organization ID from URL parameters const { orgId, eventId } = useParams(); - if (!orgId) { + if (!orgId || !eventId) { return ; } + const [group, setGroup] = useState(null); + const [modalMode, setModalMode] = useState<'create' | 'edit'>('create'); const [searchValue, setSearchValue] = useState(''); const [searchTerm, setSearchTerm] = useState(''); - const [sortBy, setSortBy] = useState<'dueDate_ASC' | 'dueDate_DESC' | null>( + const [sortBy, setSortBy] = useState<'member_ASC' | 'member_DESC' | null>( null, ); - const [status, setStatus] = useState(null); - const [searchBy, setSearchBy] = useState<'assignee' | 'category'>('assignee'); + const [searchBy, setSearchBy] = useState<'leader' | 'group'>('group'); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.SAME]: false, + [ModalState.DELETE]: false, + [ModalState.VIEW]: false, + }); /** - * Query to fetch action items for the organization based on filters and sorting. + * Query to fetch the list of volunteer groups for the event. */ const { - data: actionItemsData, - loading: actionItemsLoading, - error: actionItemsError, + data: groupsData, + loading: groupsLoading, + error: groupsError, + refetch: refetchGroups, }: { - data: InterfaceActionItemList | undefined; + data?: { + getEventVolunteerGroups: InterfaceVolunteerGroupInfo[]; + }; loading: boolean; error?: Error | undefined; - } = useQuery(ACTION_ITEM_LIST, { + refetch: () => void; + } = useQuery(EVENT_VOLUNTEER_GROUP_LIST, { variables: { - organizationId: orgId, - eventId: eventId, - orderBy: sortBy, where: { - assigneeName: searchBy === 'assignee' ? searchTerm : undefined, - categoryName: searchBy === 'category' ? searchTerm : undefined, - is_completed: - status === null ? undefined : status === ItemStatus.Completed, + eventId: eventId, + leaderName: searchBy === 'leader' ? searchTerm : null, + name_contains: searchBy === 'group' ? searchTerm : null, }, + orderBy: sortBy, }, }); - const actionItems = useMemo( - () => actionItemsData?.actionItemsByOrganization || [], - [actionItemsData], + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); + + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + + const handleModalClick = useCallback( + (group: InterfaceVolunteerGroupInfo | null, modal: ModalState): void => { + if (modal === ModalState.SAME) { + setModalMode(group ? 'edit' : 'create'); + } + setGroup(group); + openModal(modal); + }, + [openModal], + ); + + const groups = useMemo( + () => groupsData?.getEventVolunteerGroups || [], + [groupsData], ); - if (actionItemsLoading) { + if (groupsLoading) { return ; } - if (actionItemsError) { + if (groupsError) { return (
- {tErrors('errorLoading', { entity: 'Action Items' })} + {tErrors('errorLoading', { entity: 'Volunteer Groups' })}
- {`${actionItemsError.message}`} + {`${groupsError.message}`}
); @@ -139,7 +160,27 @@ function volunteerGroups(): JSX.Element { sortable: false, headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { - const { _id, firstName, lastName, image } = params.row.assignee; + return ( +
+ {params.row.name} +
+ ); + }, + }, + { + field: 'leader', + headerName: 'Leader', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.leader; return (
)} - {params.row.assignee.firstName + ' ' + params.row.assignee.lastName} + {firstName + ' ' + lastName}
); }, }, { - field: 'leader', - headerName: 'Leader', + field: 'actions', + headerName: 'Actions Completed', flex: 1, align: 'center', - minWidth: 100, headerAlign: 'center', sortable: false, headerClassName: `${styles.tableHeader}`, @@ -181,16 +221,16 @@ function volunteerGroups(): JSX.Element { return (
- {params.row.actionItemCategory?.name} + {params.row.assignments.length}
); }, }, { - field: 'actions', - headerName: 'Actions Completed', + field: 'members', + headerName: 'No. of Members', flex: 1, align: 'center', headerAlign: 'center', @@ -198,13 +238,12 @@ function volunteerGroups(): JSX.Element { headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { return ( - } - label={params.row.isCompleted ? 'Completed' : 'Pending'} - variant="outlined" - color="primary" - className={`${styles.chip} ${params.row.isCompleted ? styles.active : styles.pending}`} - /> +
+ {params.row.volunteers.length} +
); }, }, @@ -225,8 +264,8 @@ function volunteerGroups(): JSX.Element { size="sm" style={{ minWidth: '32px' }} className="me-2 rounded" - data-testid={`viewItemBtn${params.row.id}`} - onClick={() => console.log('View Button Clicked')} + data-testid={`viewGroupBtn${params.row.id}`} + onClick={() => handleModalClick(params.row, ModalState.VIEW)} > @@ -234,7 +273,7 @@ function volunteerGroups(): JSX.Element { variant="success" size="sm" className="me-2 rounded" - data-testid={`editItemBtn${params.row.id}`} + data-testid={`editGroupBtn${params.row.id}`} onClick={() => console.log('Edit Button Clicked')} > @@ -243,8 +282,8 @@ function volunteerGroups(): JSX.Element { size="sm" variant="danger" className="rounded" - data-testid={`deleteItemBtn${params.row.id}`} - onClick={() => console.log('Delete Button Clicked')} + data-testid={`deleteGroupBtn${params.row.id}`} + onClick={() => handleModalClick(params.row, ModalState.DELETE)} > @@ -302,16 +341,16 @@ function volunteerGroups(): JSX.Element { setSearchBy('assignee')} - data-testid="assignee" + onClick={() => setSearchBy('leader')} + data-testid="leader" > - {t('assignee')} + {t('leader')} setSearchBy('category')} - data-testid="category" + onClick={() => setSearchBy('group')} + data-testid="group" > - {t('category')} + {t('group')} @@ -327,47 +366,16 @@ function volunteerGroups(): JSX.Element { setSortBy('dueDate_DESC')} - data-testid="dueDate_DESC" + onClick={() => setSortBy('member_DESC')} + data-testid="member_DESC" > - {t('latestDueDate')} + {t('mostMembers')} setSortBy('dueDate_ASC')} - data-testid="dueDate_ASC" + onClick={() => setSortBy('member_ASC')} + data-testid="member_ASC" > - {t('earliestDueDate')} - - - - - - - {t('status')} - - - setStatus(null)} - data-testid="statusAll" - > - {tCommon('all')} - - setStatus(ItemStatus.Pending)} - data-testid="statusPending" - > - {tCommon('pending')} - - setStatus(ItemStatus.Completed)} - data-testid="statusCompleted" - > - {tCommon('completed')} + {t('leastMembers')} @@ -375,7 +383,7 @@ function volunteerGroups(): JSX.Element {
- {/* Table with Action Items */} + {/* Table with Volunteer Groups */} `${styles.rowBackground}`} autoHeight rowHeight={65} - rows={actionItems.map((actionItem, index) => ({ + rows={groups.map((group, index) => ({ id: index + 1, - ...actionItem, + ...group, }))} columns={columns} isRowSelectable={() => false} /> + + closeModal(ModalState.SAME)} + refetchGroups={refetchGroups} + eventId={eventId} + orgId={orgId} + group={group} + mode={modalMode} + /> + + closeModal(ModalState.DELETE)} + refetchGroups={refetchGroups} + group={group} + /> + + {group && ( + closeModal(ModalState.VIEW)} + group={group} + /> + )}
); } diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx new file mode 100644 index 0000000000..810dd4ffcd --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx @@ -0,0 +1,151 @@ +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceUserInfo } from 'utils/interfaces'; +import styles from '../EventVolunteers.module.css'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { Autocomplete, TextField } from '@mui/material'; + +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; +import { ADD_VOLUNTEER } from 'GraphQl/Mutations/EventVolunteerMutation'; + +export interface InterfaceVolunteerCreateModal { + isOpen: boolean; + hide: () => void; + eventId: string; + orgId: string; + refetchVolunteers: () => void; +} + +/** + * A modal dialog for add a volunteer for an event. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param eventId - The ID of the event associated with volunteer. + * + * @returns The rendered modal component. + * + * The `VolunteerCreateModal` component displays a form within a modal dialog for adding a volunteer. + * It includes fields for selecting user. + * + * The modal includes: + * - A header with a title and a close button. + * - A form with: + * - A multi-select dropdown for selecting user be added as volunteer. + * - A submit button to create or update the pledge. + * + * On form submission, the component: + * - Calls `addVolunteer` mutation to add a new Volunteer. + * + * Success or error messages are displayed using toast notifications based on the result of the mutation. + */ + +const VolunteerCreateModal: React.FC = ({ + isOpen, + hide, + eventId, + orgId, + refetchVolunteers, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + + const [userId, setUserId] = useState(''); + const [members, setMembers] = useState([]); + const [addVolunteer] = useMutation(ADD_VOLUNTEER); + + const { data: memberData } = useQuery(MEMBERS_LIST, { + variables: { id: orgId }, + }); + + useEffect(() => { + if (memberData) { + /*istanbul ignore next*/ + setMembers(memberData.organizations[0].members); + } + }, [memberData]); + + // Function to add a volunteer for an event + const addVolunteerHandler = useCallback( + async (e: ChangeEvent): Promise => { + try { + e.preventDefault(); + await addVolunteer({ + variables: { + data: { + eventId, + userId, + }, + }, + }); + + toast.success(t('volunteerAdded')); + refetchVolunteers(); + setUserId(''); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }, + [userId, eventId], + ); + + return ( + + +

{t('addVolunteer')}

+ +
+ +
+ {/* A Multi-select dropdown enables admin to select more than one pledger for participating in a pledge */} + + option._id === value._id} + filterSelectedOptions={true} + getOptionLabel={(member: InterfaceUserInfo): string => + `${member.firstName} ${member.lastName}` + } + onChange={ + /*istanbul ignore next*/ + (_, newVolunteer): void => { + setUserId(newVolunteer?._id ?? ''); + } + } + renderInput={(params) => } + /> + + + {/* Button to submit the volunteer form */} + +
+
+
+ ); +}; +export default VolunteerCreateModal; diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx new file mode 100644 index 0000000000..c8b5a67062 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx @@ -0,0 +1,103 @@ +import { Button, Modal } from 'react-bootstrap'; +import styles from '../EventVolunteers.module.css'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation } from '@apollo/client'; +import type { InterfaceEventVolunteerInfo } from 'utils/interfaces'; +import { toast } from 'react-toastify'; +import { DELETE_VOLUNTEER } from 'GraphQl/Mutations/EventVolunteerMutation'; + +export interface InterfaceDeleteVolunteerModal { + isOpen: boolean; + hide: () => void; + volunteer: InterfaceEventVolunteerInfo | null; + refetchVolunteers: () => void; +} + +/** + * A modal dialog for confirming the deletion of a volunteer. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param volunteer - The volunteer object to be deleted. + * @param refetchVolunteers - Function to refetch the volunteers after deletion. + * + * @returns The rendered modal component. + * + * + * The `VolunteerDeleteModal` component displays a confirmation dialog when a user attempts to delete a volunteer. + * It allows the user to either confirm or cancel the deletion. + * On confirmation, the `deleteVolunteer` mutation is called to remove the pledge from the database, + * and the `refetchVolunteers` function is invoked to update the list of volunteers. + * A success or error toast notification is shown based on the result of the deletion operation. + * + * The modal includes: + * - A header with a title and a close button. + * - A body with a message asking for confirmation. + * - A footer with "Yes" and "No" buttons to confirm or cancel the deletion. + * + * The `deleteVolunteer` mutation is used to perform the deletion operation. + */ + +const VolunteerDeleteModal: React.FC = ({ + isOpen, + hide, + volunteer, + refetchVolunteers, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const [deleteVolunteer] = useMutation(DELETE_VOLUNTEER); + + const deleteHandler = async (): Promise => { + try { + await deleteVolunteer({ + variables: { + id: volunteer?._id, + }, + }); + refetchVolunteers(); + hide(); + toast.success(t('volunteerRemoved')); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + return ( + <> + + +

{t('removeVolunteer')}

+ +
+ +

{t('removeVolunteerMsg')}

+
+ + + + +
+ + ); +}; +export default VolunteerDeleteModal; diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx new file mode 100644 index 0000000000..231396948b --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx @@ -0,0 +1,202 @@ +import { Button, Form, Modal } from 'react-bootstrap'; +import type { InterfaceEventVolunteerInfo } from 'utils/interfaces'; +import styles from '../EventVolunteers.module.css'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { + FormControl, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, +} from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; +import { HistoryToggleOff, TaskAlt } from '@mui/icons-material'; + +export interface InterfaceVolunteerViewModal { + isOpen: boolean; + hide: () => void; + volunteer: InterfaceEventVolunteerInfo; +} + +/** + * A modal dialog for viewing volunteer information for an event. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param volunteer - The volunteer object to be displayed. + * + * @returns The rendered modal component. + * + * The `VolunteerViewModal` component displays all the fields of a volunteer in a modal dialog. + * + * The modal includes: + * - A header with a title and a close button. + * - fields for volunteer name, status, hours volunteered, groups, and assignments. + */ + +const VolunteerViewModal: React.FC = ({ + isOpen, + hide, + volunteer, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const { user, hasAccepted, hoursVolunteered, groups } = volunteer; + + return ( + + +

{t('volunteerDetails')}

+ +
+ +
+ {/* Volunteer Name & Avatar */} + + + + {user.image ? ( + Volunteer + ) : ( +
+ +
+ )} + + ), + }} + /> +
+
+ {/* Status and hours volunteered */} + + + {hasAccepted ? ( + + ) : ( + + )} + + ), + style: { + color: hasAccepted ? 'green' : '#ed6c02', + }, + }} + inputProps={{ + style: { + WebkitTextFillColor: hasAccepted ? 'green' : '#ed6c02', + }, + }} + disabled + /> + + + + {/* Table for Associated Volunteer Groups */} + {groups && groups.length > 0 && ( + + + Volunteer Groups Joined + + + + + + + Sr. No. + Group Name + + No. of Members + + + + + {groups.map((group, index) => { + const { _id, name, volunteers } = group; + return ( + + + {index + 1} + + + {name} + + + {volunteers.length} + + + ); + })} + +
+
+
+ )} +
+
+
+ ); +}; +export default VolunteerViewModal; diff --git a/src/screens/EventVolunteers/Volunteers.tsx b/src/screens/EventVolunteers/Volunteers/Volunteers.tsx similarity index 65% rename from src/screens/EventVolunteers/Volunteers.tsx rename to src/screens/EventVolunteers/Volunteers/Volunteers.tsx index ba2a6cabd1..17006296a6 100644 --- a/src/screens/EventVolunteers/Volunteers.tsx +++ b/src/screens/EventVolunteers/Volunteers/Volunteers.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Button, Dropdown, Form } from 'react-bootstrap'; import { Navigate, useParams } from 'react-router-dom'; @@ -12,9 +12,6 @@ import { } from '@mui/icons-material'; import { useQuery } from '@apollo/client'; -import { ACTION_ITEM_LIST } from 'GraphQl/Queries/Queries'; - -import type { InterfaceActionItemList } from 'utils/interfaces'; import Loader from 'components/Loader/Loader'; import { DataGrid, @@ -23,12 +20,23 @@ import { } from '@mui/x-data-grid'; import { Chip, Stack } from '@mui/material'; import Avatar from 'components/Avatar/Avatar'; -import styles from './EventVolunteers.module.css'; +import styles from '../EventVolunteers.module.css'; +import { EVENT_VOLUNTEER_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; +import { InterfaceEventVolunteerInfo } from 'utils/interfaces'; +import VolunteerCreateModal from './VolunteerCreateModal'; +import VolunteerDeleteModal from './VolunteerDeleteModal'; +import VolunteerViewModal from './VolunteerViewModal'; -enum ItemStatus { +enum VolunteerStatus { + All = 'all', Pending = 'pending', - Completed = 'completed', - Late = 'late', + Accepted = 'accepted', +} + +enum ModalState { + ADD = 'add', + DELETE = 'delete', + VIEW = 'view', } const dataGridStyle = { @@ -69,60 +77,89 @@ function volunteers(): JSX.Element { // Get the organization ID from URL parameters const { orgId, eventId } = useParams(); - if (!orgId) { + if (!orgId || !eventId) { return ; } + const [volunteer, setVolunteer] = + useState(null); const [searchValue, setSearchValue] = useState(''); const [searchTerm, setSearchTerm] = useState(''); - const [sortBy, setSortBy] = useState<'dueDate_ASC' | 'dueDate_DESC' | null>( - null, + const [sortBy, setSortBy] = useState< + 'hoursVolunteered_ASC' | 'hoursVolunteered_DESC' | null + >(null); + const [status, setStatus] = useState(VolunteerStatus.All); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.ADD]: false, + [ModalState.DELETE]: false, + [ModalState.VIEW]: false, + }); + + const openModal = (modal: ModalState): void => { + setModalState((prevState) => ({ ...prevState, [modal]: true })); + }; + + const closeModal = (modal: ModalState): void => { + setModalState((prevState) => ({ ...prevState, [modal]: false })); + }; + + const handleOpenModal = useCallback( + ( + volunteer: InterfaceEventVolunteerInfo | null, + modalType: ModalState, + ): void => { + setVolunteer(volunteer); + openModal(modalType); + }, + [openModal], ); - const [status, setStatus] = useState(null); - const [searchBy] = useState<'assignee' | 'category'>('assignee'); /** - * Query to fetch action items for the organization based on filters and sorting. + * Query to fetch event volunteers for the event. */ const { - data: actionItemsData, - loading: actionItemsLoading, - error: actionItemsError, + data: volunteersData, + loading: volunteersLoading, + error: volunteersError, + refetch: refetchVolunteers, }: { - data: InterfaceActionItemList | undefined; + data?: { + getEventVolunteers: InterfaceEventVolunteerInfo[]; + }; loading: boolean; error?: Error | undefined; - } = useQuery(ACTION_ITEM_LIST, { + refetch: () => void; + } = useQuery(EVENT_VOLUNTEER_LIST, { variables: { - organizationId: orgId, - eventId: eventId, - orderBy: sortBy, where: { - assigneeName: searchBy === 'assignee' ? searchTerm : undefined, - categoryName: searchBy === 'category' ? searchTerm : undefined, - is_completed: - status === null ? undefined : status === ItemStatus.Completed, + eventId: eventId, + hasAccepted: + status === VolunteerStatus.All + ? undefined + : status === VolunteerStatus.Accepted, + name_contains: searchTerm, }, + orderBy: sortBy, }, }); - const actionItems = useMemo( - () => actionItemsData?.actionItemsByOrganization || [], - [actionItemsData], + const volunteers = useMemo( + () => volunteersData?.getEventVolunteers || [], + [volunteersData], ); - if (actionItemsLoading) { + if (volunteersLoading) { return ; } - if (actionItemsError) { + if (volunteersError) { return (
- {tErrors('errorLoading', { entity: 'Action Items' })} -
- {`${actionItemsError.message}`} + {tErrors('errorLoading', { entity: 'Volunteers' })}
); @@ -133,22 +170,22 @@ function volunteers(): JSX.Element { field: 'volunteer', headerName: 'Volunteer', flex: 1, - align: 'left', + align: 'center', minWidth: 100, headerAlign: 'center', sortable: false, headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { - const { _id, firstName, lastName, image } = params.row.assignee; + const { _id, firstName, lastName, image } = params.row.user; return (
{image ? ( Assignee @@ -163,7 +200,7 @@ function volunteers(): JSX.Element { />
)} - {params.row.assignee.firstName + ' ' + params.row.assignee.lastName} + {params.row.user.firstName + ' ' + params.row.user.lastName}
); }, @@ -179,18 +216,19 @@ function volunteers(): JSX.Element { headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { return ( -
- {params.row.actionItemCategory?.name} -
+ } + label={params.row.hasAccepted ? 'Accepted' : 'Pending'} + variant="outlined" + color="primary" + className={`${styles.chip} ${params.row.hasAccepted ? styles.active : styles.pending}`} + /> ); }, }, { field: 'hours', - headerName: 'No. of Hours Volunteered', + headerName: 'Hours Volunteered', flex: 1, align: 'center', headerAlign: 'center', @@ -198,13 +236,12 @@ function volunteers(): JSX.Element { headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { return ( - } - label={params.row.isCompleted ? 'Completed' : 'Pending'} - variant="outlined" - color="primary" - className={`${styles.chip} ${params.row.isCompleted ? styles.active : styles.pending}`} - /> +
+ {params.row.hoursVolunteered ?? '-'} +
); }, }, @@ -218,7 +255,12 @@ function volunteers(): JSX.Element { flex: 1, renderCell: (params: GridCellParams) => { return ( -
{params.row.allotedHours ?? '-'}
+
+ {params.row.assignments.length} +
); }, }, @@ -240,25 +282,16 @@ function volunteers(): JSX.Element { style={{ minWidth: '32px' }} className="me-2 rounded" data-testid={`viewItemBtn${params.row.id}`} - onClick={() => console.log('View Action Item')} + onClick={() => handleOpenModal(params.row, ModalState.VIEW)} > - @@ -307,7 +340,6 @@ function volunteers(): JSX.Element { @@ -316,23 +348,22 @@ function volunteers(): JSX.Element { setSortBy('dueDate_DESC')} - data-testid="dueDate_DESC" + onClick={() => setSortBy('hoursVolunteered_DESC')} + data-testid="hoursVolunteered_DESC" > - {t('latestDueDate')} + {t('mostHoursVolunteered')} setSortBy('dueDate_ASC')} - data-testid="dueDate_ASC" + onClick={() => setSortBy('hoursVolunteered_ASC')} + data-testid="hoursVolunteered_ASC" > - {t('earliestDueDate')} + {t('leastHoursVolunteered')} @@ -341,22 +372,22 @@ function volunteers(): JSX.Element { setStatus(null)} + onClick={() => setStatus(VolunteerStatus.All)} data-testid="statusAll" > {tCommon('all')} setStatus(ItemStatus.Pending)} + onClick={() => setStatus(VolunteerStatus.Pending)} data-testid="statusPending" > {tCommon('pending')} setStatus(ItemStatus.Completed)} - data-testid="statusCompleted" + onClick={() => setStatus(VolunteerStatus.Accepted)} + data-testid="statusAccepted" > - {tCommon('completed')} + {t('accepted')} @@ -364,18 +395,18 @@ function volunteers(): JSX.Element {
- {/* Table with Action Items */} + {/* Table with Volunteers */} `${styles.rowBackground}`} autoHeight rowHeight={65} - rows={actionItems.map((actionItem, index) => ({ + rows={volunteers.map((volunteer, index) => ({ id: index + 1, - ...actionItem, + ...volunteer, }))} columns={columns} isRowSelectable={() => false} /> + + closeModal(ModalState.ADD)} + eventId={eventId} + orgId={orgId} + refetchVolunteers={refetchVolunteers} + /> + + closeModal(ModalState.DELETE)} + volunteer={volunteer} + refetchVolunteers={refetchVolunteers} + /> + {volunteer && ( + closeModal(ModalState.VIEW)} + volunteer={volunteer} + /> + )} ); } diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx index f7e339dc89..d14ee9de06 100644 --- a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx +++ b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx @@ -18,7 +18,7 @@ import Avatar from 'components/Avatar/Avatar'; import type { GridCellParams, GridColDef } from '@mui/x-data-grid'; import type { InterfacePledgeInfo, - InterfacePledger, + InterfaceUserInfo, InterfaceQueryFundCampaignsPledges, } from 'utils/interfaces'; import ProgressBar from 'react-bootstrap/ProgressBar'; @@ -84,7 +84,7 @@ const fundCampaignPledge = (): JSX.Element => { }); const [anchor, setAnchor] = useState(null); - const [extraUsers, setExtraUsers] = useState([]); + const [extraUsers, setExtraUsers] = useState([]); const [progressIndicator, setProgressIndicator] = useState< 'raised' | 'pledged' >('pledged'); @@ -189,7 +189,7 @@ const fundCampaignPledge = (): JSX.Element => { const handleClick = ( event: React.MouseEvent, - users: InterfacePledger[], + users: InterfaceUserInfo[], ): void => { setExtraUsers(users); setAnchor(anchor ? null : event.currentTarget); @@ -226,7 +226,7 @@ const fundCampaignPledge = (): JSX.Element => {
{params.row.users .slice(0, 2) - .map((user: InterfacePledger, index: number) => ( + .map((user: InterfaceUserInfo, index: number) => (
{user.image ? ( { disablePortal className={`${styles.popup} ${extraUsers.length > 4 ? styles.popupExtra : ''}`} > - {extraUsers.map((user: InterfacePledger, index: number) => ( + {extraUsers.map((user: InterfaceUserInfo, index: number) => (
= ({ pledgeEndDate: new Date(pledge?.endDate ?? new Date()), pledgeStartDate: new Date(pledge?.startDate ?? new Date()), }); - const [pledgers, setPledgers] = useState([]); + const [pledgers, setPledgers] = useState([]); const [updatePledge] = useMutation(UPDATE_PLEDGE); const [createPledge] = useMutation(CREATE_PlEDGE); @@ -235,7 +235,7 @@ const PledgeModal: React.FC = ({ value={pledgeUsers} isOptionEqualToValue={(option, value) => option._id === value._id} filterSelectedOptions={true} - getOptionLabel={(member: InterfacePledger): string => + getOptionLabel={(member: InterfaceUserInfo): string => `${member.firstName} ${member.lastName}` } onChange={ diff --git a/src/screens/UserPortal/Campaigns/PledgeModal.tsx b/src/screens/UserPortal/Campaigns/PledgeModal.tsx index d9076f52c8..44cc82401b 100644 --- a/src/screens/UserPortal/Campaigns/PledgeModal.tsx +++ b/src/screens/UserPortal/Campaigns/PledgeModal.tsx @@ -6,7 +6,7 @@ import { currencyOptions, currencySymbols } from 'utils/currency'; import type { InterfaceCreatePledge, InterfacePledgeInfo, - InterfacePledger, + InterfaceUserInfo, } from 'utils/interfaces'; import styles from './Campaigns.module.css'; import React, { useCallback, useEffect, useState } from 'react'; @@ -77,7 +77,7 @@ const PledgeModal: React.FC = ({ }); // State to manage the list of pledgers (users who are part of the pledge) - const [pledgers, setPledgers] = useState([]); + const [pledgers, setPledgers] = useState([]); // Mutation to update an existing pledge const [updatePledge] = useMutation(UPDATE_PLEDGE); @@ -252,7 +252,7 @@ const PledgeModal: React.FC = ({ readOnly={mode === 'edit' ? true : false} isOptionEqualToValue={(option, value) => option._id === value._id} filterSelectedOptions={true} - getOptionLabel={(member: InterfacePledger): string => + getOptionLabel={(member: InterfaceUserInfo): string => `${member.firstName} ${member.lastName}` } onChange={ diff --git a/src/screens/UserPortal/Pledges/Pledges.tsx b/src/screens/UserPortal/Pledges/Pledges.tsx index 59802be507..33e8bf63c2 100644 --- a/src/screens/UserPortal/Pledges/Pledges.tsx +++ b/src/screens/UserPortal/Pledges/Pledges.tsx @@ -4,7 +4,7 @@ import styles from './Pledges.module.css'; import { useTranslation } from 'react-i18next'; import { Search, Sort, WarningAmberRounded } from '@mui/icons-material'; import useLocalStorage from 'utils/useLocalstorage'; -import type { InterfacePledgeInfo, InterfacePledger } from 'utils/interfaces'; +import type { InterfacePledgeInfo, InterfaceUserInfo } from 'utils/interfaces'; import { Unstable_Popup as BasePopup } from '@mui/base/Unstable_Popup'; import { type ApolloQueryResult, useQuery } from '@apollo/client'; import { USER_PLEDGES } from 'GraphQl/Queries/fundQueries'; @@ -81,7 +81,7 @@ const Pledges = (): JSX.Element => { } const [anchor, setAnchor] = useState(null); - const [extraUsers, setExtraUsers] = useState([]); + const [extraUsers, setExtraUsers] = useState([]); const [searchTerm, setSearchTerm] = useState(''); const [pledges, setPledges] = useState([]); const [pledge, setPledge] = useState(null); @@ -154,7 +154,7 @@ const Pledges = (): JSX.Element => { const handleClick = ( event: React.MouseEvent, - users: InterfacePledger[], + users: InterfaceUserInfo[], ): void => { setExtraUsers(users); setAnchor(anchor ? null : event.currentTarget); @@ -197,7 +197,7 @@ const Pledges = (): JSX.Element => {
{params.row.users .slice(0, 2) - .map((user: InterfacePledger, index: number) => ( + .map((user: InterfaceUserInfo, index: number) => (
{user.image ? ( { disablePortal className={`${styles.popup} ${extraUsers.length > 4 ? styles.popupExtra : ''}`} > - {extraUsers.map((user: InterfacePledger, index: number) => ( + {extraUsers.map((user: InterfaceUserInfo, index: number) => (
{ + // Retrieves translation functions for various namespaces + const { t } = useTranslation('translation', { + keyPrefix: 'userVolunteer', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Retrieves stored user ID from local storage + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + // Extracts organization ID from the URL parameters + const { orgId } = useParams(); + if (!orgId || !userId) { + // Redirects to the homepage if orgId or userId is missing + return ; + } + + const [searchTerm, setSearchTerm] = useState(''); + const [searchValue, setSearchValue] = useState(''); + const [filter, setFilter] = useState(null); + const [sortBy, setSortBy] = useState< + 'createdAt_ASC' | 'createdAt_DESC' | null + >(null); + + const [updateMembership] = useMutation(UPDATE_VOLUNTEER_MEMBERSHIP); + + const updateMembershipStatus = async ( + id: string, + status: 'accepted' | 'rejected', + ): Promise => { + try { + await updateMembership({ + variables: { + id: id, + status: status, + }, + }); + toast.success( + t( + status === 'accepted' ? 'invitationAccepted' : 'invitationRejected', + ) as string, + ); + refetchInvitations(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + const { + data: invitationData, + loading: invitationLoading, + error: invitationError, + refetch: refetchInvitations, + }: { + data?: { + getVolunteerMembership: InterfaceVolunteerMembership[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(USER_VOLUNTEER_MEMBERSHIP, { + variables: { + where: { + userId: userId, + status: 'invited', + filter: filter, + eventTitle: searchTerm ? searchTerm : undefined, + }, + orderBy: sortBy ? sortBy : undefined, + }, + }); + + const invitations = useMemo(() => { + if (!invitationData) return []; + return invitationData.getVolunteerMembership; + }, [invitationData]); + + // loads the invitations when the component mounts + if (invitationLoading) return ; + if (invitationError) { + // Displays an error message if there is an issue loading the invvitations + return ( +
+
+ +
+ {tErrors('errorLoading', { entity: 'Volunteership Invitations' })} +
+ {invitationError.message} +
+
+
+ ); + } + + // Renders the invitations list and UI elements for searching, sorting, and accepting/rejecting invites + return ( + <> +
+ {/* Search input field and button */} +
+ setSearchValue(e.target.value)} + onKeyUp={(e) => { + if (e.key === 'Enter') { + setSearchTerm(searchValue); + } else if (e.key === 'Backspace' && searchValue === '') { + setSearchTerm(''); + } + }} + data-testid="searchInvitations" + /> + +
+
+
+ {/* Dropdown menu for sorting invitations */} + + + + {tCommon('sort')} + + + setSortBy('createdAt_DESC')} + data-testid="createdAt_DESC" + > + {t('receivedLatest')} + + setSortBy('createdAt_ASC')} + data-testid="createdAt_ASC" + > + {t('receivedEarliest')} + + + + + + + + {t('filter')} + + + setFilter(null)} + data-testid="filterAll" + > + {tCommon('all')} + + setFilter(ItemFilter.Group)} + data-testid="filterGroup" + > + {t('groupInvite')} + + setFilter(ItemFilter.Individual)} + data-testid="filterIndividual" + > + {t('individualInvite')} + + + +
+
+
+ {invitations.length < 1 ? ( + + {/* Displayed if no invitations are found */} + {t('noInvitations')} + + ) : ( + invitations.map( + (invite: InterfaceVolunteerMembership, index: number) => ( +
+
+
+ {invite.group ? ( + <>Invitation to join volunteer group + ) : ( + <>Invitation to volunteer for event + )} +
+
+ {invite.group && ( + <> +
+ + Group:{' '} + {invite.group.name} +
+ | + + )} +
+ + Event:{' '} + {invite.event.title} +
+ | +
+ + Received:{' '} + {new Date(invite.createdAt).toLocaleString()} +
+
+
+
+ + +
+
+ ), + ) + )} + + ); +}; + +export default Invitations; diff --git a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx new file mode 100644 index 0000000000..c95a4e7da2 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx @@ -0,0 +1,397 @@ +import React, { useMemo, useState } from 'react'; +import { Dropdown, Form, Button } from 'react-bootstrap'; +import styles from '../VolunteerManagement.module.css'; +import { useTranslation } from 'react-i18next'; +import { Navigate, useParams } from 'react-router-dom'; +import { IoLocationOutline } from 'react-icons/io5'; +import { + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, +} from '@mui/material'; +import { Circle, Search, Sort, WarningAmberRounded } from '@mui/icons-material'; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Chip, + Stack, +} from '@mui/material'; +import { GridExpandMoreIcon } from '@mui/x-data-grid'; +import useLocalStorage from 'utils/useLocalstorage'; +import { useMutation, useQuery } from '@apollo/client'; +import type { InterfaceUserEvents } from 'utils/interfaces'; +import { IoIosHand } from 'react-icons/io'; +import Loader from 'components/Loader/Loader'; +import { USER_EVENTS_VOLUNTEER } from 'GraphQl/Queries/PlugInQueries'; +import { CREATE_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Mutations/EventVolunteerMutation'; +import { toast } from 'react-toastify'; + +/** + * The `UpcomingEvents` component displays list of upcoming events for the user to volunteer. + * It allows the user to search, sort, and volunteer for events/volunteer groups. + * + * @returns The rendered component displaying the upcoming events. + */ +const UpcomingEvents = (): JSX.Element => { + // Retrieves translation functions for various namespaces + const { t } = useTranslation('translation', { + keyPrefix: 'userVolunteer', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Retrieves stored user ID from local storage + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + // Extracts organization ID from the URL parameters + const { orgId } = useParams(); + if (!orgId || !userId) { + // Redirects to the homepage if orgId or userId is missing + return ; + } + const [currentDate] = useState(new Date()); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [searchBy, setSearchBy] = useState<'title' | 'location'>('title'); + const [_, setSortBy] = useState<'endDate_ASC' | 'endDate_DESC' | null>(null); + + const [createVolunteerMembership] = useMutation(CREATE_VOLUNTEER_MEMBERSHIP); + + const handleVolunteer = async ( + eventId: string, + group: string | null, + status: string, + ): Promise => { + try { + await createVolunteerMembership({ + variables: { + data: { + event: eventId, + group, + status, + userId, + }, + }, + }); + toast.success(t('volunteerSuccess')); + refetchEvents(); + } catch (error) { + toast.error((error as Error).message); + } + }; + + // Fetches upcomin events based on the organization ID, search term, and sorting order + const { + data: eventsData, + loading: eventsLoading, + error: eventsError, + refetch: refetchEvents, + }: { + data?: { + eventsByOrganizationConnection: InterfaceUserEvents[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(USER_EVENTS_VOLUNTEER, { + variables: { + organization_id: orgId, + title_contains: searchBy === 'title' ? searchTerm : '', + location_contains: searchBy === 'location' ? searchTerm : '', + currentDate: currentDate, + first: null, + skip: null, + }, + }); + + // Extracts the list of upcoming events from the fetched data + const events = useMemo(() => { + if (eventsData) { + return eventsData.eventsByOrganizationConnection; + } + return []; + }, [eventsData]); + + // Renders a loader while events are being fetched + if (eventsLoading) return ; + if (eventsError) { + // Displays an error message if there is an issue loading the evvents + return ( +
+
+ +
+ {tErrors('errorLoading', { entity: 'Events' })} +
+ {eventsError.message} +
+
+
+ ); + } + + // Renders the upcoming events list and UI elements for searching, sorting, and adding pledges + return ( + <> +
+ {/* Search input field and button */} +
+ setSearchValue(e.target.value)} + onKeyUp={(e) => { + if (e.key === 'Enter') { + setSearchTerm(searchValue); + } else if (e.key === 'Backspace' && searchValue === '') { + setSearchTerm(''); + } + }} + data-testid="searchBy" + /> + +
+
+
+ + + + {tCommon('searchBy', { item: '' })} + + + setSearchBy('title')} + data-testid="title" + > + {t('name')} + + setSearchBy('location')} + data-testid="location" + > + {tCommon('location')} + + + + + + + {tCommon('sort')} + + + setSortBy('endDate_DESC')} + data-testid="endDate_DESC" + > + {t('latestEndDate')} + + setSortBy('endDate_ASC')} + data-testid="endDate_ASC" + > + {t('earliestEndDate')} + + + +
+
+
+ {events.length < 1 ? ( + + {/* Displayed if no events are found */} + {t('noEvents')} + + ) : ( + events.map((event: InterfaceUserEvents, index: number) => { + const { + title, + description, + startDate, + endDate, + location, + volunteerGroups, + recurring, + _id, + volunteers, + } = event; + const isVolunteered = volunteers.some( + (volunteer) => volunteer.user._id === userId, + ); + return ( + + }> +
+
+
+

{title}

+ {recurring && ( + } + label={'Recurring' as unknown as string} + variant="outlined" + color="primary" + className={`${styles.chip} ${styles.active}`} + /> + )} +
+ +
+ + {' '} + + location: {location} + + Start Date: {startDate as unknown as string} + End Date: {endDate as unknown as string} +
+
+
+ +
+
+
+ + {description && ( +
+ Description: + {description} +
+ )} + {volunteerGroups && volunteerGroups.length > 0 && ( + + + Volunteer Groups: + + + + + + + Sr. No. + + Group Name + + + No. of Members + + + Options + + + + + {volunteerGroups.map((group, index) => { + const { _id: gId, name, volunteers } = group; + const hasJoined = volunteers.some( + (volunteer) => volunteer._id === userId, + ); + return ( + + + {index + 1} + + + {name} + + + {volunteers.length} + + + + + + ); + })} + +
+
+
+ )} +
+
+ ); + }) + )} + + ); +}; + +export default UpcomingEvents; diff --git a/src/screens/UserPortal/Volunteer/VolunteerManagement.module.css b/src/screens/UserPortal/Volunteer/VolunteerManagement.module.css new file mode 100644 index 0000000000..d3b2bbaa54 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/VolunteerManagement.module.css @@ -0,0 +1,138 @@ +/* Upcoming Events Styles */ +.btnsContainer { + display: flex; + margin: 1.5rem 0; +} + +.btnsContainer .input { + flex: 1; + min-width: 18rem; + position: relative; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); + background-color: white; +} + +.btnsContainer .input button { + width: 52px; +} + +.accordionSummary { + width: 100% !important; + padding-right: 0.75rem; + display: flex; + justify-content: space-between !important; + align-items: center; +} + +.accordionSummary button { + height: 2.25rem; + padding-top: 0.35rem; +} + +.accordionSummary button:hover { + background-color: #31bb6a50 !important; + color: #31bb6b !important; +} + +.titleContainer { + display: flex; + flex-direction: column; + gap: 0.1rem; +} + +.titleContainer h3 { + font-size: 1.25rem; + font-weight: 750; + color: #5e5e5e; + margin-top: 0.2rem; +} + +.subContainer span { + font-size: 0.9rem; + margin-left: 0.5rem; + font-weight: lighter; + color: #707070; +} + +.chipIcon { + height: 0.9rem !important; +} + +.chip { + height: 1.5rem !important; + margin: 0.15rem 0 0 1.25rem; +} + +.active { + background-color: #31bb6a50 !important; +} + +.pending { + background-color: #ffd76950 !important; + color: #bb952bd0 !important; + border-color: #bb952bd0 !important; +} + +.progress { + display: flex; + width: 45rem; +} + +.progressBar { + margin: 0rem 0.75rem; + width: 100%; + font-size: 0.9rem; + height: 1.25rem; +} + +/* Pledge Modal */ + +.pledgeModal { + max-width: 80vw; + margin-top: 2vh; + margin-left: 13vw; +} + +.titlemodal { + color: #707070; + font-weight: 600; + font-size: 32px; + width: 65%; + margin-bottom: 0px; +} + +.modalCloseBtn { + width: 40px; + height: 40px; + padding: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.noOutline input { + outline: none; +} + +.greenregbtn { + margin: 1rem 0 0; + margin-top: 15px; + border: 1px solid #e8e5e5; + box-shadow: 0 2px 2px #e8e5e5; + padding: 10px 10px; + border-radius: 5px; + background-color: #31bb6b; + width: 100%; + font-size: 16px; + color: white; + outline: none; + font-weight: 600; + cursor: pointer; + transition: + transform 0.2s, + box-shadow 0.2s; + width: 100%; +} diff --git a/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx b/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx new file mode 100644 index 0000000000..bcc6861d44 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx @@ -0,0 +1,222 @@ +import React, { useState } from 'react'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; +import { FaChevronLeft, FaTasks } from 'react-icons/fa'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown } from 'react-bootstrap'; +import { TbCalendarEvent } from 'react-icons/tb'; +import { FaRegEnvelopeOpen } from 'react-icons/fa6'; +import UpcomingEvents from './UpcomingEvents/UpcomingEvents'; +import Invitations from './Invitations/Invitations'; + +/** + * List of tabs for the volunteer dashboard. + * + * Each tab is associated with an icon and value. + */ +const volunteerDashboardTabs: { + value: TabOptions; + icon: JSX.Element; +}[] = [ + { + value: 'upcomingEvents', + icon: , + }, + { + value: 'invitations', + icon: , + }, + + // { + // value: 'groups', + // icon: , + // }, + { + value: 'actions', + icon: , + }, +]; + +/** + * Tab options for the volunteer management component. + */ +type TabOptions = 'upcomingEvents' | 'invitations' | 'actions'; + +/** + * `VolunteerManagement` component handles the display and navigation of different event management sections. + * + * It provides a tabbed interface for: + * - Viewing upcoming events to volunteer + * - Managing volunteer requests + * - Managing volunteer invitations + * - Managing volunteer groups + * + * @returns JSX.Element - The `VolunteerManagement` component. + * + * @example + * ```tsx + * + * ``` + */ +const VolunteerManagement = (): JSX.Element => { + // Translation hook for internationalization + const { t } = useTranslation('translation', { + keyPrefix: 'userVolunteer', + }); + + // Extract organization ID from URL parameters + const { orgId } = useParams(); + /*istanbul ignore next*/ + if (!orgId) { + // Redirect if event ID or organization ID is missing + return ; + } + + // Hook for navigation + const navigate = useNavigate(); + + // State hook for managing the currently selected tab + const [tab, setTab] = useState('upcomingEvents'); + + /** + * Renders a button for each tab with the appropriate icon and label. + * + * @param value - The tab value + * @param icon - The icon to display for the tab + * @returns JSX.Element - The rendered button component + */ + const renderButton = ({ + value, + icon, + }: { + value: TabOptions; + icon: React.ReactNode; + }): JSX.Element => { + const selected = tab === value; + const variant = selected ? 'success' : 'light'; + const translatedText = t(value); + + const className = selected + ? 'px-4 d-flex align-items-center rounded-3 shadow-sm' + : 'text-secondary bg-white px-4 d-flex align-items-center rounded-3 shadow-sm'; + const props = { + variant, + className, + style: { height: '2.5rem' }, + onClick: () => setTab(value), + 'data-testid': `${value}Btn`, + }; + + return ( + + ); + }; + + const handleBack = (): void => { + navigate(`/user/organization/${orgId}`); + }; + + return ( +
+ + +
+ + {volunteerDashboardTabs.map(renderButton)} +
+ + + + {t(tab)} + + + {/* Render dropdown items for each settings category */} + {volunteerDashboardTabs.map(({ value, icon }, index) => ( + setTab(value) + } + className={`d-flex gap-2 ${tab === value && 'text-secondary'}`} + > + {icon} {t(value)} + + ))} + + + + + +
+
+
+ + {/* Render content based on the selected settings category */} + {(() => { + switch (tab) { + case 'upcomingEvents': + return ( +
+ +
+ ); + case 'invitations': + return ( +
+ +
+ ); + // case 'groups': + // return ( + //
+ //

Groups

+ //
+ // ); + case 'actions': + return ( +
+

Actions

+
+ ); + } + })()} +
+ ); +}; + +export default VolunteerManagement; diff --git a/src/state/reducers/userRoutersReducer.test.ts b/src/state/reducers/userRoutersReducer.test.ts index 98c4a78464..0de8941ff4 100644 --- a/src/state/reducers/userRoutersReducer.test.ts +++ b/src/state/reducers/userRoutersReducer.test.ts @@ -17,6 +17,7 @@ describe('Testing Routes reducer', () => { { name: 'Donate', url: 'user/donate/undefined' }, { name: 'Campaigns', url: 'user/campaigns/undefined' }, { name: 'My Pledges', url: 'user/pledges/undefined' }, + { name: 'Volunteer', url: 'user/volunteer/undefined' }, ], components: [ { @@ -38,6 +39,11 @@ describe('Testing Routes reducer', () => { component: 'Campaigns', }, { name: 'My Pledges', comp_id: 'pledges', component: 'Pledges' }, + { + name: 'Volunteer', + comp_id: 'volunteer', + component: 'VolunteerManagement', + }, ], }); }); @@ -57,6 +63,7 @@ describe('Testing Routes reducer', () => { { name: 'Donate', url: 'user/donate/orgId' }, { name: 'Campaigns', url: 'user/campaigns/orgId' }, { name: 'My Pledges', url: 'user/pledges/orgId' }, + { name: 'Volunteer', url: 'user/volunteer/orgId' }, ], components: [ { @@ -78,6 +85,11 @@ describe('Testing Routes reducer', () => { component: 'Campaigns', }, { name: 'My Pledges', comp_id: 'pledges', component: 'Pledges' }, + { + name: 'Volunteer', + comp_id: 'volunteer', + component: 'VolunteerManagement', + }, ], }); }); diff --git a/src/state/reducers/userRoutesReducer.ts b/src/state/reducers/userRoutesReducer.ts index 44bc91fabb..e1bf5de0dc 100644 --- a/src/state/reducers/userRoutesReducer.ts +++ b/src/state/reducers/userRoutesReducer.ts @@ -55,6 +55,7 @@ const components: ComponentType[] = [ }, { name: 'People', comp_id: 'people', component: 'People' }, { name: 'Events', comp_id: 'events', component: 'Events' }, + { name: 'Volunteer', comp_id: 'volunteer', component: 'VolunteerManagement' }, { name: 'Donate', comp_id: 'donate', component: 'Donate' }, { name: 'Campaigns', diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index 495234a5a1..55c5eebb39 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -7,6 +7,13 @@ export interface InterfaceUserType { }; } +export interface InterfaceUserInfo { + _id: string; + firstName: string; + lastName: string; + image?: string; +} + export interface InterfaceActionItemCategoryInfo { _id: string; name: string; @@ -21,18 +28,8 @@ export interface InterfaceActionItemCategoryList { export interface InterfaceActionItemInfo { _id: string; - assignee: { - _id: string; - firstName: string; - lastName: string; - image: string | null; - }; - assigner: { - _id: string; - firstName: string; - lastName: string; - image: string | null; - }; + assignee: InterfaceUserInfo; + assigner: InterfaceUserInfo; actionItemCategory: { _id: string; name: string; @@ -47,11 +44,7 @@ export interface InterfaceActionItemInfo { _id: string; title: string; } | null; - creator: { - _id: string; - firstName: string; - lastName: string; - }; + creator: InterfaceUserInfo; allotedHours: number | null; } @@ -343,7 +336,7 @@ export interface InterfacePledgeInfo { currency: string; endDate: string; startDate: string; - users: InterfacePledger[]; + users: InterfaceUserInfo[]; } export interface InterfaceQueryOrganizationEventListItem { _id: string; @@ -483,7 +476,7 @@ export interface InterfacePostCard { } export interface InterfaceCreatePledge { - pledgeUsers: InterfacePledger[]; + pledgeUsers: InterfaceUserInfo[]; pledgeAmount: number; pledgeCurrency: string; pledgeStartDate: Date; @@ -505,13 +498,6 @@ export interface InterfaceQueryMembershipRequestsListItem { }[]; } -export interface InterfacePledger { - _id: string; - firstName: string; - lastName: string; - image: string | null; -} - export interface InterfaceAgendaItemCategoryInfo { _id: string; name: string; @@ -571,3 +557,96 @@ export interface InterfaceCustomFieldData { type: string; name: string; } + +export interface InterfaceEventVolunteerInfo { + _id: string; + hasAccepted: boolean; + hoursVolunteered: number; + user: InterfaceUserInfo; + assignments: { + _id: string; + }[]; + groups: { + _id: string; + name: string; + volunteers: { + _id: string; + }[]; + }[]; +} + +export interface InterfaceVolunteerGroupInfo { + _id: string; + name: string; + description: string; + volunteersRequired: number; + createdAt: string; + creator: InterfaceUserInfo; + leader: InterfaceUserInfo; + volunteers: { + _id: string; + user: InterfaceUserInfo; + }[]; + assignments: { + _id: string; + actionItemCategory: { + _id: string; + name: string; + }; + allotedHours: number; + isCompleted: boolean; + }[]; +} + +export interface InterfaceCreateVolunteerGroup { + name: string; + description: string | null; + leader: InterfaceUserInfo | null; + volunteersRequired: number | null; + volunteerUsers: InterfaceUserInfo[]; +} + +export interface InterfaceUserEvents { + _id: string; + title: string; + description: string; + startDate: string; + endDate: string; + location: string; + startTime: string; + endTime: string; + allDay: boolean; + recurring: boolean; + volunteerGroups: { + _id: string; + name: string; + volunteersRequired: number; + description: string; + volunteers: { _id: string }[]; + }[]; + volunteers: { + _id: string; + user: { + _id: string; + }; + }[]; +} + +export interface InterfaceVolunteerMembership { + _id: string; + status: string; + createdAt: string; + event: { + _id: string; + title: string; + startDate: string; + }; + volunteer: { + _id: string; + user: InterfaceUserInfo; + }; + group: { + _id: string; + name: string; + }; +} From 7dca88b87dc1b4e7bc8393c51faff361244fb2be Mon Sep 17 00:00:00 2001 From: Glen Date: Sat, 19 Oct 2024 17:46:08 +0530 Subject: [PATCH 03/12] Add User action item screen and add support to admin action items for hour updating --- public/locales/en/translation.json | 7 +- src/GraphQl/Mutations/ActionItemMutations.ts | 8 +- .../Mutations/EventVolunteerMutation.ts | 15 +- src/GraphQl/Queries/ActionItemQueries.ts | 77 ++- .../VolunteerGroups/VolunteerGroupModal.tsx | 50 +- .../VolunteerGroups/VolunteerGroups.tsx | 2 +- .../OrganizationActionItems/ItemModal.tsx | 224 +++++++-- .../ItemUpdateStatusModal.tsx | 6 +- .../OrganizationActionItems/ItemViewModal.tsx | 41 +- .../OrganizationActionItems.module.css | 52 ++ .../OrganizationActionItems.tsx | 75 ++- .../UserPortal/Volunteer/Actions/Actions.tsx | 473 ++++++++++++++++++ .../Volunteer/VolunteerManagement.tsx | 27 +- src/utils/interfaces.ts | 6 +- 14 files changed, 928 insertions(+), 135 deletions(-) create mode 100644 src/screens/UserPortal/Volunteer/Actions/Actions.tsx diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 5203795f90..d329255fd8 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -442,7 +442,12 @@ "close": "close", "eventActionItems": "eventActionItems", "no": "no", - "yes": "yes" + "yes": "yes", + "individuals": "Individuals", + "groups": "Groups", + "assignTo": "Assign To", + "volunteers": "Volunteers", + "volunteerGroups": "Volunteer Groups" }, "organizationAgendaCategory": { "agendaCategoryDetails": "Agenda Category Details", diff --git a/src/GraphQl/Mutations/ActionItemMutations.ts b/src/GraphQl/Mutations/ActionItemMutations.ts index 143ea284d2..c147e65af7 100644 --- a/src/GraphQl/Mutations/ActionItemMutations.ts +++ b/src/GraphQl/Mutations/ActionItemMutations.ts @@ -15,8 +15,9 @@ export const CREATE_ACTION_ITEM_MUTATION = gql` mutation CreateActionItem( $actionItemCategoryId: ID! $assigneeId: ID! + $assigneeType: String! $preCompletionNotes: String - $dueDate: Date + $dDate: Date $eventId: ID $allotedHours: Float ) { @@ -24,8 +25,9 @@ export const CREATE_ACTION_ITEM_MUTATION = gql` actionItemCategoryId: $actionItemCategoryId data: { assigneeId: $assigneeId + assigneeType: $assigneeType preCompletionNotes: $preCompletionNotes - dueDate: $dueDate + dueDate: $dDate eventId: $eventId allotedHours: $allotedHours } @@ -51,6 +53,7 @@ export const UPDATE_ACTION_ITEM_MUTATION = gql` mutation UpdateActionItem( $actionItemId: ID! $assigneeId: ID! + $assigneeType: String! $preCompletionNotes: String $postCompletionNotes: String $dueDate: Date @@ -62,6 +65,7 @@ export const UPDATE_ACTION_ITEM_MUTATION = gql` id: $actionItemId data: { assigneeId: $assigneeId + assigneeType: $assigneeType preCompletionNotes: $preCompletionNotes postCompletionNotes: $postCompletionNotes dueDate: $dueDate diff --git a/src/GraphQl/Mutations/EventVolunteerMutation.ts b/src/GraphQl/Mutations/EventVolunteerMutation.ts index 23f5e58e73..eb611361c0 100644 --- a/src/GraphQl/Mutations/EventVolunteerMutation.ts +++ b/src/GraphQl/Mutations/EventVolunteerMutation.ts @@ -53,9 +53,20 @@ export const CREATE_VOLUNTEER_GROUP = gql` } `; +/** + * GraphQL mutation to update an event volunteer group. + * @param id - The ID of the event volunteer group being updated. + * @param data - The data required to update an event volunteer group. + * @returns The ID of the updated event volunteer group. + * + */ + export const UPDATE_VOLUNTEER_GROUP = gql` - mutation CreateEventVolunteerGroup($data: EventVolunteerGroupInput!) { - createEventVolunteerGroup(data: $data) { + mutation UpdateEventVolunteerGroup( + $id: ID! + $data: UpdateEventVolunteerGroupInput! + ) { + updateEventVolunteerGroup(id: $id, data: $data) { _id } } diff --git a/src/GraphQl/Queries/ActionItemQueries.ts b/src/GraphQl/Queries/ActionItemQueries.ts index 83667baca4..ecca80ed22 100644 --- a/src/GraphQl/Queries/ActionItemQueries.ts +++ b/src/GraphQl/Queries/ActionItemQueries.ts @@ -27,10 +27,18 @@ export const ACTION_ITEM_LIST = gql` _id assignee { _id - firstName - lastName - image + user { + _id + firstName + lastName + image + } + } + assigneeGroup { + _id + name } + assigneeType assigner { _id firstName @@ -66,14 +74,76 @@ export const ACTION_ITEM_LIST_BY_EVENTS = gql` actionItemsByEvent(eventId: $eventId) { _id assignee { + ... on EventVolunteer { + _id + user { + _id + firstName + lastName + image + } + } + ... on EventVolunteerGroup { + _id + name + } + __typename + } + assigner { _id firstName lastName } + actionItemCategory { + _id + name + } + preCompletionNotes + postCompletionNotes + assignmentDate + dueDate + completionDate + isCompleted + event { + _id + title + } + creator { + _id + firstName + lastName + } + } + } +`; + +export const ACTION_ITEMS_BY_USER = gql` + query ActionItemsByUser( + $userId: ID! + $where: ActionItemWhereInput + $orderBy: ActionItemsOrderByInput + ) { + actionItemsByUser(userId: $userId, where: $where, orderBy: $orderBy) { + _id + assignee { + _id + user { + _id + firstName + lastName + image + } + } + assigneeGroup { + _id + name + } + assigneeType assigner { _id firstName lastName + image } actionItemCategory { _id @@ -94,6 +164,7 @@ export const ACTION_ITEM_LIST_BY_EVENTS = gql` firstName lastName } + allotedHours } } `; diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx index 99d4c1e2a5..76993867a6 100644 --- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx @@ -15,7 +15,7 @@ import { Autocomplete, FormControl, TextField } from '@mui/material'; import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; import { CREATE_VOLUNTEER_GROUP, - // UPDATE_VOLUNTEER_GROUP, + UPDATE_VOLUNTEER_GROUP, } from 'GraphQl/Mutations/EventVolunteerMutation'; export interface InterfaceVolunteerGroupModal { @@ -83,7 +83,7 @@ const VolunteerGroupModal: React.FC = ({ }); const [members, setMembers] = useState([]); - // const [updateVolunteerGroup] = useMutation(UPDATE_VOLUNTEER_GROUP); + const [updateVolunteerGroup] = useMutation(UPDATE_VOLUNTEER_GROUP); const [createVolunteerGroup] = useMutation(CREATE_VOLUNTEER_GROUP); const { data: memberData } = useQuery(MEMBERS_LIST, { @@ -115,32 +115,26 @@ const VolunteerGroupModal: React.FC = ({ async (e: ChangeEvent): Promise => { e.preventDefault(); - // const updatedFields: { - // [key: string]: number | string | string[] | undefined; - // } = {}; - // checks if there are changes to the pledge and adds them to the updatedFields object - // if (pledgeAmount !== pledge?.amount) { - // updatedFields.amount = pledgeAmount; - // } - // if (pledgeCurrency !== pledge?.currency) { - // updatedFields.currency = pledgeCurrency; - // } - // if (startDate !== dayjs(pledge?.startDate).format('YYYY-MM-DD')) { - // updatedFields.startDate = startDate; - // } - // if (endDate !== dayjs(pledge?.endDate).format('YYYY-MM-DD')) { - // updatedFields.endDate = endDate; - // } - // if (pledgeUsers !== pledge?.users) { - // updatedFields.users = pledgeUsers.map((user) => user._id); - // } + const updatedFields: { + [key: string]: number | string | undefined | null; + } = {}; + + if (name !== group?.name) { + updatedFields.name = name; + } + if (description !== group?.description) { + updatedFields.description = description; + } + if (volunteersRequired !== group?.volunteersRequired) { + updatedFields.volunteersRequired = volunteersRequired; + } try { - // await updatePledge({ - // variables: { - // id: pledge?._id, - // ...updatedFields, - // }, - // }); + await updateVolunteerGroup({ + variables: { + id: group?._id, + data: { ...updatedFields, eventId }, + }, + }); toast.success(t('volunteerGroupUpdated')); refetchGroups(); hide(); @@ -248,6 +242,7 @@ const VolunteerGroupModal: React.FC = ({ data-testid="leaderSelect" options={members} value={leader} + disabled={mode === 'edit'} isOptionEqualToValue={(option, value) => option._id === value._id} filterSelectedOptions={true} getOptionLabel={(member: InterfaceUserInfo): string => @@ -293,6 +288,7 @@ const VolunteerGroupModal: React.FC = ({ getOptionLabel={(member: InterfaceUserInfo): string => `${member.firstName} ${member.lastName}` } + disabled={mode === 'edit'} onChange={ /*istanbul ignore next*/ (_, newUsers): void => { diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx index 70cfbbd630..e9360b5243 100644 --- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx @@ -274,7 +274,7 @@ function volunteerGroups(): JSX.Element { size="sm" className="me-2 rounded" data-testid={`editGroupBtn${params.row.id}`} - onClick={() => console.log('Edit Button Clicked')} + onClick={() => handleModalClick(params.row, ModalState.SAME)} > diff --git a/src/screens/OrganizationActionItems/ItemModal.tsx b/src/screens/OrganizationActionItems/ItemModal.tsx index d7a38ee0df..1cce9efc9b 100644 --- a/src/screens/OrganizationActionItems/ItemModal.tsx +++ b/src/screens/OrganizationActionItems/ItemModal.tsx @@ -10,8 +10,8 @@ import type { InterfaceActionItemCategoryInfo, InterfaceActionItemCategoryList, InterfaceActionItemInfo, - InterfaceMemberInfo, - InterfaceMembersList, + InterfaceEventVolunteerInfo, + InterfaceVolunteerGroupInfo, } from 'utils/interfaces'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; @@ -21,14 +21,19 @@ import { UPDATE_ACTION_ITEM_MUTATION, } from 'GraphQl/Mutations/ActionItemMutations'; import { ACTION_ITEM_CATEGORY_LIST } from 'GraphQl/Queries/ActionItemCategoryQueries'; -import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; import { Autocomplete, FormControl, TextField } from '@mui/material'; +import { + EVENT_VOLUNTEER_GROUP_LIST, + EVENT_VOLUNTEER_LIST, +} from 'GraphQl/Queries/EventVolunteerQueries'; +import { HiUser, HiUserGroup } from 'react-icons/hi2'; /** * Interface for the form state used in the `ItemModal` component. */ interface InterfaceFormStateType { dueDate: Date; + assigneeType: 'EventVolunteer' | 'EventVolunteerGroup'; actionItemCategoryId: string; assigneeId: string; eventId?: string; @@ -45,6 +50,7 @@ export interface InterfaceItemModalProps { isOpen: boolean; hide: () => void; orgId: string; + eventId: string; actionItemsRefetch: () => void; actionItem: InterfaceActionItemInfo | null; editMode: boolean; @@ -62,7 +68,8 @@ const initializeFormState = ( ): InterfaceFormStateType => ({ dueDate: actionItem?.dueDate || new Date(), actionItemCategoryId: actionItem?.actionItemCategory?._id || '', - assigneeId: actionItem?.assignee._id || '', + assigneeId: actionItem?.assignee?._id || actionItem?.assigneeGroup?._id || '', + assigneeType: actionItem?.assigneeType || 'EventVolunteer', preCompletionNotes: actionItem?.preCompletionNotes || '', postCompletionNotes: actionItem?.postCompletionNotes || null, allotedHours: actionItem?.allotedHours || null, @@ -79,6 +86,7 @@ const ItemModal: FC = ({ isOpen, hide, orgId, + eventId, actionItem, editMode, actionItemsRefetch, @@ -89,7 +97,11 @@ const ItemModal: FC = ({ const [actionItemCategory, setActionItemCategory] = useState(null); - const [assignee, setAssignee] = useState(null); + const [assignee, setAssignee] = useState( + null, + ); + const [assigneeGroup, setAssigneeGroup] = + useState(null); const [formState, setFormState] = useState( initializeFormState(actionItem), @@ -97,6 +109,7 @@ const ItemModal: FC = ({ const { dueDate, + assigneeType, actionItemCategoryId, assigneeId, preCompletionNotes, @@ -120,26 +133,58 @@ const ItemModal: FC = ({ }); /** - * Query to fetch members of the organization. + * Query to fetch event volunteers for the event. */ const { - data: membersData, + data: volunteersData, }: { - data: InterfaceMembersList | undefined; - } = useQuery(MEMBERS_LIST, { - variables: { id: orgId }, + data?: { + getEventVolunteers: InterfaceEventVolunteerInfo[]; + }; + } = useQuery(EVENT_VOLUNTEER_LIST, { + variables: { + where: { + eventId: eventId, + hasAccepted: true, + }, + }, }); + /** + * Query to fetch the list of volunteer groups for the event. + */ + const { + data: groupsData, + }: { + data?: { + getEventVolunteerGroups: InterfaceVolunteerGroupInfo[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(EVENT_VOLUNTEER_GROUP_LIST, { + variables: { + where: { + eventId: eventId, + }, + }, + }); + + const volunteers = useMemo( + () => volunteersData?.getEventVolunteers || [], + [volunteersData], + ); + + const groups = useMemo( + () => groupsData?.getEventVolunteerGroups || [], + [groupsData], + ); + const actionItemCategories = useMemo( () => actionItemCategoriesData?.actionItemCategoriesByOrganization || [], [actionItemCategoriesData], ); - const members = useMemo( - () => membersData?.organizations[0].members || [], - [membersData], - ); - /** * Mutation to create & update a new action item. */ @@ -171,13 +216,16 @@ const ItemModal: FC = ({ ): Promise => { e.preventDefault(); try { + const dDate = dayjs(dueDate).format('YYYY-MM-DD'); await createActionItem({ variables: { - assigneeId: assignee?._id, + dDate: dDate, + assigneeId: assigneeId, + assigneeType: assigneeType, actionItemCategoryId: actionItemCategory?._id, preCompletionNotes: preCompletionNotes, allotedHours: allotedHours, - dueDate: dayjs(dueDate).format('YYYY-MM-DD'), + eventId: eventId, }, }); @@ -211,10 +259,25 @@ const ItemModal: FC = ({ if (actionItemCategoryId !== actionItem?.actionItemCategory?._id) { updatedFields.actionItemCategoryId = actionItemCategoryId; } - if (assigneeId !== actionItem?.assignee._id) { + + if ( + assigneeId !== actionItem?.assignee?._id && + assigneeType === 'EventVolunteer' + ) { updatedFields.assigneeId = assigneeId; } + if ( + assigneeId !== actionItem?.assigneeGroup?._id && + assigneeType === 'EventVolunteerGroup' + ) { + updatedFields.assigneeId = assigneeId; + } + + if (assigneeType !== actionItem?.assigneeType) { + updatedFields.assigneeType = assigneeType; + } + if (preCompletionNotes !== actionItem?.preCompletionNotes) { updatedFields.preCompletionNotes = preCompletionNotes; } @@ -240,6 +303,7 @@ const ItemModal: FC = ({ variables: { actionItemId: actionItem?._id, assigneeId: assigneeId, + assigneeType: assigneeType, ...updatedFields, }, }); @@ -261,9 +325,15 @@ const ItemModal: FC = ({ ) || null, ); setAssignee( - members.find((member) => member._id === actionItem?.assignee._id) || null, + volunteers.find( + (volunteer) => volunteer._id === actionItem?.assignee?._id, + ) || null, ); - }, [actionItem, actionItemCategories, members]); + setAssigneeGroup( + groups.find((group) => group._id === actionItem?.assigneeGroup?._id) || + null, + ); + }, [actionItem, actionItemCategories, volunteers, groups]); return ( @@ -338,29 +408,103 @@ const ItemModal: FC = ({ {!isCompleted && ( <> - - - option._id === value._id + {t('assignTo')} +
+ + handleFormChange('assigneeType', 'EventVolunteer') } - filterSelectedOptions={true} - getOptionLabel={(member: InterfaceMemberInfo): string => - `${member.firstName} ${member.lastName}` + /> + + + + handleFormChange('assigneeType', 'EventVolunteerGroup') } - onChange={(_, newAssignee): void => { - /* istanbul ignore next */ - handleFormChange('assigneeId', newAssignee?._id ?? ''); - setAssignee(newAssignee); - }} - renderInput={(params) => ( - - )} + checked={assigneeType === 'EventVolunteerGroup'} /> - + +
+ {assigneeType === 'EventVolunteer' ? ( + + + option._id === value._id + } + filterSelectedOptions={true} + getOptionLabel={( + volunteer: InterfaceEventVolunteerInfo, + ): string => + `${volunteer.user.firstName} ${volunteer.user.lastName}` + } + onChange={(_, newAssignee): void => { + /* istanbul ignore next */ + handleFormChange('assigneeId', newAssignee?._id ?? ''); + setAssignee(newAssignee); + }} + renderInput={(params) => ( + + )} + /> + + ) : ( + + + option._id === value._id + } + filterSelectedOptions={true} + getOptionLabel={( + group: InterfaceVolunteerGroupInfo, + ): string => `${group.name}`} + onChange={(_, newAssignee): void => { + /* istanbul ignore next */ + handleFormChange('assigneeId', newAssignee?._id ?? ''); + setAssigneeGroup(newAssignee); + }} + renderInput={(params) => ( + + )} + /> + + )} {/* Date Calendar Component to select due date of an action item */} diff --git a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx index 44ac0e63e6..573fd0afb7 100644 --- a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx +++ b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx @@ -52,7 +52,11 @@ const ItemUpdateStatusModal: FC = ({ await updateActionItem({ variables: { actionItemId: actionItem?._id, - assigneeId: actionItem?.assignee?._id, + assigneeId: + actionItem?.assigneeType === 'EventVolunteer' + ? actionItem?.assignee?._id + : actionItem?.assigneeGroup?._id, + assigneeType: actionItem?.assigneeType, postCompletionNotes: isCompleted ? '' : postCompletionNotes, isCompleted: !isCompleted, }, diff --git a/src/screens/OrganizationActionItems/ItemViewModal.tsx b/src/screens/OrganizationActionItems/ItemViewModal.tsx index 84d9a3e7fe..6e99fda930 100644 --- a/src/screens/OrganizationActionItems/ItemViewModal.tsx +++ b/src/screens/OrganizationActionItems/ItemViewModal.tsx @@ -38,6 +38,8 @@ const ItemViewModal: FC = ({ isOpen, hide, item }) => { const { actionItemCategory, assignee, + assigneeGroup, + assigneeType, assigner, completionDate, dueDate, @@ -79,27 +81,50 @@ const ItemViewModal: FC = ({ isOpen, hide, item }) => { label={t('assignee')} variant="outlined" className={styles.noOutline} - value={assignee.firstName + ' ' + assignee.lastName} + value={ + assigneeType === 'EventVolunteer' + ? assignee?.user?.firstName + ' ' + assignee?.user?.lastName + : assigneeGroup?.name + } disabled InputProps={{ startAdornment: ( <> - {assignee.image ? ( + {assignee && assignee.user.image ? ( Assignee - ) : ( + ) : assignee ? (
+
+ ) : ( +
+
)} diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.module.css b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css index 48720ac902..d58c759cc4 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.module.css +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css @@ -231,3 +231,55 @@ hr { width: 28px; height: 26px; } + +/* Toggle Btn */ +.toggleGroup { + width: 50%; + min-width: 20rem; + margin: 0.5rem 0rem; +} + +.toggleBtn { + padding: 0rem; + height: 2rem; + display: flex; + justify-content: center; + align-items: center; +} + +.toggleBtn:hover { + color: #31bb6b !important; +} + +input[type='radio']:checked + label { + background-color: #31bb6a50 !important; +} + +input[type='radio']:checked + label:hover { + color: black !important; +} /* Toggle Btn */ +.toggleGroup { + width: 50%; + min-width: 20rem; + margin: 0.5rem 0rem; +} + +.toggleBtn { + padding: 0rem; + height: 2rem; + display: flex; + justify-content: center; + align-items: center; +} + +.toggleBtn:hover { + color: #31bb6b !important; +} + +input[type='radio']:checked + label { + background-color: #31bb6a50 !important; +} + +input[type='radio']:checked + label:hover { + color: black !important; +} diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx index c208af5cfa..60e039e8ad 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx @@ -84,7 +84,7 @@ function organizationActionItems(): JSX.Element { // Get the organization ID from URL parameters const { orgId, eventId } = useParams(); - if (!orgId) { + if (!orgId || !eventId) { return ; } @@ -185,32 +185,58 @@ function organizationActionItems(): JSX.Element { sortable: false, headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { - const { _id, firstName, lastName, image } = params.row.assignee; + const { _id, firstName, lastName, image } = + params.row.assignee?.user || {}; + return ( -
- {image ? ( - Assignee + <> + {params.row.assigneeType === 'EventVolunteer' ? ( + <> +
+ {image ? ( + Assignee + ) : ( +
+ +
+ )} + {firstName + ' ' + lastName} +
+ ) : ( -
- -
+ <> +
+
+ +
+ {params.row.assigneeGroup?.name ?? ''} +
+ )} - {params.row.assignee.firstName + ' ' + params.row.assignee.lastName} -
+ ); }, }, @@ -514,6 +540,7 @@ function organizationActionItems(): JSX.Element { isOpen={modalState[ModalState.SAME]} hide={() => closeModal(ModalState.SAME)} orgId={orgId} + eventId={eventId} actionItemsRefetch={actionItemsRefetch} actionItem={actionItem} editMode={modalMode === 'edit'} diff --git a/src/screens/UserPortal/Volunteer/Actions/Actions.tsx b/src/screens/UserPortal/Volunteer/Actions/Actions.tsx new file mode 100644 index 0000000000..e442206dae --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Actions/Actions.tsx @@ -0,0 +1,473 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useParams } from 'react-router-dom'; + +import { Circle, Search, Sort, WarningAmberRounded } from '@mui/icons-material'; +import dayjs from 'dayjs'; + +import { useQuery } from '@apollo/client'; + +import type { InterfaceActionItemInfo } from 'utils/interfaces'; +import styles from 'screens/OrganizationActionItems/OrganizationActionItems.module.css'; +import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { Chip, Stack } from '@mui/material'; +import ItemViewModal from 'screens/OrganizationActionItems/ItemViewModal'; +import Avatar from 'components/Avatar/Avatar'; +import ItemUpdateStatusModal from 'screens/OrganizationActionItems/ItemUpdateStatusModal'; +import { ACTION_ITEMS_BY_USER } from 'GraphQl/Queries/ActionItemQueries'; +import useLocalStorage from 'utils/useLocalstorage'; + +enum ModalState { + VIEW = 'view', + STATUS = 'status', +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component for managing and displaying action items within an organization. + * + * This component allows users to view, filter, sort, and create action items. It also handles fetching and displaying related data such as action item categories and members. + * + * @returns The rendered component. + */ +function actions(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'organizationActionItems', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Get the organization ID from URL parameters + const { orgId } = useParams(); + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + if (!orgId || !userId) { + return ; + } + + const [actionItem, setActionItem] = useState( + null, + ); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState<'dueDate_ASC' | 'dueDate_DESC' | null>( + null, + ); + const [searchBy, setSearchBy] = useState<'assignee' | 'category'>('assignee'); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.VIEW]: false, + [ModalState.STATUS]: false, + }); + + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); + + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + + const handleModalClick = useCallback( + (actionItem: InterfaceActionItemInfo | null, modal: ModalState): void => { + setActionItem(actionItem); + openModal(modal); + }, + [openModal], + ); + + /** + * Query to fetch action items for the organization based on filters and sorting. + */ + const { + data: actionItemsData, + loading: actionItemsLoading, + error: actionItemsError, + refetch: actionItemsRefetch, + }: { + data?: { + actionItemsByUser: InterfaceActionItemInfo[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(ACTION_ITEMS_BY_USER, { + variables: { + userId, + orderBy: sortBy, + where: { + assigneeName: searchBy === 'assignee' ? searchTerm : undefined, + categoryName: searchBy === 'category' ? searchTerm : undefined, + }, + }, + }); + + const actionItems = useMemo( + () => actionItemsData?.actionItemsByUser || [], + [actionItemsData], + ); + + if (actionItemsLoading) { + return ; + } + + if (actionItemsError) { + return ( +
+ +
+ {tErrors('errorLoading', { entity: 'Action Items' })} +
+ {`${actionItemsError.message}`} +
+
+ ); + } + + const columns: GridColDef[] = [ + { + field: 'assignee', + headerName: 'Assignee', + flex: 1, + align: 'left', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = + params.row.assignee?.user || {}; + + return ( + <> + {params.row.assigneeType === 'EventVolunteer' ? ( + <> +
+ {image ? ( + Assignee + ) : ( +
+ +
+ )} + {firstName + ' ' + lastName} +
+ + ) : ( + <> +
+
+ +
+ {params.row.assigneeGroup?.name ?? ''} +
+ + )} + + ); + }, + }, + { + field: 'itemCategory', + headerName: 'Item Category', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
+ {params.row.actionItemCategory?.name} +
+ ); + }, + }, + { + field: 'status', + headerName: 'Status', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + } + label={params.row.isCompleted ? 'Completed' : 'Pending'} + variant="outlined" + color="primary" + className={`${styles.chip} ${params.row.isCompleted ? styles.active : styles.pending}`} + /> + ); + }, + }, + { + field: 'allotedHours', + headerName: 'Alloted Hours', + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 1, + renderCell: (params: GridCellParams) => { + return ( +
{params.row.allotedHours ?? '-'}
+ ); + }, + }, + { + field: 'dueDate', + headerName: 'Due Date', + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + flex: 1, + renderCell: (params: GridCellParams) => { + return ( +
+ {dayjs(params.row.dueDate).format('DD/MM/YYYY')} +
+ ); + }, + }, + { + field: 'options', + headerName: 'Options', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + + ); + }, + }, + { + field: 'completed', + headerName: 'Completed', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
+ handleModalClick(params.row, ModalState.STATUS)} + /> +
+ ); + }, + }, + ]; + + return ( +
+ {/* Header with search, filter and Create Button */} +
+
+ setSearchValue(e.target.value)} + onKeyUp={(e) => { + if (e.key === 'Enter') { + setSearchTerm(searchValue); + } else if (e.key === 'Backspace' && searchValue === '') { + setSearchTerm(''); + } + }} + data-testid="searchBy" + /> + +
+
+
+ + + + {tCommon('searchBy', { item: '' })} + + + setSearchBy('assignee')} + data-testid="assignee" + > + {t('assignee')} + + setSearchBy('category')} + data-testid="category" + > + {t('category')} + + + + + + + {tCommon('sort')} + + + setSortBy('dueDate_DESC')} + data-testid="dueDate_DESC" + > + {t('latestDueDate')} + + setSortBy('dueDate_ASC')} + data-testid="dueDate_ASC" + > + {t('earliestDueDate')} + + + +
+
+
+ + {/* Table with Action Items */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noActionItems')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={actionItems.map((actionItem, index) => ({ + id: index + 1, + ...actionItem, + }))} + columns={columns} + isRowSelectable={() => false} + /> + + closeModal(ModalState.STATUS)} + actionItemsRefetch={actionItemsRefetch} + /> + + {/* View Modal */} + {actionItem && ( + closeModal(ModalState.VIEW)} + item={actionItem} + /> + )} +
+ ); +} + +export default actions; diff --git a/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx b/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx index bcc6861d44..270b8d75e2 100644 --- a/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx +++ b/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx @@ -9,6 +9,7 @@ import { TbCalendarEvent } from 'react-icons/tb'; import { FaRegEnvelopeOpen } from 'react-icons/fa6'; import UpcomingEvents from './UpcomingEvents/UpcomingEvents'; import Invitations from './Invitations/Invitations'; +import Actions from './Actions/Actions'; /** * List of tabs for the volunteer dashboard. @@ -27,11 +28,6 @@ const volunteerDashboardTabs: { value: 'invitations', icon: , }, - - // { - // value: 'groups', - // icon: , - // }, { value: 'actions', icon: , @@ -53,11 +49,6 @@ type TabOptions = 'upcomingEvents' | 'invitations' | 'actions'; * - Managing volunteer groups * * @returns JSX.Element - The `VolunteerManagement` component. - * - * @example - * ```tsx - * - * ``` */ const VolunteerManagement = (): JSX.Element => { // Translation hook for internationalization @@ -195,22 +186,10 @@ const VolunteerManagement = (): JSX.Element => {
); - // case 'groups': - // return ( - //
- //

Groups

- //
- // ); case 'actions': return ( -
-

Actions

+
+
); } diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index 55c5eebb39..275f8c6b51 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -28,7 +28,9 @@ export interface InterfaceActionItemCategoryList { export interface InterfaceActionItemInfo { _id: string; - assignee: InterfaceUserInfo; + assigneeType: 'EventVolunteer' | 'EventVolunteerGroup'; + assignee: InterfaceEventVolunteerInfo | null; + assigneeGroup: InterfaceVolunteerGroupInfo | null; assigner: InterfaceUserInfo; actionItemCategory: { _id: string; @@ -38,7 +40,7 @@ export interface InterfaceActionItemInfo { postCompletionNotes: string | null; assignmentDate: Date; dueDate: Date; - completionDate: Date; + completionDate: Date | null; isCompleted: boolean; event: { _id: string; From 2abc3179fbd695622d3d55c32db3e286f9c0a36c Mon Sep 17 00:00:00 2001 From: Glen Date: Fri, 25 Oct 2024 21:26:14 +0530 Subject: [PATCH 04/12] Adding Leaderboard screens --- public/locales/en/translation.json | 20 +- public/locales/fr/translation.json | 174 +++++--- public/locales/hi/translation.json | 144 ++++-- public/locales/sp/translation.json | 172 ++++--- public/locales/zh/translation.json | 148 ++++-- src/App.tsx | 4 +- src/GraphQl/Queries/ActionItemQueries.ts | 6 + src/GraphQl/Queries/EventVolunteerQueries.ts | 19 + src/assets/images/bronze.png | Bin 0 -> 169265 bytes src/assets/images/gold.png | Bin 0 -> 157071 bytes src/assets/images/silver.png | Bin 0 -> 136779 bytes .../OrganizationScreen/OrganizationScreen.tsx | 1 + src/screens/Leaderboard/Leaderboard.tsx | 372 +++++++++++++++ .../OrganizationActionItems/ItemModal.tsx | 165 +++++-- .../ItemUpdateStatusModal.tsx | 4 +- .../OrganizationActionItems.module.css | 6 + .../OrganizationActionItems.tsx | 6 +- .../OrganizationDashboard.module.css | 6 + .../OrganizationDashboard.tsx | 185 ++++++-- .../Volunteer/Groups/GroupModal.tsx | 407 +++++++++++++++++ .../UserPortal/Volunteer/Groups/Groups.tsx | 422 ++++++++++++++++++ .../UpcomingEvents/UpcomingEvents.tsx | 34 +- .../Volunteer/VolunteerManagement.tsx | 15 +- src/utils/interfaces.ts | 18 +- 24 files changed, 1992 insertions(+), 336 deletions(-) create mode 100644 src/assets/images/bronze.png create mode 100644 src/assets/images/gold.png create mode 100644 src/assets/images/silver.png create mode 100644 src/screens/Leaderboard/Leaderboard.tsx create mode 100644 src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx create mode 100644 src/screens/UserPortal/Volunteer/Groups/Groups.tsx diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index d329255fd8..005ffa380c 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1,4 +1,16 @@ { + "leaderboard": { + "title": "Leaderboard", + "searchByVolunteer": "Search By Volunteer", + "mostHours": "Most Hours", + "leastHours": "Least Hours", + "timeFrame": "Time Frame", + "allTime": "All Time", + "weekly": "This Week", + "monthly": "This Month", + "yearly": "This Year", + "noVolunteers": "No Volunteers Found!" + }, "loginPage": { "title": "Talawa Admin", "fromPalisadoes": "An open source application by Palisadoes Foundation volunteers", @@ -266,7 +278,9 @@ "members": "members", "admins": "admins", "requests": "requests", - "talawaApiUnavailable": "talawaApiUnavailable" + "talawaApiUnavailable": "talawaApiUnavailable", + "volunteerRankings": "Volunteer Rankings", + "noVolunteers": "No Volunteers Found!" }, "organizationPeople": { "title": "Talawa Members", @@ -1361,7 +1375,9 @@ "latest": "Latest", "earliest": "Earliest", "requestAccepted": "Request accepted successfully", - "requestRejected": "Request rejected successfully" + "requestRejected": "Request rejected successfully", + "details": "Details", + "manageGroup": "Manage Group" }, "userVolunteer": { "title": "Volunteership", diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 27986096ca..914e508045 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -1,4 +1,16 @@ { + "leaderboard": { + "title": "Tableau des Leaders", + "searchByVolunteer": "Recherche par Bénévole", + "mostHours": "Le Plus d'Heures", + "leastHours": "Le Moins d'Heures", + "timeFrame": "Période", + "allTime": "Tout le Temps", + "weekly": "Cette Semaine", + "monthly": "Ce Mois", + "yearly": "Cette Année", + "noVolunteers": "Aucun Bénévole Trouvé!" + }, "loginPage": { "title": "Administrateur Talawa", "fromPalisadoes": "Une application open source réalisée par les bénévoles de la Fondation Palisadoes", @@ -266,7 +278,9 @@ "members": "Membres", "admins": "Administrateurs", "requests": "Demandes", - "talawaApiUnavailable": "API Talawa indisponible" + "talawaApiUnavailable": "API Talawa indisponible", + "volunteerRankings": "Classement des Bénévoles", + "noVolunteers": "Aucun Bénévole Trouvé!" }, "organizationPeople": { "title": "Membres Talawa", @@ -399,50 +413,55 @@ "done": "Fait" }, "organizationActionItems": { - "actionItemCategory": "Catégorie d'élément d'action", - "actionItemDetails": "Détails de l'action", - "actionItemCompleted": "Élément d'action terminé", - "assignee": "Cessionnaire", - "assigner": "Assigner", - "assignmentDate": "Date d'affectation", + "actionItemCategory": "Catégorie de l'Action", + "actionItemDetails": "Détails de l'Action", + "actionItemCompleted": "Action Terminée", + "assignee": "Attribué à", + "assigner": "Assignateur", + "assignmentDate": "Date d'Attribution", "active": "Actif", - "clearFilters": "Effacer les filtres", - "completionDate": "Date d'achèvement", - "createActionItem": "Créer un élément d'action", - "deleteActionItem": "Supprimer l'élément d'action", - "deleteActionItemMsg": "Voulez-vous supprimer cette action ?", + "clearFilters": "Effacer les Filtres", + "completionDate": "Date de Complétion", + "createActionItem": "Créer une Action", + "deleteActionItem": "Supprimer l'Action", + "deleteActionItemMsg": "Voulez-vous supprimer cette action?", "details": "Détails", - "dueDate": "Date d'échéance", - "earliest": "Le plus tôt", - "editActionItem": "Modifier l'élément d'action", - "isCompleted": "Complété", - "latest": "Dernier", - "makeActive": "Actif", - "noActionItems": "Aucune action", - "options": "Possibilités", - "preCompletionNotes": "Notes préalables à l'achèvement", - "actionItemActive": "Actif", - "markCompletion": "Marquer l'achèvement", - "actionItemStatus": "Statut de l'action", - "postCompletionNotes": "Notes post-achèvement", - "selectActionItemCategory": "Sélectionnez une catégorie d'élément d'action", - "selectAssignee": "Sélectionnez un responsable", + "dueDate": "Date d'Échéance", + "earliest": "Le Plus Ancien", + "editActionItem": "Modifier l'Action", + "isCompleted": "Terminé", + "latest": "Le Plus Récent", + "makeActive": "Rendre Actif", + "noActionItems": "Aucune Action", + "options": "Options", + "preCompletionNotes": "Notes Pré-Complétion", + "actionItemActive": "Action Active", + "markCompletion": "Marquer comme Terminé", + "actionItemStatus": "État de l'Action", + "postCompletionNotes": "Notes Post-Complétion", + "selectActionItemCategory": "Sélectionnez une Catégorie d'Action", + "selectAssignee": "Sélectionner un Attribué", "status": "Statut", - "successfulCreation": "Élément d'action créé avec succès", - "successfulUpdation": "Élément d'action mis à jour avec succès", - "successfulDeletion": "Élément d'action supprimé avec succès", - "title": "Éléments d'action", + "successfulCreation": "Action créée avec succès", + "successfulUpdation": "Action mise à jour avec succès", + "successfulDeletion": "Action supprimée avec succès", + "title": "Actions", "category": "Catégorie", - "allotedHours": "Heures allouées", - "latestDueDate": "Date d'échéance la plus récente", - "earliestDueDate": "Date d'échéance la plus ancienne", - "updateActionItem": "Mettre à jour l'élément d'action", - "noneUpdated": "Aucun des champs n'a été mis à jour", - "updateStatusMsg": "Êtes-vous sûr de vouloir marquer cet élément d'action comme en attente?", + "allotedHours": "Heures Attribuées", + "latestDueDate": "Date d'Échéance la Plus Récente", + "earliestDueDate": "Date d'Échéance la Plus Ancienne", + "updateActionItem": "Mettre à Jour l'Action", + "noneUpdated": "Aucun champ n'a été mis à jour", + "updateStatusMsg": "Voulez-vous vraiment marquer cette action comme en attente?", "close": "Fermer", - "eventActionItems": "Éléments d'action d'événement", + "eventActionItems": "Actions de l'Événement", "no": "Non", - "yes": "Oui" + "yes": "Oui", + "individuals": "Individus", + "groups": "Groupes", + "assignTo": "Attribuer à", + "volunteers": "Bénévoles", + "volunteerGroups": "Groupes de Bénévoles" }, "organizationAgendaCategory": { "agendaCategoryDetails": "Détails de la catégorie d'ordre du jour", @@ -1318,38 +1337,75 @@ "title": "Mes Promesses" }, "eventVolunteers": { - "volunteers": "Volontaires", + "volunteers": "Bénévoles", "volunteer": "Bénévole", - "volunteerGroups": "Groupes de bénévoles", + "volunteerGroups": "Groupes de Bénévoles", "individuals": "Individus", "groups": "Groupes", "status": "Statut", - "noVolunteers": "Pas de volontaires", - "noVolunteerGroups": "Pas de groupes de bénévoles", + "noVolunteers": "Aucun Bénévole", + "noVolunteerGroups": "Aucun Groupe de Bénévoles", "add": "Ajouter", - "mostHoursVolunteered": "Le plus d'heures bénévoles", - "leastHoursVolunteered": "Le moins d'heures bénévoles", + "mostHoursVolunteered": "Le Plus d'Heures de Bénévolat", + "leastHoursVolunteered": "Le Moins d'Heures de Bénévolat", "accepted": "Accepté", - "addVolunteer": "Ajouter un bénévole", - "removeVolunteer": "Retirer un bénévole", + "addVolunteer": "Ajouter un Bénévole", + "removeVolunteer": "Supprimer le Bénévole", "volunteerAdded": "Bénévole ajouté avec succès", - "volunteerRemoved": "Bénévole retiré avec succès", + "volunteerRemoved": "Bénévole supprimé avec succès", "volunteerGroupCreated": "Groupe de bénévoles créé avec succès", "volunteerGroupUpdated": "Groupe de bénévoles mis à jour avec succès", "volunteerGroupDeleted": "Groupe de bénévoles supprimé avec succès", - "removeVolunteerMsg": "Êtes-vous sûr de vouloir retirer ce bénévole?", + "removeVolunteerMsg": "Êtes-vous sûr de vouloir supprimer ce bénévole?", "deleteVolunteerGroupMsg": "Êtes-vous sûr de vouloir supprimer ce groupe de bénévoles?", - "mostMembers": "Le plus de membres", - "leastMembers": "Le moins de membres", + "mostMembers": "Plus de Membres", + "leastMembers": "Moins de Membres", "leader": "Chef", "group": "Groupe", - "createGroup": "Créer un groupe", - "updateGroup": "Mettre à jour le groupe", - "deleteGroup": "Supprimer le groupe", - "volunteersRequired": "Bénévoles requis", - "volunteerDetails": "Détails du bénévole", - "hoursVolunteered": "Heures de bénévolat", - "groupDetails": "Détails du groupe", - "creator": "Créateur" + "createGroup": "Créer un Groupe", + "updateGroup": "Mettre à Jour le Groupe", + "deleteGroup": "Supprimer le Groupe", + "volunteersRequired": "Bénévoles Requis", + "volunteerDetails": "Détails du Bénévole", + "hoursVolunteered": "Heures de Bénévolat", + "groupDetails": "Détails du Groupe", + "creator": "Créateur", + "requests": "Demandes", + "noRequests": "Aucune Demande", + "latest": "Le Plus Récent", + "earliest": "Le Plus Ancien", + "requestAccepted": "Demande acceptée avec succès", + "requestRejected": "Demande rejetée avec succès", + "details": "Détails", + "manageGroup": "Gérer le Groupe" + }, + "userVolunteer": { + "title": "Volontariat", + "name": "Titre", + "upcomingEvents": "Événements à Venir", + "requests": "Demandes", + "invitations": "Invitations", + "groups": "Groupes de Bénévoles", + "actions": "Actions", + "searchByName": "Rechercher par Nom", + "latestEndDate": "Date de Fin la Plus Récente", + "earliestEndDate": "Date de Fin la Plus Ancienne", + "noEvents": "Aucun Événement à Venir", + "volunteer": "Bénévole", + "volunteered": "A Bénévolé", + "join": "Rejoindre", + "joined": "Rejoint", + "searchByEventName": "Rechercher par Titre d'Événement", + "filter": "Filtrer", + "groupInvite": "Invitation de Groupe", + "individualInvite": "Invitation Individuelle", + "noInvitations": "Aucune Invitation", + "accept": "Accepter", + "reject": "Rejeter", + "receivedLatest": "Reçu le Plus Récemment", + "receivedEarliest": "Reçu en Premier", + "invitationAccepted": "Invitation acceptée avec succès", + "invitationRejected": "Invitation rejetée avec succès", + "volunteerSuccess": "Demande de bénévolat envoyée avec succès" } } diff --git a/public/locales/hi/translation.json b/public/locales/hi/translation.json index 17ee9ab0d4..dbd43f4e89 100644 --- a/public/locales/hi/translation.json +++ b/public/locales/hi/translation.json @@ -1,4 +1,16 @@ { + "leaderboard": { + "title": "लीडरबोर्ड", + "searchByVolunteer": "स्वयंसेवक द्वारा खोजें", + "mostHours": "सबसे अधिक घंटे", + "leastHours": "सबसे कम घंटे", + "timeFrame": "समय सीमा", + "allTime": "सभी समय", + "weekly": "इस सप्ताह", + "monthly": "इस माह", + "yearly": "इस वर्ष", + "noVolunteers": "कोई स्वयंसेवक नहीं मिला!" + }, "loginPage": { "title": "तालावा व्यवस्थापक", "fromPalisadoes": "Palisadoes फाउंडेशन स्वयंसेवकों द्वारा विकसित एक ओपन-सोर्स एप्लिकेशन", @@ -266,7 +278,9 @@ "members": "सदस्य", "admins": "प्रशासक", "requests": "अनुरोध", - "talawaApiUnavailable": "तालावा एपीआई अनुपलब्ध" + "talawaApiUnavailable": "तालावा एपीआई अनुपलब्ध", + "volunteerRankings": "स्वयंसेवक रैंकिंग", + "noVolunteers": "कोई स्वयंसेवक नहीं मिला!" }, "organizationPeople": { "title": "तालावा सदस्य", @@ -399,50 +413,55 @@ "done": "पूर्ण" }, "organizationActionItems": { - "actionItemCategory": "कार्य आइटम श्रेणी", - "actionItemDetails": "कार्रवाई मद विवरण", - "actionItemCompleted": "कार्य आइटम पूर्ण हुआ", - "assignee": "संपत्ति-भागी", - "assigner": "असाइनर", - "assignmentDate": "असाइनमेंट दिनांक", + "actionItemCategory": "क्रिया वस्तु श्रेणी", + "actionItemDetails": "क्रिया वस्तु विवरण", + "actionItemCompleted": "क्रिया वस्तु पूरी", + "assignee": "प्राप्तकर्ता", + "assigner": "सौंपने वाला", + "assignmentDate": "आवंटन तिथि", "active": "सक्रिय", "clearFilters": "फ़िल्टर साफ़ करें", - "completionDate": "पूरा करने की तिथि", - "createActionItem": "कार्रवाई आइटम बनाएं", - "deleteActionItem": "क्रिया आइटम हटाएँ", - "deleteActionItemMsg": "क्या आप इस क्रिया आइटम को हटाना चाहते हैं?", + "completionDate": "पूर्णता तिथि", + "createActionItem": "क्रिया वस्तु बनाएँ", + "deleteActionItem": "क्रिया वस्तु हटाएँ", + "deleteActionItemMsg": "क्या आप इस क्रिया वस्तु को हटाना चाहते हैं?", "details": "विवरण", - "dueDate": "नियत तारीख", - "earliest": "जल्द से जल्द", - "editActionItem": "क्रिया आइटम संपादित करें", - "isCompleted": "पुरा होना।", + "dueDate": "समाप्ति तिथि", + "earliest": "सबसे पहले", + "editActionItem": "क्रिया वस्तु संपादित करें", + "isCompleted": "पूर्ण", "latest": "नवीनतम", - "makeActive": "सक्रिय", - "noActionItems": "कोई एक्शन आइटम नहीं", + "makeActive": "सक्रिय बनाएं", + "noActionItems": "कोई क्रिया वस्तु नहीं", "options": "विकल्प", - "preCompletionNotes": "समापन पूर्व नोट्स", - "actionItemActive": "सक्रिय", - "markCompletion": "पूर्णता चिह्नित करें", - "actionItemStatus": "कार्रवाई मद स्थिति", - "postCompletionNotes": "समापन के बाद के नोट्स", - "selectActionItemCategory": "एक क्रिया आइटम श्रेणी का चयन करें", - "selectAssignee": "एक समनुदेशिती का चयन करें", + "preCompletionNotes": "पूर्व-पूर्णता नोट्स", + "actionItemActive": "सक्रिय क्रिया वस्तु", + "markCompletion": "पूर्णता को चिह्नित करें", + "actionItemStatus": "क्रिया वस्तु स्थिति", + "postCompletionNotes": "पूर्णता के बाद नोट्स", + "selectActionItemCategory": "क्रिया वस्तु श्रेणी चुनें", + "selectAssignee": "प्राप्तकर्ता चुनें", "status": "स्थिति", - "successfulCreation": "कार्रवाई आइटम सफलतापूर्वक बनाया गया", - "successfulUpdation": "कार्रवाई आइटम सफलतापूर्वक अपडेट किया गया", - "successfulDeletion": "कार्रवाई आइटम सफलतापूर्वक हटा दिया गया", - "title": "एक्शन आइटम्स", + "successfulCreation": "क्रिया वस्तु सफलतापूर्वक बनाई गई", + "successfulUpdation": "क्रिया वस्तु सफलतापूर्वक अद्यतन की गई", + "successfulDeletion": "क्रिया वस्तु सफलतापूर्वक हटाई गई", + "title": "क्रिया वस्तुएँ", "category": "श्रेणी", "allotedHours": "आवंटित घंटे", - "latestDueDate": "सबसे अधिक नियत तिथि", - "earliestDueDate": "सबसे पहले की नियत तिथि", - "updateActionItem": "कार्य आइटम अपडेट करें", - "noneUpdated": "कोई फ़ील्ड अपडेट नहीं किया गया", - "updateStatusMsg": "क्या आप वाकई इस कार्य आइटम को लंबित के रूप में चिह्नित करना चाहते हैं?", + "latestDueDate": "नवीनतम समाप्ति तिथि", + "earliestDueDate": "प्रारंभिक समाप्ति तिथि", + "updateActionItem": "क्रिया वस्तु अपडेट करें", + "noneUpdated": "कोई फ़ील्ड अपडेट नहीं की गई", + "updateStatusMsg": "क्या आप वाकई इस क्रिया वस्तु को लंबित के रूप में चिह्नित करना चाहते हैं?", "close": "बंद करें", - "eventActionItems": "कार्यक्रम कार्रवाई आइटम", + "eventActionItems": "घटना क्रिया वस्तुएं", "no": "नहीं", - "yes": "हाँ" + "yes": "हाँ", + "individuals": "व्यक्तियों", + "groups": "समूहों", + "assignTo": "सौंपें", + "volunteers": "स्वयंसेवक", + "volunteerGroups": "स्वयंसेवक समूह" }, "organizationAgendaCategory": { "agendaCategoryDetails": "एजेंडा श्रेणी विवरण", @@ -1327,8 +1346,8 @@ "noVolunteers": "कोई स्वयंसेवक नहीं", "noVolunteerGroups": "कोई स्वयंसेवक समूह नहीं", "add": "जोड़ें", - "mostHoursVolunteered": "सबसे अधिक घंटे स्वेच्छा से", - "leastHoursVolunteered": "सबसे कम घंटे स्वेच्छा से", + "mostHoursVolunteered": "सबसे अधिक घंटे स्वयंसेवा", + "leastHoursVolunteered": "सबसे कम घंटे स्वयंसेवा", "accepted": "स्वीकृत", "addVolunteer": "स्वयंसेवक जोड़ें", "removeVolunteer": "स्वयंसेवक हटाएं", @@ -1337,19 +1356,56 @@ "volunteerGroupCreated": "स्वयंसेवक समूह सफलतापूर्वक बनाया गया", "volunteerGroupUpdated": "स्वयंसेवक समूह सफलतापूर्वक अपडेट किया गया", "volunteerGroupDeleted": "स्वयंसेवक समूह सफलतापूर्वक हटाया गया", - "removeVolunteerMsg": "क्या आप इस स्वयंसेवक को हटाना चाहते हैं?", - "deleteVolunteerGroupMsg": "क्या आप इस स्वयंसेवक समूह को हटाना चाहते हैं?", - "mostMembers": "अधिकतम सदस्य", - "leastMembers": "न्यूनतम सदस्य", + "removeVolunteerMsg": "क्या आप वाकई इस स्वयंसेवक को हटाना चाहते हैं?", + "deleteVolunteerGroupMsg": "क्या आप वाकई इस स्वयंसेवक समूह को हटाना चाहते हैं?", + "mostMembers": "सबसे अधिक सदस्य", + "leastMembers": "सबसे कम सदस्य", "leader": "नेता", "group": "समूह", "createGroup": "समूह बनाएं", "updateGroup": "समूह अपडेट करें", "deleteGroup": "समूह हटाएं", - "volunteersRequired": "स्वयंसेवकों की आवश्यकता", + "volunteersRequired": "आवश्यक स्वयंसेवक", "volunteerDetails": "स्वयंसेवक विवरण", - "hoursVolunteered": "स्वेच्छा से दिए गए घंटे", + "hoursVolunteered": "स्वयंसेवा घंटे", "groupDetails": "समूह विवरण", - "creator": "निर्माता" + "creator": "निर्माता", + "requests": "अनुरोध", + "noRequests": "कोई अनुरोध नहीं", + "latest": "नवीनतम", + "earliest": "प्रारंभिक", + "requestAccepted": "अनुरोध सफलतापूर्वक स्वीकृत", + "requestRejected": "अनुरोध सफलतापूर्वक अस्वीकृत", + "details": "विवरण", + "manageGroup": "समूह प्रबंधित करें" + }, + "userVolunteer": { + "title": "स्वयंसेवकता", + "name": "शीर्षक", + "upcomingEvents": "आगामी कार्यक्रम", + "requests": "अनुरोध", + "invitations": "निमंत्रण", + "groups": "स्वयंसेवक समूह", + "actions": "क्रियाएँ", + "searchByName": "नाम से खोजें", + "latestEndDate": "नवीनतम समाप्ति तिथि", + "earliestEndDate": "प्रारंभिक समाप्ति तिथि", + "noEvents": "कोई आगामी कार्यक्रम नहीं", + "volunteer": "स्वयंसेवक", + "volunteered": "स्वयंसेवित", + "join": "शामिल हों", + "joined": "शामिल हुआ", + "searchByEventName": "कार्यक्रम शीर्षक से खोजें", + "filter": "फ़िल्टर", + "groupInvite": "समूह निमंत्रण", + "individualInvite": "व्यक्तिगत निमंत्रण", + "noInvitations": "कोई निमंत्रण नहीं", + "accept": "स्वीकारें", + "reject": "अस्वीकार करें", + "receivedLatest": "हाल में प्राप्त", + "receivedEarliest": "सबसे पहले प्राप्त", + "invitationAccepted": "निमंत्रण सफलतापूर्वक स्वीकार किया गया", + "invitationRejected": "निमंत्रण सफलतापूर्वक अस्वीकृत", + "volunteerSuccess": "स्वयंसेवक के रूप में अनुरोध सफलतापूर्वक किया गया" } } diff --git a/public/locales/sp/translation.json b/public/locales/sp/translation.json index 51202d9215..c46a798463 100644 --- a/public/locales/sp/translation.json +++ b/public/locales/sp/translation.json @@ -1,4 +1,16 @@ { + "leaderboard": { + "title": "Tabla de Clasificación", + "searchByVolunteer": "Buscar por Voluntario", + "mostHours": "Más Horas", + "leastHours": "Menos Horas", + "timeFrame": "Período", + "allTime": "Todo el Tiempo", + "weekly": "Esta Semana", + "monthly": "Este Mes", + "yearly": "Este Año", + "noVolunteers": "¡No Se Encontraron Voluntarios!" + }, "loginPage": { "title": "Administrador Talawa", "fromPalisadoes": "Una aplicación de código abierto de los voluntarios de la Fundación palisados", @@ -266,7 +278,9 @@ "noPostsPresent": "No Hay Publicaciones Presentes", "membershipRequests": "Solicitudes de Membresía", "noMembershipRequests": "No Hay Solicitudes de Membresía", - "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red.", + "volunteerRankings": "Clasificación de Voluntarios", + "noVolunteers": "¡No Se Encontraron Voluntarios!" }, "organizationPeople": { "title": "Miembros Talawa", @@ -399,50 +413,55 @@ "done": "Hecho" }, "organizationActionItems": { - "actionItemCategory": "Categoría del ítem de acción", - "actionItemActive": "Elemento de acción activo", - "actionItemCompleted": "Elemento de acción completado", - "actionItemDetails": "Detalles del ítem de acción", - "actionItemStatus": "Estado del elemento de acción", + "actionItemCategory": "Categoría de Acción", + "actionItemDetails": "Detalles de la Acción", + "actionItemCompleted": "Acción Completada", "assignee": "Asignado", "assigner": "Asignador", - "assignmentDate": "Fecha de asignación", + "assignmentDate": "Fecha de Asignación", "active": "Activo", - "clearFilters": "Borrar filtros", - "close": "Cerrar", - "completionDate": "Fecha de finalización", - "createActionItem": "Crear ítem de acción", - "deleteActionItem": "Eliminar ítem de acción", - "deleteActionItemMsg": "¿Desea eliminar este ítem de acción?", + "clearFilters": "Limpiar Filtros", + "completionDate": "Fecha de Finalización", + "createActionItem": "Crear Acción", + "deleteActionItem": "Eliminar Acción", + "deleteActionItemMsg": "¿Desea eliminar esta acción?", "details": "Detalles", - "dueDate": "Fecha de vencimiento", - "earliest": "Lo más temprano", - "editActionItem": "Editar ítem de acción", - "eventActionItems": "Elementos de acción del evento", + "dueDate": "Fecha de Vencimiento", + "earliest": "El Más Antiguo", + "editActionItem": "Editar Acción", "isCompleted": "Completado", - "latest": "Lo más reciente", - "makeActive": "Activar", - "markCompletion": "Marcar finalización", - "no": "No", - "noActionItems": "No hay ítems de acción", + "latest": "El Más Reciente", + "makeActive": "Hacer Activo", + "noActionItems": "No Hay Acciones", "options": "Opciones", - "preCompletionNotes": "Notas previas a la finalización", - "postCompletionNotes": "Notas posteriores a la finalización", - "selectActionItemCategory": "Seleccione una categoría de ítem de acción", - "selectAssignee": "Seleccione un asignado", + "preCompletionNotes": "Notas Pre-Compleción", + "actionItemActive": "Acción Activa", + "markCompletion": "Marcar como Completado", + "actionItemStatus": "Estado de la Acción", + "postCompletionNotes": "Notas de Finalización", + "selectActionItemCategory": "Seleccionar una Categoría de Acción", + "selectAssignee": "Seleccionar Asignado", "status": "Estado", - "successfulCreation": "Ítem de acción creado con éxito", - "successfulUpdation": "Ítem de acción actualizado con éxito", - "successfulDeletion": "Ítem de acción eliminado con éxito", - "title": "Ítems de acción", - "yes": "Sí", + "successfulCreation": "Acción creada con éxito", + "successfulUpdation": "Acción actualizada con éxito", + "successfulDeletion": "Acción eliminada con éxito", + "title": "Acciones", "category": "Categoría", - "allotedHours": "Horas asignadas", - "latestDueDate": "Fecha de vencimiento más reciente", - "earliestDueDate": "Fecha de vencimiento más antigua", - "updateActionItem": "Actualizar elemento de acción", - "noneUpdated": "Ninguno de los campos se actualizó", - "updateStatusMsg": "¿Está seguro de que desea marcar este elemento de acción como pendiente?" + "allotedHours": "Horas Asignadas", + "latestDueDate": "Fecha de Vencimiento Más Reciente", + "earliestDueDate": "Fecha de Vencimiento Más Antigua", + "updateActionItem": "Actualizar Acción", + "noneUpdated": "Ningún campo fue actualizado", + "updateStatusMsg": "¿Está seguro de que desea marcar esta acción como pendiente?", + "close": "Cerrar", + "eventActionItems": "Acciones del Evento", + "no": "No", + "yes": "Sí", + "individuals": "Individuos", + "groups": "Grupos", + "assignTo": "Asignar a", + "volunteers": "Voluntarios", + "volunteerGroups": "Grupos de Voluntarios" }, "organizationAgendaCategory": { "agendaCategoryDetails": "Detalles de la categoría de la agenda", @@ -1321,36 +1340,73 @@ "eventVolunteers": { "volunteers": "Voluntarios", "volunteer": "Voluntario", - "volunteerGroups": "Grupos de voluntarios", + "volunteerGroups": "Grupos de Voluntarios", "individuals": "Individuos", "groups": "Grupos", "status": "Estado", - "noVolunteers": "No hay voluntarios", - "noVolunteerGroups": "No hay grupos de voluntarios", - "add": "Añadir", - "mostHoursVolunteered": "Más horas voluntarias", - "leastHoursVolunteered": "Menos horas voluntarias", + "noVolunteers": "No Hay Voluntarios", + "noVolunteerGroups": "No Hay Grupos de Voluntarios", + "add": "Agregar", + "mostHoursVolunteered": "Más Horas de Voluntariado", + "leastHoursVolunteered": "Menos Horas de Voluntariado", "accepted": "Aceptado", - "addVolunteer": "Añadir voluntario", - "removeVolunteer": "Eliminar voluntario", - "volunteerAdded": "Voluntario añadido con éxito", + "addVolunteer": "Agregar Voluntario", + "removeVolunteer": "Eliminar Voluntario", + "volunteerAdded": "Voluntario agregado con éxito", "volunteerRemoved": "Voluntario eliminado con éxito", "volunteerGroupCreated": "Grupo de voluntarios creado con éxito", "volunteerGroupUpdated": "Grupo de voluntarios actualizado con éxito", "volunteerGroupDeleted": "Grupo de voluntarios eliminado con éxito", - "removeVolunteerMsg": "¿Estás seguro de que quieres eliminar este voluntario?", - "deleteVolunteerGroupMsg": "¿Estás seguro de que quieres eliminar este grupo de voluntarios?", - "mostMembers": "Más miembros", - "leastMembers": "Menos miembros", + "removeVolunteerMsg": "¿Está seguro de que desea eliminar a este Voluntario?", + "deleteVolunteerGroupMsg": "¿Está seguro de que desea eliminar este Grupo de Voluntarios?", + "mostMembers": "Más Miembros", + "leastMembers": "Menos Miembros", "leader": "Líder", "group": "Grupo", - "createGroup": "Crear grupo", - "updateGroup": "Actualizar grupo", - "deleteGroup": "Eliminar grupo", - "volunteersRequired": "Voluntarios requeridos", - "volunteerDetails": "Detalles del voluntario", - "hoursVolunteered": "Horas voluntarias", - "groupDetails": "Detalles del grupo", - "creator": "Creador" + "createGroup": "Crear Grupo", + "updateGroup": "Actualizar Grupo", + "deleteGroup": "Eliminar Grupo", + "volunteersRequired": "Voluntarios Necesarios", + "volunteerDetails": "Detalles del Voluntario", + "hoursVolunteered": "Horas de Voluntariado", + "groupDetails": "Detalles del Grupo", + "creator": "Creador", + "requests": "Solicitudes", + "noRequests": "No Hay Solicitudes", + "latest": "Más Reciente", + "earliest": "Más Antiguo", + "requestAccepted": "Solicitud aceptada con éxito", + "requestRejected": "Solicitud rechazada con éxito", + "details": "Detalles", + "manageGroup": "Gestionar Grupo" + }, + "userVolunteer": { + "title": "Voluntariado", + "name": "Título", + "upcomingEvents": "Próximos Eventos", + "requests": "Solicitudes", + "invitations": "Invitaciones", + "groups": "Grupos de Voluntarios", + "actions": "Acciones", + "searchByName": "Buscar por Nombre", + "latestEndDate": "Fecha de Finalización Más Reciente", + "earliestEndDate": "Fecha de Finalización Más Antigua", + "noEvents": "No Hay Próximos Eventos", + "volunteer": "Voluntario", + "volunteered": "Voluntariado", + "join": "Unirse", + "joined": "Unido", + "searchByEventName": "Buscar por Título del Evento", + "filter": "Filtrar", + "groupInvite": "Invitación de Grupo", + "individualInvite": "Invitación Individual", + "noInvitations": "No Hay Invitaciones", + "accept": "Aceptar", + "reject": "Rechazar", + "receivedLatest": "Recibido Recientemente", + "receivedEarliest": "Recibido en Primer Lugar", + "invitationAccepted": "Invitación aceptada con éxito", + "invitationRejected": "Invitación rechazada con éxito", + "volunteerSuccess": "Solicitud de voluntariado realizada con éxito" } } diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index 3bc8814f00..9049c81474 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -1,4 +1,16 @@ { + "leaderboard": { + "title": "排行榜", + "searchByVolunteer": "按志愿者搜索", + "mostHours": "最多时数", + "leastHours": "最少时数", + "timeFrame": "时间范围", + "allTime": "全部时间", + "weekly": "本周", + "monthly": "本月", + "yearly": "今年", + "noVolunteers": "未找到志愿者!" + }, "loginPage": { "title": "塔拉瓦管理员", "fromPalisadoes": "Palisadoes 基金会志愿者开发的开源应用程序", @@ -266,7 +278,9 @@ "members": "成员", "admins": "管理员", "requests": "请求", - "talawaApiUnavailable": "塔拉瓦 API 不可用" + "talawaApiUnavailable": "塔拉瓦 API 不可用", + "volunteerRankings": "志愿者排名", + "noVolunteers": "未找到志愿者!" }, "organizationPeople": { "title": "塔拉瓦会员", @@ -399,50 +413,55 @@ "done": "完成" }, "organizationActionItems": { - "actionItemCategory": "行动项目类别", - "actionItemDetails": "行动项目详情", - "actionItemCompleted": "行动项目已完成", - "assignee": "受让人", - "assigner": "转让人", + "actionItemCategory": "行动项类别", + "actionItemDetails": "行动项详情", + "actionItemCompleted": "行动项已完成", + "assignee": "受托人", + "assigner": "分配人", "assignmentDate": "分配日期", - "active": "积极的", + "active": "活跃", "clearFilters": "清除过滤器", "completionDate": "完成日期", - "createActionItem": "创建操作项", - "deleteActionItem": "删除操作项", - "deleteActionItemMsg": "您想删除此操作项吗?", - "details": "细节", - "dueDate": "到期日", + "createActionItem": "创建行动项", + "deleteActionItem": "删除行动项", + "deleteActionItemMsg": "是否要删除此行动项?", + "details": "详情", + "dueDate": "截止日期", "earliest": "最早", - "editActionItem": "编辑操作项", - "isCompleted": "完全的", - "latest": "最新的", - "makeActive": "积极的", - "noActionItems": "无行动项目", + "editActionItem": "编辑行动项", + "isCompleted": "已完成", + "latest": "最新", + "makeActive": "激活", + "noActionItems": "无行动项", "options": "选项", - "preCompletionNotes": "预完成注释", - "actionItemActive": "积极的", - "markCompletion": "标记完成", - "actionItemStatus": "行动项目状态", - "postCompletionNotes": "完成后注释", - "selectActionItemCategory": "选择操作项类别", + "preCompletionNotes": "预完成备注", + "actionItemActive": "活跃的行动项", + "markCompletion": "标记为完成", + "actionItemStatus": "行动项状态", + "postCompletionNotes": "完成后备注", + "selectActionItemCategory": "选择行动项类别", "selectAssignee": "选择受托人", - "status": "地位", - "successfulCreation": "操作项创建成功", - "successfulUpdation": "操作项已成功更新", - "successfulDeletion": "操作项已成功删除", - "title": "行动项目", + "status": "状态", + "successfulCreation": "行动项创建成功", + "successfulUpdation": "行动项更新成功", + "successfulDeletion": "行动项删除成功", + "title": "行动项", "category": "类别", "allotedHours": "分配的小时", - "latestDueDate": "最晚到期日", - "earliestDueDate": "最早到期日", - "updateActionItem": "更新操作项", - "noneUpdated": "没有更新任何字段", - "updateStatusMsg": "您确定要将此操作项标记为待处理吗?", + "latestDueDate": "最新截止日期", + "earliestDueDate": "最早截止日期", + "updateActionItem": "更新行动项", + "noneUpdated": "没有字段被更新", + "updateStatusMsg": "您确定要将此行动项标记为待处理吗?", "close": "关闭", - "eventActionItems": "活动行动项目", + "eventActionItems": "事件行动项", "no": "否", - "yes": "是" + "yes": "是", + "individuals": "个人", + "groups": "小组", + "assignTo": "分配给", + "volunteers": "志愿者", + "volunteerGroups": "志愿者小组" }, "organizationAgendaCategory": { "agendaCategoryDetails": "议程类别详情", @@ -1324,19 +1343,19 @@ "individuals": "个人", "groups": "小组", "status": "状态", - "noVolunteers": "没有志愿者", - "noVolunteerGroups": "没有志愿者小组", + "noVolunteers": "无志愿者", + "noVolunteerGroups": "无志愿者小组", "add": "添加", - "mostHoursVolunteered": "最多志愿小时", - "leastHoursVolunteered": "最少志愿小时", + "mostHoursVolunteered": "最多志愿时数", + "leastHoursVolunteered": "最少志愿时数", "accepted": "已接受", "addVolunteer": "添加志愿者", "removeVolunteer": "移除志愿者", - "volunteerAdded": "志愿者添加成功", - "volunteerRemoved": "志愿者移除成功", - "volunteerGroupCreated": "志愿者小组创建成功", - "volunteerGroupUpdated": "志愿者小组更新成功", - "volunteerGroupDeleted": "志愿者小组删除成功", + "volunteerAdded": "志愿者已成功添加", + "volunteerRemoved": "志愿者已成功移除", + "volunteerGroupCreated": "志愿者小组已成功创建", + "volunteerGroupUpdated": "志愿者小组已成功更新", + "volunteerGroupDeleted": "志愿者小组已成功删除", "removeVolunteerMsg": "您确定要移除此志愿者吗?", "deleteVolunteerGroupMsg": "您确定要删除此志愿者小组吗?", "mostMembers": "最多成员", @@ -1348,8 +1367,45 @@ "deleteGroup": "删除小组", "volunteersRequired": "需要志愿者", "volunteerDetails": "志愿者详情", - "hoursVolunteered": "志愿小时", + "hoursVolunteered": "志愿时数", "groupDetails": "小组详情", - "creator": "创建者" + "creator": "创建者", + "requests": "请求", + "noRequests": "无请求", + "latest": "最新", + "earliest": "最早", + "requestAccepted": "请求已成功接受", + "requestRejected": "请求已成功拒绝", + "details": "详情", + "manageGroup": "管理小组" + }, + "userVolunteer": { + "title": "志愿服务", + "name": "标题", + "upcomingEvents": "即将举行的活动", + "requests": "请求", + "invitations": "邀请", + "groups": "志愿者小组", + "actions": "操作", + "searchByName": "按名称搜索", + "latestEndDate": "最晚结束日期", + "earliestEndDate": "最早结束日期", + "noEvents": "无即将举行的活动", + "volunteer": "志愿者", + "volunteered": "已志愿", + "join": "加入", + "joined": "已加入", + "searchByEventName": "按活动标题搜索", + "filter": "筛选", + "groupInvite": "小组邀请", + "individualInvite": "个人邀请", + "noInvitations": "无邀请", + "accept": "接受", + "reject": "拒绝", + "receivedLatest": "最近收到", + "receivedEarliest": "最早收到", + "invitationAccepted": "邀请已成功接受", + "invitationRejected": "邀请已成功拒绝", + "volunteerSuccess": "志愿请求成功" } } diff --git a/src/App.tsx b/src/App.tsx index 0530ad1fcc..dfeb566ca1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -18,6 +18,7 @@ import OrganizationDashboard from 'screens/OrganizationDashboard/OrganizationDas import OrganizationEvents from 'screens/OrganizationEvents/OrganizationEvents'; import OrganizaitionFundCampiagn from 'screens/OrganizationFundCampaign/OrganizationFundCampagins'; import OrganizationFunds from 'screens/OrganizationFunds/OrganizationFunds'; +import FundCampaignPledge from 'screens/FundCampaignPledge/FundCampaignPledge'; import OrganizationPeople from 'screens/OrganizationPeople/OrganizationPeople'; import OrganizationTags from 'screens/OrganizationTags/OrganizationTags'; import ManageTag from 'screens/ManageTag/ManageTag'; @@ -27,6 +28,7 @@ import Requests from 'screens/Requests/Requests'; import Users from 'screens/Users/Users'; import CommunityProfile from 'screens/CommunityProfile/CommunityProfile'; import OrganizationVenues from 'screens/OrganizationVenues/OrganizationVenues'; +import Leaderboard from 'screens/Leaderboard/Leaderboard'; import React, { useEffect } from 'react'; // User Portal Components @@ -41,7 +43,6 @@ import { useQuery } from '@apollo/client'; import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; import Advertisements from 'components/Advertisements/Advertisements'; import SecuredRouteForUser from 'components/UserPortal/SecuredRouteForUser/SecuredRouteForUser'; -import FundCampaignPledge from 'screens/FundCampaignPledge/FundCampaignPledge'; import useLocalStorage from 'utils/useLocalstorage'; import UserScreen from 'screens/UserPortal/UserScreen/UserScreen'; @@ -179,6 +180,7 @@ function app(): JSX.Element { } /> } /> } /> + } /> {extraRoutes} diff --git a/src/GraphQl/Queries/ActionItemQueries.ts b/src/GraphQl/Queries/ActionItemQueries.ts index ecca80ed22..3704ccdd27 100644 --- a/src/GraphQl/Queries/ActionItemQueries.ts +++ b/src/GraphQl/Queries/ActionItemQueries.ts @@ -38,6 +38,12 @@ export const ACTION_ITEM_LIST = gql` _id name } + assigneeUser { + _id + firstName + lastName + image + } assigneeType assigner { _id diff --git a/src/GraphQl/Queries/EventVolunteerQueries.ts b/src/GraphQl/Queries/EventVolunteerQueries.ts index 03e5554069..4fff73669d 100644 --- a/src/GraphQl/Queries/EventVolunteerQueries.ts +++ b/src/GraphQl/Queries/EventVolunteerQueries.ts @@ -79,6 +79,9 @@ export const EVENT_VOLUNTEER_GROUP_LIST = gql` allotedHours isCompleted } + event { + _id + } } } `; @@ -113,3 +116,19 @@ export const USER_VOLUNTEER_MEMBERSHIP = gql` } } `; + +export const VOLUNTEER_RANKING = gql` + query GetVolunteerRanks($orgId: ID!, $where: VolunteerRankWhereInput!) { + getVolunteerRanks(orgId: $orgId, where: $where) { + rank + hoursVolunteered + user { + _id + lastName + firstName + image + email + } + } + } +`; diff --git a/src/assets/images/bronze.png b/src/assets/images/bronze.png new file mode 100644 index 0000000000000000000000000000000000000000..e5b748a5722cdeee1184a1d54924060fac450856 GIT binary patch literal 169265 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 literal 0 HcmV?d00001 diff --git a/src/assets/images/gold.png b/src/assets/images/gold.png new file mode 100644 index 0000000000000000000000000000000000000000..cdbb0efdc443f8b76df5547b366c76c1b88c8277 GIT binary patch literal 157071 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

w>?%wYn z7#+Rt^6PKv?Y(Xfs5;Ml`p=Qr5@ZRD`KFY*das{fFn@mhp!RO=&&Y%1#tx&acKv?*AefQPN8`TF!N1@@{Z;*S(@T~5fu~xMUo^0VMJwg3%zUB z(~g%oHGZ6(J^fHz3o6Ll}!Rb*oHQQCv8LsSL7Y+E@e1dyF(F zl4AS>L35dEus~59?WHl(+l|{iq+L+RsI{hVw=Vvk!L@yF=&kgOlq)^FtNNF`?K_69y!pnLZQecfOGE3! z1O21?eXYgYCnn==ym14SUh(xML*uj>snqFm^K`i-s(y*0Z=kR^BI>4>rtZab%33_u43cOFNH!cs3Oa?7I7TY)i(%*A|8u29=xT#v`iX< z&pe_dh{_IiL0_N$>?8LEJg+KLIRIvbSdTJ@GUyJ;ennYE5#&{)(YcMuiX@xS&vB~H zZ#8P=KBF?nWvMomZ-{&Vt_)Nez4AJBx>jeVF(Z3!zareer)r1R@b>%ffBbEi?Yh># z_kX@8D5?|__ERcugjOFW?V2S{DD@ZdCZ<%Ot5l&Ml_JV2r#+d0*aW1ygeRcr8}zy< zs;$GU562lUjiR3q?XP>2y8M-I*6mhAs|NE6-ptHFoJb$4M62PIcZC;FrMWQU zf=+}AFyguG)|;gel~`J4N3-3g-AY5-aw=&iI*Xldw;DmaJ!>BO>_=2G@vPr)!xe7B z?#t}Rj=jacZJS@yx3%8Ns@)%N^8?wdcxH8mPI69GzAAmn^E$Mlw_8&uMtX& zSCDCqHWra4k+$@fLltUAp#4a>T7p3PMw}_H3lR0rrK(Iuk>373B&)My^9X&tCAxam zZx3(m>D{n>BrB~SG2=6BG1UQvH(jZEuDk<+UMO_oGE1Y;Ahj8#t}289%63o{X^LH5 z!nGl@2A@}<4$&9GEc;s<=aZ_=cSizH9#4jlfyon(XoW-0Q^Af)Xx7TYb5 z03((HH3}?IHlCN?eyh4{%UW~#$Vnfmre9tje`S))KQuTR{b~Pb*R|#T5x?c~%kA}V z`%b^{wXZacbnE3)&(byA#}zl-poX?@g;GUj)AKCMWol^&+HJ5F;>5I}K-{KN4_+K` zLAORVurRj7VOL}7OcUi*%h@uLHANLIUEKxMCdo^pR$CQuvhSgfsJ+*{LiOGFI@Q-s zC2k#c>Y0aBI(B@0`^@Z5w5H;JDX#S2PmkAs{d?c>lS?}eb@R;O*+xoJ43$$f})>Q6LVb zJG2I+J2GkplT#-Rl5T8Kk!Hm*XSwq!4$?1c~ z*|ld9szacQ;32I$de&UdrtQbnr$2K4258SLslKSnY~Kh@_3*mayc$U+=+-CcE(Xj` zX;bM6-B4HLY7@t=N*B)j{H8(m28k>_D%tgWU#3Q{yh$@K9MC!~N&P8AD^(aO6Y2_S zyG`T)-Q?`}7?YDNl14Z-MA=6kJ-~9i%{`y_Jk>6kZ*<hq&a~JELLJ9Xj1JKK^laS^qMdPr7%helyT@{U8^GfecgQi(;ri}-EzJC=->U# zV4>=M>#FN_Q61`4%agNee6mje=pMCh?`@D3L3M*Fc21UMVRjB^1P^j;J`aolGaS`vm*h>|{Hy6*Z27w^Zc~$5wkdku)1?gy3iSCFN zh{orlwCA-*4PNEd;i_S;I+x_si!3H9eu%jtv?q?^Tyqq#*5R$iTZ?m-&i7Y~TzmH` z4)Nka%ow`bs8)xRYsFH;(HcJuHYU^oSPcRjH}0mdYlui-?C3!t2G>M|LgEz!Wv;mX zrC4Kl>Zw!m^ns^?m%a98w`mLC^MSv5?{~cEO|SRwfB%P#^*M*xLYxDhymBt3r#GUY zDQO>5P#MNplmTtPEzB}x0;;7h;&u`Y5B0h3O3-!W*+>89z+mNx(M{XlP#9S6*X_C1 zUH_^#nbA96ZWtJ0dHN7%=g%k~wv~=jg0kR)4ACBf0<;~^Jaw2jfmR&SZWnYb4r#{z zjOY*(lw|eVK3{nI0u|uCpesTT5cV-XdsbC@hsaVlKQS>&PgN*&MY3+kHA-D}2Ys0! ztyye3!_?GKYK=P6XYc3qhaXl~U3(KF+pZzp@ttaLa60VSw9k*sAN3O_4y+w*@;jx9 z`jLGH-utuHUwhq0bg+@94t-JYy!u9OO@S;5iL}9cAt*HI9RMVu5EaUWLIGTYm;|LW zj}OyG4E5QQyy;CZQJFs}Yq#;98}HgVQY!0g?3uA}dcG#%z^K}D=PSULA?VJLh++Yc z5r|tYMhE*ag%UK{w5Dcw=HVxqJ337iXjI^3xxLJ_o3?@v&g|H=I}uaVaUA<7iY{@? z{)r=sqRx!aLYjbz^0uZ{XbI6u@JjMZQE3E&U{PXn?NRmIA#Pq3{^RGzdq`|u=9FP+;%c^hcS>FCHU&UYi>HY8d z&ENQ=&;R&;e8a-&6K4Xg`!QZ?LyT4pl2lkX)Wg{`vr43aidyI>MjN5zJe#A4C`mYY z)&?6k4%=P3%exMJ=6!#A?Nw%Pp}Lc{*=zgOUuM*XK8;DmP92g{HeB&?F1zcE+2lqY31E2i3T0Z%#qOVWF-FsB;OKuAG-uCUjZ_{Rb<6S%VZr@Y>+x-W={98u1 z*|B-pAKG`nsf10GohQ&LuLe|1wOfP4M1??^K!JBF00#xeL>7+jds_Q=*?;mApLoM{ zH*EYKuiEaZ{riLQv$Im{TEpIJUjdc%5arGl=%BNzS&VohQ=+Tf3u3S{v+RHD3C2&H zrM~27)IBIeD~_daWG!Hhq^TteBULQs9LP&a@Sirc<~-46`y59=ujo*Y;khcv*W&^?RP1@u22x9nC_FM?zOa1C)z;Tnud5D z+I6h&cumHhku6uy)jLXaF=O)B2?#V~30b>Ap}PuEfla&j(h^h_A@@H%W@4#j*WR#k z!viBT$*%tB9Zl~PC=A`pT^DcX1ft=N6njq0a<;)m7fKxD7F zb^B`%-v1|$ZQ7FVEe}ar+Ok&qZ@WEEn|DAxkyHEksk5`=YTND&^bM40HJ2gws00Em znv?*6W}E$w9V2Z)97CLDK2991G&|l%>|~+RMc>e{lqy{`S{X~V^OE2NddXeTiBN#a zB|&#>l%|CwAAw{Mi1S&S8-nOEklm>68`*yC>$&yTJFu;j?0@2q zn0Vq(m7hKe(RN|<+th{|eju>rA$R4CSGXOQkNm{GXTEgLv17;jc5U0~=B7^vh8B&+ zJYF)aOE7_evV@UOJFEq|x`v5VHDGC>Qt*~*cU@0~3Y#}ZKR&v16Jux2%5qJVDOcIN z`x;eTdktiL;7x8py@DpR35~f~l4e3uPdR$;7r6H$A7}dHSqc&nVW^hM#F9V0z`5F$@lDiMYiD0D$-n6+E3B(*Sc`ZOdd6vDj1YBiv>%;?sQ^o|U$)P$J@ zr}f?#bN*{&43ccYJk^@ByIBxzxLns zWA}ere&rATlU#pS;ol#;_rH9+(toO2TIX%FacjiJJ;1cI9{Ef4@JD`46&lCbv~3H7 zJt(PAj`|=dL0BXbLy$OVJLZp^<&pcJVQwy;ytFeU^_oo7GwZf&&gL5pEz00TG-=Di{)a%tIixu&f>eNRkY11~(clK| zc=f9o>NiZE-N$1Oe@>myPaE z^?f>uQi9MC$0=!Q6&jTCbx1*HM1??1AkdockEFqwWBcr1{pJ7KJ38EdJGB~fQ?W@b zvT?_Cs%yvfoxiKxA?IY|D$RLynbd29DqwbEn%UFiM41p+gNrRLbrgb-q%D#;qo52b zIHtn@Yc1aUjwWXQ|NQt?pTUbII+O{c!OJQ_bk&paE2=?O|F1A;9jqcjp@SOL=hG+7 z4PI7g6beHaM2J^7n>$ZXDoeZ3&MQJMmny<#otk0dkw;*00qS)~8&DAFE-<`i2vMm1Za98$Nrz!7TQ+g? zU;V}3U3cX00oz>>oLd~BTx5B%CMdM`j`}<`pHykJv@{dT&;Q16sdxRSf9J1%&Glx} zX8!E>m;dNj(#B)b*B86g*Mdf~E=-)_%qQNjjy>~vy254F427MpMF42%(0fQMsE9yU zm^n7dN8b0hOq}&(8PZB2wvc*{)8+~51rI8AzT-Y|-t~Ne0%e}}DlWVbV5#X@yJ@$? ziQ~o__e{i1cT)QZB#@-ltL~y)?84TkaJ7R> z9C*KC;bDbBN~3F4VN{3Jb#Yc2t#65gvk%#z@m;gENk3mZt-Zu(Rb*zWk;{GPbP<(; ziYZky9~9~|>*K?rS|T#j4EFIITeoZqC&p)Ovw`aG-@uw3w?KIV_z=W_jzOhZarpx4 z66y;Jh=o=?p}m-*V~dInN!=k9db+AouUXcv-DyC#>+$kf7=(E5#W~j@eXo$eFX&VM z&n8wJ=uOZWw|5ei(Hhk`v^HpMFh;K?x4aTmoy2zj{hi0Gd{4hnRjANftv+v>rg_D$ zFP+n`KRTO~PJ8>jEla+fdw<+?4^rtGHCY-^4gxuO@EH~-kE2bBRwhp@g&u-6o7lW( zFH1}C__zNFB_T)#tzrA?CUcP-q7N%#- z$!Cwr*&~N|_Tew8>C?wa+I1*;tWUsul+V`zQ5miJ0u;-zl=0X{KhHF7^3qwjJNP&hhoSab5}_|IDwPA*G~K zv3(76%@>#fu2g(l>*rL3=YRbiVQ3Oh%drg-P`&cUVlIzr==W`z!?#iPZd#e(wQ zDFSajm7o z5WLaN*%pg6GfcGhO1bkjZ!wW-@(cgUX!KWFZ%)g#Xf+c#a`-s)1|L~mYSXI4CT)627DY}R zdWPo26Hr_PlVWv%*G14pbX3Sik$pFe>||uaR%RAwIDPaf2x1E5gmOf{nBQxi-7`&(?cA_!3<;isgwa8oF z!R@_UE0-@VO?xq-b)Xp-Sp&+@mW(vWRU&uTz`cy0c#7@<1P;;~EKNHWCo+ydah6Yi=<_`G$%im$fYFdzSgxVQ z5A1WVc-7Tgueq9+qw1t_V+3o6TN%ScMWViP_+<*A5@BEIX zXFmKNTztfD+&Uc0KYLm|b97M_(z3eo<*!rQw(cU06Bb)_X4(x}_#Ajw)F278g@psB zIQ-x~{_cGr<=~?yS)9!G;8{CA(iX}(B=L|6f0tNG=Dcw}m-Z76%|?1bC%~1spc7%o z(GAIGG9C%|?B{uScCNm!-Ezt$_)=ITRGKFqyN7i45D>3Q0_D~f2bi zeme^b3rru~2W6o+)W`b0*Q?8~xs!To#CmPEZ`)w!Cl2Gr_I+^M4c87$Jw9P?dHFlE zRedC}%(ded;B{~BAU<;xO}e&V8jNn}d3*O@nd#}XK25C(iUn1ylz<#?VYSbF={z0U zM2-5{XL;<=`w^dm64MNjl8!uCohS8P54|f$Sh}G(x!U^Z* zN6(>ATuO-FXyi#uIvs{i$nz86*A7TpNpxmKH2WW^@-%rebe;JxoKs5iURI5JFU3C| zD>x@D&{%GeSwRO85UA7{km_GEx(5m)s+|dyl9F^G;q0>qAZvoFbN0wS&OE!1_M#_i z0}iwbaS6Bte5|1zFf}$$tDd5@#ze4o1I#T=O3&JeZ+{K1Tm0-Ny1OdXLFyT4Bcm7w zn4(_(!@v98c*D2fX&ycKY<9ydZ`;*6eD9yN<{qUK)p_>lA@$^;F&WuPHHV1*hg(bCR&$X%^BlV@_ptsv* z6XW-+r+w`GwR)NFdh36+%C4tb*K_T5Gef5;8t7GF!I0QS|GWOnhfC|%kG>q`X|?KF z8Kh7uQtaslmtw@DeTwmM{^@aT+`Q0?gEJ0aMqCMTg>!>);1Z(nn-9|=)UW0%9pLhIm7kp*C(F#uPIp*)qdx%0dNzU$@kvZy0el@QqS;Vg z19jo#C%?>RKKuzDyyr0*b1fnl;@gV2odaDHYe+IBX@<%iK68*b9*rH(SPz-=-gS`4 z7gJpDiO>__R1v2lyp*JsD3+V{V{`LOqGGpcG#%}RMJI4_|1-FmQ{WdnV3{mp= zQiQ}n&o=tk?7|c(j2%4+X$#UOnRlq3wQRrgT9%r1nV&ly7W8=L7oWI$=gY47)%X0) zABgwsh?@g*N$e6-3R$X@(xBpj@BP7zTf4do8JFx#t@y$gLbS8!>7e3EJliNmjTnOa(h|zzVk6muWtInJCI=u7e zp@J{2#p<6na$t-RPv~<=Iz&@0byJK=*f?QfVp49q{WkOQkKMC?Er0s5mwY?(ZSQ*q zN9gYkm_E74Q}^G;;isNp;mka74O+_(x4>pXl39kU=obJ0fB;EEK~&O2$P&mh!DWzT zpj3#pP^&>$ge$Jzt{Tk+y1JuHO37u)ThO7{1S+Khjpou!7B)y2hvt2M5M=wW3Yg6T zlLnddGQ4gFm*4$b2>U=Ha1lOnWGx^A9fwRGo8g}KeuxJ?{Rj)E=g}!N7ah&zj5O9H zDYOzrD;3(QB6EoKTC5Imrtp_mMK~20>p?_eFEZ7l3px>cG+r0*s)VNtPnRbs(cL%l zXkx=hT8UED<8AB}jX+p--1qVK!NTDjm1*0onyHEgB9JOb7egDbX7}Z{(5l7EpE?Fv z9jzR$(Soo`?Y{gfmYehR^fZH|h5J3VPyO`fJJ-G4$`;0_Mq14lHR2Yi0IxmDw0jFB zciq5fuQ3Y0d)H2~Bvw%r<&s8#_8Eaz;A1EXCqMfslIdw=ImTomWFc7+VY3i#JwC3} z-vuKBA(OLnTyxV)HE{^^{7qbMf{kglrtrFs(ivVH$_vV0axwp>ia-lWvb;Si9x!M^ zM1|zZFv_*Cv_W)`^9VZ*6k2PvTB*=A=ZkcIMaT=>FFE}}e)eOPb09I0+lv&&Xpef5=64dL*UhdBE55nRI) zFIx(#fR+N*3f_UU;Dr4DovJf#dz@7ii;yI3#Yn#@6b+*zgFVGa-?tX=B-1q&{6QA_UOQ(WUXQrip?G7%x_I8Et0#gObpo@q%*d$-#S~btJ zPadT)-A1>8w!tNN3p9>%tU)_fv@%6AQPN5jZEJkn2SFmyu}l^JG*b~?6`a=wK_gz_ zFCwtr1)T^XS9Wj|ang;WO0Cf{UK{3@(%)QIjOpxP#H1m*t&m!aLtpwdES-T;XYmrq z)#f^=O;v=_T81}XOAu8#duj}t%S46TQWagKG%%`$)^C)0Z9z#kCGEK{gF5jmUAMlZ z_{SgES6{3xFA!;{R3uK@s38hiH zMVzlAB+s2?U5alyv;n{JzKQ_3erPVR{k$Y6&rNuubO(N}SDh!IGyDEW)|eGt(#~Ii ztf<+nZg5nmEq7_7^N+>K`)swxc7}w-NYLpbt?9!=t+PCM?}uHM%yR71$lQ+KX z&E|pq$KA}*v>F;gR0<~6=rlk(gII7jug0zS`FWBK#e!hA_wA+o! z$Vl(q)k?t9@)V^4vM{?qt0q$;Jr2@?KkJf11bW8T+AYEx##f2q9SNG5dTd{dOi8G@FuQQZxBS8XZ4vlmA zk$a(b8nEXsQl-J9xt)&mLvbTpwqMC|qt4{mQJ{@dE{98Z4>GiVhpN?;xYV1)$^9Aj z*^N|A{^%zk`>)c@<`$?gLKu+PgxEH^O~Jhk*TRGbf`BaZd3Dfn8Zau?6^&0E;?Taw zNoz~!R)A?2ajlRnHFzgDmk}p1fd*sCJp84TYWJQyUEd9NL+0K;HGeX><@HyYG&?}1 zj-#S!5;uvLI$qi5ETZSvAQ$|_@GXd_pwZf~I%h^bx3Uw>3IbH0hYnTBbUX{s&Hi%G zmY}q(f^b&+3#G#?M4$ijE1rZNy&`~oDZZvynT}h%a(E>4h+8IdbF3-W=wVDRp1NP( zeBJus=<$7Rbot#IUh*ogx$V`|iA6&2ZG=_{NfbV_c$?r|mbax9APSGhNvD!hE4EyD z5}7y))Dji9t<)RKg{PmM-=?EfTIm#NhSI7+R_EBdtJmDb;^TMBoZj#I2K!A*m*ncZ zUZ?2Z0(65935ykUR05YLHmjiFpq1rElAb%78MG|4Q)p+Jb_VTCr0s;3^^$lMq+TC) zMDG=ztu;K>ML1C+&e2?iWEq}$ z1v@vNeh-8VzT2-$*94fCQqz$eK^OGEY z>T#NLvxE*L^SC&76Hs2rd`6PS6ap9+LfR6m+h293yZifoI3yZ9x_D;(SD0Vq*?ay< z6__+Lr}t^28dw+Olsk_@`BhqRm*T622DI@g?a+9^pN}Kg&sF7LeZ*Hh1Lw}gd7=Ds zsziAH0@PVhpEnC!K?Qrcgc|*-p&)f0t2+z4Ptl<;w0D#GkN@dkE132>*Jpm>;3w@h z+oIs&JG>v4bsHEv-WEi1RP_4yTN(J=9#4P7O(FXr~a{fF#M)W8xIrDJr)3%xf&> zH?5~_J;sT`i^{89=W%jz&7d!6_X+UKPETOGXWm;1(xT)o6(6~=`dNx$@S(+d|L+C| zdR|gX&$zAt69z~aph6FifA%xnRIO0mel;%XLIqvuas{$QP&G*Az%?kAD@4U^9{AD& zTy}XvZ~p+n=rD+4&DK2}Is7==ckI#6?t8>u-n(a%!p47Pm;6b51i`SFU{Y24M0$D) z#OabM3~m<2Yorzxmdg1|&@Vz%;@IcD#QgCSkYu>b;v6I%oXhZlHk#B!UoWzA&oCof z2gIz~pxChuTK=cxM6LPCSAD1E*zekGc!(trt(h7_Yxb%mV@pD7f#z`eQ-%a(W<%ZDU~C%cPMh7N#_;TgOZLj zh~qi)`Khz8|H(7-4qDnVjE+@3{TjIP}P?7UoaVZ3cDsn%xri z-JoDN?=1K>gaRdD{-MwCEWjsJNzu^QWJ@VG=sM5X#H8pEHvsKn?X-61Vz+*mO08*4ekRA zM<4rpW5@U}uf9s{f9$^3Jb3??f40knKcrfgQzwth&W)Q?U~+Q3xD^rZOBLZa6UG2K zm(+f4MYt0BEC2sI;EPu)4)!Zwcetc45+0qq9*9OnaE`Cw5ncjAeQhD)@o9rFon_C? zVRiDzqq1$+`rh8bt`D`ArtaOeZS?-Z0rkwxp?iL4P){-S*nNi?82p7z+pc1{Y29Tn zyH;)6331}3ucwM~1|&jIhzHvl{ac@_IXQ2!)?%GQe0~+wmaHliDii`#yU|u8j;xi^ zQ_+ODP?o2^FKf@Mfxcep8QiME?yWgORE0TLqhP?+SbFS>Jo&(bOdhY1#o$vQR!D5H zIW2-XGo-1(riL_ABx(M)Cti_>lGNvIT)F}q`v-@*ZVi;TI@E!LRy-D^EG9O5_QN0G_E+3NG|)wBVS!dX zVPRs9#zLJ|eUWmpK+$TFB>#=Iv$GtUS)%LY8TMX(HCs1sRAUDpl#Q2d(MzX~2=iuV zPhVkRd3MV8Y!qX(mLM#sQdnlGQ3Gq$@^T%m!6tQREyCgw2lqWqvsTYVeA57D1KQ4$ zc#C&}NWS^&ijb|FDypZa#~+<72g4h0Tf(US&~S&?cvZUh-~IZl{%EiY<-!5frvXbhq) zh{-`NohlHe@_C@>yejNeg86+uM}~T}YTWCD{Cj}+tRf#*sT>#28uh;~R9?ZEY?%Qw z&HI1jm(^Xbx?2{<#{RhK+TT&W?7FOc*`^?S;FD{6T>XzIEWdK}^3iurKK+GXUbFY6 zxB2CntLtZu*xT>EDxh^lCQr3QNkIvkOoccs&V!HxsWR)aE>~|^IXyuDv$JikDi70Y z&#|!Rp=oI~ts3s>673gDt;NMsp&Ci0I;>1(yAZ5XC?T~qB5k4BWZ~Jz`10pI%iQTj zd@EOyBmlNhTzj!zo3aI@)PQJ5v%{A+@4Xt1?dzqRo3n%wKx6_A0LiSK9LV zt-k2ygcn6AunK=Bz!70pM5>FVI?`dam!*34FBg|-wBmA*xPnh?pi&o#%>ryoXiU|( z|5Kmf@O_`<;DcY{-~(S~;>byor6%pg7PXmW;-xmB3(%>;HZ84%7SkukdE(3Wlg=*@ zBu3fkIa$AXNG0_N89Q@kU}claNkIs1vn zr(^ek z;oGOqJo+6o3nwj67*JfthF!P1x=U=jeC#`!dHA6&;BeCP7kbxtnjk zLiP6t1f+r&ywjvsV>?xpvo24HD}Bb!`O!da8A`=6VN{@9hb%V4ZKPT*s{Y zN=1b(3&AkxF2rS!)j_qHeBu$l@Tt!+esY1Vt?;SFrjS{Mb(+`;?M!H;8LiaOOdYM% zk))nD^&}pZdTle&VJ7N;Q~F1}F*&(J<=4_GlKCrU+286j_)ilTd?Gx5EaK_(zjZ{M zCqh3lGZ}2yy5;a6fXOr_)r8id6GgVz;-P!L#KM^+#*aJMg5KUUnbX_Fni=2Zr&Avz5fX7_XCiNF8J{`IBHc5dF_ zHf`Cf+i4rO>Q{FuzLCgTgL$?yt68t(LAZ(rHh=*gAle`uPT@H}Lc>?;lfF=#qg*`y zes6O{nbqjDRYje9+@*No2n{$>;l!kJg)KMf_R&XwvE4XAT}~>fE3y&Px?9ZP^*5Su zK&4a9e0+EI%so$n9A#+t>vvuAo!s}O6Q&U__-#A7)zCnRVvt*F1-gj#y3WHl(wnAcs*b1>lQjf~K_7)RlDo8x~yFEIwN*iwi5d!=QwQSWZ z^V|Vk6v^;{{)A|t-DuHlwrI3s8m*XGD`mNDsl|@v6siNGc7Ca8)^ED<1B*-i_HsjX zGsdQ=QArAE>PcdUYbtCVY#n@4$YMvDTCz;?BlTn{*i2zQ?pNh%fpRqvBqa(`oRDd z15IJ>8Qs^@v}H9OG4}Mkn@cS|`SDMpmBIv^vu3&!UstTGYf1$mV7@A${dra4i+z9f zXI}iHxw=d5K=D^8sF&jF3N28e&CboE#zbX+SIy0zzIN-zii_J5I-Y!1s81`FX9SZW z6(5bR53|YfM|QTK`t$+B-NVKke&FS=`PY2;{$p&}w9~H}>Q?<_B_>U%%{6jL6srs= zfOAQ)Lt{>2Na75o426hX9Y#=Lv49n)rfM}6boC+LD748DqFIaS#~4@}o}c{Z8pX&@M-b=Dg)3b7ZN* zW*J$QVLQjg5*Pf8u-$I054m!1Ydj*PC1xX4% zA&dfLmr~FL;&x19wndtNcCa)PgFxCON3L~1F8; zdr3I_njbtyeevd^Iq@T{+2j9x`s}kZFgi%4wK3VE*ztP^diqqmxnHW)IkP;u%+l2G zYX+`)?dI!EbZTJ38g=r_gq)ivT}p;uYpiS?1fHwt@?zWm7eLo36?9ssS!YhDb5y80 z4>j6ZJ@fm{xm9S@LF{$D_8z=-AO&>^u=`?GH z5ROl&+KES`E{BoOD$27WYFP$*3gOTil{Lrj+a9)BPk#K1vwPq4BR@U#+SitU?c;y; z+wS&jcSy3hpu7(Sm#O4=pR4CzA_{1?pxthx11OiHJP`s>xr@d29LpJ0rGzyF!gLOT z9^z-7<^I3Fho$jF0tJ^Y*B9G_4cC(9T4~R*A)1r%WiK z{zRF=dj+kPDOfLHz2v&JC~Rk^<(0lDTkjWiMF`MrwP-b4v^o`GqZLzcr_|b(j zpnGtgoH{$Nzw<5MF104#Jw4TGE;m#d$6=Nvfl3odQzXqGOFQ!xZ#u=2MOGIV(@})T z+XUiOt|XDtx!+(LFnMGN+Bqp2@eqbNd7c7`vu)-kb5r1IrJU;!CJGw^Ho#{&+RHmY zVErg^+uc{g#*OOBANqV|3R}XpZ~BoL!r!7zOKkA^7*0k%8vhQSs7mB zR&D8?#!{C21|4RFh}E z%+l-uTFsWK^sYg|J_$?JFs{$0XOBL)=S^>V%?CgD>%aT!T=A-3d+BR`)I9w73BSCQ z_{eG17Z#=9yae8_x?4cLBy=VvxtmNIY)ddMq7YSB5d<$pUCcKfD(azLvxGqeQHVWx zkdJ@p!_=pj&_1NOEY#}>rLY7p*ELO(j!R9dI_OYED-mfXP*1#Sr}&PZXy`=$nKI!I zc{J#PIHhr-aiXx|No+!9Es3?HHb=c?o#SGO3%(+3G#Usw{9F_$@n|er2$@lwnwh6J zDv~8FfB58aV^nye5vQ*;%l2d5sjhAbG6@Ky$Y3<05GBr|okC>}32gqnD7+6bta!xb za%)a<*NAD`STcvWT;{h^scSOl&|YI*K+&YsCR^yfh=Kkgn(a2B*5HfGE~Kau^pz}B zyWrqc-21W5GjnDUWfeLzIAidVQcqgo^6^cU7_5z0SZJf8GVL^zg_=h~qcUZj)q#;v zfs=QG{&^$-6)2~)cmf2A_nypoGACG@w?X}Rn>FB~K__3(tDFZKt=4K)*lf0Fweopk zEp{v?FxN<#X*AG*CXBo*6hmV(zA&>GUq7>$9j-Sdj9WTuwY9Y4P^DQYl0}dhT&{Krr%9W&YuD=DYVTLo zw!9S2jq@u)y*dN>%8!yf2Q~WjeALd#aJ}eHbSlCXwCZy?gZ@&L|Fwh!EY7#3yL$+t z>`e=E#~B{&A+?E8QBe)A*+>wCfX==AS`jdyii0~C-Mm|QgFf=~{T%JK3px=( zJ|k?mTeMbgTP>RHn0n%=XF_ZuGOaz6?C*<#U_QLT_97BVL^<3xrB%d%(fb~Sr+N$&mBn7jO@H-vZo#BV>!uA8o% z{o==;ETzZaUoOw>J~4eNyY}YYK_j&?H8)G4T2bY$5+*3o+p`TAL`eY3tKF{_6uYWruTVF!&z*?5-wR{249s&i`lIq^NRYo>$)M=Wzi6c*N z;xB*w{X5pM?(g3Bhwm}3dd(|d{v$s*clm912NHytODxKX%GyYlI9c_HR31-4n!(Zi zGc3$G2G?)m%*-VH{ff9g#c+R>X06WHiAlcrxraIaY#keePl}{%MVvWo=5UG59VHq$ zt0G;7_OeJ|Jl19^%QCNX7o`xbW<_y_X!Sl%V8j%}X)RuN^lv+SR_6t0J=S`%EI+KZ zq-jc;rX)%79Pi8vIWB@k7}IXGX}8uB&fzrPX_A&DOJJZE z&Yo;DJ9ZWlN4eNf5O$*lLT@nwMg*4%S=-@VTacDS1))@_sG0fL9yqeh+ur$Kg1vA2 zvA?8$-R=86{dZ$3Ir|e`X8yZQo;_kmHy4Abrz!`IoTPtro7%SP8VZ#@vP{4iA;}wY zXq1%mR;x~uB%JPc4cPpb6S(e!}^%@A2R$umTqlfzi9XO?(QySM%H}Wc1Epi?gj~w&l5> zTd4-W;(hC^1x}^GiM5$Jwj6BDg zLVx{v@&7J25~XkkgzF;OkTv}5#0*0Nn<)10fUFDAT?heZPM?CfmJf$r0#Tr%;eH0U zjY#(hL49G;cct~WHlKO$Wj$GgkG}tJ$5?m8t?Rz?M}PCmH@`zhFTX129qw|s-LTf} z*pN$ujtnBNxVuYkzGak}g|$1^KsjJ>Zjt%v7L`ITvtwuRi6fF6VC-6uH8V&vs$ov| zit9O}qEtlgdTCMK^yX{TbuW1dCr_NQ%~qzA(m|mRj0Iu%4z2a=TB(z0V?-P4l*Z}+ zr&bRA9NypxmB*v-t6bSt{?51h1pbr71rL^4`LO!VW>~LK8o>0Z&56@zKhdf;eqm&w`j$8mPM(^y*NhD4>#y(E)f;XT%u}eTut@;dP_08D&wnCw>UsiRw zF2&aqE6GrZSY0$$L!YDFtg3P3pcnNuZJhPj4?$ zpSu6A*R^iC^_@Sa-~ZkZW=D@b@^63cm;U|xD&^|0KJi(3d80YQ+D+TNE>8Pzzx#Hr z{EXcH;A0eeF&lR55|-+?CaNY7w-nDFKSFITPj(2Di%?$z+ZovmcOxT%71nK9qxuH= z$(+a&PaJmpp01hMMS^xlT}B%;l93D z(z~!L!Iik+6QO_J|5m=v#fTko9OFdcRFI3Xc_9=_!COksa^)qq8-r24L#$S4 z4Av$z8xFd9sm)qAGX*<0P%O<$(ncMgnw1^yQ9s%3>n-1KqLw$$xhk76^4nYFFk^ z@HHha`A3r6YBE3nJ-R58q1(1+n}!qDoIZ7wq!FvGLRIy4t%0BdVFZ0cRC{`vSzMsL zv_My}fDbjX(v&M*46oa!9)9wu^p2Fw?Bs;)BD(Q`4}AEC+UaF~JUg9*Klh*hKmTk0 z`M*9v+PeFvfA#&}^VDDd;m7m{Y%w}d+(L34rzd# z9$Tbdv&tsO%1(cB0yb`d;ZdY33|Tmyv14dGE-ARDA2`ABvvX!<8C`1`iaos_@^SNL zmz%AlnTAStuUSgcya}WXqM%T&VtmdI6mN1NZ!|04PttbYZMewef=`4m7S82^-DW!> z^ctt~mug4}y`$(e67OhIM07~+=oYvC=rKLmU1DHh&1bR6XJ@7-eyA%6ezw_aZaQ`5 zD1$?=XLn#Pzif|QyZuTvw(kT7_m4}XW>vkOiq@!}Qi)_4iXLel9#`oC(w=Eix@uHO zVM=Yee5XA0i6d&Hftj70VPP@h%v_V+T{qOP|F$=MbmZo{-~H#m^ZO@4qj<-UeV;k? z&_~nI%#!r^U+nEOtiODVOBNP``=1_{Ywx;SRr+^=Ekanv&QD+>Lx@5Zf*i74$|C-}B>6(_+Va&4WDjIO3{YA_ zCM7a&Og=R3bSC5*oBOT)2IX^##MkiCxpsHHl?j3ntqonJ@~SBJSAT-%OT2xxBzI9X z5fsV_ksqL0+uW|r)6>ogNh&m6@V$z*T0U1nI#%ia};~}Fkw!3w*ok3Oh>^tFudFTMM(uKwCThYk=G%Lb!;GqKL< zkW6VZt+8mzrBW{XPL6X>!~-t_k5X>eOS$eXmw>?3r0}#Y+Owl?_xjHPpH* z=9FM?Un?v&pHy=9S-miy6EBL+;bR_+8xf@>{w0 zOCSBN-CMiwR9(2HPtBM19g}s}U9bADy%SV_XYus}AuKK|(bF5|yIGY%5Q4MJ&MvdD zZ&)-<-CCZaO1iNzKSyux27e*Wf>xR}Pe1t-a6Z2&H?-BECQup^L7%+(s;mWt5lqS$~OByuefLvq4#-3*lxEwMCEfI;#54T zq$m+$T_#hW(5Dn6z?2lDJ1WivaP;6IGd#MbRt)4%yv+T{(&F;9GdB3{rMcugXC}^W z+_=4mJMO-cuorH6*&Tl7#A%6_G8)r0>~bQ7!a%Th&nAv8)jdSI*wZII?d9@2?<|)` zUi$9uTYKw)gU3!13~u3X-uJis*+)LEKmNH-^2y)(FK$gT%kI&Fd(VISVDYw>1wXIC zl&+zE=36Zl_IAnIomYby1YgL3F`Nf`5uNusT}S`T`JA?)6fSFbjDXYr$unbIb^Tr9 zF0h5{E1H;{_McxBrS_}$8=hage5FCI#-l``@f}zIc@pY;-FaqQV)5RhRDkG^MhsDL z2sUid*~1?$s>tMMhR${NjaE&%lQ`Y#^E^M!Elk>Y!Vs)&gU@s+DqwYixRuaV>822b zl#0=Le~(9tpym0`eD3enK7ViYdEqq3!zF8A_=&qzc@ZrDsi(h`@n{Quw z;0vEnTkm+4y!Q|PhZAjh=^Ngl|Lwp2apiuu6_>g-W~lfU%7&v~d_vV~4X3O!XQ!7x z^NM%>!eRD5`fon0r8 z_8dGhW-x)Q-?7URbzzHLEI9?`J`x>Z5u6APN1;@~TTAYk!D>Y)BH(>TO#a2L!;2>_ z+C;cABXsVC)rePSVws9?fYTAyhbV23#1JdRn(bG(sRIwIa!;hIm9j4vichqg^2FTI z(!0lJ(>u=0&EJ0D#OH6=ySwM|Et~p>d#gn@?pVhOH_oBi1zz)pw@tEs)9*d}`@i+W zXOHh+zwRY_C0U4F&p=l|Tzi}9sT}BCI~+cCw0i!1}#FF|ROm{u*-yoKEGia&*?W&}od4rSnCq)AG|gch%NtlnU`E0v&ej zlXSiwYL6j1Z}E3%aTxD&l@<|9r+Q1XCY3@Dqiffz#!O2QRcLY;-^$3SkM_*)q6xPzV$RMNA>WU=Zgzi8V!$SIZ)v0E3qtROZi1 z_#zz#4bdPTtvZgCE1L~v&%ODg&zqrMpg$5G{!|x8AO*u78fR2 zID4G_%Pt2M5-0<{%%+W3@E{MVsp)yS?XJ!0^Y@-|#R4OvBfPR$3O=N;x~em`WLub_ zb^Ouae9*u5lmAQq$$$SD-ujL=>}*Xwdp&{W$iahJymHnWp18mMw|oEe6Tg4MzxjXu zV05YXr4KyvfPLnX2kXm=N#n>Vj-P38=-uynyWM}^7bu$oM^8OR3m}w<+R0-jge5i3X?84vf+m)avK%0z123b6m8E z@Tg`+8C=?2xh|`%*Tz1(e ze)(6P9=dAR^4<+=*i`MJV4-_>?ZySJyY27dFMN7oc7E!nGbazPUw7SFU+SqSvVe4Q z?%RC1`mUK~BkNzcmJfX316b$jqDA0idi#fExtU;vw}^3Eb=?jqhmx5Ro36YC=q8OJ zC>VqkL(b*Nq4=Cjf)20{ItZ+y6cuPSnxLcZjax>liRxM61!bZCdB*w88P7SR(DNPL zb*^WI)+^Fy9wI@^qTkbjR}RSJSmxiquOT>T?bz)T)umkd1&7m zH#pRdSDr9TQL=#F&Y@O7KH^bIqfA7gy09)lv`4f; ztAN!`!iAXxJ4r7bvT2HV5v|ShhN>EzhH?)SLYCXGI6qB)vORB`>M|^~pfbe9O(Q&Y zU{by6)z@&t%|_-HjuR)mwGf0K3bc~4&S=r1ku;zfGCnb(vLK+jyzq+3=um;NF*|?u ztV!BgusBaPILsH@M7;NR-+#b~IZ%}WuD|ZpgbwZyO|xr=&pq&nj$B2ZIy)g-_g?9n zR$QhvRzndj=P4{9l_0 zfsTD#r4>wx5wuD0}QS}~w?+Y4=5yJqN?+b{P=Cl0*gb>FZ5_T!)P zzP`j@!E*G`htv&M?(_!_+`p#M!z+eHyNNao>+$h346MIQQQQdafT%P;Ms2kd3V9Mp z+cDT&jh;A$*+rUj9;u`hv|(;;4sb<+N^b~D_JT-(E8$=DhnLz^@8ebyp(9P5Ab=L0H{_2OT(+(uj{p4Wv@eiTlz9WyzFC1|k7`Z4I#W^`SdYp>o;YHO|%@cFsZr!s$bIxKA%l-Z?8+uhe2usHs0GqvQv!dzPk z0p)@r%$Dd5Qf-WPj`Y?2!Iol5V8RX4ZDuBr4?OLtCNBLYi)}-xulGZeVUZ7HHV^j+y zuO7uKQg84SXf&!6OWkBjh;54Xx??*0t&Xq18to*$4tPn1w9$x&D5Xh~1X?ZVF*xth zoz`HrcYtblz}&Vb) zfNm|EbpySly!{8>q2Bu^e=YC$i635j`s9air8>;i_!*;9ocE6YLGD#1;NE*aYi87t zb1Go-?kh2yx8_utLX}!-@uf0N9b(IhI&IJyo&@IteCBbfr^gl$Wzn74pC&?_!rFW$ zn0iO%eQp9S9td$7ytYWE1@Dm;pb=eM@qce36et4g)Nv|)4q1`N>a^N4ibQo&_lksm zpiFEc(x8e+844x9v!?r6uK2baM5$2XMvLyA9?H!bd^*9AP3Za3fc#&3J(W1qTb z-@>u!>jt;%@g-GLh0u~NOuVMlGx{6<>F0jK-*U(8^czJaEp~4k@**v&1BJH?kCq6# z3JGY?<=myFP z0uZan>I&NiZxvn?UK?pIhxNtDQrj+8ONDeOZY=JpJ#g$_Zrrr~%I=|l?_Ap$)fSY^ zyVE{LRywh(yYQ8vt#m3p?>q_tf1W<5$m-8ttD*1(OL8GV?RizXtuRZf~6KXk|#gMM*i&%@Ywy0DP zux;0^Pmhl`TWwp%6siQOh=?J7zs|j`|FiMJ+{Uj)?(pIJ55=Zn~Cc>FO>}?S{sLQv08rWaDc_ z)b1Stk344I8sPq@SSQCym)zhvq@!6M^y6ZjEtQ$LVSVw}6t!HkQ&v>bz zb+^=)W5V81n%$$cq7-E`rD~Ds`Lk3aO%^(oO330_e6m1qmqBZfxC#=d>@5r^g;kv) z0JTO;=JF(%cu(q$kDZVzMdBk;3S^Xs#nJA}gT2Uw+W!8U{Ufl0Gvn;W%mY8K&BGu_KT#dfv1X92CoyW7@W2s5z7k=f-oS{7E|nIswvQpDEcBn zP~zjC{IvP@JFj*@CZCxbJA2(AMX6T%wXKcOYWo|${Re++Ya{vCiMM?B8`Wq3>UU-Q z^Z|9%wqbev@KZZ8T6gsgu3>8ItT}nSAv>?HDpU!H6I5s@m=K5SSVQH&4wuBtOf;F9 zYS6AbioQfy8Je+!LIG(TL=_aOU{QtI1-rwO{DgXat}UlK3$j)zk<_S$OFBxe_oohA z_sog=|9aiV;Y?IPDMIBkr^Zj8LSfa$wVMe|p9;cmg0Q5lSlY>=N|H9>oKi|FBrx7* zftR?bR9wkihTs@pJ4|6@jYC<3O$C+YEi+MhJ4sgffd1U3T5_#g=lzT5b-b|f-OA5u z0f#0i6fs6oZ!L*Ex=))@zgLB3AC!K87C#{M0xmO%^BCn&y5o_l129ou(UlApnWfO< zF}jLY4y7bF{q=^nS2S8h;%4(53iGGMC^H_M>r{&0`UP@@AG(5=&hJ~PRh7@*IAKLz zULY4J7gPjJ=w zqv2p^>voPmc2WxE5k=VFhT_a4kL>5B8?TU~M@}O?!TWrc<)3FO^kVFxZ$%Ao{_kC_ zpv2{Cpa@zrLa9?$bwY`0)XtRG3>G$4%8Ej{n>5K)V1~Bb4rC`h0FkkY6802m(Qja+PYA6naXEP#GkXjyI0V=YHpr4%EubvV+d_g18K=a)p|e z>hSzZPa}A7DDkaV!j)^a%5Re7_YZ~dua$}3ew zOA#j(zE!-kmEZb1zxzJ`k2i7t{`v^x1B}a+q}uaKSnY8tLKKAB<_5MJ78l#}jZ~)z zdl6GqYj$ko%-AH;#}3iA`%VhFjF=Qm0<`Jss!)!KG^g{mB6Cpl3C>!4T!$p25S3V7 zm{W5L$gb@>eYLz?T3o8HUE4cy($KB${^|E{&j)_Tzw&!;?wdXE#k-)u*#oC_l;V2| zJ=!kw#b5mouV|bYdsde=TK}5w`bnBW4{4GR83@A!@DvN(D7UB^clN3;eD1R{JvHx3 zh4pgP?!e!;eJ9-A;DdkhM?qIXcPk&PZ+q2;&zqe_8zq_7LFT8Ok57eG>T!niSsU-Y zqF^M5D!8PL^C{k^-;#6ue=;umM5yDlMCk-WU6%RD6RNL2k~nQTN5t>_!TqN12R99d zG>WKH09A-8DsCgqx~gaKLhWCE-yK%`g0q>BSwp2dK%+HAGBslkJiUZ*k$>qc-zbHy zerD5Inzl($8eysB(JrLzGr?FM`ZABaYM^zxH9xUrejLQB1z-S>&nsMAAjHj zzb992TSuiQ#OoGlHh1?FX*JtO7N}4Jlj@F)NCIA?l?DpA4^#l{`2|RGhkH_kq;zHl zIW?-?_AD*c8C_EaRcVcl&n)(J_b_&PPEZ~dD13GvN9~_`wb&tx!3gvw+0>9c4b+}H;^lOXrCE(6`jA%qG&Upfb5-nuOvZPAs zo{CnkJr1cMbsA4ZDiyKL;H?9dqD-5JHu3xnC8LSLB1+}r0%>AZk|Ydm-N3F_->Fd= zkKWqx@W~UtxE$E?EvgjG|E=e@@xAi7T@n_NPRC$HLsN2&r1PK^;xs@ojV=)uOUf@S zQqh{lGiP$HZ4e-|a-?n2W`2GFpMfMAgT`Bh7L9WnNi~vb+Ko2WL!%DmYE`;>LXyO- z>+7n5L@GTquhO8))yKweFNcK@>f*-soz^}>t=qDNiPPhs4plc}r%tKeo7NNRWo*{M zh{b1~wYzrfFMsUgYVYpLT-F}e2>eeKN@F5A`D-gor+v1gyW@zB%vZ4}ksFftTv z)ULJ0Il59ykY@RqIEacwK}ZG`WoDJOW46f$(v;s4E8>kPBbgMHq8J#OtD3prl2iSE zBrf_y*yU#^xjD|Bs;Qy=0ZEfOh0y++ax{O}Z@lZW&9*(U%@9{KRzyU3pDK!x=)S@N zsxXr!2N- zAR48+YJfcbC#@uucu`wra~FV22n*=_Plb?MA%YO_agz41-29ch2aPw#!} zo7B?8lcIG40~?0>yIEXX!g?=88)cn+-YfJ#l8?L=$2fNQ8GLLY5wcY9){_U^kIYx&1K$3+Y_@N(a{oe2VHcQKs1SOL*$pVWKFka^>E8psq_yVtZH3Yoxd_tw8 zfFTM&z^9lFXD_vaDfff)YN+H^4Q_>M-$DOHbR^d@pi0O9A#^h9`5zMpIaCU~L%hos zs-)8r)q*&eBTvP5s0f`Thy!tWNmlPe`PC}WcdA<@f^-~J&dmsU-tAYeN?IuuX$?k{ z(i!L^Ps=`UVH#7!7?V?lOdFN8sa7Ji%Y6);wTKonYq2)NWr^TDCT}@AM-lBu^1Xoy zK&AQdHOSKaZ@V5=0F6L$zcv)U*ipMlaV92JIg&UI=$PPkNCOh#1+vge7B)yEnkyJ% zE5%YUH#sGNjaZynLguDWYu2J|9Y|O>a)Q~j^SIRGGm8_QySJmsY$p+>8kbp&g4ua6 zk&>Y`WsaX--soIHXf$8E|8sbq(OynpGh7*f@ur+Tw#eq~J!URz)SrBI?!IepD3PkN z@9rs5NRLrfFml};`Y(R-f2z>quGo1QJsYYabMCTaseMPbIPtRN6Tf%Egn*cg{}N-m-SfsB`TW zfpdi3QYk`XMJM7SO@q7;!2H!vf8phUU#1ias*r(l=#HKE zz`!6`=1AgfG_l!e)YFIa4x56@G>xSsIdyX1fl{ga%L_BL&pq<+;$uJl@4jo|+Us^W zsq}MX`i!~mb>Huw{PHuR3m)GJ+5hAiFTZjxvr|ufYD?1kK9=WHrE5?vE-$&Eq2d7J zhwms>2R__7GOsJ;4PLo6TG-Ij6LIFuj1m!Lw0?ob&qKTbw3vS8DbAicg~=kEHF%d{ zy(gA@#4%U}+e`(JN_Q3T)8G63-{)KP7CqH~I6H&ZEsW7X1ky`BMZFN>1=6+hsGLwp znmP)UK+3F&5E$K=gJn5_(q?$F4u48eD~7x7T)Cl@;Bknov^Z@}fmo42!y{rl?b_U^ zQdAC27iAG=@uaLI!Tj+n3Dx4A1Mg5ipDp4%PW&p_S)9iKV$bgx$276d17A? z_5NqIKz1bH0Iiz&W<&*q&Qp;LoFMcg$`dRKDU=5n7sth=f;g|HCr&ZCZV-|h z%Tp5^e)=G_xjM?`Eou?TN$S!$FP(jj2^0a)PNCjdWY3kGc<9M}8+0{e-PS=BsKmbh zyWUbBd-y|lGrWe$N1xE80KaMdpgDGQ>5+H-==Ywv?oHpV;;uz$shHxXjrt>h_&<0} zQT&@;bv@Osqq~=%di+NlhbCW{q|>{?A|#nGKY1FV?!#{UrjdzrAmu{PHMD(jZB7(F7_XRidpjQA89*gcVJ1wL({ax6oY@ zie88U;-v<&!L_lUYdG+77u;+(|^C8 zy7F0~@#32qp^&~|CvNV89#)0ChxM-4*x#S+b;5X^ZLp0A284x?kU%+%W~9kEbsHlsp6B@l+-VdU&8!<;ejbZ$^G)9oSr)hc z@)v1-ce2*1f<)xt2s#OPQ}>KM)exw zU1xsi!AmY;qYO$5+NYiO03tbgT9$=s0!?TF!Z097GOW+9o~emx+}TOW!B%|c5mmsd zd~xJ;is)4i9slMhNk;~*@)nO!_xqX5ZQSMrLO8q1@ zZBi^QRC`7SXD1I)azfI!9DekE*6!I1CC`~dk1}^*5^0kIZbg$g@J_JacTBl+5ROPr z;T3_|xk;|Q@dcCzShwKEdG1U1swKNXdiL?>^>k%h(KY|rv4>Q(8^2+o!2Y{uKijOF z;&=YXkLVx!;BU)c{r>-v`3d81dg-^(y?yP~{>1%1aps?HeP?e^DJoVB-b4~~ZF5p7 zvU#1+g_0<>DKfMss4Yw&jRu>lm#Jd0l6%GpP^f~bpw3P(-I$k_pkf=ER;qmB46%u} zBWi!9M2QFnlPfDd!{Zs92m#VGrD%*aT1`acGVd)Yr&N#yreq|`3_+!$d{Cn8h3Ux| z3PnR@ejHUsslGBp>((;3eghje?}X`^&~)B5GifK8s#eSW!?BFE(5EzS=W2r@s4#e&FK4u@65$ZQ>OSZ}m~JqytrB zu~vWa3*YqK?t>qFv=+=yv3V^6)$Z4*H{v?Si3xgvdj8{tve5?(#&ZOtLcp zzvK#7{=qj}%k)d%WoI_0JV6j(Ob1jXg4dU3e}0viwaOiC^Y2BkRC&u5ND7;`J0)*% z8kOrYYC7N;S*}Df1fN%Tc&yJl2`*27D@6KL&zJA-IvS510MH88P<0ZRUuliv^RLQF zC+X$MFA#;3Wje_!qiWKePwxfs7Oh+-Z{+qn8lAu7s(G6dm^?d%>K!V4OdEWY#=yd)c`9 zB4eld=gn7CdHeUhMgQYp|7lk0E7QMo?eoJE7k~Wt?SJ#utTmg8QC*^?Yxb;fOrMml=$x#T z*^Q^qeByr%G>`q{mD_Lnzrp(F{NeqdKXR^&rnhw=>L0S{+>xc*mgdgCqG#Pz5|)a( z*-m_+x440e$8XfF>D!_xq>u0Cwlh9i}W$eg9%#5ETl#sNo z$go`eoopr|tQre@REsdl~83`P-LgRI)5+y}Ykv2sU3$E1Or4Pe_0uVlN?HrIWZj z$#5A(nkTtj=}5%mC3l=~oy3T!Rmm_H(-xOgfmpRE(p)S>JqZf`B!xGFT2a5zqB(x( z1ic$Z7`?HoFcv52%JEPVT++1tHx7@-kc;Iz?Mbvn6hxV(;^$eT?g721%4=Tgh=zJ- zjK7%5z@xif{q76IMJNv`aH?ETK===8<27&JeccPxnS=jCPjg-tCL8M90}mplI`b0? z&@{vi2Nt}8ObM>z(yqM6`&_5hdyjRnX^WC-S5+0m9u)ok@BH3dOMmnyd)hC5^XtvT zogaFo4z@6P@RTZO{Ekfv z^NSbQdD#uNr}uhedN&00h(Jv3>|x?oLj~GU=&e%eDghi~yiOm;xI!7AQve=nA zkKBEL)}jz-Lp=+mZ9_HRY8{`q@uLN82)p}ybE%Hk0mY)H8E60YAM(FpJfjn#06yqq zV&2NmoolI&&3?ApNPjjgcQ2nTSlS(!}tmbAL zEG@Qj)eGfwfPzb*HP6v~`)Mz>shB<*3oUR$>I~Led?vW0MOOu`ym}qc$Od6xjfUu) zUA%agQZXQYa_X$!zNY9OzWd${18eqt@8)eghSu%e@W(GI4m`SI+1GJ$SQ(i;jR1+& zu`H^dt6zA;I}+E%`ZRAjYKIAw1cgG!8Yx@h8|Lm4t|K;`TMwz_c3&qc3d_DouJgTg zl9kIXpX5^Ysj-N%c@mTiBu>!0A<@pSVD^Tu&Uz79`FgOD0V)wI_wPuBjC6DRKd`K^Q1k&BN#SnDc}{7L`D ztA4_#QG<3yKF8v0i@1(7V^pIhuGaQimwWE+jk@e& zv#AS(g3mBy&eKk_Z-OiR|7|>@6QKvrk2ykFD@V`P8J~(D9T@1EOcS?OjPq`>q3-|u zr?}zf*Fk>)O5Gra98ginm;Buk#qNOOkOyyRPM%?Q`V@~p^3N2)fDLPRslF|{gr02_ zx_79;nz^7@IqH`t5Bn^hs7xO@|I@>JUh@2%H{bMa3kUAJ@Zh~1e&O?5hj5L{O<%7s zFIBXPgoWhzD>uCC=2CP2V!LT=+!pVvrGj3!c~q<)XY68&%()z$h=pXDL$}`sOO~SV zA#P`&6*hA?5o||o+k2r@g{WIGaq+Yt+0~_Kw{JUo;Y{<}zUzC;g$u`3SIRqf}T z3z#Rlymg7n6PHpJ@eZxjN(*+SqU)eTMO@DR>m)-#^7)`&evE|&y2_;x{jGn%D*(+W~ViV{t(X3Chv6?Y+-kZVUce#PJYkv6Rk-7h~ zWBYEXcpFZi?`}5t{kWT)tR{Uod|zD#{c~@;#vD3$|IFUYH+;Sw+qXqg-CuRpn&9GN zQ`i`47aawwN!x-BOs8$Fz^TqL1o37?57t^JmSNr2iloUL#y414nymfNAN_nob{AZF!{?D(?%s)V1ZicId=Fo zkKX?{wfThRybvc)Z;LcirCUzpRPfhe$&!pD%Sck2&z#jaJ5t~qk7slubU<7B2nvxD zN|D~YdBFAm3960xyXVrp`>t{kQ*C29nU59#8(qB;bn(#MUQ z2acJzb|KxdW8~)PeSiNCyx6k8uT5Cgcp=|o$9eO z_gj`-gU*V+Q+Y^-@90!MJA@}xaI2jRpB&!h73^{~v%D`ITE=pZbeYPrA}AsO%QI3f zQHPH3^oIb6^OUt%1fI=u+Nh z_nIyReZ?|LDYE$%laC$d=tD<1cIX^&3z8PJ+mOV_VhdGEylYu8iQ|q~($8a^A_#md zj>%juJP`x|nR{lpM!&f+58q%oASw3Iq|D;f1T>dO+V=l6n@W--46?Qn9mDL2iyV9S z4w!rlh&y7uLEc+eb_I$J1#n$Z+)jDp^VzoZCPaDC_84V*7S%eW=4S6!*fB+=AW^kj zEzXG(5OM0Hc4%R%%^0|kys(kge>jw>@{rII09`a)qyRB z>V|W`7l-vB#vl5%bjR++J#PB*pR7bnYVF8cOL=`radSxjF5hyP~#*w@Rb!KXjWRpVVG}G5E6y~fe9&yuZ=3p3$NUDmCD-BrBde5gZJqzgHV!$ z#?0dU8@~Uhzh~?--x=2q*uf#=r^aW@sS{H&HJ^}(R*MT0EX-V>RkPT(&grZoPzj(C zpo#^QgD?xoPEK&}V|Vb`Kl*!a`@7qD?BR3NmcW=EoRn!N0kd_e$4E1Swg->;t&SP9 zUT&>tHp|yt&+Ie-doIkdYqFZ91*WgV`(;AhSE*29n z2M(SLW+x9irjEeE+28+;_k72HK6mKg3=RQg)+!b1<$78mB1T9U?4 z@f52Hr6Fy$v9(#4y2#ks^HfTZr8$r$%RJ8JZ5ro0MT3W+j0~>pQRl{LzIXI$km~LG z9=N}eWJ{)6szLL>AI**3TheYRTbjBM5YG#$DX3I$-ZA87Cmx}B;tRjGZTppj6O)T> z)A|jnT!>KGQ7#sq?vMCOLMffQGib@toX&zvmCIuC#Aowa;EEf)y#!*BEU(%m#Y>8p zIH#XThL;Q>MI>GMSw8d2R@$KA6ND7y-3mCydyDs3XS2vM->(zC1GI2H>+l6Tvq6`) zRr4yY(}r6~qW+Qqw-c0Go>i?vnZnA=d4;V1l|r7Jayvg>-p%MI0BOEiB1sagSVAov zy7TjRn?QU1|4SPeD|>f!Wrb?p5Y?pBJV2vyQ6^``)!LCB89#YDG!OsI<=5=(s)Qj& z9(r_|%BI^Yl^rnW{pK65Q(JZ*sk;OWgIs`GyjnrmIuWcFtmIt*B@i0G7$OzWsMQ$k ztuC4R6yuNF`KC=H0|v47*#6^OvuC3oJ9AX_>@wG77aq82e)2(E?8?lkvnO?83(_~V zOFjSQH>sV^e=&mt-DsPFGvEpYJ{P^9o#mv(`5LWr6MXS+KE`MM>JvQr*~ghaKF7?( z43|ZualpCrOEi*@n36bMPzlB-qD|`5!|33Xh{lO=o*++tPnZEev*VfD8ddoT98;i) zr9y$z7iK^en3!(=|0GavjznouMvMqWRg?>lA63oPUvTYf-U!vr#PtNz6?P6&0dIo* z2Uu5#C9}6 zJ1tLVSAaQ6cMzK$T7;Gy_##-uciKrS$k2TD=e^56vkv898SyFp5-nl{@#z(+!w-~I zx}#1y`$JBW7mY(YX2ZGSj_OP$mvv9`ugk&=IsZ|kRyY&OL~%st-+P5~&}_8;^<~v; zp6;lWBI1@Xu=84Dv&600J@~eXeII>uK`pq(d@U%1A`5NHY-2%1p=aA=yF^nrJ!&Ca ztUa))H`?>RON2kv3VI+b{u=9__x8zqj|P2A%JyxejGr2pw(WRbi{Pw7B%cXdpEuMy ztQ7DH>x8rkQg0!W5r$Q~ZO!x)np`+_;+@yN@mkX3M^(-lZAgEAq%svtD;e{>Ye#~I z4jhs=Dap1S*Q?R1Z-oASSQy8}Z334Pry)v0u#V<*6Z+ds96!pzgU2{`Y98fsjR>ES zw{$JEni;KBa1t?JPo)ui>WP9 z@yt#4N}-G<$sEm8Xi9;m6n&v0uaCf_reX8B^y3r7qG__KR!PZ*LojJjypZO>( zo}<_$XyO$#pjVzu=c*b`YtTiI0-N?em&>od0oTsBc=ROcY>lAQO`1W}HLNyV^#V1r zWtU9N&*?awQB#lJ;kVv&y&#FAJ|*EmNwu3TS1d-%EFAl;ptwkPPq~GOu+E~55v@U` zo~aWP)GjWP)jT+j_8?9nu7J0>v23H6A_}g!3R!dgUUl&CBW}m_uTzAZ|KY%)qhIh| z*mK$Qw%5kS{>S*)qjZ&(Sy-5%)t+H;>_K(#@lSH$_?@)cV-l!FurPhn&z-*iyDqCh309$43ttU8!UGsI|xdjX9evuB+EJ)lq%-~V)L)c;#G#%7N-&% zxx$Q>EU*5SD?pOYmVr+5gsCjvCkQcKlFs8+ZQ}CEvO{L~K5yOTRbrk{#d&bc)u6+7 zW}D0I6y9ez*HNKa`TeE;FISOydpLg%=Q;qK4iLvLQ#asJa_^AzFCl2T1QJrq)v_nc zz}cMU;l0O1Awg&eLW7B(em}x`t;Wu+yVb>G=iHi|+j^Nf_#4tX!J3|c*8G?{efUl$ zPTiw=q6V8bk5F2-g+kYWq;4Ttnm;V@*u6ivVejzGjYf^b`;I-%$n}4?X48!vKQwNq z&rhky6vU z*;zjI!4Gryt@kl@Y#tIw+t6shVl9_NOA|<9!Ml*mK_j-*6RYZpb_z!N2Z17$vv2Pnst+tK zO&%pIV^d9N%0wmyjJ9VSZeC-XAwCW9wt%-qyepAqigv4w7wGCiZhHRZ*vC&vrMMyJ z-t{tzTK7xMrIdc-AUX4!>DbXqdvVb^F}jte5=2fl7RRa2Ucj~HRHYEGZo?MU-&>Wj zqo0N5xS^~;iJy_0FfxKym@-u=pYvp*P4}TP(%oHfQZm;H^C;<7Ux-|WU68uDSkPzYKv1Dp0tw;mw_~S zB6Z%bv|HV>Y7KcS*5U9f|G8gIu4Fju%Hv(J3^GfWWkgXx5NU!)6NXR!?W0&Iqr$RQgb=D9n>csx#&UTfbL|CF zo0%1fTPkZd=q?UGJA#H*NJvk)q}C5c&Nq)j>)3xUmpx4h!FBylwfUxnzz&Daap#Ls zgw{&Dha|}>B)442Lq{7(;W`zwbXud$8l-LX4BKG|NXssm*A%Q)wreYFp(|;!aKMJK3+CY-DXv@$E+vwb$fra;!AL%1${9=nm~ws?OTBE^a}`5_YnVEJma$U@ zG15SnOb4h?hM-SHy(1Kd)~IzmHmmXZ(_}KOu(K4qyR}2?rY(i?nfSgQ)?ks zyfKjq0z;ByRHAMo-389zEZ9t8Go5>`CZ5IlCer3la}%w^Z;d{z1LYGs~K zT`S4KINo>2`OZ=-7EwlH!VnV~OcXwipM4(NckWWh4()U6wheU?kAL6n%prGLDwx8dH^23YYbR^dw^Xj!CimR> zQN4K!vTe^MRkIEH*KcE~4l~U%o3DR8^zI}l{14}Vy(|T-FuIJ*4DB{#F{E{3(|Lk5vTuD|hmF5LI9Z)UwAqc2*(RsLsDTl%VFpb!5*9^DRgMf-EGk zAtnn6vJjm{sI&-4gd_!2T12GY}C0@xCg6_G4NY=pNFl7(Ocd>Z1i0Gow)AA&F9 zrHJzp&W4@GUfM^p2xlY26;Lij`y$RpcwYb)qFe}_WW0Q{w;q%+Ai~hl8ltdB7!?Vk zB0-dExBkCOhH)H!$<}JMXf~U9#ZRn-1yEz}$tE9M-)dg4v-9J6dTxQyjoVaIEVHmw zM`D|s5qk~QHF&*&`fQ|zN)_Kae*oHte`5C3gESTeWW#T>;l?xN-t8fE>jq4q3Lt@k zz!y+1*ITvLqMRadn#ksxQP4dQQs^I&#Y7nD8k|h)@%OITyanQ>pPZ|!7rgjN#%E4a zsFp}%04eNY+YR3aJ(ts5Y~Z7gMVNDhA&@3ajLkB$=y0B#*e`jfzg5qZp-aJgjkTIA zgLdL*wj9maQ)@#lhE{@VXJn}(@Dko-UGV!tL}rzZox^$|bqTIB+xF5CnOB!O2Vb&1 zL*f~m2$x%vWBRLiTIJ(TFPQmf|d<^BStk_N=PE?qT~Gj z!`%1rkHP#Tlr^-+A)BLM>U5PYun2wz>eDbY0p%iV2Zyjr8IRq4AJc~pV3!uaYd4jM~Q zbU3WG?07!Gmg^~22T4;8t#&SOTJ2SXBO}sX)w(@<$}zU@+U-|ve{`c1fx8GNm1k$K^xa?MADQ)4?hBN3bBL4Ln@F6q#9)da0Qf&I$MZJLUcPo zHx0V3(G88R1?YN+X@r=DK{o<)BOs_pgv}yBqfF2&6V^-l_l+_^tCDZcu6%2E6ErHA zW))ShLZb}z64I#R>J_BXg*3Xb%@VFwB&!!mYX!1enXFzUYnDkGMY3jzv{}Zs^3BB+ zT)To#x^PJsKB?kXwk~W^CT$lO=#SvLMB5sGY6vj)yKOI@n_IYXblVm_bL&5v z>#pA_OO1I|w@~U|k3^g3-FY*pwO}=sN{K96fMgC#OmgfHU;OjGWZxqPNv)yXgjS~w z8h2)ZS)z08Qwy0@B&ns@%BaUFwODAzNIONfJudZxmZ;_>`hHJ<^=Q$C)Gj-rTmo)A zLFE4#E;#y(MU84D7_CV%i&6$>QmnTq6<{c$ROUjw86N3C-3kTix^SaOW?bu%(xIeym9EVmmW zA6a@4yvtupY`%cY5wHrup;y^&S?^dafwsIqfX1M-LX_z|UUv|Vo!9ET_dqYVS97h? zoSq>o?<1daDU1@DDWnc0EJ755@)W`%LV(l!n?vi+6^%U+1gPfAbd)TWUE?t1tkHebD)@`mf7yc-yVLJ7AxhY2i&Vg~g| zPCa}-kKXq%bCY$7p`pFx$YP+w5zfzFMP@ZgmiunTHX}}5~qCXFjj>) z6}{DpK8^$i0;eUHjX-&{&(Y8;*TE|FqGxhEV-um$3T;?qh0T;x5!FS6gp+aXI4VvRI}ZpvADqJ7e7h&V1?8qWMnv>;yOYj zp#$T=wV)C~=oLjPxCD}{$?>_zIdl3X+b`e6h8-K|8QDg4vBZhT9%RRrJJ9LlWG4;~ zZoEdNW7E<*++RF?c#^(gNZQS&YBwR&Ieg9eTt-bxfX>MQXgo%cbwmB?@rRH2LTO8| z>5V@eqx;{rZ{LBmz0l$Xuef55J@mzQ9NYIWy~9OQYbQcsROxlsLrXw)Q?3k>q@K9d zq&Ns+xkwmzC83dOm(~Xk-R?)PzxhR5cD?*%_uPN}4xVPKGNlw~gYxE*gczDkS4eb~ zSSl0?J!D}Y7fxN|-1(z<8dxR1B1)~SexKlUB~SE#Tp^|VOY@V}>MqOg=ThQY-tS3Y zeGc$hVMs`a$}B>lHR1)O72YlT7D`9o5|q9K_*qG)0)cTTrBOz$&?T(RX&1Sy+%o^r zu3R7a`@M7=my=}}Dxwftsn8V2qAt)OUKGX{gaEB{&bs(F)*971S2}68+l*Zt_mZW6 z|A7++?xbKEB<)z0yVgk0o*My!Hq~5q&}9(hLap9sm|_v{0u>f}B}?08^2}Mbo;>=7 z8{hP<-T(aecN}%aDijBQc;jo|ef`df@$1h%a+fV>f`n9zD6xXd-AnRwA(1qfvenSn z+f94CE(L|6t4juV?ckwXKcx2V*(7)0^N`wc)gIPeek1g6homo`TefSM3c29Jg_9h( z|BD>jcYw4d7?+wFBDIQE;)pY7Sx8ePwy4Z2NkvO48mFTl zbUyfJj}AP6%{h^(g9=_gPdk!;-vaha%khj&gv+tADpxtT%IgqEffNTCPM(`nySHtW zFFZ8(&oY8B{|wASM20}pZG$U(Mj*~I288|hL5oO|#%n>G)yG&`?)dYcji1x2AO z+b-WoeR@(Ur6r0`zLl#zSm$sGyt6c#8P%YKZfCNwufW`eDallyyz~ct9)>UffuoNe zIDGB(R~L^xcyG+o$#0XT@lYpCyKZ!IFj*kd1`_j*=megY54)9?U*#plaL0CXkCn0xufK~*XZg~5z9=h{yehn>m8+_+)0?z;CUpNtTZ9MX-lBpkk z?#o_X`1nUYnf!;hzV6$uzvbKa*_qQ_t;v(Fxr9lqh}DoP16oL0ZN!HJA@mGFwOXWI zt8w-;-16PmFn9I@TQ-g|H#VjU)qr)ou7EXrfbRUp6fZ!b39T8%AG)6d5A0*?+}S-IJ0JWeTmM|j%g3~j*UlqL;a-ZtrQ zv%GkcxW&o&qfDF_WBZ<+)aMn)=g+cj=N8iGIid}lsLw3W)zwFsws2v-+Vsw0Q_01= z6j-&IvQ>P|1a;f)bjz2px*_`iSaFW&tl?>5Kw{c~Kjb1;^?>dfJX z=qdzCd?4k@kje$di{ym62vsbhjG@(TQk9NxpK<6)Sv6{NB0;QA9KWAEJKy(`?Hflb z3g48Dq0!Uv`3k`kZph7Mn?h8jWk=a_?Q>+`Ll1G)bDw+4=xPnJZYVCF8LOT|=Wl<- z$B$)S!qxWlPkQA`BHkDDRz%<_qtKTfMMdo8!uC7tK8Qh3-Nxt)}4GG0s`C46IkAPLWt4wvc9>q-YhX zha`h$4DBp$hh~CUWipS6M468`75rx*KswmxoGy`{!-71i!vEHaXKW&rj$vlfjxkDM zFuCf6cnld@Ia2SSx0@~7_WE<@PMQrHx6e*boO%6XEqx#gqDrL2`cMVMFpx;Jcu`6@ zhgKbc2Cn1pmd_*|bQV;3yFrx0OAYCqU?RDPn^zjIp%tg>TRcpu%g}5XUx>k_rL zuNM>bsuV}D+Jst71*%52>`SNewwueKIb+47uyJ>v(#1+TZ-%1q#jkycLidlh6qL*Y z{pvhJyZWwJ+;``7t)&ZW+cBcEhGxyqZJ;$)S+oywz07hE9T*z58pC*WZc{_l(?@OW z99KPWue$${V}4KL*p^b)bDo3vJIPrBxi`X7rNb5brhlzZSac0!+3PLkY(y#+x1WSUIWhC&b(B2D#HA;77@V+B=y(UFC1rhZMULisSa;e^lroZ z0vaIYIo8>Nt`BgUd0~oR3Kh-Br5o4QRZDv1vsU(C-BRhLGS2r zP?##?G11sl^h2GP!nzq*rY}oEDo<1II z+PLG;;`G>msMlsbGuT@Ul9JEL1s#?Oh9DA&j8TDcD3?2wJA5v)MW=NmxelR_SAok5 zYqfljatdcOxgDL*YQ{8c9;0DSgmiHn(Pc(%eg)IV4lvx;iwQG2qW5^656a0v5~RBb z{X?i~-7+16yAIo4@*N?x%j?=k%R_`ro*ASDAf(|It@fqq-g#tk|xB z0dscA)3bI@=ZILm&UtWzB?yYNTP;xe+EGLkmivfZsH#Ilf*Q`}!dkGH-ck|5=~WMUr)WpEc&E16^`j z5JixyDN4ubRvCaiDXcPQPzdC}z)sc^5${nt|IkG|-uaG6gh-%uUR*0BUWB0Yym{kX zwl3l!UcIt7~_c%2(+hB0rjX(rC1X7d<@gCyE z79?nI`VmLWdOTwj zq1YTYQCnCfSH!$@*{P0exE4r!5rZZ4DUlf4JU?wBai0sl+|Zh+e{^KHx-pR;YdQ&v znNwZWKti!7MB#H0LalSAfmZqwfPvikTpKXtEh**mTWOYMI4zK^ydf01MM}^5J|4aA zG;6jlGQ4I7>EuCXXBsFCS6#E7g?OI*54WTzfVhs@wWo){kuB-tXKT@OUi-aA*z?Ml z-1>K)nEt8%`g7)S?gClCDUnlM}l;K6cA)4Od)o)xYo)&JXm>FM2U_z(T6yGr#)Nc9&MP4G#@q zWg3Dg^7YZGwxsSLDxdnyLh02HSIfKPALXjoU)6xjEuX$5VJINz6pHzOSGggf6c`io zghj&>xLaQ)m3-9&{F4?SUrQ3}5c~5Zm9C(pE^!IIhUa)vEWh&$=gzLYBd5WsTwoy5 zibyHEb)Xem<;8ZW1H!=QcH23M$%{x1_9=bNO;0p+&^@erw_FRp)H&9jS-llXiH4Sf zLIKHgFG$thN3qm{Q&UP610o$@nlWegpM3qk>B=8{;;x6~eLwnL=y*};GZ*!~-}{6A zeeDmt*PWY5-+y89q`C6SUVD9UF(?(0zREf=y29f}kE>R_C9izn_o{^hkKkR*{8Ga3 zNFNtw&Jb5&DzY>pvzpj?VxQ7ZLlU=)2z4Y@ zBu|E(*rJ?h>r@aprSW2Z9BqC(UzjWHMR|`R&GH17*bJi$nYSGoKbL!8c7R$A!CSk6 zmi}^Q+%pAE^NdY|%leD0b}RqElY8Ht8%m}F-153OR|j!`LFq@lO0QdJtG{zfzqAyJ zi;YqqbfmQyrNrpY+S@?jL7UZg1cw6xt8?Xkr7sCL%OyBFqR}0BCNChdVYqLUhrW0} z&-?Col8&8aVM#MRiEJK9)#cY-BU?uoIr;E3OHu02j4iqI&FSdMm%RJ%;LY!T$!GrV zvoo)G+jp2Re)#{mvya}PUVQZ~`Q%4Fy5ojx2A>z|I+?dRu|lzH4V3#jXYy*ft&l=g zp`E6XIkeY!40wYfN5}KRcm2xBaj7a$ouPm#SX*3Q1(SwYU2J|KgWiT}8{2 zv+k46>#y`|2n<1O004jhNkl`@l zyS(aFO5t2aP*9k#oSW(y``YI8VX|yS3R0!7e*;h^zpZ(|5f%y*i$!cJ&bhJuJ?J2V zf`Njj(%r>;9bWvLt+F^aqvyxwxwz1}vApqRBQJZ&%@b2+&#B8cjmp{`SNXsE@JIAg zsqZ&l`ktR`-2QvN`n$&;KOWrtf&n|&W8}n-C^7w{l zhkn(+U-h}3_#4%6U-+`m_|#9ay1A>KwEvTD7+(+c;K?+LFMT&(=AC_A$L(vlWyw=L z_R?|w*SYz1Zn%mZ#Ab4&Y~U4m(?JAltQWLWh&V!{@HVEt&~^(;O;xS>-SczvSnE`p zrbOlPm%IRiKz+aGLbXVxTBI>Pk8jVS!ybrh(1@WmN1W8~3X0v9o+MP`XA)`0eqjHD z|GatEH8)Mno;sznp3hgW#OUT5vW`f;P*O zT-~Ll9iLHWg=Xq-S&j&`x#X$09;ZYFMguG_(V&2}(Y0 zXFt4DYac2G=6Ah~!h(S?2(1pp1VN^v0#XQ}V3Z0~fRMLcQF)8sJC6@KkOBH&V=>7gT%+qQhdQHC^pJ+^$UvX#KFH6t+kq%XorVSOwiVYi$D7Fzx1;Y zo|yf>p}+ksuXy7-^hZDbX*b-h3FoG$giAzGj4^ggY8NS1oK%K}RM%pPcMfeWE5pa- zP?|!afK59dE|RVE?E)OFmQ#`mzR?ioreUq$+|}EQ!-{teio}Ej7>UqWA~l_((|k7~ zMXd525$Ft2|H9$Y|Ks>d7xwBTrRB@DJHLTgL29o4K)yoCk+1Umf3@&WSg`zSyy9|N zjkB1jq(Iso%uy+yq@oFe3~y7?*fP-Dht?s=6jjTmGBUEZi}ciR?#`lB9LG7QVA+>Z z3rZA3T@;Gl%(mvS?TqN+7-Q2HnVy*-Ybhot5~{s$Vd{d~G%zCNuF$F3Ea)y4*A{&X znl)7l3e?I2)aof$-|z~*_v)SIqaXbH!(vM>8M)>y-}&jk{M)O({mpyVU%syUb-Q2x zk`l8s@`ZaIRHR^IIDYIjaRNGpW)niKn3)%Pdch^&S0%rWzBx9hK;SY@>cM4RG7DKd zp997gZ#`ZI1Q|+;(&wD!w=Mj>Q#uhv;K8yCidhz=SKyV;H@@;ZNs# z<{N5Fe^souR`|?pmf{6_?voAsbq>?LM6s_er7lHK$TlitS-){WQ7X#fLPKd|^1*~DaLJD0(w*IVM{9A8vhk#G zLR9RdXaXjtp{f#DQ(B`YPfoFReR*Bd)`&P?@G(6sLh7NoSuHfCB#a&>Gy(0#b`sl9 zrMpNYZDIjU__TcT>Kn*j-^jjS%X2TQ%KTfr-oNZkKJmZb5UNmtkP#?B`9;FqGYcIA zh;I>w%7|;>vxLx;JkAKJfc6j;O5IYAhi7MJDZ5NLoXV_y(is&%d6>uyBiRKWy!$Ye zHH*z97MAiwr*9dS>Tv2}#`-l%4Ga&!*-4~b-(u33AhURzQExUN>SiI1x#!W-?(Oe; zum0md`=HO(U;F1T{_zoRe9_jo#fwMZ#%R@l@h|^MwX!xL$hnhqXep@0$wV?i#TFVZ z!9ea?n0DO3I!V*J91UKGkil-K%|v9rNUCA7QIi7NE2SV(fz?{Ky+3c2`Yn%q&??jL z0#>2DR#uip+9gkf%iS2KI)d%Wul(GrC*qz~&$_?X`1jT#U47<$3n#)nk|Y6Gv7Uh( z>8Z7*Ad0P{8)R&D8fC2+92wo;TkU=4%;d!XUaZ^ygetrt|Oc;M`#XJ)zk!Gq=x|M+*@$3OIUm~xqNRK&WBdXlhX z&u*WjO@hE}j#HtyagCDc8LaguZ$Qr3mdB^15okV+{R@NaofceO&6)%g3r`M>_XKlXj5>lt31yn$q1<)P2=Z)#FT}0*tIH5)?(b)aT;;ZIMEuM73N|K~RuF zRKj~lqoFx=XwlEiq_Q|auLBim?X=dp*XjjP`nPn%2bK5rd{Lo{h;eA`l?pmd{5%mV zwJNz8L$IujByMG~73e3XvadxtaYf>9)q?Ho;g>EeIw}1xTkw6O`=^=9g)aU@dp`qW zd8M(N3OzH54F?AOCceyUz;zjL5F3d7Ko zwJnSDOKzaDR(9^%qSx;&t4uFS$2e7qh%_1vrl;rC{3OJSfIuTb+A$0agIJ4Cas38; z`o7O{-L^jI>gm(oG_4BLQf>bi|Dcg|z539}8FS4`Uh5JGD3!XYwcCWoU{slqb=XWe zbLLFwovbUB0j#=sZcIt0NK;2?_0_Qwj<8ZjImP7pCAy0h(gZ9GR2pL28FACAB$-#u z*=exZx>8Uq)EX`^x=YiV^FQ}1KM&=(4Jy#HS8lnwJ#*k3n>KDRi}fkj*E>oxDUf6u z6GTtA{yruqzW4gMnarq zG+J*hg>Au(WDk z=4N7P&!&2OY(bwHUsC7hF%4@-GLI)XDM9c>t%BP^V?N{YwM;xpi7`Rwy%)EPL>ANv zoeL#ToXzVzaVW|4X*CX`6kad;RIYmHS4oE6$tt-%jsH3wDLRy)e1HA*PoKY${RK_t zVhrEHiEufdm_Yn5 zw8%@Fo*R-PeeL=r2aiv({tR^WB5V30*V9#z{-J)gZPPZjVR#K^if35AZadl(SZFty zpP3hujL;TUmsw*o&kpzY(zj-?8|rOlrnS89w{Y?IrXTtI zTZj5b7eX_5U+?za|M}vvL+AhCk3Xz__5a+;@uL&cSZdN+>CI=g&mcROXJd7&;(0!W zb#tLmA~anjiE!ckIUV&(xQ%Pq?YcP6?`7@yW+k(Xoj(cZPQHE96*s?DSE>hT$ADdr zoujX( ztI|DIty@>2cGix@Hs)ow+~Qk-qHf!$Qi-f?iL;b9zUN))@BZ{x?c0C&4QnP3-TR-q zwr*qYvB&hicRT)um;_2OUr#rfB+!qzD7+&GgU>oKj|!%p>otG}qm=Smh0ZHQpfySi zmsDePt{u@i*2}rj(BUI1kMe>xVXkXyEUT$RPn85$qo%EOm%J>sJYoN@B{J<+qzjk# z|9V9Hzn1;KQiU4FfXU&6yr3YyiXjFHu~t9 zGmLClci0dgZZ9srUr}7sbUZ(4r7uTkFP%TY)=*OzjnbgEYSHBy-Th+>^(c1i*+8Yg z2MU^!?qYP~TBL5d`->+?dUqVW^4;(Ip~K&M^Y57ci&w9Ee%bYJxz4o59`Ze-U9`{M z^-F8|{cVrl`!P2(I7}@r5EZ)7S;~;fsCui`^mR+ogrk9SJ>G_#eeATV&4BN=G~45J zu@mP@Xi?w-NNZ4Saq960iI*};Xj~%r6nqxYb}3e%dpN*Y)U_{M2YRszjdfE~2ghdJ zIK#z*A8XGaxTV#YXJqG^F5m9jc;V#ut2S)e`!hfD^Z(-mM-Lxn_hm28hYlU_t$Ksh z=6u4ZI{Aa}8#_h+T~V|ec$tDziwOq`_AtBFXp5UiUzl_SW;V{A@PCk0+zT67iCvd?&HpZ`f^3U%*{`$B5$lcAk<2T*&z-RW_Ms{V=ZuiD2lBM~RsAgL& z%(ngci;P>(nRr@-SfM^=DF}VmX>PZ>nsXp028I0BtXd127DpP0qiu)~x(FUzG+Wgz>|HLaq zW39`%lh);$zutfACc@=-az%Ja^cPYB7MhMAD&n=l*_;n(OoSCkGV$xytzlw%Oa~IH z_5Gt>TG^C#e9TDtF-00=G`6KN8>XgN-_U-uF0r}T5Fkm7 zbG1nxQeGXpYHjt4M?UlqOQmw@H!hx=_^VU*-p{s|y-?CjOi3#n28++zdHrSIarlvo zf4TeetAZnECTyB!wA(`F8`v~fBq>JdM?&q1ybvkxQ(T%+TbyPsO^hn$D{18*^d!d) zGCMYg7O+;~EcoTGPH+Oc=o#pSW_#NAERJc0HV$?dm)Nwe_igisPTw*zm}YS`FjO>A z*E-i91U>VU7yht!V9oQ2VfsC%&OGk-?%ku09y;!qA>Gf$GdNbr?N6!*MRU~^d)4tX zkI8$#@5flTx%(H6-uKC0+P!lx^z~VE5=@>rBG%8E4I9?l`KgOHt=lp3w(;|`e-Cx< zW=~V8SW2NnS*Xu1(Cf3jWU&d^%taw&Wq+F`4SO#<@@GHNw__6*?tj=^IC++m z!g)`ynD9sMe($#(KX76pYJL2H2TDvnu%>q-^@iogfAvTZ0~H`5mj{2#TlU&C)7VuP zgHxKLXD4X2lAzI^_f7}WJ2>c;?Ys~{dkDP8WfpM)l2>HQf*xP)+S02^#K;7BP88|9 zo7FP2Puj2Z%*$S{S}RIXA(tc8`YHGOX4!w4r>d0ArLTaXV?*|ABK(p>n4c&H!B9X- z5wVrr-bM%bj+pi`bbcxpqMo&0J6LEXlzglVZ7pJf#BSKI;TTzZEKH!3WrQxq3>XfD zb7Lkn+H=$8 zCsdg}ODU0t6F{cFR@P}$4mLw@q;!SCMuf;abi7rph^(FgtRz0c9k zIj`ku_xF7^{$GT$pp#DP+ji!H%bd2HlyUILVJYf4Hf>kGarS|a|CG~J&%jo})dOm$ zr4`T8ju+MZWL+&T6)8@9@n?&w=kKBGY%89n+V6Ci5dsSf<5O&q1WG__l7o-j#l>@H zNsC*Q6GRq5#q0Qs#X-Yya;5_+RR$e(_gD%My(=rl-{6 z*M96(^44#A4Ga4}@$2h0jt0y$?C1aS&cM&&t3C*VLRdR>q5bPw%QA87WcIT^_C7sz z?q0qB(0yKYZSe2^gCDk@Zip3++f4K~N`3ea|$*L}ZRul^P zym8q&?5njkpRWCvCFOD#6TxSB@(+z87hL=nk2HN^YjpWQn!un96p2W!BMie%zdguh z)zEnDb9)?J0*P=m$y7@+w2Kso1WccwR)N;KB#NT*Z0hNfO1V#Lp(JT&XxUL(t!erO zcd&E!dj0-i`j8r^uIH66dyf0FpZYQN?eBUkKIWI>*^8e(|KL4re8p>|Z*W+XHEmVv z%}gKvCEUVK9r@xvo2FE)HyWoyBnSi(A?O*-qPlSRv8;X1U%zSF3*LD9uHEZick1+k=H|_pX~aA`Bzz`@lDr+d zdIsD9$)KzQc->C=}!N*_}>G)YLo;ZqaTabV>v&8L=`G?OvA6>`J zDAZuQM=R**uS!$|YniRj)#xsUDs3!?D)fM_vt!3V@Y+{jW4B*F`n}EZ)34E8d)%Q< z-)5$cEKy2vm8hy`78if}ZLfdz`FkFE*!+h#yx!e)=cmNkCGU!BXwi+89_nqOJM6)i zw^B;24P7hw4P1BHp#WO@OP-lr;<&EX z6MAw&H0lzQ`fH&|Jh|%X7$kpPr^M5;zg*%{#y~-G-%jI9Uc!G}@8TI4PoA+X1JAs- zh%77JyUsz>x&K|~dr_WJP@wGtGRg#D5efz7Y8UD6E08%y|LA5hDs%>q@|MLQ-go{BTXw$496B`Vlui*7;i8vFim|Q2dBfKpFOG{8HmB4$3hle35 z)VXkSiQc1c^^KG0ZYSD+i2~;4j;ZX>AJW~oUi!8_NA0;`clhufAI-*t>6eT?@4cVh zw)M&vd%W#jvR`&B_v9JWw~8A6zx#NKK9y1m>l5N+PWM;5+q}X4&vfdM_ZAEDHrmu@ zsC_}5JbF}ANvpM+)==r{0>4DHE8?1~Hal<61S~%IMtU#*hrYqJEKal)-DS!Zn46x1 z`Ekf9Jp9GGXwN68%;23OZVOSE6V;tl#BE0q6|jv2Lp~WO7LeZIUUX5Rl}xT3S<8jy zaU}&H>fr@9-E0ni;Y0R{H@|kr#QsnH*2v|1;Lve(_!D=iz64(k31?>)FWhsO-?-@p zgR3q0s9d8F6{$ySv2^3akUE2uLz)sY-PRP#1GLH+nQr5K8KV@T6fwF$i-f?GP)5kI z1dHH|B{zO^cxQ8)ITYS!h~#KdSw)5TY6))j@4s4m@k>AEC$C|@KAo9=tNn#e7eYPB zb?jgCs^0>!jC0GKb5!mip>vFusJw4)bwH|vT&Gm!2ra8LPHASAn)skVEE#Rr03CyF zfoUM7LCY>sDk|2QA_HwpzclGDD0Dc;k{!er*3#6y%=&I-(~wW!`YBaX!t4b9EwIAa ziN^y>BBPr}RjoPi!*asZ!MpzCnj2r%b#(uu?nN)UP8aKAyzw0z;;Sjn}=)$nK{My>EmQe34v9RdeRJR$1Qzz6pPSmwS;0(TFn+1eSys* z-R|`MSERKG5T~6o;)77>C}VNvG0qTQmqTPa|hl))=Ja)RuT{?ie)kj?H05qFH$>kl={>HDg&{aG+8zk zF*v8NSq}A=9A}cNy2QDuMxh*`LQR%2QD3N2sssc@;mTWHuI|70i|+E*zf#X1eDH5Z zHm$7^D*MHc{Jm~ZI(Cm%{mxD6n5pv%-}k*&*6w}$L9_RUtHeg0#k9?IGiE8xm2~in zl=Kwc;RFRaOUO9RPGeo2*e5i-qm9rOi*gBJ*2Fg!DY}$0mZGyn-V!-W=q*NU?t-#x zRrN1KVSl|z@ZVFYCndixsVtxFH~7sKD@ynXna?PdiWG}Qiscf%lkB|CnI}pK&e@!Y zLz584KvxCjn%L$AdWx_nONf-Gpi_*q=oAWVsHP=!s93Al(kvHQ2>Mt`GSV!;>k^Gh zKh`I_?hUW;ClB3g-t(TfKJ@9&e&Y9bnD!5I@)669tHb8ftSMDZR<5MmW>5XYpRZAk zH~+`0en@`f7v4kIosz^&E?gXwIAtm*6?RJ9h>j4Op|X0Lg~@TcvPtHrPH^GGY3ve& zO5r>?s>*l#8=b=X{O2nm&Mc!Dw?X_V;^uQ&jm1r+qVc$bqBubJKrh2X>#0vnQCnPK ze)=(m8xtLcY}`B=PF>t@D_!f~Ssr@bQRw|8a@_R_6YOigC|9Jvo}2`q?Y91_hLTPz z?kn49t$;I@TXeFDE2=D&O2M?UN!wl0FKE;r{*!ZOKE>sm%BpdETuqK&kR+|Ep5e6& zjBEv00g4@&zd)2&9nxg#;)(0m?9@Bkb-CbexShI_?x70j#+qvS>>1M3Qk!bw5`}n8 zmRZDW6hUtNm^lJdAkI8mhhQ_RW!SjBtWw)1v5qWb!e$w9t4W&7@-y#wqk7x-yh9cq zyW@|;uzfuPo3qFN;iKWPlM8g0u$S-I9Nd1-!Ova$lF>hV!w-I^TKw}*x|%Igpo@2X z&-ds!Q7W|=?dCMig;UhV9wwPRFMi}Ol|mn--gPRhj?y!_3)4MJxqn!?D^>ZA-}60E z$_zmq(=#|kE6&J7NW5UZC-WJpS2$&IGv@q2g9y%ftmK}8;xB3B<_ODt%drkR=K?B~ zTd{pZ@y)n@&Tmwm(^9WU6JC1kvx)F2BA<(S3Z){2Vx9~|L8d$MMBWhkl#6E~G<>QnMz3cqck#YI-?Mn)5*?PrUk4wR4x!|uChy_X&rI=|-&<aIf zsGdBzcs8+pbHr20im$%0ta2HFT-hY&i)xLyl8!f~?L!|OJNi$m%gni?zF^Ltnv$?k zP=zR9sJ|a5;(dV90ZN5=LiGU@Bb(KhB7)L2kt<)QEy(sbsmZ4G8`Po4j&k(CL8_HL zZ~<}KqE;*>L$WNlHd4wU-r%goTT3y3p<%de?}#)O7f70bVq8^vh|@V1lPvh|?|Pjb z-BkQ(X^($**VavT?*7Mu2ktmXF~Gn5EiVj?J#wUZ*M0op3-_+!GxzQ{@A`?KmRoQA zyfmA!|L~vvU*FwRrX4R}RE>g6Q*~n$U7hCQEX{0|gg3rlTg zYjw3{#{lcsZKBk*EBA%ldNs+x$CzD+8Q#&)+N&;8t;L$8wQ<$gH81-<`ioq9)A#;4 z-7h$K;IZikuDs|ByZNx#806Ls>zR@Z|YvDfA2xXBkP{VAsG9C`~4wLKHy)aZ{9vg`gaf zH9g$-=tybn?xTw*KmO7q2QSK=t1f4BSTQ@}s4dhHWhhk&G?o%TU{rvc2zuv!dv$&HN%x!=5 zX_Z_+-v0K>q_H&3k>j&J_WnQok&_$V{JZKO@A*0V(Bm~WjPB*?mtJ8|wcRwQb}>I* zrI=R9mb%Fnx{~a&BsYrsSgNq76z+E^4m?>mkl8X_}IyXmrD1|bLz$%I zT(U5_W8I_p;Mgl(^U79hX^HJuU+G%yHsA51Kk=E{KK-Y^Sz7CVs;`)3xG-EZ(x=8J zCS|a96BiEM_ZJ(kzvVOs&pdebH7_Y7iFU1qzH9vK)K9M4STs>t7};p#;xVV%4afQ8 z=SZ6tydkx@OS*TUJ6q<+7y1?mV8c3ut_tT)&IMQ9_)?*_e4s${dm8OFVYN${;vj^B zp!&f_U|`GcYdL%PPFk}IlsAl0=*5G=FwNa{X5U@zVU_Og{dRyOTXim z%TNB(Z+v+BDW)HprfefapH1M)+{4V zGLj@+0sJkuN~Oc$6_FL${cqL2%d?5_siIS9luMPBc0-6zCZ*t-7_TWxi@09XYe)Ni z!KEBKc%iqqo10Xmo}-K9Ys#U&Dhk>gLW2r&zgoJwx`2#AxlOS=L(qBzl~qtd7fxvw z8?zJ&-Aq50QYv(xUAK1hQ8hUHApN8FQW`xrzyILW4R3wlfBM{qf9<;0zm}IoTb)f> zv%%=_PTguHc65silQW_T()UcG12z*I8bcf@i_7LqGNVryIrT;+pmhH zQ6=Fps7g+DQWb_b?&RG5&oO=O6q`mjU1THn$mak}sMh=g3KiKO{ca-*k8~4eNIp3PV*{ni`Y2hNZ2e+ZIZL{L=$p%zpHz zU)4ALPrvnv?VI|_Y#6Zzf9p?znd2GP-BfS`TdLuQKXB*gzU@8V{(Zds`8N-qJNCZ$ z$3A%7OlxsVnAWH-OydKGBBUoAb=AVCSRF~ItGLXn#bzDl8w6&FYB8fAB1zm*#$+n- znXWBfC@;*jXK|iA14HZIRjE42l!_9Dp;WuO#gt3=Ehb42vxGLOh<8{5y1KQh zH)m9-Cp3*_ZS$F_+U9Cw@=d{+BUJm=&Q=CTA1o(uU*wG;q#wuM(-AMP4rqGX4 z-9VW4RWk>s%7&3m)SBanYmml5Askf2>aYy-SD2VQYmVIaVfMVF`@d}4apgz$KlbpE zy;oeRAANNH$~Br3Aa!mgsw}8Duh2D+xQ-*e0>4Z+&IrFjdA4umSnXeD1R`|aLem+d z+JrPHclV>!8a#$4l-w%>`dqL=$PhmVQTTq2+}YKdKWdBRH1JWEl=?R+wqFHj4|QJ8 zbR@uXpjKEeLfg|`%(!@JNx9imEKaBNbhp;yptNSk7gRX#rg&jaBFU8U9qN;!lK_|b zuYz;ny}~V<{knWszH`T@;1$kCX1`d@!cUHHuZ_(*@Hwv|nLv&aAV z&%=lAydXDRqvWb<_L@8IymS29zVpq0%f^kLY~KBa*Uj5H4U>?#8WLu0G%b04nsiX9-FP&H1(}s4fXqM5xM?Dt!=@AuNJYGI8jj+;`W*et!HSNgdrE zRxZzy_c0jS{m2M+?m0(<+ZP(-t($o_?z#) z_0+)!KYriC`+xGv%XWlSeO8M7{j?{tuv*nwvwixx^@D%&SH9Hyj zZhJ|yHA`llkD{U`0ZOI(m??v`DM7i1sMyWI#iJ}uPt&)42T+8;bt5$KRwBx1;#g5CRB|p@+NMwxL@g17b+n3!8%>Hq7gGQg(?v%CzURWG|n zJ@T1->{`E};F_9$O;8WY4E9x3}358n@hp@&zulb)MQO@aof6j;(A(%`ec%*t3=dTK&+fX zoUS6PM7J+(&&F4ZXA|L5#4@}%P1D?>gn-ni_^d^xh_-3VYy5u*#QzS;gYuaTFimH5 zPyZm{njzwHkyt!|50vpHpHY}1&U-|myzz|Y zJ@wkSnVvjN0nN@WS4!5zN2ZHR35oMWh3FD^=Gi3pbw%D*Hh{+j0X}JfZ=qE}=3)v_ z+x+9-{)xQfUGMRtH{e)D5Ehiy1zBD+qBMwB4n42_hO&e~|_K-5-L&qt!lMvN~9?S+;E zDnQ{tav4NtZKnz(2Z=cFE^oVvgRU|XrK0M`CR|`Ey1uY*&#(RW=e1w_!oC0L(1V|Q z?=`P|iDPm;_}GVTWlcX^{k)B;wQzyW+t-NF4AlK3L)Tt!+4Ova^aq$oXvHvJQ%QS? z>BT8!X;COSy1EN=^>pTWl52dTGVlVabX0Ld2qQZEeuawY8Xl$GJI>^66P1dNQ!%YX z+1N6WidiorW7=m*X(L`7g24&+uPR^tY%IsKiSQ}HpwP--6N@(nr9DYzNu49{q7Xxt z2G=R?QKBbTkEQcyEX^a%W8)^SImhAsAHubk z=qU`SwQJWxS<^i@0)smQHKI0+yg2|Xi%XB#Glw4v21-$(Z~a!8tIa9#iZpJ>#vNPL z#p5T<`q9mPZtlo`*?sNqqqhCLzp^wAW2#ps>7?&pQ`J!w;#tt0_K~wW_#p?(=uS20 z(GI$*h-)Qk{=&T5G`d+AcRc6bkN?VVFTC`+uC=Y2#S|1tyG46pinZ%6gCqr`(E&h$ z9^OE;XM~wkQ*7Urp(;8TKrZzX_K(2CJQ7dpL!bI%_P+5y{m(0|c+MvtIdFLC$}6_2 zIF1DsQ7V@SLZceZx>PE??(*GNqEd@(CzPWSscRYW&Q;1q+TP;63@7Rm*#F5m@o&vF z^D;{GiQ>%5hOT)|GKCn!9HnAlyo4@w75CaVeLt+*+N~&9()pHm-BK=gsU(&>8DcSl zR*7+h#rH9JX3N;&d$W&-l7)8E_H^D)o5<=*X!*P81%&(J2`{ zj8>sJQImzmMHN*?c<9cB5B$#EKk%YEKJd%$f6)uC7b?T*Q~$sBE3J?%J9<^q!D4e! z)@@#^%7cAEe-->>AZP9r(PcS%;j~H`F?Kel7T4+DGs4y@cT?zD4>kj5E(r|yH1}N+ z2Rh0VU{uU?-`Y*mM#_Z~=Q;M!IVLYOmC{uf+E(J&Nh221vXFVHJ90F;h{bD%)j3ec zd%^SUy!>m4XA|L5gi;z~G+CUYgAfxb9E#X^7MI!-!icQRB2olN6}dtRQ*%>lolOaV z)OtJ>G^O0nu%lACya__JXALn?TTB+-iw0m!S?K;+7`}P3&V5mc#P;-Wqs9+T7f^?S?jcWdcouAy=s_C?= zYvdo&_T1e*3!Msk>Fet?ix>ldN>i)v1w!8D_Rp%&tcovxEV4LZ+r|<74}bna zdD)Aft?feX<A#^atV1qI4y-8MYBaO;vG=1jG>ASq;_s2exZ7w9a z0e*o*>+{(J?nXZm^g-d(EOoRfeCPoLC=&q{>(up$LH}PP=P>4 zpyLqYxHXV1u=TpXS-$FP|Ge+1dk{HkT?3Mr6J%(zN0a2s7>l(EX`rhOF*`n`W8pfH zP!Iprr+>5f!Y4oS!tkbH+|A3(eSh{or?e2+OjGw3w zYmbyHh*T=Y>9JE}fi|5Z?K$YsQeO1wP6@CXh+QzLW=1F=l}pSAg@UlbiP8Pc7fVc> zJ^L^9O04dn0*Y95tQq(%}9lb?bptpEk?@*Gd?1;(V`*9{Ssi z)dpAiqC8WiG;@lfZ6V19!GQ7b(rsX3dY7-{z~0B1ES_Oluf%gx5Jq&gcVT@Wp|Ii1 zl$bs66y1GSzvt}Op%1!Vq#N}TU0FkQvSuAqqN7m#!2HxB@12{UW8H?g5|q`?3*C63 zrFZB7C;}Cd%A~26D)e>qyVIve)YX^mpnX-}TPug}{0(94rh(xV5LDU!*8kg|{obGRtH1e&^k06Bvw#17z4@YzH&HybW$)ofO?#ms8!}|g#n%Z$ z3tqkzbQy#ujs&rSY%UFXk9h1bd9wbk6D;mU}k!Oz55TaP^?l~RD@vy z*dhiSz(NsXgAD>hBa${ymLL!WO8l-6ErrFA{Nh37Lf{pm*CVv;O61V__ z-!!BU;EIIxW-Te#qEILtT$j;O<5X*vc*&~nfs-T0|ExaW_=4Lv z@bg$@GoG}f>BcE!f?KZ$llXKw21^V9*sWLI2+P*}P1QR9^;*^l(q2=xsJ2)`q++O6 zA)f=AP_~7W0+B=J+bFbmQL0vm8)b5>Z3!*a_sO)iiN(^C?QPG>URl`22gL+OD{(vrm|4lJttp9EuCuXGV5y9~|27 zLv*$M;>5_Yr$-M>vvSRiPO4^g5J#w*26>K*@O9^#|5{*p4it=dNfE{hh~kj;wgN+g z%f!(`FWSlDFQ`>p`c_cO{mI!U?s}6BODwy1nKu)UCoQ)bqh|m1M=-~&@lufp^#mRK^L(2fRA<@LRnWRLH^}&J-Av`?F z@gt+0JUC5d+951i!m5D?Vm~I6btsien5oH}N6dYn`e=0Pf4lu}mXGdz|J);AusUjp z=-hHPA~BrRBH^gS4uMIm*H)}>?a-x{*j;x&ESIfWajdny{cT5%?Adnn&%Z|-jGvie^2{`qO2GW0qEbt0LKcXc)lzh#EEm=jL5oO9LM=t0L|koX zFNk;mCv(4X9AS{!BGJwAuf-yobAl2slt%vzaRCUwNm$3?I1t5kgcIY&F%flYT46Ml z$4;BxmNsT4;y)_5`aRuUomm~YCa5jSY>RKBS;PzXKgsy1(_DPTRro!tL8L%OAS}j- zo9waVCM1N1u*vQ<3>;FKPI{IV5W2yU@EOidA17=qu*o;12bW`Iibm*??_UN%4b%dN z5<{I?rbZ7jH8Uf+>@u5KxxvoPS3JK3-Mw__4Pw5lHJXmfetV`RZW#NL?%uh_mxu}u z4kj=*mv$($IaX!6-OS1jCvXd&EDIOhlvgU1e2hXm4mu188#O2|KwBTE7>fdH5snWw z&p^*GN006zs+P!gwUML&Svq_Bm_9y9i{r5{H>HD9d)##A((li>@pGWX<4-)t=2af? zfyZCl)m6sn&WVZfGp?B2&*17UmbPv!(r4}N=lWgJPyx~S@T_q`=5RGugwr7O6=;D>Sw74i6N4|Pp_iYmRy{Njt%cm1X8j(f|7c7h%IK$lOMS=wgXB@(+B8rlcR8K%l zOO{%#Dr$`e$BynP^rm|#n=&9i*0OQi|L8pa{POzLsF_*RB3XG-pquXNTA~7pvI?1o z&6@`?XXnJ?EQrj^(zB(~>YIP)O}2XEMR#)Kn7!eWH5@)PDi#_MYq#`pYOzQyZsnTS z{RG*84d4_ALXC7Id?!Qul0HgvV^n5l5|W*95z1lgz$|mepJ!pA!oqxwI079v0WL~z z34w;#CYOU&i4eGs6RuDr#0H@e^)S*w?0SKci?NkIp14j(p$t|x_G1Es6^W;5uF}>?4P$jTsq^;mmM{>>!v1#`t48n2nQyHvHV=Z(Kt!DG3 zJLvB2X5#D&XO54c=VlR(gX?%niN!BK%K&7$s0S{+gDdDC?BvYEh*&svlqJK0vw;Vwl3hpC#RSSuY*} zG5_WjYlb>Tj~v&VFS<;xxb)IoCKF!Yw=_c>hcZ?TJ3F}-JNhJeC8v9Rue)q8rB01J zY3Fu-=_iRt_x1IquRJ}mTMsPhkgHb@iT?r+_iqmYN-C5SVPt?50qfVSc1QN_)T@TG zx#h#&-PN66_>)6BKcCC`3u^V%o21*<=`c4{oW zabd||Cqbxiq|4moWY%fS5?1HEPkiX(wT`V<|LyR`Efl&sw3Ub`0;^5)h!av;Xz-oH zMWwg5MVvS}Aq?1sN-=Z!O;=k)!06F^?6_nzr%sQF*!9@7V=Fe@OTKFzTW|eAvI7?p zMj0#x+*E6F4dUUYvlQ~}q*FOuCxr?iC`-;9tuVTOnuYN?VG+VI)EA*T54A;zYM=v% z>q*tLRufdKP^mzdLjSSQfNCd z2O+i|TDRd4%q+6+sfT&t&VPit5pZf?BV=rlHit2JVg->3(INszgS3g*u;`&}`6f1P zyp-W3{Y;LZV*d+IVan6^tuBZKFbfb=v9V7!zZqkeA^ietHm#yuJ}XKyqZBe3F*|kw z22*x$jW0`!W45)sMYOfKL{YLcmD0f)OV9|ZRzt!twyr=7uU)FoHX?86vKvoR)&Jla zmu|=9s2h?k%s&I_aUfC7*@H z_`AoR`aHQ*N%+2`(9$h%3W!`M!gYZV6PG~OsTWJs7eP0`HhiLrgARRkm=Hf2b;#!- zosl-1gZcSI9(!oloD;(QWYNe}7q}gN-n(|o?v7>4yumf?I^Tj2+S-(3k;Y)-kV4j@ zQH5<=1jcB)@5r1j#)xeWh}@oTX8g1Qkh8g|I=B_#+4# z&Lr9{g_MB?1K6*f7(k?-F5 z1^-I&`hWTO&v(Utn?uNRb|n%+3MFzxqCibML{5q)ckZ=;S<6vT}QGnBwNHYmDE}tTob_wU}9N%?- zXTJIU*|usAhlmabUsSZjz> z%zsS}!i zMb}W9Xz9!1rX(nZ<0K5+qx<(mEzG06-l`TXT{|#nCJ(J{&x9=L$xF|*w6=GEaFaf* zFd*uC~trvpn;}bM~F@ z{66Q-&wO5`x83klwq+T^t2W6iuGnIu03o!tD9HMt!!j8UHm%*vsnb(pDnMLz>vq~- zf0L*kc~M9av2)iUQD|Sv(8kNi_O7OD({;E5+ffx4bc(QE$D=_$t#ND(Dszq(6RN< zp&B`&8lgfXJp9yGL^}IFl;f~as~ee0;rglb8@R7KyRQJl3!wKe$Auo@{}rbBuSV;T zMxz2IZt9I10vY4k2(3aQ6EnDet9|r^UCxbfxJ2zcu={N_>7d34u zkMi*;c8;9E0G-_(EL}Q8M^7)#vVlY{BeR;E&M-G}gkZ6bcFu}yx)qu27M1EET|+CW z7p+hvzGdfV=GiPX>R2hEuQw(72UoO~wHs`k<2h3kN6mo;-*4Bfd(+RPm*2c0-MRG53#U$%dX^13Q!}&r z^O@IO_l7@t{_YR`^3wL!Xzl72|H#oYje4R-oykBh50!T?NO|``M)n+HbYzT5IV7ltI8xvU zi#A||Al90=De1+4LoK#6VhEJAQSvBaZR6N_9=`LaO{L#t9iMWo zAu{>ARn`#2$+fF(q67sRgCvR+T5Ggv&WykXF#H$d0uX+a&_x_Of{AT17x zSjPlfvourS(yMRO&+gjeY}|VF@e@b(-ZVWIKH_#dEyALt(5~-cJx^Nc2tjBm*5-MB z=4lQ-{~XduENvX8sj386?O{n{04*w1GzjhB>A{3{x}H%$%9y;_I&=oAaqOrU-+WLM}&dS44Z8!uQi0J~VH8 zy1;jH0_*DspE%^*bjJ_Qw`{%k7wdcOjc?P7_6(HkvD?Bdq5m z!U(d)Fh72Z?#*2gD3A(=MWD=yV+RQ;0ci(}0vUmHd}^g2nIjINv{)8hE!|@B>?zti z=lY=0TgXIHy0N&__hLLDY@xjie`q~8eV_!g|00&HoagAS$H?YV!mZbAzQ5Ossgp7) zjoIfO{HJ*PmGMpKb$2}6(bs=%X?CL4T4;Nv88GMW75|w%5MRlUUAJ<`89%Z|uUg;p z)66{krw1PU5F$LKd)r!FDU3aJ_9Wxws@QtS`4JzcOcf8Yl<^vxhv-O7mHE{UgYaY4l!<(f~j2M|b!>X-AT>GB4Gye2_U>lq~b&}N=uVd+!%b;xq zHu4cp4ijr6K_ZW)0|*<;AK$}~T|1dQK1OvW8F{d=hernANz8;BVI6A)k+Q^b!ZA=r zpbUiCkboUT+My8}8d}hZuwf(!log>7vBmSO<34E+w*;Y$grj99+hUYSoHZIzoN%3* zE*s}ELltXcrO-+xqZAk7UyKVt_)WrUjYcqWcIp)+2IE?UHKa_0Zv*0}gkvM5@%7OI zM_g%mu~H9jn$q@RI#Y#|wJMtuuE@AHmG-PQS_mnyv7r`Qq+stR4Cfmx7(*jYE`Vcu#}Nmn$hD5q-kE2^>V8%%U(X9;yC?;khwgrq zo8I&)Ji3q>!(w!rMx{hYA6$C#cDrN8qNvQqOrNgnuReUz>Dzb-o8I-)KlJ>)_s;IP zbgT3H{ZHzwzl7t(wA|dX&Q#Um(*^C4O}n;UE!s#S{Gh>^1H0&6u^eOp2%$8>sYB0k z?7%VnAQAG$LcJcMOu`B@8cYn6V~ea*10o+q5ClEgpjVdWrrdrxSgFooL|u4oZJ^UY z8ZCSr716ip8YWI2XJTQVrPo|3YKvv^-K%VmVyL%|wrs|(-Fh)QpM283 z{+(}?d!KnW-164<-Znik_4xSFr-nO-qT!`2UMOoK)7@rGF2{oOx%OS}VCIPjnHxJw zqyt)(EobRv*Fw(C3 zaJ338Q54gNLWJXBjBW~xpA)ASD67#b$q1Fv|1V4Ezhqnh!fz7BBy)rHMjdzw2yLP& zOlTFpfmry-3j#cZlEQJdaCgpEq8qFA;NkvuzYxSC4vp|K%G#7KZOU;3UP6&R=eH-C zgc2dnfnw9By{R4#B>rJWAdEflEhfY(iT{b3hNe0@P4UbOGbc{c(UwC+(AnNXC?X!Z z`vGovk^495qUzBK3y!=!Mb8}bh6oN3|X8Shw0NWyb4N_j2+y?$-{>cVWKQ$n-p=S zlCqbv9>#zmrc&0h7?LtVQ=E0^tt?IJU@xI<^&E@mfa5!fE~D{5WD_tHignwsV%H1z zbL{XwR&TzTm6vpjxx*v2sB1*kdH=pIzCV5y>8sP5@3^NrGj@yTrp)lF_44%TQKOqF zxgqIciSs0%|LE2Dt%sBnDLe!oLK)U9U*?XD?o(G>w(3p#)Z-t0;m-GwW8Ajn`{ne) zf^`e6LZtGTT8WI`Ldq|IaY;E2(r6Ht#=Teg9<3^x>`edW^JQBPf)Fi zFoI$9ld?%5yn#{D5g~%{#|;?Hj-P$A13$J%2Lw=ySUt8Qy-)8Wh?pSBoWU zm$3QDS2Oz1Lp*i&Q@rtY8#y+0nk7TaiNZR*>w=E3^+^OCL=_ef9$?oqk1{iHil7Qn zHQCIWI60I8W0JW{WejnY$P}6;;Ds^7S`cXn4K!jws0FdLgc=)0mQWcH#nOZtqonIw z={{kkcZ(6SVZlLo+6qY=C7T3o1vb{iT7!;J+MWkOjl~$9RG2Pgg#T(>0K#t))_^va zhDwHS&q0lC-W(;C$U;mW2rx3hT7~ZmCB2NR8t%@8TKy)O@*l_;(V7<`&TH-FVw&QX*l(mn3`4AJQV0f^{oH$Xf-tmq%{p^_+k9_KVfA)Uo zhkxUDbR~-LoB&K6hrl{0jF4lsx}{dvi9n9PhOrWhXJ(isTR8gp5mwxCAW05osbf z!a6?LC4;n_>1S%}Bujhy$#e|Sb@9cb(A8>B>^W@PiZk9)zG*nl0Dddgt_s z#kU+edcdq+yFrXiOxZZl_@0A6B%1x-WA_mAO}}mlqmZ1JVrhTBGd8kUEnm}pb9CnM z&p-0Tzoj=@(H-sW&WYKw6{!Lj-E`nRc)S-*c1n$Ag*46Ew;p_zt#G z$EXl&J(6w!rJ2=1txVmEgpL(jH8+z^QeK=oeu4up?n5g}9BZs`&{|=!7?aG>#W6@n z5HyumvU%{_H02U_F7t2x!5^BT7Vy)*@Y8lSuHZQyLc~ZD>B+O>PD@Z7%MY%+R81az zPd(M~e`agd)+=9ivt@9J7`gjveC@6$*|s^u^yCySg2}Pt*tr?j_4Yt^5FzT!?-^nA zz(Gci9>7Ksl~S{sVG~s0EQRG-3!f#8%i? zK@eLJYZOAbS~$`=-UqdmKVb!03mlNzh?ff6=dN|FG+M>PI!;WqFT}qq{;SdDzHMO; zC_srUu}Bk1pU{yM!+==$%BI>J%e8vY9l4cA);q$xHqrJ5F%s-e-aHVBh4 z$;*#W2?8Yv6@;-&cEd5mQF5rroL#Lh`7m#P@2zIlMLlB4sx{Aubb6pvtN!z1HS~V|=YLVBoGLB( z2qO~Dv*!L6BfTS9xQ$Xt$(1YCCZ#M_l9F)z$YB^g#Q5@++pX0{p z#PtH};yNj6HK>7ir_#w?s&fZoA`?KyRKJW)|`Gx!6+`F>tgN3wVvAjS!n?d*$Ax#!V)KOkB&CEYjJ<`kpQMwu=yy6Fu9 z-=iKkutMUca^Pp0sskcP=dGqTH^cZDpcfPU`eG)f@=8V1Xn=IFUEKv1=4+-@gmfx@{|Eo-ugq`% z)^9mpI)xBEsuALuGL6z{uDb3Lq*rC4a%SO8zwS}X&ppY5pZGLi{?wi9dUz-0@c=hSK_fAVFcIk3K}R03 zl1X_}3F?te#vlSiHA=4Ss&c3+s478KC(o-2TUXecvZ5YaLQNbQ+z3Y-H}zx2aeh<@ zsTD$Mgf=2+j~J2)(aYz5FDS=+>v16?{5QtAo%Somn+37(F~T5)!9gNZ9t|rH*3(Wl z>+}xvjXw0ilb3H?*ZMbg-~NQo2&yrvvw%wtD;#YdA5tkVF~1SEX#r)C)*@t5E=tOD z0@*Buo}10n`lXb`Hm?X_Emj${RJcuRvqqF)h791z`*+ip?_+M}EH6Ct2wSeWm}Nsl z1c8#*{=gfoo@!jZX8X3kX3h0KvFq+5(YEWZaQ8g_F%<+2GF{hFo(;M2)wkLwp1n`> zFI{os*y-I5&&&q5FIkq=Z7n#pN`SF2J~G2IJWLqIs6_``^D(i(Gfgq3cD<+}tATJNsCiK26((S3yPNN(V!Vy3MeB)i!1h z@8jg*<8&=shx9XO>)^Myiw&1;u_t$rh*c_fKl_p2Q$M_<|A&_>+3>_{vHZ_Yrqj*m zQ>s>};)s{XcHhh4I&RW0!jeh3=%{K^6d|sC@btc~r87*$L(2-@Vrj+(ZjSA*f2Saq zCp^8AnfW=aameLziE~020}jNB>0LY7`}7&o2CxOFg=k>`p>-UAK}O|>(3SYG&Rb7{?E?kjc{^`=mM{Zkn!v-+1{n8)*g&5nnfG%S_ z0gE#Y5ro*;u^CaRK(^Cx->2@QSQW%IXd^>L<%wfWxvmhxLs>(+iFNHdnPlSxfiqB5_^#b}>Ly8&Ilh+X$=;VwWfugb@UhBnlyjAc_o8 zWC#OI7-*vA5r^jdaV|@YLqilAQ~+@URFFtD#ZgjnnmARq3u8qq79p6zJpb@+d-UKD zVT~1wlVdooSW*i=RNeozr?%a3?ea$-xl65I)9-c`(kv{NNM%}4#t5j6eiH%_E$Hlx_jz+c?(H&~a2%EY4NYDsh%Dv4XiNj_uz?eZE9ktq}(X)m)e7 z)@K|iRSgxt)JN{G=EilyuXY$Nm)qcgA zjrC&>?{w0Q+gdlTjw@5s_Tzu`Au+OZ0V>!un4y6-J32CA$42KxX&x&gm>;*)rYugy zlG8o}Km;ash{F^?;1L84^+fuNdI&*iX@pP4V&S5M zuVdkxSo)5_b&Z?)ymeBSXdz$F!gXUDqYzdZh_xX$idY*Wm5^YRR+z-s^g?_a;sOx< zJHv|Ps73*`P*DwN0->N9SgNt6p(56-S*uT-9ut*nT`pU-{-d*Hed$zH?k$O&H&u6K zB@(LIz}6Z@)EipV>e^Q7mP*}HZD?xsm_}Vut7{r{P0+AJ4NFuv$q^XB@av8Mf)K(0 zR70Qxku>!U!~u4C9HMev^yV^V{Xn1e%CPg^!)Elk1GHuHV*Jc;$kyV_KzQlg(Ys!} z{s(S;)xM(>>hS4?y!Bo05!S|J-5eROU@Fy!w)WopCZ?i^ay52V3=LUqQabXDM_d+| zx{Hi6IKst|N&oYu(vHN4b80SWf{N zxxZ*jTRgPLrrqQwV_$BY^*tB@!Z;$8Nwa)-nLK)Wuj*OezBZiN`8!|!;$N_O$aM^5 zJ6o)9`SouR^lk>X1*}JTb`hco&xy%)WS}%pG%?BJ_dUSKzGKXtimA_nt^rdqb7KMR znL$W*sgz#;n^9KzR2M>AGFS_5Oa3r8;rMr&Vm2ttjWLZezOU)3m4MfYE}>CM5>dtUHcYind* ze_Y&o!n^CQ?_zO(jckOe&Le#3I6E%AL~hR3kK1 zA{En!1=WV6Tz4tgp{7VcZLkYyts$0S`Bw6+NdYD*X!BBhA6CejLJ463P9oMeUn3Cb7$f$=?h zg@5-%&V5mniwJ2txvPer?tHn#3@u>y3V_^8;*qplbY)Svr>Dgd( za>2Uu6=W?Gs!|uG+AyM0*S1pEwp`aXA)+KZ>RJem0P2lIl|HB?J;6BQd>>Ia$tT8w zI`6$^krL|&?2;vj)oY+{Nk_ctqAhau(3Wy#7SW%}$Rp34(vN@f0Xp(+1aagkQB`f- zQOCl8`@XjQrtLqsd}Y6R;LZ=&YhQhZEY)k=@T%MF?Ch+wY}xWf7rr<(F;81p*5uj{ z*$jlW2o*V?Q@F05*b|DE4iL>Uus}$G6oNQbxPYu>2<8MfbU^!o5-s3%E?89{u1g!& zj0kHDinC{c2E+}d1>eaNS8I^!WZi}s|EE~aaY4C7NVLd$uxaiwm7xNzF>d*4}adeecrE^M|RzrZt*kj;E+1; z$n)NPpZuz=jfKK3q4FXl^J&*HiU4^>+^9pR8^C zNEq>p25*@oH4doesD^N`(v?_Og5xG;FRp+T2u~!u1r;Qjsq_;!n7%>CWFXgq&H9Lf zo3^tv0RzhltX#R=#$l*cfLL76-kD0Jy6zo6edVz~x&QL43_mnD*y&84omWqN^(lAr z6&Ks?;a0aH7IdMf)v48X{>8TKeVd(u?LTt#{(H^l8?Sax@7|>%9oXK^cJ{x>r)H)X ze&UiV+T@xo(jIx3M zEz!xDakg$K_{&+5ex zzr6!Tx*#oEuDVKm<=7|f%D$W^hy@<{@LzJ%um0tq4=&&E&__S{nZ@_K>-)qPzjUuv zS|k1imv1TmWA~Cl5PZ|uB!*`mdys3dyxiHpcdzcfV)(~`y`Oy5=>rd_OSUa>#>;g( zu=!@ubMf`WB1MpjiK?^YQU+I9!V=`O9-~j~`Fq%tsea@NjQ ztt8)7NBd(7^A(&Wt)bC^s0!03rpapLz}Tiqwzdi2nR8=S$@Ap8F@%+{`SpKW zkMKfI@EgYkAp9012!gKzLJLBnO(L-*ltEcY`-w2`Y_Vp%bQ_^HPFgzkNVtDluU9^- z9r@!a>HM4{>=KN|u?ok6FVT*RbsdE3ATm;rN~OrAbL7&76>HiUTG>T+PXTQ!4R^1$LkN?clVdZlqr37 z#k%Ef)5VGS!7o1UU2^?Kde;m(3+1zB*~(#4FOIx7Ixw+e?Q3p*%ZUe`nrP{4bFaGm zGL=Pf`*pWHad70JedWdCMax(A>-L;+o_=)Fmdka~*5Z?r9*stXH4J3&kn9AKsuIY=7#-0`hr=*Q^oahfdfHYlfXi9)B#}{OFeldu|%|-Hdd8I<|;v zJ@}rkHwkOF_PQ&@q352^n=iY#hqEvK&SPKsD60kw(obha965I7rmHZboe+iRLE3YY z>{^2lEKHSHoQo;X*Ki^*4Tu9vP&ddBJdv_9^@-FHkkd4@^?YFedr_I8KxYd%NKJD_2lk7_;eAuQ++O!ssL)*qTi(965E0=U%vPv;A>3sF$_dBO{oyDs`K@#_N^m`NIbEi+8 z3g7g`_q=)cNSyKR{D;rR1B2$xSKe~_)wSJE{n+IA)EhdN3>93jN@t72RwBlBO)xvV zU@8@bCS$E^L0V}usVuovOhrW^j;shmXedMk0)bE%81Jy9dAxKHtTAM z(;Q?Dg(0rRkckP>%E}Y7Ry9H<(k_kaf=qb=PZ)e@g>hqAmb9_*qDwh7J;(f9ed6rl zLyzsz_rqt;#?6`8pMY2_>C!aXzbWa`^ zSKV~296!8I^!E41nU?s9h25Xnz2e%}zV+;bFFt$%b{Lp8pCXyPjmtP&dMn z31AkwS+{v3qkE3hh-|5$mul>?BuVj~-hpMD~$a#?Rh$Yl9l&xT5`BP^({=VP5 zta$yB48^b$?YOd#@%7eAFXR4)o^Wq}!y8Zh_g}yJGTalNeAVkNdDH7|*lHepevf_n zs}IN>S6oW4xZvel8mgnUwP$|s*B)E4dE-y4A6x$SSqdh9``et?h4oLoc=+Srzjj;U zHKqEL>RaC8UbHo~d!MU_#d%FSMZ(xgx`kM2lTw%kjcrzTl8r(T1R@L->3l1Q)Tq&b z^v-tmb}eKx`Ofm}to0j`*0d)^5ALUT`*n#Hq?^Ksrn`Yvkn_2C^G5bOx0mUC2kBk8 z5;9qcL&WkWw00CkwNbX)cC458K72qGPw#7KZyk7T#*-gRyF&6ZEz&4pksqo z8ryUsYtLb?*s+?C7x&uE?oN02o-^UmWBlsH*J~!vp44x?4LAPiwyPzd|MG**4exrJ8gpv= z?VtXU{iXl?hpgRvxr|Ot@dv;C2WN_A>`bQ1e5n>M@RRTTTM%+r{XpRSz_1Id@i)H5HgcD()!xCxrWg#F|yTlOdFV7RZ*T*a=tX% zSjZJ}PW$D1CcMqsxg*t%XXH>u~Irh6H{AQARIkJYU3p! zBr2}srzE&_2ujE}zztyk6Ni~TI*mvPmTz1^%i0ZW+_;|m?|ELV*@*4w5aQW~?&8)B zSHIoU@dqD%=y7x7P1k-)6!q`4eD}X>yz0x_Z+WL#d)4|4>iO|AT)e$cmTDoZ zH>?tPt+;N4D^h?&$~4#+MxK3yh1mt-NFYQOiKSkTQ8832;QLTqgyn6CXnH1-vBqzK zK%cNt9p3|bmmSFFdNKH@Ahgm&q*KYzxmJk+3)V+lA7c%e2x%afhDg9wmw0%-D<&pQ zJUqP0J96lSKmNs^c*~KRn#IP8Tyw>a_m4jD(|uxra{t%4@E_?oZ~d!zb>0K)&hwZ`UQKgrABqvWIG0H(xtCYWgc@dG2eU z7PvLJbX7aI{J?AN-~9b+OAmkUKq=*PQ4edR^Eo0EwXo4-i$@eIRj}Z?0>@e$oisPK z6ppcgaICQyi_povKqgjHHqkCR?~){vYvUz5rB||*<$2kEi+tHMv-zGaSA2KH1t9zm zg%A!1CmDVf5@SWPhXu)QFlmZw0gfv%ga~b{1+9gPk}i=&m{`e-=hM}{M2lEeqBz31 z?!2^y7{lh(>k!spg~UpM6%Zp3jwE+wz}b>=PMtLi!N~GBH7Esm#8jLka>DXLHn@sf#PNL-*QEzbQGoOw&^rud0(if+k ztnFxPVIin6xme=Zk-cnMIRx1jQrQ%+0Q2J%PaL2$vp~uM5iCv>39V(OIM4F4bM&_K z<7MFNHAWy>cj!^kepZZI5JOYn#}u z#L6O2=jY_$oB*=Kl@cK&q0&@w@o;dgN~HF!M7Y>OF0XUh48oO^=I4b~mbR7_zzAO} zj*J`=zE7~661+NNDnrrX)F@f79?c^Cg@OK|GYd73z zOD09#kBA+ECDtGO*yCiKb*#JbXFv9ZkN?%-Xr}zdEw@}UaQmw_n@67CFBU2ksog%P%_d&g-sPHkk23-LtaK8CX)Z zr;Z}hLMAr?E78r~$hnO0oYIU^#`?LGEp!jiNVlFj{@9bVr}sSVUVZUOMaS?1p5J$e zaHdG-QnVC2d!k$u$42+Ce0&9kHJboMG2B4_ck$CJs}T1`vq%o&6hs+ zMH?%royHg|S7y2XM_(&(3NAD}r11eC91r8CXw1q>`)79k_OE<;?a9R_KY8+@~MQwQc$JfBNTZfB(LFAOG>K>+P2_ zOVh&ED)!RLSBX<2$E`pKtlt#bcCbRDEy=D~B(!>K!Es$%XzwK3(R;Xf{1~^t=4Pf& z?uWrEzASRR6{RTXFtq(E1~@r$1{EmwKl2P%t{Q^rDUR)Wn(5g`tnb{JVEKH3d!WDHkuILpnK6yVYu71l~Uw_9fe~_rOzU;hytGa7n4}Rxh z_S?yI5C%jb9mY9mDySA2!W45KGLrzXqXzd+J2H+e&5zbUq2o~A-#A8%u%cy!H z!lP7Ekw`g2N@0uyo9M7E?dzhDc9;%hqg_Y#4X^*|!*_mZapx0HI#*n}O+#i%XIsam z@3cD3O9Ja)(Z)qfL8LUHQW&N2!lcZ)tT%C~c=C~by034k``in={_54YT=#`7m#q8U z2R`|?zuwyGvEv8cuFR>!-beoN^TZ3-ts7jfyk>(vb@-5+997S~@n_%jn{WKk_18=v zAA8lnnyzJq*6tXuFY6Bj!0+PKufIWqKrrA2ZSc3kZU0&vtTSzB$WjW>`LhJvqA z)l;;jrWv^GQc-<=T>i!TKV>Tmv60?Veeq@AN6U%p&ccE5PS z4lU`xHPX%G(|YKVK4*4f?)Tbr!Oj2sAO6p~AAbKI{jc`k)xV2xO?zLKOE1lcz0Wj| zHbzRPX?Nsej3Q{N&7?`xMEVDpQnea6uxw9haUb~`uCu@R-gnC%u1%j=HPG{@=civ6 zS1P)%v&BhkD3xKdafZrMPqSE>Bbuq>1{o^F21*I6lemDp*+kl{5d)FIF)r0vh0}o9 z;}zT2+A2r(>}TQ3^A~k2U2+LJyVKZ|l#VpBv$M3fxBn~WU%u>LICA(X0753Sh*l;# zvdD8n0x#*tCcV>SjhyTKEnB|q73=EjrxwfQYVukWU|r!N-54XLr41%bTS2^P=Jv2y%N#itJWAqGzvYULbZ-2+^d z3TT8STDnp!Te%Y4E<%;kDW_%fwQn3egqMAhOy7Qj;HkBjU3K~^PaM&E4tV z`JWeu_mAm@@+pRvlCqRlOl&o$PM^WV3TY)$I_J;Np^;-r5A1H3lOMg6@k(MYaO(8FvehPbJCfnpIjtx z@xeqaPB+BhrU4t*0#%wFbvvl8wXxVKQyI}{G{|PN-%@E*SepG@fwbQN*8nTg22yFC z`yPD6yzZtg(3o3Yo;giE2aTvq(_kK40Yu=$j6C-QCk~I`Sr1*;=*VIsP_ZD=CQ*6O z60ISqhqPrt=m=#advbo>86Ms-<}P3Mm}3p?{maa2-trE4_rs5oUa{g!ZGD|TAc9tL ze7s0+w`=E0S}2te#xOvvi5t+<3OjbJCkiW!9V^S0!E8O(-4Q+U*gX$>c`xADOoO?XY1(uaN07yY}uAseFoUH*K_mKiHRPX=QmEv6G4fo)koyg~~#;T5Z#1E(gn>o}CBrYV++q&-QdwG{`4Mm=GY8zfN_C5-51NPCWT>tL-x z*y!ul)Hxtj=f@*1j7EIt;{p(VhvKCL93}jF_07LG){0l|^$q8S3>@u}OBV8e&{nldz1Bbp}jp% zrCKDNajDi8OkZD@&gNX;JxIqG$bw2;oGs7G~t$1~s)Iiv1eaoo1# z0^*r5(cRg`_FHy{*}Ws2*gawg2l_>^*l^niyVTGYnK8!v@xqjz*z?fyX6yFNvd}8+ zl3~f=gC-fy6KQlPklMk=V04TL5QvNpWY+0lvTWylANz;Bp=sr_pZ$z^+q>Q=Mn3aV z3M(%DnigG)hN-q7YM5L;sTLazb2A3l0XOC1dp=PVCUSG;8~}=!ZA2grV^Xe9WS~?F za8g>dv}4Cl9A`LIYtV-I`FXP0EUxSRt2ZV2O?x?siLyNBY9T;ci7*mz-hA>L3)H-< zGx@LehF;zql&DBhGjP*&Z!vB*6!Dout4qZ>)~@OilM|CT7Vz>w2#pG}FTTj(1BZ#~ z3T+@%2HTwVQ^pdT5TzYd?1HxF7+QK9d(*3K5J!)U=ra}M5^L|@^})ZYJo4!;IZ~zc zTYvb+O)dHgr0pZ2aHeuSJ$;3?qA4#bAxWI-J)J@*fi^K#z}AQ`Q8@qrVpB;(K~(Fy z7`k>1U-`fn>FRJ9J#{QKt>)jbdHZ^nU9(+{J@u&f;tPAwb?mw|h~Bn5PN7D{YtTB} zZQI*-(Am91&~>pTmj}1u!n}aG1z&Uwq)6(|7Fe+L@*ZYS?-BW^Zc|~+)=CXqnXB2c zgU^|u980Sxq};C8OS|m#!fl^hH$3>Y!Ohz~eeb=y?m0bvTuV>Tn$9^{8R#qlnY2U_ zp^Qr|#^0cX{*Ae2WPtdLunY zONT>8Ym0K-8f(|}$;E{^F*`jYO2x>nEErL*m2H>uMNg{&-vgNVSr z&wT8IvQRuVvAKWs<9nWc@%5pyCY|wIYvW{tttG~~L>3~F0e)jZ;3TqDFUtt6ZJGkx z#4VgaQ4NZA*-%JIc*GQ#O|8J-Dd{6M)o$MSj-bnz_8U!*a zlm5HcPO?^nm3Y2GOG}HGpO0)y!ReTu93Qr}&cKp&;<3l3X~|_FodFe~XC`^_!N-_C zTOyrGQK^Q|RD97o(W;FxXzPL!SffG1>a~M-sWiI}jtQF;oSmNfd{0j=YnSv{>1FxE zXYRCz4jqzT{^x3OZD;?3r%xXIKBX`!#1RhGlL!Zcj$$gauzkD3Ro7k3J)gOo<7W`V z>y^Fy=1ZOBTh^HQ%A~mGLx17s1@@vfowQ|AqO>?eY^vm2T3EN?B4P@{8@Lz>8zJ%q zgGOkrUbO9PouqtUAU(Tk&7g=&F!I6zwMvco zlBO0WGwzOojxLva19!6OlE3=4FPkGDX2beHdw9>23}ggvzkD?-(-EbG+D9sp_xg#6 zs@S+;n>~5_Sr!+-X%5m0M>fd^NhvxRQ;>&`2W)l_hM- zo<$mzmROTWqUbOrm%;Y+X2r;{F?IYTZlSy7>5UsV-tP;^j&0k`gn)9R&d>bJ&x)N- zet}h&-+tGjJ-ffp_s)vV>oa2Sk-Aj@$S}s#VC@Qc*PCzV%b&cLgGb=%H+0*}Z{9B4 z)|CC~{hto2Q1BQG9g=IAL? zJ~L}7Ge^Yqv9p(+*z@9NdsnU6xoPW;KlA)@gi3+q zeS;+Kn`zVj8=>+-2KXI`3qbf?9R{OA(lQ{;BB^K&Usv!%Bn_?>Qmop)>*?Pa+0Q$C z*CSW(?Xsmybo*eJ6fJ34jYDSUt9V`)`JN%s;d`vvnkSVjK%oQDg+wREz-^5wM%k-8f*r$;1lSWhK*6$;;S@m{j14$E2`7e+!+9$<3xP=Eij%X)!nzHwpd-*gUzut*fbYJ^Rm zJC1{t0;HGBfC?v>F*`qJ_VU5%Z(eSFSwe*{go& zr+@hOfASY9=~O|+VPv$Gr2Q0)D8LcTa;SxG4uTirKRPY|;df;uIiZ6=s4~9aAZ-^x zmx!#w^MpZ!Z%3LB=38Z;$fiTT1u&HaBI9{B~vYaNZU7?*M3!9n;G@>=< z+Np`r?tY<%gb?2p2)|xA=IbF#2nR>RxQ@ahz@d&55r_z+AQmpxNn=G8$biX$^_xd? z=2E=!onJZFcrF`MAOm7M%fkF3?XAn8I=!aRm}IceGh?TwWl)Dq#)ZjI_U?R|umX;? z=ukCX;$L!CkK(2%wsMH-inK6vw81skc8YRkJgztJTC!b#b=jtip8f0>?{Thr-4Ey} z*N)O<+VX9LRn3hz-r@Y?#}@S3%{TpTGxGfXd!K$v=K6%a`l?P5&1IOGsUTY5nwxge zyYXVC_Uz|@KYyCR0l0qiAd|CaIW|8_XLlck643}^QrWao<~$$QY!3cH>;jF)!Vw0RwKl?qGO z4^h)~4xTv(C&6i8Paef&b17%(re*Jc-~alh=d4J(4?px(6~=XRK7-VX)?7QAFT2t_ z`Ro(!rQ0@)R?CyWeRiVwhgyYZ3C9hRyvH#tFjA#a3=94u|k59by5b8fuhC4CTyd6_`gxz~JA!4o0E7<|u=^{rGU z5Vh*OP&T$swjf-m6=NKe&j$K47hn&@$}_C$RJTj8=+K*M(GT_9X&*~ zg*H!yV3jy?dK||A6T_h=pJ#r`($NA7v!G*vQ4*^qag>0f(g{A8MgtpK+6vg!%UyBN zjw|&iKXi}hz?m(ZxBo_1i*eF9qjIe*1Od6U!q$ptm8WlDsmY|R_YWWV^RL~yI{&xT zn4c<{hK?#VxvY1M`2IimF=)+FIdz23{^LI|dK|91yoJHO9u6NrPD^Kw!J)O(j3COi z(%QX*uEAmO3*dTKr$9&!jUbCb;Ly7IVnn2<&WD)LVj3Y)pqM{fWGsJ*6)io@&kL}M zpuB)mg-cZz&4CQ85{>}tyGQ4=wr{^ zsoczl_THh!*i1+&Wm z-Cq_~86&U?yh1)})7dUd%Tj@C1LJ{>v7U=?1zIbN)yaI5v@gv$2^Xy`LTEG^YeF2y z!;x*!v4*zg4#kCtd=P{2IC^N5)|P%!{R7~-$kHM*lTA`BrJI?ig~639>FTF{#c7T{ z@i21}ihK@g4b4}+bbvMMdg$%VvgYbbSqzF86;U3aro%5fh1O-Yi+}L8j~x5#!>nyv zrmntZlhd(&v)TXDeKsY0TGTMC?fK02CEWh3#2+Pk{+Sa$)LEfiNZ~$1uBg)nM{T_h(QYH<$XG9ZF7b* ziIc~UB{F)rfWdVFT+c(t4pDuY920c*x60=qeL<{Uvq?u$!yqCujs!f$Po2O`wPSP# zaoAvfez$Y|^_SYI<0nmIS~+p}Q6jn%rJ-iY^gOc^IC}VC^Tr{j#3T_0j2oUzudfo8Br;9hi_i_dlhFmX_nU{I_?m z=D>4Zr;g9F?9!D&c6LIxi~4g%c;<62aPs&Bbpe-Oo~5NP&+)}^Hr;#`jVML?vaR&y zd!edI%HU^QCMBa zl>v@paAb@m1fda*M<(OZVl2U8h54BU>Xm?cxrV5Q_+f~y2e`_BaS~erKL@D-L>9C} z6x!%+ZNmwQ1W`mGTcD-jabRDO>8UA%V<~iY!n zc1p1rEZT*N7An?=X8%VwLGYZ%8y1Xq(MF(E@;z(T!1gP*Gj+OT-29;IzvNY)GctFS z(PqCALS(A&PyJmQD2| zLl{CBXmo7AKvc6-OPY1V*vl{OWT49t-NS3*d+*upEiAsg0?!!@|xTR;yW+OVfWaaFvc<8fV zNP~!N*IZ9wU@fidF2`vZgiJdKKM||OMMxi4rtpM=PmD*1 z<0PL!(*c{}*f?iTjngPA;>by6N+ZeQOoh^1gYs;HN-?BX(L{BUK4>E`x>n6c9YP#I z99p6fq6iux1R(?wq7hlD4J|75$dnt(iH!J4J+{x`rsZO_VN10JkXlH;&Cb%8dy(l= zrx{!|#L{&uaXb5y-KdkrmlCT~)A!+AL|_*a0s#VQ6--=badClqqlzlmi6)EG=j!N1 zg~2kmaFU6UNrV&_YjIqcOeRMvlg4vBx_WzvR7^`t3j@7fh{4q?snjrICuq;NP?@hV zldDo&gpnst+0%PZGqieGcq{ru#f;O|-)9Gw^tEee_J7PDyZ5~-SGN8o{agR`*dzNF zXV1)#$r)$K_HB0dktfZM{p8Q;zx}(vcD7%9-Q&+Zc>nwE|I*Q4dHoyLD1SKP+`4+b zc<%AT_P{PgP)+s**1UAvN%%4z)+T+zbFVeRlmls%Tz#^Js+TBD zAE!D$b+WI=d(gT3=D#bXPwyG|+6%NV-{5#+Q9~L-8bKQCxJ@z;SYa>%jBqgqTHQL0 zsYB#1x(XTLxd!r?7W{M`X_HJRRt6Pol(NJsx!FfL##(TVq+U0;z>-1ijjvfoSe+6B z{p-{t_de>69Iu`nSi1g4L`u*zlon+tV>ey*YWa^J`It!gO6SCwUi+r4J!Y!q8j53Q+3c!5Gi*7>q_92CM>ku;?REH=4DRT*Z?(t3>}tOSST_zb(UJaPO&(LH5Lz_>SP_?$V4yE zT7)BsY9Z>}P`ZH%RnAFpo^Veksyf!pwi z-V>ZXbxJJTG-Q=TR8_+`nT+Y_?(0UCe>XTV{u8U$Zv7hu)_v&AllRS?ef9zV;J5x< z{OOTSZdC^<1jOMW>|&-7(yi zTR3{^x6Yn8@)M3#Suf)-J$;Z;t)ym4XY68Sk+rKgvTD^@(Yn0gw506t=~MfDM4dkR zL)|?){;BtxoB!wH(Ic}EIac`EkjBaa+GNl+g%LhRfEJ*oi?xt)G>zgUzKk%+xNR-1 zqzi4-=F3(Jgi;9zs8|rG#AG*$lX9TY;NlWjB8G;s*IqkBTT3KVx}e5pYVNZKs|#ND z@GVO=?U)Xovj4+B`!m{P4SRPzV6MD$ko8v&FAJy7{Als;JwGO#MptiV3$%7BigjoA zmmha`K622OrVyfzl@Vs33)$WVS6?y2Vo+rHKsS~7I{Au$oJmTdHbMxMoHGMBF4Sx2 zg(8h=k@3?9s4Pw~H#X8;Q$>qr9H~!GSf3N6c>u1B2=kFRH@KtL>LWjN@A5o z8H>^i*EE@nB=!&ri#4JtKK(M4mS*`!S;aZo#7M%)g<6tnC$m^+o>I-#&mJrChkySm`OFLNx8=;p_Z_*FS#`|VxNuq!n!j?&U4PqlWGw(TFZN0i< zsJM3exxc(?zBIAHx*jXnTo$K0JDghaw9w_6(-1MlRWY{rA$w-u6Z8+QVBN-zX6X8@ zdhXy6FR1T+Z~39oR}bFseRtGGr+1Eyop1&QS8D5YV{IFdNk$ulL`#DbpajHN>TyV9 z4bo`0y{(JdLWOD-=4O+dzg7aRBr1k5GUyn5;em$YRK%(w?3T?bF51*0CQlyMh4vNh z=N>%}FF1wQZ`yIo$PfJf`^8`X`VU9Nkx}mW{#!kYr>?7(MBFX%$z-WtB0%Ih`I)t%C8A+rpN;^cx5Lv7;l0a$E2r)r~wF1Wq{=i80&x~}0 z!8OJ@O(&I?0PrPo8S`x)qIkKX(*-d6_r(Pu{H~3r$dcpIFp^ZRlZG)?yX~}f_y6q4 zW4k(+^m^}V#IeeyrSv>0wH3Bj78b`5IGRSajxlxgVwI7dyK$Vv`9f)pH5O?sz5=OV z@&i;2ngi6Jn&RNrsDu!5UYg7_!LF&&ViQ0#O?KnC?~|TG#&?pQT%=JAO+AMGrR}(? z#_E;p2s4G_C#RlU)zi`9lxhnqn5v7TQzx9Uqp)IiizsNs|$z()lxD&Hr_dw5d_ZyHtt|^7)LD z^R(_;*1rAp;~#jaTs&ClS+OeW-Ex&j-S_Yvn;YmS*MsQk_p#LhD#s_pnUiNYx^Isi zJ#koEeeJbg*XDH=Wz?Bx4-Fpq%7>p_chzmTt&*)@tA-`V^;>i-Vhk}xDvU5FX|Tee zEtDg8%X@!POg1C~8`sX2OV3cAnr3>YCZL%OHZwx4Bt|({ZK+pd2%)bBHmvF9imQgj znIn5mzHOPa|G*r(c5(X~zwer-N}|N{{0nKQTwXo&*litXQ{E!o&Mt-Q`TJ|sXF zo&&mO8fcnzR%H@@#JHI;0w`?~05pa`3F1U#z{VD$Sc_V$l~%Y`g6F$`(Z>ZDwzt=Ye@iV$7A$Fbbn=vQxGs z>_p=vS)Wa~REhe%Y5E3QY;!j6yoMqY{dLl105-HJ6(!P{P2y%t4pM0$I`ciMebrW% ztKRnOkNx>;r*FPO{l$`=!q&lMK7lE#(V1B8f4VFu+h4TH)+`tKFzd3oX!33I#&Oba zYj6I#MrG`}=*Yw2bsKn5;NS0?!G}NmH~tg9_Ui{P8{9ts%oW#d+)!+oE7 zz^>gi&c(04%^SSzVs+x_o$kWuw3B9-(BBc+LzgTW_gG>Gc3q!U&Sx@=z8Cr&4<9plHId)2|u|I!Ug%?(Shj!g%2_jj6nzRN_5Rp;z8XWiq6 zj@!{=v9%hJ&!BsjV^aoKGz62UW*(jlv%ho6JAdX;E_usu)MpOg(B_BA=BvIpTedTE zfvqeej?NzBD2H&pEJ_)|I3hMWaqn=P<~p-j9idc&&<@rlhc<>-H^r>2i#1N7ovM-^ z-?`Au-k*w1GBepU#7we2fii+X85?T|jTOpR+lXx(gm{ii&{Amm5y$gBUa3`ywG~b( zZ;?LAisagm0>^c5jY%r(!kia&NPhqSTk`Kh{Kv!v*64R>2uI+$9?OP?h>RezDcnpu z(#ABKmJ+!yQ#&cuq##m1(Erij+>d@i{S9l_Y4h6MxgE+8gB@xy| ztHgmk)}~o9bI{tw=%hrXj6fUNWW6~FUEMkuE0gEeIsaVS;jpp!#dXq4^$*WP=F z$#zv|-tXG`gsSSQj<@^f9HgtOEFpwMGRXuZ40ud5#xNK#;|GsDFf(92jBRY3FrLqe z0b^r~6W9g~vcWb%0wt95&G~ls?c9}4+Iy|hG!wd9bS9(WKD#lZ^x5sX*`JA2_|va_ z!xh_kQcKHr>g^D<(ZXj zSARTNV4F!D830xq3#prr4B0@VK((r|dh2;~YEjGjEn7Dw2fy(X69*r}_(Vp90VO$5 zSV2()U?ZTMVG_pJ5U_1y4Wol0It%j>t11p0nxLImJni;sfB)K3U%BC9$M65j>yq^7 zWh9eBgF`HOUDM*5OyV9V?q=~S>3Pza|CNcw*ke4q;f8w{=;cwLoqOITO+xC=4Mr zKw1EqQRrGil8bb$Ajv^V!IW5-+>**gY0G#dh$=ryLHzHT6>Wq>g;iIkM&PX1MBIhB z?D!RE<;=JPtr2Jq9R$d8^Tdx0D=y#e|Nip$E2Qy^aH|>T#)DN z%7P+GnV&NU?R_y_mgkyD2tvKgP`S*oycGe^N+B0UQCN^+!~mqjhy!3Cg4FwgYp(65 zO;_y(vbGsntOZJK!--Ss|Czh_%L}*Od0TYd%U_hg`sX%(>Ze}yJAe1HFFg6yjhD>7 z>%!+;vhi83-2}{!%yw^7&oD^jZt%lKrQiP}<)wQh{rtx+)Z z^COlqJvGzad&?BgzjOl?wu{C%X3!-hg349fyt0Qn4LVEr(%b^vat zi%RRMhwr%?DkMqr#09}HfRO@{&SUd{!SG0+v;2e|+O+D8&3#kPi26qgjBE~(TS;NS z$O-5mR4t&G2PZSo?FmRLLD8B6Cn<`g3*EHg{w$cn&UULodEJKtVXaU4lgC5CBrfDR+<0MB^VI;>wajBkATL97|6V!Sy;EepQorhm9b)p5<}Py@qj z2kqKT8znP^nx31YV|N}3=1&wdf7+EAN5?>yUJ+s4*cyq^P!q=&u=kGRd-u;=@H-#5 z{*q7r`CtF7?bDy3kALi)>P^4#NAmDJH=n-X=`VjZ9~u3-xq~+~CT{sk5m!iG@XVcR z&AO`G{EfqyIPO;YY^f$^39zDIvH-b(8~h`Nz`%-uA%bB>!LEEy%n&9Nh4c4gcID8b za6bj5%Z7EMu$dKDfuxp^TOz|?3t}r22o#vqpV|QL%Awj~C}1lF%9*Aa0HUmu%oBko zAk+jVjo=&$gF?W_(BKn3HuS_CmMbzn{_n3p{-CgO%UEm5E@Fl$42(5CBYd(F1PW0Y zVPJ3&77C0QNs_}938H|&MS;Q?X=eyTMJG>Bwf`KDYNwN3m1ag;(afTxNDE~Qld+JZ z0Ojl?w6emMZQulB6pBJnSVCbKg%LMfW|ws*Gb_joDX$9(2HemCpMxG^f;=}@u9Y2j`YX;5c zqKZOL90w4aOQ*SDB{x*BMNxeql)33S8d|rWY@R_F80ZI@a|Yc6U@dMN6bzLcR0T9L z7;{jI)Y_dFKQcdSKl9-oCYWRWn_C_ZRW_meB4%3`MK0kwEVG+r6g0z*Q+fLjRixmXW;8bXCu7&30 zNjmTRU3BkVx6)W`_@X^mzv7dh`@7F|Ui(u&P6zJ)CK`=F*ql)b7;!8BQVb8*(OnqF zn$>~uvD@D=e&~^SX2u}PfKCU*4CG0Uq$!96c=H=C$DS+p;D*oLgkvXxW@0F=LpGf^ ztoB^BNjC2owe`Uox>-jZK73g1+k1+RA8w+v$kZQ$cJJt;tFPLEi!ajI>}%axR0SAZNJ1$7R{b zx(0)sU7LMj3569HBd`U#vZ@i}7HBsa$bf+u*t8CE=_ML3ylxL|`q4{JExMe~E%1g7 z>x2H$U21l!`pr*%`tFx*-nr$*^%q`A4_RVx;)yD0%lO-5_<%{Y+^Zuu9 zf7Y9>Y^)uX#kNh?9X)V#G^PSWTgR~G{Pnc+;?+2R`v8Fo>a-SdaBqiBAD>5adO<}J zQZ1~Z+s%=ym=M;a+i9V%8j}Lt zv3a+O<>h+khVw_ZuCA}%9CxN??r)u1Sdas!W&{G>vwkc-c+-v3ue$E{Kl#*acNX>4 zjSJUpT-TU5a-5K*#m@C380Z5rx>C^8bnm~hB-}J zAyv+G(o#qQ5tIV7(og|G1qwnjNR`_UMzfGC9~ zK~>i=GtovhSckjrIgC3VY#}pFQ-BI!Ab`B-O&3tAD!lW$pS)mU-s~&l5fl=kC_)sr zhMX%9Rlz{qLVNu4!S*$Y34`Q+pPHC`%lfCi(x6fgfH^7V9wwVkL$Wrqb{9oAM|-9T z+sV*vc9FMJB<&nrKEE+2M^iMcbtP%V5k!%kUToU2O>2XfzV7F*zyF@QUv}WYoqEmY zi|x7#UxOxBL6sJCkfB<1v8L9BUbqc0S^ygVb@uS|hfkfDG1vc}13Jq<%_h*-2mIJe zR%83tLEL!bK3u%#LTuT#1BIT!_~~QVfA9oOodRlApuZ0ES2e;wP_IPjtA$W7XcY-; z9jMgns8@%eX#hdE4*kQUl80TIU7U2EpFD<^b=bV+@^&z?VIM};-Ho{MO@RLSfq(hi z@tO$42B6U5y}$O`V{d-#MgL{JE`DxxB^a4JydR6RIl?G1eT{Xr|KO~eo=I_fwm`Q4 zB?2jwCMicp3<+{^rB3Jf7{RiJEi9~MFk4|3FzKuwPkHR(=9%{0kNyA0 z1D(|gE%d}5;rsFa#xQbYU{+jwAbgTityWzi+^`;%N(FtDevmMnZbgnL6qu}oB56Yj zpvn)#V!NZ(ty?Fy$mG=FL$!fWUf);2&!in(U8w+-DnUdH5hw}*rIdmuLb>A5`y3H^ z3MwSd38SpYbQc+Y5oDyVPJMA97oA_n`P)`u*Ou*)Oib|phaaM5E7z8Q(d}cv$k0Q# zJ~Z|FzxkK*fBA_|{%Vm2IpRu+Ms*gKz34}N6rHJ`#r*WM+nw2AjV^S)h}Ob5GSdVq zLnf$Q09{+F>y0sr<4_i+P9X12QX^`iId=p}XS#HB=t2u4ln^oXV`0MLi_fNUNAWYBn?y%pLpkgR||aJv(3eMhhuadg5l%`83jG5uD{n z+8MGABWoEXZG*g>BTp<$p2HOE8apgOZ0N>07*G-;vN23yrI~l6U0C&!SG<01?Mq*| z{Y!uK*9$-Tnm5!@Thjn|0NfddB CI#99>+}a4!S%;a)?ellsx@BM}mRoNA3cB5d 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 O&A6%Rs5N37qW%ZstEK(` literal 0 HcmV?d00001 diff --git a/src/assets/images/silver.png b/src/assets/images/silver.png new file mode 100644 index 0000000000000000000000000000000000000000..b13d604de514eb14df97b5c05d3afcdbfa911cf2 GIT binary patch literal 136779 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

FS_?8U>J!u+=*N=i1ss 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 literal 0 HcmV?d00001 diff --git a/src/components/OrganizationScreen/OrganizationScreen.tsx b/src/components/OrganizationScreen/OrganizationScreen.tsx index 7bd2119a82..ddef0d1504 100644 --- a/src/components/OrganizationScreen/OrganizationScreen.tsx +++ b/src/components/OrganizationScreen/OrganizationScreen.tsx @@ -146,4 +146,5 @@ const map: InterfaceMapType = { blockuser: 'blockUnblockUser', orgvenues: 'organizationVenues', event: 'eventManagement', + leaderboard: 'leaderboard', }; diff --git a/src/screens/Leaderboard/Leaderboard.tsx b/src/screens/Leaderboard/Leaderboard.tsx new file mode 100644 index 0000000000..4eca682d44 --- /dev/null +++ b/src/screens/Leaderboard/Leaderboard.tsx @@ -0,0 +1,372 @@ +import React, { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; + +import { + FilterAltOutlined, + Search, + Sort, + WarningAmberRounded, +} from '@mui/icons-material'; +import gold from 'assets/images/gold.png'; +import silver from 'assets/images/silver.png'; +import bronze from 'assets/images/bronze.png'; + +import type { InterfaceVolunteerRank } from 'utils/interfaces'; +import styles from '../OrganizationActionItems/OrganizationActionItems.module.css'; +import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { Stack } from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; +import { VOLUNTEER_RANKING } from 'GraphQl/Queries/EventVolunteerQueries'; +import { useQuery } from '@apollo/client'; + +enum TimeFrame { + All = 'allTime', + Weekly = 'weekly', + Monthly = 'monthly', + Yearly = 'yearly', +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component for managing and displaying action items within an organization. + * + * This component allows users to view, filter, sort, and create action items. It also handles fetching and displaying related data such as action item categories and members. + * + * @returns The rendered component. + */ +function leaderboard(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'leaderboard', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + // Get the organization ID from URL parameters + const { orgId } = useParams(); + + if (!orgId) { + return ; + } + + const navigate = useNavigate(); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState<'hours_ASC' | 'hours_DESC'>( + 'hours_DESC', + ); + const [timeFrame, setTimeFrame] = useState(TimeFrame.All); + + /** + * Query to fetch volunteer rankings. + */ + const { + data: rankingsData, + loading: rankingsLoading, + error: rankingsError, + }: { + data?: { + getVolunteerRanks: InterfaceVolunteerRank[]; + }; + loading: boolean; + error?: Error | undefined; + } = useQuery(VOLUNTEER_RANKING, { + variables: { + orgId, + where: { + order_by: sortBy, + time_frame: timeFrame, + name_contains: searchTerm, + }, + }, + }); + + const rankings = useMemo( + () => rankingsData?.getVolunteerRanks || [], + [rankingsData], + ); + + if (rankingsLoading) { + return ; + } + + if (rankingsError) { + return ( +

+ +
+ {tErrors('errorLoading', { entity: 'Volunteer Rankings' })} +
+ {`${rankingsError.message}`} +
+
+ ); + } + + const columns: GridColDef[] = [ + { + field: 'rank', + headerName: 'Rank', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + if (params.row.rank === 1) { + return ( + <> + gold + + ); + } else if (params.row.rank === 2) { + return ( + <> + silver + + ); + } else if (params.row.rank === 3) { + return ( + <> + bronze + + ); + } else return <>{params.row.rank}; + }, + }, + { + field: 'volunteer', + headerName: 'Volunteer', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.user || {}; + + return ( + <> +
+ navigate(`/member/${orgId}`, { state: { id: _id } }) + } + data-testid="userName" + > + {image ? ( + User + ) : ( +
+ +
+ )} + {firstName + ' ' + lastName} +
+ + ); + }, + }, + { + field: 'email', + headerName: 'Email', + flex: 2, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
+ {params.row.user.email} +
+ ); + }, + }, + { + field: 'hoursVolunteered', + headerName: 'Hours Volunteered', + flex: 2, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return
{params.row.hoursVolunteered}
; + }, + }, + ]; + + return ( +
+ {/* Header with search, filter and Create Button */} +
+
+ setSearchValue(e.target.value)} + onKeyUp={(e) => { + if (e.key === 'Enter') { + setSearchTerm(searchValue); + } else if (e.key === 'Backspace' && searchValue === '') { + setSearchTerm(''); + } + }} + data-testid="searchBy" + /> + +
+
+
+ + + + {tCommon('sort')} + + + setSortBy('hours_DESC')} + data-testid="hours_DESC" + > + {t('mostHours')} + + setSortBy('hours_ASC')} + data-testid="hours_ASC" + > + {t('leastHours')} + + + + + + + {t('timeFrame')} + + + setTimeFrame(TimeFrame.All)} + data-testid="timeFrameAll" + > + {t('allTime')} + + setTimeFrame(TimeFrame.Weekly)} + data-testid="timeFrameWeekly" + > + {t('weekly')} + + setTimeFrame(TimeFrame.Monthly)} + data-testid="timeFrameMonthly" + > + {t('monthly')} + + setTimeFrame(TimeFrame.Yearly)} + data-testid="timeFrameYearly" + > + {t('yearly')} + + + +
+
+
+ + {/* Table with Action Items */} + row.user._id} + slots={{ + noRowsOverlay: () => ( + + {t('noVolunteers')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={rankings.map((ranking, index) => ({ + id: index + 1, + ...ranking, + }))} + columns={columns} + isRowSelectable={() => false} + /> +
+ ); +} + +export default leaderboard; diff --git a/src/screens/OrganizationActionItems/ItemModal.tsx b/src/screens/OrganizationActionItems/ItemModal.tsx index 1cce9efc9b..03dad3dd67 100644 --- a/src/screens/OrganizationActionItems/ItemModal.tsx +++ b/src/screens/OrganizationActionItems/ItemModal.tsx @@ -11,6 +11,8 @@ import type { InterfaceActionItemCategoryList, InterfaceActionItemInfo, InterfaceEventVolunteerInfo, + InterfaceMemberInfo, + InterfaceMembersList, InterfaceVolunteerGroupInfo, } from 'utils/interfaces'; import { useTranslation } from 'react-i18next'; @@ -27,13 +29,14 @@ import { EVENT_VOLUNTEER_LIST, } from 'GraphQl/Queries/EventVolunteerQueries'; import { HiUser, HiUserGroup } from 'react-icons/hi2'; +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; /** * Interface for the form state used in the `ItemModal` component. */ interface InterfaceFormStateType { dueDate: Date; - assigneeType: 'EventVolunteer' | 'EventVolunteerGroup'; + assigneeType: 'EventVolunteer' | 'EventVolunteerGroup' | 'User'; actionItemCategoryId: string; assigneeId: string; eventId?: string; @@ -50,7 +53,7 @@ export interface InterfaceItemModalProps { isOpen: boolean; hide: () => void; orgId: string; - eventId: string; + eventId: string | undefined; actionItemsRefetch: () => void; actionItem: InterfaceActionItemInfo | null; editMode: boolean; @@ -68,8 +71,12 @@ const initializeFormState = ( ): InterfaceFormStateType => ({ dueDate: actionItem?.dueDate || new Date(), actionItemCategoryId: actionItem?.actionItemCategory?._id || '', - assigneeId: actionItem?.assignee?._id || actionItem?.assigneeGroup?._id || '', - assigneeType: actionItem?.assigneeType || 'EventVolunteer', + assigneeId: + actionItem?.assignee?._id || + actionItem?.assigneeGroup?._id || + actionItem?.assigneeUser?._id || + '', + assigneeType: actionItem?.assigneeType || 'User', preCompletionNotes: actionItem?.preCompletionNotes || '', postCompletionNotes: actionItem?.postCompletionNotes || null, allotedHours: actionItem?.allotedHours || null, @@ -103,6 +110,10 @@ const ItemModal: FC = ({ const [assigneeGroup, setAssigneeGroup] = useState(null); + const [assigneeUser, setAssigneeUser] = useState( + null, + ); + const [formState, setFormState] = useState( initializeFormState(actionItem), ); @@ -170,6 +181,22 @@ const ItemModal: FC = ({ }, }); + /** + * Query to fetch members of the organization. + */ + const { + data: membersData, + }: { + data: InterfaceMembersList | undefined; + } = useQuery(MEMBERS_LIST, { + variables: { id: orgId }, + }); + + const members = useMemo( + () => membersData?.organizations[0].members || [], + [membersData], + ); + const volunteers = useMemo( () => volunteersData?.getEventVolunteers || [], [volunteersData], @@ -225,7 +252,7 @@ const ItemModal: FC = ({ actionItemCategoryId: actionItemCategory?._id, preCompletionNotes: preCompletionNotes, allotedHours: allotedHours, - eventId: eventId, + ...(eventId && { eventId }), }, }); @@ -274,6 +301,13 @@ const ItemModal: FC = ({ updatedFields.assigneeId = assigneeId; } + if ( + assigneeId !== actionItem?.assigneeUser?._id && + assigneeType === 'User' + ) { + updatedFields.assigneeId = assigneeId; + } + if (assigneeType !== actionItem?.assigneeType) { updatedFields.assigneeType = assigneeType; } @@ -333,7 +367,11 @@ const ItemModal: FC = ({ groups.find((group) => group._id === actionItem?.assigneeGroup?._id) || null, ); - }, [actionItem, actionItemCategories, volunteers, groups]); + setAssigneeUser( + members.find((member) => member._id === actionItem?.assigneeUser?._id) || + null, + ); + }, [actionItem, actionItemCategories, volunteers, groups, members]); return ( @@ -408,48 +446,53 @@ const ItemModal: FC = ({ {!isCompleted && ( <> - {t('assignTo')} -
- - handleFormChange('assigneeType', 'EventVolunteer') - } - /> - - - - handleFormChange('assigneeType', 'EventVolunteerGroup') - } - checked={assigneeType === 'EventVolunteerGroup'} - /> - -
+ {assigneeType !== 'User' && ( + <> + {t('assignTo')} +
+ + handleFormChange('assigneeType', 'EventVolunteer') + } + /> + + + + handleFormChange('assigneeType', 'EventVolunteerGroup') + } + checked={assigneeType === 'EventVolunteerGroup'} + /> + +
+ + )} + {assigneeType === 'EventVolunteer' ? ( = ({ )} /> - ) : ( + ) : assigneeType === 'EventVolunteerGroup' ? ( = ({ )} /> + ) : ( + + + option._id === value._id + } + filterSelectedOptions={true} + getOptionLabel={(member: InterfaceMemberInfo): string => + `${member.firstName} ${member.lastName}` + } + onChange={(_, newAssignee): void => { + /* istanbul ignore next */ + handleFormChange('assigneeId', newAssignee?._id ?? ''); + setAssigneeUser(newAssignee); + }} + renderInput={(params) => ( + + )} + /> + )} diff --git a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx index 573fd0afb7..f43f5865f4 100644 --- a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx +++ b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx @@ -55,7 +55,9 @@ const ItemUpdateStatusModal: FC = ({ assigneeId: actionItem?.assigneeType === 'EventVolunteer' ? actionItem?.assignee?._id - : actionItem?.assigneeGroup?._id, + : actionItem?.assigneeType === 'EventVolunteerGroup' + ? actionItem?.assigneeGroup?._id + : actionItem?.assigneeUser?._id, assigneeType: actionItem?.assigneeType, postCompletionNotes: isCompleted ? '' : postCompletionNotes, isCompleted: !isCompleted, diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.module.css b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css index d58c759cc4..97a20848ec 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.module.css +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.module.css @@ -283,3 +283,9 @@ input[type='radio']:checked + label { input[type='radio']:checked + label:hover { color: black !important; } + +.rankings { + aspect-ratio: 1; + border-radius: 50%; + width: 50px; +} diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx index 60e039e8ad..1969988841 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx @@ -84,7 +84,7 @@ function organizationActionItems(): JSX.Element { // Get the organization ID from URL parameters const { orgId, eventId } = useParams(); - if (!orgId || !eventId) { + if (!orgId) { return ; } @@ -186,11 +186,11 @@ function organizationActionItems(): JSX.Element { headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { const { _id, firstName, lastName, image } = - params.row.assignee?.user || {}; + params.row.assigneeUser || params.row.assignee?.user || {}; return ( <> - {params.row.assigneeType === 'EventVolunteer' ? ( + {params.row.assigneeType !== 'EventVolunteerGroup' ? ( <>
rankingsData?.getVolunteerRanks || [], + [rankingsData], + ); + /** * Query to fetch posts for the organization. */ @@ -83,7 +117,7 @@ function organizationDashboard(): JSX.Element { loading: boolean; error?: ApolloError; } = useQuery(ORGANIZATION_POST_LIST, { - variables: { id: currentUrl, first: 10 }, + variables: { id: orgId, first: 10 }, }); /** @@ -95,7 +129,7 @@ function organizationDashboard(): JSX.Element { error: errorEvent, } = useQuery(ORGANIZATION_EVENT_CONNECTION_LIST, { variables: { - organization_id: currentUrl, + organization_id: orgId, }, }); @@ -325,44 +359,109 @@ function organizationDashboard(): JSX.Element { - -
-
{t('membershipRequests')}
- -
- - {loadingOrgData ? ( - [...Array(4)].map((_, index) => { - return ; - }) - ) : data?.organizations[0].membershipRequests.length == 0 ? ( -
-
{t('noMembershipRequests')}
+ + +
+
+ {t('membershipRequests')}
- ) : ( - data?.organizations[0]?.membershipRequests - .slice(0, 8) - .map((request) => { + +
+ + {loadingOrgData ? ( + [...Array(4)].map((_, index) => { + return ; + }) + ) : data?.organizations[0].membershipRequests.length == 0 ? ( +
+
{t('noMembershipRequests')}
+
+ ) : ( + data?.organizations[0]?.membershipRequests + .slice(0, 8) + .map((request) => { + return ( + + ); + }) + )} +
+
+
+ + +
+
{t('volunteerRankings')}
+ +
+ + {rankingsLoading ? ( + [...Array(3)].map((_, index) => { + return ; + }) + ) : rankings.length == 0 ? ( +
+
{t('noVolunteers')}
+
+ ) : ( + rankings.map(({ rank, user, hoursVolunteered }, index) => { return ( - + <> +
+
+ {rank <= 3 ? ( + gold + ) : ( + rank + )} +
+
{`${user.firstName} ${user.lastName}`}
+
- {hoursVolunteered} hours
+
+ {index < 2 &&
} + ); }) - )} -
-
+ )} + + +
diff --git a/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx b/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx new file mode 100644 index 0000000000..5f4dfc6cce --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx @@ -0,0 +1,407 @@ +import type { ChangeEvent } from 'react'; +import { Button, Form, Modal } from 'react-bootstrap'; +import type { + InterfaceCreateVolunteerGroup, + InterfaceVolunteerGroupInfo, + InterfaceVolunteerMembership, +} from 'utils/interfaces'; +import styles from 'screens/EventVolunteers/EventVolunteers.module.css'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useMutation, useQuery } from '@apollo/client'; +import { toast } from 'react-toastify'; +import { + FormControl, + Paper, + Stack, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, +} from '@mui/material'; +import { + UPDATE_VOLUNTEER_GROUP, + UPDATE_VOLUNTEER_MEMBERSHIP, +} from 'GraphQl/Mutations/EventVolunteerMutation'; +import { PiUserListBold } from 'react-icons/pi'; +import { TbListDetails } from 'react-icons/tb'; +import { USER_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Queries/EventVolunteerQueries'; +import Avatar from 'components/Avatar/Avatar'; +import { FaXmark } from 'react-icons/fa6'; + +export interface InterfaceGroupModal { + isOpen: boolean; + hide: () => void; + eventId: string; + group: InterfaceVolunteerGroupInfo | null; + refetchGroups: () => void; +} + +/** + * A modal dialog for creating or editing a volunteer group. + * + * @param isOpen - Indicates whether the modal is open. + * @param hide - Function to close the modal. + * @param eventId - The ID of the event associated with volunteer group. + * @param orgId - The ID of the organization associated with volunteer group. + * @param group - The volunteer group object to be edited. + * @param refetchGroups - Function to refetch the volunteer groups after creation or update. + * @returns The rendered modal component. + * + * The `VolunteerGroupModal` component displays a form within a modal dialog for creating or editing a Volunteer Group. + * It includes fields for entering the group name, description, volunteersRequired, and selecting volunteers/leaders. + * + * The modal includes: + * - A header with a title indicating the current mode (create or edit) and a close button. + * - A form with: + * - An input field for entering the group name. + * - A textarea for entering the group description. + * - An input field for entering the number of volunteers required. + * - A submit button to create or update the pledge. + * + * On form submission, the component either: + * - Calls `updateVoluneerGroup` mutation to update an existing pledge, or + * + * Success or error messages are displayed using toast notifications based on the result of the mutation. + */ + +const GroupModal: React.FC = ({ + isOpen, + hide, + eventId, + group, + refetchGroups, +}) => { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + + const [modalType, setModalType] = useState<'details' | 'requests'>('details'); + const [formState, setFormState] = useState({ + name: group?.name ?? '', + description: group?.description ?? '', + leader: group?.leader ?? null, + volunteerUsers: group?.volunteers.map((volunteer) => volunteer.user) ?? [], + volunteersRequired: group?.volunteersRequired ?? null, + }); + + const [updateVolunteerGroup] = useMutation(UPDATE_VOLUNTEER_GROUP); + const [updateMembership] = useMutation(UPDATE_VOLUNTEER_MEMBERSHIP); + + const updateMembershipStatus = async ( + id: string, + status: 'accepted' | 'rejected', + ): Promise => { + try { + await updateMembership({ + variables: { + id: id, + status: status, + }, + }); + toast.success( + t( + status === 'accepted' ? 'requestAccepted' : 'requestRejected', + ) as string, + ); + refetchRequests(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }; + + /** + * Query to fetch volunteer Membership requests for the event. + */ + const { + data: requestsData, + refetch: refetchRequests, + }: { + data?: { + getVolunteerMembership: InterfaceVolunteerMembership[]; + }; + refetch: () => void; + } = useQuery(USER_VOLUNTEER_MEMBERSHIP, { + variables: { + where: { + eventId, + status: 'requested', + }, + }, + }); + + const requests = useMemo(() => { + if (!requestsData) return []; + return requestsData.getVolunteerMembership; + }, [requestsData]); + + useEffect(() => { + setFormState({ + name: group?.name ?? '', + description: group?.description ?? '', + leader: group?.leader ?? null, + volunteerUsers: + group?.volunteers.map((volunteer) => volunteer.user) ?? [], + volunteersRequired: group?.volunteersRequired ?? null, + }); + }, [group]); + + const { name, description, volunteersRequired } = formState; + + /*istanbul ignore next*/ + const updateGroupHandler = useCallback( + async (e: ChangeEvent): Promise => { + e.preventDefault(); + + const updatedFields: { + [key: string]: number | string | undefined | null; + } = {}; + + if (name !== group?.name) { + updatedFields.name = name; + } + if (description !== group?.description) { + updatedFields.description = description; + } + if (volunteersRequired !== group?.volunteersRequired) { + updatedFields.volunteersRequired = volunteersRequired; + } + try { + await updateVolunteerGroup({ + variables: { + id: group?._id, + data: { ...updatedFields, eventId }, + }, + }); + toast.success(t('volunteerGroupUpdated')); + refetchGroups(); + hide(); + } catch (error: unknown) { + toast.error((error as Error).message); + } + }, + [formState, group], + ); + + return ( + + +

{t('manageGroup')}

+ +
+ +
+ setModalType('details')} + /> + + + setModalType('requests')} + checked={modalType === 'requests'} + /> + +
+ + {modalType === 'details' ? ( +
+ {/* Input field to enter the group name */} + + + + setFormState({ ...formState, name: e.target.value }) + } + /> + + + {/* Input field to enter the group description */} + + + + setFormState({ ...formState, description: e.target.value }) + } + /> + + + + + + { + if (parseInt(e.target.value) > 0) { + setFormState({ + ...formState, + volunteersRequired: parseInt(e.target.value), + }); + } else if (e.target.value === '') { + setFormState({ + ...formState, + volunteersRequired: null, + }); + } + }} + /> + + + + {/* Button to submit the pledge form */} + +
+ ) : ( +
+ {requests.length === 0 ? ( + + {t('noRequests')} + + ) : ( + + + + + Name + Actions + + + + {requests.map((request, index) => { + const { _id, firstName, lastName, image } = + request.volunteer.user; + return ( + + + {image ? ( + volunteer + ) : ( +
+ +
+ )} + {firstName + ' ' + lastName} +
+ +
+ + +
+
+
+ ); + })} +
+
+
+ )} +
+ )} +
+
+ ); +}; +export default GroupModal; diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.tsx b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx new file mode 100644 index 0000000000..477fd70825 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx @@ -0,0 +1,422 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Button, Dropdown, Form } from 'react-bootstrap'; +import { Navigate, useParams } from 'react-router-dom'; + +import { Search, Sort, WarningAmberRounded } from '@mui/icons-material'; + +import { useQuery } from '@apollo/client'; + +import type { InterfaceVolunteerGroupInfo } from 'utils/interfaces'; +import Loader from 'components/Loader/Loader'; +import { + DataGrid, + type GridCellParams, + type GridColDef, +} from '@mui/x-data-grid'; +import { Stack } from '@mui/material'; +import Avatar from 'components/Avatar/Avatar'; +import styles from 'screens/EventVolunteers/EventVolunteers.module.css'; +import { EVENT_VOLUNTEER_GROUP_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; +import VolunteerGroupViewModal from 'screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal'; +import useLocalStorage from 'utils/useLocalstorage'; +import GroupModal from './GroupModal'; + +enum ModalState { + EDIT = 'edit', + VIEW = 'view', +} + +const dataGridStyle = { + '&.MuiDataGrid-root .MuiDataGrid-cell:focus-within': { + outline: 'none !important', + }, + '&.MuiDataGrid-root .MuiDataGrid-columnHeader:focus-within': { + outline: 'none', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-row.Mui-hovered': { + backgroundColor: 'transparent', + }, + '& .MuiDataGrid-root': { + borderRadius: '0.5rem', + }, + '& .MuiDataGrid-main': { + borderRadius: '0.5rem', + }, +}; + +/** + * Component for managing volunteer groups for an event. + * This component allows users to view, filter, sort, and create action items. It also provides a modal for creating and editing action items. + * @returns The rendered component. + */ +function groups(): JSX.Element { + const { t } = useTranslation('translation', { + keyPrefix: 'eventVolunteers', + }); + const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); + + const { getItem } = useLocalStorage(); + const userId = getItem('userId'); + + // Get the organization ID from URL parameters + const { orgId } = useParams(); + + if (!orgId || !userId) { + return ; + } + + const [group, setGroup] = useState(null); + const [searchValue, setSearchValue] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [sortBy, setSortBy] = useState<'member_ASC' | 'member_DESC' | null>( + null, + ); + const [searchBy, setSearchBy] = useState<'leader' | 'group'>('group'); + const [modalState, setModalState] = useState<{ + [key in ModalState]: boolean; + }>({ + [ModalState.EDIT]: false, + [ModalState.VIEW]: false, + }); + + /** + * Query to fetch the list of volunteer groups for the event. + */ + const { + data: groupsData, + loading: groupsLoading, + error: groupsError, + refetch: refetchGroups, + }: { + data?: { + getEventVolunteerGroups: InterfaceVolunteerGroupInfo[]; + }; + loading: boolean; + error?: Error | undefined; + refetch: () => void; + } = useQuery(EVENT_VOLUNTEER_GROUP_LIST, { + variables: { + where: { + eventId: undefined, + userId: userId, + leaderName: searchBy === 'leader' ? searchTerm : null, + name_contains: searchBy === 'group' ? searchTerm : null, + }, + orderBy: sortBy, + }, + }); + + const openModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: true })); + + const closeModal = (modal: ModalState): void => + setModalState((prevState) => ({ ...prevState, [modal]: false })); + + const handleModalClick = useCallback( + (group: InterfaceVolunteerGroupInfo | null, modal: ModalState): void => { + setGroup(group); + openModal(modal); + }, + [openModal], + ); + + const groups = useMemo( + () => groupsData?.getEventVolunteerGroups || [], + [groupsData], + ); + + if (groupsLoading) { + return ; + } + + if (groupsError) { + return ( +
+ +
+ {tErrors('errorLoading', { entity: 'Volunteer Groups' })} +
+ {`${groupsError.message}`} +
+
+ ); + } + + const columns: GridColDef[] = [ + { + field: 'group', + headerName: 'Group', + flex: 1, + align: 'left', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
+ {params.row.name} +
+ ); + }, + }, + { + field: 'leader', + headerName: 'Leader', + flex: 1, + align: 'center', + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + const { _id, firstName, lastName, image } = params.row.leader; + return ( +
+ {image ? ( + Assignee + ) : ( +
+ +
+ )} + {firstName + ' ' + lastName} +
+ ); + }, + }, + { + field: 'actions', + headerName: 'Actions Completed', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
+ {params.row.assignments.length} +
+ ); + }, + }, + { + field: 'members', + headerName: 'No. of Members', + flex: 1, + align: 'center', + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( +
+ {params.row.volunteers.length} +
+ ); + }, + }, + { + field: 'options', + headerName: 'Options', + align: 'center', + flex: 1, + minWidth: 100, + headerAlign: 'center', + sortable: false, + headerClassName: `${styles.tableHeader}`, + renderCell: (params: GridCellParams) => { + return ( + <> + + {params.row.leader._id === userId && ( + + )} + + ); + }, + }, + ]; + + return ( +
+ {/* Header with search, filter and Create Button */} +
+
+ setSearchValue(e.target.value)} + onKeyUp={(e) => { + if (e.key === 'Enter') { + setSearchTerm(searchValue); + } else if (e.key === 'Backspace' && searchValue === '') { + setSearchTerm(''); + } + }} + data-testid="searchBy" + /> + +
+
+
+ + + + {tCommon('searchBy', { item: '' })} + + + setSearchBy('leader')} + data-testid="leader" + > + {t('leader')} + + setSearchBy('group')} + data-testid="group" + > + {t('group')} + + + + + + + {tCommon('sort')} + + + setSortBy('member_DESC')} + data-testid="member_DESC" + > + {t('mostMembers')} + + setSortBy('member_ASC')} + data-testid="member_ASC" + > + {t('leastMembers')} + + + +
+
+
+ + {/* Table with Volunteer Groups */} + row._id} + slots={{ + noRowsOverlay: () => ( + + {t('noVolunteerGroups')} + + ), + }} + sx={dataGridStyle} + getRowClassName={() => `${styles.rowBackground}`} + autoHeight + rowHeight={65} + rows={groups.map((group, index) => ({ + id: index + 1, + ...group, + }))} + columns={columns} + isRowSelectable={() => false} + /> + + {group && ( + <> + closeModal(ModalState.EDIT)} + refetchGroups={refetchGroups} + group={group} + eventId={group.event._id} + /> + closeModal(ModalState.VIEW)} + group={group} + /> + + )} +
+ ); +} + +export default groups; diff --git a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx index c95a4e7da2..8168ac0b58 100644 --- a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx +++ b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx @@ -30,6 +30,7 @@ import Loader from 'components/Loader/Loader'; import { USER_EVENTS_VOLUNTEER } from 'GraphQl/Queries/PlugInQueries'; import { CREATE_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Mutations/EventVolunteerMutation'; import { toast } from 'react-toastify'; +import { FaCheck } from 'react-icons/fa'; /** * The `UpcomingEvents` component displays list of upcoming events for the user to volunteer. @@ -59,7 +60,6 @@ const UpcomingEvents = (): JSX.Element => { const [searchValue, setSearchValue] = useState(''); const [searchTerm, setSearchTerm] = useState(''); const [searchBy, setSearchBy] = useState<'title' | 'location'>('title'); - const [_, setSortBy] = useState<'endDate_ASC' | 'endDate_DESC' | null>(null); const [createVolunteerMembership] = useMutation(CREATE_VOLUNTEER_MEMBERSHIP); @@ -197,31 +197,6 @@ const UpcomingEvents = (): JSX.Element => { - - - - {tCommon('sort')} - - - setSortBy('endDate_DESC')} - data-testid="endDate_DESC" - > - {t('latestEndDate')} - - setSortBy('endDate_ASC')} - data-testid="endDate_ASC" - > - {t('earliestEndDate')} - - -

@@ -288,7 +263,12 @@ const UpcomingEvents = (): JSX.Element => { disabled={isVolunteered || new Date(endDate) < new Date()} onClick={() => handleVolunteer(_id, null, 'requested')} > - + {isVolunteered ? ( + + ) : ( + + )} + {t(isVolunteered ? 'volunteered' : 'volunteer')}
diff --git a/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx b/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx index 270b8d75e2..5e8cf1ed27 100644 --- a/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx +++ b/src/screens/UserPortal/Volunteer/VolunteerManagement.tsx @@ -6,10 +6,11 @@ import { FaChevronLeft, FaTasks } from 'react-icons/fa'; import { useTranslation } from 'react-i18next'; import { Button, Dropdown } from 'react-bootstrap'; import { TbCalendarEvent } from 'react-icons/tb'; -import { FaRegEnvelopeOpen } from 'react-icons/fa6'; +import { FaRegEnvelopeOpen, FaUserGroup } from 'react-icons/fa6'; import UpcomingEvents from './UpcomingEvents/UpcomingEvents'; import Invitations from './Invitations/Invitations'; import Actions from './Actions/Actions'; +import Groups from './Groups/Groups'; /** * List of tabs for the volunteer dashboard. @@ -32,12 +33,16 @@ const volunteerDashboardTabs: { value: 'actions', icon: , }, + { + value: 'groups', + icon: , + }, ]; /** * Tab options for the volunteer management component. */ -type TabOptions = 'upcomingEvents' | 'invitations' | 'actions'; +type TabOptions = 'upcomingEvents' | 'invitations' | 'actions' | 'groups'; /** * `VolunteerManagement` component handles the display and navigation of different event management sections. @@ -192,6 +197,12 @@ const VolunteerManagement = (): JSX.Element => {
); + case 'groups': + return ( +
+ +
+ ); } })()}
diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index 275f8c6b51..d46f7d3f9c 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -28,9 +28,10 @@ export interface InterfaceActionItemCategoryList { export interface InterfaceActionItemInfo { _id: string; - assigneeType: 'EventVolunteer' | 'EventVolunteerGroup'; + assigneeType: 'EventVolunteer' | 'EventVolunteerGroup' | 'User'; assignee: InterfaceEventVolunteerInfo | null; assigneeGroup: InterfaceVolunteerGroupInfo | null; + assigneeUser: InterfaceUserInfo | null; assigner: InterfaceUserInfo; actionItemCategory: { _id: string; @@ -581,6 +582,9 @@ export interface InterfaceVolunteerGroupInfo { _id: string; name: string; description: string; + event: { + _id: string; + }; volunteersRequired: number; createdAt: string; creator: InterfaceUserInfo; @@ -652,3 +656,15 @@ export interface InterfaceVolunteerMembership { name: string; }; } + +export interface InterfaceVolunteerRank { + rank: number; + hoursVolunteered: number; + user: { + _id: string; + firstName: string; + lastName: string; + email: string; + image: string | null; + }; +} From fc17ac34d23111f55af235950a2b40ca8668d698 Mon Sep 17 00:00:00 2001 From: Glen Date: Fri, 1 Nov 2024 13:45:47 +0530 Subject: [PATCH 05/12] Add Screens In user portal for volunteer management & Add tests --- src/GraphQl/Queries/PlugInQueries.ts | 4 +- .../EventManagement/EventManagement.test.tsx | 15 +- .../EventManagement/EventManagement.tsx | 6 +- .../Requests/Requests.mocks.ts | 221 +++++++++ .../Requests/Requests.test.tsx | 254 ++++++++++ .../EventVolunteers/Requests/Requests.tsx | 12 +- .../VolunteerContainer.test.tsx | 94 ++++ .../EventVolunteers/VolunteerContainer.tsx | 3 + .../VolunteerGroupDeleteModal.test.tsx | 141 ++++++ .../VolunteerGroupModal.test.tsx | 349 +++++++++++++ .../VolunteerGroups/VolunteerGroupModal.tsx | 8 +- .../VolunteerGroupViewModal.test.tsx | 126 +++++ .../VolunteerGroupViewModal.tsx | 10 +- .../VolunteerGroups/VolunteerGroups.mocks.ts | 452 +++++++++++++++++ .../VolunteerGroups/VolunteerGroups.test.tsx | 235 +++++++++ .../VolunteerGroups/VolunteerGroups.tsx | 44 +- .../Volunteers/VolunteerCreateModal.test.tsx | 122 +++++ .../Volunteers/VolunteerCreateModal.tsx | 9 +- .../Volunteers/VolunteerDeleteModal.test.tsx | 129 +++++ .../Volunteers/VolunteerDeleteModal.tsx | 4 +- .../Volunteers/VolunteerViewModal.test.tsx | 101 ++++ .../Volunteers/VolunteerViewModal.tsx | 6 +- .../Volunteers/Volunteers.mocks.ts | 303 ++++++++++++ .../Volunteers/Volunteers.test.tsx | 261 ++++++++++ .../EventVolunteers/Volunteers/Volunteers.tsx | 41 +- .../FundCampaignPledge/PledgeModal.test.tsx | 4 +- src/screens/Leaderboard/Leaderboard.mocks.ts | 198 ++++++++ src/screens/Leaderboard/Leaderboard.test.tsx | 286 +++++++++++ src/screens/Leaderboard/Leaderboard.tsx | 8 +- .../ItemDeleteModal.test.tsx | 9 +- .../ItemModal.test.tsx | 449 ++++++++++++++++- .../OrganizationActionItems/ItemModal.tsx | 5 +- .../ItemUpdateStatusModal.test.tsx | 100 +++- .../ItemUpdateStatusModal.tsx | 35 +- .../ItemViewModal.test.tsx | 236 +++++++-- .../OrganizationActionItems/ItemViewModal.tsx | 71 ++- .../OrganizationActionItem.mocks.ts | 468 ++++++++++++++++-- .../OrganizationActionItems.test.tsx | 12 +- .../OrganizationActionItems.tsx | 46 +- .../OrganizationDashboard.test.tsx | 422 +++++++++------- .../OrganizationDashboard.tsx | 40 +- .../OrganizationDashboardMocks.ts | 144 +++++- .../UserPortal/Campaigns/PledgeModal.test.tsx | 4 +- .../Volunteer/Actions/Actions.mocks.ts | 268 ++++++++++ .../Volunteer/Actions/Actions.test.tsx | 224 +++++++++ .../UserPortal/Volunteer/Actions/Actions.tsx | 37 +- .../Volunteer/Groups/GroupModal.test.tsx | 308 ++++++++++++ .../Volunteer/Groups/GroupModal.tsx | 48 +- .../Volunteer/Groups/Groups.mocks.ts | 468 ++++++++++++++++++ .../Volunteer/Groups/Groups.test.tsx | 220 ++++++++ .../UserPortal/Volunteer/Groups/Groups.tsx | 19 +- .../Invitations/Invitations.mocks.ts | 263 ++++++++++ .../Invitations/Invitations.test.tsx | 325 ++++++++++++ .../Volunteer/Invitations/Invitations.tsx | 4 +- .../UpcomingEvents/UpcomingEvents.mocks.ts | 281 +++++++++++ .../UpcomingEvents/UpcomingEvents.test.tsx | 235 +++++++++ .../UpcomingEvents/UpcomingEvents.tsx | 24 +- .../Volunteer/VolunteerManagement.test.tsx | 128 +++++ .../Volunteer/VolunteerManagement.tsx | 3 +- src/state/reducers/userRoutersReducer.test.ts | 24 +- src/utils/interfaces.ts | 8 +- 61 files changed, 7822 insertions(+), 552 deletions(-) create mode 100644 src/screens/EventVolunteers/Requests/Requests.mocks.ts create mode 100644 src/screens/EventVolunteers/Requests/Requests.test.tsx create mode 100644 src/screens/EventVolunteers/VolunteerContainer.test.tsx create mode 100644 src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.test.tsx create mode 100644 src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.test.tsx create mode 100644 src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.test.tsx create mode 100644 src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.mocks.ts create mode 100644 src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx create mode 100644 src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.test.tsx create mode 100644 src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.test.tsx create mode 100644 src/screens/EventVolunteers/Volunteers/VolunteerViewModal.test.tsx create mode 100644 src/screens/EventVolunteers/Volunteers/Volunteers.mocks.ts create mode 100644 src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx create mode 100644 src/screens/Leaderboard/Leaderboard.mocks.ts create mode 100644 src/screens/Leaderboard/Leaderboard.test.tsx create mode 100644 src/screens/UserPortal/Volunteer/Actions/Actions.mocks.ts create mode 100644 src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx create mode 100644 src/screens/UserPortal/Volunteer/Groups/GroupModal.test.tsx create mode 100644 src/screens/UserPortal/Volunteer/Groups/Groups.mocks.ts create mode 100644 src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx create mode 100644 src/screens/UserPortal/Volunteer/Invitations/Invitations.mocks.ts create mode 100644 src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx create mode 100644 src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.mocks.ts create mode 100644 src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx create mode 100644 src/screens/UserPortal/Volunteer/VolunteerManagement.test.tsx diff --git a/src/GraphQl/Queries/PlugInQueries.ts b/src/GraphQl/Queries/PlugInQueries.ts index e884d22813..c24f44c25a 100644 --- a/src/GraphQl/Queries/PlugInQueries.ts +++ b/src/GraphQl/Queries/PlugInQueries.ts @@ -106,7 +106,7 @@ export const USER_EVENTS_VOLUNTEER = gql` $location_contains: String $first: Int $skip: Int - $currentDate: DateTime + $upcomingOnly: Boolean ) { eventsByOrganizationConnection( where: { @@ -116,7 +116,7 @@ export const USER_EVENTS_VOLUNTEER = gql` } first: $first skip: $skip - currentDate: $currentDate + upcomingOnly: $upcomingOnly ) { _id title diff --git a/src/screens/EventManagement/EventManagement.test.tsx b/src/screens/EventManagement/EventManagement.test.tsx index fb851ec72f..24b7e65e21 100644 --- a/src/screens/EventManagement/EventManagement.test.tsx +++ b/src/screens/EventManagement/EventManagement.test.tsx @@ -64,7 +64,7 @@ describe('Event Management', () => { test('Testing Event Management Screen', async () => { renderEventManagement(); - const dashboardTab = await screen.findByTestId('eventDashboadTab'); + const dashboardTab = await screen.findByTestId('eventDashboardTab'); expect(dashboardTab).toBeInTheDocument(); const dashboardButton = screen.getByTestId('dashboardBtn'); @@ -72,6 +72,7 @@ describe('Event Management', () => { expect(dashboardTab).toBeInTheDocument(); }); + test('Testing back button navigation when userType is SuperAdmin', async () => { setItem('SuperAdmin', true); renderEventManagement(); @@ -93,22 +94,28 @@ describe('Event Management', () => { const registrantsTab = screen.getByTestId('eventRegistrantsTab'); expect(registrantsTab).toBeInTheDocument(); - const eventActionsButton = screen.getByTestId('eventActionsBtn'); + const eventActionsButton = screen.getByTestId('actionsBtn'); userEvent.click(eventActionsButton); const eventActionsTab = screen.getByTestId('eventActionsTab'); expect(eventActionsTab).toBeInTheDocument(); - const eventAgendasButton = screen.getByTestId('eventAgendasBtn'); + const eventAgendasButton = screen.getByTestId('agendasBtn'); userEvent.click(eventAgendasButton); const eventAgendasTab = screen.getByTestId('eventAgendasTab'); expect(eventAgendasTab).toBeInTheDocument(); - const eventStatsButton = screen.getByTestId('eventStatsBtn'); + const eventStatsButton = screen.getByTestId('statisticsBtn'); userEvent.click(eventStatsButton); const eventStatsTab = screen.getByTestId('eventStatsTab'); expect(eventStatsTab).toBeInTheDocument(); + + const volunteerButton = screen.getByTestId('volunteersBtn'); + userEvent.click(volunteerButton); + + const eventVolunteersTab = screen.getByTestId('eventVolunteersTab'); + expect(eventVolunteersTab).toBeInTheDocument(); }); }); diff --git a/src/screens/EventManagement/EventManagement.tsx b/src/screens/EventManagement/EventManagement.tsx index a45721cb68..691584d7ea 100644 --- a/src/screens/EventManagement/EventManagement.tsx +++ b/src/screens/EventManagement/EventManagement.tsx @@ -5,11 +5,11 @@ import { Navigate, useNavigate, useParams } from 'react-router-dom'; import { FaChevronLeft, FaTasks } from 'react-icons/fa'; import { MdOutlineDashboard } from 'react-icons/md'; import EventRegistrantsIcon from 'assets/svgs/people.svg?react'; -import { IoMdStats } from 'react-icons/io'; +import { IoMdStats, IoIosHand } from 'react-icons/io'; import EventAgendaItemsIcon from 'assets/svgs/agenda-items.svg?react'; import { useTranslation } from 'react-i18next'; import { Button, Dropdown } from 'react-bootstrap'; -import { IoIosHand } from 'react-icons/io'; + import EventDashboard from 'components/EventManagement/Dashboard/EventDashboard'; import OrganizationActionItems from 'screens/OrganizationActionItems/OrganizationActionItems'; import VolunteerContainer from 'screens/EventVolunteers/VolunteerContainer'; @@ -217,7 +217,7 @@ const EventManagement = (): JSX.Element => { switch (tab) { case 'dashboard': return ( -
+
); diff --git a/src/screens/EventVolunteers/Requests/Requests.mocks.ts b/src/screens/EventVolunteers/Requests/Requests.mocks.ts new file mode 100644 index 0000000000..4d2ae14ed0 --- /dev/null +++ b/src/screens/EventVolunteers/Requests/Requests.mocks.ts @@ -0,0 +1,221 @@ +import { UPDATE_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Mutations/EventVolunteerMutation'; +import { USER_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Queries/EventVolunteerQueries'; + +const membership1 = { + _id: 'membershipId1', + status: 'requested', + createdAt: '2024-10-29T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 1', + startDate: '2044-10-31', + }, + volunteer: { + _id: 'volunteerId1', + user: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: 'img-url', + }, + }, + group: null, +}; + +const membership2 = { + _id: 'membershipId2', + status: 'requested', + createdAt: '2024-10-30T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 2', + startDate: '2044-11-31', + }, + volunteer: { + _id: 'volunteerId1', + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + group: null, +}; + +export const MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + status: 'requested', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + status: 'requested', + }, + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + getVolunteerMembership: [membership2, membership1], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + status: 'requested', + }, + orderBy: 'createdAt_ASC', + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + status: 'requested', + userName: 'T', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership2], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'rejected', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + status: 'requested', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + status: 'requested', + userName: undefined, + }, + orderBy: undefined, + }, + }, + error: new Error('Mock Graphql USER_VOLUNTEER_MEMBERSHIP Error'), + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_MEMBERSHIP Error'), + }, +]; + +export const UPDATE_ERROR_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + status: 'requested', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_MEMBERSHIP Error'), + }, +]; diff --git a/src/screens/EventVolunteers/Requests/Requests.test.tsx b/src/screens/EventVolunteers/Requests/Requests.test.tsx new file mode 100644 index 0000000000..540c20ca09 --- /dev/null +++ b/src/screens/EventVolunteers/Requests/Requests.test.tsx @@ -0,0 +1,254 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Requests from './Requests'; +import type { ApolloLink } from '@apollo/client'; +import { + MOCKS, + EMPTY_MOCKS, + ERROR_MOCKS, + UPDATE_ERROR_MOCKS, +} from './Requests.mocks'; +import { toast } from 'react-toastify'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const link4 = new StaticMockLink(UPDATE_ERROR_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const renderRequests = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> +
} + /> + + + + + + , + ); +}; + +describe('Testing Requests Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> +
} + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Requests screen', async () => { + renderRequests(link1); + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + }); + + it('Check Sorting Functionality', async () => { + renderRequests(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by createdAt_DESC + fireEvent.click(sortBtn); + const createdAtDESC = await screen.findByTestId('createdAt_DESC'); + expect(createdAtDESC).toBeInTheDocument(); + fireEvent.click(createdAtDESC); + + let volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + + // Sort by createdAt_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const createdAtASC = await screen.findByTestId('createdAt_ASC'); + expect(createdAtASC).toBeInTheDocument(); + fireEvent.click(createdAtASC); + + volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('John Doe'); + }); + + it('Search Requests by volunteerName and clear the input by backspace', async () => { + renderRequests(link1); + + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Clear the search input by backspace + userEvent.type(searchInput, 'T{backspace}'); + await waitFor(() => { + const volunteerName = screen.getAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('John Doe'); + }); + }); + + it('Search Requests by volunteer name on press of ENTER', async () => { + renderRequests(link1); + + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'T'); + userEvent.type(searchInput, '{enter}'); + + await waitFor(() => { + const volunteerName = screen.getAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + }); + }); + + it('Search Requests by volunteer name on click of search button', async () => { + renderRequests(link1); + + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'T'); + userEvent.click(screen.getByTestId('searchBtn')); + + await waitFor(() => { + const volunteerName = screen.getAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + }); + }); + + it('should render screen with No Requests', async () => { + renderRequests(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noRequests)).toBeInTheDocument(); + }); + }); + + it('Error while fetching requests data', async () => { + renderRequests(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Accept Request', async () => { + renderRequests(link1); + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + const acceptBtn = await screen.findAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + + // Accept Request + userEvent.click(acceptBtn[0]); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.requestAccepted); + }); + }); + + it('Reject Request', async () => { + renderRequests(link1); + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + const rejectBtn = await screen.findAllByTestId('rejectBtn'); + expect(rejectBtn).toHaveLength(2); + + // Reject Request + userEvent.click(rejectBtn[0]); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.requestRejected); + }); + }); + + it('Error in Update Request Mutation', async () => { + renderRequests(link4); + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + const acceptBtn = await screen.findAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + + // Accept Request + userEvent.click(acceptBtn[0]); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/EventVolunteers/Requests/Requests.tsx b/src/screens/EventVolunteers/Requests/Requests.tsx index cb8342d02a..869b739993 100644 --- a/src/screens/EventVolunteers/Requests/Requests.tsx +++ b/src/screens/EventVolunteers/Requests/Requests.tsx @@ -16,7 +16,7 @@ import { Stack } from '@mui/material'; import Avatar from 'components/Avatar/Avatar'; import styles from '../EventVolunteers.module.css'; import { USER_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Queries/EventVolunteerQueries'; -import { InterfaceVolunteerMembership } from 'utils/interfaces'; +import type { InterfaceVolunteerMembership } from 'utils/interfaces'; import dayjs from 'dayjs'; import { UPDATE_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Mutations/EventVolunteerMutation'; import { toast } from 'react-toastify'; @@ -166,7 +166,7 @@ function requests(): JSX.Element { sortable: false, headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { - const { _id, firstName, lastName, image } = params.row.volunteer.user; + const { firstName, lastName, image } = params.row.volunteer.user; return (
) : (
updateMembershipStatus(params.row._id, 'accepted')} > @@ -234,7 +234,7 @@ function requests(): JSX.Element { size="sm" variant="danger" className="rounded" - data-testid={`rejectBtn${params.row.id}`} + data-testid={`rejectBtn`} onClick={() => updateMembershipStatus(params.row._id, 'rejected')} > diff --git a/src/screens/EventVolunteers/VolunteerContainer.test.tsx b/src/screens/EventVolunteers/VolunteerContainer.test.tsx new file mode 100644 index 0000000000..928d04195c --- /dev/null +++ b/src/screens/EventVolunteers/VolunteerContainer.test.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import { MockedProvider } from '@apollo/react-testing'; +import { I18nextProvider } from 'react-i18next'; +import i18n from 'utils/i18n'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import { store } from 'state/store'; +import VolunteerContainer from './VolunteerContainer'; +import userEvent from '@testing-library/user-event'; +import { MOCKS } from './Volunteers/Volunteers.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { LocalizationProvider } from '@mui/x-date-pickers'; + +const link1 = new StaticMockLink(MOCKS); + +const renderVolunteerContainer = (): RenderResult => { + return render( + + + + + + + } + /> + paramsError
} + /> + + + + + + , + ); +}; + +describe('Testing Volunteer Container', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> +
} + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + test('Testing Volunteer Container Screen -> Toggle screens', async () => { + renderVolunteerContainer(); + + const groupRadio = await screen.findByTestId('groupsRadio'); + expect(groupRadio).toBeInTheDocument(); + userEvent.click(groupRadio); + + const requestsRadio = await screen.findByTestId('requestsRadio'); + expect(requestsRadio).toBeInTheDocument(); + userEvent.click(requestsRadio); + + const individualRadio = await screen.findByTestId('individualRadio'); + expect(individualRadio).toBeInTheDocument(); + userEvent.click(individualRadio); + }); +}); diff --git a/src/screens/EventVolunteers/VolunteerContainer.tsx b/src/screens/EventVolunteers/VolunteerContainer.tsx index 29c3e8fed1..1a425a706e 100644 --- a/src/screens/EventVolunteers/VolunteerContainer.tsx +++ b/src/screens/EventVolunteers/VolunteerContainer.tsx @@ -56,6 +56,7 @@ function volunteerContainer(): JSX.Element {
} + /> + + + + + + , + ); +}; + +describe('Testing VolunteerGroups Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> + } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Groups screen', async () => { + renderVolunteerGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + }); + + it('Check Sorting Functionality', async () => { + renderVolunteerGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by members_DESC + fireEvent.click(sortBtn); + const membersDESC = await screen.findByTestId('members_DESC'); + expect(membersDESC).toBeInTheDocument(); + fireEvent.click(membersDESC); + + let groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + + // Sort by members_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const membersASC = await screen.findByTestId('members_ASC'); + expect(membersASC).toBeInTheDocument(); + fireEvent.click(membersASC); + + groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 2'); + }); + + it('Search by Groups and clear the input by backspace', async () => { + renderVolunteerGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Clear the search input by backspace + userEvent.type(searchInput, '1{backspace}'); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('Search by Groups on press of ENTER', async () => { + renderVolunteerGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByGroup = await screen.findByTestId('group'); + expect(searchByGroup).toBeInTheDocument(); + userEvent.click(searchByGroup); + + userEvent.type(searchInput, '1{enter}'); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('Search by Leader on click of search button', async () => { + renderVolunteerGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByLeader = await screen.findByTestId('leader'); + expect(searchByLeader).toBeInTheDocument(); + userEvent.click(searchByLeader); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'Bruce'); + userEvent.click(await screen.findByTestId('searchBtn')); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('should render screen with No Groups', async () => { + renderVolunteerGroups(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteerGroups)).toBeInTheDocument(); + }); + }); + + it('Error while fetching groups data', async () => { + renderVolunteerGroups(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Open and close ViewModal', async () => { + renderVolunteerGroups(link1); + + const viewGroupBtn = await screen.findAllByTestId('viewGroupBtn'); + userEvent.click(viewGroupBtn[0]); + + expect(await screen.findByText(t.groupDetails)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('volunteerViewModalCloseBtn')); + }); + + it('Open and Close Delete Modal', async () => { + renderVolunteerGroups(link1); + + const deleteGroupBtn = await screen.findAllByTestId('deleteGroupBtn'); + userEvent.click(deleteGroupBtn[0]); + + expect(await screen.findByText(t.deleteGroup)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and close GroupModal (Edit)', async () => { + renderVolunteerGroups(link1); + + const editGroupBtn = await screen.findAllByTestId('editGroupBtn'); + userEvent.click(editGroupBtn[0]); + + expect(await screen.findAllByText(t.updateGroup)).toHaveLength(2); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and close GroupModal (Create)', async () => { + renderVolunteerGroups(link1); + + const createGroupBtn = await screen.findByTestId('createGroupBtn'); + userEvent.click(createGroupBtn); + + expect(await screen.findAllByText(t.createGroup)).toHaveLength(2); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); +}); diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx index e9360b5243..89ceb757a3 100644 --- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx @@ -72,7 +72,7 @@ function volunteerGroups(): JSX.Element { const [modalMode, setModalMode] = useState<'create' | 'edit'>('create'); const [searchValue, setSearchValue] = useState(''); const [searchTerm, setSearchTerm] = useState(''); - const [sortBy, setSortBy] = useState<'member_ASC' | 'member_DESC' | null>( + const [sortBy, setSortBy] = useState<'members_ASC' | 'members_DESC' | null>( null, ); const [searchBy, setSearchBy] = useState<'leader' | 'group'>('group'); @@ -264,7 +264,7 @@ function volunteerGroups(): JSX.Element { size="sm" style={{ minWidth: '32px' }} className="me-2 rounded" - data-testid={`viewGroupBtn${params.row.id}`} + data-testid="viewGroupBtn" onClick={() => handleModalClick(params.row, ModalState.VIEW)} > @@ -273,7 +273,7 @@ function volunteerGroups(): JSX.Element { variant="success" size="sm" className="me-2 rounded" - data-testid={`editGroupBtn${params.row.id}`} + data-testid="editGroupBtn" onClick={() => handleModalClick(params.row, ModalState.SAME)} > @@ -282,7 +282,7 @@ function volunteerGroups(): JSX.Element { size="sm" variant="danger" className="rounded" - data-testid={`deleteGroupBtn${params.row.id}`} + data-testid="deleteGroupBtn" onClick={() => handleModalClick(params.row, ModalState.DELETE)} > @@ -366,14 +366,14 @@ function volunteerGroups(): JSX.Element { setSortBy('member_DESC')} - data-testid="member_DESC" + onClick={() => setSortBy('members_DESC')} + data-testid="members_DESC" > {t('mostMembers')} setSortBy('member_ASC')} - data-testid="member_ASC" + onClick={() => setSortBy('members_ASC')} + data-testid="members_ASC" > {t('leastMembers')} @@ -385,7 +385,7 @@ function volunteerGroups(): JSX.Element { variant="success" onClick={() => handleModalClick(null, ModalState.SAME)} style={{ marginTop: '11px' }} - data-testid="createActionItemBtn" + data-testid="createGroupBtn" > {tCommon('create')} @@ -429,19 +429,21 @@ function volunteerGroups(): JSX.Element { mode={modalMode} /> - closeModal(ModalState.DELETE)} - refetchGroups={refetchGroups} - group={group} - /> - {group && ( - closeModal(ModalState.VIEW)} - group={group} - /> + <> + closeModal(ModalState.VIEW)} + group={group} + /> + + closeModal(ModalState.DELETE)} + refetchGroups={refetchGroups} + group={group} + /> + )} ); diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.test.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.test.tsx new file mode 100644 index 0000000000..cac8fe94f0 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.test.tsx @@ -0,0 +1,122 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { + fireEvent, + render, + screen, + waitFor, + within, +} from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18n from 'utils/i18nForTest'; +import { MOCKS, MOCKS_ERROR } from './Volunteers.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceVolunteerCreateModal } from './VolunteerCreateModal'; +import VolunteerCreateModal from './VolunteerCreateModal'; +import userEvent from '@testing-library/user-event'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceVolunteerCreateModal[] = [ + { + isOpen: true, + hide: jest.fn(), + eventId: 'eventId', + orgId: 'orgId', + refetchVolunteers: jest.fn(), + }, +]; + +const renderCreateModal = ( + link: ApolloLink, + props: InterfaceVolunteerCreateModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing VolunteerCreateModal', () => { + it('VolunteerCreateModal -> Create', async () => { + renderCreateModal(link1, itemProps[0]); + expect(screen.getAllByText(t.addVolunteer)).toHaveLength(2); + + // Select Volunteers + const membersSelect = await screen.findByTestId('membersSelect'); + expect(membersSelect).toBeInTheDocument(); + const volunteerInputField = within(membersSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('John Doe'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.volunteerAdded); + expect(itemProps[0].refetchVolunteers).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('VolunteerCreateModal -> Create -> Error', async () => { + renderCreateModal(link2, itemProps[0]); + expect(screen.getAllByText(t.addVolunteer)).toHaveLength(2); + + // Select Volunteers + const membersSelect = await screen.findByTestId('membersSelect'); + expect(membersSelect).toBeInTheDocument(); + const volunteerInputField = within(membersSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('John Doe'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx index 810dd4ffcd..6b4a1e3f0c 100644 --- a/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx +++ b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx @@ -25,6 +25,8 @@ export interface InterfaceVolunteerCreateModal { * @param isOpen - Indicates whether the modal is open. * @param hide - Function to close the modal. * @param eventId - The ID of the event associated with volunteer. + * @param orgId - The ID of the organization associated with volunteer. + * @param refetchVolunteers - Function to refetch the volunteers after adding a volunteer. * * @returns The rendered modal component. * @@ -64,7 +66,6 @@ const VolunteerCreateModal: React.FC = ({ useEffect(() => { if (memberData) { - /*istanbul ignore next*/ setMembers(memberData.organizations[0].members); } }, [memberData]); @@ -102,7 +103,7 @@ const VolunteerCreateModal: React.FC = ({ variant="danger" onClick={hide} className={styles.modalCloseBtn} - data-testid="volunteerCreateModalCloseBtn" + data-testid="modalCloseBtn" > @@ -113,7 +114,7 @@ const VolunteerCreateModal: React.FC = ({ onSubmitCapture={addVolunteerHandler} className="p-3" > - {/* A Multi-select dropdown enables admin to select more than one pledger for participating in a pledge */} + {/* A Multi-select dropdown enables admin to invite a member as volunteer */} = ({ diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.test.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.test.tsx new file mode 100644 index 0000000000..dd9d6d5985 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.test.tsx @@ -0,0 +1,129 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18n from 'utils/i18nForTest'; +import { MOCKS, MOCKS_ERROR } from './Volunteers.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceDeleteVolunteerModal } from './VolunteerDeleteModal'; +import VolunteerDeleteModal from './VolunteerDeleteModal'; +import userEvent from '@testing-library/user-event'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceDeleteVolunteerModal[] = [ + { + isOpen: true, + hide: jest.fn(), + refetchVolunteers: jest.fn(), + volunteer: { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 10, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [ + { + _id: 'groupId1', + name: 'group1', + volunteers: [ + { + _id: 'volunteerId1', + }, + ], + }, + ], + }, + }, +]; + +const renderVolunteerDeleteModal = ( + link: ApolloLink, + props: InterfaceDeleteVolunteerModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing Volunteer Delete Modal', () => { + it('Delete Volunteer', async () => { + renderVolunteerDeleteModal(link1, itemProps[0]); + expect(screen.getByText(t.removeVolunteer)).toBeInTheDocument(); + + const yesBtn = screen.getByTestId('deleteyesbtn'); + expect(yesBtn).toBeInTheDocument(); + userEvent.click(yesBtn); + + await waitFor(() => { + expect(itemProps[0].refetchVolunteers).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.volunteerRemoved); + }); + }); + + it('Close Delete Modal', async () => { + renderVolunteerDeleteModal(link1, itemProps[0]); + expect(screen.getByText(t.removeVolunteer)).toBeInTheDocument(); + + const noBtn = screen.getByTestId('deletenobtn'); + expect(noBtn).toBeInTheDocument(); + userEvent.click(noBtn); + + await waitFor(() => { + expect(itemProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('Delete Volunteer -> Error', async () => { + renderVolunteerDeleteModal(link2, itemProps[0]); + expect(screen.getByText(t.removeVolunteer)).toBeInTheDocument(); + + const yesBtn = screen.getByTestId('deleteyesbtn'); + expect(yesBtn).toBeInTheDocument(); + userEvent.click(yesBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx index c8b5a67062..8f253fdf50 100644 --- a/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx +++ b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx @@ -10,7 +10,7 @@ import { DELETE_VOLUNTEER } from 'GraphQl/Mutations/EventVolunteerMutation'; export interface InterfaceDeleteVolunteerModal { isOpen: boolean; hide: () => void; - volunteer: InterfaceEventVolunteerInfo | null; + volunteer: InterfaceEventVolunteerInfo; refetchVolunteers: () => void; } @@ -56,7 +56,7 @@ const VolunteerDeleteModal: React.FC = ({ try { await deleteVolunteer({ variables: { - id: volunteer?._id, + id: volunteer._id, }, }); refetchVolunteers(); diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.test.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.test.tsx new file mode 100644 index 0000000000..155dba8464 --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.test.tsx @@ -0,0 +1,101 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import i18n from 'utils/i18nForTest'; +import type { InterfaceVolunteerViewModal } from './VolunteerViewModal'; +import VolunteerViewModal from './VolunteerViewModal'; + +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceVolunteerViewModal[] = [ + { + isOpen: true, + hide: jest.fn(), + volunteer: { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 10, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [ + { + _id: 'groupId1', + name: 'group1', + volunteers: [ + { + _id: 'volunteerId1', + }, + ], + }, + ], + }, + }, + { + isOpen: true, + hide: jest.fn(), + volunteer: { + _id: 'volunteerId2', + hasAccepted: false, + hoursVolunteered: null, + user: { + _id: 'userId3', + firstName: 'Bruce', + lastName: 'Graza', + image: 'img-url', + }, + assignments: [], + groups: [], + }, + }, +]; + +const renderVolunteerViewModal = ( + props: InterfaceVolunteerViewModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing VolunteerViewModal', () => { + it('Render VolunteerViewModal (variation 1)', async () => { + renderVolunteerViewModal(itemProps[0]); + expect(screen.getByText(t.volunteerDetails)).toBeInTheDocument(); + expect(screen.getByTestId('volunteer_avatar')).toBeInTheDocument(); + }); + + it('Render VolunteerViewModal (variation 2)', async () => { + renderVolunteerViewModal(itemProps[1]); + expect(screen.getByText(t.volunteerDetails)).toBeInTheDocument(); + expect(screen.getByTestId('volunteer_image')).toBeInTheDocument(); + }); +}); diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx index 231396948b..0904d34b9c 100644 --- a/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx +++ b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx @@ -59,7 +59,7 @@ const VolunteerViewModal: React.FC = ({ variant="danger" onClick={hide} className={styles.modalCloseBtn} - data-testid="volunteerViewModalCloseBtn" + data-testid="modalCloseBtn" > @@ -82,7 +82,7 @@ const VolunteerViewModal: React.FC = ({ Volunteer ) : ( @@ -91,7 +91,7 @@ const VolunteerViewModal: React.FC = ({ key={user._id + '1'} containerStyle={styles.imageContainer} avatarStyle={styles.TableImage} - dataTestId={`${user.firstName}_avatar`} + dataTestId="volunteer_avatar" name={user.firstName + ' ' + user.lastName} alt={user.firstName + ' ' + user.lastName} /> diff --git a/src/screens/EventVolunteers/Volunteers/Volunteers.mocks.ts b/src/screens/EventVolunteers/Volunteers/Volunteers.mocks.ts new file mode 100644 index 0000000000..72c927b8ff --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/Volunteers.mocks.ts @@ -0,0 +1,303 @@ +import { + ADD_VOLUNTEER, + DELETE_VOLUNTEER, +} from 'GraphQl/Mutations/EventVolunteerMutation'; +import { EVENT_VOLUNTEER_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; +import { MEMBERS_LIST } from 'GraphQl/Queries/Queries'; + +const volunteer1 = { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 10, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [ + { + _id: 'groupId1', + name: 'group1', + volunteers: [ + { + _id: 'volunteerId1', + }, + ], + }, + ], +}; + +const volunteer2 = { + _id: 'volunteerId2', + hasAccepted: false, + hoursVolunteered: null, + user: { + _id: 'userId3', + firstName: 'Bruce', + lastName: 'Graza', + image: 'img-url', + }, + assignments: [], + groups: [], +}; + +export const MOCKS = [ + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer1, volunteer2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: 'hoursVolunteered_ASC', + }, + }, + result: { + data: { + getEventVolunteers: [volunteer2, volunteer1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: 'hoursVolunteered_DESC', + }, + }, + result: { + data: { + getEventVolunteers: [volunteer1, volunteer2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: 'T' }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '', hasAccepted: false }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '', hasAccepted: false }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '', hasAccepted: true }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [volunteer1], + }, + }, + }, + { + request: { + query: DELETE_VOLUNTEER, + variables: { + id: 'volunteerId1', + }, + }, + result: { + data: { + removeEventVolunteer: { + _id: 'volunteerId1', + }, + }, + }, + }, + { + request: { + query: MEMBERS_LIST, + variables: { + id: 'orgId', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ + { + _id: 'userId2', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + { + _id: 'userId3', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ADD_VOLUNTEER, + variables: { + data: { + eventId: 'eventId', + userId: 'userId3', + }, + }, + }, + result: { + data: { + createEventVolunteer: { + _id: 'volunteerId1', + }, + }, + }, + }, +]; + +export const MOCKS_ERROR = [ + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: null, + }, + }, + error: new Error('An error occurred'), + }, + { + request: { + query: DELETE_VOLUNTEER, + variables: { + id: 'volunteerId1', + }, + }, + error: new Error('An error occurred'), + }, + { + request: { + query: MEMBERS_LIST, + variables: { + id: 'orgId', + }, + }, + result: { + data: { + organizations: [ + { + _id: 'orgId', + members: [ + { + _id: 'userId2', + firstName: 'Harve', + lastName: 'Lance', + email: 'harve@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + { + _id: 'userId3', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@example.com', + image: '', + organizationsBlockedBy: [], + createdAt: '2024-02-14', + }, + ], + }, + ], + }, + }, + }, + { + request: { + query: ADD_VOLUNTEER, + variables: { + data: { + eventId: 'eventId', + userId: 'userId3', + }, + }, + }, + error: new Error('An error occurred'), + }, +]; + +export const MOCKS_EMPTY = [ + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { + where: { eventId: 'eventId', name_contains: '' }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteers: [], + }, + }, + }, +]; diff --git a/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx b/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx new file mode 100644 index 0000000000..00ff450fca --- /dev/null +++ b/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx @@ -0,0 +1,261 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Volunteers from './Volunteers'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, MOCKS_EMPTY, MOCKS_ERROR } from './Volunteers.mocks'; + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(MOCKS_ERROR); +const link3 = new StaticMockLink(MOCKS_EMPTY); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const renderVolunteers = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> + } + /> + + + + + + , + ); +}; + +describe('Testing Volunteers Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> + } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Volunteers screen', async () => { + renderVolunteers(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + }); + + it('Check Sorting Functionality', async () => { + renderVolunteers(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by hoursVolunteered_DESC + fireEvent.click(sortBtn); + const hoursVolunteeredDESC = await screen.findByTestId( + 'hoursVolunteered_DESC', + ); + expect(hoursVolunteeredDESC).toBeInTheDocument(); + fireEvent.click(hoursVolunteeredDESC); + + let volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + + // Sort by hoursVolunteered_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const hoursVolunteeredASC = await screen.findByTestId( + 'hoursVolunteered_ASC', + ); + expect(hoursVolunteeredASC).toBeInTheDocument(); + fireEvent.click(hoursVolunteeredASC); + + volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Bruce Graza'); + }); + + it('Filter Volunteers by status (All)', async () => { + renderVolunteers(link1); + + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + + // Filter by All + fireEvent.click(filterBtn); + await waitFor(() => { + expect(screen.getByTestId('statusAll')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('statusAll')); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName).toHaveLength(2); + }); + + it('Filter Volunteers by status (Pending)', async () => { + renderVolunteers(link1); + + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + + // Filter by Pending + fireEvent.click(filterBtn); + await waitFor(() => { + expect(screen.getByTestId('statusPending')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('statusPending')); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Bruce Graza'); + }); + + it('Filter Volunteers by status (Accepted)', async () => { + renderVolunteers(link1); + + const filterBtn = await screen.findByTestId('filter'); + expect(filterBtn).toBeInTheDocument(); + + // Filter by Accepted + fireEvent.click(filterBtn); + await waitFor(() => { + expect(screen.getByTestId('statusAccepted')).toBeInTheDocument(); + }); + fireEvent.click(screen.getByTestId('statusAccepted')); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('Search and clear the input by backspace', async () => { + renderVolunteers(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Clear the search input by backspace + userEvent.type(searchInput, 'T{backspace}'); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName).toHaveLength(2); + }); + + it('Search on press of ENTER', async () => { + renderVolunteers(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + userEvent.type(searchInput, 'T{enter}'); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('Search on click of search button', async () => { + renderVolunteers(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'T'); + userEvent.click(await screen.findByTestId('searchBtn')); + + const volunteerName = await screen.findAllByTestId('volunteerName'); + expect(volunteerName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('should render screen with No Volunteers', async () => { + renderVolunteers(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteers)).toBeInTheDocument(); + }); + }); + + it('Error while fetching volunteers data', async () => { + renderVolunteers(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Open and close Volunteer Modal (View)', async () => { + renderVolunteers(link1); + + const viewItemBtn = await screen.findAllByTestId('viewItemBtn'); + userEvent.click(viewItemBtn[0]); + + expect(await screen.findByText(t.volunteerDetails)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and Close Volunteer Modal (Delete)', async () => { + renderVolunteers(link1); + + const deleteItemBtn = await screen.findAllByTestId('deleteItemBtn'); + userEvent.click(deleteItemBtn[0]); + + expect(await screen.findByText(t.removeVolunteer)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and close Volunteer Modal (Create)', async () => { + renderVolunteers(link1); + + const addVolunteerBtn = await screen.findByTestId('addVolunteerBtn'); + userEvent.click(addVolunteerBtn); + + expect(await screen.findAllByText(t.addVolunteer)).toHaveLength(2); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); +}); diff --git a/src/screens/EventVolunteers/Volunteers/Volunteers.tsx b/src/screens/EventVolunteers/Volunteers/Volunteers.tsx index 17006296a6..fad3f404a5 100644 --- a/src/screens/EventVolunteers/Volunteers/Volunteers.tsx +++ b/src/screens/EventVolunteers/Volunteers/Volunteers.tsx @@ -22,7 +22,7 @@ import { Chip, Stack } from '@mui/material'; import Avatar from 'components/Avatar/Avatar'; import styles from '../EventVolunteers.module.css'; import { EVENT_VOLUNTEER_LIST } from 'GraphQl/Queries/EventVolunteerQueries'; -import { InterfaceEventVolunteerInfo } from 'utils/interfaces'; +import type { InterfaceEventVolunteerInfo } from 'utils/interfaces'; import VolunteerCreateModal from './VolunteerCreateModal'; import VolunteerDeleteModal from './VolunteerDeleteModal'; import VolunteerViewModal from './VolunteerViewModal'; @@ -61,9 +61,9 @@ const dataGridStyle = { }; /** - * Component for managing and displaying action items within an organization. + * Component for managing and displaying event volunteers realted to an event. * - * This component allows users to view, filter, sort, and create action items. It also handles fetching and displaying related data such as action item categories and members. + * This component allows users to view, filter, sort, and create volunteers. It also handles fetching and displaying related data such as volunteer acceptance status, etc. * * @returns The rendered component. */ @@ -180,19 +180,20 @@ function volunteers(): JSX.Element { return (
{image ? ( volunteer ) : (
)} - {params.row.user.firstName + ' ' + params.row.user.lastName} + {firstName + ' ' + lastName}
); }, @@ -281,7 +282,7 @@ function volunteers(): JSX.Element { size="sm" style={{ minWidth: '32px' }} className="me-2 rounded" - data-testid={`viewItemBtn${params.row.id}`} + data-testid="viewItemBtn" onClick={() => handleOpenModal(params.row, ModalState.VIEW)} > @@ -290,7 +291,7 @@ function volunteers(): JSX.Element { size="sm" variant="danger" className="rounded" - data-testid={`deleteItemBtn${params.row.id}`} + data-testid="deleteItemBtn" onClick={() => handleOpenModal(params.row, ModalState.DELETE)} > @@ -439,18 +440,20 @@ function volunteers(): JSX.Element { refetchVolunteers={refetchVolunteers} /> - closeModal(ModalState.DELETE)} - volunteer={volunteer} - refetchVolunteers={refetchVolunteers} - /> {volunteer && ( - closeModal(ModalState.VIEW)} - volunteer={volunteer} - /> + <> + closeModal(ModalState.VIEW)} + volunteer={volunteer} + /> + closeModal(ModalState.DELETE)} + volunteer={volunteer} + refetchVolunteers={refetchVolunteers} + /> + )} ); diff --git a/src/screens/FundCampaignPledge/PledgeModal.test.tsx b/src/screens/FundCampaignPledge/PledgeModal.test.tsx index 49c0447992..50d6c94624 100644 --- a/src/screens/FundCampaignPledge/PledgeModal.test.tsx +++ b/src/screens/FundCampaignPledge/PledgeModal.test.tsx @@ -57,7 +57,7 @@ const pledgeProps: InterfacePledgeModal[] = [ _id: '1', firstName: 'John', lastName: 'Doe', - image: null, + image: undefined, }, ], }, @@ -81,7 +81,7 @@ const pledgeProps: InterfacePledgeModal[] = [ _id: '1', firstName: 'John', lastName: 'Doe', - image: null, + image: undefined, }, ], }, diff --git a/src/screens/Leaderboard/Leaderboard.mocks.ts b/src/screens/Leaderboard/Leaderboard.mocks.ts new file mode 100644 index 0000000000..b6b22c832a --- /dev/null +++ b/src/screens/Leaderboard/Leaderboard.mocks.ts @@ -0,0 +1,198 @@ +import { VOLUNTEER_RANKING } from 'GraphQl/Queries/EventVolunteerQueries'; + +const rank1 = { + rank: 1, + hoursVolunteered: 5, + user: { + _id: 'userId1', + lastName: 'Bradley', + firstName: 'Teresa', + image: 'image-url', + email: 'testuser4@example.com', + }, +}; + +const rank2 = { + rank: 2, + hoursVolunteered: 4, + user: { + _id: 'userId2', + lastName: 'Garza', + firstName: 'Bruce', + image: null, + email: 'testuser5@example.com', + }, +}; + +const rank3 = { + rank: 3, + hoursVolunteered: 3, + user: { + _id: 'userId3', + lastName: 'Doe', + firstName: 'John', + image: null, + email: 'testuser6@example.com', + }, +}; + +const rank4 = { + rank: 4, + hoursVolunteered: 2, + user: { + _id: 'userId4', + lastName: 'Doe', + firstName: 'Jane', + image: null, + email: 'testuser7@example.com', + }, +}; + +export const MOCKS = [ + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1, rank2, rank3, rank4], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_ASC', + timeFrame: 'allTime', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank4, rank3, rank2, rank1], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'weekly', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'monthly', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1, rank2], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'yearly', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1, rank2, rank3], + }, + }, + }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + nameContains: 'T', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [rank1], + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + nameContains: '', + }, + }, + }, + result: { + data: { + getVolunteerRanks: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + nameContains: '', + }, + }, + }, + error: new Error('Mock Graphql VOLUNTEER_RANKING Error'), + }, +]; diff --git a/src/screens/Leaderboard/Leaderboard.test.tsx b/src/screens/Leaderboard/Leaderboard.test.tsx new file mode 100644 index 0000000000..90f7177174 --- /dev/null +++ b/src/screens/Leaderboard/Leaderboard.test.tsx @@ -0,0 +1,286 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Leaderboard from './Leaderboard'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, EMPTY_MOCKS, ERROR_MOCKS } from './Leaderboard.mocks'; + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify(i18n.getDataByLanguage('en')?.translation.leaderboard ?? {}), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const renderLeaderboard = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> + } + /> + } + /> + + + + + + , + ); +}; + +describe('Testing Leaderboard Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> + } + /> + + + + + , + ); + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Leaderboard screen', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + }); + + it('Check Sorting Functionality', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + const sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by hours_DESC + fireEvent.click(sortBtn); + const hoursDesc = await screen.findByTestId('hours_DESC'); + expect(hoursDesc).toBeInTheDocument(); + fireEvent.click(hoursDesc); + + let userName = await screen.findAllByTestId('userName'); + expect(userName[0]).toHaveTextContent('Teresa Bradley'); + + // Sort by hours_ASC + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const hoursAsc = await screen.findByTestId('hours_ASC'); + expect(hoursAsc).toBeInTheDocument(); + fireEvent.click(hoursAsc); + + userName = await screen.findAllByTestId('userName'); + expect(userName[0]).toHaveTextContent('Jane Doe'); + }); + + it('Check Timeframe filter Functionality (All Time)', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + // Filter by allTime + const filter = await screen.findByTestId('timeFrame'); + expect(filter).toBeInTheDocument(); + + fireEvent.click(filter); + const timeFrameAll = await screen.findByTestId('timeFrameAll'); + expect(timeFrameAll).toBeInTheDocument(); + + fireEvent.click(timeFrameAll); + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(4); + }); + + it('Check Timeframe filter Functionality (Weekly)', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + const filter = await screen.findByTestId('timeFrame'); + expect(filter).toBeInTheDocument(); + + // Filter by weekly + expect(filter).toBeInTheDocument(); + fireEvent.click(filter); + + const timeFrameWeekly = await screen.findByTestId('timeFrameWeekly'); + expect(timeFrameWeekly).toBeInTheDocument(); + fireEvent.click(timeFrameWeekly); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(1); + }); + + it('Check Timeframe filter Functionality (Monthly)', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + // Filter by monthly + const filter = await screen.findByTestId('timeFrame'); + expect(filter).toBeInTheDocument(); + fireEvent.click(filter); + + const timeFrameMonthly = await screen.findByTestId('timeFrameMonthly'); + expect(timeFrameMonthly).toBeInTheDocument(); + fireEvent.click(timeFrameMonthly); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(2); + }); + + it('Check Timeframe filter Functionality (Yearly)', async () => { + renderLeaderboard(link1); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + }); + + // Filter by yearly + const filter = await screen.findByTestId('timeFrame'); + expect(filter).toBeInTheDocument(); + fireEvent.click(filter); + + const timeFrameYearly = await screen.findByTestId('timeFrameYearly'); + expect(timeFrameYearly).toBeInTheDocument(); + fireEvent.click(timeFrameYearly); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(3); + }); + + it('Search Volunteers and clear the input by backspace', async () => { + renderLeaderboard(link1); + + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Clear the search input by backspace + userEvent.type(searchInput, 'T{backspace}'); + await waitFor(() => { + const userName = screen.getAllByTestId('userName'); + expect(userName).toHaveLength(4); + }); + }); + + it('Search Volunteers on press of ENTER', async () => { + renderLeaderboard(link1); + + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'T'); + userEvent.type(searchInput, '{enter}'); + + await waitFor(() => { + const userName = screen.getAllByTestId('userName'); + expect(userName).toHaveLength(1); + }); + }); + + it('Search Volunteers on click of search button', async () => { + renderLeaderboard(link1); + + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'T'); + userEvent.click(screen.getByTestId('searchBtn')); + + await waitFor(() => { + const userName = screen.getAllByTestId('userName'); + expect(userName).toHaveLength(1); + }); + }); + + it('OnClick of Member navigate to Member Screen', async () => { + renderLeaderboard(link1); + + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const userName = screen.getAllByTestId('userName'); + userEvent.click(userName[0]); + + await waitFor(() => { + expect(screen.getByTestId('memberScreen')).toBeInTheDocument(); + }); + }); + + it('should render Leaderboard screen with No Volunteers', async () => { + renderLeaderboard(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteers)).toBeInTheDocument(); + }); + }); + + it('Error while fetching volunteer data', async () => { + renderLeaderboard(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); +}); diff --git a/src/screens/Leaderboard/Leaderboard.tsx b/src/screens/Leaderboard/Leaderboard.tsx index 4eca682d44..ab148ebf2e 100644 --- a/src/screens/Leaderboard/Leaderboard.tsx +++ b/src/screens/Leaderboard/Leaderboard.tsx @@ -100,9 +100,9 @@ function leaderboard(): JSX.Element { variables: { orgId, where: { - order_by: sortBy, - time_frame: timeFrame, - name_contains: searchTerm, + orderBy: sortBy, + timeFrame: timeFrame, + nameContains: searchTerm, }, }, }); @@ -171,7 +171,7 @@ function leaderboard(): JSX.Element { sortable: false, headerClassName: `${styles.tableHeader}`, renderCell: (params: GridCellParams) => { - const { _id, firstName, lastName, image } = params.row.user || {}; + const { _id, firstName, lastName, image } = params.row.user; return ( <> diff --git a/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx b/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx index 3d45e12a25..3321e4b805 100644 --- a/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx +++ b/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx @@ -38,11 +38,14 @@ const itemProps: InterfaceItemDeleteModalProps = { actionItemsRefetch: jest.fn(), actionItem: { _id: 'actionItemId1', - assignee: { + assignee: null, + assigneeGroup: null, + assigneeType: 'User', + assigneeUser: { _id: 'userId1', firstName: 'John', lastName: 'Doe', - image: null, + image: undefined, }, actionItemCategory: { _id: 'actionItemCategoryId1', @@ -60,7 +63,7 @@ const itemProps: InterfaceItemDeleteModalProps = { _id: 'userId2', firstName: 'Wilt', lastName: 'Shepherd', - image: null, + image: undefined, }, creator: { _id: 'userId2', diff --git a/src/screens/OrganizationActionItems/ItemModal.test.tsx b/src/screens/OrganizationActionItems/ItemModal.test.tsx index 6901e16291..7dfd99152e 100644 --- a/src/screens/OrganizationActionItems/ItemModal.test.tsx +++ b/src/screens/OrganizationActionItems/ItemModal.test.tsx @@ -47,6 +47,7 @@ const itemProps: InterfaceItemModalProps[] = [ isOpen: true, hide: jest.fn(), orgId: 'orgId', + eventId: undefined, actionItemsRefetch: jest.fn(), editMode: false, actionItem: null, @@ -55,11 +56,24 @@ const itemProps: InterfaceItemModalProps[] = [ isOpen: true, hide: jest.fn(), orgId: 'orgId', + eventId: 'eventId', + actionItemsRefetch: jest.fn(), + editMode: false, + actionItem: null, + }, + { + isOpen: true, + hide: jest.fn(), + orgId: 'orgId', + eventId: undefined, actionItemsRefetch: jest.fn(), editMode: true, actionItem: { _id: 'actionItemId1', - assignee: { + assignee: null, + assigneeGroup: null, + assigneeType: 'User', + assigneeUser: { _id: 'userId1', firstName: 'Harve', lastName: 'Lance', @@ -81,7 +95,7 @@ const itemProps: InterfaceItemModalProps[] = [ _id: 'userId2', firstName: 'Wilt', lastName: 'Shepherd', - image: null, + image: undefined, }, creator: { _id: 'userId2', @@ -94,11 +108,15 @@ const itemProps: InterfaceItemModalProps[] = [ isOpen: true, hide: jest.fn(), orgId: 'orgId', + eventId: undefined, actionItemsRefetch: jest.fn(), editMode: true, actionItem: { _id: 'actionItemId2', - assignee: { + assignee: null, + assigneeGroup: null, + assigneeType: 'User', + assigneeUser: { _id: 'userId2', firstName: 'Wilt', lastName: 'Shepherd', @@ -129,6 +147,133 @@ const itemProps: InterfaceItemModalProps[] = [ }, }, }, + { + isOpen: true, + hide: jest.fn(), + orgId: 'orgId', + eventId: 'eventId', + actionItemsRefetch: jest.fn(), + editMode: true, + actionItem: { + _id: 'actionItemId2', + assigneeType: 'EventVolunteer', + assignee: { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 0, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [], + }, + assigneeGroup: null, + assigneeUser: null, + actionItemCategory: { + _id: 'categoryId2', + name: 'Category 2', + }, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: { + _id: 'eventId', + title: 'Event 1', + }, + allotedHours: null, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: 'wilt-image', + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + orgId: 'orgId', + eventId: 'eventId', + actionItemsRefetch: jest.fn(), + editMode: true, + actionItem: { + _id: 'actionItemId2', + assigneeType: 'EventVolunteerGroup', + assigneeGroup: { + _id: 'groupId1', + name: 'group1', + description: 'desc', + volunteersRequired: 10, + createdAt: '2024-10-27T15:34:15.889Z', + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, + }, + assignee: null, + assigneeUser: null, + actionItemCategory: { + _id: 'categoryId2', + name: 'Category 2', + }, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: { + _id: 'eventId', + title: 'Event 1', + }, + allotedHours: null, + assigner: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: 'wilt-image', + }, + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + }, + }, ]; const renderItemModal = ( @@ -151,7 +296,7 @@ const renderItemModal = ( }; describe('Testing ItemModal', () => { - it('Create Action Item', async () => { + it('Create Action Item (for Member)', async () => { renderItemModal(link1, itemProps[0]); expect(screen.getAllByText(t.createActionItem)).toHaveLength(2); @@ -206,8 +351,132 @@ describe('Testing ItemModal', () => { }); }); - it('Update Action Item (completed)', async () => { + it('Create Action Item (for Volunteer)', async () => { renderItemModal(link1, itemProps[1]); + expect(screen.getAllByText(t.createActionItem)).toHaveLength(2); + + // Select Category 1 + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(individualRadio); + + // Select Individual Volunteer + const volunteerSelect = await screen.findByTestId('volunteerSelect'); + expect(volunteerSelect).toBeInTheDocument(); + const volunteerInputField = within(volunteerSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('Teresa Bradley'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + // Select Due Date + fireEvent.change(screen.getByLabelText(t.dueDate), { + target: { value: '02/01/2044' }, + }); + + // Select Allotted Hours (try all options) + const allotedHours = screen.getByLabelText(t.allotedHours); + const allotedHoursOptions = ['', '-1', '9']; + + allotedHoursOptions.forEach((option) => { + fireEvent.change(allotedHours, { target: { value: option } }); + expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Add Pre Completion Notes + fireEvent.change(screen.getByLabelText(t.preCompletionNotes), { + target: { value: 'Notes' }, + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[1].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[1].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulCreation); + }); + }); + + it('Create Action Item (for Group)', async () => { + renderItemModal(link1, itemProps[1]); + expect(screen.getAllByText(t.createActionItem)).toHaveLength(2); + + // Select Category 1 + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(groupRadio); + + // Select Individual Volunteer + const groupSelect = await screen.findByTestId('volunteerGroupSelect'); + expect(groupSelect).toBeInTheDocument(); + const groupInputField = within(groupSelect).getByRole('combobox'); + fireEvent.mouseDown(groupInputField); + + const groupOption = await screen.findByText('group1'); + expect(groupOption).toBeInTheDocument(); + fireEvent.click(groupOption); + + // Select Due Date + fireEvent.change(screen.getByLabelText(t.dueDate), { + target: { value: '02/01/2044' }, + }); + + // Select Allotted Hours (try all options) + const allotedHours = screen.getByLabelText(t.allotedHours); + const allotedHoursOptions = ['', '-1', '9']; + + allotedHoursOptions.forEach((option) => { + fireEvent.change(allotedHours, { target: { value: option } }); + expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Add Pre Completion Notes + fireEvent.change(screen.getByLabelText(t.preCompletionNotes), { + target: { value: 'Notes' }, + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[1].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[1].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulCreation); + }); + }); + + it('Update Action Item (completed)', async () => { + renderItemModal(link1, itemProps[2]); expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); // Update Category @@ -240,14 +509,170 @@ describe('Testing ItemModal', () => { fireEvent.click(submitButton); await waitFor(() => { - expect(itemProps[1].actionItemsRefetch).toHaveBeenCalled(); - expect(itemProps[1].hide).toHaveBeenCalled(); + expect(itemProps[2].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[2].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('Update Action Item (Volunteer)', async () => { + renderItemModal(link1, itemProps[4]); + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); + + // Update Category + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(individualRadio); + + // Select Individual Volunteer + const volunteerSelect = await screen.findByTestId('volunteerSelect'); + expect(volunteerSelect).toBeInTheDocument(); + const volunteerInputField = within(volunteerSelect).getByRole('combobox'); + fireEvent.mouseDown(volunteerInputField); + + const volunteerOption = await screen.findByText('Bruce Graza'); + expect(volunteerOption).toBeInTheDocument(); + fireEvent.click(volunteerOption); + + // Update Allotted Hours (try all options) + const allotedHours = screen.getByLabelText(t.allotedHours); + const allotedHoursOptions = ['', '-1', '19']; + + allotedHoursOptions.forEach((option) => { + fireEvent.change(allotedHours, { target: { value: option } }); + expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[4].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[4].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('Update Action Item (Group)', async () => { + renderItemModal(link1, itemProps[5]); + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); + + // Update Category + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(groupRadio); + + // Select Individual Volunteer + const groupSelect = await screen.findByTestId('volunteerGroupSelect'); + expect(groupSelect).toBeInTheDocument(); + const groupInputField = within(groupSelect).getByRole('combobox'); + fireEvent.mouseDown(groupInputField); + + const groupOption = await screen.findByText('group2'); + expect(groupOption).toBeInTheDocument(); + fireEvent.click(groupOption); + + // Update Allotted Hours (try all options) + const allotedHours = screen.getByLabelText(t.allotedHours); + const allotedHoursOptions = ['', '-1', '19']; + + allotedHoursOptions.forEach((option) => { + fireEvent.change(allotedHours, { target: { value: option } }); + expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[5].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[5].hide).toHaveBeenCalled(); + expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); + }); + }); + + it('Update Action Item (Volunteer -> Group)', async () => { + renderItemModal(link1, itemProps[4]); + expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); + + // Update Category + const categorySelect = await screen.findByTestId('categorySelect'); + expect(categorySelect).toBeInTheDocument(); + const inputField = within(categorySelect).getByRole('combobox'); + fireEvent.mouseDown(inputField); + + const categoryOption = await screen.findByText('Category 1'); + expect(categoryOption).toBeInTheDocument(); + fireEvent.click(categoryOption); + + // Select Volunteer Role + const groupRadio = await screen.findByText(t.groups); + const individualRadio = await screen.findByText(t.individuals); + expect(groupRadio).toBeInTheDocument(); + expect(individualRadio).toBeInTheDocument(); + fireEvent.click(groupRadio); + + // Select Individual Volunteer + const groupSelect = await screen.findByTestId('volunteerGroupSelect'); + expect(groupSelect).toBeInTheDocument(); + const groupInputField = within(groupSelect).getByRole('combobox'); + fireEvent.mouseDown(groupInputField); + + const groupOption = await screen.findByText('group2'); + expect(groupOption).toBeInTheDocument(); + fireEvent.click(groupOption); + + // Update Allotted Hours (try all options) + const allotedHours = screen.getByLabelText(t.allotedHours); + const allotedHoursOptions = ['', '-1', '19']; + + allotedHoursOptions.forEach((option) => { + fireEvent.change(allotedHours, { target: { value: option } }); + expect(allotedHours).toHaveValue(parseInt(option) > 0 ? option : ''); + }); + + // Click Submit + const submitButton = screen.getByTestId('submitBtn'); + expect(submitButton).toBeInTheDocument(); + fireEvent.click(submitButton); + + await waitFor(() => { + expect(itemProps[4].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[4].hide).toHaveBeenCalled(); expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); }); }); it('Update Action Item (not completed)', async () => { - renderItemModal(link1, itemProps[2]); + renderItemModal(link1, itemProps[3]); expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); // Update Category @@ -295,8 +720,8 @@ describe('Testing ItemModal', () => { fireEvent.click(submitButton); await waitFor(() => { - expect(itemProps[2].actionItemsRefetch).toHaveBeenCalled(); - expect(itemProps[2].hide).toHaveBeenCalled(); + expect(itemProps[3].actionItemsRefetch).toHaveBeenCalled(); + expect(itemProps[3].hide).toHaveBeenCalled(); expect(toast.success).toHaveBeenCalledWith(t.successfulUpdation); }); }); @@ -341,7 +766,7 @@ describe('Testing ItemModal', () => { }); it('No Fields Updated while Updating', async () => { - renderItemModal(link2, itemProps[1]); + renderItemModal(link2, itemProps[2]); // Click Submit const submitButton = screen.getByTestId('submitBtn'); expect(submitButton).toBeInTheDocument(); @@ -353,7 +778,7 @@ describe('Testing ItemModal', () => { }); it('should fail to Update Action Item', async () => { - renderItemModal(link2, itemProps[1]); + renderItemModal(link2, itemProps[2]); expect(screen.getAllByText(t.updateActionItem)).toHaveLength(2); // Update Post Completion Notes diff --git a/src/screens/OrganizationActionItems/ItemModal.tsx b/src/screens/OrganizationActionItems/ItemModal.tsx index 03dad3dd67..9507f34e2a 100644 --- a/src/screens/OrganizationActionItems/ItemModal.tsx +++ b/src/screens/OrganizationActionItems/ItemModal.tsx @@ -170,9 +170,6 @@ const ItemModal: FC = ({ data?: { getEventVolunteerGroups: InterfaceVolunteerGroupInfo[]; }; - loading: boolean; - error?: Error | undefined; - refetch: () => void; } = useQuery(EVENT_VOLUNTEER_GROUP_LIST, { variables: { where: { @@ -446,7 +443,7 @@ const ItemModal: FC = ({
{!isCompleted && ( <> - {assigneeType !== 'User' && ( + {eventId && ( <> {t('assignTo')}
{ }); it('should fail to Update status of Action Item', async () => { - renderItemUpdateStatusModal(link2, itemProps[0]); + renderItemUpdateStatusModal(link2, itemProps[2]); expect(screen.getByText(t.actionItemStatus)).toBeInTheDocument(); const yesBtn = await screen.findByTestId('yesBtn'); diff --git a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx index f43f5865f4..6b709a1929 100644 --- a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx +++ b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.tsx @@ -12,7 +12,7 @@ export interface InterfaceItemUpdateStatusModalProps { isOpen: boolean; hide: () => void; actionItemsRefetch: () => void; - actionItem: InterfaceActionItemInfo | null; + actionItem: InterfaceActionItemInfo; } const ItemUpdateStatusModal: FC = ({ @@ -26,11 +26,17 @@ const ItemUpdateStatusModal: FC = ({ }); const { t: tCommon } = useTranslation('common'); - const [isCompleted, setIsCompleted] = useState( - actionItem?.isCompleted ?? false, - ); + const { + _id, + isCompleted, + assignee, + assigneeGroup, + assigneeUser, + assigneeType, + } = actionItem; + const [postCompletionNotes, setPostCompletionNotes] = useState( - actionItem?.postCompletionNotes ?? '', + actionItem.postCompletionNotes ?? '', ); /** @@ -51,14 +57,14 @@ const ItemUpdateStatusModal: FC = ({ try { await updateActionItem({ variables: { - actionItemId: actionItem?._id, + actionItemId: _id, assigneeId: - actionItem?.assigneeType === 'EventVolunteer' - ? actionItem?.assignee?._id - : actionItem?.assigneeType === 'EventVolunteerGroup' - ? actionItem?.assigneeGroup?._id - : actionItem?.assigneeUser?._id, - assigneeType: actionItem?.assigneeType, + assigneeType === 'EventVolunteer' + ? assignee?._id + : assigneeType === 'EventVolunteerGroup' + ? assigneeGroup?._id + : assigneeUser?._id, + assigneeType, postCompletionNotes: isCompleted ? '' : postCompletionNotes, isCompleted: !isCompleted, }, @@ -73,10 +79,7 @@ const ItemUpdateStatusModal: FC = ({ }; useEffect(() => { - if (actionItem) { - setIsCompleted(actionItem?.isCompleted); - setPostCompletionNotes(actionItem?.postCompletionNotes ?? ''); - } + setPostCompletionNotes(actionItem.postCompletionNotes ?? ''); }, [actionItem]); return ( diff --git a/src/screens/OrganizationActionItems/ItemViewModal.test.tsx b/src/screens/OrganizationActionItems/ItemViewModal.test.tsx index 13c208b854..3ccef54c9c 100644 --- a/src/screens/OrganizationActionItems/ItemViewModal.test.tsx +++ b/src/screens/OrganizationActionItems/ItemViewModal.test.tsx @@ -3,7 +3,7 @@ import type { ApolloLink } from '@apollo/client'; import { MockedProvider } from '@apollo/react-testing'; import { LocalizationProvider } from '@mui/x-date-pickers'; import type { RenderResult } from '@testing-library/react'; -import { render, screen } from '@testing-library/react'; +import { render, screen, within } from '@testing-library/react'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; @@ -13,6 +13,11 @@ import i18nForTest from '../../utils/i18nForTest'; import { MOCKS } from './OrganizationActionItem.mocks'; import { StaticMockLink } from 'utils/StaticMockLink'; import ItemViewModal, { type InterfaceViewModalProps } from './ItemViewModal'; +import type { + InterfaceEventVolunteerInfo, + InterfaceUserInfo, + InterfaceVolunteerGroupInfo, +} from 'utils/interfaces'; jest.mock('react-toastify', () => ({ toast: { @@ -28,22 +33,67 @@ const t = JSON.parse( ), ); +const createUser = ( + id: string, + firstName: string, + lastName: string, + image?: string, +): InterfaceUserInfo => ({ + _id: id, + firstName, + lastName, + image, +}); + +const createAssignee = ( + user: ReturnType, + hasAccepted = true, +): InterfaceEventVolunteerInfo => ({ + _id: `${user._id}-assignee`, + user, + assignments: [], + groups: [], + hasAccepted, + hoursVolunteered: 0, +}); + +const createAssigneeGroup = ( + id: string, + name: string, + leader: ReturnType, +): InterfaceVolunteerGroupInfo => ({ + _id: id, + name, + description: `${name} description`, + event: { _id: 'eventId1' }, + volunteers: [], + assignments: [], + volunteersRequired: 10, + leader, + creator: leader, + createdAt: '2024-08-27', +}); + +const userWithImage = createUser('userId', 'Wilt', 'Shepherd', 'wilt-image'); +const userWithoutImage = createUser('userId', 'Wilt', 'Shepherd'); +const assigneeWithImage = createUser('userId1', 'John', 'Doe', 'image-url'); +const assigneeWithoutImage = createUser('userId1', 'John', 'Doe'); +const actionItemCategory = { + _id: 'actionItemCategoryId2', + name: 'Category 2', +}; + const itemProps: InterfaceViewModalProps[] = [ { isOpen: true, hide: jest.fn(), item: { _id: 'actionItemId1', - assignee: { - _id: 'userId1', - firstName: 'John', - lastName: 'Doe', - image: null, - }, - actionItemCategory: { - _id: 'actionItemCategoryId1', - name: 'Category 1', - }, + assignee: createAssignee(assigneeWithoutImage), + assigneeGroup: null, + assigneeType: 'EventVolunteer', + assigneeUser: null, + actionItemCategory, preCompletionNotes: 'Notes 1', postCompletionNotes: 'Cmp Notes 1', assignmentDate: new Date('2024-08-27'), @@ -52,17 +102,74 @@ const itemProps: InterfaceViewModalProps[] = [ isCompleted: true, event: null, allotedHours: 24, - assigner: { - _id: 'userId2', - firstName: 'Wilt', - lastName: 'Shepherd', - image: null, - }, - creator: { - _id: 'userId2', - firstName: 'Wilt', - lastName: 'Shepherd', - }, + assigner: userWithoutImage, + creator: userWithoutImage, + }, + }, + { + isOpen: true, + hide: jest.fn(), + item: { + _id: 'actionItemId2', + assignee: createAssignee(assigneeWithImage), + assigneeGroup: null, + assigneeType: 'EventVolunteer', + assigneeUser: null, + actionItemCategory, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: null, + allotedHours: null, + assigner: userWithImage, + creator: userWithoutImage, + }, + }, + { + isOpen: true, + hide: jest.fn(), + item: { + _id: 'actionItemId2', + assignee: null, + assigneeGroup: null, + assigneeType: 'User', + assigneeUser: assigneeWithImage, + actionItemCategory, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: null, + allotedHours: null, + assigner: userWithImage, + creator: userWithoutImage, + }, + }, + { + isOpen: true, + hide: jest.fn(), + item: { + _id: 'actionItemId2', + assignee: null, + assigneeGroup: null, + assigneeType: 'User', + assigneeUser: createUser('userId1', 'Jane', 'Doe'), + actionItemCategory, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: null, + allotedHours: null, + assigner: userWithoutImage, + creator: userWithoutImage, }, }, { @@ -70,16 +177,15 @@ const itemProps: InterfaceViewModalProps[] = [ hide: jest.fn(), item: { _id: 'actionItemId2', - assignee: { - _id: 'userId1', - firstName: 'Jane', - lastName: 'Doe', - image: 'image-url', - }, - actionItemCategory: { - _id: 'actionItemCategoryId2', - name: 'Category 2', - }, + assignee: null, + assigneeGroup: createAssigneeGroup( + 'groupId1', + 'Group 1', + assigneeWithoutImage, + ), + assigneeType: 'EventVolunteerGroup', + assigneeUser: null, + actionItemCategory, preCompletionNotes: 'Notes 2', postCompletionNotes: null, assignmentDate: new Date('2024-08-27'), @@ -88,17 +194,8 @@ const itemProps: InterfaceViewModalProps[] = [ isCompleted: false, event: null, allotedHours: null, - assigner: { - _id: 'userId2', - firstName: 'Wilt', - lastName: 'Shepherd', - image: 'wilt-image', - }, - creator: { - _id: 'userId2', - firstName: 'Wilt', - lastName: 'Shepherd', - }, + assigner: userWithoutImage, + creator: userWithoutImage, }, }, ]; @@ -126,22 +223,65 @@ describe('Testing ItemViewModal', () => { it('should render ItemViewModal with pending item & assignee with null image', () => { renderItemViewModal(link1, itemProps[0]); expect(screen.getByText(t.actionItemDetails)).toBeInTheDocument(); - expect(screen.getByTestId('John_avatar')).toBeInTheDocument(); - expect(screen.getByTestId('Wilt_avatar')).toBeInTheDocument(); + + const assigneeInput = screen.getByTestId('assignee_input'); + expect(assigneeInput).toBeInTheDocument(); + + const inputElement = within(assigneeInput).getByRole('textbox'); + expect(inputElement).toHaveValue('John Doe'); + + expect(screen.getByTestId('assignee_avatar')).toBeInTheDocument(); + expect(screen.getByTestId('assigner_avatar')).toBeInTheDocument(); expect(screen.getByLabelText(t.postCompletionNotes)).toBeInTheDocument(); expect(screen.getByLabelText(t.allotedHours)).toBeInTheDocument(); expect(screen.getByLabelText(t.allotedHours)).toHaveValue('24'); }); - it('should render ItemViewModal with completed item & assignee with null image', () => { + it('should render ItemViewModal with completed item & assignee with image', () => { renderItemViewModal(link1, itemProps[1]); expect(screen.getByText(t.actionItemDetails)).toBeInTheDocument(); - expect(screen.getByTestId('Jane_image')).toBeInTheDocument(); - expect(screen.getByTestId('Wilt_image')).toBeInTheDocument(); + expect(screen.getByTestId('assignee_image')).toBeInTheDocument(); + expect(screen.getByTestId('assigner_image')).toBeInTheDocument(); expect( screen.queryByLabelText(t.postCompletionNotes), ).not.toBeInTheDocument(); expect(screen.getByLabelText(t.allotedHours)).toBeInTheDocument(); expect(screen.getByLabelText(t.allotedHours)).toHaveValue('-'); }); + + it('should render ItemViewModal with assigneeUser with image', () => { + renderItemViewModal(link1, itemProps[2]); + expect(screen.getByText(t.actionItemDetails)).toBeInTheDocument(); + expect(screen.getByTestId('assignee_image')).toBeInTheDocument(); + expect(screen.getByTestId('assigner_image')).toBeInTheDocument(); + const assigneeInput = screen.getByTestId('assignee_input'); + expect(assigneeInput).toBeInTheDocument(); + + const inputElement = within(assigneeInput).getByRole('textbox'); + expect(inputElement).toHaveValue('John Doe'); + }); + + it('should render ItemViewModal with assigneeUser without image', () => { + renderItemViewModal(link1, itemProps[3]); + expect(screen.getByText(t.actionItemDetails)).toBeInTheDocument(); + expect(screen.getByTestId('assignee_avatar')).toBeInTheDocument(); + expect(screen.getByTestId('assigner_avatar')).toBeInTheDocument(); + const assigneeInput = screen.getByTestId('assignee_input'); + expect(assigneeInput).toBeInTheDocument(); + + const inputElement = within(assigneeInput).getByRole('textbox'); + expect(inputElement).toHaveValue('Jane Doe'); + }); + + it('should render ItemViewModal with assigneeGroup', () => { + renderItemViewModal(link1, itemProps[4]); + expect(screen.getByText(t.actionItemDetails)).toBeInTheDocument(); + expect(screen.getByTestId('assigneeGroup_avatar')).toBeInTheDocument(); + expect(screen.getByTestId('assigner_avatar')).toBeInTheDocument(); + const assigneeInput = screen.getByTestId('assignee_input'); + expect(assigneeInput).toBeInTheDocument(); + + const inputElement = within(assigneeInput).getByRole('textbox'); + expect(inputElement).toHaveValue('Group 1'); + }); }); diff --git a/src/screens/OrganizationActionItems/ItemViewModal.tsx b/src/screens/OrganizationActionItems/ItemViewModal.tsx index 6e99fda930..8fd2d95d21 100644 --- a/src/screens/OrganizationActionItems/ItemViewModal.tsx +++ b/src/screens/OrganizationActionItems/ItemViewModal.tsx @@ -39,6 +39,7 @@ const ItemViewModal: FC = ({ isOpen, hide, item }) => { actionItemCategory, assignee, assigneeGroup, + assigneeUser, assigneeType, assigner, completionDate, @@ -81,52 +82,46 @@ const ItemViewModal: FC = ({ isOpen, hide, item }) => { label={t('assignee')} variant="outlined" className={styles.noOutline} + data-testid="assignee_input" value={ assigneeType === 'EventVolunteer' - ? assignee?.user?.firstName + ' ' + assignee?.user?.lastName - : assigneeGroup?.name + ? `${assignee?.user?.firstName} ${assignee?.user?.lastName}` + : assigneeType === 'EventVolunteerGroup' + ? assigneeGroup?.name + : `${assigneeUser?.firstName} ${assigneeUser?.lastName}` } disabled InputProps={{ startAdornment: ( <> - {assignee && assignee.user.image ? ( + {assignee?.user?.image || assigneeUser?.image ? ( Assignee - ) : assignee ? ( -
- -
+ ) : assignee || assigneeUser ? ( + ) : ( -
- -
+ )} ), @@ -146,8 +141,8 @@ const ItemViewModal: FC = ({ isOpen, hide, item }) => { {assigner.image ? ( Assignee ) : ( @@ -156,9 +151,9 @@ const ItemViewModal: FC = ({ isOpen, hide, item }) => { key={assigner._id + '1'} containerStyle={styles.imageContainer} avatarStyle={styles.TableImage} - dataTestId={`${assigner.firstName}_avatar`} + dataTestId={`assigner_avatar`} name={assigner.firstName + ' ' + assigner.lastName} - alt={assigner.firstName + ' ' + assigner.lastName} + alt={`assigner_avatar`} />
)} diff --git a/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts b/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts index 0d57023507..27924dd014 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts +++ b/src/screens/OrganizationActionItems/OrganizationActionItem.mocks.ts @@ -4,70 +4,187 @@ import { DELETE_ACTION_ITEM_MUTATION, UPDATE_ACTION_ITEM_MUTATION, } from 'GraphQl/Mutations/ActionItemMutations'; +import { + EVENT_VOLUNTEER_GROUP_LIST, + EVENT_VOLUNTEER_LIST, +} from 'GraphQl/Queries/EventVolunteerQueries'; import { ACTION_ITEM_CATEGORY_LIST, ACTION_ITEM_LIST, MEMBERS_LIST, } from 'GraphQl/Queries/Queries'; +import type { InterfaceActionItemInfo } from 'utils/interfaces'; + +const actionItemCategory1 = { + _id: 'actionItemCategoryId1', + name: 'Category 1', +}; + +const actionItemCategory2 = { + _id: 'actionItemCategoryId2', + name: 'Category 2', +}; const baseActionItem = { assigner: { - _id: 'userId2', + _id: 'userId', firstName: 'Wilt', lastName: 'Shepherd', image: null, }, creator: { - _id: 'userId2', + _id: 'userId', firstName: 'Wilt', lastName: 'Shepherd', + image: null, __typename: 'User', }, }; -const actionItem1 = { +const itemWithVolunteer: InterfaceActionItemInfo = { _id: 'actionItemId1', + assigneeType: 'EventVolunteer', assignee: { - _id: 'userId1', - firstName: 'John', - lastName: 'Doe', - image: null, + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 12, + assignments: [], + groups: [], + user: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: null, + }, }, - actionItemCategory: { - _id: 'actionItemCategoryId1', - name: 'Category 1', + assigneeUser: null, + assigneeGroup: null, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: true, + event: null, + allotedHours: 24, + actionItemCategory: actionItemCategory1, + ...baseActionItem, +}; + +const itemWithVolunteerImage: InterfaceActionItemInfo = { + _id: 'actionItemId1b', + assigneeType: 'EventVolunteer', + assignee: { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 12, + assignments: [], + groups: [], + user: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: 'user-image', + }, }, + assigneeUser: null, + assigneeGroup: null, preCompletionNotes: 'Notes 1', postCompletionNotes: 'Cmp Notes 1', - assignmentDate: '2024-08-27', - dueDate: '2044-08-30', - completionDate: '2044-09-03', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), isCompleted: true, event: null, allotedHours: 24, + actionItemCategory: actionItemCategory1, ...baseActionItem, }; -const actionItem2 = { +const itemWithUser: InterfaceActionItemInfo = { _id: 'actionItemId2', - assignee: { + assigneeType: 'User', + assigneeUser: { _id: 'userId1', firstName: 'Jane', lastName: 'Doe', - image: 'image-url', + image: null, }, - actionItemCategory: { - _id: 'actionItemCategoryId2', - name: 'Category 2', + assignee: null, + assigneeGroup: null, + preCompletionNotes: 'Notes 2', + postCompletionNotes: null, + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), + isCompleted: false, + event: null, + allotedHours: null, + actionItemCategory: actionItemCategory2, + ...baseActionItem, +}; + +const itemWithUserImage: InterfaceActionItemInfo = { + _id: 'actionItemId2b', + assigneeType: 'User', + assigneeUser: { + _id: 'userId1', + firstName: 'Jane', + lastName: 'Doe', + image: 'user-image', }, + assignee: null, + assigneeGroup: null, preCompletionNotes: 'Notes 2', postCompletionNotes: null, - assignmentDate: '2024-08-27', - dueDate: '2044-09-30', - completionDate: '2044-10-03', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-09-30'), + completionDate: new Date('2044-10-03'), isCompleted: false, event: null, allotedHours: null, + actionItemCategory: actionItemCategory2, + ...baseActionItem, +}; + +const itemWithGroup: InterfaceActionItemInfo = { + _id: 'actionItemId3', + assigneeType: 'EventVolunteerGroup', + assigneeUser: null, + assignee: null, + assigneeGroup: { + _id: 'volunteerGroupId1', + name: 'Group 1', + description: 'Group 1 Description', + volunteersRequired: 10, + event: { + _id: 'eventId1', + }, + assignments: [], + volunteers: [], + createdAt: '2024-08-27', + creator: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: undefined, + }, + leader: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: undefined, + }, + }, + preCompletionNotes: 'Notes 1', + postCompletionNotes: 'Cmp Notes 1', + assignmentDate: new Date('2024-08-27'), + dueDate: new Date('2044-08-30'), + completionDate: new Date('2044-09-03'), + isCompleted: true, + event: null, + allotedHours: 24, + actionItemCategory: actionItemCategory1, ...baseActionItem, }; @@ -107,6 +224,152 @@ const memberListQuery = { }, }; +const volunteerListQuery = [ + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { where: { eventId: 'eventId', hasAccepted: true } }, + }, + result: { + data: { + getEventVolunteers: [ + { + _id: 'volunteerId1', + hasAccepted: true, + hoursVolunteered: 0, + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + assignments: [], + groups: [ + { + _id: 'groupId1', + name: 'group1', + volunteers: [ + { + _id: 'volunteerId1', + }, + ], + }, + ], + }, + { + _id: 'volunteerId2', + hasAccepted: true, + hoursVolunteered: 0, + user: { + _id: 'userId3', + firstName: 'Bruce', + lastName: 'Graza', + image: null, + }, + assignments: [], + groups: [], + }, + ], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_LIST, + variables: { where: { hasAccepted: true } }, + }, + result: { + data: { + getEventVolunteers: [], + }, + }, + }, +]; + +const groupListQuery = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { where: { eventId: 'eventId' } }, + }, + result: { + data: { + getEventVolunteerGroups: [ + { + _id: 'groupId1', + name: 'group1', + description: 'desc', + volunteersRequired: 10, + createdAt: '2024-10-27T15:34:15.889Z', + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, + }, + { + _id: 'groupId2', + name: 'group2', + description: 'desc', + volunteersRequired: 10, + createdAt: '2024-10-27T15:34:15.889Z', + creator: { + _id: 'userId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [], + assignments: [], + event: { + _id: 'eventId', + }, + }, + ], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { where: { eventId: undefined } }, + }, + result: { + data: { + getEventVolunteerGroups: [], + }, + }, + }, +]; + const actionItemCategoryListQuery = { request: { query: ACTION_ITEM_CATEGORY_LIST, @@ -159,7 +422,13 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1, actionItem2], + actionItemsByOrganization: [ + itemWithVolunteer, + itemWithUser, + itemWithGroup, + itemWithVolunteerImage, + itemWithUserImage, + ], }, }, }, @@ -176,7 +445,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1, actionItem2], + actionItemsByOrganization: [itemWithVolunteer, itemWithUser], }, }, }, @@ -193,7 +462,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1, actionItem2], + actionItemsByOrganization: [itemWithVolunteer, itemWithUser], }, }, }, @@ -210,7 +479,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem2, actionItem1], + actionItemsByOrganization: [itemWithUser, itemWithVolunteer], }, }, }, @@ -228,7 +497,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1], + actionItemsByOrganization: [itemWithVolunteer], }, }, }, @@ -246,7 +515,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem2], + actionItemsByOrganization: [itemWithUser], }, }, }, @@ -263,7 +532,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1], + actionItemsByOrganization: [itemWithVolunteer], }, }, }, @@ -280,7 +549,7 @@ export const MOCKS = [ }, result: { data: { - actionItemsByOrganization: [actionItem1], + actionItemsByOrganization: [itemWithVolunteer], }, }, }, @@ -305,6 +574,7 @@ export const MOCKS = [ variables: { actionItemId: 'actionItemId1', assigneeId: 'userId1', + assigneeType: 'User', postCompletionNotes: '', isCompleted: false, }, @@ -323,6 +593,7 @@ export const MOCKS = [ variables: { actionItemId: 'actionItemId1', assigneeId: 'userId1', + assigneeType: 'User', actionItemCategoryId: 'categoryId2', postCompletionNotes: 'Cmp Notes 2', allotedHours: 19, @@ -336,12 +607,32 @@ export const MOCKS = [ }, }, }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId1', + assigneeId: 'volunteerGroupId1', + assigneeType: 'EventVolunteerGroup', + postCompletionNotes: 'Cmp Notes 1', + isCompleted: true, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, { request: { query: UPDATE_ACTION_ITEM_MUTATION, variables: { actionItemId: 'actionItemId2', assigneeId: 'userId1', + assigneeType: 'User', actionItemCategoryId: 'categoryId1', preCompletionNotes: 'Notes 3', allotedHours: 19, @@ -374,15 +665,116 @@ export const MOCKS = [ }, }, }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId2', + assigneeId: 'volunteerId2', + assigneeType: 'EventVolunteer', + actionItemCategoryId: 'categoryId1', + allotedHours: 19, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_ACTION_ITEM_MUTATION, + variables: { + actionItemId: 'actionItemId2', + assigneeId: 'groupId2', + assigneeType: 'EventVolunteerGroup', + actionItemCategoryId: 'categoryId1', + allotedHours: 19, + }, + }, + result: { + data: { + updateActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, { request: { query: CREATE_ACTION_ITEM_MUTATION, variables: { assigneeId: 'userId1', + assigneeType: 'User', actionItemCategoryId: 'categoryId1', preCompletionNotes: 'Notes', allotedHours: 9, - dueDate: '2044-01-02', + dDate: '2044-01-02', + }, + }, + result: { + data: { + createActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + assigneeId: 'userId1', + assigneeType: 'User', + actionItemCategoryId: 'categoryId1', + preCompletionNotes: 'Notes', + allotedHours: 9, + dDate: '2044-01-02', + }, + }, + result: { + data: { + createActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + assigneeId: 'volunteerId1', + assigneeType: 'EventVolunteer', + actionItemCategoryId: 'categoryId1', + preCompletionNotes: 'Notes', + allotedHours: 9, + dDate: '2044-01-02', + eventId: 'eventId', + }, + }, + result: { + data: { + createActionItem: { + _id: 'actionItemId1', + }, + }, + }, + }, + { + request: { + query: CREATE_ACTION_ITEM_MUTATION, + variables: { + assigneeId: 'groupId1', + assigneeType: 'EventVolunteerGroup', + actionItemCategoryId: 'categoryId1', + preCompletionNotes: 'Notes', + allotedHours: 9, + dDate: '2044-01-02', + eventId: 'eventId', }, }, result: { @@ -395,6 +787,8 @@ export const MOCKS = [ }, memberListQuery, actionItemCategoryListQuery, + ...volunteerListQuery, + ...groupListQuery, ]; export const MOCKS_ERROR = [ @@ -425,7 +819,8 @@ export const MOCKS_ERROR = [ query: UPDATE_ACTION_ITEM_MUTATION, variables: { actionItemId: 'actionItemId1', - assigneeId: 'userId1', + assigneeId: 'volunteerId1', + assigneeType: 'EventVolunteer', postCompletionNotes: '', isCompleted: false, }, @@ -436,9 +831,11 @@ export const MOCKS_ERROR = [ request: { query: CREATE_ACTION_ITEM_MUTATION, variables: { + assigneeId: '', + assigneeType: 'User', preCompletionNotes: '', allotedHours: null, - dueDate: dayjs().format('YYYY-MM-DD'), + dDate: dayjs().format('YYYY-MM-DD'), }, }, error: new Error('Mock Graphql Error'), @@ -449,6 +846,7 @@ export const MOCKS_ERROR = [ variables: { actionItemId: 'actionItemId1', assigneeId: 'userId1', + assigneeType: 'User', postCompletionNotes: 'Cmp Notes 2', }, }, @@ -456,6 +854,8 @@ export const MOCKS_ERROR = [ }, memberListQuery, actionItemCategoryListQuery, + ...volunteerListQuery, + ...groupListQuery, ]; export const MOCKS_EMPTY = [ @@ -478,4 +878,6 @@ export const MOCKS_EMPTY = [ }, memberListQuery, actionItemCategoryListQuery, + ...volunteerListQuery, + ...groupListQuery, ]; diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx index c163ff9546..417752ae10 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx @@ -114,8 +114,8 @@ describe('Testing Organization Action Items Screen', () => { renderOrganizationActionItems(link1); await waitFor(() => { expect(screen.getByTestId('searchBy')).toBeInTheDocument(); - expect(screen.getByText('John Doe')).toBeInTheDocument(); - expect(screen.getByText('Jane Doe')).toBeInTheDocument(); + expect(screen.getAllByText('John Doe')).toHaveLength(2); + expect(screen.getAllByText('Jane Doe')).toHaveLength(2); }); }); @@ -171,8 +171,8 @@ describe('Testing Organization Action Items Screen', () => { fireEvent.click(screen.getByTestId('statusAll')); await waitFor(() => { - expect(screen.getByText('Category 1')).toBeInTheDocument(); - expect(screen.getByText('Category 2')).toBeInTheDocument(); + expect(screen.getAllByText('Category 1')).toHaveLength(3); + expect(screen.getAllByText('Category 2')).toHaveLength(2); }); // Filter by Pending @@ -341,8 +341,8 @@ describe('Testing Organization Action Items Screen', () => { // Clear the search input by backspace userEvent.type(searchInput, 'A{backspace}'); await waitFor(() => { - expect(screen.getByText('Category 1')).toBeInTheDocument(); - expect(screen.getByText('Category 2')).toBeInTheDocument(); + expect(screen.getAllByText('Category 1')).toHaveLength(3); + expect(screen.getAllByText('Category 2')).toHaveLength(2); }); }); diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx index 1969988841..730cc2a130 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx @@ -228,11 +228,11 @@ function organizationActionItems(): JSX.Element { key={_id + '1'} containerStyle={styles.imageContainer} avatarStyle={styles.TableImage} - name={params.row.assigneeGroup?.name ?? ''} - alt={params.row.assigneeGroup?.name ?? ''} + name={params.row.assigneeGroup?.name as string} + alt={'assigneeGroup_avatar'} /> - {params.row.assigneeGroup?.name ?? ''} + {params.row.assigneeGroup?.name as string} )} @@ -546,27 +546,29 @@ function organizationActionItems(): JSX.Element { editMode={modalMode === 'edit'} /> - closeModal(ModalState.DELETE)} - actionItem={actionItem} - actionItemsRefetch={actionItemsRefetch} - /> - - closeModal(ModalState.STATUS)} - actionItemsRefetch={actionItemsRefetch} - /> - {/* View Modal */} {actionItem && ( - closeModal(ModalState.VIEW)} - item={actionItem} - /> + <> + closeModal(ModalState.VIEW)} + item={actionItem} + /> + + closeModal(ModalState.STATUS)} + actionItemsRefetch={actionItemsRefetch} + /> + + closeModal(ModalState.DELETE)} + actionItem={actionItem} + actionItemsRefetch={actionItemsRefetch} + /> + )} ); diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx index dde6b3120f..9c0a5d7761 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx @@ -1,202 +1,282 @@ +import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { fireEvent, render, screen } from '@testing-library/react'; -import 'jest-location-mock'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; - -import userEvent from '@testing-library/user-event'; -import { toast } from 'react-toastify'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; -import i18nForTest from 'utils/i18nForTest'; -import useLocalStorage from 'utils/useLocalstorage'; +import i18n from 'utils/i18nForTest'; import OrganizationDashboard from './OrganizationDashboard'; -import { EMPTY_MOCKS, ERROR_MOCKS, MOCKS } from './OrganizationDashboardMocks'; -import React, { act } from 'react'; -const { setItem } = useLocalStorage(); -import type { InterfaceQueryOrganizationEventListItem } from 'utils/interfaces'; - -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} -const link1 = new StaticMockLink(MOCKS, true); -const link2 = new StaticMockLink(EMPTY_MOCKS, true); -const link3 = new StaticMockLink(ERROR_MOCKS, true); +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, EMPTY_MOCKS, ERROR_MOCKS } from './OrganizationDashboardMocks'; +import { toast } from 'react-toastify'; jest.mock('react-toastify', () => ({ toast: { success: jest.fn(), - warn: jest.fn(), error: jest.fn(), }, })); -const mockNavgate = jest.fn(); -let mockId: string | undefined = undefined; -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useNavigate: () => mockNavgate, - useParams: () => ({ orgId: mockId }), -})); -beforeEach(() => { - setItem('FirstName', 'John'); - setItem('LastName', 'Doe'); - setItem( - 'UserImage', - 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify(i18n.getDataByLanguage('en')?.translation.dashboard ?? {}), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const renderOrganizationDashboard = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + + + + + + , ); -}); +}; -afterEach(() => { - jest.clearAllMocks(); - localStorage.clear(); -}); +describe('Testing Organization Dashboard Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); -describe('Organisation Dashboard Page', () => { - test('Should render props and text elements test for the screen', async () => { - await act(async () => { - render( - - - - - - - - - , - ); + it('should redirect to fallback URL if URL params are undefined', async () => { + render( + + + + + + } /> + } + /> + + + + + , + ); + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); }); + }); - await wait(); - expect(screen.getByText('Members')).toBeInTheDocument(); - expect(screen.getByText('Admins')).toBeInTheDocument(); - expect(screen.getAllByText('Posts')).toHaveLength(1); - expect(screen.getAllByText('Events')).toHaveLength(1); - expect(screen.getByText('Blocked Users')).toBeInTheDocument(); - expect(screen.getByText('Requests')).toBeInTheDocument(); - expect(screen.getByText('Upcoming Events')).toBeInTheDocument(); - expect(screen.getByText('Latest Posts')).toBeInTheDocument(); - expect(screen.getByText('Membership requests')).toBeInTheDocument(); - - // Checking if posts are rendered + it('should render Organization Dashboard screen', async () => { + renderOrganizationDashboard(link1); + + // Dashboard cards + const membersBtn = await screen.findByText(t.members); + expect(membersBtn).toBeInTheDocument(); + expect(screen.getByText(t.admins)).toBeInTheDocument(); + expect(screen.getByText(t.posts)).toBeInTheDocument(); + expect(screen.getByText(t.events)).toBeInTheDocument(); + expect(screen.getByText(t.blockedUsers)).toBeInTheDocument(); + + // Upcoming events + expect(screen.getByText(t.upcomingEvents)).toBeInTheDocument(); + expect(screen.getByText('Event 1')).toBeInTheDocument(); + + // Latest posts + expect(screen.getByText(t.latestPosts)).toBeInTheDocument(); expect(screen.getByText('postone')).toBeInTheDocument(); - // Checking if membership requests are rendered + // Membership requests + expect(screen.getByText(t.membershipRequests)).toBeInTheDocument(); expect(screen.getByText('Jane Doe')).toBeInTheDocument(); - const peopleBtn = screen.getByText('Members'); - const adminBtn = screen.getByText('Admins'); - const postBtn = screen.getAllByText('Posts'); - const eventBtn = screen.getAllByText('Events'); - const blockUserBtn = screen.getByText('Blocked Users'); - const requestBtn = screen.getByText('Requests'); - userEvent.click(peopleBtn); - userEvent.click(adminBtn); - userEvent.click(postBtn[0]); - userEvent.click(eventBtn[0]); - userEvent.click(postBtn[0]); - userEvent.click(eventBtn[0]); - userEvent.click(blockUserBtn); - userEvent.click(requestBtn); - }); - - test('Testing buttons and checking empty events, posts and membership requests', async () => { - await act(async () => { - render( - - - - - - - - - , - ); + // Volunteer rankings + expect(screen.getByText(t.volunteerRankings)).toBeInTheDocument(); + expect(screen.getByText('Teresa Bradley')).toBeInTheDocument(); + }); + + it('Click People Card', async () => { + renderOrganizationDashboard(link1); + const membersBtn = await screen.findByText(t.members); + expect(membersBtn).toBeInTheDocument(); + + userEvent.click(membersBtn); + await waitFor(() => { + expect(screen.getByTestId('orgpeople')).toBeInTheDocument(); }); + }); + + it('Click Admin Card', async () => { + renderOrganizationDashboard(link1); + const adminsBtn = await screen.findByText(t.admins); + expect(adminsBtn).toBeInTheDocument(); - await wait(); - const viewEventsBtn = screen.getByTestId('viewAllEvents'); - const viewPostsBtn = screen.getByTestId('viewAllPosts'); - const viewMSBtn = screen.getByTestId('viewAllMembershipRequests'); - - userEvent.click(viewEventsBtn); - userEvent.click(viewPostsBtn); - fireEvent.click(viewMSBtn); - expect(toast.success).toBeCalledWith('Coming soon!'); - - expect( - screen.getByText(/No membership requests present/i), - ).toBeInTheDocument(); - expect(screen.getByText(/No upcoming events/i)).toBeInTheDocument(); - expect(screen.getByText(/No Posts Present/i)).toBeInTheDocument(); - }); - - test('Testing error scenario', async () => { - await act(async () => { - render( - - - - - - - - - , - ); + userEvent.click(adminsBtn); + await waitFor(() => { + expect(screen.getByTestId('orgpeople')).toBeInTheDocument(); }); + }); + + it('Click Post Card', async () => { + renderOrganizationDashboard(link1); + const postsBtn = await screen.findByText(t.posts); + expect(postsBtn).toBeInTheDocument(); - await wait(); - expect(mockNavgate).toHaveBeenCalledWith('/orglist'); - }); - test('upcomingEvents cardItem component should render when length>0', async () => { - mockId = '123'; - await act(async () => { - render( - - - - - - - - - , - ); + userEvent.click(postsBtn); + await waitFor(() => { + expect(screen.getByTestId('orgpost')).toBeInTheDocument(); }); - screen.getByTestId('cardItem'); - }); - - test('event data should get updated using useState function', async () => { - mockId = '123'; - const mockSetState = jest.spyOn(React, 'useState'); - jest.doMock('react', () => ({ - ...jest.requireActual('react'), - useState: (initial: InterfaceQueryOrganizationEventListItem[]) => [ - initial, - mockSetState, - ], - })); - await act(async () => { - render( - - - - - - - - - , - ); + }); + + it('Click Events Card', async () => { + renderOrganizationDashboard(link1); + const eventsBtn = await screen.findByText(t.events); + expect(eventsBtn).toBeInTheDocument(); + + userEvent.click(eventsBtn); + await waitFor(() => { + expect(screen.getByTestId('orgevents')).toBeInTheDocument(); + }); + }); + + it('Click Blocked Users Card', async () => { + renderOrganizationDashboard(link1); + const blockedUsersBtn = await screen.findByText(t.blockedUsers); + expect(blockedUsersBtn).toBeInTheDocument(); + + userEvent.click(blockedUsersBtn); + await waitFor(() => { + expect(screen.getByTestId('blockuser')).toBeInTheDocument(); + }); + }); + + it('Click Requests Card', async () => { + renderOrganizationDashboard(link1); + const requestsBtn = await screen.findByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + + userEvent.click(requestsBtn); + await waitFor(() => { + expect(screen.getByTestId('requests')).toBeInTheDocument(); + }); + }); + + it('Click View All Events', async () => { + renderOrganizationDashboard(link1); + const viewAllBtn = await screen.findAllByText(t.viewAll); + expect(viewAllBtn[0]).toBeInTheDocument(); + + userEvent.click(viewAllBtn[0]); + await waitFor(() => { + expect(screen.getByTestId('orgevents')).toBeInTheDocument(); + }); + }); + + it('Click View All Posts', async () => { + renderOrganizationDashboard(link1); + const viewAllBtn = await screen.findAllByText(t.viewAll); + expect(viewAllBtn[1]).toBeInTheDocument(); + + userEvent.click(viewAllBtn[1]); + await waitFor(() => { + expect(screen.getByTestId('orgpost')).toBeInTheDocument(); + }); + }); + + it('Click View All Requests', async () => { + renderOrganizationDashboard(link1); + const viewAllBtn = await screen.findAllByText(t.viewAll); + expect(viewAllBtn[2]).toBeInTheDocument(); + + userEvent.click(viewAllBtn[2]); + await waitFor(() => { + expect(toast.success).toHaveBeenCalled(); + }); + }); + + it('Click View All Leaderboard', async () => { + renderOrganizationDashboard(link1); + const viewAllBtn = await screen.findAllByText(t.viewAll); + expect(viewAllBtn[3]).toBeInTheDocument(); + + userEvent.click(viewAllBtn[3]); + await waitFor(() => { + expect(screen.getByTestId('leaderboard')).toBeInTheDocument(); + }); + }); + + it('should render Organization Dashboard screen with empty data', async () => { + renderOrganizationDashboard(link3); + + await waitFor(() => { + expect(screen.getByText(t.noUpcomingEvents)).toBeInTheDocument(); + expect(screen.getByText(t.noPostsPresent)).toBeInTheDocument(); + expect(screen.getByText(t.noMembershipRequests)).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteers)).toBeInTheDocument(); + }); + }); + + it('should redirectt to / if error occurs', async () => { + renderOrganizationDashboard(link2); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); }); - expect(mockSetState).toHaveBeenCalled(); }); }); diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx index 1649011427..2aaf52c2db 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx @@ -20,7 +20,7 @@ import CardItem from 'components/OrganizationDashCards/CardItem'; import CardItemLoading from 'components/OrganizationDashCards/CardItemLoading'; import DashBoardCard from 'components/OrganizationDashCards/DashboardCard'; import DashboardCardLoading from 'components/OrganizationDashCards/DashboardCardLoading'; -import { useNavigate, useParams } from 'react-router-dom'; +import { Navigate, useNavigate, useParams } from 'react-router-dom'; import gold from 'assets/images/gold.png'; import silver from 'assets/images/silver.png'; import bronze from 'assets/images/bronze.png'; @@ -44,9 +44,14 @@ import { VOLUNTEER_RANKING } from 'GraphQl/Queries/EventVolunteerQueries'; function organizationDashboard(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'dashboard' }); const { t: tCommon } = useTranslation('common'); + const { t: tErrors } = useTranslation('errors'); document.title = t('title'); const { orgId } = useParams(); + if (!orgId) { + return ; + } + const leaderboardLink = `/leaderboard/${orgId}`; const peopleLink = `/orgpeople/${orgId}`; const postsLink = `/orgpost/${orgId}`; @@ -82,17 +87,19 @@ function organizationDashboard(): JSX.Element { const { data: rankingsData, loading: rankingsLoading, + error: errorRankings, }: { data?: { getVolunteerRanks: InterfaceVolunteerRank[]; }; loading: boolean; + error?: ApolloError; } = useQuery(VOLUNTEER_RANKING, { variables: { orgId, where: { - order_by: 'hours_DESC', - time_frame: 'allTime', + orderBy: 'hours_DESC', + timeFrame: 'allTime', limit: 3, }, }, @@ -156,11 +163,11 @@ function organizationDashboard(): JSX.Element { * UseEffect to handle errors and navigate if necessary. */ useEffect(() => { - if (errorOrg || errorPost || errorEvent) { - console.log('error', errorPost?.message); - navigate('/orglist'); + if (errorOrg || errorPost || errorEvent || errorRankings) { + toast.error(tErrors('errorLoading', { entity: '' })); + navigate('/'); } - }, [errorOrg, errorPost, errorEvent]); + }, [errorOrg, errorPost, errorEvent, errorRankings]); return ( <> @@ -170,7 +177,12 @@ function organizationDashboard(): JSX.Element { {[...Array(6)].map((_, index) => { return ( - + ); @@ -287,7 +299,7 @@ function organizationDashboard(): JSX.Element { {loadingEvent ? ( [...Array(4)].map((_, index) => { - return ; + return ; }) ) : upcomingEvents.length == 0 ? (
@@ -329,7 +341,7 @@ function organizationDashboard(): JSX.Element { {loadingPost ? ( [...Array(4)].map((_, index) => { - return ; + return ; }) ) : postData?.organizations[0].posts.totalCount == 0 ? ( /* eslint-disable */ @@ -382,7 +394,7 @@ function organizationDashboard(): JSX.Element { > {loadingOrgData ? ( [...Array(4)].map((_, index) => { - return ; + return ; }) ) : data?.organizations[0].membershipRequests.length == 0 ? (
{rankingsLoading ? ( [...Array(3)].map((_, index) => { - return ; + return ; }) ) : rankings.length == 0 ? (
@@ -432,7 +444,7 @@ function organizationDashboard(): JSX.Element { ) : ( rankings.map(({ rank, user, hoursVolunteered }, index) => { return ( - <> +
{rank <= 3 ? ( @@ -455,7 +467,7 @@ function organizationDashboard(): JSX.Element {
- {hoursVolunteered} hours
{index < 2 &&
} - +
); }) )} diff --git a/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts index 26e5441f92..e005ed2e7d 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts +++ b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts @@ -1,3 +1,4 @@ +import { VOLUNTEER_RANKING } from 'GraphQl/Queries/EventVolunteerQueries'; import { ORGANIZATIONS_LIST, ORGANIZATION_EVENT_CONNECTION_LIST, @@ -8,12 +9,13 @@ export const MOCKS = [ { request: { query: ORGANIZATIONS_LIST, + variables: { id: 'orgId' }, }, result: { data: { organizations: [ { - _id: 123, + _id: 'orgId', image: '', name: 'Dummy Organization', description: 'This is a Dummy Organization', @@ -53,7 +55,7 @@ export const MOCKS = [ ], membershipRequests: [ { - _id: '456', + _id: 'requestId1', user: { firstName: 'Jane', lastName: 'Doe', @@ -77,7 +79,7 @@ export const MOCKS = [ { request: { query: ORGANIZATION_POST_LIST, - variables: { first: 10 }, + variables: { id: 'orgId', first: 10 }, }, result: { data: { @@ -87,7 +89,7 @@ export const MOCKS = [ edges: [ { node: { - _id: '6411e53835d7ba2344a78e21', + _id: 'postId1', title: 'postone', text: 'This is the first post', imageUrl: null, @@ -105,11 +107,11 @@ export const MOCKS = [ pinned: true, likedBy: [], }, - cursor: '6411e53835d7ba2344a78e21', + cursor: 'postId1', }, { node: { - _id: '6411e54835d7ba2344a78e29', + _id: 'postId2', title: 'posttwo', text: 'Tis is the post two', imageUrl: null, @@ -127,11 +129,11 @@ export const MOCKS = [ likedBy: [], comments: [], }, - cursor: '6411e54835d7ba2344a78e29', + cursor: 'postId2', }, { node: { - _id: '6411e54835d7ba2344a78e30', + _id: 'postId3', title: 'posttwo', text: 'Tis is the post two', imageUrl: null, @@ -149,11 +151,11 @@ export const MOCKS = [ likedBy: [], comments: [], }, - cursor: '6411e54835d7ba2344a78e30', + cursor: 'postId3', }, { node: { - _id: '6411e54835d7ba2344a78e31', + _id: 'postId4', title: 'posttwo', text: 'Tis is the post two', imageUrl: null, @@ -171,12 +173,12 @@ export const MOCKS = [ likedBy: [], comments: [], }, - cursor: '6411e54835d7ba2344a78e31', + cursor: 'postId4', }, ], pageInfo: { - startCursor: '6411e53835d7ba2344a78e21', - endCursor: '6411e54835d7ba2344a78e31', + startCursor: 'postId1', + endCursor: 'postId4', hasNextPage: false, hasPreviousPage: false, }, @@ -191,15 +193,15 @@ export const MOCKS = [ request: { query: ORGANIZATION_EVENT_CONNECTION_LIST, variables: { - organization_id: '123', + organization_id: 'orgId', }, }, result: { data: { eventsByOrganizationConnection: [ { - _id: '1', - title: 'Sample Event', + _id: 'eventId1', + title: 'Event 1', description: 'Sample Description', startDate: '2025-10-29T00:00:00.000Z', endDate: '2023-10-29T23:59:59.000Z', @@ -214,8 +216,8 @@ export const MOCKS = [ isRegisterable: true, }, { - _id: '2', - title: 'Sample Event', + _id: 'eventId2', + title: 'Event 2', description: 'Sample Description', startDate: '2022-10-29T00:00:00.000Z', endDate: '2023-10-29T23:59:59.000Z', @@ -233,12 +235,76 @@ export const MOCKS = [ }, }, }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: 'orgId', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + limit: 3, + }, + }, + }, + result: { + data: { + getVolunteerRanks: [ + { + rank: 1, + hoursVolunteered: 5, + user: { + _id: 'userId1', + lastName: 'Bradley', + firstName: 'Teresa', + image: null, + email: 'testuser4@example.com', + }, + }, + { + rank: 2, + hoursVolunteered: 4, + user: { + _id: 'userId2', + lastName: 'Garza', + firstName: 'Bruce', + image: null, + email: 'testuser5@example.com', + }, + }, + { + rank: 3, + hoursVolunteered: 3, + user: { + _id: 'userId3', + lastName: 'John', + firstName: 'Doe', + image: null, + email: 'testuser6@example.com', + }, + }, + { + rank: 4, + hoursVolunteered: 2, + user: { + _id: 'userId4', + lastName: 'Jane', + firstName: 'Doe', + image: null, + email: 'testuser7@example.com', + }, + }, + ], + }, + }, + }, ]; export const EMPTY_MOCKS = [ { request: { query: ORGANIZATIONS_LIST, + variables: { id: 'orgId' }, }, result: { data: { @@ -299,7 +365,7 @@ export const EMPTY_MOCKS = [ { request: { query: ORGANIZATION_POST_LIST, - variables: { first: 10 }, + variables: { id: 'orgId', first: 10 }, }, result: { data: { @@ -323,6 +389,9 @@ export const EMPTY_MOCKS = [ { request: { query: ORGANIZATION_EVENT_CONNECTION_LIST, + variables: { + organization_id: 'orgId', + }, }, result: { data: { @@ -330,25 +399,62 @@ export const EMPTY_MOCKS = [ }, }, }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: '123', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + limit: 3, + }, + }, + }, + result: { + data: { + getVolunteerRanks: [], + }, + }, + }, ]; export const ERROR_MOCKS = [ { request: { query: ORGANIZATIONS_LIST, + variables: { id: 'orgId' }, }, error: new Error('Mock Graphql ORGANIZATIONS_LIST Error'), }, { request: { query: ORGANIZATION_POST_LIST, + variables: { id: 'orgId', first: 10 }, }, error: new Error('Mock Graphql ORGANIZATION_POST_LIST Error'), }, { request: { query: ORGANIZATION_EVENT_CONNECTION_LIST, + variables: { + organization_id: 'orgId', + }, }, error: new Error('Mock Graphql ORGANIZATION_EVENT_LIST Error'), }, + { + request: { + query: VOLUNTEER_RANKING, + variables: { + orgId: '123', + where: { + orderBy: 'hours_DESC', + timeFrame: 'allTime', + limit: 3, + }, + }, + }, + error: new Error('Mock Graphql VOLUNTEER_RANKING Error'), + }, ]; diff --git a/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx b/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx index 3f299c5c48..b9fd7a7d4d 100644 --- a/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx +++ b/src/screens/UserPortal/Campaigns/PledgeModal.test.tsx @@ -53,7 +53,7 @@ const pledgeProps: InterfacePledgeModal[] = [ _id: '1', firstName: 'John', lastName: 'Doe', - image: null, + image: undefined, }, ], }, @@ -77,7 +77,7 @@ const pledgeProps: InterfacePledgeModal[] = [ _id: '1', firstName: 'John', lastName: 'Doe', - image: null, + image: undefined, }, ], }, diff --git a/src/screens/UserPortal/Volunteer/Actions/Actions.mocks.ts b/src/screens/UserPortal/Volunteer/Actions/Actions.mocks.ts new file mode 100644 index 0000000000..1468c0f12d --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Actions/Actions.mocks.ts @@ -0,0 +1,268 @@ +import { ACTION_ITEMS_BY_USER } from 'GraphQl/Queries/ActionItemQueries'; + +const action1 = { + _id: 'actionId1', + assignee: { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + assigneeGroup: null, + assigneeType: 'EventVolunteer', + assigner: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + actionItemCategory: { + _id: 'categoryId1', + name: 'Category 1', + }, + preCompletionNotes: '', + postCompletionNotes: '', + assignmentDate: '2024-10-25', + dueDate: '2025-10-25', + completionDate: '2024-11-01', + isCompleted: false, + event: { + _id: 'eventId1', + title: 'Event 1', + }, + creator: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + allotedHours: 8, +}; + +const action2 = { + _id: 'actionId2', + assignee: null, + assigneeGroup: { + _id: 'groupId1', + name: 'Group 1', + }, + assigneeType: 'EventVolunteerGroup', + assigner: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + actionItemCategory: { + _id: 'categoryId2', + name: 'Category 2', + }, + preCompletionNotes: '', + postCompletionNotes: '', + assignmentDate: '2024-10-25', + dueDate: '2025-10-26', + completionDate: '2024-11-01', + isCompleted: false, + event: { + _id: 'eventId1', + title: 'Event 1', + }, + creator: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + allotedHours: 8, +}; + +const action3 = { + _id: 'actionId3', + assignee: { + _id: 'volunteerId3', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + }, + assigneeGroup: null, + assigneeType: 'EventVolunteer', + assigner: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + actionItemCategory: { + _id: 'categoryId3', + name: 'Category 3', + }, + preCompletionNotes: '', + postCompletionNotes: '', + assignmentDate: '2024-10-25', + dueDate: '2024-10-27', + completionDate: '2024-11-01', + isCompleted: true, + event: { + _id: 'eventId2', + title: 'Event 2', + }, + creator: { + _id: 'userId1', + firstName: 'Wilt', + lastName: 'Shepherd', + }, + allotedHours: null, +}; + +export const MOCKS = [ + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action1, action2, action3], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: 'dueDate_DESC', + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action2, action1], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: 'dueDate_ASC', + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action1, action2], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + assigneeName: '1', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action2], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + categoryName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action1, action2], + }, + }, + }, + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + categoryName: '1', + }, + }, + }, + result: { + data: { + actionItemsByUser: [action1], + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + result: { + data: { + actionItemsByUser: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: ACTION_ITEMS_BY_USER, + variables: { + userId: 'userId', + orderBy: null, + where: { + orgId: 'orgId', + assigneeName: '', + }, + }, + }, + error: new Error('Mock Graphql ACTION_ITEMS_BY_USER Error'), + }, +]; diff --git a/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx b/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx new file mode 100644 index 0000000000..cb79be91a6 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx @@ -0,0 +1,224 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Actions from './Actions'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, EMPTY_MOCKS, ERROR_MOCKS } from './Actions.mocks'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); + +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.organizationActionItems ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const renderActions = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> +
} + /> + + + + + + , + ); +}; + +describe('Testing Actions Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + beforeEach(() => { + setItem('userId', 'userId'); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + setItem('userId', null); + render( + + + + + + } /> +
} + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Actions screen', async () => { + renderActions(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('Check Sorting Functionality', async () => { + renderActions(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by dueDate_DESC + fireEvent.click(sortBtn); + const dueDateDESC = await screen.findByTestId('dueDate_DESC'); + expect(dueDateDESC).toBeInTheDocument(); + fireEvent.click(dueDateDESC); + + let assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Group 1'); + + // Sort by dueDate_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const dueDateASC = await screen.findByTestId('dueDate_ASC'); + expect(dueDateASC).toBeInTheDocument(); + fireEvent.click(dueDateASC); + + assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('Search by Assignee name and clear the input by backspace', async () => { + renderActions(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Clear the search input by backspace + userEvent.type(searchInput, '1{backspace}'); + + const assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('Search by Assignee name on press of ENTER', async () => { + renderActions(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByAssignee = await screen.findByTestId('assignee'); + expect(searchByAssignee).toBeInTheDocument(); + userEvent.click(searchByAssignee); + + userEvent.type(searchInput, '1{enter}'); + + const assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Group 1'); + }); + + it('Search by Category name on click of search button', async () => { + renderActions(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByCategory = await screen.findByTestId('category'); + expect(searchByCategory).toBeInTheDocument(); + userEvent.click(searchByCategory); + + // Search by name on press of ENTER + userEvent.type(searchInput, '1'); + userEvent.click(await screen.findByTestId('searchBtn')); + + const assigneeName = await screen.findAllByTestId('assigneeName'); + expect(assigneeName[0]).toHaveTextContent('Teresa Bradley'); + }); + + it('should render screen with No Actions', async () => { + renderActions(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noActionItems)).toBeInTheDocument(); + }); + }); + + it('Error while fetching Actions data', async () => { + renderActions(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Open and close ItemUpdateStatusModal', async () => { + renderActions(link1); + + const checkbox = await screen.findAllByTestId('statusCheckbox'); + userEvent.click(checkbox[0]); + + expect(await screen.findByText(t.actionItemStatus)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); + + it('Open and close ItemViewModal', async () => { + renderActions(link1); + + const viewItemBtn = await screen.findAllByTestId('viewItemBtn'); + userEvent.click(viewItemBtn[0]); + + expect(await screen.findByText(t.actionItemDetails)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/Actions/Actions.tsx b/src/screens/UserPortal/Volunteer/Actions/Actions.tsx index e442206dae..ab9c799556 100644 --- a/src/screens/UserPortal/Volunteer/Actions/Actions.tsx +++ b/src/screens/UserPortal/Volunteer/Actions/Actions.tsx @@ -122,6 +122,7 @@ function actions(): JSX.Element { userId, orderBy: sortBy, where: { + orgId, assigneeName: searchBy === 'assignee' ? searchTerm : undefined, categoryName: searchBy === 'category' ? searchTerm : undefined, }, @@ -204,11 +205,11 @@ function actions(): JSX.Element { key={_id + '1'} containerStyle={styles.imageContainer} avatarStyle={styles.TableImage} - name={params.row.assigneeGroup?.name ?? ''} - alt={params.row.assigneeGroup?.name ?? ''} + name={params.row.assigneeGroup?.name as string} + alt={params.row.assigneeGroup?.name as string} />
- {params.row.assigneeGroup?.name ?? ''} + {params.row.assigneeGroup?.name as string}
)} @@ -303,7 +304,7 @@ function actions(): JSX.Element { size="sm" style={{ minWidth: '32px' }} className="me-2 rounded" - data-testid={`viewItemBtn${params.row.id}`} + data-testid={`viewItemBtn`} onClick={() => handleModalClick(params.row, ModalState.VIEW)} > @@ -326,7 +327,7 @@ function actions(): JSX.Element {
handleModalClick(params.row, ModalState.STATUS)} /> @@ -451,20 +452,22 @@ function actions(): JSX.Element { isRowSelectable={() => false} /> - closeModal(ModalState.STATUS)} - actionItemsRefetch={actionItemsRefetch} - /> - {/* View Modal */} {actionItem && ( - closeModal(ModalState.VIEW)} - item={actionItem} - /> + <> + closeModal(ModalState.VIEW)} + item={actionItem} + /> + + closeModal(ModalState.STATUS)} + actionItemsRefetch={actionItemsRefetch} + /> + )}
); diff --git a/src/screens/UserPortal/Volunteer/Groups/GroupModal.test.tsx b/src/screens/UserPortal/Volunteer/Groups/GroupModal.test.tsx new file mode 100644 index 0000000000..1d83d9a872 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/GroupModal.test.tsx @@ -0,0 +1,308 @@ +import React from 'react'; +import type { ApolloLink } from '@apollo/client'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import i18n from 'utils/i18nForTest'; +import { MOCKS, UPDATE_ERROR_MOCKS } from './Groups.mocks'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; +import type { InterfaceGroupModal } from './GroupModal'; +import GroupModal from './GroupModal'; +import userEvent from '@testing-library/user-event'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(UPDATE_ERROR_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const itemProps: InterfaceGroupModal[] = [ + { + isOpen: true, + hide: jest.fn(), + eventId: 'eventId', + refetchGroups: jest.fn(), + group: { + _id: 'groupId', + name: 'Group 1', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId', + }, + }, + }, + { + isOpen: true, + hide: jest.fn(), + eventId: 'eventId', + refetchGroups: jest.fn(), + group: { + _id: 'groupId', + name: 'Group 1', + description: null, + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [], + assignments: [], + event: { + _id: 'eventId', + }, + }, + }, +]; + +const renderGroupModal = ( + link: ApolloLink, + props: InterfaceGroupModal, +): RenderResult => { + return render( + + + + + + + + + + + , + ); +}; + +describe('Testing GroupModal', () => { + it('GroupModal -> Requests -> Accept', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const requestsBtn = screen.getByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + userEvent.click(requestsBtn); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(2); + expect(userName[0]).toHaveTextContent('John Doe'); + expect(userName[1]).toHaveTextContent('Teresa Bradley'); + + const acceptBtn = screen.getAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + userEvent.click(acceptBtn[0]); + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.requestAccepted); + }); + }); + + it('GroupModal -> Requests -> Reject', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const requestsBtn = screen.getByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + userEvent.click(requestsBtn); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(2); + expect(userName[0]).toHaveTextContent('John Doe'); + expect(userName[1]).toHaveTextContent('Teresa Bradley'); + + const rejectBtn = screen.getAllByTestId('rejectBtn'); + expect(rejectBtn).toHaveLength(2); + userEvent.click(rejectBtn[0]); + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.requestRejected); + }); + }); + + it('GroupModal -> Click Requests -> Click Details', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const requestsBtn = screen.getByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + userEvent.click(requestsBtn); + + const detailsBtn = await screen.findByText(t.details); + expect(detailsBtn).toBeInTheDocument(); + userEvent.click(detailsBtn); + }); + + it('GroupModal -> Details -> Update', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const nameInput = screen.getByLabelText(`${t.name} *`); + expect(nameInput).toBeInTheDocument(); + fireEvent.change(nameInput, { target: { value: 'Group 2' } }); + expect(nameInput).toHaveValue('Group 2'); + + const descInput = screen.getByLabelText(t.description); + expect(descInput).toBeInTheDocument(); + fireEvent.change(descInput, { target: { value: 'desc new' } }); + expect(descInput).toHaveValue('desc new'); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '10' } }); + expect(vrInput).toHaveValue('10'); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.volunteerGroupUpdated); + expect(itemProps[0].refetchGroups).toHaveBeenCalled(); + expect(itemProps[0].hide).toHaveBeenCalled(); + }); + }); + + it('GroupModal -> Details -> Update -> Error', async () => { + renderGroupModal(link2, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const nameInput = screen.getByLabelText(`${t.name} *`); + expect(nameInput).toBeInTheDocument(); + fireEvent.change(nameInput, { target: { value: 'Group 2' } }); + expect(nameInput).toHaveValue('Group 2'); + + const descInput = screen.getByLabelText(t.description); + expect(descInput).toBeInTheDocument(); + fireEvent.change(descInput, { target: { value: 'desc new' } }); + expect(descInput).toHaveValue('desc new'); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '10' } }); + expect(vrInput).toHaveValue('10'); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + it('GroupModal -> Requests -> Accept -> Error', async () => { + renderGroupModal(link2, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const requestsBtn = screen.getByText(t.requests); + expect(requestsBtn).toBeInTheDocument(); + userEvent.click(requestsBtn); + + const userName = await screen.findAllByTestId('userName'); + expect(userName).toHaveLength(2); + expect(userName[0]).toHaveTextContent('John Doe'); + expect(userName[1]).toHaveTextContent('Teresa Bradley'); + + const acceptBtn = screen.getAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + userEvent.click(acceptBtn[0]); + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); + + it('Try adding different values for volunteersRequired', async () => { + renderGroupModal(link1, itemProps[1]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const vrInput = screen.getByLabelText(t.volunteersRequired); + expect(vrInput).toBeInTheDocument(); + fireEvent.change(vrInput, { target: { value: '-1' } }); + + await waitFor(() => { + expect(vrInput).toHaveValue(''); + }); + + userEvent.clear(vrInput); + userEvent.type(vrInput, '1{backspace}'); + + await waitFor(() => { + expect(vrInput).toHaveValue(''); + }); + + fireEvent.change(vrInput, { target: { value: '0' } }); + await waitFor(() => { + expect(vrInput).toHaveValue(''); + }); + + fireEvent.change(vrInput, { target: { value: '19' } }); + await waitFor(() => { + expect(vrInput).toHaveValue('19'); + }); + }); + + it('GroupModal -> Details -> No values updated', async () => { + renderGroupModal(link1, itemProps[0]); + expect(screen.getByText(t.manageGroup)).toBeInTheDocument(); + + const submitBtn = screen.getByTestId('submitBtn'); + expect(submitBtn).toBeInTheDocument(); + userEvent.click(submitBtn); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx b/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx index 5f4dfc6cce..4ae162cd70 100644 --- a/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx +++ b/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx @@ -36,7 +36,7 @@ export interface InterfaceGroupModal { isOpen: boolean; hide: () => void; eventId: string; - group: InterfaceVolunteerGroupInfo | null; + group: InterfaceVolunteerGroupInfo; refetchGroups: () => void; } @@ -63,7 +63,7 @@ export interface InterfaceGroupModal { * - A submit button to create or update the pledge. * * On form submission, the component either: - * - Calls `updateVoluneerGroup` mutation to update an existing pledge, or + * - Calls `updateVoluneerGroup` mutation to update an existing group, or * * Success or error messages are displayed using toast notifications based on the result of the mutation. */ @@ -82,11 +82,11 @@ const GroupModal: React.FC = ({ const [modalType, setModalType] = useState<'details' | 'requests'>('details'); const [formState, setFormState] = useState({ - name: group?.name ?? '', - description: group?.description ?? '', - leader: group?.leader ?? null, - volunteerUsers: group?.volunteers.map((volunteer) => volunteer.user) ?? [], - volunteersRequired: group?.volunteersRequired ?? null, + name: group.name, + description: group.description ?? '', + leader: group.leader, + volunteerUsers: group.volunteers.map((volunteer) => volunteer.user), + volunteersRequired: group.volunteersRequired ?? null, }); const [updateVolunteerGroup] = useMutation(UPDATE_VOLUNTEER_GROUP); @@ -129,6 +129,7 @@ const GroupModal: React.FC = ({ variables: { where: { eventId, + groupId: group._id, status: 'requested', }, }, @@ -141,18 +142,16 @@ const GroupModal: React.FC = ({ useEffect(() => { setFormState({ - name: group?.name ?? '', - description: group?.description ?? '', - leader: group?.leader ?? null, - volunteerUsers: - group?.volunteers.map((volunteer) => volunteer.user) ?? [], - volunteersRequired: group?.volunteersRequired ?? null, + name: group.name, + description: group.description ?? '', + leader: group.leader, + volunteerUsers: group.volunteers.map((volunteer) => volunteer.user), + volunteersRequired: group.volunteersRequired ?? null, }); }, [group]); const { name, description, volunteersRequired } = formState; - /*istanbul ignore next*/ const updateGroupHandler = useCallback( async (e: ChangeEvent): Promise => { e.preventDefault(); @@ -181,6 +180,7 @@ const GroupModal: React.FC = ({ refetchGroups(); hide(); } catch (error: unknown) { + console.log(error); toast.error((error as Error).message); } }, @@ -253,6 +253,7 @@ const GroupModal: React.FC = ({ variant="outlined" className={styles.noOutline} value={name} + data-testid="nameInput" onChange={(e) => setFormState({ ...formState, name: e.target.value }) } @@ -282,7 +283,7 @@ const GroupModal: React.FC = ({ label={t('volunteersRequired')} variant="outlined" className={styles.noOutline} - value={volunteersRequired} + value={volunteersRequired ?? ''} onChange={(e) => { if (parseInt(e.target.value) > 0) { setFormState({ @@ -304,7 +305,7 @@ const GroupModal: React.FC = ({ @@ -343,6 +344,7 @@ const GroupModal: React.FC = ({ component="th" scope="row" className="d-flex gap-1 align-items-center" + data-testid="userName" > {image ? ( = ({ size="sm" style={{ minWidth: '32px' }} className="me-2 rounded" - data-testid={`acceptBtn${_id}`} + data-testid={`acceptBtn`} onClick={() => - updateMembershipStatus(_id, 'accepted') + updateMembershipStatus( + request._id, + 'accepted', + ) } > @@ -382,9 +387,12 @@ const GroupModal: React.FC = ({ size="sm" variant="danger" className="rounded" - data-testid={`rejectBtn${_id}`} + data-testid={`rejectBtn`} onClick={() => - updateMembershipStatus(_id, 'rejected') + updateMembershipStatus( + request._id, + 'rejected', + ) } > diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.mocks.ts b/src/screens/UserPortal/Volunteer/Groups/Groups.mocks.ts new file mode 100644 index 0000000000..58f2d525b5 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/Groups.mocks.ts @@ -0,0 +1,468 @@ +import { + UPDATE_VOLUNTEER_GROUP, + UPDATE_VOLUNTEER_MEMBERSHIP, +} from 'GraphQl/Mutations/EventVolunteerMutation'; +import { + EVENT_VOLUNTEER_GROUP_LIST, + USER_VOLUNTEER_MEMBERSHIP, +} from 'GraphQl/Queries/EventVolunteerQueries'; + +const group1 = { + _id: 'groupId1', + name: 'Group 1', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-25T16:16:32.978Z', + creator: { + _id: 'creatorId1', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: 'img-url', + }, + volunteers: [ + { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId1', + }, +}; + +const group2 = { + _id: 'groupId2', + name: 'Group 2', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-27T15:25:13.044Z', + creator: { + _id: 'creatorId2', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId2', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId2', + }, +}; + +const group3 = { + _id: 'groupId3', + name: 'Group 3', + description: 'desc', + volunteersRequired: null, + createdAt: '2024-10-27T15:34:15.889Z', + creator: { + _id: 'creatorId3', + firstName: 'Wilt', + lastName: 'Shepherd', + image: null, + }, + leader: { + _id: 'userId1', + firstName: 'Bruce', + lastName: 'Garza', + image: null, + }, + volunteers: [ + { + _id: 'volunteerId3', + user: { + _id: 'userId', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + ], + assignments: [], + event: { + _id: 'eventId3', + }, +}; + +const membership1 = { + _id: 'membershipId1', + status: 'requested', + createdAt: '2024-10-29T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 1', + startDate: '2044-10-31', + }, + volunteer: { + _id: 'volunteerId1', + user: { + _id: 'userId1', + firstName: 'John', + lastName: 'Doe', + image: 'img-url', + }, + }, + group: { + _id: 'groupId', + name: 'Group 1', + }, +}; + +const membership2 = { + _id: 'membershipId2', + status: 'requested', + createdAt: '2024-10-29T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 1', + startDate: '2044-10-31', + }, + volunteer: { + _id: 'volunteerId2', + user: { + _id: 'userId2', + firstName: 'Teresa', + lastName: 'Bradley', + image: null, + }, + }, + group: { + _id: 'groupId', + name: 'Group 2', + }, +}; + +export const MOCKS = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1, group2, group3], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: 'members_DESC', + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1, group2], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: 'members_ASC', + }, + }, + result: { + data: { + getEventVolunteerGroups: [group2, group1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '1', + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: '', + name_contains: null, + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group1, group2, group3], + }, + }, + }, + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: 'Bruce', + name_contains: null, + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [group3], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + groupId: 'groupId', + status: 'requested', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'rejected', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + data: { + eventId: 'eventId', + name: 'Group 2', + description: 'desc new', + volunteersRequired: 10, + }, + }, + }, + result: { + data: { + updateEventVolunteerGroup: { + _id: 'groupId', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + data: { + eventId: 'eventId', + }, + }, + }, + result: { + data: { + updateEventVolunteerGroup: { + _id: 'groupId', + }, + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: null, + }, + }, + result: { + data: { + getEventVolunteerGroups: [], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + group: 'groupId', + status: 'requested', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: EVENT_VOLUNTEER_GROUP_LIST, + variables: { + where: { + userId: 'userId', + orgId: 'orgId', + leaderName: null, + name_contains: '', + }, + orderBy: null, + }, + }, + error: new Error('Mock Graphql EVENT_VOLUNTEER_GROUP_LIST Error'), + }, +]; + +export const UPDATE_ERROR_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + eventId: 'eventId', + groupId: 'groupId', + status: 'requested', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_MEMBERSHIP Error'), + }, + { + request: { + query: UPDATE_VOLUNTEER_GROUP, + variables: { + id: 'groupId', + data: { + eventId: 'eventId', + name: 'Group 2', + description: 'desc new', + volunteersRequired: 10, + }, + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_GROUP Error'), + }, +]; diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx b/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx new file mode 100644 index 0000000000..947d708134 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx @@ -0,0 +1,220 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Groups from './Groups'; +import type { ApolloLink } from '@apollo/client'; +import { MOCKS, EMPTY_MOCKS, ERROR_MOCKS } from './Groups.mocks'; +import useLocalStorage from 'utils/useLocalstorage'; + +const { setItem } = useLocalStorage(); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.eventVolunteers ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const renderGroups = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } /> + } + /> + + + + + + , + ); +}; + +describe('Testing Groups Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + beforeEach(() => { + setItem('userId', 'userId'); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + setItem('userId', null); + render( + + + + + + } /> + } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Groups screen', async () => { + renderGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + }); + + it('Check Sorting Functionality', async () => { + renderGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by members_DESC + fireEvent.click(sortBtn); + const membersDESC = await screen.findByTestId('members_DESC'); + expect(membersDESC).toBeInTheDocument(); + fireEvent.click(membersDESC); + + let groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + + // Sort by members_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const membersASC = await screen.findByTestId('members_ASC'); + expect(membersASC).toBeInTheDocument(); + fireEvent.click(membersASC); + + groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 2'); + }); + + it('Search by Groups and clear the input by backspace', async () => { + renderGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Clear the search input by backspace + userEvent.type(searchInput, '1{backspace}'); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('Search by Groups on press of ENTER', async () => { + renderGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByGroup = await screen.findByTestId('group'); + expect(searchByGroup).toBeInTheDocument(); + userEvent.click(searchByGroup); + + userEvent.type(searchInput, '1{enter}'); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('Search by Leader on click of search button', async () => { + renderGroups(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const searchToggle = await screen.findByTestId('searchByToggle'); + expect(searchToggle).toBeInTheDocument(); + userEvent.click(searchToggle); + + const searchByLeader = await screen.findByTestId('leader'); + expect(searchByLeader).toBeInTheDocument(); + userEvent.click(searchByLeader); + + // Search by name on press of ENTER + userEvent.type(searchInput, 'Bruce'); + userEvent.click(await screen.findByTestId('searchBtn')); + + const groupName = await screen.findAllByTestId('groupName'); + expect(groupName[0]).toHaveTextContent('Group 1'); + }); + + it('should render screen with No Groups', async () => { + renderGroups(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noVolunteerGroups)).toBeInTheDocument(); + }); + }); + + it('Error while fetching groups data', async () => { + renderGroups(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Open and close ViewModal', async () => { + renderGroups(link1); + + const viewGroupBtn = await screen.findAllByTestId('viewGroupBtn'); + userEvent.click(viewGroupBtn[0]); + + expect(await screen.findByText(t.groupDetails)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('volunteerViewModalCloseBtn')); + }); + + it('Open and close GroupModal', async () => { + renderGroups(link1); + + const editGroupBtn = await screen.findAllByTestId('editGroupBtn'); + userEvent.click(editGroupBtn[0]); + + expect(await screen.findByText(t.manageGroup)).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('modalCloseBtn')); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.tsx b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx index 477fd70825..f0212a611a 100644 --- a/src/screens/UserPortal/Volunteer/Groups/Groups.tsx +++ b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx @@ -73,7 +73,7 @@ function groups(): JSX.Element { const [group, setGroup] = useState(null); const [searchValue, setSearchValue] = useState(''); const [searchTerm, setSearchTerm] = useState(''); - const [sortBy, setSortBy] = useState<'member_ASC' | 'member_DESC' | null>( + const [sortBy, setSortBy] = useState<'members_ASC' | 'members_DESC' | null>( null, ); const [searchBy, setSearchBy] = useState<'leader' | 'group'>('group'); @@ -103,7 +103,8 @@ function groups(): JSX.Element { variables: { where: { eventId: undefined, - userId: userId, + userId, + orgId, leaderName: searchBy === 'leader' ? searchTerm : null, name_contains: searchBy === 'group' ? searchTerm : null, }, @@ -182,7 +183,7 @@ function groups(): JSX.Element { return (
{image ? ( handleModalClick(params.row, ModalState.VIEW)} > @@ -272,7 +273,7 @@ function groups(): JSX.Element { variant="success" size="sm" className="me-2 rounded" - data-testid={`editGroupBtn${params.row.id}`} + data-testid={`editGroupBtn`} onClick={() => handleModalClick(params.row, ModalState.EDIT)} > @@ -357,14 +358,14 @@ function groups(): JSX.Element { setSortBy('member_DESC')} - data-testid="member_DESC" + onClick={() => setSortBy('members_DESC')} + data-testid="members_DESC" > {t('mostMembers')} setSortBy('member_ASC')} - data-testid="member_ASC" + onClick={() => setSortBy('members_ASC')} + data-testid="members_ASC" > {t('leastMembers')} diff --git a/src/screens/UserPortal/Volunteer/Invitations/Invitations.mocks.ts b/src/screens/UserPortal/Volunteer/Invitations/Invitations.mocks.ts new file mode 100644 index 0000000000..c400d96939 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Invitations/Invitations.mocks.ts @@ -0,0 +1,263 @@ +import { UPDATE_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Mutations/EventVolunteerMutation'; +import { USER_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Queries/EventVolunteerQueries'; + +const membership1 = { + _id: 'membershipId1', + status: 'invited', + createdAt: '2024-10-29T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 1', + startDate: '2044-10-31', + }, + volunteer: { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'John', + lastName: 'Doe', + image: 'img-url', + }, + }, + group: null, +}; + +const membership2 = { + _id: 'membershipId2', + status: 'invited', + createdAt: '2024-10-30T10:18:05.851Z', + event: { + _id: 'eventId', + title: 'Event 2', + startDate: '2044-11-31', + }, + volunteer: { + _id: 'volunteerId1', + user: { + _id: 'userId', + firstName: 'John', + lastName: 'Doe', + image: null, + }, + }, + group: { + _id: 'groupId1', + name: 'Group 1', + }, +}; + +export const MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + orderBy: 'createdAt_DESC', + }, + }, + result: { + data: { + getVolunteerMembership: [membership2, membership1], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + orderBy: 'createdAt_ASC', + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: 'group', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership2], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: 'individual', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1], + }, + }, + }, + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + eventTitle: '1', + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'rejected', + }, + }, + result: { + data: { + updateVolunteerMembership: { + _id: 'membershipId1', + }, + }, + }, + }, +]; + +export const EMPTY_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + }, + }, + result: { + data: { + getVolunteerMembership: [], + }, + }, + }, +]; + +export const ERROR_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + }, + }, + error: new Error('Mock Graphql USER_VOLUNTEER_MEMBERSHIP Error'), + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_MEMBERSHIP Error'), + }, +]; + +export const UPDATE_ERROR_MOCKS = [ + { + request: { + query: USER_VOLUNTEER_MEMBERSHIP, + variables: { + where: { + userId: 'userId', + status: 'invited', + filter: null, + }, + }, + }, + result: { + data: { + getVolunteerMembership: [membership1, membership2], + }, + }, + }, + { + request: { + query: UPDATE_VOLUNTEER_MEMBERSHIP, + variables: { + id: 'membershipId1', + status: 'accepted', + }, + }, + error: new Error('Mock Graphql UPDATE_VOLUNTEER_MEMBERSHIP Error'), + }, +]; diff --git a/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx b/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx new file mode 100644 index 0000000000..d28075f378 --- /dev/null +++ b/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx @@ -0,0 +1,325 @@ +import React from 'react'; +import { MockedProvider } from '@apollo/react-testing'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import type { RenderResult } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; +import i18n from 'utils/i18nForTest'; +import Invitations from './Invitations'; +import type { ApolloLink } from '@apollo/client'; +import { + MOCKS, + EMPTY_MOCKS, + ERROR_MOCKS, + UPDATE_ERROR_MOCKS, +} from './Invitations.mocks'; +import { toast } from 'react-toastify'; +import useLocalStorage from 'utils/useLocalstorage'; + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +const { setItem } = useLocalStorage(); + +const link1 = new StaticMockLink(MOCKS); +const link2 = new StaticMockLink(ERROR_MOCKS); +const link3 = new StaticMockLink(EMPTY_MOCKS); +const link4 = new StaticMockLink(UPDATE_ERROR_MOCKS); +const t = { + ...JSON.parse( + JSON.stringify( + i18n.getDataByLanguage('en')?.translation.userVolunteer ?? {}, + ), + ), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.common ?? {})), + ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), +}; + +const renderInvitations = (link: ApolloLink): RenderResult => { + return render( + + + + + + + } + /> +
} + /> + + + + + + , + ); +}; + +describe('Testing Invvitations Screen', () => { + beforeAll(() => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ orgId: 'orgId' }), + })); + }); + + beforeEach(() => { + setItem('userId', 'userId'); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should redirect to fallback URL if URL params are undefined', async () => { + setItem('userId', null); + render( + + + + + + } /> + } + /> + + + + + , + ); + + await waitFor(() => { + expect(screen.getByTestId('paramsError')).toBeInTheDocument(); + }); + }); + + it('should render Invitations screen', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + }); + + it('Check Sorting Functionality', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + let sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + + // Sort by createdAt_DESC + fireEvent.click(sortBtn); + const createdAtDESC = await screen.findByTestId('createdAt_DESC'); + expect(createdAtDESC).toBeInTheDocument(); + fireEvent.click(createdAtDESC); + + let inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to join volunteer group', + ); + + // Sort by createdAt_ASC + sortBtn = await screen.findByTestId('sort'); + expect(sortBtn).toBeInTheDocument(); + fireEvent.click(sortBtn); + const createdAtASC = await screen.findByTestId('createdAt_ASC'); + expect(createdAtASC).toBeInTheDocument(); + fireEvent.click(createdAtASC); + + inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to volunteer for event', + ); + }); + + it('Filter Invitations (all)', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Filter by All + const filter = await screen.findByTestId('filter'); + expect(filter).toBeInTheDocument(); + + fireEvent.click(filter); + const filterAll = await screen.findByTestId('filterAll'); + expect(filterAll).toBeInTheDocument(); + + fireEvent.click(filterAll); + const inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(2); + }); + + it('Filter Invitations (group)', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Filter by All + const filter = await screen.findByTestId('filter'); + expect(filter).toBeInTheDocument(); + + fireEvent.click(filter); + const filterGroup = await screen.findByTestId('filterGroup'); + expect(filterGroup).toBeInTheDocument(); + + fireEvent.click(filterGroup); + const inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(1); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to join volunteer group', + ); + }); + + it('Filter Invitations (individual)', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Filter by All + const filter = await screen.findByTestId('filter'); + expect(filter).toBeInTheDocument(); + + fireEvent.click(filter); + const filterIndividual = await screen.findByTestId('filterIndividual'); + expect(filterIndividual).toBeInTheDocument(); + + fireEvent.click(filterIndividual); + const inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(1); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to volunteer for event', + ); + }); + + it('Search Invitations by event title and clear the input by backspace', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Clear the search input by backspace + userEvent.type(searchInput, '1{backspace}'); + + const inviteSubject = await screen.findAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(2); + }); + + it('Search Invitations by event title on press of ENTER', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Search by name on press of ENTER + userEvent.type(searchInput, '1'); + userEvent.type(searchInput, '{enter}'); + + await waitFor(() => { + const inviteSubject = screen.getAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(1); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to volunteer for event', + ); + }); + }); + + it('Search Invitations by event title on click of search button', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + // Search by name on press of ENTER + userEvent.type(searchInput, '1'); + userEvent.click(screen.getByTestId('searchBtn')); + + await waitFor(() => { + const inviteSubject = screen.getAllByTestId('inviteSubject'); + expect(inviteSubject).toHaveLength(1); + expect(inviteSubject[0]).toHaveTextContent( + 'Invitation to volunteer for event', + ); + }); + }); + + it('should render screen with No Invitations', async () => { + renderInvitations(link3); + + await waitFor(() => { + expect(screen.getByTestId('searchBy')).toBeInTheDocument(); + expect(screen.getByText(t.noInvitations)).toBeInTheDocument(); + }); + }); + + it('Error while fetching invitations data', async () => { + renderInvitations(link2); + + await waitFor(() => { + expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); + }); + }); + + it('Accept Invite', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const acceptBtn = await screen.findAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + + // Accept Request + userEvent.click(acceptBtn[0]); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.invitationAccepted); + }); + }); + + it('Reject Invite', async () => { + renderInvitations(link1); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const rejectBtn = await screen.findAllByTestId('rejectBtn'); + expect(rejectBtn).toHaveLength(2); + + // Reject Request + userEvent.click(rejectBtn[0]); + + await waitFor(() => { + expect(toast.success).toHaveBeenCalledWith(t.invitationRejected); + }); + }); + + it('Error in Update Invite Mutation', async () => { + renderInvitations(link4); + const searchInput = await screen.findByTestId('searchBy'); + expect(searchInput).toBeInTheDocument(); + + const acceptBtn = await screen.findAllByTestId('acceptBtn'); + expect(acceptBtn).toHaveLength(2); + + // Accept Request + userEvent.click(acceptBtn[0]); + + await waitFor(() => { + expect(toast.error).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx b/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx index 6de38155d7..d0ebf50951 100644 --- a/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx +++ b/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx @@ -151,7 +151,7 @@ const Invitations = (): JSX.Element => { setSearchTerm(''); } }} - data-testid="searchInvitations" + data-testid="searchBy" /> diff --git a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx index b3a599c8c9..04653f8c53 100644 --- a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx +++ b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { act } from 'react'; import { MockedProvider } from '@apollo/react-testing'; import { LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; @@ -46,6 +46,14 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; +const debounceWait = async (ms = 350): Promise => { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +}; + const renderUpcomingEvents = (link: ApolloLink): RenderResult => { return render( @@ -118,27 +126,7 @@ describe('Testing Upcoming Events Screen', () => { expect(searchInput).toBeInTheDocument(); }); - it('Search by event title and clear the input by backspace', async () => { - renderUpcomingEvents(link1); - const searchInput = await screen.findByTestId('searchBy'); - expect(searchInput).toBeInTheDocument(); - - const searchToggle = await screen.findByTestId('searchByToggle'); - expect(searchToggle).toBeInTheDocument(); - userEvent.click(searchToggle); - - const searchByTitle = await screen.findByTestId('title'); - expect(searchByTitle).toBeInTheDocument(); - userEvent.click(searchByTitle); - - // Clear the search input by backspace - userEvent.type(searchInput, '1{backspace}'); - - const eventTitle = await screen.findAllByTestId('eventTitle'); - expect(eventTitle[0]).toHaveTextContent('Event 1'); - }); - - it('Search by event title on press of ENTER', async () => { + it('Search by event title', async () => { renderUpcomingEvents(link1); const searchInput = await screen.findByTestId('searchBy'); expect(searchInput).toBeInTheDocument(); @@ -151,7 +139,8 @@ describe('Testing Upcoming Events Screen', () => { expect(searchByTitle).toBeInTheDocument(); userEvent.click(searchByTitle); - userEvent.type(searchInput, '1{enter}'); + userEvent.type(searchInput, '1'); + await debounceWait(); const eventTitle = await screen.findAllByTestId('eventTitle'); expect(eventTitle[0]).toHaveTextContent('Event 1'); @@ -172,7 +161,7 @@ describe('Testing Upcoming Events Screen', () => { // Search by name on press of ENTER userEvent.type(searchInput, 'M'); - userEvent.click(screen.getByTestId('searchBtn')); + await debounceWait(); const eventTitle = await screen.findAllByTestId('eventTitle'); expect(eventTitle[0]).toHaveTextContent('Event 1'); diff --git a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx index 308ff1a53b..b44f8c6619 100644 --- a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx +++ b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx @@ -17,6 +17,7 @@ import { AccordionSummary, Chip, Stack, + debounce, } from '@mui/material'; import { Circle, Search, Sort, WarningAmberRounded } from '@mui/icons-material'; @@ -61,6 +62,11 @@ const UpcomingEvents = (): JSX.Element => { const [createVolunteerMembership] = useMutation(CREATE_VOLUNTEER_MEMBERSHIP); + const debouncedSearch = useMemo( + () => debounce((value: string) => setSearchTerm(value), 300), + [], + ); + const handleVolunteer = async ( eventId: string, group: string | null, @@ -149,13 +155,9 @@ const UpcomingEvents = (): JSX.Element => { required className={styles.inputField} value={searchValue} - onChange={(e) => setSearchValue(e.target.value)} - onKeyUp={(e) => { - if (e.key === 'Enter') { - setSearchTerm(searchValue); - } else if (e.key === 'Backspace' && searchValue === '') { - setSearchTerm(''); - } + onChange={(e) => { + setSearchValue(e.target.value); + debouncedSearch(e.target.value); }} data-testid="searchBy" /> @@ -163,7 +165,6 @@ const UpcomingEvents = (): JSX.Element => { tabIndex={-1} className={`position-absolute z-10 bottom-0 end-0 d-flex justify-content-center align-items-center`} data-testid="searchBtn" - onClick={() => setSearchTerm(searchValue)} > diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index 835269130d..12a071f9b9 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -14,6 +14,20 @@ export interface InterfaceUserInfo { image?: string | null; } +// Base interface for common event properties +export interface InterfaceBaseEvent { + _id: string; + title: string; + description: string; + startDate: string; + endDate: string; + location: string; + startTime: string; + endTime: string; + allDay: boolean; + recurring: boolean; +} + export interface InterfaceActionItemCategoryInfo { _id: string; name: string; @@ -355,17 +369,8 @@ export interface InterfacePledgeInfo { startDate: string; users: InterfaceUserInfo[]; } -export interface InterfaceQueryOrganizationEventListItem { - _id: string; - title: string; - description: string; - startDate: string; - endDate: string; - location: string; - startTime: string; - endTime: string; - allDay: boolean; - recurring: boolean; +export interface InterfaceQueryOrganizationEventListItem + extends InterfaceBaseEvent { isPublic: boolean; isRegisterable: boolean; } @@ -626,17 +631,7 @@ export interface InterfaceCreateVolunteerGroup { volunteerUsers: InterfaceUserInfo[]; } -export interface InterfaceUserEvents { - _id: string; - title: string; - description: string; - startDate: string; - endDate: string; - location: string; - startTime: string; - endTime: string; - allDay: boolean; - recurring: boolean; +export interface InterfaceUserEvents extends InterfaceBaseEvent { volunteerGroups: { _id: string; name: string; From dca3d95de9bccd043a93bdb2e3d6f4137618f63d Mon Sep 17 00:00:00 2001 From: Glen Date: Sat, 2 Nov 2024 11:22:09 +0530 Subject: [PATCH 11/12] coderabbit suggestions --- public/locales/en/translation.json | 5 +- public/locales/fr/translation.json | 5 +- public/locales/hi/translation.json | 5 +- public/locales/sp/translation.json | 5 +- public/locales/zh/translation.json | 5 +- .../Requests/Requests.test.tsx | 2 +- .../EventVolunteers/Requests/Requests.tsx | 2 - .../VolunteerGroups/VolunteerGroups.test.tsx | 2 +- .../VolunteerGroups/VolunteerGroups.tsx | 2 - .../Volunteers/Volunteers.test.tsx | 2 +- src/screens/Leaderboard/Leaderboard.test.tsx | 2 +- src/screens/Leaderboard/Leaderboard.tsx | 8 +- .../OrganizationActionItems.test.tsx | 2 +- .../OrganizationActionItems.tsx | 2 - .../Volunteer/Actions/Actions.test.tsx | 2 +- .../UserPortal/Volunteer/Actions/Actions.tsx | 9 +- .../Volunteer/Groups/Groups.test.tsx | 2 +- .../UserPortal/Volunteer/Groups/Groups.tsx | 2 - .../Invitations/Invitations.test.tsx | 2 +- .../Volunteer/Invitations/Invitations.tsx | 118 +++++++++--------- .../UpcomingEvents/UpcomingEvents.test.tsx | 2 +- .../UpcomingEvents/UpcomingEvents.tsx | 4 +- 22 files changed, 92 insertions(+), 98 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 3d371ee4bf..61b5d01081 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1433,6 +1433,9 @@ "receivedEarliest": "Received Earliest", "invitationAccepted": "Invitation accepted successfully", "invitationRejected": "Invitation rejected successfully", - "volunteerSuccess": "Requested to volunteer successfully" + "volunteerSuccess": "Requested to volunteer successfully", + "recurring": "Recurring", + "groupInvitationSubject": "Invitation to join volunteer group", + "eventInvitationSubject": "Invitation to volunteer for event" } } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 28af730836..58d92af115 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -1433,6 +1433,9 @@ "receivedEarliest": "Reçu en Premier", "invitationAccepted": "Invitation acceptée avec succès", "invitationRejected": "Invitation rejetée avec succès", - "volunteerSuccess": "Demande de bénévolat envoyée avec succès" + "volunteerSuccess": "Demande de bénévolat envoyée avec succès", + "recurring": "Récurrent", + "groupInvitationSubject": "Invitation à rejoindre le groupe de bénévoles", + "eventInvitationSubject": "Invitation à faire du bénévolat pour l'événement" } } diff --git a/public/locales/hi/translation.json b/public/locales/hi/translation.json index a44dc637b7..5b4d9b7f50 100644 --- a/public/locales/hi/translation.json +++ b/public/locales/hi/translation.json @@ -1433,6 +1433,9 @@ "receivedEarliest": "सबसे पहले प्राप्त", "invitationAccepted": "निमंत्रण सफलतापूर्वक स्वीकार किया गया", "invitationRejected": "निमंत्रण सफलतापूर्वक अस्वीकृत", - "volunteerSuccess": "स्वयंसेवक के रूप में अनुरोध सफलतापूर्वक किया गया" + "volunteerSuccess": "स्वयंसेवक के रूप में अनुरोध सफलतापूर्वक किया गया", + "recurring": "पुनरावृत्ति", + "groupInvitationSubject": "स्वयंसेवक समूह में शामिल होने के लिए निमंत्रण", + "eventInvitationSubject": "कार्यक्रम के लिए स्वयंसेवक बनने का निमंत्रण" } } diff --git a/public/locales/sp/translation.json b/public/locales/sp/translation.json index 5300ad939b..3b80396ab6 100644 --- a/public/locales/sp/translation.json +++ b/public/locales/sp/translation.json @@ -1434,6 +1434,9 @@ "receivedEarliest": "Recibido en Primer Lugar", "invitationAccepted": "Invitación aceptada con éxito", "invitationRejected": "Invitación rechazada con éxito", - "volunteerSuccess": "Solicitud de voluntariado realizada con éxito" + "volunteerSuccess": "Solicitud de voluntariado realizada con éxito", + "recurring": "Recurrente", + "groupInvitationSubject": "Invitación a unirse al grupo de voluntarios", + "eventInvitationSubject": "Invitación a ser voluntario para el evento" } } diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index 82c93cfca6..8fd741603a 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -1433,6 +1433,9 @@ "receivedEarliest": "最早收到", "invitationAccepted": "邀请已成功接受", "invitationRejected": "邀请已成功拒绝", - "volunteerSuccess": "志愿请求成功" + "volunteerSuccess": "志愿请求成功", + "recurring": "重复", + "groupInvitationSubject": "邀请加入志愿者小组", + "eventInvitationSubject": "邀请参加活动志愿服务" } } diff --git a/src/screens/EventVolunteers/Requests/Requests.test.tsx b/src/screens/EventVolunteers/Requests/Requests.test.tsx index f74fe78819..3b55ea872c 100644 --- a/src/screens/EventVolunteers/Requests/Requests.test.tsx +++ b/src/screens/EventVolunteers/Requests/Requests.test.tsx @@ -28,7 +28,7 @@ jest.mock('react-toastify', () => ({ }, })); -const debounceWait = async (ms = 350): Promise => { +const debounceWait = async (ms = 300): Promise => { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); diff --git a/src/screens/EventVolunteers/Requests/Requests.tsx b/src/screens/EventVolunteers/Requests/Requests.tsx index fb52e8369f..41abcad763 100644 --- a/src/screens/EventVolunteers/Requests/Requests.tsx +++ b/src/screens/EventVolunteers/Requests/Requests.tsx @@ -139,8 +139,6 @@ function requests(): JSX.Element {
{tErrors('errorLoading', { entity: 'Volunteership Requests' })} -
- {requestsError.message}
diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx index 05919d2330..0dcba34a3a 100644 --- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx @@ -28,7 +28,7 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; -const debounceWait = async (ms = 350): Promise => { +const debounceWait = async (ms = 300): Promise => { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx index 4f18cb90b7..fa98abc9f2 100644 --- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx +++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.tsx @@ -147,8 +147,6 @@ function volunteerGroups(): JSX.Element {
{tErrors('errorLoading', { entity: 'Volunteer Groups' })} -
- {`${groupsError.message}`}
); diff --git a/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx b/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx index be205be94f..2af25b0b84 100644 --- a/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx +++ b/src/screens/EventVolunteers/Volunteers/Volunteers.test.tsx @@ -28,7 +28,7 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; -const debounceWait = async (ms = 350): Promise => { +const debounceWait = async (ms = 300): Promise => { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); diff --git a/src/screens/Leaderboard/Leaderboard.test.tsx b/src/screens/Leaderboard/Leaderboard.test.tsx index 9d8353e70a..d2f12a9052 100644 --- a/src/screens/Leaderboard/Leaderboard.test.tsx +++ b/src/screens/Leaderboard/Leaderboard.test.tsx @@ -26,7 +26,7 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; -const debounceWait = async (ms = 350): Promise => { +const debounceWait = async (ms = 300): Promise => { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); diff --git a/src/screens/Leaderboard/Leaderboard.tsx b/src/screens/Leaderboard/Leaderboard.tsx index c884b945aa..c5ad7a2efe 100644 --- a/src/screens/Leaderboard/Leaderboard.tsx +++ b/src/screens/Leaderboard/Leaderboard.tsx @@ -55,9 +55,11 @@ const dataGridStyle = { }; /** - * Component for managing and displaying action items within an organization. + * Component to display the leaderboard of volunteers. * - * This component allows users to view, filter, sort, and create action items. It also handles fetching and displaying related data such as action item categories and members. + * This component shows a leaderboard of volunteers ranked by hours contributed, + * with features for filtering by time frame and sorting by hours. It displays + * volunteer details including rank, name, email, and hours volunteered. * * @returns The rendered component. */ @@ -127,8 +129,6 @@ function leaderboard(): JSX.Element {
{tErrors('errorLoading', { entity: 'Volunteer Rankings' })} -
- {`${rankingsError.message}`}
); diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx index c755df41d1..44e11baa35 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.test.tsx @@ -47,7 +47,7 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; -const debounceWait = async (ms = 350): Promise => { +const debounceWait = async (ms = 300): Promise => { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); diff --git a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx index 5a616f9dc0..429338b93c 100644 --- a/src/screens/OrganizationActionItems/OrganizationActionItems.tsx +++ b/src/screens/OrganizationActionItems/OrganizationActionItems.tsx @@ -172,8 +172,6 @@ function organizationActionItems(): JSX.Element {
{tErrors('errorLoading', { entity: 'Action Items' })} -
- {`${actionItemsError.message}`}
); diff --git a/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx b/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx index 5272252587..ce64d98adf 100644 --- a/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx +++ b/src/screens/UserPortal/Volunteer/Actions/Actions.test.tsx @@ -32,7 +32,7 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; -const debounceWait = async (ms = 350): Promise => { +const debounceWait = async (ms = 300): Promise => { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); diff --git a/src/screens/UserPortal/Volunteer/Actions/Actions.tsx b/src/screens/UserPortal/Volunteer/Actions/Actions.tsx index 2ba0456f4e..36b1f29b83 100644 --- a/src/screens/UserPortal/Volunteer/Actions/Actions.tsx +++ b/src/screens/UserPortal/Volunteer/Actions/Actions.tsx @@ -149,8 +149,6 @@ function actions(): JSX.Element {
{tErrors('errorLoading', { entity: 'Action Items' })} -
- {`${actionItemsError.message}`}
); @@ -378,7 +376,6 @@ function actions(): JSX.Element { @@ -403,7 +400,6 @@ function actions(): JSX.Element { @@ -446,10 +442,7 @@ function actions(): JSX.Element { getRowClassName={() => `${styles.rowBackground}`} autoHeight rowHeight={65} - rows={actionItems.map((actionItem, index) => ({ - id: index + 1, - ...actionItem, - }))} + rows={actionItems} columns={columns} isRowSelectable={() => false} /> diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx b/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx index 16749e22db..bc0a4993b9 100644 --- a/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx +++ b/src/screens/UserPortal/Volunteer/Groups/Groups.test.tsx @@ -31,7 +31,7 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; -const debounceWait = async (ms = 350): Promise => { +const debounceWait = async (ms = 300): Promise => { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.tsx b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx index 86a3353f08..3941f461d5 100644 --- a/src/screens/UserPortal/Volunteer/Groups/Groups.tsx +++ b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx @@ -146,8 +146,6 @@ function groups(): JSX.Element {
{tErrors('errorLoading', { entity: 'Volunteer Groups' })} -
- {`${groupsError.message}`}
); diff --git a/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx b/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx index 6d385301d4..2c0cafc6a9 100644 --- a/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx +++ b/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx @@ -45,7 +45,7 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; -const debounceWait = async (ms = 350): Promise => { +const debounceWait = async (ms = 300): Promise => { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); diff --git a/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx b/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx index 941ad14619..a79b64251d 100644 --- a/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx +++ b/src/screens/UserPortal/Volunteer/Invitations/Invitations.tsx @@ -127,8 +127,6 @@ const Invitations = (): JSX.Element => {
{tErrors('errorLoading', { entity: 'Volunteership Invitations' })} -
- {invitationError.message}
@@ -230,69 +228,67 @@ const Invitations = (): JSX.Element => { {t('noInvitations')} ) : ( - invitations.map( - (invite: InterfaceVolunteerMembership, index: number) => ( -
-
-
- {invite.group ? ( - <>Invitation to join volunteer group - ) : ( - <>Invitation to volunteer for event - )} + invitations.map((invite: InterfaceVolunteerMembership) => ( +
+
+
+ {invite.group ? ( + <>{t('groupInvitationSubject')} + ) : ( + <>{t('eventInvitationSubject')} + )} +
+
+ {invite.group && ( + <> +
+ + Group:{' '} + {invite.group.name} +
+ | + + )} +
+ + Event:{' '} + {invite.event.title}
-
- {invite.group && ( - <> -
- - Group:{' '} - {invite.group.name} -
- | - - )} -
- - Event:{' '} - {invite.event.title} -
- | -
- - Received:{' '} - {new Date(invite.createdAt).toLocaleString()} -
+ | +
+ + Received:{' '} + {new Date(invite.createdAt).toLocaleString()}
-
- - -
- ), - ) +
+ + +
+
+ )) )} ); diff --git a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx index 04653f8c53..43e0b15cdb 100644 --- a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx +++ b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.test.tsx @@ -46,7 +46,7 @@ const t = { ...JSON.parse(JSON.stringify(i18n.getDataByLanguage('en')?.errors ?? {})), }; -const debounceWait = async (ms = 350): Promise => { +const debounceWait = async (ms = 300): Promise => { await act(() => { return new Promise((resolve) => { setTimeout(resolve, ms); diff --git a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx index b44f8c6619..bd61ca97e0 100644 --- a/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx +++ b/src/screens/UserPortal/Volunteer/UpcomingEvents/UpcomingEvents.tsx @@ -132,8 +132,6 @@ const UpcomingEvents = (): JSX.Element => {
{tErrors('errorLoading', { entity: 'Events' })} -
- {eventsError.message}
@@ -233,7 +231,7 @@ const UpcomingEvents = (): JSX.Element => { {recurring && ( } - label={'Recurring' as unknown as string} + label={t('recurring')} variant="outlined" color="primary" className={`${styles.chip} ${styles.active}`} From a653e3160ed515dd3c7755551c076328d22ccd1c Mon Sep 17 00:00:00 2001 From: Glen Date: Sat, 2 Nov 2024 18:28:12 +0530 Subject: [PATCH 12/12] Removed old query and fixed translation --- public/locales/zh/translation.json | 2 +- src/GraphQl/Queries/ActionItemQueries.ts | 48 ------------------------ 2 files changed, 1 insertion(+), 49 deletions(-) diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index d3dbd2f9c1..c5c8c2c2c5 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -752,7 +752,7 @@ "title": "事件管理", "dashboard": "仪表板", "registrants": "注册者", - "actions": "行动", + "actions": "操作", "agendas": "议程", "statistics": "统计数据", "to": "到", diff --git a/src/GraphQl/Queries/ActionItemQueries.ts b/src/GraphQl/Queries/ActionItemQueries.ts index bf76925ac6..7b24dd6138 100644 --- a/src/GraphQl/Queries/ActionItemQueries.ts +++ b/src/GraphQl/Queries/ActionItemQueries.ts @@ -75,54 +75,6 @@ export const ACTION_ITEM_LIST = gql` } `; -export const ACTION_ITEM_LIST_BY_EVENTS = gql` - query actionItemsByEvent($eventId: ID!) { - actionItemsByEvent(eventId: $eventId) { - _id - assignee { - ... on EventVolunteer { - _id - user { - _id - firstName - lastName - image - } - } - ... on EventVolunteerGroup { - _id - name - } - __typename - } - assigner { - _id - firstName - lastName - } - actionItemCategory { - _id - name - } - preCompletionNotes - postCompletionNotes - assignmentDate - dueDate - completionDate - isCompleted - event { - _id - title - } - creator { - _id - firstName - lastName - } - } - } -`; - export const ACTION_ITEMS_BY_USER = gql` query ActionItemsByUser( $userId: ID!