فهرست منبع

working on apollo refetch and update

Tomi Cvetic 4 سال پیش
والد
کامیت
6b6bf575db

+ 19 - 12
backend/schema.graphql

@@ -11,6 +11,25 @@ type FsFile {
 }
 
 type Query {
+  # Training module
+  publishedTrainings(
+    where: TrainingWhereInput
+    orderBy: TrainingOrderByInput
+    skip: Int
+    first: Int
+  ): [Training!]!
+  training(id: ID): Training!
+  trainings(
+    where: TrainingWhereInput
+    orderBy: TrainingOrderByInput
+    skip: Int
+    after: String
+    before: String
+    first: Int
+    last: Int
+  ): [Training!]!
+  trainingsCount(where: TrainingWhereInput): TrainingConnection!
+
   # File module
   fsFiles(directory: String!): [FsFile!]!
   files: [File!]!
@@ -25,18 +44,6 @@ type Query {
     first: Int
     last: Int
   ): [User!]!
-  training(id: ID!): Training
-  trainings(
-    where: TrainingWhereInput
-    orderBy: TrainingOrderByInput
-    skip: Int
-    after: String
-    before: String
-    first: Int
-    last: Int
-  ): [Training!]!
-  publishedTrainings: [Training!]!
-  trainingsCount(where: TrainingWhereInput): TrainingConnection!
   trainingType(where: TrainingTypeWhereUniqueInput!): TrainingType
   trainingTypes(
     where: TrainingTypeWhereInput

+ 27 - 12
backend/src/training/resolvers.ts

@@ -7,9 +7,35 @@ import { checkPermission } from '../user/resolvers'
 
 export const resolvers: IResolvers = {
   Query: {
+    publishedTrainings: async (parent, args, context, info) => {
+      checkPermission(context)
+      return context.db.query.trainings(
+        {
+          where: { published: true },
+          orderBy: 'trainingDate_DESC',
+          first: 10,
+          ...args,
+        },
+        info
+      )
+    },
     training: async (parent, args, context, info) => {
       checkPermission(context)
-      return context.db.query.training({ where: args }, info)
+      if (args && args.id) {
+        console.log('?', args)
+        return context.db.query.training({ where: args }, info)
+      } else {
+        const trainingsArray = await context.db.query.trainings(
+          {
+            where: { published: true },
+            orderBy: 'trainingDate_DESC',
+            first: 1,
+          },
+          info
+        )
+        console.log(trainingsArray)
+        if (trainingsArray && trainingsArray.length > 0) return trainingsArray[0]
+      }
     },
     trainings: async (parent, args, context, info) => {
       checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
@@ -19,17 +45,6 @@ export const resolvers: IResolvers = {
       checkPermission(context)
       return await context.db.query.trainingsConnection(args, '{ aggregate { count } }')
     },
-    publishedTrainings: async (parent, args, context, info) => {
-      checkPermission(context)
-      return context.db.query.trainings(
-        {
-          where: { published: true },
-          orderBy: 'trainingDate_DESC',
-          first: 20,
-        },
-        info
-      )
-    },
     trainingTypes: async (parent, args, context, info) => {
       checkPermission(context)
       return context.db.query.trainingTypes({}, info)

+ 6 - 6
frontend/pages/index.tsx

@@ -1,21 +1,21 @@
 //import initialData from '../initial-data'
-import { usePublishedTrainingsQuery } from '../src/gql'
-import { Training, TrainingArchive } from '../src/training'
+import { useTrainingQuery } from '../src/gql'
+import { TrainingArchive } from '../src/training'
 import { Page } from '../src/app'
 import { useState, useEffect } from 'react'
 import { TTraining } from '../src/training/types'
 import TrainingProgram from '../src/training/components/TrainingProgram'
 import TrainingMeta from '../src/training/components/TrainingMeta'
 import theme from '../src/styles/theme'
-import { formatTime, calculateDuration } from '../src/training/utils'
 
 const Home = () => {
-  const { data, error, loading } = usePublishedTrainingsQuery()
+  const { data, error, loading } = useTrainingQuery()
   const [training, setTraining] = useState<undefined | TTraining>()
+  console.log(data)
 
   useEffect(() => {
-    if (data?.publishedTrainings && data.publishedTrainings.length > 0) {
-      setTraining(data.publishedTrainings[0])
+    if (data?.training) {
+      setTraining(data.training)
     }
   }, [data])
 

+ 9 - 6
frontend/src/app/components/Page.tsx

@@ -8,17 +8,20 @@ import { LoginPage } from '../../user'
 
 const Page: FunctionComponent = ({ children }) => {
   const { user } = useContext(UserContext)
+  console.log(user)
+
+  let content
+  if (!user || user.loading) content = <p>Please wait...</p>
+  else if (user.error) content = <p>Error logging in.</p>
+  else if (user.data?.currentUser) content = children
+  else content = <LoginPage />
+
   return (
     <>
       <Meta />
 
       <Header />
-      <main>
-        {(!user || user.loading) && <p>Please wait...</p>}
-        {user?.error && <p>Error logging in.</p>}
-        {!user?.data && <LoginPage />}
-        {children}
-      </main>
+      <main>{content}</main>
       <Footer />
 
       <style jsx global>

+ 162 - 273
frontend/src/gql/index.tsx

@@ -1656,15 +1656,15 @@ export enum Permission {
 }
 
 export type Query = {
+  publishedTrainings: Array<Training>,
+  training: Training,
+  trainings: Array<Training>,
+  trainingsCount: TrainingConnection,
   fsFiles: Array<FsFile>,
   files: Array<File>,
   currentUser: User,
   user?: Maybe<User>,
   users: Array<User>,
-  training?: Maybe<Training>,
-  trainings: Array<Training>,
-  publishedTrainings: Array<Training>,
-  trainingsCount: TrainingConnection,
   trainingType?: Maybe<TrainingType>,
   trainingTypes: Array<TrainingType>,
   block?: Maybe<Block>,
@@ -1676,19 +1676,22 @@ export type Query = {
 };
 
 
-export type QueryFsFilesArgs = {
-  directory: Scalars['String']
+export type QueryPublishedTrainingsArgs = {
+  where?: Maybe<TrainingWhereInput>,
+  orderBy?: Maybe<TrainingOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  first?: Maybe<Scalars['Int']>
 };
 
 
-export type QueryUserArgs = {
-  where: UserWhereUniqueInput
+export type QueryTrainingArgs = {
+  id?: Maybe<Scalars['ID']>
 };
 
 
-export type QueryUsersArgs = {
-  where?: Maybe<UserWhereInput>,
-  orderBy?: Maybe<UserOrderByInput>,
+export type QueryTrainingsArgs = {
+  where?: Maybe<TrainingWhereInput>,
+  orderBy?: Maybe<TrainingOrderByInput>,
   skip?: Maybe<Scalars['Int']>,
   after?: Maybe<Scalars['String']>,
   before?: Maybe<Scalars['String']>,
@@ -1697,14 +1700,24 @@ export type QueryUsersArgs = {
 };
 
 
-export type QueryTrainingArgs = {
-  id: Scalars['ID']
+export type QueryTrainingsCountArgs = {
+  where?: Maybe<TrainingWhereInput>
 };
 
 
-export type QueryTrainingsArgs = {
-  where?: Maybe<TrainingWhereInput>,
-  orderBy?: Maybe<TrainingOrderByInput>,
+export type QueryFsFilesArgs = {
+  directory: Scalars['String']
+};
+
+
+export type QueryUserArgs = {
+  where: UserWhereUniqueInput
+};
+
+
+export type QueryUsersArgs = {
+  where?: Maybe<UserWhereInput>,
+  orderBy?: Maybe<UserOrderByInput>,
   skip?: Maybe<Scalars['Int']>,
   after?: Maybe<Scalars['String']>,
   before?: Maybe<Scalars['String']>,
@@ -1713,11 +1726,6 @@ export type QueryTrainingsArgs = {
 };
 
 
-export type QueryTrainingsCountArgs = {
-  where?: Maybe<TrainingWhereInput>
-};
-
-
 export type QueryTrainingTypeArgs = {
   where: TrainingTypeWhereUniqueInput
 };
@@ -3399,87 +3407,25 @@ export type UserWhereUniqueInput = {
   email?: Maybe<Scalars['String']>,
 };
 
-export type ExerciseContentFragment = Pick<Exercise, 'id' | 'name' | 'description' | 'videos' | 'pictures' | 'targets' | 'baseExercise'>;
+export type PublishedTrainingsQueryVariables = {
+  where?: Maybe<TrainingWhereInput>,
+  orderBy?: Maybe<TrainingOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  first?: Maybe<Scalars['Int']>
+};
 
-export type BlockWithoutBlocksFragment = (
-  Pick<Block, 'id' | 'title' | 'description' | 'videos' | 'pictures' | 'duration' | 'rest'>
-  & { format: Pick<Format, 'id' | 'name' | 'description'>, exercises: Maybe<Array<(
-    Pick<ExerciseInstance, 'id' | 'order' | 'repetitions' | 'variation'>
-    & { exercise: ExerciseContentFragment }
-  )>> }
-);
 
-export type BlockInstanceWithoutBlockFragment = Pick<BlockInstance, 'id' | 'order' | 'rounds' | 'variation'>;
+export type PublishedTrainingsQuery = { publishedTrainings: Array<(
+    Pick<Training, 'id' | 'title' | 'trainingDate' | 'attendance'>
+    & { type: Pick<TrainingType, 'id' | 'name' | 'description'>, registrations: Maybe<Array<Pick<User, 'id'>>> }
+  )>, count: { aggregate: Pick<AggregateTraining, 'count'> } };
 
 export type TrainingQueryVariables = {
-  id: Scalars['ID']
+  id?: Maybe<Scalars['ID']>
 };
 
 
-export type TrainingQuery = { training: Maybe<(
-    Pick<Training, 'id' | 'title' | 'createdAt' | 'trainingDate' | 'location' | 'attendance' | 'published'>
-    & { type: Pick<TrainingType, 'id' | 'name' | 'description'>, blocks: Maybe<Array<(
-      { block: (
-        { blocks: Maybe<Array<(
-          { block: (
-            { blocks: Maybe<Array<(
-              { block: BlockWithoutBlocksFragment }
-              & BlockInstanceWithoutBlockFragment
-            )>> }
-            & BlockWithoutBlocksFragment
-          ) }
-          & BlockInstanceWithoutBlockFragment
-        )>> }
-        & BlockWithoutBlocksFragment
-      ) }
-      & BlockInstanceWithoutBlockFragment
-    )>>, registrations: Maybe<Array<Pick<User, 'id' | 'name'>>> }
-  )> };
-
-export type DisplayTrainingFragment = (
-  Pick<Training, 'id' | 'title' | 'trainingDate' | 'location' | 'attendance'>
-  & { type: Pick<TrainingType, 'id' | 'name' | 'description'>, blocks: Maybe<Array<(
-    { block: (
-      { blocks: Maybe<Array<(
-        { block: (
-          { blocks: Maybe<Array<(
-            { block: (
-              { blocks: Maybe<Array<Pick<BlockInstance, 'id'>>> }
-              & DisplayBlockFragment
-            ) }
-            & DisplayBlockInstanceFragment
-          )>> }
-          & DisplayBlockFragment
-        ) }
-        & DisplayBlockInstanceFragment
-      )>> }
-      & DisplayBlockFragment
-    ) }
-    & DisplayBlockInstanceFragment
-  )>>, registrations: Maybe<Array<Pick<User, 'id'>>> }
-);
-
-export type DisplayBlockInstanceFragment = Pick<BlockInstance, 'id' | 'order' | 'rounds' | 'variation'>;
-
-export type DisplayBlockFragment = (
-  Pick<Block, 'id' | 'title' | 'description' | 'videos' | 'pictures' | 'duration' | 'rest'>
-  & { format: Pick<Format, 'name' | 'description'>, exercises: Maybe<Array<(
-    Pick<ExerciseInstance, 'order' | 'repetitions' | 'variation'>
-    & { exercise: DisplayExerciseFragment }
-  )>> }
-);
-
-export type DisplayExerciseInstanceFragment = (
-  Pick<ExerciseInstance, 'id' | 'order' | 'repetitions' | 'variation'>
-  & { exercise: DisplayExerciseFragment }
-);
-
-export type DisplayExerciseFragment = Pick<Exercise, 'id' | 'name' | 'description' | 'videos' | 'pictures' | 'targets' | 'baseExercise'>;
-
-export type PublishedTrainingsQueryVariables = {};
-
-
-export type PublishedTrainingsQuery = { publishedTrainings: Array<DisplayTrainingFragment> };
+export type TrainingQuery = { training: DisplayTrainingFragment };
 
 export type TrainingsQueryVariables = {
   where?: Maybe<TrainingWhereInput>,
@@ -3492,25 +3438,7 @@ export type TrainingsQueryVariables = {
 };
 
 
-export type TrainingsQuery = { count: { aggregate: Pick<AggregateTraining, 'count'> }, trainings: Array<(
-    Pick<Training, 'id' | 'title' | 'trainingDate' | 'location' | 'attendance' | 'published'>
-    & { type: Pick<TrainingType, 'id' | 'name' | 'description'>, blocks: Maybe<Array<(
-      { block: (
-        { blocks: Maybe<Array<(
-          { block: (
-            { blocks: Maybe<Array<(
-              { block: BlockWithoutBlocksFragment }
-              & BlockInstanceWithoutBlockFragment
-            )>> }
-            & BlockWithoutBlocksFragment
-          ) }
-          & BlockInstanceWithoutBlockFragment
-        )>> }
-        & BlockWithoutBlocksFragment
-      ) }
-      & BlockInstanceWithoutBlockFragment
-    )>>, registrations: Maybe<Array<Pick<User, 'id' | 'name'>>> }
-  )> };
+export type TrainingsQuery = { count: { aggregate: Pick<AggregateTraining, 'count'> }, trainings: Array<DisplayTrainingFragment> };
 
 export type TrainingTypesQueryVariables = {};
 
@@ -3527,7 +3455,13 @@ export type BlocksQueryVariables = {};
 
 export type BlocksQuery = { blocks: Array<(
     { blocks: Maybe<Array<(
-      { block: BlockWithoutBlocksFragment }
+      { block: (
+        { blocks: Maybe<Array<(
+          { block: BlockWithoutBlocksFragment }
+          & BlockInstanceWithoutBlockFragment
+        )>> }
+        & BlockWithoutBlocksFragment
+      ) }
       & BlockInstanceWithoutBlockFragment
     )>> }
     & BlockWithoutBlocksFragment
@@ -3597,6 +3531,47 @@ export type PublishMutationVariables = {
 
 export type PublishMutation = Pick<Mutation, 'publish'>;
 
+export type ExerciseContentFragment = Pick<Exercise, 'id' | 'name' | 'description' | 'videos' | 'pictures' | 'targets' | 'baseExercise'>;
+
+export type BlockWithoutBlocksFragment = (
+  Pick<Block, 'id' | 'title' | 'description' | 'videos' | 'pictures' | 'duration' | 'rest'>
+  & { format: Pick<Format, 'id' | 'name' | 'description'>, exercises: Maybe<Array<(
+    Pick<ExerciseInstance, 'id' | 'order' | 'repetitions' | 'variation'>
+    & { exercise: ExerciseContentFragment }
+  )>> }
+);
+
+export type BlockInstanceWithoutBlockFragment = Pick<BlockInstance, 'id' | 'order' | 'rounds' | 'variation'>;
+
+export type DisplayTrainingFragment = (
+  Pick<Training, 'id' | 'title' | 'createdAt' | 'trainingDate' | 'location' | 'attendance' | 'published'>
+  & { type: Pick<TrainingType, 'id' | 'name' | 'description'>, blocks: Maybe<Array<(
+    { block: (
+      { blocks: Maybe<Array<(
+        { block: (
+          { blocks: Maybe<Array<(
+            { block: (
+              { blocks: Maybe<Array<(
+                { block: (
+                  { blocks: Maybe<Array<Pick<BlockInstance, 'id'>>> }
+                  & BlockWithoutBlocksFragment
+                ) }
+                & BlockInstanceWithoutBlockFragment
+              )>> }
+              & BlockWithoutBlocksFragment
+            ) }
+            & BlockInstanceWithoutBlockFragment
+          )>> }
+          & BlockWithoutBlocksFragment
+        ) }
+        & BlockInstanceWithoutBlockFragment
+      )>> }
+      & BlockWithoutBlocksFragment
+    ) }
+    & BlockInstanceWithoutBlockFragment
+  )>>, registrations: Maybe<Array<Pick<User, 'id'>>> }
+);
+
 export type UsersQueryVariables = {};
 
 
@@ -3659,6 +3634,14 @@ export type UserUpdateMutationVariables = {
 
 export type UserUpdateMutation = { updateUser: Maybe<Pick<User, 'id' | 'name' | 'email' | 'permissions' | 'interests'>> };
 
+export const BlockInstanceWithoutBlockFragmentDoc = gql`
+    fragment blockInstanceWithoutBlock on BlockInstance {
+  id
+  order
+  rounds
+  variation
+}
+    `;
 export const ExerciseContentFragmentDoc = gql`
     fragment exerciseContent on Exercise {
   id
@@ -3695,56 +3678,6 @@ export const BlockWithoutBlocksFragmentDoc = gql`
   }
 }
     ${ExerciseContentFragmentDoc}`;
-export const BlockInstanceWithoutBlockFragmentDoc = gql`
-    fragment blockInstanceWithoutBlock on BlockInstance {
-  id
-  order
-  rounds
-  variation
-}
-    `;
-export const DisplayBlockInstanceFragmentDoc = gql`
-    fragment displayBlockInstance on BlockInstance {
-  id
-  order
-  rounds
-  variation
-}
-    `;
-export const DisplayExerciseFragmentDoc = gql`
-    fragment displayExercise on Exercise {
-  id
-  name
-  description
-  videos
-  pictures
-  targets
-  baseExercise
-}
-    `;
-export const DisplayBlockFragmentDoc = gql`
-    fragment displayBlock on Block {
-  id
-  title
-  description
-  videos
-  pictures
-  duration
-  format {
-    name
-    description
-  }
-  rest
-  exercises {
-    order
-    repetitions
-    variation
-    exercise {
-      ...displayExercise
-    }
-  }
-}
-    ${DisplayExerciseFragmentDoc}`;
 export const DisplayTrainingFragmentDoc = gql`
     fragment displayTraining on Training {
   id
@@ -3754,23 +3687,31 @@ export const DisplayTrainingFragmentDoc = gql`
     name
     description
   }
+  createdAt
   trainingDate
   location
   attendance
+  published
   blocks {
-    ...displayBlockInstance
+    ...blockInstanceWithoutBlock
     block {
-      ...displayBlock
+      ...blockWithoutBlocks
       blocks {
-        ...displayBlockInstance
+        ...blockInstanceWithoutBlock
         block {
-          ...displayBlock
+          ...blockWithoutBlocks
           blocks {
-            ...displayBlockInstance
+            ...blockInstanceWithoutBlock
             block {
-              ...displayBlock
+              ...blockWithoutBlocks
               blocks {
-                id
+                ...blockInstanceWithoutBlock
+                block {
+                  ...blockWithoutBlocks
+                  blocks {
+                    id
+                  }
+                }
               }
             }
           }
@@ -3782,22 +3723,11 @@ export const DisplayTrainingFragmentDoc = gql`
     id
   }
 }
-    ${DisplayBlockInstanceFragmentDoc}
-${DisplayBlockFragmentDoc}`;
-export const DisplayExerciseInstanceFragmentDoc = gql`
-    fragment displayExerciseInstance on ExerciseInstance {
-  id
-  order
-  repetitions
-  variation
-  exercise {
-    ...displayExercise
-  }
-}
-    ${DisplayExerciseFragmentDoc}`;
-export const TrainingDocument = gql`
-    query training($id: ID!) {
-  training(id: $id) {
+    ${BlockInstanceWithoutBlockFragmentDoc}
+${BlockWithoutBlocksFragmentDoc}`;
+export const PublishedTrainingsDocument = gql`
+    query publishedTrainings($where: TrainingWhereInput, $orderBy: TrainingOrderByInput, $skip: Int, $first: Int) {
+  publishedTrainings(where: $where, orderBy: $orderBy, skip: $skip, first: $first) {
     id
     title
     type {
@@ -3805,95 +3735,81 @@ export const TrainingDocument = gql`
       name
       description
     }
-    createdAt
     trainingDate
-    location
     attendance
-    published
-    blocks {
-      ...blockInstanceWithoutBlock
-      block {
-        ...blockWithoutBlocks
-        blocks {
-          ...blockInstanceWithoutBlock
-          block {
-            ...blockWithoutBlocks
-            blocks {
-              ...blockInstanceWithoutBlock
-              block {
-                ...blockWithoutBlocks
-              }
-            }
-          }
-        }
-      }
-    }
     registrations {
       id
-      name
+    }
+  }
+  count: trainingsCount(where: $where) {
+    aggregate {
+      count
     }
   }
 }
-    ${BlockInstanceWithoutBlockFragmentDoc}
-${BlockWithoutBlocksFragmentDoc}`;
+    `;
 
 /**
- * __useTrainingQuery__
+ * __usePublishedTrainingsQuery__
  *
- * To run a query within a React component, call `useTrainingQuery` and pass it any options that fit your needs.
- * When your component renders, `useTrainingQuery` returns an object from Apollo Client that contains loading, error, and data properties 
+ * To run a query within a React component, call `usePublishedTrainingsQuery` and pass it any options that fit your needs.
+ * When your component renders, `usePublishedTrainingsQuery` returns an object from Apollo Client that contains loading, error, and data properties 
  * you can use to render your UI.
  *
  * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
  *
  * @example
- * const { data, loading, error } = useTrainingQuery({
+ * const { data, loading, error } = usePublishedTrainingsQuery({
  *   variables: {
- *      id: // value for 'id'
+ *      where: // value for 'where'
+ *      orderBy: // value for 'orderBy'
+ *      skip: // value for 'skip'
+ *      first: // value for 'first'
  *   },
  * });
  */
-export function useTrainingQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<TrainingQuery, TrainingQueryVariables>) {
-        return ApolloReactHooks.useQuery<TrainingQuery, TrainingQueryVariables>(TrainingDocument, baseOptions);
+export function usePublishedTrainingsQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>) {
+        return ApolloReactHooks.useQuery<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>(PublishedTrainingsDocument, baseOptions);
       }
-export function useTrainingLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<TrainingQuery, TrainingQueryVariables>) {
-          return ApolloReactHooks.useLazyQuery<TrainingQuery, TrainingQueryVariables>(TrainingDocument, baseOptions);
+export function usePublishedTrainingsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>) {
+          return ApolloReactHooks.useLazyQuery<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>(PublishedTrainingsDocument, baseOptions);
         }
-export type TrainingQueryHookResult = ReturnType<typeof useTrainingQuery>;
-export type TrainingLazyQueryHookResult = ReturnType<typeof useTrainingLazyQuery>;
-export type TrainingQueryResult = ApolloReactCommon.QueryResult<TrainingQuery, TrainingQueryVariables>;
-export const PublishedTrainingsDocument = gql`
-    query publishedTrainings {
-  publishedTrainings {
+export type PublishedTrainingsQueryHookResult = ReturnType<typeof usePublishedTrainingsQuery>;
+export type PublishedTrainingsLazyQueryHookResult = ReturnType<typeof usePublishedTrainingsLazyQuery>;
+export type PublishedTrainingsQueryResult = ApolloReactCommon.QueryResult<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>;
+export const TrainingDocument = gql`
+    query training($id: ID) {
+  training(id: $id) {
     ...displayTraining
   }
 }
     ${DisplayTrainingFragmentDoc}`;
 
 /**
- * __usePublishedTrainingsQuery__
+ * __useTrainingQuery__
  *
- * To run a query within a React component, call `usePublishedTrainingsQuery` and pass it any options that fit your needs.
- * When your component renders, `usePublishedTrainingsQuery` returns an object from Apollo Client that contains loading, error, and data properties 
+ * To run a query within a React component, call `useTrainingQuery` and pass it any options that fit your needs.
+ * When your component renders, `useTrainingQuery` returns an object from Apollo Client that contains loading, error, and data properties 
  * you can use to render your UI.
  *
  * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
  *
  * @example
- * const { data, loading, error } = usePublishedTrainingsQuery({
+ * const { data, loading, error } = useTrainingQuery({
  *   variables: {
+ *      id: // value for 'id'
  *   },
  * });
  */
-export function usePublishedTrainingsQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>) {
-        return ApolloReactHooks.useQuery<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>(PublishedTrainingsDocument, baseOptions);
+export function useTrainingQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<TrainingQuery, TrainingQueryVariables>) {
+        return ApolloReactHooks.useQuery<TrainingQuery, TrainingQueryVariables>(TrainingDocument, baseOptions);
       }
-export function usePublishedTrainingsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>) {
-          return ApolloReactHooks.useLazyQuery<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>(PublishedTrainingsDocument, baseOptions);
+export function useTrainingLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<TrainingQuery, TrainingQueryVariables>) {
+          return ApolloReactHooks.useLazyQuery<TrainingQuery, TrainingQueryVariables>(TrainingDocument, baseOptions);
         }
-export type PublishedTrainingsQueryHookResult = ReturnType<typeof usePublishedTrainingsQuery>;
-export type PublishedTrainingsLazyQueryHookResult = ReturnType<typeof usePublishedTrainingsLazyQuery>;
-export type PublishedTrainingsQueryResult = ApolloReactCommon.QueryResult<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>;
+export type TrainingQueryHookResult = ReturnType<typeof useTrainingQuery>;
+export type TrainingLazyQueryHookResult = ReturnType<typeof useTrainingLazyQuery>;
+export type TrainingQueryResult = ApolloReactCommon.QueryResult<TrainingQuery, TrainingQueryVariables>;
 export const TrainingsDocument = gql`
     query trainings($where: TrainingWhereInput, $orderBy: TrainingOrderByInput, $skip: Int, $after: String, $before: String, $first: Int, $last: Int) {
   count: trainingsCount(where: $where) {
@@ -3902,43 +3818,10 @@ export const TrainingsDocument = gql`
     }
   }
   trainings(where: $where, orderBy: $orderBy, skip: $skip, after: $after, before: $before, first: $first, last: $last) {
-    id
-    title
-    type {
-      id
-      name
-      description
-    }
-    trainingDate
-    location
-    attendance
-    published
-    blocks {
-      ...blockInstanceWithoutBlock
-      block {
-        ...blockWithoutBlocks
-        blocks {
-          ...blockInstanceWithoutBlock
-          block {
-            ...blockWithoutBlocks
-            blocks {
-              ...blockInstanceWithoutBlock
-              block {
-                ...blockWithoutBlocks
-              }
-            }
-          }
-        }
-      }
-    }
-    registrations {
-      id
-      name
-    }
+    ...displayTraining
   }
 }
-    ${BlockInstanceWithoutBlockFragmentDoc}
-${BlockWithoutBlocksFragmentDoc}`;
+    ${DisplayTrainingFragmentDoc}`;
 
 /**
  * __useTrainingsQuery__
@@ -4047,6 +3930,12 @@ export const BlocksDocument = gql`
       ...blockInstanceWithoutBlock
       block {
         ...blockWithoutBlocks
+        blocks {
+          ...blockInstanceWithoutBlock
+          block {
+            ...blockWithoutBlocks
+          }
+        }
       }
     }
   }

+ 4 - 4
frontend/src/lib/apollo.js

@@ -17,7 +17,7 @@ import fetch from 'isomorphic-unfetch'
 
 const client = new ApolloClient({
   link: ApolloLink.from([
-    onError(errors => {
+    onError((errors) => {
       console.log(errors)
       if (errors && errors.response && errors.response.errors) {
         // errors.response.errors = null
@@ -26,10 +26,10 @@ const client = new ApolloClient({
     new HttpLink({
       uri: 'http://localhost:8801/graphql',
       credentials: 'include',
-      fetch
-    })
+      fetch,
+    }),
   ]),
-  cache: new InMemoryCache()
+  cache: new InMemoryCache(),
 })
 
 export default client

+ 42 - 0
frontend/src/training/components/RegistrationButton.tsx

@@ -0,0 +1,42 @@
+import { useRegisterMutation, useDeregisterMutation, User, TrainingDocument } from '../../gql'
+import { FunctionComponent, useContext } from 'react'
+import { UserContext } from '../../user/hooks'
+
+const RegistrationButton: FunctionComponent<{ registrations?: User[] }> = ({ registrations }) => {
+  const [register, registerData] = useRegisterMutation({
+    refetchQueries: [{ query: TrainingDocument }],
+    update: (cache, data) => {
+      console.log('salie', cache, data)
+    },
+  })
+  const [deregister, deregisterData] = useDeregisterMutation({
+    refetchQueries: [{ query: TrainingDocument }],
+    update: (cache, data) => {
+      console.log('salie', cache, data)
+    },
+  })
+  const { user } = useContext(UserContext)
+
+  const isRegistered =
+    registrations &&
+    user?.data?.currentUser.id &&
+    registrations.find((registeredUser) => registeredUser.id === user.data?.currentUser.id)
+  const action = isRegistered ? () => deregister() : () => register()
+  const label = isRegistered ? 'cancel' : 'register'
+
+  return (
+    <>
+      <button
+        type='button'
+        onClick={action}
+        disabled={registerData.loading || deregisterData.loading}
+      >
+        {label}
+      </button>
+      {registerData.error && registerData.error.message}
+      {deregisterData.error && deregisterData.error.message}
+    </>
+  )
+}
+
+export default RegistrationButton

+ 7 - 3
frontend/src/training/components/TrainingArchive.tsx

@@ -1,11 +1,12 @@
-import { useTrainingsQuery } from '../../gql'
+import { useTrainingsQuery, usePublishedTrainingsQuery } from '../../gql'
 import { useState } from 'react'
 import TrainingHint from './TrainingHint'
 import theme from '../../styles/theme'
 
 const TrainingArchive = () => {
-  const trainingsPerPage = 1
+  const trainingsPerPage = 5
   const [state, setState] = useState(0)
+  const archive = usePublishedTrainingsQuery()
   const { data, error, loading } = useTrainingsQuery({
     variables: { skip: state * trainingsPerPage, first: trainingsPerPage },
   })
@@ -42,11 +43,14 @@ const TrainingArchive = () => {
           border: none;
           padding: 0.3em 0.6em;
           margin: 0 0.3em;
-          background-color: none;
+          background-color: transparent;
           color: ${theme.colors.darkblue};
           border-radius: 6px;
           cursor: pointer;
         }
+        button:hover {
+          background-color: ${theme.colors.darkblue}22;
+        }
         button.active {
           background-color: ${theme.colors.darkblue};
           color: ${theme.colors.offWhite};

+ 108 - 184
frontend/src/training/training.graphql

@@ -1,48 +1,13 @@
 # import * from '../../../backend/database/generated/prisma.graphql'
 
-fragment exerciseContent on Exercise {
-  id
-  name
-  description
-  videos
-  pictures
-  targets
-  baseExercise
-}
-
-fragment blockWithoutBlocks on Block {
-  id
-  title
-  description
-  videos
-  pictures
-  duration
-  format {
-    id
-    name
-    description
-  }
-  rest
-  exercises {
-    id
-    exercise {
-      ...exerciseContent
-    }
-    order
-    repetitions
-    variation
-  }
-}
-
-fragment blockInstanceWithoutBlock on BlockInstance {
-  id
-  order
-  rounds
-  variation
-}
-
-query training($id: ID!) {
-  training(id: $id) {
+# Only some basic data to be able to display the training
+query publishedTrainings(
+  $where: TrainingWhereInput
+  $orderBy: TrainingOrderByInput
+  $skip: Int
+  $first: Int
+) {
+  publishedTrainings(where: $where, orderBy: $orderBy, skip: $skip, first: $first) {
     id
     title
     type {
@@ -50,128 +15,27 @@ query training($id: ID!) {
       name
       description
     }
-    createdAt
     trainingDate
-    location
     attendance
-    published
-    blocks {
-      ...blockInstanceWithoutBlock
-      block {
-        ...blockWithoutBlocks
-        blocks {
-          ...blockInstanceWithoutBlock
-          block {
-            ...blockWithoutBlocks
-            blocks {
-              ...blockInstanceWithoutBlock
-              block {
-                ...blockWithoutBlocks
-              }
-            }
-          }
-        }
-      }
-    }
     registrations {
       id
-      name
-    }
-  }
-}
-
-fragment displayTraining on Training {
-  id
-  title
-  type {
-    id
-    name
-    description
-  }
-  trainingDate
-  location
-  attendance
-  blocks {
-    ...displayBlockInstance
-    block {
-      ...displayBlock
-      blocks {
-        ...displayBlockInstance
-        block {
-          ...displayBlock
-          blocks {
-            ...displayBlockInstance
-            block {
-              ...displayBlock
-              blocks {
-                id
-              }
-            }
-          }
-        }
-      }
     }
   }
-  registrations {
-    id
-  }
-}
-
-fragment displayBlockInstance on BlockInstance {
-  id
-  order
-  rounds
-  variation
-}
-
-fragment displayBlock on Block {
-  id
-  title
-  description
-  videos
-  pictures
-  duration
-  format {
-    name
-    description
-  }
-  rest
-  exercises {
-    order
-    repetitions
-    variation
-    exercise {
-      ...displayExercise
+  count: trainingsCount(where: $where) {
+    aggregate {
+      count
     }
   }
 }
 
-fragment displayExerciseInstance on ExerciseInstance {
-  id
-  order
-  repetitions
-  variation
-  exercise {
-    ...displayExercise
-  }
-}
-
-fragment displayExercise on Exercise {
-  id
-  name
-  description
-  videos
-  pictures
-  targets
-  baseExercise
-}
-
-query publishedTrainings {
-  publishedTrainings {
+# The full data set, single item.
+query training($id: ID) {
+  training(id: $id) {
     ...displayTraining
   }
 }
 
+# The full data set.
 query trainings(
   $where: TrainingWhereInput
   $orderBy: TrainingOrderByInput
@@ -195,39 +59,7 @@ query trainings(
     first: $first
     last: $last
   ) {
-    id
-    title
-    type {
-      id
-      name
-      description
-    }
-    trainingDate
-    location
-    attendance
-    published
-    blocks {
-      ...blockInstanceWithoutBlock
-      block {
-        ...blockWithoutBlocks
-        blocks {
-          ...blockInstanceWithoutBlock
-          block {
-            ...blockWithoutBlocks
-            blocks {
-              ...blockInstanceWithoutBlock
-              block {
-                ...blockWithoutBlocks
-              }
-            }
-          }
-        }
-      }
-    }
-    registrations {
-      id
-      name
-    }
+    ...displayTraining
   }
 }
 
@@ -254,6 +86,12 @@ query blocks {
       ...blockInstanceWithoutBlock
       block {
         ...blockWithoutBlocks
+        blocks {
+          ...blockInstanceWithoutBlock
+          block {
+            ...blockWithoutBlocks
+          }
+        }
       }
     }
   }
@@ -316,3 +154,89 @@ mutation deregister($training: ID!) {
 mutation publish($training: ID!, $status: Boolean) {
   publish(training: $training, status: $status)
 }
+
+fragment exerciseContent on Exercise {
+  id
+  name
+  description
+  videos
+  pictures
+  targets
+  baseExercise
+}
+
+fragment blockWithoutBlocks on Block {
+  id
+  title
+  description
+  videos
+  pictures
+  duration
+  format {
+    id
+    name
+    description
+  }
+  rest
+  exercises {
+    id
+    exercise {
+      ...exerciseContent
+    }
+    order
+    repetitions
+    variation
+  }
+}
+
+fragment blockInstanceWithoutBlock on BlockInstance {
+  id
+  order
+  rounds
+  variation
+}
+
+fragment displayTraining on Training {
+  id
+  title
+  type {
+    id
+    name
+    description
+  }
+  createdAt
+  trainingDate
+  location
+  attendance
+  published
+  blocks {
+    ...blockInstanceWithoutBlock
+    block {
+      ...blockWithoutBlocks
+      blocks {
+        ...blockInstanceWithoutBlock
+        block {
+          ...blockWithoutBlocks
+          blocks {
+            ...blockInstanceWithoutBlock
+            block {
+              ...blockWithoutBlocks
+              blocks {
+                ...blockInstanceWithoutBlock
+                block {
+                  ...blockWithoutBlocks
+                  blocks {
+                    id
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  registrations {
+    id
+  }
+}

+ 9 - 3
frontend/src/user/hooks.tsx

@@ -5,10 +5,12 @@ import {
   useUserLoginMutation,
   CurrentUserDocument,
   TrainingsDocument,
+  CurrentUserQuery,
 } from '../gql'
+import { ApolloError } from '@apollo/client'
 
 interface IUserContext {
-  user?: ReturnType<typeof useCurrentUserQuery>
+  user?: { data: CurrentUserQuery | undefined; error: ApolloError | undefined; loading: boolean }
   login?: ReturnType<typeof useUserLoginMutation>
   logout?: ReturnType<typeof useUserLogoutMutation>
 }
@@ -16,12 +18,16 @@ interface IUserContext {
 export const UserContext = createContext<IUserContext>({})
 
 export const UserProvider: FunctionComponent = ({ children }) => {
-  const user = useCurrentUserQuery({ fetchPolicy: 'network-only' })
+  const { data, error, loading } = useCurrentUserQuery()
   const logout = useUserLogoutMutation({
     refetchQueries: [{ query: CurrentUserDocument }, { query: TrainingsDocument }],
   })
   const login = useUserLoginMutation({
     refetchQueries: [{ query: CurrentUserDocument }, { query: TrainingsDocument }],
   })
-  return <UserContext.Provider value={{ user, login, logout }}>{children}</UserContext.Provider>
+  return (
+    <UserContext.Provider value={{ user: { data, error, loading }, login, logout }}>
+      {children}
+    </UserContext.Provider>
+  )
 }