@@ -6,8 +6,9 @@ import { useWorkPackageSearch } from "../hooks/useWorkPackageSearch";
66import type { WorkPackage } from "../openProjectTypes" ;
77import { linkToWorkPackage } from "../services/openProjectApi" ;
88
9+ import "./OpenProjectWorkPackageBlock.css" ;
10+
911const UI_BLUE = "#000091" ; // Default color for task status icons
10- const UI_BEIGE = "#FBF5F2" ;
1112
1213interface BlockProps {
1314 props : {
@@ -35,8 +36,6 @@ const OpenProjectWorkPackageBlockComponent = ({
3536 searchQuery,
3637 setSearchQuery,
3738 searchResults,
38- // loading: searchLoading,
39- // error: searchError,
4039 } = useWorkPackageSearch ( ) ;
4140
4241 const [ selectedWorkPackage , setSelectedWorkPackage ] = useState < WorkPackage | null > ( null ) ;
@@ -45,12 +44,20 @@ const OpenProjectWorkPackageBlockComponent = ({
4544
4645 // Load saved work package if it exists
4746 const workPackageResult = useWorkPackage ( block . props . wpid ) ;
48- if ( ! workPackageResult . error && workPackageResult . workPackage ) {
49- setSelectedWorkPackage ( workPackageResult . workPackage ) ;
50- } else {
51- // Autofocus search
52- setTimeout ( ( ) => inputRef ?. current ?. focus ( ) , 50 ) ;
53- }
47+
48+ // Set selected work package when loaded
49+ useEffect ( ( ) => {
50+ if ( ! workPackageResult . error && workPackageResult . workPackage ) {
51+ setSelectedWorkPackage ( workPackageResult . workPackage ) ;
52+ }
53+ } , [ workPackageResult . error , workPackageResult . workPackage ] ) ;
54+
55+ // Autofocus search if no work package
56+ useEffect ( ( ) => {
57+ if ( workPackageResult . error || ! workPackageResult . workPackage ) {
58+ setTimeout ( ( ) => inputRef ?. current ?. focus ( ) , 50 ) ;
59+ }
60+ } , [ workPackageResult . error , workPackageResult . workPackage ] ) ;
5461
5562 // Handle click outside to close dropdown
5663 useEffect ( ( ) => {
@@ -121,80 +128,45 @@ const OpenProjectWorkPackageBlockComponent = ({
121128 } ;
122129
123130 return (
124- < div
125- style = { {
126- padding : "12px 10px" ,
127- border : "none" ,
128- borderRadius : "5px" ,
129- backgroundColor : UI_BEIGE ,
130- width : "450px" ,
131- } }
132- >
131+ < div className = "opwp-block" >
133132 < div >
134133 { ! block . props . wpid && (
135- < div style = { { position : "relative" } } >
136- < div
137- style = { {
138- display : "flex" ,
134+ < div className = "opwp-search-container" >
135+ < input
136+ ref = { inputRef }
137+ type = "text"
138+ className = "opwp-search-input"
139+ placeholder = { "Search for work package ID or subject" }
140+ value = { searchQuery }
141+ onChange = { ( e ) => {
142+ setSearchQuery ( e . target . value ) ;
143+ if ( e . target . value ) {
144+ setIsDropdownOpen ( true ) ;
145+ }
139146 } }
140- >
141- < input
142- ref = { inputRef }
143- type = "text"
144- placeholder = { "Search for work package ID or subject" }
145- value = { searchQuery }
146- onChange = { ( e ) => {
147- setSearchQuery ( e . target . value ) ;
148- if ( e . target . value ) {
149- setIsDropdownOpen ( true ) ;
150- }
151- } }
152- onFocus = { ( ) => {
153- if ( searchResults . length > 0 ) {
154- setIsDropdownOpen ( true ) ;
155- }
156- } }
157- onKeyDown = { handleKeyDown }
158- style = { {
159- width : "100%" ,
160- padding : "8px 12px" ,
161- borderRadius : "4px" ,
162- border : "1px solid #ccc" ,
163- fontSize : "14px" ,
164- } }
165- />
166- { /* <button onClick={() => setMode('create')}>
167- {t('New Work Package')}
168- </button> */ }
169- </ div >
147+ onFocus = { ( ) => {
148+ if ( searchResults . length > 0 ) {
149+ setIsDropdownOpen ( true ) ;
150+ }
151+ } }
152+ onKeyDown = { handleKeyDown }
153+ />
170154
171155 { /* Autocomplete dropdown */ }
172156 { isDropdownOpen && searchResults . length > 0 && (
173157 < div
174158 ref = { dropdownRef }
175159 role = "listbox"
176160 aria-label = { "Work package search results" }
177- style = { {
178- position : "absolute" ,
179- top : "100%" ,
180- left : 0 ,
181- right : 0 ,
182- zIndex : 10 ,
183- backgroundColor : "white" ,
184- border : "1px solid #ccc" ,
185- borderRadius : "0 0 4px 4px" ,
186- boxShadow : "0 2px 4px rgba(0,0,0,0.1)" ,
187- maxHeight : "200px" ,
188- overflowY : "auto" ,
189- marginTop : "2px" ,
190- } }
161+ className = "opwp-dropdown"
191162 >
192163 { searchResults . slice ( 0 , 5 ) . map ( ( wp , index ) => (
193164 < div
194165 key = { wp . id }
195166 role = "option"
196167 aria-selected = { focusedResultIndex === index }
197168 tabIndex = { 0 }
169+ className = { `opwp-dropdown-option${ focusedResultIndex === index ? " selected" : "" } ` }
198170 onClick = { ( ) => handleSelectWorkPackage ( wp ) }
199171 onKeyDown = { ( e ) => {
200172 if ( e . key === "Enter" || e . key === " " ) {
@@ -203,12 +175,6 @@ const OpenProjectWorkPackageBlockComponent = ({
203175 }
204176 } }
205177 onMouseEnter = { ( ) => setFocusedResultIndex ( index ) }
206- style = { {
207- padding : "8px 12px" ,
208- cursor : "pointer" ,
209- backgroundColor : focusedResultIndex === index ? "#f0f0f0" : "transparent" ,
210- borderBottom : index < searchResults . length - 1 ? "1px solid #eee" : "none" ,
211- } }
212178 >
213179 < div style = { { fontWeight : "bold" } } >
214180 #{ wp . id } - { wp . subject }
@@ -222,57 +188,30 @@ const OpenProjectWorkPackageBlockComponent = ({
222188 ) }
223189 </ div >
224190 ) }
225- { block . props . wpid && ! selectedWorkPackage && (
226- < div >
227- #{ block . props . wpid } { block . props . subject }
228- </ div >
229- ) }
230191 { /* Display selected work package details */ }
231192 { selectedWorkPackage && (
232193 < div >
233- < div
234- style = { {
235- display : "flex" ,
236- gap : "8px" ,
237- } }
238- >
194+ < div style = { { display : "flex" , gap : "8px" } } >
239195 < div
240- style = { {
241- gap : "8px" ,
242- color : selectedWorkPackage . _embedded ?. type ?. color || UI_BLUE ,
243- fontWeight : "bold" ,
244- textTransform : "uppercase" ,
245- } }
196+ className = "opwp-type opwp-type-color"
197+ style = { { color : selectedWorkPackage . _embedded ?. type ?. color || UI_BLUE } }
246198 >
247199 { selectedWorkPackage . _links ?. type ?. title }
248200 </ div >
201+ < div className = "opwp-id" > #{ selectedWorkPackage . id } </ div >
249202 < div
250- style = { {
251- color : "#666" ,
252- } }
253- >
254- #{ selectedWorkPackage . id }
255- </ div >
256- < div
257- style = { {
258- fontSize : "0.8rem" ,
259- borderRadius : "12px" ,
260- padding : "2px 8px" ,
261- border : "1px solid #ccc" ,
262- backgroundColor : selectedWorkPackage . _embedded ?. status ?. color || UI_BLUE ,
263- } }
203+ className = "opwp-status"
204+ style = { { backgroundColor : selectedWorkPackage . _embedded ?. status ?. color || UI_BLUE } }
264205 >
265206 { selectedWorkPackage . _links ?. status ?. title }
266207 </ div >
267208 </ div >
268209
269210 < div >
270- < a href = { linkToWorkPackage ( block . props . wpid ) } style = { {
271- marginRight : 6 ,
272- textDecoration : "none" ,
273- color : UI_BLUE ,
274- cursor : "pointer" ,
275- } } >
211+ < a
212+ href = { linkToWorkPackage ( block . props . wpid ) }
213+ className = "opwp-link"
214+ >
276215 { selectedWorkPackage . subject }
277216 </ a >
278217 </ div >
0 commit comments