@@ -2,56 +2,136 @@ import '../styles/Metadata.css';
22import '../styles/Type.css' ;
33
44import { TagFill } from 'react-bootstrap-icons' ;
5- import { useState , useContext } from 'react' ;
6- import { ListGroup , OverlayTrigger , Tooltip } from 'react-bootstrap' ;
5+ import { useState , useEffect , useContext , useCallback } from 'react' ;
6+ import { ListGroup , Form , InputGroup , Button } from 'react-bootstrap' ;
77import { TypesContext } from './TypesContext.js' ;
8+ import { v4 as uuidv4 } from 'uuid' ;
89
910export function TypeBadge ( { type, addClassName } ) {
1011 const types = useContext ( TypesContext ) ;
1112 if ( ! type ) return null ;
1213 const typeSelected = types . find ( ( t ) => t . id === type ) ;
13- if ( ! typeSelected ) return ;
14- return < div style = { { backgroundColor : typeSelected . doc . color } } className = { `typeBadge ${ addClassName ?? '' } ` } >
15- { typeSelected . doc . type_name }
16- </ div > ;
14+ if ( ! typeSelected || ! typeSelected . doc ) return null ;
15+
16+ return (
17+ < span
18+ className = { `typeBadge ${ addClassName ?? '' } ` }
19+ style = { { backgroundColor : typeSelected . doc . color } }
20+ >
21+ { typeSelected . doc . type_name }
22+ </ span >
23+ ) ;
1724}
1825
19- function TypeList ( { typeSelected, handleUpdate } ) {
20- const types = useContext ( TypesContext ) ;
26+ function TypeList ( { typeSelected, handleUpdate, addNewType , backend } ) {
27+ const [ types , setTypes ] = useState ( [ ] ) ;
2128 const [ searchTerm , setSearchTerm ] = useState ( '' ) ;
29+ const [ newType , setNewType ] = useState ( '' ) ;
30+ const [ newColor , setNewColor ] = useState ( '#FF5733' ) ;
31+
32+ const fetchTypes = useCallback ( async ( ) => {
33+ try {
34+ const response = await backend . getView ( { view : 'types' , options : [ 'include_docs' ] } ) ;
35+ setTypes ( response ) ;
36+ console . log ( 'Types récupérés:' , response ) ;
37+ } catch ( error ) {
38+ console . error ( 'Erreur lors de la récupération des types:' , error ) ;
39+ }
40+ } , [ backend ] ) ;
41+
42+ useEffect ( ( ) => {
43+ fetchTypes ( ) ;
44+ } , [ fetchTypes ] ) ;
2245
23- const filteredTypes = types . filter ( type =>
24- type . doc . type_name . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) )
46+ const handleAddNewType = ( ) => {
47+ if ( newType . trim ( ) ) {
48+ addNewType ( newType , newColor )
49+ . then ( ( ) => {
50+ window . location . reload ( ) ;
51+ } )
52+ . catch ( ( error ) => {
53+ console . error ( 'Erreur lors de l\'ajout du type:' , error ) ;
54+ } ) ;
55+
56+ setNewType ( '' ) ;
57+ setNewColor ( '#FF5733' ) ;
58+ }
59+ } ;
60+
61+ const filteredTypes = types . filter (
62+ ( type ) =>
63+ type . doc &&
64+ type . doc . type_name &&
65+ type . doc . type_name . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) )
2566 ) ;
67+
2668 return (
2769 < >
28- < h6 style = { { textAlign : 'left' } } > Select a type</ h6 >
29- < input
70+ < h6 style = { { textAlign : 'left' , marginBottom : '15px' } } > Select a type</ h6 >
71+ < Form . Control
3072 type = "text"
3173 id = "searchType"
3274 placeholder = "Filter types..."
3375 value = { searchTerm }
3476 onChange = { ( e ) => setSearchTerm ( e . target . value ) }
35- style = { { marginBottom : '10px ' , width : '100% ' , padding : '5px ' } }
77+ style = { { marginBottom : '15px ' , padding : '10px ' , borderRadius : '8px ' } }
3678 />
79+
3780 < ListGroup style = { { textAlign : 'center' , paddingTop : 0 , paddingBottom : 20 } } >
3881 { filteredTypes . map ( ( type , index ) =>
3982 < ListGroup . Item action
4083 key = { index }
41- style = { { backgroundColor : type === typeSelected ? 'grey' : '' } }
42- onClick = { ( ) => handleUpdate ( type . id ) } >
43- < TypeBadge type = { type . id } />
84+ onClick = { ( ) => handleUpdate ( type . id ) }
85+ className = "typeContainer"
86+ style = { { cursor : 'pointer' } }
87+ >
88+ < TypeBadge type = { type . id } />
4489 </ ListGroup . Item >
4590 ) }
46- { typeSelected ?
91+ { typeSelected && (
4792 < ListGroup . Item action
48- key = { 'remove type' }
49- style = { { color : 'red' } }
50- onClick = { ( ) => handleUpdate ( '' ) } >
93+ key = "remove-type"
94+ onClick = { ( ) => handleUpdate ( '' ) }
95+ style = { {
96+ color : 'red' ,
97+ cursor : 'pointer' ,
98+ marginTop : '10px' ,
99+ textAlign : 'center'
100+ } }
101+ >
51102 Remove the current type
52103 </ ListGroup . Item >
53- : null }
104+ ) }
54105 </ ListGroup >
106+
107+ < div style = { { marginTop : '20px' } } >
108+ < h6 style = { { textAlign : 'left' , marginBottom : '10px' } } > Create a new type</ h6 >
109+ < InputGroup style = { { marginBottom : '10px' } } >
110+ < Form . Control
111+ type = "text"
112+ placeholder = "New type name"
113+ value = { newType }
114+ onChange = { ( e ) => setNewType ( e . target . value ) }
115+ className = "inputField"
116+ />
117+ </ InputGroup >
118+
119+ < InputGroup >
120+ < Form . Control
121+ type = "color"
122+ value = { newColor }
123+ onChange = { ( e ) => setNewColor ( e . target . value ) }
124+ style = { { height : '40px' , width : '40px' , border : 'none' , cursor : 'pointer' } }
125+ />
126+ < Button
127+ variant = "success"
128+ onClick = { handleAddNewType }
129+ className = "addButton"
130+ >
131+ Add Type
132+ </ Button >
133+ </ InputGroup >
134+ </ div >
55135 </ >
56136 ) ;
57137}
@@ -77,26 +157,43 @@ function Type({ metadata, editable, backend }) {
77157 . catch ( console . error ) ;
78158 } ;
79159
160+ const addNewType = async ( newTypeName , newColor ) => {
161+ const newId = uuidv4 ( ) ;
162+ const newTypeObject = {
163+ type_name : newTypeName ,
164+ color : newColor ,
165+ } ;
166+
167+ try {
168+ const response = await backend . putDocument ( newTypeObject , newId ) ;
169+ console . log ( 'Type ajouté avec succès:' , response ) ;
170+ return response ;
171+ } catch ( error ) {
172+ console . error ( 'Erreur lors de l\'ajout du type:' , error ) ;
173+ throw new Error ( 'L\'ajout du type a échoué. Veuillez réessayer.' ) ;
174+ }
175+ } ;
176+
80177 return (
81178 < div style = { { paddingTop : 10 , paddingBottom : 30 } } >
82179 < div style = { { paddingTop : 0 , justifyContent : 'flex-end' } } >
83180 < TypeBadge addClassName = "typeSelected" type = { typeSelected } />
84181 { editable ? (
85- < OverlayTrigger
86- placement = "top"
87- overlay = { < Tooltip id = "tooltip-apply-label" > Apply a label...</ Tooltip > }
88- >
89- < TagFill
90- onClick = { handleEdit }
91- className = "icon typeIcon always-visible"
92- />
93- </ OverlayTrigger >
182+ < TagFill
183+ onClick = { handleEdit }
184+ className = "icon typeIcon"
185+ title = "Apply a label..."
186+ />
94187 ) : null }
95188 </ div >
96- { beingEdited ?
97- < TypeList typeSelected = { typeSelected } handleUpdate = { handleUpdate } />
98- : null
99- }
189+ { beingEdited && (
190+ < TypeList
191+ typeSelected = { typeSelected }
192+ handleUpdate = { handleUpdate }
193+ addNewType = { addNewType }
194+ backend = { backend }
195+ />
196+ ) }
100197 </ div >
101198 ) ;
102199}
0 commit comments