11"use client" ;
22
3+ import { useMutation } from "@tanstack/react-query" ;
34import { format } from "date-fns" ;
4- import { ChevronDownIcon , UserIcon } from "lucide-react" ;
5+ import { ChevronDownIcon , StarIcon , UserIcon } from "lucide-react" ;
56import Link from "next/link" ;
67import { useState } from "react" ;
78import { toast } from "sonner" ;
@@ -56,13 +57,12 @@ export function SupportCaseDetails({ ticket, team }: SupportCaseDetailsProps) {
5657 setRating ( starIndex + 1 ) ;
5758 } ;
5859
59- const handleSendFeedback = async ( ) => {
60- if ( rating === 0 ) {
61- toast . error ( "Please select a rating" ) ;
62- return ;
63- }
60+ const submitFeedbackMutation = useMutation ( {
61+ mutationFn : async ( ) => {
62+ if ( rating === 0 ) {
63+ throw new Error ( "Please select a rating" ) ;
64+ }
6465
65- try {
6666 const result = await submitSupportFeedback ( {
6767 rating,
6868 feedback,
@@ -73,6 +73,9 @@ export function SupportCaseDetails({ ticket, team }: SupportCaseDetailsProps) {
7373 throw new Error ( result . error ) ;
7474 }
7575
76+ return result ;
77+ } ,
78+ onSuccess : ( ) => {
7679 toast . success ( "Thank you for your feedback!" ) ;
7780 setRating ( 0 ) ;
7881 setFeedback ( "" ) ;
@@ -91,10 +94,17 @@ export function SupportCaseDetails({ ticket, team }: SupportCaseDetailsProps) {
9194 ) ;
9295 }
9396 }
94- } catch ( error ) {
97+ } ,
98+ onError : ( error ) => {
9599 console . error ( "Failed to submit feedback:" , error ) ;
96- toast . error ( "Failed to submit feedback. Please try again." ) ;
97- }
100+ toast . error (
101+ error . message || "Failed to submit feedback. Please try again." ,
102+ ) ;
103+ } ,
104+ } ) ;
105+
106+ const handleSendFeedback = ( ) => {
107+ submitFeedbackMutation . mutate ( ) ;
98108 } ;
99109
100110 const handleSendReply = async ( ) => {
@@ -225,36 +235,42 @@ export function SupportCaseDetails({ ticket, team }: SupportCaseDetailsProps) {
225235 className = "transition-colors"
226236 aria-label = { `Rate ${ starValue } out of 5 stars` }
227237 >
228- < svg
229- width = "32"
230- height = "32"
231- viewBox = "0 0 24 24"
232- fill = { starValue <= rating ? "#ff00aa" : "none" }
233- stroke = { starValue <= rating ? "#ff00aa" : "#666" }
238+ < StarIcon
239+ size = { 32 }
240+ className = { cn (
241+ "transition-colors hover:fill-pink-500 hover:stroke-pink-500" ,
242+ starValue <= rating
243+ ? "fill-[#ff00aa] stroke-[#ff00aa]"
244+ : "fill-none stroke-[#666]" ,
245+ ) }
234246 strokeWidth = { starValue <= rating ? "2" : "1" }
235- className = "hover:fill-pink-500 hover:stroke-pink-500 rounded-sm"
236- rx = "2"
237- aria-hidden = "true"
238- >
239- < polygon points = "12,2 15.09,8.26 22,9.27 17,14.14 18.18,21.02 12,17.77 5.82,21.02 7,14.14 2,9.27 8.91,8.26" />
240- </ svg >
247+ />
241248 </ button >
242249 ) ) }
243250 </ div >
244251
245252 < div className = "relative" >
246- < textarea
253+ < AutoResizeTextarea
247254 value = { feedback }
248255 onChange = { ( e ) => setFeedback ( e . target . value ) }
249256 placeholder = "Optional: Tell us how we can improve."
257+ maxLength = { 1000 }
250258 className = "text-muted-foreground text-sm w-full bg-black text-white rounded-lg p-4 pr-28 min-h-[100px] resize-none border border-[#262626] focus:border-[#262626] focus:outline-none placeholder-[#A1A1A1]"
251259 />
252260 < button
253261 type = "button"
254262 onClick = { handleSendFeedback }
255- className = "absolute mb-2 bottom-3 right-3 bg-white text-black px-4 py-2 rounded-full text-sm font-medium hover:bg-gray-100 transition-colors"
263+ disabled = { submitFeedbackMutation . isPending }
264+ className = "absolute mb-2 bottom-3 right-3 bg-white text-black px-4 py-2 rounded-full text-sm font-medium hover:bg-gray-100 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
256265 >
257- Send Feedback
266+ { submitFeedbackMutation . isPending ? (
267+ < >
268+ < Spinner className = "size-4 mr-2" />
269+ Sending...
270+ </ >
271+ ) : (
272+ "Send Feedback"
273+ ) }
258274 </ button >
259275 </ div >
260276 </ div >
0 commit comments