Skip to content

Commit 282de02

Browse files
committed
improve feedback system with validation and UI enhancements
1 parent ff00113 commit 282de02

File tree

2 files changed

+43
-27
lines changed

2 files changed

+43
-27
lines changed

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/SupportCaseDetails.tsx

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"use client";
22

3+
import { useMutation } from "@tanstack/react-query";
34
import { format } from "date-fns";
4-
import { ChevronDownIcon, UserIcon } from "lucide-react";
5+
import { ChevronDownIcon, StarIcon, UserIcon } from "lucide-react";
56
import Link from "next/link";
67
import { useState } from "react";
78
import { 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>

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/apis/feedback.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export async function submitSupportFeedback(
2323
}
2424

2525
// Basic input validation/normalization
26-
if (!Number.isFinite(data.rating) || data.rating < 1 || data.rating > 5) {
26+
if (!Number.isInteger(data.rating) || data.rating < 1 || data.rating > 5) {
2727
return { error: "Rating must be an integer between 1 and 5." };
2828
}
2929

@@ -33,7 +33,7 @@ export async function submitSupportFeedback(
3333
.slice(0, 1000); // hard cap length
3434

3535
const payload = {
36-
rating: Math.round(data.rating),
36+
rating: data.rating.toString(),
3737
feedback: normalizedFeedback,
3838
ticket_id: data.ticketId || null,
3939
};

0 commit comments

Comments
 (0)