Error Feedback Service + friendly error handling across all pages
- Error Feedback Service: POST /api/feedback saves to JSONL, GET with admin token - ErrorFeedback component: warm amber tones, friendly messages, 'Report Issue' button - Replaced ALL red-themed error displays across 15+ pages with ErrorFeedback - Kind classification: network, auth, location, upgrade, default messages - QA test suite v2: 8-layer testing (system, API, render, scenario, edge, mobile, perf, security) - Browser-based visual QA with Playwright (Layer 9)
This commit is contained in:
@@ -8,7 +8,6 @@ import {
|
||||
Crown,
|
||||
Star,
|
||||
Clock,
|
||||
AlertTriangle,
|
||||
CheckCircle,
|
||||
Loader2,
|
||||
Lock,
|
||||
@@ -16,6 +15,7 @@ import {
|
||||
ShieldCheck,
|
||||
Flag,
|
||||
} from "lucide-react";
|
||||
import ErrorFeedback from "@/components/ErrorFeedback";
|
||||
|
||||
interface AuthorInfo {
|
||||
id: string;
|
||||
@@ -206,16 +206,7 @@ export default function ThreadDetailPage() {
|
||||
<p className="text-sm text-gray-500">Loading thread...</p>
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="mx-4 mt-4 bg-red-900/10 border border-red-800/30 rounded-2xl p-6 text-center">
|
||||
<AlertTriangle size={32} className="mx-auto text-red-400 mb-2" />
|
||||
<p className="text-sm text-red-300">{error}</p>
|
||||
<button
|
||||
onClick={() => { fetchThread(); fetchPosts(); }}
|
||||
className="mt-3 text-xs text-[#D4AF37] underline"
|
||||
>
|
||||
Try again
|
||||
</button>
|
||||
</div>
|
||||
<ErrorFeedback error={error} kind="network" onRetry={() => { fetchThread(); fetchPosts(); }} context="thread posts" />
|
||||
) : !thread ? (
|
||||
<div className="mx-4 mt-4 bg-gray-900/40 border border-gray-800/60 rounded-2xl p-6 text-center">
|
||||
<p className="text-sm text-gray-400">Thread not found</p>
|
||||
@@ -384,9 +375,7 @@ export default function ThreadDetailPage() {
|
||||
</div>
|
||||
|
||||
{replyError && (
|
||||
<div className="bg-red-900/10 border border-red-800/30 rounded-xl p-3">
|
||||
<p className="text-xs text-red-300">{replyError}</p>
|
||||
</div>
|
||||
<ErrorFeedback error={replyError} kind="default" onRetry={() => setReplyError(null)} context="reply" />
|
||||
)}
|
||||
</form>
|
||||
)}
|
||||
|
||||
+3
-13
@@ -21,6 +21,7 @@ import {
|
||||
FileText,
|
||||
} from "lucide-react";
|
||||
import PremiumBadge from "@/components/PremiumBadge";
|
||||
import ErrorFeedback from "@/components/ErrorFeedback";
|
||||
|
||||
interface Category {
|
||||
id: string;
|
||||
@@ -375,16 +376,7 @@ export default function ForumPage() {
|
||||
<p className="text-sm text-gray-500">Loading threads...</p>
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="bg-red-900/10 border border-red-800/30 rounded-2xl p-6 text-center">
|
||||
<AlertTriangle size={32} className="mx-auto text-red-400 mb-2" />
|
||||
<p className="text-sm text-red-300">{error}</p>
|
||||
<button
|
||||
onClick={fetchThreads}
|
||||
className="mt-3 text-xs text-[#D4AF37] underline"
|
||||
>
|
||||
Try again
|
||||
</button>
|
||||
</div>
|
||||
<ErrorFeedback error={error} kind="network" onRetry={fetchThreads} context="forum threads" />
|
||||
) : threads.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center py-20">
|
||||
<div className="w-16 h-16 rounded-2xl bg-gray-800/40 flex items-center justify-center mb-4">
|
||||
@@ -624,9 +616,7 @@ export default function ForumPage() {
|
||||
</div>
|
||||
|
||||
{createError && (
|
||||
<div className="bg-red-900/10 border border-red-800/30 rounded-xl p-3">
|
||||
<p className="text-xs text-red-300">{createError}</p>
|
||||
</div>
|
||||
<ErrorFeedback error={createError} kind="default" onRetry={() => setCreateError(null)} context="create thread" />
|
||||
)}
|
||||
|
||||
<div className="flex gap-3 pt-2">
|
||||
|
||||
Reference in New Issue
Block a user