Tomi Cvetic 5 年之前
父节点
当前提交
932948bb5b

+ 0 - 2
frontend/pages/index.tsx

@@ -4,8 +4,6 @@ import initialData from '../initial-data'
 import { useTrainingsQuery } from '../src/gql'
 import { Training } from '../src/training'
 
-console.log(initialData)
-
 const Home = () => {
   //const { data, error, loading } = useTrainingsQuery();
 

+ 0 - 1
frontend/src/training/components/AddTrainingType.tsx

@@ -29,7 +29,6 @@ const AddTrainingType = ({
   return (
     <form
       onSubmit={async event => {
-        console.log(event)
         event.preventDefault()
         event.stopPropagation()
         const result = await createTrainingType({

+ 30 - 5
frontend/src/training/components/BlockInputs.tsx

@@ -1,15 +1,16 @@
 import { BlockContentFragment } from '../../gql'
 import FormatSelector from './FormatSelector'
 import { TextInput } from '../../form'
+import BlockInstanceInputs from './BlockInstanceInputs'
+import { emptyBlockInstance } from '../utils'
 
 interface IBlockInputs {
   onChange: GenericEventHandler
-  value: BlockContentFragment
+  value?: Partial<BlockContentFragment>
   name: string
 }
 
 const BlockInputs = ({ onChange, value, name }: IBlockInputs) => {
-  console.log('blockinput', name, value)
   return (
     <fieldset>
       <TextInput
@@ -26,23 +27,47 @@ const BlockInputs = ({ onChange, value, name }: IBlockInputs) => {
       <TextInput
         name={`${name}.description`}
         label='Description'
-        value={value.description}
+        value={value.description || ''}
         onChange={onChange}
       />
       <TextInput
         name={`${name}.duration`}
         label='Duration'
-        value={value.duration}
+        value={value.duration || ''}
         type='number'
         onChange={onChange}
       />
       <TextInput
         name={`${name}.rest`}
         label='Rest'
-        value={value.rest}
+        value={value.rest || ''}
         type='number'
         onChange={onChange}
       />
+      <label>Blocks</label>
+      {value.blocks && (
+        <BlockInstanceInputs
+          name={`${name}.blocks`}
+          value={value.blocks}
+          onChange={onChange}
+        />
+      )}
+      <button
+        onClick={event => {
+          event.preventDefault()
+          const newBlock = emptyBlockInstance()
+          onChange({
+            target: {
+              type: 'custom',
+              name: 'blocks',
+              value: value.blocks ? [...value.blocks, newBlock] : [newBlock]
+            }
+          })
+        }}
+        type='button'
+      >
+        Add block
+      </button>
     </fieldset>
   )
 }

+ 3 - 5
frontend/src/training/components/BlockInstanceInputs.tsx

@@ -10,11 +10,10 @@ const BlockInstanceInputs = ({
   onChange
 }: {
   name: string
-  value: SubBlockFragment[]
+  value?: Partial<SubBlockFragment>[]
   onChange: GenericEventHandler
 }) => {
   const [state, setState] = useState(value.map((item, index) => index))
-  console.log(name, value)
 
   function onSortEnd({
     oldIndex,
@@ -37,11 +36,10 @@ const BlockInstanceInputs = ({
 
   const items = state.map((order, index) => {
     const item = value[order]
-    console.log({ value, order, item })
     return (
       <BlockInputs
-        key={item.order}
-        name={`${name}.${index}.block`}
+        key={item.id}
+        name={`${name}.${order}.block`}
         value={item.block}
         onChange={onChange}
       />

+ 0 - 1
frontend/src/training/components/EditBlock.tsx

@@ -9,7 +9,6 @@ interface IBlockFormInputs {
 }
 
 const BlockFormInputs = ({ onChange, value, name }: IBlockFormInputs) => {
-  console.log({ value })
   return (
     <fieldset>
       <TextInput

+ 18 - 0
frontend/src/training/components/EditSubBlocks.tsx

@@ -0,0 +1,18 @@
+import { useState } from 'react'
+import { SortableList } from '../../sortable'
+
+const EditSubBlocks = ({
+  name,
+  value,
+  onChange
+}: {
+  name: string
+  value: any
+  onChange: GenericEventHandler
+}) => {
+  const [state, setState] = useState([1, 2, 3])
+
+  return <SortableList items={state} useDragHandle lockAxis={'y'} />
+}
+
+export default EditSubBlocks

+ 65 - 6
frontend/src/training/components/EditTraining.tsx

@@ -1,17 +1,17 @@
 import { useEffect } from 'react'
 import { useTrainingQuery, useCreateTrainingMutation } from '../../gql'
-import { useForm } from '../../form'
-import { emptyTraining } from '../constants'
-import TrainingInputs from './TrainingInputs'
+import { useForm, TextInput, DateTimeInput, Checkbox } from '../../form'
+import { emptyTraining, emptyBlockInstance } from '../utils'
+import TrainingTypeSelector from './TrainingTypeSelector'
+import BlockInstanceInputs from './BlockInstanceInputs'
 
 const EditTraining = ({ id = '' }: { id?: string }) => {
   const trainingData = useTrainingQuery({ variables: { id } })
 
-  const { values, touched, onChange, loadData } = useForm(emptyTraining)
+  const { values, touched, onChange, loadData } = useForm(emptyTraining())
   const [createTraining, createData] = useCreateTrainingMutation()
 
   useEffect(() => {
-    console.log('training effect', trainingData)
     if (trainingData.data?.training) loadData(trainingData.data.training)
   }, [trainingData.data])
 
@@ -23,7 +23,66 @@ const EditTraining = ({ id = '' }: { id?: string }) => {
           //createTraining({ variables: values })
         }}
       >
-        <TrainingInputs name='test' values={values} onChange={onChange} />
+        <TextInput
+          name='title'
+          label='Title'
+          value={values.title}
+          onChange={onChange}
+        />
+        <TrainingTypeSelector
+          name='type'
+          value={values.type}
+          onChange={onChange}
+        />
+        <DateTimeInput
+          name='trainingDate'
+          label='Training date'
+          value={values.trainingDate}
+          onChange={onChange}
+        />
+        <TextInput
+          name='location'
+          label='Location'
+          value={values.location}
+          onChange={onChange}
+        />
+        <TextInput
+          name='attendance'
+          label='Attendance'
+          type='number'
+          value={values.attendance}
+          onChange={onChange}
+        />
+        <Checkbox
+          name='published'
+          label='Published'
+          value={values.published}
+          onChange={onChange}
+        />
+        <label>Blocks</label>
+        {values.blocks && (
+          <BlockInstanceInputs
+            name='blocks'
+            value={values.blocks}
+            onChange={onChange}
+          />
+        )}
+        <button
+          onClick={event => {
+            event.preventDefault()
+            const newBlock = emptyBlockInstance()
+            onChange({
+              target: {
+                type: 'custom',
+                name: 'blocks',
+                value: values.blocks ? [...values.blocks, newBlock] : [newBlock]
+              }
+            })
+          }}
+          type='button'
+        >
+          Add block
+        </button>
         <button type='submit' disabled={createData.loading}>
           Save
         </button>

+ 0 - 1
frontend/src/training/components/FormatSelector.tsx

@@ -19,7 +19,6 @@ const FormatSelector = ({
 
   useEffect(() => {
     if (formats.data && formats.data.formats.length > 0 && !id) {
-      console.log('format:', name)
       onChange({
         target: {
           type: 'custom',

+ 8 - 7
frontend/src/training/components/TrainingInputs.tsx

@@ -2,7 +2,7 @@ import { TextInput, DateTimeInput, Checkbox } from '../../form'
 import TrainingTypeSelector from './TrainingTypeSelector'
 import BlockInstanceInputs from './BlockInstanceInputs'
 import { TrainingQuery } from '../../gql'
-import { emptyBlockInstance } from '../constants'
+import { emptyBlockInstance } from '../utils'
 
 const TrainingInputs = ({
   values,
@@ -63,16 +63,17 @@ const TrainingInputs = ({
         onClick={event => {
           event.preventDefault()
           console.log('add')
+          const newBlock = emptyBlockInstance({
+            id: `__${Math.random()
+              .toString(36)
+              .replace(/[^a-zA-Z0-9]+/g, '')
+              .substr(0, 11)}`
+          })
           onChange({
             target: {
               type: 'custom',
               name: 'blocks',
-              value: values.blocks
-                ? [
-                    ...values.blocks,
-                    { ...emptyBlockInstance, order: values.blocks.length - 1 }
-                  ]
-                : [{ ...emptyBlockInstance, order: 0 }]
+              value: values.blocks ? [...values.blocks, newBlock] : [newBlock]
             }
           })
         }}

+ 0 - 1
frontend/src/training/components/TrainingTypeSelector.tsx

@@ -22,7 +22,6 @@ const TrainingTypeSelector = ({
 
   useEffect(() => {
     if (trainingTypes.data && trainingTypes.data.trainingTypes.length > 0) {
-      console.log('tt:', name)
       onChange({
         target: {
           type: 'custom',

+ 0 - 30
frontend/src/training/constants.ts

@@ -1,30 +0,0 @@
-import { nextTime } from './utils'
-import { SubBlockFragment, TrainingQuery, BlockContentFragment } from '../gql'
-
-export const emptyBlock: BlockContentFragment = {
-  id: '',
-  title: '',
-  format: { id: '', name: '', description: '' },
-  videos: [],
-  pictures: [],
-  blocks: [],
-  exercises: []
-}
-
-export const emptyBlockInstance: SubBlockFragment = {
-  id: '',
-  order: 0,
-  block: emptyBlock
-}
-
-export const emptyTraining: NonNullable<TrainingQuery['training']> = {
-  id: '',
-  createdAt: '',
-  title: '',
-  location: '',
-  attendance: 0,
-  trainingDate: nextTime('Tuesday', '11:45'),
-  type: { id: '', name: '', description: '' },
-  blocks: [] as SubBlockFragment[],
-  published: false
-}

+ 47 - 1
frontend/src/training/utils.ts

@@ -1,6 +1,6 @@
 import { parse } from 'date-fns'
 import { IBlock, IExercise, IRating } from './types'
-import { TrainingQuery, SubBlockFragment } from '../gql'
+import { TrainingQuery, SubBlockFragment, BlockContentFragment } from '../gql'
 
 /**
  * Takes a block of exercises and calculates the duration in seconds.
@@ -99,3 +99,49 @@ export function nextTime(weekDay: TWeekdays, time: string) {
   )
   return nextTime.toISOString()
 }
+
+function randomID() {
+  return `__${Math.random()
+    .toString(36)
+    .replace(/[^a-zA-Z0-9]+/g, '')
+    .substr(0, 11)}`
+}
+
+export function emptyBlock(input?: Partial<BlockContentFragment>) {
+  const emptyBlock: BlockContentFragment = {
+    id: randomID(),
+    title: '',
+    format: { id: '', name: '', description: '' },
+    videos: [],
+    pictures: [],
+    blocks: [],
+    exercises: []
+  }
+  return { ...emptyBlock, ...input }
+}
+
+export function emptyBlockInstance(input?: Partial<SubBlockFragment>) {
+  const emptyBlockInstance: SubBlockFragment = {
+    id: randomID(),
+    order: 0,
+    block: emptyBlock()
+  }
+  return { ...emptyBlockInstance, ...input }
+}
+
+export function emptyTraining(
+  input?: Partial<NonNullable<TrainingQuery['training']>>
+) {
+  const emptyTraining: NonNullable<TrainingQuery['training']> = {
+    id: randomID(),
+    createdAt: '',
+    title: '',
+    location: '',
+    attendance: 0,
+    trainingDate: nextTime('Tuesday', '11:45'),
+    type: { id: '', name: '', description: '' },
+    blocks: [] as SubBlockFragment[],
+    published: false
+  }
+  return { ...emptyTraining, ...input }
+}