Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ export default function App() {
path="/animal/:id"
component={React.lazy(() => import('./pages/AnimalDetailsPage'))}
/>
<PrivateRoute
exact
path="/organization-tasks"
component={React.lazy(() => import('./pages/OrganizationTasksPage'))}
/>
<Route
exact
path="/search"
Expand Down
8 changes: 8 additions & 0 deletions src/graphql/queries/organization-tasks.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
query GetOrganizationTasks {
organizationTasks {
id
title
description
isDone
}
}
95 changes: 91 additions & 4 deletions src/graphql/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export type Scalars = {
Boolean: boolean;
Int: number;
Float: number;
/** The `Upload` scalar type represents a file upload. */
Upload: any;
};

export type Query = {
Expand Down Expand Up @@ -37,6 +39,14 @@ export type Query = {
* breeds(species: "2", language: "lt")
*/
breeds?: Maybe<Array<Maybe<Breed>>>;
/**
* Get all chipCompanies.
*
* Examples:
*
* chipCompanies(language: "lt")
*/
chipCompanies?: Maybe<Array<Maybe<ChipCompany>>>;
/**
* Get all colors.
*
Expand All @@ -52,6 +62,22 @@ export type Query = {
* events(language: "lt")
*/
events?: Maybe<Array<Maybe<Events>>>;
/**
* Get all former animal owners.
*
* Examples:
*
* formerAnimalOwners
*/
formerAnimalOwners?: Maybe<Array<Maybe<FormerAnimalOwner>>>;
/**
* Get a former animal owner with a specific ID.
*
* Examples:
*
* formerAnimalOwner(id: 1)
*/
formerAnimalOwner?: Maybe<FormerAnimalOwner>;
/**
* Get all genders.
*
Expand All @@ -60,6 +86,7 @@ export type Query = {
* genders(language: "lt")
*/
genders?: Maybe<Array<Maybe<Gender>>>;
municipalities?: Maybe<Array<Maybe<Municipality>>>;
/**
* Lookup an organization.
*
Expand All @@ -76,6 +103,8 @@ export type Query = {
* organizations
*/
organizations?: Maybe<Array<Maybe<Organization>>>;
organizationTasks?: Maybe<Array<Maybe<OrganizationTask>>>;
organizationTask?: Maybe<OrganizationTask>;
_empty?: Maybe<Scalars['String']>;
/**
* Get all species.
Expand Down Expand Up @@ -115,11 +144,19 @@ export type QueryAnimalArgs = {
id: Scalars['Int'];
};

export type QueryAnimalsArgs = {
ids?: Maybe<Array<Scalars['Int']>>;
};

export type QueryBreedsArgs = {
species: Scalars['String'];
language: Scalars['String'];
};

export type QueryChipCompaniesArgs = {
language: Scalars['String'];
};

export type QueryColorsArgs = {
language: Scalars['String'];
};
Expand All @@ -128,6 +165,10 @@ export type QueryEventsArgs = {
language: Scalars['String'];
};

export type QueryFormerAnimalOwnerArgs = {
id: Scalars['Int'];
};

export type QueryGendersArgs = {
language: Scalars['String'];
};
Expand All @@ -136,6 +177,10 @@ export type QueryOrganizationArgs = {
id: Scalars['Int'];
};

export type QueryOrganizationTaskArgs = {
id?: Maybe<Scalars['Int']>;
};

export type QuerySpeciesArgs = {
language: Scalars['String'];
};
Expand Down Expand Up @@ -273,8 +318,8 @@ export type CreateAnimalInput = {
organization: Scalars['Int'];
/** Status */
status?: Maybe<AnimalStatus>;
/** Image URL */
image_url?: Maybe<Scalars['String']>;
/** Image File */
image?: Maybe<Scalars['Upload']>;
/** Comments */
comments?: Maybe<Scalars['String']>;
/** AnimalRegistration */
Expand All @@ -294,8 +339,8 @@ export type UpdateAnimalInput = {
organization?: Maybe<Scalars['Int']>;
/** Status */
status?: Maybe<AnimalStatus>;
/** Image URL */
image_url?: Maybe<Scalars['String']>;
/** Image File */
image?: Maybe<Scalars['Upload']>;
/** Comments */
comments?: Maybe<Scalars['String']>;
/** AnimalRegistration */
Expand Down Expand Up @@ -481,6 +526,15 @@ export type Breed = {
value: Scalars['String'];
};

/** Represents a chip company. */
export type ChipCompany = {
__typename?: 'ChipCompany';
/** Chip company id */
id: Scalars['String'];
/** Chip company value */
value: Scalars['String'];
};

/** Represents a color. */
export type Color = {
__typename?: 'Color';
Expand Down Expand Up @@ -557,6 +611,19 @@ export type EventsAnimalMedicalArgs = {
animalId: Scalars['Int'];
};

/** Represents a former animal owner. */
export type FormerAnimalOwner = {
__typename?: 'FormerAnimalOwner';
/** Former animal owner ID, e.g., 1 */
id: Scalars['Int'];
/** Former animal owner name */
name: Scalars['String'];
/** Former animal owner surname */
surname?: Maybe<Scalars['String']>;
/** Former animal owner phone number */
phone?: Maybe<Scalars['String']>;
};

/** Represents a gender. */
export type Gender = {
__typename?: 'Gender';
Expand All @@ -566,6 +633,17 @@ export type Gender = {
value: Scalars['String'];
};

export type Municipality = {
__typename?: 'municipality';
id: Scalars['Int'];
name: Scalars['String'];
};

export type Subscription = {
__typename?: 'Subscription';
organizationCreated?: Maybe<Organization>;
};

/** Represents an organization. */
export type Organization = {
__typename?: 'Organization';
Expand Down Expand Up @@ -615,6 +693,15 @@ export type UpdateOrganizationInput = {
phone?: Maybe<Scalars['String']>;
};

export type OrganizationTask = {
__typename?: 'OrganizationTask';
id: Scalars['Int'];
title?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
organization: Scalars['Int'];
isDone?: Maybe<Scalars['Boolean']>;
};

/** Represents a breed. */
export type Species = {
__typename?: 'Species';
Expand Down
1 change: 1 addition & 0 deletions src/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const navigation: Array<NavigationItem> = [
{ authRequired: true, title: 'Animals', to: '/animal-list', pageTitle: 'Animal list' },
{ authRequired: true, title: 'Favourites', to: '/favourites', pageTitle: 'Favourites' },
{ authRequired: true, title: 'Reports', to: '/reports', pageTitle: 'Reports' },
{ authRequired: true, title: 'Organization Tasks', to: '/organization-tasks', pageTitle: 'Organization Tasks' },
];

export { navigation };
Expand Down
52 changes: 52 additions & 0 deletions src/pages/OrganizationTasks.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { loader } from 'graphql.macro';
import React from 'react';
import { act } from 'react-dom/test-utils';

import { screen } from '@testing-library/react';
import { renderWithMockProvider } from '../test-utils/render-mock-provider';
import OrganizationTasksPage from './OrganizationTasksPage';

jest.mock('@material-ui/lab/Skeleton', () => () => <div>Loading...</div>);
const GET_ORGANIZATION_TASKS = loader('../graphql/queries/organization-tasks.graphql');
test('should have loading state', () => {
renderWithMockProvider(<OrganizationTasksPage />, { query: GET_ORGANIZATION_TASKS });
expect(screen.getByText('Loading...')).toBeInTheDocument();
});
test('should handle error state', async () => {
renderWithMockProvider(<OrganizationTasksPage />, {
query: GET_ORGANIZATION_TASKS,
error: new Error('Something went wrong'),
});
// Wait for the application to update
await act(async () => new Promise(resolve => setTimeout(resolve, 0)));
expect(screen.getByText('Oooops! Something went wrong')).toBeInTheDocument();
});
test('should load organization tasks', async () => {
renderWithMockProvider(<OrganizationTasksPage />, {
query: GET_ORGANIZATION_TASKS,
data: {
organizationTasks: [
{ title: 'Organiz', id: 1, description: 'This is description', organization: 2, isDone: true },
],
},
});
// Wait for the application to update
await act(async () => new Promise(resolve => setTimeout(resolve, 0)));
expect(screen.getByText('Organiz')).toBeInTheDocument();
expect(screen.getByText('This is description')).toBeInTheDocument();
expect(screen.getByText('Task is done')).toBeInTheDocument();
});
test('should load organization tasks without title', async () => {
renderWithMockProvider(<OrganizationTasksPage />, {
query: GET_ORGANIZATION_TASKS,
data: {
organizationTasks: [
{ title: '', id: 1, description: 'This is description', organization: 2, isDone: true },
],
},
});
// Wait for the application to update
await act(async () => new Promise(resolve => setTimeout(resolve, 0)));
expect(screen.getByText('This is description')).toBeInTheDocument();
expect(screen.getByText('Task is done')).toBeInTheDocument();
});
43 changes: 43 additions & 0 deletions src/pages/OrganizationTasksPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { loader } from 'graphql.macro';
import React from 'react';

import { useQuery } from '@apollo/client';
import { Box, Card, CardContent, Typography } from '@material-ui/core';
import { Skeleton } from '@material-ui/lab';
import { OrganizationTask } from '../graphql/types';
import Page from './Page';

const GET_ORGANIZATION_TASKS_QUERY = loader('src/graphql/queries/organization-tasks.graphql');

export default function OrganizationTasksPage() {
const { loading, data, error } = useQuery(GET_ORGANIZATION_TASKS_QUERY);

if (loading) {
return <Skeleton animation="wave" variant="rect" height="70vh" width="40vw" />;
}
if (error) {
return <Typography variant="h6">Oooops! Something went wrong</Typography>;
}

if (!data?.organizationTasks) {
return <Typography variant="h6">Sorry, no data found.</Typography>;
}

return (
<Page title="Organization Tasks">
{data.organizationTasks.map((task: OrganizationTask) => (
<Box key={task.id} width="40vw" my={1}>
<Card>
<CardContent>
<Typography variant="body1">{task.title}</Typography>
<Typography variant="body1">{task.description}</Typography>
</CardContent>
<Box bgcolor={task.isDone ? 'lightGreen' : 'pink'} height="50px" p={1.5}>
<Typography align="center">{task.isDone ? 'Task is done' : 'Task to be taken'}</Typography>
</Box>
</Card>
</Box>
))}
</Page>
);
}