@@ -2,32 +2,58 @@ import {
22 Avatar ,
33 Button ,
44 ButtonDomRef ,
5+ Form ,
6+ FormGroup ,
7+ FormItem ,
58 Icon ,
9+ Label ,
610 List ,
711 ListItemStandard ,
812 Popover ,
913 PopoverDomRef ,
14+ RatingIndicator ,
1015 ShellBar ,
1116 ShellBarDomRef ,
17+ ShellBarItem ,
18+ ShellBarItemDomRef ,
19+ TextArea ,
20+ TextAreaDomRef ,
1221 Ui5CustomEvent ,
1322} from '@ui5/webcomponents-react' ;
1423import { useAuth } from '../../spaces/onboarding/auth/AuthContext.tsx' ;
15- import { RefObject , useEffect , useRef , useState } from 'react' ;
24+ import {
25+ Dispatch ,
26+ RefObject ,
27+ SetStateAction ,
28+ useEffect ,
29+ useRef ,
30+ useState ,
31+ } from 'react' ;
1632import { ShellBarProfileClickEventDetail } from '@ui5/webcomponents-fiori/dist/ShellBar.js' ;
1733import PopoverPlacement from '@ui5/webcomponents/dist/types/PopoverPlacement.js' ;
1834import { useTranslation } from 'react-i18next' ;
1935import { generateInitialsForEmail } from '../Helper/generateInitialsForEmail.ts' ;
2036import styles from './ShellBar.module.css' ;
2137import { ThemingParameters } from '@ui5/webcomponents-react-base' ;
38+ import { ShellBarItemClickEventDetail } from '@ui5/webcomponents-fiori/dist/ShellBarItem.js' ;
39+ import { t } from 'i18next' ;
2240
2341export function ShellBarComponent ( ) {
2442 const auth = useAuth ( ) ;
2543 const profilePopoverRef = useRef < PopoverDomRef > ( null ) ;
2644 const betaPopoverRef = useRef < PopoverDomRef > ( null ) ;
45+ const feedbackPopoverRef = useRef < PopoverDomRef > ( null ) ;
2746 const [ profilePopoverOpen , setProfilePopoverOpen ] = useState ( false ) ;
2847 const [ betaPopoverOpen , setBetaPopoverOpen ] = useState ( false ) ;
48+ const [ feedbackPopoverOpen , setFeedbackPopoverOpen ] = useState ( false ) ;
49+ const [ rating , setRating ] = useState ( 0 ) ;
50+ const [ feedbackMessage , setFeedbackMessage ] = useState ( '' ) ;
51+ const [ feedbackSent , setFeedbackSent ] = useState ( false ) ;
52+
2953 const betaButtonRef = useRef < ButtonDomRef > ( null ) ;
3054
55+ const { user } = useAuth ( ) ;
56+
3157 const onProfileClick = (
3258 e : Ui5CustomEvent < ShellBarDomRef , ShellBarProfileClickEventDetail > ,
3359 ) => {
@@ -42,6 +68,45 @@ export function ShellBarComponent() {
4268 }
4369 } ;
4470
71+ const onFeedbackClick = (
72+ e : Ui5CustomEvent < ShellBarItemDomRef , ShellBarItemClickEventDetail > ,
73+ ) => {
74+ feedbackPopoverRef . current ! . opener = e . detail . targetRef ;
75+ setFeedbackPopoverOpen ( ! feedbackPopoverOpen ) ;
76+ } ;
77+
78+ const onFeedbackMessageChange = (
79+ event : Ui5CustomEvent <
80+ TextAreaDomRef ,
81+ { value : string ; previousValue : string }
82+ > ,
83+ ) => {
84+ const newValue = event . target . value ;
85+ setFeedbackMessage ( newValue ) ;
86+ } ;
87+
88+ async function onFeedbackSent ( ) {
89+ const payload = {
90+ message : feedbackMessage ,
91+ rating : rating . toString ( ) ,
92+ user : user ?. email ,
93+ environment : window . location . hostname ,
94+ } ;
95+ try {
96+ await fetch ( '/api/feedback' , {
97+ method : 'POST' ,
98+ headers : {
99+ 'Content-Type' : 'application/json' ,
100+ } ,
101+ body : JSON . stringify ( payload ) ,
102+ } ) ;
103+ } catch ( err ) {
104+ console . log ( err ) ;
105+ } finally {
106+ setFeedbackSent ( true ) ;
107+ }
108+ }
109+
45110 useEffect ( ( ) => {
46111 const shellbar = document . querySelector ( 'ui5-shellbar' ) ;
47112 const el = shellbar ?. shadowRoot ?. querySelector (
@@ -82,7 +147,13 @@ export function ShellBarComponent() {
82147 </ div >
83148 }
84149 onProfileClick = { onProfileClick }
85- />
150+ >
151+ < ShellBarItem
152+ icon = "feedback"
153+ text = { t ( 'ShellBar.feedbackNotification' ) }
154+ onClick = { onFeedbackClick }
155+ />
156+ </ ShellBar >
86157
87158 < ProfilePopover
88159 open = { profilePopoverOpen }
@@ -94,6 +165,17 @@ export function ShellBarComponent() {
94165 setOpen = { setBetaPopoverOpen }
95166 popoverRef = { betaPopoverRef }
96167 />
168+ < FeedbackPopover
169+ open = { feedbackPopoverOpen }
170+ setOpen = { setFeedbackPopoverOpen }
171+ popoverRef = { feedbackPopoverRef }
172+ setRating = { setRating }
173+ rating = { rating }
174+ feedbackMessage = { feedbackMessage }
175+ feedbackSent = { feedbackSent }
176+ onFeedbackSent = { onFeedbackSent }
177+ onFeedbackMessageChange = { onFeedbackMessageChange }
178+ />
97179 </ >
98180 ) ;
99181}
@@ -163,3 +245,106 @@ const BetaPopover = ({
163245 </ Popover >
164246 ) ;
165247} ;
248+
249+ const FeedbackPopover = ( {
250+ open,
251+ setOpen,
252+ popoverRef,
253+ setRating,
254+ rating,
255+ onFeedbackSent,
256+ feedbackMessage,
257+ onFeedbackMessageChange,
258+ feedbackSent,
259+ } : {
260+ open : boolean ;
261+ setOpen : ( arg0 : boolean ) => void ;
262+ popoverRef : RefObject < PopoverDomRef | null > ;
263+ setRating : Dispatch < SetStateAction < number > > ;
264+ rating : number ;
265+ onFeedbackSent : ( ) => void ;
266+ feedbackMessage : string ;
267+ onFeedbackMessageChange : (
268+ event : Ui5CustomEvent <
269+ TextAreaDomRef ,
270+ {
271+ value : string ;
272+ previousValue : string ;
273+ }
274+ > ,
275+ ) => void ;
276+ feedbackSent : boolean ;
277+ } ) => {
278+ const { t } = useTranslation ( ) ;
279+
280+ const onRatingChange = ( event : {
281+ detail : { selectedValue : SetStateAction < number > } ;
282+ } ) => {
283+ setRating ( event . detail . selectedValue ) ;
284+ } ;
285+
286+ return (
287+ < >
288+ < Popover
289+ ref = { popoverRef }
290+ placement = { PopoverPlacement . Bottom }
291+ open = { open }
292+ onClose = { ( ) => setOpen ( false ) }
293+ >
294+ < div
295+ style = { {
296+ padding : '1rem' ,
297+ width : '250px' ,
298+ } }
299+ >
300+ { ! feedbackSent ? (
301+ < Form headerText = { t ( 'ShellBar.feedbackHeader' ) } >
302+ < FormGroup >
303+ < FormItem
304+ labelContent = {
305+ < Label style = { { color : 'black' } } >
306+ { t ( 'ShellBar.feedbackRatingLabel' ) }
307+ </ Label >
308+ }
309+ >
310+ < RatingIndicator
311+ value = { rating }
312+ max = { 5 }
313+ onChange = { onRatingChange }
314+ />
315+ </ FormItem >
316+ < FormItem
317+ className = "formAlignLabelStart"
318+ labelContent = {
319+ < Label style = { { color : 'black' } } >
320+ { t ( 'ShellBar.feedbackMessageLabel' ) }
321+ </ Label >
322+ }
323+ >
324+ < TextArea
325+ value = { feedbackMessage }
326+ placeholder = { t ( 'ShellBar.feedbackPlaceholder' ) }
327+ rows = { 5 }
328+ onInput = { onFeedbackMessageChange }
329+ />
330+ </ FormItem >
331+ < FormItem >
332+ < Button design = "Emphasized" onClick = { ( ) => onFeedbackSent ( ) } >
333+ Send Feedback
334+ </ Button >
335+ </ FormItem >
336+ < FormItem >
337+ < Label style = { { color : 'gray' } } >
338+ { t ( 'ShellBar.feedbackNotification' ) }
339+ </ Label >
340+ </ FormItem >
341+ </ FormGroup >
342+ </ Form >
343+ ) : (
344+ < Label > { t ( 'ShellBar.feedbackThanks' ) } </ Label >
345+ ) }
346+ </ div >
347+ </ Popover >
348+ </ >
349+ ) ;
350+ } ;
0 commit comments