Skip to content

Commit 3e6ce96

Browse files
committed
fix
1 parent c8e885a commit 3e6ce96

File tree

4 files changed

+98
-141
lines changed

4 files changed

+98
-141
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Shared utility functions for support ticket status handling
3+
*/
4+
5+
/**
6+
* Get the CSS classes for a support ticket status badge
7+
*/
8+
export function getStatusColor(status: string): string {
9+
switch (status.toLowerCase()) {
10+
case "resolved":
11+
case "closed":
12+
return "border-muted text-muted-foreground bg-muted/10";
13+
case "in_progress":
14+
return "border-destructive text-destructive bg-destructive/10";
15+
case "needs_response":
16+
return "warning";
17+
case "on_hold":
18+
return "border-secondary text-secondary-foreground bg-secondary/10";
19+
default:
20+
return "warning";
21+
}
22+
}
23+
24+
/**
25+
* Get the display label for a support ticket status
26+
*/
27+
export function getStatusLabel(status: string): string {
28+
const statusLower = status.toLowerCase();
29+
30+
switch (statusLower) {
31+
case "closed":
32+
return "Closed";
33+
case "resolved":
34+
return "Resolved";
35+
case "in_progress":
36+
return "Needs Response";
37+
case "needs_response":
38+
return "In Progress";
39+
case "on_hold":
40+
return "On Hold";
41+
default:
42+
return "In Progress";
43+
}
44+
}

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

Lines changed: 35 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -51,37 +51,42 @@ export function CreateSupportCase({ team, authToken }: CreateSupportCaseProps) {
5151
router.push(`/team/${team.slug}/~/support`);
5252
};
5353

54-
const _handleStartChat = useCallback(
55-
async (initialMessage?: string) => {
56-
async function sendMessageToSiwa(
57-
message: string,
58-
currentConversationId?: string,
54+
// Extracted sendMessageToSiwa function to avoid duplication
55+
const sendMessageToSiwa = useCallback(
56+
async (message: string, currentConversationId?: string) => {
57+
if (!authToken) {
58+
throw new Error("Authentication token is required");
59+
}
60+
61+
const apiUrl = process.env.NEXT_PUBLIC_SIWA_URL;
62+
const payload = {
63+
conversationId: currentConversationId,
64+
message,
65+
source: "support-in-dashboard",
66+
};
67+
const response = await fetch(`${apiUrl}/v1/chat`, {
68+
body: JSON.stringify(payload),
69+
headers: {
70+
Authorization: `Bearer ${authToken}`,
71+
"Content-Type": "application/json",
72+
"x-team-id": team.id,
73+
},
74+
method: "POST",
75+
});
76+
const data = await response.json();
77+
if (
78+
data.conversationId &&
79+
data.conversationId !== currentConversationId
5980
) {
60-
const apiUrl = process.env.NEXT_PUBLIC_SIWA_URL;
61-
const payload = {
62-
conversationId: currentConversationId,
63-
message,
64-
source: "support-in-dashboard",
65-
};
66-
const response = await fetch(`${apiUrl}/v1/chat`, {
67-
body: JSON.stringify(payload),
68-
headers: {
69-
Authorization: `Bearer ${authToken}`,
70-
"Content-Type": "application/json",
71-
"x-team-id": team.id,
72-
},
73-
method: "POST",
74-
});
75-
const data = await response.json();
76-
if (
77-
data.conversationId &&
78-
data.conversationId !== currentConversationId
79-
) {
80-
setConversationId(data.conversationId);
81-
}
82-
return data.data;
81+
setConversationId(data.conversationId);
8382
}
83+
return data.data;
84+
},
85+
[authToken, team.id],
86+
);
8487

88+
const _handleStartChat = useCallback(
89+
async (initialMessage?: string) => {
8590
// Show initial AI greeting message immediately
8691
const initialAIMsg = {
8792
content:
@@ -141,41 +146,12 @@ export function CreateSupportCase({ team, authToken }: CreateSupportCaseProps) {
141146
}
142147
}
143148
},
144-
[authToken, team.id],
149+
[sendMessageToSiwa],
145150
);
146151

147152
const handleChatSend = useCallback(async () => {
148153
if (!chatInput.trim()) return;
149154

150-
async function sendMessageToSiwa(
151-
message: string,
152-
currentConversationId?: string,
153-
) {
154-
const apiUrl = process.env.NEXT_PUBLIC_SIWA_URL;
155-
const payload = {
156-
conversationId: currentConversationId,
157-
message,
158-
source: "support-in-dashboard",
159-
};
160-
const response = await fetch(`${apiUrl}/v1/chat`, {
161-
body: JSON.stringify(payload),
162-
headers: {
163-
Authorization: `Bearer ${authToken}`,
164-
"Content-Type": "application/json",
165-
"x-team-id": team.id,
166-
},
167-
method: "POST",
168-
});
169-
const data = await response.json();
170-
if (
171-
data.conversationId &&
172-
data.conversationId !== currentConversationId
173-
) {
174-
setConversationId(data.conversationId);
175-
}
176-
return data.data;
177-
}
178-
179155
const currentInput = chatInput;
180156
setChatInput("");
181157

@@ -218,7 +194,7 @@ export function CreateSupportCase({ team, authToken }: CreateSupportCaseProps) {
218194
},
219195
]);
220196
}
221-
}, [chatInput, conversationId, authToken, team.id]);
197+
}, [chatInput, conversationId, sendMessageToSiwa]);
222198

