Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0797d9e
feat: complete FAQ system with admin dashboard, voting, dark mode, un…
vittaldevak1 May 30, 2026
967a606
chore: remove junk txt files
vittaldevak1 May 30, 2026
e385485
chore: remove all junk files
vittaldevak1 May 30, 2026
624e26e
chore: remove chroma_data from repo, add to gitignore
vittaldevak1 May 30, 2026
686a15b
atlas mongodb, dark mode, admin dashboard, sidebar, voting, duplicate…
vittaldevak1 May 30, 2026
87a44d3
fix unresolved query saving,admin improvements
vittaldevak1 May 30, 2026
48966b8
fix signin
vittaldevak1 May 30, 2026
ba5452f
leaderboard + points system, super_admin and admin
vittaldevak1 May 31, 2026
c218124
feat: real-time notifications via Socket.io, ChromaDB fix, admin alerts
BeldhariSwapna May 31, 2026
7b4a787
feat: answer approval workflow — pending/approved/rejected status, ad…
BeldhariSwapna May 31, 2026
651cfea
feat: answer center with approve/reject, +20/-5 points, question-auth…
BeldhariSwapna May 31, 2026
35a2c7f
fix: colors, ui design, admin roles
vittaldevak1 May 31, 2026
c4e70b5
fix: notification dropdown layering - set top-header z-index to 100
BeldhariSwapna Jun 2, 2026
130a510
fix: hide Raise a Query button for admin/super_admin roles
BeldhariSwapna Jun 2, 2026
c327ea5
fix: notification dropdown use position fixed to avoid stacking conte…
BeldhariSwapna Jun 2, 2026
636b8a1
fix: revert dropdown to absolute positioning with max z-index
BeldhariSwapna Jun 2, 2026
18d41d2
feat: centered styled modal for respond & resolve popup
BeldhariSwapna Jun 2, 2026
49b537e
fix: remove prompt popup, auto-promote query to faq using its content
BeldhariSwapna Jun 2, 2026
7f90a7c
fix: delete query instead of marking resolved on promote to faq
BeldhariSwapna Jun 2, 2026
7665a8c
feat: add resolved queries filter toggle to queries tab
BeldhariSwapna Jun 2, 2026
ba6d5eb
revert: promote now deletes query, remove resolved filter
BeldhariSwapna Jun 2, 2026
4811db2
fix: allow admin role for createFaq, fix deleteQuery super_admin check
BeldhariSwapna Jun 2, 2026
b554572
feat: styled centered toast modal instead of alert
BeldhariSwapna Jun 2, 2026
ae26658
Added hybrid chatbot and FAQ search improvements
vittaldevak1 Jun 2, 2026
81a9816
Merge branch 'main' of https://github.com/BeldhariSwapna/FAQ_SYSTEM1
vittaldevak1 Jun 2, 2026
732f621
fix: leaderboard visible to all authenticated users
BeldhariSwapna Jun 2, 2026
f3eac7e
fix: answer card buttons overflow - add minWidth 0 and wordBreak
BeldhariSwapna Jun 2, 2026
8425d79
fix: min answer 10 chars, styled all popups, styled query page
BeldhariSwapna Jun 2, 2026
095ba33
fix: show own pending answers to author after submission, remove depl…
BeldhariSwapna Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .gitignore
Binary file not shown.
1 change: 0 additions & 1 deletion chroma_err.txt

This file was deleted.

Empty file removed chroma_out.txt
Empty file.
88 changes: 87 additions & 1 deletion client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-hot-toast": "^2.4.1",
"react-router-dom": "^7.0.0"
"react-router-dom": "^7.0.0",
"socket.io-client": "^4.8.3"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.3.1",
Expand Down
54 changes: 35 additions & 19 deletions client/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { Toaster } from 'react-hot-toast';
import { AuthProvider } from './context/AuthContext';
import { SocketProvider } from './context/SocketContext';
import { NotificationProvider } from './context/NotificationContext';
import ProtectedRoute from './components/ProtectedRoute';
import AuthLayout from './components/AuthLayout';
import DashboardLayout from './components/layout/DashboardLayout';
import LoginPage from './pages/LoginPage';
import RegisterPage from './pages/RegisterPage';
import UserPage from './pages/UserPage';
import QueryPage from './pages/QueryPage';
import DashboardHome from './pages/DashboardHome';
import AskQuestion from './pages/AskQuestion';
import MyQuestions from './pages/MyQuestions';
import QuestionDetail from './pages/QuestionDetail';
import AnswerCenter from './pages/AnswerCenter';
import AdminArea from './pages/AdminArea';
import './styles/auth.css';
import Leaderboard from './pages/Leaderboard'

