From 6ca61b71b4422abcde58c287a109d04ab4c42f3a Mon Sep 17 00:00:00 2001 From: Aiste Tamosauskiene Date: Wed, 28 Apr 2021 11:49:39 +0300 Subject: [PATCH] Workshop task create organization tasks page --- src/App.tsx | 5 + .../queries/organization-tasks.graphql | 8 ++ src/graphql/types.ts | 95 ++++++++++++++++++- src/navigation.ts | 1 + src/pages/OrganizationTasks.test.tsx | 52 ++++++++++ src/pages/OrganizationTasksPage.tsx | 43 +++++++++ 6 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 src/graphql/queries/organization-tasks.graphql create mode 100644 src/pages/OrganizationTasks.test.tsx create mode 100644 src/pages/OrganizationTasksPage.tsx diff --git a/src/App.tsx b/src/App.tsx index 1d724b23..6f2d3496 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -55,6 +55,11 @@ export default function App() { path="/animal/:id" component={React.lazy(() => import('./pages/AnimalDetailsPage'))} /> + import('./pages/OrganizationTasksPage'))} + /> >>; + /** + * Get all chipCompanies. + * + * Examples: + * + * chipCompanies(language: "lt") + */ + chipCompanies?: Maybe>>; /** * Get all colors. * @@ -52,6 +62,22 @@ export type Query = { * events(language: "lt") */ events?: Maybe>>; + /** + * Get all former animal owners. + * + * Examples: + * + * formerAnimalOwners + */ + formerAnimalOwners?: Maybe>>; + /** + * Get a former animal owner with a specific ID. + * + * Examples: + * + * formerAnimalOwner(id: 1) + */ + formerAnimalOwner?: Maybe; /** * Get all genders. * @@ -60,6 +86,7 @@ export type Query = { * genders(language: "lt") */ genders?: Maybe>>; + municipalities?: Maybe>>; /** * Lookup an organization. * @@ -76,6 +103,8 @@ export type Query = { * organizations */ organizations?: Maybe>>; + organizationTasks?: Maybe>>; + organizationTask?: Maybe; _empty?: Maybe; /** * Get all species. @@ -115,11 +144,19 @@ export type QueryAnimalArgs = { id: Scalars['Int']; }; +export type QueryAnimalsArgs = { + ids?: Maybe>; +}; + export type QueryBreedsArgs = { species: Scalars['String']; language: Scalars['String']; }; +export type QueryChipCompaniesArgs = { + language: Scalars['String']; +}; + export type QueryColorsArgs = { language: Scalars['String']; }; @@ -128,6 +165,10 @@ export type QueryEventsArgs = { language: Scalars['String']; }; +export type QueryFormerAnimalOwnerArgs = { + id: Scalars['Int']; +}; + export type QueryGendersArgs = { language: Scalars['String']; }; @@ -136,6 +177,10 @@ export type QueryOrganizationArgs = { id: Scalars['Int']; }; +export type QueryOrganizationTaskArgs = { + id?: Maybe; +}; + export type QuerySpeciesArgs = { language: Scalars['String']; }; @@ -273,8 +318,8 @@ export type CreateAnimalInput = { organization: Scalars['Int']; /** Status */ status?: Maybe; - /** Image URL */ - image_url?: Maybe; + /** Image File */ + image?: Maybe; /** Comments */ comments?: Maybe; /** AnimalRegistration */ @@ -294,8 +339,8 @@ export type UpdateAnimalInput = { organization?: Maybe; /** Status */ status?: Maybe; - /** Image URL */ - image_url?: Maybe; + /** Image File */ + image?: Maybe; /** Comments */ comments?: Maybe; /** AnimalRegistration */ @@ -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'; @@ -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; + /** Former animal owner phone number */ + phone?: Maybe; +}; + /** Represents a gender. */ export type Gender = { __typename?: 'Gender'; @@ -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; +}; + /** Represents an organization. */ export type Organization = { __typename?: 'Organization'; @@ -615,6 +693,15 @@ export type UpdateOrganizationInput = { phone?: Maybe; }; +export type OrganizationTask = { + __typename?: 'OrganizationTask'; + id: Scalars['Int']; + title?: Maybe; + description?: Maybe; + organization: Scalars['Int']; + isDone?: Maybe; +}; + /** Represents a breed. */ export type Species = { __typename?: 'Species'; diff --git a/src/navigation.ts b/src/navigation.ts index 5bf4ae6f..3d4daf70 100644 --- a/src/navigation.ts +++ b/src/navigation.ts @@ -11,6 +11,7 @@ const navigation: Array = [ { 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 }; diff --git a/src/pages/OrganizationTasks.test.tsx b/src/pages/OrganizationTasks.test.tsx new file mode 100644 index 00000000..ffaeecda --- /dev/null +++ b/src/pages/OrganizationTasks.test.tsx @@ -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', () => () =>
Loading...
); +const GET_ORGANIZATION_TASKS = loader('../graphql/queries/organization-tasks.graphql'); +test('should have loading state', () => { + renderWithMockProvider(, { query: GET_ORGANIZATION_TASKS }); + expect(screen.getByText('Loading...')).toBeInTheDocument(); +}); +test('should handle error state', async () => { + renderWithMockProvider(, { + 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(, { + 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(, { + 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(); +}); diff --git a/src/pages/OrganizationTasksPage.tsx b/src/pages/OrganizationTasksPage.tsx new file mode 100644 index 00000000..27cf3f04 --- /dev/null +++ b/src/pages/OrganizationTasksPage.tsx @@ -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 ; + } + if (error) { + return Oooops! Something went wrong; + } + + if (!data?.organizationTasks) { + return Sorry, no data found.; + } + + return ( + + {data.organizationTasks.map((task: OrganizationTask) => ( + + + + {task.title} + {task.description} + + + {task.isDone ? 'Task is done' : 'Task to be taken'} + + + + ))} + + ); +}