223199
const handleChatKeyPress = useCallback(
224200
(e: React.KeyboardEvent) => {

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

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import { format } from "date-fns";
44
import { ArrowLeftIcon, SendIcon } from "lucide-react";
55
import { useRef, useState } from "react";
66
import { toast } from "sonner";
7+
import { revalidatePathAction } from "@/actions/revalidate";
78
import type { SupportTicket } from "@/api/support";
89
import { sendMessageToTicket } from "@/api/support";
910
import type { Team } from "@/api/team";
1011
import { Badge } from "@/components/ui/badge";
1112
import { Button } from "@/components/ui/button";
1213
import { Textarea } from "@/components/ui/textarea";
1314
import { useDashboardRouter } from "@/lib/DashboardRouter";
15+
import { getStatusColor, getStatusLabel } from "@/lib/support-utils";
1416
import { SupportHeader } from "./SupportHeader";
1517

1618
interface SupportCaseDetailsProps {
@@ -52,6 +54,12 @@ export function SupportCaseDetails({ ticket, team }: SupportCaseDetailsProps) {
5254
toast.success("Reply sent successfully!");
5355
setReplyMessage("");
5456

57+
// Revalidate the cache to fetch the latest messages
58+
await revalidatePathAction(
59+
`/team/${team.slug}/~/support/cases/${ticket.id}`,
60+
"page",
61+
);
62+
5563
// Refresh the page to show the new message
5664
router.refresh();
5765
} catch (error) {
@@ -69,41 +77,6 @@ export function SupportCaseDetails({ ticket, team }: SupportCaseDetailsProps) {
6977
}
7078
};
7179

72-
const getStatusColor = (status: string) => {
73-
switch (status.toLowerCase()) {
74-
case "resolved":
75-
case "closed":
76-
return "border-muted text-muted-foreground bg-muted/10";
77-
case "in_progress":
78-
return "border-destructive text-destructive bg-destructive/10";
79-
case "needs_response":
80-
return "warning";
81-
case "on_hold":
82-
return "border-secondary text-secondary-foreground bg-secondary/10";
83-
default:
84-
return "warning";
85-
}
86-
};
87-
88-
const getStatusLabel = (status: string) => {
89-
const statusLower = status.toLowerCase();
90-
91-
switch (statusLower) {
92-
case "closed":
93-
return "Closed";
94-
case "resolved":
95-
return "Resolved";
96-
case "in_progress":
97-
return "Needs Response";
98-
case "needs_response":
99-
return "In Progress";
100-
case "on_hold":
101-
return "On Hold";
102-
default:
103-
return "In Progress";
104-
}
105-
};
106-
10780
return (
10881
<div className="min-h-screen bg-background text-foreground">
10982
<SupportHeader

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

Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { SupportTicket } from "@/api/support";
66
import type { Team } from "@/api/team";
77
import { Badge } from "@/components/ui/badge";
88
import { useDashboardRouter } from "@/lib/DashboardRouter";
9+
import { getStatusColor, getStatusLabel } from "@/lib/support-utils";
910
import { SupportHeader } from "./SupportHeader";
1011
import { SupportTabs } from "./SupportTabs";
1112

@@ -52,66 +53,29 @@ export default function SupportCasesClient({
5253
return matchesTab && matchesSearch;
5354
});
5455

55-
// Helper function to check if ticket matches search query
56-
const matchesSearch = (ticket: SupportTicket) => {
57-
return (
58-
searchQuery === "" ||
59-
ticket.id.toLowerCase().includes(searchQuery.toLowerCase())
60-
);
61-
};
62-
63-
// Calculate counts for tabs
56+
// Calculate counts for tabs using inline search logic
6457
const counts = {
65-
all: tickets.filter(matchesSearch).length,
58+
all: tickets.filter(
59+
(ticket) =>
60+
searchQuery === "" ||
61+
ticket.id.toLowerCase().includes(searchQuery.toLowerCase()),
62+
).length,
6663
closed: tickets.filter(
6764
(ticket) =>
6865
(ticket.status === "resolved" || ticket.status === "closed") &&
69-
matchesSearch(ticket),
66+
(searchQuery === "" ||
67+
ticket.id.toLowerCase().includes(searchQuery.toLowerCase())),
7068
).length,
7169
open: tickets.filter(
7270
(ticket) =>
7371
((ticket.status as string) === "in_progress" ||
7472
(ticket.status as string) === "needs_response" ||
7573
(ticket.status as string) === "on_hold") &&
76-
matchesSearch(ticket),
74+
(searchQuery === "" ||
75+
ticket.id.toLowerCase().includes(searchQuery.toLowerCase())),
7776
).length,
7877
};
7978

80-
const getStatusColor = (status: string) => {
81-
switch (status.toLowerCase()) {
82-
case "resolved":
83-
case "closed":
84-
return "border-muted text-muted-foreground bg-muted/10";
85-
case "in_progress":
86-
return "border-destructive text-destructive bg-destructive/10";
87-
case "needs_response":
88-
return "warning";
89-
case "on_hold":
90-
return "border-secondary text-secondary-foreground bg-secondary/10";
91-
default:
92-
return "warning";
93-
}
94-
};
95-
96-
const getStatusLabel = (status: string) => {
97-
const statusLower = status.toLowerCase();
98-
99-
switch (statusLower) {
100-
case "closed":
101-
return "Closed";
102-
case "resolved":
103-
return "Resolved";
104-
case "in_progress":
105-
return "Needs Response";
106-
case "needs_response":
107-
return "In Progress";
108-
case "on_hold":
109-
return "On Hold";
110-
default:
111-
return "In Progress";
112-
}
113-
};
114-
11579
const handleSelectCase = (ticketId: string) => {
11680
router.push(`/team/${team.slug}/~/support/cases/${ticketId}`);
11781
};

0 commit comments

Comments
 (0)