export default function App() {
return (
<BrowserRouter>
<AuthProvider>
<Toaster
<SocketProvider>
<NotificationProvider>
<Toaster
position="top-right"
toastOptions={{
duration: 4000,
Expand All @@ -30,28 +42,32 @@ export default function App() {
}}
/>
<Routes>
{/* Public routes */}
<Route path="/login" element={<AuthLayout><LoginPage /></AuthLayout>} />
<Route path="/register" element={<AuthLayout><RegisterPage /></AuthLayout>} />
<Route
path="/user"
element={
<ProtectedRoute>
<UserPage />
</ProtectedRoute>
}
/>
<Route
path="/query"
element={
<ProtectedRoute>
<QueryPage />
</ProtectedRoute>
}
/>

{/* Standalone pages */}
<Route path="/user" element={<ProtectedRoute><UserPage /></ProtectedRoute>} />
<Route path="/query" element={<ProtectedRoute><QueryPage /></ProtectedRoute>} />

{/* Dashboard layout routes */}
<Route element={<ProtectedRoute><DashboardLayout /></ProtectedRoute>}>
<Route path="/dashboard" element={<DashboardHome />} />
<Route path="/ask-question" element={<AskQuestion />} />
<Route path="/my-questions" element={<MyQuestions />} />
<Route path="/questions/:id" element={<QuestionDetail />} />
<Route path="/answer-center" element={<AnswerCenter />} />
<Route path="/admin" element={<AdminArea />} />
<Route path="/leaderboard" element={<Leaderboard />} />
</Route>

{/* Redirects */}
<Route path="/" element={<Navigate to="/user" replace />} />
<Route path="*" element={<Navigate to="/user" replace />} />
<Route path="*" element={<Navigate to="/dashboard" replace />} />
</Routes>
</NotificationProvider>
</SocketProvider>
</AuthProvider>
</BrowserRouter>
);
}
}
11 changes: 10 additions & 1 deletion client/src/api/searchApi.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import api from './axios';

const suggestionsCache = new Map();
const searchCache = new Map();

export async function searchFAQs(query) {
const key = query.toLowerCase().trim();
if (searchCache.has(key)) return searchCache.get(key);
const { data } = await api.post('/search', { query });
searchCache.set(key, data);
return data;
}

export async function getSuggestions(query) {
const key = query.toLowerCase().trim();
if (suggestionsCache.has(key)) return suggestionsCache.get(key);
const { data } = await api.get(`/search/suggestions?q=${encodeURIComponent(query)}`);
suggestionsCache.set(key, data);
return data;
}

Expand All @@ -18,4 +27,4 @@ export async function askFAQ(query, history = []) {
export async function sendFeedback(faqId, helpful) {
const { data } = await api.post('/faqs/feedback', { faqId, helpful });
return data;
}
}
34 changes: 34 additions & 0 deletions client/src/components/ConfirmModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export default function ConfirmModal({ open, title, message, confirmLabel, cancelLabel, variant, onConfirm, onCancel }) {
if (!open) return null;
return (
<div onClick={onCancel} style={{
position: 'fixed', inset: 0, zIndex: 99999,
background: 'rgba(0,0,0,0.5)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
}}>
<div onClick={e => e.stopPropagation()} style={{
background: 'var(--bg-card)', borderRadius: 'var(--radius-md)',
padding: 28, width: 420, maxWidth: '90vw',
boxShadow: '0 25px 60px rgba(0,0,0,0.3)',
display: 'flex', flexDirection: 'column', gap: 16,
}}>
{title && <h3 style={{ fontSize: 17, fontWeight: 700, margin: 0 }}>{title}</h3>}
<div style={{ fontSize: 14, color: 'var(--text-secondary)', lineHeight: 1.6 }}>{message}</div>
<div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 4 }}>
<button onClick={onCancel} style={{
padding: '9px 20px', borderRadius: 'var(--radius-sm)',
border: '1px solid var(--border)', background: 'transparent',
color: 'var(--text-secondary)', fontSize: 14, fontWeight: 600,
cursor: 'pointer', fontFamily: 'inherit',
}}>{cancelLabel || 'Cancel'}</button>
<button onClick={onConfirm} style={{
padding: '9px 20px', borderRadius: 'var(--radius-sm)', border: 'none',
background: variant === 'danger' ? '#ef4444' : 'var(--accent)',
color: '#fff', fontSize: 14, fontWeight: 600,
cursor: 'pointer', fontFamily: 'inherit',
}}>{confirmLabel || 'Confirm'}</button>
</div>
</div>
</div>
);
}
4 changes: 3 additions & 1 deletion client/src/components/FaqAssistant.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { useState, useRef, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import { searchFAQs } from '../api/searchApi';

export default function FaqAssistant() {
const { user } = useAuth();
const navigate = useNavigate();
const [open, setOpen] = useState(false);
const [query, setQuery] = useState('');
Expand Down Expand Up @@ -103,7 +105,7 @@ export default function FaqAssistant() {
))}
</div>
)}
{msg.noAnswer && (
{msg.noAnswer && user.role !== 'admin' && user.role !== 'super_admin' && (
<button
className="ym-raise-btn"
onClick={() => {
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/GoogleSignInButton.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useRef } from 'react';

const CLIENT_ID = '411209099641-5vc33p4ukqnmoo4h1tuvduc323hhc7jl.apps.googleusercontent.com';
const CLIENT_ID = '595587356763-0pqkro6bjvh86sec3m34pr53ma51nrhh.apps.googleusercontent.com';

export default function GoogleSignInButton({ onSuccess, onError, text = 'Sign in with Google' }) {
const buttonRef = useRef(null);
Expand Down
Loading