From f6991a21a23c590222950589a0831b303d4dd6b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafael=20L=C3=A1szl=C3=B3?= <rlacko99@gmail.com>
Date: Sun, 13 Dec 2020 16:11:54 +0100
Subject: [PATCH] refactor admin page routing

---
 client/src/components/Content.tsx             |  9 +--
 .../components/admin/GroupAdminContent.tsx    | 79 +++++++++++++++++++
 .../{GroupAdmin.tsx => GroupAdminPanel.tsx}   | 72 ++++-------------
 .../components/admin/group/GroupDocuments.tsx | 17 ++--
 .../src/components/admin/group/GroupItems.tsx | 10 ++-
 .../components/admin/group/GroupMembers.tsx   | 17 ++--
 .../components/admin/group/GroupRentals.tsx   | 17 ++--
 .../components/admin/group/GroupStorages.tsx  | 10 ++-
 .../queries/group/listGroupMembers.tsx        | 23 ++++++
 9 files changed, 153 insertions(+), 101 deletions(-)
 create mode 100644 client/src/components/admin/GroupAdminContent.tsx
 rename client/src/components/admin/group/{GroupAdmin.tsx => GroupAdminPanel.tsx} (55%)
 create mode 100644 client/src/graphql/queries/group/listGroupMembers.tsx

diff --git a/client/src/components/Content.tsx b/client/src/components/Content.tsx
index 8ee6031..02e31d9 100644
--- a/client/src/components/Content.tsx
+++ b/client/src/components/Content.tsx
@@ -2,7 +2,7 @@ import { Box, Container } from '@material-ui/core';
 import { Redirect, Route, Switch } from 'react-router-dom';
 
 import { Faq } from './Faq';
-import { GroupAdmin } from './admin/group/GroupAdmin';
+import { GroupAdminContent } from './admin/GroupAdminContent';
 import { GroupDocuments } from './admin/group/GroupDocuments';
 import { GroupInfo } from './group/GroupInfo';
 import { GroupItems } from './admin/group/GroupItems';
