1+ import { useAllLinkTypes } from '../../hooks/projects.hooks' ;
2+ import LoadingIndicator from '../LoadingIndicator' ;
3+ import ErrorPage from '../../pages/ErrorPage' ;
4+ import { IconButton , MenuItem , Select , TextField } from '@mui/material' ;
5+ import { FieldArrayWithId , UseFieldArrayAppend , UseFieldArrayRemove , UseFormRegister , UseFormWatch } from 'react-hook-form' ;
6+ import DeleteIcon from '@mui/icons-material/Delete' ;
7+ import { getRequiredLinkTypeNames } from '../../utils/link.utils' ;
8+ import { ProjectFormInput } from '../../pages/ProjectDetailPage/ProjectForm/ProjectForm' ;
9+ import { Box } from '@mui/system' ;
10+ import { NERButton } from '../NERButton' ;
11+
12+ const LinksEditView : React . FC < {
13+ ls : FieldArrayWithId [ ] ;
14+ register : UseFormRegister < ProjectFormInput > ;
15+ watch : UseFormWatch < ProjectFormInput > ;
16+ append : UseFieldArrayAppend < any , any > ;
17+ remove : UseFieldArrayRemove ;
18+ } > = ( { ls, register, append, remove, watch } ) => {
19+ const { isLoading, isError, error, data : linkTypes } = useAllLinkTypes ( ) ;
20+ if ( isLoading || ! linkTypes ) return < LoadingIndicator /> ;
21+ if ( isError ) return < ErrorPage message = { error . message } /> ;
22+
23+ const requiredLinkTypeNames = getRequiredLinkTypeNames ( linkTypes ) ;
24+
25+ const links = watch ( 'links' ) ;
26+
27+ const currentLinkTypeNames = links . map ( ( link ) => link . linkTypeName ) ;
28+
29+ /* Checks whether the link at the given index is of a required type and does not already exist */
30+ const isRequired = ( index : number ) => {
31+ const link = watch ( `links.${ index } ` ) ;
32+ const { linkTypeName } = link ;
33+ return (
34+ requiredLinkTypeNames . includes ( linkTypeName ) &&
35+ ! currentLinkTypeNames . includes ( linkTypeName , currentLinkTypeNames . indexOf ( linkTypeName ) + 1 )
36+ ) ;
37+ } ;
38+
39+ const availableOptions = linkTypes . filter ( ( linkType ) => ! currentLinkTypeNames . includes ( linkType . name ) ) ;
40+
41+ return (
42+ < >
43+ { ls . map ( ( _element , i ) => {
44+ return (
45+ < Box sx = { { display : 'flex' , alignItems : 'center' , mb : '5px' } } >
46+ < Select
47+ { ...register ( `links.${ i } .linkTypeName` , { required : true } ) }
48+ sx = { { minWidth : '200px' , mr : '5px' } }
49+ disabled = { isRequired ( i ) }
50+ value = { watch ( `links.${ i } .linkTypeName` ) }
51+ >
52+ { linkTypes . map ( ( linkType ) => (
53+ < MenuItem key = { linkType . name } value = { linkType . name } disabled = { ! availableOptions . includes ( linkType ) } >
54+ { linkType . name }
55+ </ MenuItem >
56+ ) ) }
57+ </ Select >
58+ < TextField required fullWidth autoComplete = "off" { ...register ( `links.${ i } .url` , { required : true } ) } />
59+ < Box sx = { { minWidth : '56px' , height : '40px' } } >
60+ { ! isRequired ( i ) && (
61+ < IconButton type = "button" onClick = { ( ) => remove ( i ) } sx = { { mx : 1 , my : 0 } } >
62+ < DeleteIcon />
63+ </ IconButton >
64+ ) }
65+ </ Box >
66+ </ Box >
67+ ) ;
68+ } ) }
69+ { availableOptions . length > 0 && (
70+ < NERButton
71+ variant = "contained"
72+ color = "primary"
73+ onClick = { ( ) => append ( { linkId : '-1' , url : '' , linkTypeName : '-1' } ) }
74+ sx = { { my : 2 , width : 'max-content' } }
75+ >
76+ + Add New Link
77+ </ NERButton >
78+ ) }
79+ </ >
80+ ) ;
81+ } ;
82+
83+ export default LinksEditView ;
0 commit comments