Skip to content

Commit 5b212fb

Browse files
Merge pull request #195 from Jagath-P/jagp
[SPRINT-M25] feature: added feedback stats
2 parents 7869fc3 + 9e4aea9 commit 5b212fb

File tree

4 files changed

+114
-18
lines changed

4 files changed

+114
-18
lines changed

frontend/src/Components/Feedback/FeedbackForm.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { useFeedbackForm } from "../../hooks/useFeedback";
66
const FeedbackForm = () => {
77
const { formData, filteredTargets, updateFormData, submitFeedback } =
88
useFeedbackForm();
9-
109
const feedbackTypes = [
1110
"Suggestion",
1211
"Complaint",
@@ -117,8 +116,10 @@ const FeedbackForm = () => {
117116
<Select
118117
options={filteredTargets}
119118
value={
120-
filteredTargets.find((option) => option.value === formData.target_id) || null
121-
}
119+
filteredTargets.find(
120+
(option) => option.value === formData.target_id,
121+
) || null
122+
}
122123
onChange={handleTargetChange}
123124
isClearable
124125
placeholder="Select target"
Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,82 @@
11
import React from "react";
2-
2+
import { useState, useContext } from "react";
3+
import { AdminContext } from "../../context/AdminContext";
4+
import { useFeedback } from "../../hooks/useFeedback";
5+
import getCurrentTenureRange from "../../utils/getCurrentTenureRange";
36
const FeedbackStats = () => {
4-
return <div>FeedbackStats</div>;
7+
const {
8+
loading,
9+
activeTab,
10+
setActiveTab,
11+
statusFilter,
12+
setStatusFilter,
13+
filteredFeedbacks,
14+
markAsResolved,
15+
} = useFeedback();
16+
const { startDate, endDate, tenureYearString } = getCurrentTenureRange();
17+
const tenureFeedback = filteredFeedbacks.filter((fb) => {
18+
const createdAt = new Date(fb.created_at);
19+
return createdAt >= startDate && createdAt <= endDate;
20+
});
21+
const { isUserLoggedIn } = useContext(AdminContext);
22+
const isStudent = isUserLoggedIn?.role === "STUDENT";
23+
24+
return (
25+
<div className="p-2 flex flex-col items-center justify-center">
26+
<p className="text-xl font-semibold justify-center">Feedback Stats</p>
27+
<p className="text-gray-800 mb-2 ">
28+
Total feedbacks:{" "}
29+
<span className="font-semibold text-blue-600">
30+
{tenureFeedback.length}
31+
</span>
32+
</p>
33+
34+
<p className="text-gray-800 mb-2">
35+
Pending feedbacks:{" "}
36+
<span className="font-semibold text-yellow-600">
37+
{tenureFeedback.filter((fb) => !fb.is_resolved).length}
38+
</span>
39+
</p>
40+
41+
<p className="text-gray-800 mb-2 ">
42+
Total resolved feedbacks:{" "}
43+
<span className="font-semibold text-green-600">
44+
{tenureFeedback.filter((fb) => fb.is_resolved).length}
45+
</span>
46+
</p>
47+
48+
<p className="text-gray-800 mb-2">
49+
Recent feedbacks:{" "}
50+
<span className="font-semibold text-purple-600">
51+
{
52+
tenureFeedback.filter((fb) => {
53+
const now = new Date();
54+
const thirtyDaysAgo = new Date();
55+
thirtyDaysAgo.setDate(now.getDate() - 30);
56+
// Clamp to tenure start boundary
57+
const effectiveStart =
58+
thirtyDaysAgo < startDate ? startDate : thirtyDaysAgo;
59+
const createdAt = new Date(fb.created_at);
60+
return createdAt >= effectiveStart && createdAt <= now;
61+
}).length
62+
}
63+
</span>
64+
</p>
65+
<p className="text-gray-800 mb-2">
66+
Average Rating:{" "}
67+
<span className="font-bold">
68+
{tenureFeedback.filter((fb) => fb.rating).length > 0
69+
? (
70+
tenureFeedback.reduce(
71+
(sum, fb) => (fb.rating ? sum + fb.rating : sum),
72+
0,
73+
) / tenureFeedback.filter((fb) => fb.rating).length
74+
).toFixed(1)
75+
: 0}
76+
</span>
77+
</p>
78+
</div>
79+
);
580
};
681

782
export default FeedbackStats;

frontend/src/hooks/useFeedback.js

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,22 @@ export const useFeedback = () => {
1212
const [statusFilter, setStatusFilter] = useState("All");
1313
const { isUserLoggedIn } = useContext(AdminContext);
1414

15+
const fetchFeedback = async () => {
16+
try {
17+
const res = await api.get(`/api/feedback/view-feedback`);
18+
const sorted = res.data.sort(
19+
(a, b) => new Date(b.created_at) - new Date(a.created_at),
20+
);
21+
setFeedbacks(sorted);
22+
} catch (error) {
23+
console.error("Error fetching feedbacks:", error);
24+
} finally {
25+
setLoading(false);
26+
}
27+
};
28+
1529
// Fetch feedbacks
1630
useEffect(() => {
17-
const fetchFeedback = async () => {
18-
try {
19-
const res = await api.get(`/api/feedback/view-feedback`);
20-
const sorted = res.data.sort(
21-
(a, b) => new Date(b.created_at) - new Date(a.created_at),
22-
);
23-
setFeedbacks(sorted);
24-
} catch (error) {
25-
console.error("Error fetching feedbacks:", error);
26-
} finally {
27-
setLoading(false);
28-
}
29-
};
3031
fetchFeedback();
3132
}, []);
3233

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const getCurrentTenureRange = () => {
2+
const now = new Date();
3+
const current_year = now.getFullYear();
4+
const current_month = now.getMonth(); // months are 0-indexed
5+
6+
let startDate, endDate, tenureYearString;
7+
if (current_month < 3) {
8+
startDate = new Date(current_year - 1, 3, 1);
9+
endDate = new Date(current_year, 2, 31, 23, 59, 59);
10+
tenureYearString = `${current_year - 1}-${current_year}`;
11+
} else {
12+
startDate = new Date(current_year, 3, 1);
13+
endDate = new Date(current_year + 1, 2, 31, 23, 59, 59);
14+
tenureYearString = `${current_year}-${current_year + 1}`;
15+
}
16+
return { startDate, endDate, tenureYearString };
17+
};
18+
19+
module.exports = getCurrentTenureRange;

0 commit comments

Comments
 (0)