Skip to content

Commit

Permalink
Onboarding requests date direction and pagination (#128)
Browse files Browse the repository at this point in the history

Co-authored-by: Shahan Neda <shahan.neda@gmail.com>
  • Loading branch information
Tudor-Barsan and shahanneda authored May 18, 2024
1 parent 2964079 commit dd85454
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 38 deletions.
17 changes: 14 additions & 3 deletions backend/app/graphql/onboarding_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@

from ..graphql.services import services

from .types import Mutation, MutationList, QueryList, UserInfo, UserInfoInput
from .types import (
Mutation,
MutationList,
QueryList,
SortDirection,
UserInfo,
UserInfoInput,
)

ONBOARDING_REQUEST_EMAIL_ALREADY_EXISTS_ERROR = (
"Failed to create onboarding request. Reason = Email already exists"
Expand All @@ -25,26 +32,30 @@ class OnboardingRequest(graphene.ObjectType):
class OnboardingRequestQueries(QueryList):
getAllOnboardingRequests = graphene.List(
OnboardingRequest,
number=graphene.Int(default_value=5),
number=graphene.Int(default_value=9),
offset=graphene.Int(default_value=0),
role=graphene.String(default_value=""),
status=graphene.List(
graphene.String,
default_value=["Pending", "Approved", "Rejected"],
),
sort_by_date_direction=SortDirection(default_value=SortDirection.ASCENDING),
)
getOnboardingRequestById = graphene.Field(
OnboardingRequest, id=graphene.String(required=True)
)

def resolve_getAllOnboardingRequests(self, info, number, offset, role, status):
def resolve_getAllOnboardingRequests(
self, info, number, offset, role, status, sort_by_date_direction
):
onboarding_request_dtos = services[
"onboarding_request_service"
].get_all_onboarding_requests(
number,
offset,
role,
status,
sort_by_date_direction,
)
return [
OnboardingRequest(
Expand Down
17 changes: 15 additions & 2 deletions backend/app/services/implementations/onboarding_request_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ONBOARDING_REQUEST_STATUS_REJECTED,
)
from ...models.user_info import UserInfo
from ...graphql.types import SortDirection
from ...resources.onboarding_request_dto import OnboardingRequestDTO


Expand Down Expand Up @@ -68,11 +69,23 @@ def create_onboarding_request(self, userInfo: UserInfo):
)
raise e

def get_all_onboarding_requests(self, number=5, offset=0, role="", status=[]):
def get_all_onboarding_requests(
self,
number=9,
offset=0,
role="",
status=[],
sort_by_date_direction=SortDirection.ASCENDING,
):
onboarding_request_dtos = []

try:
filteredRequests = OnboardingRequest.objects()
sort_prefix = "+"
if sort_by_date_direction == SortDirection.DESCENDING:
sort_prefix = "-"
filteredRequests = OnboardingRequest.objects().order_by(
f"{sort_prefix}date_submitted"
)
if role:
filteredRequests = filteredRequests.filter(info__role=role)
if status:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ def create_onboarding_request(self, userInfo):
pass

@abstractmethod
def get_all_onboarding_requests(self, number, offset, role, status):
def get_all_onboarding_requests(
self, number, offset, role, status, sort_by_date_direction
):
"""
Gets all OnboardingRequest objects
Expand All @@ -32,6 +34,8 @@ def get_all_onboarding_requests(self, number, offset, role, status):
:type role: string
:param status: optional filter for status of onboarding requests
:type status: string
:param sort_by_date_direction: the direction to sort by (ASC or DESC)
:type sort_by_date_direction: string
:return: list of OnboardingRequest object dicts
:rtype: [OnboardingRequestDTO]
:raises Exception: if OnboardingRequests could not be retrieved
Expand Down
171 changes: 139 additions & 32 deletions frontend/src/pages/OnboardingRequestsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { gql, useMutation, useQuery } from "@apollo/client";
import { ChevronLeftIcon, ChevronRightIcon } from "@chakra-ui/icons";
import {
Badge,
Box,
Expand All @@ -18,6 +19,7 @@ import {
ModalFooter,
ModalHeader,
ModalOverlay,
Select,
Spacer,
Spinner,
Text,
Expand All @@ -39,8 +41,19 @@ import { logPossibleGraphQLError } from "../utils/GraphQLUtils";
import useIsWebView from "../utils/useIsWebView";

const GET_ASP_ONBOARDING_REQUESTS = gql`
query GetASPOnboardingRequests($status: [String!]) {
getAllOnboardingRequests(status: $status, role: "ASP", number: 100) {
query GetASPOnboardingRequests(
$status: [String!]
$sortByDateDirection: SortDirection!
$number: Int!
$offset: Int!
) {
getAllOnboardingRequests(
status: $status
role: "ASP"
number: $number
offset: $offset
sortByDateDirection: $sortByDateDirection
) {
id
info {
email
Expand All @@ -66,8 +79,19 @@ const GET_ASP_ONBOARDING_REQUESTS = gql`
`;

const GET_MEAL_DONOR_ONBOARDING_REQUESTS = gql`
query GetMealDonorOnboardingRequests($status: [String!]) {
getAllOnboardingRequests(status: $status, role: "Donor", number: 100) {
query GetMealDonorOnboardingRequests(
$status: [String!]
$sortByDateDirection: SortDirection!
$number: Int!
$offset: Int!
) {
getAllOnboardingRequests(
status: $status
role: "Donor"
number: $number
offset: $offset
sortByDateDirection: $sortByDateDirection
) {
id
info {
email
Expand Down Expand Up @@ -391,34 +415,46 @@ const ASPCardDisplay = ({
const isWebView = useIsWebView();

return (
<Flex
width="90%"
margin="0 5% 5%"
display="grid"
gridTemplateColumns={isWebView ? "repeat(3, 1fr)" : "repeat(1, 1fr)"}
gridColumnGap="3%"
gridRowGap={isWebView ? "30px" : "50px"}
>
{onboardingRequests
? onboardingRequests.map((request: OnboardingRequest) => (
<ASPCard
key={request?.id}
onboardingRequest={request}
isASP={isASP}
refetch={refetch}
/>
))
: null}
<Flex flexDir="column" width="100%">
<Flex
width="90%"
margin="0 5% 2% 5%"
display="grid"
gridTemplateColumns={isWebView ? "repeat(3, 1fr)" : "repeat(1, 1fr)"}
gridColumnGap="3%"
gridRowGap={isWebView ? "30px" : "50px"}
>
{onboardingRequests
? onboardingRequests.map((request: OnboardingRequest) => (
<ASPCard
key={request?.id}
onboardingRequest={request}
isASP={isASP}
refetch={refetch}
/>
))
: null}
</Flex>
{onboardingRequests.length === 0 && (
<Center h="100px">
<Text fontSize="24">No meal requests to display</Text>
</Center>
)}
</Flex>
);
};

const OnboardingRequestsPage = (): React.ReactElement => {
const [isASP, setIsASP] = React.useState(true);
const [filter, setFilter] = React.useState<Array<OnboardingRequestStatuses>>([
OnboardingRequestStatuses.PENDING,
]);
const [statusFilter, setStatusFilter] = React.useState<
Array<OnboardingRequestStatuses>
>([OnboardingRequestStatuses.PENDING]);
const [dateDirectionFilter, setDateDirectionFilter] = React.useState(
"DESCENDING",
);
const isWebView = useIsWebView();
const [currentPage, setCurrentPage] = React.useState<number>(1);
const requestsPerPage = 9;

const {
data: OnboardingData,
Expand All @@ -429,12 +465,63 @@ const OnboardingRequestsPage = (): React.ReactElement => {
isASP ? GET_ASP_ONBOARDING_REQUESTS : GET_MEAL_DONOR_ONBOARDING_REQUESTS,
{
variables: {
status: filter,
status: statusFilter,
sortByDateDirection: dateDirectionFilter,
number: requestsPerPage,
offset: (currentPage - 1) * requestsPerPage,
},
},
);
logPossibleGraphQLError(OnboardingError);

const getPagination = (): React.ReactElement => {
const a = "hi";
return (
<Flex width="100%" justifyContent="right">
<Flex
display="flex"
alignItems="center"
w="280px"
h="70px"
p="12px 16px"
mr="5%"
bgColor="gray.50"
border="1px solid #E2E8F0"
borderRadius="8px 8px 8px 8px"
gap="12px"
color="#4A5568"
justifyContent="center"
>
<Text fontSize="18px">Page: {currentPage}</Text>
{currentPage === 1 ? (
<ChevronLeftIcon w="30px" h="30px" ml="10px" color="#A0AEC0" />
) : (
<ChevronLeftIcon
w="30px"
h="30px"
ml="10px"
cursor="pointer"
onClick={() => setCurrentPage(currentPage - 1)}
/>
)}
{!OnboardingLoading &&
!OnboardingError &&
OnboardingData.getAllOnboardingRequests &&
OnboardingData.getAllOnboardingRequests.length === 9 ? (
<ChevronRightIcon
w="30px"
h="30px"
cursor="pointer"
onClick={() => setCurrentPage(currentPage + 1)}
/>
) : (
<ChevronRightIcon w="30px" h="30px" color="#A0AEC0" />
)}
</Flex>
</Flex>
);
};

const getTitleSection = (): React.ReactElement => (
<Flex flexDir="column" width="100%">
<TitleSection
Expand All @@ -455,15 +542,15 @@ const OnboardingRequestsPage = (): React.ReactElement => {
padding="2"
borderRadius="3px"
border="solid 1px #E2E8F0"
boxShadow="lg"
boxShadow="md"
color="black"
backgroundColor="white"
_hover={{ backgroundColor: "gray.200" }}
>
<Flex gap="2px" alignItems="center" justifyContent="space-around">
<FiFilter />
<Text>Filter:</Text>
{filter.includes(OnboardingRequestStatuses.PENDING) && (
{statusFilter.includes(OnboardingRequestStatuses.PENDING) && (
<Badge
fontSize="0.7em"
colorScheme="yellow"
Expand All @@ -472,7 +559,7 @@ const OnboardingRequestsPage = (): React.ReactElement => {
Pending
</Badge>
)}
{filter.includes(OnboardingRequestStatuses.APPROVED) && (
{statusFilter.includes(OnboardingRequestStatuses.APPROVED) && (
<Badge
fontSize="0.7em"
colorScheme="green"
Expand All @@ -481,7 +568,7 @@ const OnboardingRequestsPage = (): React.ReactElement => {
Approved
</Badge>
)}
{filter.includes(OnboardingRequestStatuses.REJECTED) && (
{statusFilter.includes(OnboardingRequestStatuses.REJECTED) && (
<Badge fontSize="0.7em" colorScheme="red" borderRadius="8px">
Rejected
</Badge>
Expand All @@ -491,9 +578,9 @@ const OnboardingRequestsPage = (): React.ReactElement => {
<MenuList zIndex="2">
<MenuOptionGroup
type="checkbox"
value={filter}
value={statusFilter}
onChange={(value) =>
setFilter(value as Array<OnboardingRequestStatuses>)
setStatusFilter(value as Array<OnboardingRequestStatuses>)
}
>
<MenuItemOption value={OnboardingRequestStatuses.PENDING}>
Expand Down Expand Up @@ -548,6 +635,25 @@ const OnboardingRequestsPage = (): React.ReactElement => {
</Button>
</Flex>
</Flex>
<Select
width="180px"
height={{ base: "40px", lg: "45px" }}
pt="3"
fontSize="xs"
boxShadow="md"
placeholder="Select option"
value={dateDirectionFilter}
onChange={(e) => {
const { target } = e;
if (target.type === "select-one") {
const selectValue = target.selectedOptions[0].value;
setDateDirectionFilter(selectValue);
}
}}
>
<option value="DESCENDING">Newest to Oldest</option>
<option value="ASCENDING">Oldest to Newest</option>
</Select>
</Flex>
);

Expand All @@ -574,6 +680,7 @@ const OnboardingRequestsPage = (): React.ReactElement => {
/>
)
)}
{getPagination()}
</Flex>
);
};
Expand Down

0 comments on commit dd85454

Please sign in to comment.