Skip to content

Commit d86415d

Browse files
committed
refactor: add positive feedback
1 parent 8761afe commit d86415d

File tree

2 files changed

+79
-62
lines changed

2 files changed

+79
-62
lines changed

packages/backend/src/routes/api/chat/feedback.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { getAuthenticatedContext } from '../middleware/authentication'
1010
interface ChatFeedbackRequest {
1111
traceId: string
1212
feedback: string
13+
score: number
1314
}
1415

1516
const handleChatFeedback = async (
@@ -19,7 +20,7 @@ const handleChatFeedback = async (
1920
const context = getAuthenticatedContext(req)
2021

2122
try {
22-
const { traceId, feedback } = req.body as ChatFeedbackRequest
23+
const { traceId, feedback, score } = req.body as ChatFeedbackRequest
2324

2425
if (!traceId || !feedback) {
2526
res.status(400).json({ error: 'Trace ID and feedback are required' })
@@ -30,7 +31,7 @@ const handleChatFeedback = async (
3031
id: `feedback-${traceId}-${context.currentUser.email}`,
3132
environment: appConfig.appEnv,
3233
name: 'user-feedback',
33-
value: 0, // 1 for positive, 0 for negative
34+
value: score, // 1 for positive, 0 for negative
3435
comment: feedback,
3536
})
3637
res.status(200).json({ success: true })
Lines changed: 76 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React, { useState } from 'react'
2-
import { FaRegThumbsDown } from 'react-icons/fa'
1+
import React, { useRef, useState } from 'react'
2+
import { FaRegThumbsDown, FaRegThumbsUp } from 'react-icons/fa'
33
import {
44
Button,
55
ButtonGroup,
@@ -24,13 +24,23 @@ interface ChatMessageToolbarProps {
2424
traceId: string
2525
}
2626

27-
export default function ChatMessageToolbar({
28-
traceId,
29-
}: ChatMessageToolbarProps) {
27+
interface FeedbackButtonProps {
28+
feedbackType: 'positive' | 'negative'
29+
traceId: string
30+
}
31+
32+
const FeedbackButton = ({ feedbackType, traceId }: FeedbackButtonProps) => {
3033
const { onOpen, onClose, isOpen } = useDisclosure()
34+
const firstFieldRef = useRef(null)
3135
const toast = useToast()
32-
const firstFieldRef = React.useRef(null)
33-
const [comment, setComment] = useState('')
36+
const icon = feedbackType === 'positive' ? FaRegThumbsUp : FaRegThumbsDown
37+
const formLabel =
38+
feedbackType === 'positive'
39+
? 'What was helpful about this?'
40+
: 'Why was this not helpful?'
41+
const score = feedbackType === 'positive' ? 1 : 0
42+
43+
const [feedback, setFeedback] = useState('')
3444

3545
const handleSubmitFeedback = async (comment: string) => {
3646
try {
@@ -44,7 +54,7 @@ export default function ChatMessageToolbar({
4454
await fetch('/api/chat/feedback', {
4555
method: 'POST',
4656
headers: { 'Content-Type': 'application/json' },
47-
body: JSON.stringify({ traceId, feedback: comment }),
57+
body: JSON.stringify({ traceId, feedback, score }),
4858
})
4959
} catch {
5060
// don't throw error if feedback submission fails
@@ -55,7 +65,7 @@ export default function ChatMessageToolbar({
5565
// if they attempt to submit again
5666
onClose()
5767
toast({
58-
title: "Thank you! We've sent your feeback to the Plumber team.",
68+
title: "Thank you! We've sent your feedback to the Plumber team.",
5969
status: 'success',
6070
duration: 3000,
6171
isClosable: true,
@@ -65,58 +75,64 @@ export default function ChatMessageToolbar({
6575
}
6676

6777
return (
68-
<Flex gap={1} mt={2}>
69-
<Popover
70-
isOpen={isOpen}
71-
initialFocusRef={firstFieldRef}
72-
onOpen={onOpen}
73-
onClose={onClose}
74-
>
75-
<PopoverTrigger>
76-
<IconButton
77-
variant="clear"
78-
colorScheme="secondary"
79-
aria-label="Thumbs down"
80-
icon={<Icon as={FaRegThumbsDown} />}
81-
onClick={onOpen}
82-
/>
83-
</PopoverTrigger>
84-
<PopoverContent>
85-
<FocusLock persistentFocus={false}>
86-
<PopoverArrow />
78+
<Popover
79+
isOpen={isOpen}
80+
initialFocusRef={firstFieldRef}
81+
onOpen={onOpen}
82+
onClose={onClose}
83+
>
84+
<PopoverTrigger>
85+
<IconButton
86+
variant="clear"
87+
colorScheme="secondary"
88+
aria-label="Thumbs down"
89+
icon={<Icon as={icon} />}
90+
onClick={onOpen}
91+
/>
92+
</PopoverTrigger>
93+
<PopoverContent>
94+
<FocusLock persistentFocus={false}>
95+
<PopoverArrow />
8796

88-
<PopoverBody>
89-
<Stack spacing={4}>
90-
<FormControl>
91-
<FormLabel htmlFor="why-not-helpful">
92-
Why was this not helpful?
93-
</FormLabel>
94-
<Textarea
95-
ref={firstFieldRef}
96-
id="why-not-helpful"
97-
rows={3}
98-
resize="none"
99-
value={comment}
100-
onChange={(e) => setComment(e.target.value)}
101-
/>
102-
</FormControl>
103-
<ButtonGroup display="flex" justifyContent="flex-end">
104-
<Button variant="outline" onClick={onClose}>
105-
Cancel
106-
</Button>
107-
<Button
108-
isDisabled={!comment}
109-
colorScheme="teal"
110-
onClick={() => handleSubmitFeedback(comment)}
111-
>
112-
Submit feedback
113-
</Button>
114-
</ButtonGroup>
115-
</Stack>
116-
</PopoverBody>
117-
</FocusLock>
118-
</PopoverContent>
119-
</Popover>
97+
<PopoverBody>
98+
<Stack spacing={4}>
99+
<FormControl>
100+
<FormLabel htmlFor="feedback-details">{formLabel}</FormLabel>
101+
<Textarea
102+
ref={firstFieldRef}
103+
id="feedback-details"
104+
rows={3}
105+
resize="none"
106+
value={feedback}
107+
onChange={(e) => setFeedback(e.target.value)}
108+
/>
109+
</FormControl>
110+
<ButtonGroup display="flex" justifyContent="flex-end">
111+
<Button variant="outline" onClick={onClose}>
112+
Cancel
113+
</Button>
114+
<Button
115+
isDisabled={!feedback}
116+
onClick={() => handleSubmitFeedback(feedback)}
117+
>
118+
Submit
119+
</Button>
120+
</ButtonGroup>
121+
</Stack>
122+
</PopoverBody>
123+
</FocusLock>
124+
</PopoverContent>
125+
</Popover>
126+
)
127+
}
128+
129+
export default function ChatMessageToolbar({
130+
traceId,
131+
}: ChatMessageToolbarProps) {
132+
return (
133+
<Flex gap={1} mt={2}>
134+
<FeedbackButton feedbackType="negative" traceId={traceId} />
135+
<FeedbackButton feedbackType="positive" traceId={traceId} />
120136
</Flex>
121137
)
122138
}

0 commit comments

Comments
 (0)