@@ -30,12 +30,7 @@ export const Content: React.FC = () => {
             <SwitchComponentByAuth isLoggedIn={<OwnProfile />} notLoggedIn={<NotAuthorized />} />
           </Route>
           <Route path="/group/:id/info" component={GroupInfo} />
-          <Route path="/group/:id/admin/members" component={GroupMembers} />
-          <Route path="/group/:id/admin/rentals" component={GroupRentals} />
-          <Route path="/group/:id/admin/documents" component={GroupDocuments} />
-          <Route path="/group/:id/admin/storages" component={GroupStorages} />
-          <Route path="/group/:id/admin/items" component={GroupItems} />
-          <Route path="/group/:id/admin" component={GroupAdmin} />
+          <Route path="/group/:id/admin" component={GroupAdminContent} />
           <Route exact path="/">
             <SwitchComponentByAuth isLoggedIn={<LoggedInHome />} notLoggedIn={<LoggedOutHome />} />
           </Route>
diff --git a/client/src/components/admin/GroupAdminContent.tsx b/client/src/components/admin/GroupAdminContent.tsx
new file mode 100644
index 0000000..3f08d57
--- /dev/null
+++ b/client/src/components/admin/GroupAdminContent.tsx
@@ -0,0 +1,79 @@
+import { IgetGroupById, getGroupById } from '../../graphql/queries/group/getGroupById';
+import { Route, RouteComponentProps, Switch, useLocation } from 'react-router-dom';
+import { useLazyQuery, useQuery } from '@apollo/client';
+
+import { GroupAdminPanel } from './group/GroupAdminPanel';
+import { GroupDocuments } from './group/GroupDocuments';
+import { GroupItems } from './group/GroupItems';
+import { GroupMembers } from './group/GroupMembers';
+import { GroupNotExists } from '../utils/GroupNotExists';
+import { GroupRentals } from './group/GroupRentals';
+import { GroupRole } from '../../types/graphqlSchema';
+import { GroupStorages } from './group/GroupStorages';
+import { Loader } from '../utils/Loader';
+import { NotAdminOfGroup } from '../utils/NotAdminOfGroup';
+import React from 'react';
+
+function useUrlParams() {
+  return new URLSearchParams(useLocation().search);
+}
+
+type TParams = { id: string };
+
+export const GroupAdminContent: React.FC<RouteComponentProps<TParams>> = ({ match }) => {
+  const urlQuery = useUrlParams();
+  const { loading: preGroupDataIsLoading, data: preGroupData, error: preError } = useQuery<IgetGroupById>(
+    getGroupById(''),
+    {
+      variables: { groupId: Number(match.params.id) },
+    },
+  );
+
+  const [getGroup, { loading: groupDataIsLoading, data: groupData, error }] = useLazyQuery<IgetGroupById>(
+    getGroupById('id, name, description, applicantNum, activeRentalNum'),
+    {
+      variables: { groupId: Number(match.params.id) },
+    },
+  );
+
+  React.useEffect(() => {
+    if (
+      !preGroupDataIsLoading &&
+      !!preGroupData &&
+      !(!preGroupData?.group.ownMemberShip || preGroupData?.group.ownMemberShip.groupRole !== GroupRole.Admin)
+    )
+      getGroup();
+  }, [getGroup, preGroupData, preGroupDataIsLoading]);
+
+  if (preGroupDataIsLoading) return <Loader />;
+  if (!!preError) console.log(preError);
+  if (!!error) console.log(error);
+  if (!preGroupData) return <GroupNotExists />;
+  if (!preGroupData?.group.ownMemberShip || preGroupData?.group.ownMemberShip.groupRole !== GroupRole.Admin)
+    return <NotAdminOfGroup />;
+
+  if (groupDataIsLoading) return <Loader />;
+
+  return (
+    <Switch>
+      <Route path={`${match.url}/members`}>
+        <GroupMembers group={groupData?.group} filterBy={urlQuery.get('f')} />
+      </Route>
+      <Route path={`${match.url}/rentals`}>
+        <GroupRentals group={groupData?.group} state={urlQuery.get('s')} />
+      </Route>
+      <Route path={`${match.url}/documents`}>
+        <GroupDocuments group={groupData?.group} orderBy={urlQuery.get('o')} />
+      </Route>
+      <Route path={`${match.url}/storages`}>
+        <GroupStorages group={groupData?.group} />
+      </Route>
+      <Route path={`${match.url}/items`}>
+        <GroupItems group={groupData?.group} />
+      </Route>
+      <Route path={`${match.url}`}>
+        <GroupAdminPanel group={groupData?.group} />
+      </Route>
+    </Switch>
+  );
+};
diff --git a/client/src/components/admin/group/GroupAdmin.tsx b/client/src/components/admin/group/GroupAdminPanel.tsx
similarity index 55%
rename from client/src/components/admin/group/GroupAdmin.tsx
rename to client/src/components/admin/group/GroupAdminPanel.tsx
index 0058ed6..34b660a 100644
--- a/client/src/components/admin/group/GroupAdmin.tsx
+++ b/client/src/components/admin/group/GroupAdminPanel.tsx
@@ -1,50 +1,15 @@
 import { Card, CardContent, Grid, Typography, useTheme } from '@material-ui/core';
-import { IgetGroupById, getGroupById } from '../../../graphql/queries/group/getGroupById';
-import { useLazyQuery, useQuery } from '@apollo/client';
 
-import { GroupNotExists } from '../../utils/GroupNotExists';
-import { GroupRole } from '../../../types/graphqlSchema';
-import { Loader } from '../../utils/Loader';
-import { NotAdminOfGroup } from '../../utils/NotAdminOfGroup';
+import { Group } from '../../../types/graphqlSchema';
 import React from 'react';
-import { RouteComponentProps } from 'react-router-dom';
 import { StyledLink } from '../../utils/StyledLink';
 
-type TParams = { id: string };
+interface TParams {
+  group: Partial<Group> | undefined;
+}
 
-export const GroupAdmin: React.FC<RouteComponentProps<TParams>> = ({ match }) => {
+export const GroupAdminPanel: React.FC<TParams> = ({ group }) => {
   const theme = useTheme();
-  const { loading: preGroupDataIsLoading, data: preGroupData, error: preError } = useQuery<IgetGroupById>(
-    getGroupById(''),
-    {
-      variables: { groupId: Number(match.params.id) },
-    },
-  );
-
-  const [getGroup, { loading: groupDataIsLoading, data: groupData, error }] = useLazyQuery<IgetGroupById>(
-    getGroupById('name, description, applicantNum, activeRentalNum'),
-    {
-      variables: { groupId: Number(match.params.id) },
-    },
-  );
-
-  React.useEffect(() => {
-    if (
-      !preGroupDataIsLoading &&
-      !!preGroupData &&
-      !(!preGroupData?.group.ownMemberShip || preGroupData?.group.ownMemberShip.groupRole !== GroupRole.Admin)
-    )
-      getGroup();
-  }, [getGroup, preGroupData, preGroupDataIsLoading]);
-
-  if (preGroupDataIsLoading) return <Loader />;
-  if (!!preError) console.log(preError);
-  if (!!error) console.log(error);
-  if (!preGroupData) return <GroupNotExists />;
-  if (!preGroupData?.group.ownMemberShip || preGroupData?.group.ownMemberShip.groupRole !== GroupRole.Admin)
-    return <NotAdminOfGroup />;
-
-  if (groupDataIsLoading) return <Loader />;
 
   return (
     <Grid container spacing={1} justify="center">
@@ -52,8 +17,8 @@ export const GroupAdmin: React.FC<RouteComponentProps<TParams>> = ({ match }) =>
         <Card>
           <CardContent>
             <Typography variant="subtitle1">Csoport adatai</Typography>
-            <Typography variant="subtitle1">Neve: {groupData?.group.name}</Typography>
-            <Typography variant="subtitle1">Leírása: {groupData?.group.description}</Typography>
+            <Typography variant="subtitle1">Neve: {group?.name}</Typography>
+            <Typography variant="subtitle1">Leírása: {group?.description}</Typography>
           </CardContent>
         </Card>
       </Grid>
@@ -63,11 +28,11 @@ export const GroupAdmin: React.FC<RouteComponentProps<TParams>> = ({ match }) =>
             <Card>
               <CardContent>
                 <Typography align="center" variant="subtitle1">
-                  {groupData?.group.applicantNum} Új jelentkező
+                  {group?.applicantNum} Új jelentkező
                 </Typography>
                 <Typography align="center" variant="subtitle1">
                   <StyledLink
-                    to={`/group/${match.params.id}/admin/members?role=applicant`}
+                    to={`/group/${group?.id}/admin/members?f=applicant`}
                     style={{ color: theme.palette.primary.dark }}
                   >
                     Bírálás
@@ -80,11 +45,11 @@ export const GroupAdmin: React.FC<RouteComponentProps<TParams>> = ({ match }) =>
             <Card>
               <CardContent>
                 <Typography align="center" variant="subtitle1">
-                  {groupData?.group.activeRentalNum} Kölcsönzés
+                  {group?.activeRentalNum} Kölcsönzés
                 </Typography>
                 <Typography align="center" variant="subtitle1">
                   <StyledLink
-                    to={`/group/${match.params.id}/admin/rentals?state=active`}
+                    to={`/group/${group?.id}/admin/rentals?s=active`}
                     style={{ color: theme.palette.primary.dark }}
                   >
                     Kezelés
@@ -98,8 +63,7 @@ export const GroupAdmin: React.FC<RouteComponentProps<TParams>> = ({ match }) =>
       <Grid item xs={12} md={3}>
         <Grid container spacing={1}>
           <Grid item xs={12}>
-            {/* TODO link to actual group */}
-            <StyledLink to="/group/1/admin/members">
+            <StyledLink to={`/group/${group?.id}/admin/members`}>
               <Card>
                 <CardContent>
                   <Typography align="center" variant="subtitle1">
@@ -110,8 +74,7 @@ export const GroupAdmin: React.FC<RouteComponentProps<TParams>> = ({ match }) =>
             </StyledLink>
           </Grid>
           <Grid item xs={12}>
-            {/* TODO link to actual group */}
-            <StyledLink to="/group/1/admin/items">
+            <StyledLink to={`/group/${group?.id}/admin/items`}>
               <Card>
                 <CardContent>
                   <Typography align="center" variant="subtitle1">
@@ -122,8 +85,7 @@ export const GroupAdmin: React.FC<RouteComponentProps<TParams>> = ({ match }) =>
             </StyledLink>
           </Grid>
           <Grid item xs={12}>
-            {/* TODO link to actual group */}
-            <StyledLink to="/group/1/admin/storages">
+            <StyledLink to={`/group/${group?.id}/admin/storages`}>
               <Card>
                 <CardContent>
                   <Typography align="center" variant="subtitle1">
@@ -134,8 +96,7 @@ export const GroupAdmin: React.FC<RouteComponentProps<TParams>> = ({ match }) =>
             </StyledLink>
           </Grid>
           <Grid item xs={12}>
-            {/* TODO link to actual group */}
-            <StyledLink to="/group/1/admin/documents">
+            <StyledLink to={`/group/${group?.id}/admin/documents`}>
               <Card>
                 <CardContent>
                   <Typography align="center" variant="subtitle1">
@@ -146,8 +107,7 @@ export const GroupAdmin: React.FC<RouteComponentProps<TParams>> = ({ match }) =>
             </StyledLink>
           </Grid>
           <Grid item xs={12}>
-            {/* TODO link to actual group */}
-            <StyledLink to="/group/1/admin/rentals">
+            <StyledLink to={`/group/${group?.id}/admin/rentals`}>
               <Card>
                 <CardContent>
                   <Typography align="center" variant="subtitle1">
diff --git a/client/src/components/admin/group/GroupDocuments.tsx b/client/src/components/admin/group/GroupDocuments.tsx
index 675166d..6af62f1 100644
--- a/client/src/components/admin/group/GroupDocuments.tsx
+++ b/client/src/components/admin/group/GroupDocuments.tsx
@@ -1,15 +1,12 @@
-import { RouteComponentProps, useLocation } from 'react-router-dom';
-
+import { Group } from '../../../types/graphqlSchema';
 import React from 'react';
 
-function useQuery() {
-  return new URLSearchParams(useLocation().search);
+interface TParams {
+  group: Partial<Group> | undefined;
+  orderBy: string | null;
 }
 
-type TParams = { id: string };
-
-export const GroupDocuments: React.FC<RouteComponentProps<TParams>> = ({ match }) => {
-  const query = useQuery();
-  console.log(match.params.id);
-  return <>ordered by = {query.get('order_by') || 'none'}</>;
+export const GroupDocuments: React.FC<TParams> = ({ group, orderBy }) => {
+  console.log(group?.id);
+  return <>ordered by = {orderBy || 'none'}</>;
 };
diff --git a/client/src/components/admin/group/GroupItems.tsx b/client/src/components/admin/group/GroupItems.tsx
index 649f27c..edd7013 100644
--- a/client/src/components/admin/group/GroupItems.tsx
+++ b/client/src/components/admin/group/GroupItems.tsx
@@ -1,9 +1,11 @@
+import { Group } from '../../../types/graphqlSchema';
 import React from 'react';
-import { RouteComponentProps } from 'react-router-dom';
 
-type TParams = { id: string };
+interface TParams {
+  group: Partial<Group> | undefined;
+}
 
-export const GroupItems: React.FC<RouteComponentProps<TParams>> = ({ match }) => {
-  console.log(match.params.id);
+export const GroupItems: React.FC<TParams> = ({ group }) => {
+  console.log(group?.id);
   return <>items</>;
 };
diff --git a/client/src/components/admin/group/GroupMembers.tsx b/client/src/components/admin/group/GroupMembers.tsx
index 04797f0..22e1cbc 100644
--- a/client/src/components/admin/group/GroupMembers.tsx
+++ b/client/src/components/admin/group/GroupMembers.tsx
@@ -1,15 +1,12 @@
-import { RouteComponentProps, useLocation } from 'react-router-dom';
-
+import { Group } from '../../../types/graphqlSchema';
 import React from 'react';
 
-function useQuery() {
-  return new URLSearchParams(useLocation().search);
+interface TParams {
+  group: Partial<Group> | undefined;
+  filterBy: string | null;
 }
 
-type TParams = { id: string };
-
-export const GroupMembers: React.FC<RouteComponentProps<TParams>> = ({ match }) => {
-  const query = useQuery();
-  console.log(match.params.id);
-  return <>filtered role = {query.get('role') || 'none'}</>;
+export const GroupMembers: React.FC<TParams> = ({ group, filterBy }) => {
+  console.log(group?.id);
+  return <>filtered role = {filterBy || 'none'}</>;
 };
diff --git a/client/src/components/admin/group/GroupRentals.tsx b/client/src/components/admin/group/GroupRentals.tsx
index 3492ca2..16298be 100644
--- a/client/src/components/admin/group/GroupRentals.tsx
+++ b/client/src/components/admin/group/GroupRentals.tsx
@@ -1,15 +1,12 @@
-import { RouteComponentProps, useLocation } from 'react-router-dom';
-
+import { Group } from '../../../types/graphqlSchema';
 import React from 'react';
 
-function useQuery() {
-  return new URLSearchParams(useLocation().search);
+interface TParams {
+  group: Partial<Group> | undefined;
+  state: string | null;
 }
 
-type TParams = { id: string };
-
-export const GroupRentals: React.FC<RouteComponentProps<TParams>> = ({ match }) => {
-  const query = useQuery();
-  console.log(match.params.id);
-  return <>filtered state = {query.get('state') || 'none'}</>;
+export const GroupRentals: React.FC<TParams> = ({ group, state }) => {
+  console.log(group?.id);
+  return <>filtered state = {state || 'none'}</>;
 };
diff --git a/client/src/components/admin/group/GroupStorages.tsx b/client/src/components/admin/group/GroupStorages.tsx
index 08d4620..aed57cf 100644
--- a/client/src/components/admin/group/GroupStorages.tsx
+++ b/client/src/components/admin/group/GroupStorages.tsx
@@ -1,9 +1,11 @@
+import { Group } from '../../../types/graphqlSchema';
 import React from 'react';
-import { RouteComponentProps } from 'react-router-dom';
 
-type TParams = { id: string };
+interface TParams {
+  group: Partial<Group> | undefined;
+}
 
-export const GroupStorages: React.FC<RouteComponentProps<TParams>> = ({ match }) => {
-  console.log(match.params.id);
+export const GroupStorages: React.FC<TParams> = ({ group }) => {
+  console.log(group?.id);
   return <>storages</>;
 };
diff --git a/client/src/graphql/queries/group/listGroupMembers.tsx b/client/src/graphql/queries/group/listGroupMembers.tsx
new file mode 100644
index 0000000..fbd31f7
--- /dev/null
+++ b/client/src/graphql/queries/group/listGroupMembers.tsx
@@ -0,0 +1,23 @@
+import { DocumentNode } from 'graphql';
+import { Member } from '../../../types/graphqlSchema';
+import gql from 'graphql-tag';
+
+// Query
+export const listGroupMembers = (fields: string): DocumentNode => {
+  return gql`
+    query listGroupMembers($groupId: Int!) {
+      group(id: $groupId) {
+        members {
+          ${fields}
+        }
+      }
+    }
+  `;
+};
+
+// Returned data
+export interface IListGroupMembers {
+  group: {
+    members: Partial<Member>[];
+  };
+}
-- 
GitLab