Skip to content

Commit 2dd01cb

Browse files
committed
implement the user feedback UI and functionality
1 parent 94ab39f commit 2dd01cb

File tree

2 files changed

+96
-31
lines changed

2 files changed

+96
-31
lines changed

web/src/app/admin/feedback-from-user/FeedbackList.tsx

Lines changed: 92 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,72 @@ import { useEffect, useState } from "react";
44
import DataTable from "react-data-table-component";
55
import { Eye, Trash2 } from "lucide-react";
66

7+
interface ModalProps {
8+
isOpen: boolean;
9+
title: string;
10+
children: React.ReactNode;
11+
onClose: () => void;
12+
onConfirm?: () => void;
13+
confirmText?: string;
14+
confirmVariant?: "danger" | "primary";
15+
}
16+
17+
function Modal({
18+
isOpen,
19+
title,
20+
children,
21+
onClose,
22+
onConfirm,
23+
confirmText = "OK",
24+
confirmVariant = "primary",
25+
}: ModalProps) {
26+
if (!isOpen) return null;
27+
28+
return (
29+
<div
30+
className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm"
31+
onClick={onClose}
32+
>
33+
<div
34+
className="bg-white rounded-2xl shadow-xl w-full max-w-md p-6 animate-fadeIn"
35+
onClick={(e) => e.stopPropagation()}
36+
>
37+
<h2 className="text-lg font-semibold mb-4">{title}</h2>
38+
<div className="mb-6 text-gray-700">{children}</div>
39+
<div className="flex justify-end gap-3">
40+
<button
41+
onClick={onClose}
42+
className="px-4 py-2 rounded-lg border border-gray-300 hover:bg-gray-100"
43+
>
44+
Cancel
45+
</button>
46+
{onConfirm && (
47+
<button
48+
onClick={() => {
49+
onConfirm();
50+
onClose();
51+
}}
52+
className={`px-4 py-2 rounded-lg text-white ${
53+
confirmVariant === "danger"
54+
? "bg-red-600 hover:bg-red-700"
55+
: "bg-blue-600 hover:bg-blue-700"
56+
}`}
57+
>
58+
{confirmText}
59+
</button>
60+
)}
61+
</div>
62+
</div>
63+
</div>
64+
);
65+
}
66+
767
export default function FeedbackList() {
868
const [feedbacks, setFeedbacks]: any = useState([]);
969
const [loading, setLoading] = useState(false);
70+
1071
const [selectedComment, setSelectedComment] = useState<string | null>(null);
72+
const [deleteTarget, setDeleteTarget] = useState<any | null>(null);
1173

1274
const truncate = (text: string, length: number = 50) =>
1375
text.length > length ? `${text.slice(0, length)}...` : text;
@@ -43,6 +105,10 @@ export default function FeedbackList() {
43105
fetchFeedback();
44106
}, []);
45107

108+
const handleDelete = (id: string) => {
109+
setFeedbacks((prev: any) => prev.filter((f: any) => f.id !== id));
110+
};
111+
46112
const columns: any = [
47113
{
48114
name: "ID",
@@ -73,7 +139,7 @@ export default function FeedbackList() {
73139
},
74140
{
75141
name: "Date",
76-
selector: (row: any) => row.date,
142+
selector: (row: any) => new Date(row.date).toUTCString(),
77143
sortable: true,
78144
},
79145
{
@@ -89,9 +155,7 @@ export default function FeedbackList() {
89155
</button>
90156
)}
91157
<button
92-
onClick={() =>
93-
setFeedbacks((prev: any) => prev.filter((f: any) => f.id !== row.id))
94-
}
158+
onClick={() => setDeleteTarget(row)}
95159
className="flex items-center gap-1 px-2 py-1 text-sm border border-red-600 text-red-600 rounded hover:bg-red-50"
96160
>
97161
<Trash2 size={14} /> Delete
@@ -102,7 +166,7 @@ export default function FeedbackList() {
102166
];
103167

104168
return (
105-
<div className="p-6 w-[160vh] bg-white rounded shadow">
169+
<div className="p-6 w-[90rem] bg-white rounded shadow">
106170
<h2 className="text-xl font-semibold mb-6">User Feedback</h2>
107171

108172
<DataTable
@@ -120,33 +184,34 @@ export default function FeedbackList() {
120184
}}
121185
/>
122186

123-
{selectedComment && (
124-
<div
125-
className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center"
126-
onClick={() => setSelectedComment(null)}
127-
>
128-
<div
129-
className="bg-white p-4 rounded shadow max-w-md w-full"
130-
onClick={(e) => e.stopPropagation()}
131-
>
132-
<h3 className="font-semibold mb-2">Full Comment</h3>
133-
<p>{selectedComment}</p>
134-
<button
135-
onClick={() => setSelectedComment(null)}
136-
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded"
137-
>
138-
Close
139-
</button>
140-
</div>
141-
</div>
142-
)}
187+
{/* View Modal */}
188+
<Modal
189+
isOpen={!!selectedComment}
190+
title="Full Comment"
191+
onClose={() => setSelectedComment(null)}
192+
>
193+
<p>{selectedComment}</p>
194+
</Modal>
195+
196+
{/* Delete Confirmation Modal */}
197+
<Modal
198+
isOpen={!!deleteTarget}
199+
title="Delete Feedback"
200+
onClose={() => setDeleteTarget(null)}
201+
onConfirm={() => handleDelete(deleteTarget?.id)}
202+
confirmText="Delete"
203+
confirmVariant="danger"
204+
>
205+
<p>
206+
Are you sure you want to delete this feedback? This action cannot be
207+
undone.
208+
</p>
209+
</Modal>
143210
</div>
144211
);
145-
146212
}
147213

148214

149-
150215
// "use client";
151216

152217
// import { useState } from "react";

web/src/components/admin/ClientLayout.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,10 @@ const collections = (
176176
name: "Document Management",
177177
items: document_management_items(),
178178
},
179-
// {
180-
// name: "Feedback From User",
181-
// items: chat_feedback_from_users(),
182-
// },
179+
{
180+
name: "Feedback From User",
181+
items: chat_feedback_from_users(),
182+
},
183183
{
184184
name: "Custom Assistants",
185185
items: custom_assistants_items(isCurator, enableEnterprise),

0 commit comments

Comments
 (0)