diff --git a/client/src/Style/UserDashboard.css b/client/src/Style/UserDashboard.css
index 835646c..4cf9454 100644
--- a/client/src/Style/UserDashboard.css
+++ b/client/src/Style/UserDashboard.css
@@ -1114,4 +1114,89 @@ input:checked + .slider:before {
flex-direction: column;
gap: 10px;
}
-}
\ No newline at end of file
+}
+/* ===============================
+ ADMIN FEEDBACK TABLE FIX
+ =============================== */
+
+.table-wrapper {
+ width: 100%;
+ overflow-x: auto;
+ margin-top: 20px;
+}
+
+.admin-table {
+ width: 100%;
+ border-collapse: collapse;
+ background: #0f0f14;
+ color: #ffffff;
+ border: 1px solid rgba(255, 255, 255, 0.25);
+ table-layout: fixed;
+}
+
+/* Table Head */
+.admin-table thead th {
+ background: #161622;
+ color: #ffffff;
+ font-weight: 600;
+ padding: 14px 16px;
+ border: 1px solid rgba(255, 255, 255, 0.25);
+ text-align: left;
+ white-space: nowrap;
+}
+
+/* Table Body */
+.admin-table tbody td {
+ padding: 14px 16px;
+ border: 1px solid rgba(255, 255, 255, 0.18);
+ vertical-align: top;
+ word-wrap: break-word;
+ font-size: 14px;
+}
+
+/* Row hover */
+.admin-table tbody tr:hover {
+ background: rgba(255, 255, 255, 0.05);
+}
+
+/* Column width control */
+.admin-table th:nth-child(1),
+.admin-table td:nth-child(1) {
+ width: 15%;
+}
+
+.admin-table th:nth-child(2),
+.admin-table td:nth-child(2) {
+ width: 22%;
+}
+
+.admin-table th:nth-child(3),
+.admin-table td:nth-child(3) {
+ width: 33%;
+}
+
+.admin-table th:nth-child(4),
+.admin-table td:nth-child(4) {
+ width: 18%;
+}
+
+.admin-table th:nth-child(5),
+.admin-table td:nth-child(5) {
+ width: 12%;
+ text-align: center;
+}
+
+/* Delete button */
+.btn-danger {
+ background: #e63946;
+ color: #fff;
+ border: none;
+ padding: 6px 14px;
+ border-radius: 6px;
+ cursor: pointer;
+ font-size: 13px;
+}
+
+.btn-danger:hover {
+ background: #d62828;
+}
diff --git a/client/src/components/Dashboard/DashboardSidebar.jsx b/client/src/components/Dashboard/DashboardSidebar.jsx
index 4ac8721..0e93ba9 100644
--- a/client/src/components/Dashboard/DashboardSidebar.jsx
+++ b/client/src/components/Dashboard/DashboardSidebar.jsx
@@ -86,6 +86,14 @@ const DashboardSidebar = ({
{!sidebarCollapsed && Settings}
+
{/* Quick Links Section */}
diff --git a/client/src/components/Dashboard/FeedbackTab.jsx b/client/src/components/Dashboard/FeedbackTab.jsx
new file mode 100644
index 0000000..b0d2c2b
--- /dev/null
+++ b/client/src/components/Dashboard/FeedbackTab.jsx
@@ -0,0 +1,91 @@
+import React, { useEffect, useState } from 'react';
+import { collection, getDocs, deleteDoc, doc } from 'firebase/firestore';
+import { db } from '../../firebase';
+import '../../Style/UserDashboard.css';
+
+const FeedbackTab = () => {
+ const [feedbackList, setFeedbackList] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ const fetchFeedback = async () => {
+ try {
+ const querySnapshot = await getDocs(collection(db, 'feedback'));
+ const feedbackData = querySnapshot.docs.map((docSnap) => ({
+ id: docSnap.id,
+ ...docSnap.data(),
+ }));
+ setFeedbackList(feedbackData);
+ } catch (error) {
+ console.error('Error fetching feedback:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ fetchFeedback();
+ }, []);
+
+ const handleDelete = async (id) => {
+ const confirmDelete = window.confirm('Are you sure you want to delete this feedback?');
+ if (!confirmDelete) return;
+
+ try {
+ await deleteDoc(doc(db, 'feedback', id));
+ setFeedbackList((prev) => prev.filter((item) => item.id !== id));
+ } catch (error) {
+ console.error('Error deleting feedback:', error);
+ alert('Failed to delete feedback. Please try again.');
+ }
+ };
+
+ return (
+
+
User Feedback
+
+ {loading ? (
+
Loading feedback...
+ ) : feedbackList.length === 0 ? (
+
No feedback submitted yet.
+ ) : (
+
+
+
+
+ | User |
+ Email |
+ Message |
+ Date |
+ Action |
+
+
+
+ {feedbackList.map((feedback) => (
+
+ | {feedback.name || 'Anonymous'} |
+ {feedback.email || '-'} |
+ {feedback.message} |
+
+ {feedback.createdAt?.seconds
+ ? new Date(feedback.createdAt.seconds * 1000).toLocaleString()
+ : '-'}
+ |
+
+
+ |
+
+ ))}
+
+
+
+ )}
+
+ );
+};
+
+export default FeedbackTab;
diff --git a/client/src/components/UserDashboard.jsx b/client/src/components/UserDashboard.jsx
index 5636e8b..7f6ab33 100644
--- a/client/src/components/UserDashboard.jsx
+++ b/client/src/components/UserDashboard.jsx
@@ -18,6 +18,7 @@ import OverviewTab from './Dashboard/OverviewTab';
import SnippetsTab from './Dashboard/SnippetsTab';
import AchievementsTab from './Dashboard/AchievementsTab';
import SettingsTab from './Dashboard/SettingsTab';
+import FeedbackTab from './Dashboard/FeedbackTab';
/**
* UserDashboard Component - Comprehensive User Dashboard
@@ -332,6 +333,9 @@ const UserDashboard = () => {
identityLabel={identityLabel}
/>
)}
+ {activeTab === 'feedback' && (
+
+ )}
{/* Placeholder for other tabs */}
{activeTab === 'coding-stats' && (
diff --git a/client/src/firebase.js b/client/src/firebase.js
index abe0185..0c25cc4 100644
--- a/client/src/firebase.js
+++ b/client/src/firebase.js
@@ -1,5 +1,6 @@
// src/firebase.js
import { initializeApp, getApps } from "firebase/app";
+import { getFirestore } from "firebase/firestore";
import {
getAuth,
GoogleAuthProvider,
@@ -34,6 +35,7 @@ const isFirebaseConfigured = () => {
*/
let app = null;
let auth = null;
+let db = null;
let googleProvider = null;
let githubProvider = null;
@@ -41,6 +43,7 @@ try {
if (isFirebaseConfigured()) {
app = getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0];
auth = getAuth(app);
+ db = getFirestore(app);
googleProvider = new GoogleAuthProvider();
githubProvider = new GithubAuthProvider();
googleProvider.setCustomParameters({ prompt: "select_account" });
@@ -53,6 +56,7 @@ try {
export {
app,
auth,
+ db,
googleProvider,
githubProvider,
-};
+};
\ No newline at end of file