@@ -2,56 +2,137 @@ 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 } from 'react' ;
6+ import { ListGroup , Form , InputGroup , Button } from 'react-bootstrap' ;
7+ import { useCallback , useEffect } from 'react' ;
78import { TypesContext } from './TypesContext.js' ;
9+ import { v4 as uuidv4 } from 'uuid' ;
810
911export function TypeBadge ( { type, addClassName } ) {
1012 const types = useContext ( TypesContext ) ;
1113 if ( ! type ) return null ;
1214 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 > ;
15+ if ( ! typeSelected || ! typeSelected . doc ) return null ;
16+
17+ return (
18+ < span
19+ className = { `typeBadge ${ addClassName ?? '' } ` }
20+ style = { { backgroundColor : typeSelected . doc . color } }
21+ >
22+ { typeSelected . doc . type_name }
23+ </ span >
24+ ) ;
1725}
1826
19- function TypeList ( { typeSelected, handleUpdate } ) {
20- const types = useContext ( TypesContext ) ;
27+ function TypeList ( { typeSelected, handleUpdate, addNewType , backend } ) {
28+ const [ types , setTypes ] = useState ( [ ] ) ;
2129 const [ searchTerm , setSearchTerm ] = useState ( '' ) ;
30+ const [ newType , setNewType ] = useState ( '' ) ;
31+ const [ newColor , setNewColor ] = useState ( '#FF5733' ) ;
32+
33+ const fetchTypes = useCallback ( async ( ) => {
34+ try {
35+ const response = await backend . getView ( { view : 'types' , options : [ 'include_docs' ] } ) ;
36+ setTypes ( response ) ;
37+ console . log ( 'Types récupérés:' , response ) ;
38+ } catch ( error ) {
39+ console . error ( 'Erreur lors de la récupération des types:' , error ) ;
40+ }
41+ } , [ backend ] ) ;
42+
43+ useEffect ( ( ) => {
44+ fetchTypes ( ) ;
45+ } , [ fetchTypes ] ) ;
2246
23- const filteredTypes = types . filter ( type =>
24- type . doc . type_name . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) )
47+ const handleAddNewType = ( ) => {
48+ if ( newType . trim ( ) ) {
49+ addNewType ( newType , newColor )
50+ . then ( ( ) => {
51+ window . location . reload ( ) ;
52+ } )
53+ . catch ( ( error ) => {
54+ console . error ( 'Erreur lors de l\'ajout du type:' , error ) ;
55+ } ) ;
56+
57+ setNewType ( '' ) ;
58+ setNewColor ( '#FF5733' ) ;
59+ }
60+ } ;
61+
62+ const filteredTypes = types . filter (
63+ ( type ) =>
64+ type . doc &&
65+ type . doc . type_name &&
66+ type . doc . type_name . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) )
2567 ) ;
68+
2669 return (
2770 < >
28- < h6 style = { { textAlign : 'left' } } > Select a type</ h6 >
29- < input
71+ < h6 style = { { textAlign : 'left' , marginBottom : '15px' } } > Select a type</ h6 >
72+ < Form . Control
3073 type = "text"
3174 id = "searchType"
3275 placeholder = "Filter types..."
3376 value = { searchTerm }
3477 onChange = { ( e ) => setSearchTerm ( e . target . value ) }
35- style = { { marginBottom : '10px ' , width : '100% ' , padding : '5px ' } }
78+ style = { { marginBottom : '15px ' , padding : '10px ' , borderRadius : '8px ' } }
3679 />
80+
3781 < ListGroup style = { { textAlign : 'center' , paddingTop : 0 , paddingBottom : 20 } } >
3882 { filteredTypes . map ( ( type , index ) =>
3983 < ListGroup . Item action
4084 key = { index }
41- style = { { backgroundColor : type === typeSelected ? 'grey' : '' } }
42- onClick = { ( ) => handleUpdate ( type . id ) } >
43- < TypeBadge type = { type . id } />
85+ onClick = { ( ) => handleUpdate ( type . id ) }
86+ className = "typeContainer"
87+ style = { { cursor : 'pointer' } }
88+ >
89+ < TypeBadge type = { type . id } />
4490 </ ListGroup . Item >
4591 ) }
46- { typeSelected ?
92+ { typeSelected && (
4793 < ListGroup . Item action
48- key = { 'remove type' }
49- style = { { color : 'red' } }
50- onClick = { ( ) => handleUpdate ( '' ) } >
94+ key = "remove-type"
95+ onClick = { ( ) => handleUpdate ( '' ) }
96+ style = { {
97+ color : 'red' ,
98+ cursor : 'pointer' ,
99+ marginTop : '10px' ,
100+ textAlign : 'center'
101+ } }
102+ >
51103 Remove the current type
52104 </ ListGroup . Item >
53- : null }
105+ ) }
54106 </ ListGroup >
107+
108+ < div style = { { marginTop : '20px' } } >
109+ < h6 style = { { textAlign : 'left' , marginBottom : '10px' } } > Create a new type</ h6 >
110+ < InputGroup style = { { marginBottom : '10px' } } >
111+ < Form . Control
112+ type = "text"
113+ placeholder = "New type name"
114+ value = { newType }
115+ onChange = { ( e ) => setNewType ( e . target . value ) }
116+ className = "inputField"
117+ />
118+ </ InputGroup >
119+
120+ < InputGroup >
121+ < Form . Control
122+ type = "color"
123+ value = { newColor }
124+ onChange = { ( e ) => setNewColor ( e . target . value ) }
125+ style = { { height : '40px' , width : '40px' , border : 'none' , cursor : 'pointer' } }
126+ />
127+ < Button
128+ variant = "success"
129+ onClick = { handleAddNewType }
130+ className = "addButton"
131+ >
132+ Add Type
133+ </ Button >
134+ </ InputGroup >
135+ </ div >
55136 </ >
56137 ) ;
57138}
@@ -77,26 +158,43 @@ function Type({ metadata, editable, backend }) {
77158 . catch ( console . error ) ;
78159 } ;
79160
161+ const addNewType = async ( newTypeName , newColor ) => {
162+ const newId = uuidv4 ( ) ;
163+ const newTypeObject = {
164+ type_name : newTypeName ,
165+ color : newColor ,
166+ } ;
167+
168+ try {
169+ const response = await backend . putDocument ( newTypeObject , newId ) ;
170+ console . log ( 'Type ajouté avec succès:' , response ) ;
171+ return response ;
172+ } catch ( error ) {
173+ console . error ( 'Erreur lors de l\'ajout du type:' , error ) ;
174+ throw new Error ( 'L\'ajout du type a échoué. Veuillez réessayer.' ) ;
175+ }
176+ } ;
177+
80178 return (
81179 < div style = { { paddingTop : 10 , paddingBottom : 30 } } >
82180 < div style = { { paddingTop : 0 , justifyContent : 'flex-end' } } >
83181 < TypeBadge addClassName = "typeSelected" type = { typeSelected } />
84182 { 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 >
183+ < TagFill
184+ onClick = { handleEdit }
185+ className = "icon typeIcon"
186+ title = "Apply a label..."
187+ />
94188 ) : null }
95189 </ div >
96- { beingEdited ?
97- < TypeList typeSelected = { typeSelected } handleUpdate = { handleUpdate } />
98- : null
99- }
190+ { beingEdited && (
191+ < TypeList
192+ typeSelected = { typeSelected }
193+ handleUpdate = { handleUpdate }
194+ addNewType = { addNewType }
195+ backend = { backend }
196+ />
197+ ) }
100198 </ div >
101199 ) ;
102200}
0 commit comments