Skip to content

Commit 839c00a

Browse files
committed
feat: implement GitHub Issues-based feedback system
1 parent e40a68f commit 839c00a

File tree

3 files changed

+419
-183
lines changed

3 files changed

+419
-183
lines changed

src/components/FeedbackForm.tsx

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import { useState } from "react";
2+
3+
type FeedbackFormProps = {
4+
lessonName: string;
5+
};
6+
7+
export default function FeedbackForm({ lessonName }: FeedbackFormProps) {
8+
const [feedbackType, setFeedbackType] = useState("bug");
9+
const [description, setDescription] = useState("");
10+
const [loading, setLoading] = useState(false);
11+
const [message, setMessage] = useState<string | null>(null);
12+
const [error, setError] = useState<string | null>(null);
13+
14+
const handleSubmit = async (e: React.FormEvent) => {
15+
e.preventDefault();
16+
setLoading(true);
17+
setMessage(null);
18+
setError(null);
19+
20+
try {
21+
const res = await fetch("/api/feedback", {
22+
method: "POST",
23+
headers: { "Content-Type": "application/json" },
24+
body: JSON.stringify({
25+
lessonName,
26+
feedbackType,
27+
description
28+
})
29+
});
30+
31+
const data = await res.json();
32+
if (!res.ok) throw new Error(data.error || "Submission failed");
33+
34+
setMessage("✅ Feedback submitted successfully!");
35+
setDescription("");
36+
} catch (err: any) {
37+
setError(err.message || "Failed to submit feedback");
38+
} finally {
39+
setLoading(false);
40+
}
41+
};
42+
43+
return (
44+
<form onSubmit={handleSubmit}>
45+
<h3 style={{ marginBottom: "1rem", color: "#fff" }}>
46+
Lesson Feedback
47+
</h3>
48+
49+
{/* Lesson */}
50+
<div style={{ marginBottom: "0.75rem" }}>
51+
<label style={labelStyle}>Lesson</label>
52+
<input
53+
type="text"
54+
value={lessonName}
55+
readOnly
56+
style={inputStyle}
57+
/>
58+
</div>
59+
60+
{/* Type */}
61+
<div style={{ marginBottom: "0.75rem" }}>
62+
<label style={labelStyle}>Feedback Type</label>
63+
<select
64+
value={feedbackType}
65+
onChange={(e) => setFeedbackType(e.target.value)}
66+
style={inputStyle}
67+
>
68+
<option value="bug">Bug</option>
69+
<option value="suggestion">Suggestion</option>
70+
<option value="content-quality">Content Quality</option>
71+
</select>
72+
</div>
73+
74+
{/* Description */}
75+
<div style={{ marginBottom: "1rem" }}>
76+
<label style={labelStyle}>Description</label>
77+
<textarea
78+
required
79+
rows={4}
80+
value={description}
81+
onChange={(e) => setDescription(e.target.value)}
82+
style={{ ...inputStyle, resize: "vertical" }}
83+
/>
84+
</div>
85+
86+
{/* Submit */}
87+
<button
88+
type="submit"
89+
disabled={loading}
90+
style={{
91+
padding: "0.5rem 1.25rem",
92+
borderRadius: "8px",
93+
border: "none",
94+
background: loading ? "#4B5563" : "#1295D8",
95+
color: "#fff",
96+
fontWeight: 600,
97+
cursor: loading ? "not-allowed" : "pointer"
98+
}}
99+
>
100+
{loading ? "Submitting..." : "Submit Feedback"}
101+
</button>
102+
103+
{/* Messages */}
104+
{message && (
105+
<p style={{ marginTop: "0.75rem", color: "#22C55E" }}>
106+
{message}
107+
</p>
108+
)}
109+
{error && (
110+
<p style={{ marginTop: "0.75rem", color: "#EF4444" }}>
111+
{error}
112+
</p>
113+
)}
114+
</form>
115+
);
116+
}
117+
118+
const labelStyle = {
119+
display: "block",
120+
marginBottom: "0.25rem",
121+
fontSize: "0.85rem",
122+
color: "#CBD5E1"
123+
};
124+
125+
const inputStyle = {
126+
width: "100%",
127+
padding: "0.45rem 0.6rem",
128+
borderRadius: "6px",
129+
border: "1px solid #374151",
130+
background: "#111827",
131+
color: "#F9FAFB",
132+
fontSize: "0.9rem"
133+
};

0 commit comments

Comments
 (0)