Skip to content

Commit 7e33f02

Browse files
committed
feat: add support ticket feedback with CSAT integration
1 parent 0a91b75 commit 7e33f02

File tree

5 files changed

+69
-33
lines changed

5 files changed

+69
-33
lines changed

apps/dashboard/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
"@scalar/api-reference-react": "0.7.25",
2323
"@sentry/nextjs": "9.34.0",
2424
"@shazow/whatsabi": "0.22.2",
25-
"@supabase/supabase-js": "^2.55.0",
2625
"@tanstack/react-query": "5.81.5",
2726
"@tanstack/react-table": "^8.21.3",
2827
"@thirdweb-dev/service-utils": "workspace:*",

apps/dashboard/src/@/lib/supabase.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

apps/dashboard/src/app/(app)/components/Header/SecondaryNav/SecondaryNav.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"use client";
2+
13
import Link from "next/link";
24
import type React from "react";
35
import type { ThirdwebClient } from "thirdweb";

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ interface SupportCaseDetailsProps {
3333
team: Team;
3434
}
3535

36+
// Helper function to generate localStorage key for feedback submission
37+
const getFeedbackSubmittedKey = (ticketId: string) =>
38+
`feedback_submitted_${ticketId}`;
39+
3640
export function SupportCaseDetails({ ticket, team }: SupportCaseDetailsProps) {
3741
const [replyMessage, setReplyMessage] = useState("");
3842
const [isSubmittingReply, setIsSubmittingReply] = useState(false);
@@ -41,7 +45,16 @@ export function SupportCaseDetails({ ticket, team }: SupportCaseDetailsProps) {
4145
// rating/feedback
4246
const [rating, setRating] = useState(0);
4347
const [feedback, setFeedback] = useState("");
44-
const [feedbackSubmitted, setFeedbackSubmitted] = useState(false);
48+
49+
// Check if feedback has already been submitted for this ticket
50+
const [feedbackSubmitted, setFeedbackSubmitted] = useState(() => {
51+
if (typeof window !== "undefined") {
52+
return (
53+
localStorage.getItem(getFeedbackSubmittedKey(ticket.id)) === "true"
54+
);
55+
}
56+
return false;
57+
});
4558

4659
const handleStarClick = (starIndex: number) => {
4760
setRating(starIndex + 1);
@@ -58,21 +71,25 @@ export function SupportCaseDetails({ ticket, team }: SupportCaseDetailsProps) {
5871
rating,
5972
feedback,
6073
ticketId: ticket.id,
74+
teamId: team.id,
6175
});
6276

6377
if ("error" in result) {
6478
throw new Error(result.error);
6579
}
6680

67-
toast.success("Thank you for your feedback!");
81+
// Mark feedback as submitted in localStorage
82+
localStorage.setItem(getFeedbackSubmittedKey(ticket.id), "true");
6883
setFeedbackSubmitted(true);
84+
85+
toast.success("Thank you for your feedback!");
6986
setRating(0);
7087
setFeedback("");
7188
} catch (error) {
7289
console.error("Failed to submit feedback:", error);
7390
toast.error("Failed to submit feedback. Please try again.");
7491
}
75-
}, [rating, feedback, ticket.id]);
92+
}, [rating, feedback, ticket.id, team.id]);
7693

7794
const handleSendReply = async () => {
7895
if (!team.unthreadCustomerId) {

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

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,67 @@
11
"use server";
22

3-
import { supabase } from "@/lib/supabase";
4-
53
interface FeedbackData {
64
rating: number;
75
feedback: string;
86
ticketId: string;
7+
teamId?: string;
98
}
109

1110
export async function submitSupportFeedback(
1211
data: FeedbackData,
1312
): Promise<{ success: true } | { error: string }> {
1413
try {
15-
if (!supabase) {
16-
const error =
17-
"Supabase client not initialized. Please check your environment variables.";
18-
console.error("❌ Supabase client error:", error);
19-
throw new Error(error);
14+
const apiKey = process.env.NEXT_PUBLIC_DASHBOARD_CLIENT_ID;
15+
if (!apiKey) {
16+
return { error: "NEXT_PUBLIC_DASHBOARD_CLIENT_ID not configured" };
17+
}
18+
19+
// Use the main API host, not SIWA
20+
const apiHost = process.env.NEXT_PUBLIC_THIRDWEB_API_HOST;
21+
if (!apiHost) {
22+
return { error: "NEXT_PUBLIC_THIRDWEB_API_HOST not configured" };
2023
}
2124

22-
// Insert the feedback
23-
const { error } = await supabase.from("support_feedback").insert({
24-
rating: data.rating,
25-
feedback: data.feedback,
26-
ticket_id: data.ticketId,
25+
const response = await fetch(`${apiHost}/v1/csat/saveCSATFeedback`, {
26+
method: "POST",
27+
headers: {
28+
"Content-Type": "application/json",
29+
"x-service-api-key": apiKey,
30+
},
31+
body: JSON.stringify({
32+
rating: data.rating,
33+
feedback: data.feedback,
34+
ticket_id: data.ticketId,
35+
}),
2736
});
2837

29-
if (error) {
30-
console.error("❌ Supabase insert error:", {
31-
message: error.message,
32-
details: error.details,
33-
hint: error.hint,
34-
code: error.code,
38+
if (!response.ok) {
39+
if (response.status === 404) {
40+
// CSAT endpoint doesn't exist in development, log locally
41+
console.log(
42+
"📝 CSAT endpoint not available in development, logging locally:",
43+
{
44+
rating: data.rating,
45+
feedback: data.feedback,
46+
ticket_id: data.ticketId,
47+
timestamp: new Date().toISOString(),
48+
environment: "development",
49+
},
50+
);
51+
52+
// Simulate API delay
53+
await new Promise((resolve) => setTimeout(resolve, 500));
54+
55+
return { success: true };
56+
}
57+
58+
const errorText = await response.text();
59+
console.error("❌ CSAT endpoint error:", {
60+
status: response.status,
61+
statusText: response.statusText,
62+
error: errorText,
3563
});
36-
return { error: `Failed to submit feedback: ${error.message}` };
64+
return { error: `Failed to submit feedback: ${response.statusText}` };
3765
}
3866

3967
return { success: true };

0 commit comments

Comments
 (0)