ExerciseInstanceInputs.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import { useState, useEffect } from 'react'
  2. import arrayMove from 'array-move'
  3. import ExerciseInputs from './ExerciseInputs'
  4. import { SortableList } from '../../sortable'
  5. import { TextInput } from '../../form'
  6. import { TExerciseInstance } from '../types'
  7. const ExerciseInstanceInputs = ({
  8. value = [],
  9. name,
  10. onChange
  11. }: {
  12. value?: TExerciseInstance[]
  13. name: string
  14. onChange: GenericEventHandler
  15. }) => {
  16. const [state, setState] = useState(value.map(item => item.id))
  17. function updateOrderProperty<T extends { id: U }, U>(
  18. values: T[],
  19. orderList: U[]
  20. ) {
  21. const orderedValues = values.map(value => {
  22. const order = orderList.findIndex(orderedId => orderedId === value.id)
  23. return { ...value, order }
  24. })
  25. onChange({ target: { type: 'custom', name, value: orderedValues } })
  26. }
  27. function onSortEnd({
  28. oldIndex,
  29. newIndex
  30. }: {
  31. oldIndex: number
  32. newIndex: number
  33. }) {
  34. const newOrder = arrayMove(state, oldIndex, newIndex)
  35. setState(newOrder)
  36. updateOrderProperty(value, newOrder)
  37. }
  38. useEffect(() => {
  39. const missingIds = value
  40. .filter(item => !state.includes(item.id))
  41. .filter(item => !item.id.startsWith('--'))
  42. .map(item => item.id)
  43. const stateWithoutRemovedItems = state.filter(stateId =>
  44. value.find(item => stateId === item.id)
  45. )
  46. setState([...stateWithoutRemovedItems, ...missingIds])
  47. }, [value])
  48. const items = state
  49. .map(stateId => {
  50. const itemIndex = value.findIndex(item => item.id === stateId)
  51. if (itemIndex < 0) return null
  52. const item = value[itemIndex]
  53. return (
  54. <div key={item.id}>
  55. <p>{item.id}</p>
  56. <TextInput
  57. name={`${name}.${itemIndex}.order`}
  58. label='Order'
  59. value={item.order}
  60. type='number'
  61. onChange={onChange}
  62. />
  63. <TextInput
  64. name={`${name}.${itemIndex}.repetitions`}
  65. label='Repetitions'
  66. value={item.repetitions}
  67. type='number'
  68. onChange={onChange}
  69. />
  70. <TextInput
  71. name={`${name}.${itemIndex}.variation`}
  72. label='Variation'
  73. value={item.variation}
  74. onChange={onChange}
  75. />
  76. {item.exercise && (
  77. <ExerciseInputs
  78. name={`${name}.${itemIndex}.block`}
  79. value={item.exercise}
  80. onChange={onChange}
  81. />
  82. )}
  83. <button
  84. type='button'
  85. onClick={ev => {
  86. const newOrder = state.filter(orderedId => item.id !== orderedId)
  87. setState(newOrder)
  88. const newValues = item.id?.startsWith('++')
  89. ? [...value.slice(0, itemIndex), ...value.slice(itemIndex + 1)]
  90. : [
  91. ...value.slice(0, itemIndex),
  92. { ...item, id: `--${item.id}` },
  93. ...value.slice(itemIndex + 1)
  94. ]
  95. updateOrderProperty(newValues, newOrder)
  96. }}
  97. >
  98. Delete block
  99. </button>
  100. </div>
  101. )
  102. })
  103. .filter(block => block !== null)
  104. return (
  105. <SortableList
  106. items={items}
  107. onSortEnd={onSortEnd}
  108. useDragHandle
  109. lockAxis={'y'}
  110. />
  111. )
  112. }
  113. export default ExerciseInstanceInputs