Skip to content

Commit 25953c7

Browse files
committed
Create Field Region tabs, Add Projects grid components and gql
1 parent 142deeb commit 25953c7

File tree

6 files changed

+247
-102
lines changed

6 files changed

+247
-102
lines changed

src/api/schema/typePolicies/typePolicies.base.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ export const typePolicies: TypePolicies = {
8585
engagements: {},
8686
},
8787
},
88+
FieldRegion: {
89+
fields: {
90+
projects: {}, // no page merging (infinite scroll)
91+
},
92+
},
8893
Query: {
8994
fields: {
9095
projects: {},
Lines changed: 47 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,154 +1,99 @@
11
import { useQuery } from '@apollo/client';
2-
import { Edit } from '@mui/icons-material';
3-
import { Box, Skeleton, Typography } from '@mui/material';
2+
import { TabContext, TabList, TabPanel } from '@mui/lab';
3+
import { Box, Skeleton, Stack, Typography } from '@mui/material';
44
import { Helmet } from 'react-helmet-async';
55
import { useParams } from 'react-router-dom';
6-
import { canEditAny } from '~/common';
7-
import { useDialog } from '~/components/Dialog';
8-
import {
9-
DisplaySimpleProperty,
10-
DisplaySimplePropertyProps,
11-
} from '~/components/DisplaySimpleProperty';
12-
import { EditFieldRegion } from '~/components/FieldRegion';
13-
import { Link } from '~/components/Routing';
6+
import { Tab, TabsContainer } from '~/components/Tabs';
7+
import { EnumParam, makeQueryHandler, withDefault } from '~/hooks';
148
import { Error } from '../../../components/Error';
15-
import { Fab } from '../../../components/Fab';
169
import { Redacted } from '../../../components/Redacted';
1710
import { FieldRegionDetailDocument } from './FieldRegionDetail.graphql';
11+
import { FieldRegionProfile } from './Tabs/Profile/FieldRegionProfile';
12+
import { FieldRegionProjects } from './Tabs/Projects/FieldRegionProjects';
13+
14+
const useFieldRegionDetailsFilters = makeQueryHandler({
15+
tab: withDefault(EnumParam(['profile', 'projects']), 'profile'),
16+
});
1817

1918
export const FieldRegionDetail = () => {
2019
const { fieldRegionId = '' } = useParams();
2120

22-
const [editRegionState, editRegion] = useDialog();
23-
2421
const { data, error } = useQuery(FieldRegionDetailDocument, {
2522
variables: { fieldRegionId },
2623
});
2724

25+
const [filters, setFilters] = useFieldRegionDetailsFilters();
26+
2827
const fieldRegion = data?.fieldRegion;
2928

3029
return (
31-
<Box
30+
<Stack
3231
component="main"
3332
sx={{
34-
flex: 1,
33+
overflowY: 'auto',
3534
p: 4,
35+
gap: 3,
36+
flex: 1,
37+
maxWidth: (theme) => theme.breakpoints.values.xl,
3638
}}
3739
>
38-
<Helmet title={fieldRegion?.name.value || undefined} />
3940
<Error error={error}>
4041
{{
4142
NotFound: 'Could not find field region',
4243
Default: 'Error loading field region',
4344
}}
4445
</Error>
46+
<Helmet title={fieldRegion?.name.value ?? undefined} />
47+
4548
{!error && (
46-
<Box
47-
sx={{
48-
maxWidth: (theme) => theme.breakpoints.values.md,
49-
display: 'flex',
50-
flexDirection: 'column',
51-
gap: 3,
52-
}}
53-
>
49+
<>
5450
<Box
55-
component="header"
5651
sx={{
57-
flex: 1,
5852
display: 'flex',
53+
gap: 1,
5954
}}
6055
>
6156
<Typography
6257
variant="h2"
6358
sx={{
64-
mr: 4,
65-
width: !fieldRegion?.name.value ? '40%' : undefined,
59+
mr: 2,
60+
lineHeight: 'inherit',
6661
}}
6762
>
6863
{!fieldRegion ? (
69-
<Skeleton width="100%" />
64+
<Skeleton width="20ch" />
7065
) : (
7166
fieldRegion.name.value ?? (
7267
<Redacted
7368
info="You don't have permission to view this field region's name"
74-
width="40%"
69+
width="20ch"
7570
/>
7671
)
7772
)}
7873
</Typography>
79-
{canEditAny(fieldRegion, true) && (
80-
<Fab
81-
color="primary"
82-
aria-label="edit region"
83-
onClick={editRegion}
84-
loading={!fieldRegion}
85-
>
86-
<Edit />
87-
</Fab>
88-
)}
89-
</Box>
90-
<Box
91-
sx={{
92-
display: 'flex',
93-
}}
94-
>
95-
<Typography variant="h4">
96-
{fieldRegion ? 'Field Region' : <Skeleton width={200} />}
97-
</Typography>
9874
</Box>
99-
<DisplayProperty
100-
label="Field Zone"
101-
value={
102-
<Link to={`/field-zones/${fieldRegion?.fieldZone.value?.id}`}>
103-
{fieldRegion?.fieldZone.value?.name.value}
104-
</Link>
105-
}
106-
loading={!fieldRegion}
107-
/>
108-
<DisplayProperty
109-
label="Director"
110-
value={
111-
<Link to={`/users/${fieldRegion?.director.value?.id}`}>
112-
{fieldRegion?.director.value?.fullName}
113-
</Link>
114-
}
115-
loading={!fieldRegion}
116-
/>
117-
</Box>
118-
)}
119-
{fieldRegion && (
120-
<EditFieldRegion fieldRegion={fieldRegion} {...editRegionState} />
75+
<TabsContainer>
76+
<TabContext value={filters.tab}>
77+
<TabList
78+
onChange={(_e, tab) => setFilters({ ...filters, tab })}
79+
aria-label="field region navigation tabs"
80+
variant="scrollable"
81+
>
82+
<Tab label="Profile" value="profile" />
83+
<Tab label="Projects" value="projects" />
84+
</TabList>
85+
<TabPanel value="profile">
86+
{fieldRegion && (
87+
<FieldRegionProfile fieldRegion={fieldRegion} />
88+
)}
89+
</TabPanel>
90+
<TabPanel value="projects">
91+
{fieldRegion && <FieldRegionProjects />}
92+
</TabPanel>
93+
</TabContext>
94+
</TabsContainer>
95+
</>
12196
)}
122-
</Box>
97+
</Stack>
12398
);
12499
};
125-
126-
const DisplayProperty = (props: DisplaySimplePropertyProps) =>
127-
!props.value && !props.loading ? null : (
128-
<DisplaySimpleProperty
129-
variant="body1"
130-
{...{ component: 'div' }}
131-
{...props}
132-
loading={
133-
props.loading ? (
134-
<>
135-
<Typography variant="body2">
136-
<Skeleton width="10%" />
137-
</Typography>
138-
<Typography variant="body1">
139-
<Skeleton width="40%" />
140-
</Typography>
141-
</>
142-
) : null
143-
}
144-
LabelProps={{
145-
color: 'textSecondary',
146-
variant: 'body2',
147-
...props.LabelProps,
148-
}}
149-
ValueProps={{
150-
color: 'textPrimary',
151-
...props.ValueProps,
152-
}}
153-
/>
154-
);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fragment FieldRegionProfile on FieldRegion {
2+
...DisplayFieldRegion
3+
...FieldRegionForm
4+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { Edit } from '@mui/icons-material';
2+
import {
3+
Box,
4+
IconButton,
5+
Paper,
6+
Skeleton,
7+
Stack,
8+
Tooltip,
9+
Typography,
10+
} from '@mui/material';
11+
import { canEditAny } from '~/common';
12+
import { useDialog } from '~/components/Dialog';
13+
import {
14+
DisplaySimpleProperty,
15+
DisplaySimplePropertyProps,
16+
} from '~/components/DisplaySimpleProperty';
17+
import { EditFieldRegion } from '~/components/FieldRegion/EditFieldRegion/EditFieldRegion';
18+
import { Link } from '~/components/Routing';
19+
import { FieldRegionProfileFragment } from './FieldRegionProfile.graphql';
20+
21+
interface FieldRegionProfileProps {
22+
fieldRegion: FieldRegionProfileFragment;
23+
}
24+
25+
export const FieldRegionProfile = ({
26+
fieldRegion,
27+
}: FieldRegionProfileProps) => {
28+
const [editRegionState, editRegion] = useDialog();
29+
30+
const canEditAnyFields = canEditAny(fieldRegion);
31+
32+
return (
33+
<Box
34+
component={Paper}
35+
sx={(theme) => ({
36+
display: 'flex',
37+
justifyContent: 'space-between',
38+
width: theme.breakpoints.values.md,
39+
minHeight: 200,
40+
})}
41+
>
42+
<Stack
43+
sx={{
44+
p: 2,
45+
gap: 2,
46+
}}
47+
>
48+
<DisplayProperty
49+
label="Field Zone"
50+
value={
51+
<Link to={`/field-zones/${fieldRegion.fieldZone.value?.id}`}>
52+
{fieldRegion.fieldZone.value?.name.value}
53+
</Link>
54+
}
55+
loading={!fieldRegion}
56+
/>
57+
<DisplayProperty
58+
label="Director"
59+
value={
60+
<Link to={`/users/${fieldRegion.director.value?.id}`}>
61+
{fieldRegion.director.value?.fullName}
62+
</Link>
63+
}
64+
loading={!fieldRegion}
65+
/>
66+
</Stack>
67+
<Box sx={{ p: 1 }}>
68+
{canEditAnyFields ? (
69+
<Tooltip title="Edit Field Region">
70+
<IconButton aria-label="edit field region" onClick={editRegion}>
71+
<Edit />
72+
</IconButton>
73+
</Tooltip>
74+
) : null}
75+
</Box>
76+
<EditFieldRegion fieldRegion={fieldRegion} {...editRegionState} />
77+
</Box>
78+
);
79+
};
80+
81+
const DisplayProperty = (props: DisplaySimplePropertyProps) =>
82+
!props.value && !props.loading ? null : (
83+
<DisplaySimpleProperty
84+
variant="body1"
85+
{...{ component: 'div' }}
86+
{...props}
87+
loading={
88+
props.loading ? (
89+
<>
90+
<Typography variant="body2">
91+
<Skeleton width="10%" />
92+
</Typography>
93+
<Typography variant="body1">
94+
<Skeleton width="40%" />
95+
</Typography>
96+
</>
97+
) : null
98+
}
99+
LabelProps={{
100+
color: 'textSecondary',
101+
variant: 'body2',
102+
...props.LabelProps,
103+
}}
104+
ValueProps={{
105+
color: 'textPrimary',
106+
...props.ValueProps,
107+
}}
108+
/>
109+
);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
query FieldRegionProjects($fieldRegionId: ID!, $input: ProjectListInput) {
2+
fieldRegion(id: $fieldRegionId) {
3+
id
4+
projects(input: $input) {
5+
canRead
6+
hasMore
7+
total
8+
items {
9+
...fieldRegionProjectDataGridRow
10+
}
11+
}
12+
}
13+
}
14+
15+
fragment fieldRegionProjectDataGridRow on Project {
16+
...projectDataGridRow
17+
}

0 commit comments

Comments
 (0)