|
@@ -0,0 +1,127 @@
|
|
|
+import { useTrainingTypesQuery, TrainingType } from '../../gql'
|
|
|
+import AddTrainingType from './AddTrainingType'
|
|
|
+import { useState, useEffect } from 'react'
|
|
|
+import { Modal } from '../../modal'
|
|
|
+import Dropdown from '../../dropdown/components/Dropdown'
|
|
|
+import { QueryHookOptions, QueryResult } from '@apollo/client'
|
|
|
+import { TextInput } from '../../form'
|
|
|
+
|
|
|
+interface ISelector<TQueryData, TQueryVariables> {
|
|
|
+ name: string
|
|
|
+ value: any
|
|
|
+ onChange: GenericEventHandler
|
|
|
+ callback: (selectedIndex: number) => void
|
|
|
+ query: (
|
|
|
+ baseOptions?: QueryHookOptions<TQueryData, { where: { OR: { [key: string]: string }[] } }>
|
|
|
+ ) => QueryResult<TQueryData, TQueryVariables>
|
|
|
+ searchKeys?: (keyof TQueryData)[]
|
|
|
+ dataKey: keyof TQueryData
|
|
|
+ selectedKey: keyof TQueryData
|
|
|
+ className?: string
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * The selector allows to select an item from a list and offers tools to add, edit or remove items.
|
|
|
+ * @param param0
|
|
|
+ */
|
|
|
+const Selector = <
|
|
|
+ TQueryData extends { [dataKey: string]: any[] },
|
|
|
+ TQueryVariables extends Record<string, any>
|
|
|
+>({
|
|
|
+ name,
|
|
|
+ value,
|
|
|
+ onChange,
|
|
|
+ query,
|
|
|
+ searchKeys,
|
|
|
+ dataKey,
|
|
|
+ className,
|
|
|
+}: ISelector<TQueryData, TQueryVariables>) => {
|
|
|
+ const [searchTerm, setSearchTerm] = useState('')
|
|
|
+ const searchVariables =
|
|
|
+ searchKeys && searchTerm !== ''
|
|
|
+ ? { variables: { where: { OR: searchKeys?.map((key) => ({ [key]: searchTerm })) } } }
|
|
|
+ : {}
|
|
|
+ const { data, error, loading } = query(searchVariables)
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ setTimeout(() => console.log('debouonced.'), 300)
|
|
|
+ }, [searchTerm])
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className={className}>
|
|
|
+ <TextInput
|
|
|
+ name='search'
|
|
|
+ type='search'
|
|
|
+ value={searchTerm}
|
|
|
+ onChange={(event) => setSearchTerm(event.target.vale)}
|
|
|
+ />
|
|
|
+ <select
|
|
|
+ id={name}
|
|
|
+ name={name}
|
|
|
+ value={value}
|
|
|
+ onChange={(event) => {
|
|
|
+ const changeEvent: CustomChangeEvent = {
|
|
|
+ target: {
|
|
|
+ type: 'custom',
|
|
|
+ value: { id: event.target.value },
|
|
|
+ name,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ onChange(changeEvent)
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {loading && 'loading training types...'}
|
|
|
+ {error && 'error loading training types'}
|
|
|
+ {data &&
|
|
|
+ data[dataKey].map((item) => (
|
|
|
+ <option key={item.id} value={item.id}>
|
|
|
+ {item.name}
|
|
|
+ </option>
|
|
|
+ ))}
|
|
|
+ </select>
|
|
|
+ <button
|
|
|
+ type='button'
|
|
|
+ onClick={(event) => {
|
|
|
+ setModalState(true)
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ Add type
|
|
|
+ </button>
|
|
|
+ <Modal state={[modalState, setModalState]}>
|
|
|
+ <AddTrainingType
|
|
|
+ onSuccess={(result) => {
|
|
|
+ setModalState(false)
|
|
|
+ if (result.data) {
|
|
|
+ onChange({
|
|
|
+ target: {
|
|
|
+ type: 'custom',
|
|
|
+ value: { id: result.data.createTrainingType.id },
|
|
|
+ name,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </Modal>
|
|
|
+
|
|
|
+ <style jsx>{`
|
|
|
+ div {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ label,
|
|
|
+ select,
|
|
|
+ button {
|
|
|
+ display: inline-block;
|
|
|
+ width: auto;
|
|
|
+ }
|
|
|
+ select {
|
|
|
+ flex-grow: 1;
|
|
|
+ margin: 0 0.6em;
|
|
|
+ }
|
|
|
+ `}</style>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+export default Selector
|