feat(router): add streaming app/loading.tsx skeleton and global app/error.tsx boundary [TASK-108]

This commit is contained in:
parsa aghaei 2026-07-26 14:57:06 +03:30
parent 0f32ec62c1
commit 92d24c1ed9
4 changed files with 55 additions and 6 deletions

View File

@ -102,7 +102,7 @@
"title": "ایجاد لایه‌های loading.tsx و error.tsx استاندارد در Next.js App Router",
"priority": "MEDIUM",
"assigned_role": "05_dev_frontend",
"status": "pending",
"status": "completed",
"max_file_count": 3,
"estimated_minutes": 15,
"dependency_task_ids": [],

View File

@ -5,8 +5,8 @@
"checkpoint": {
"stage": "REFACTORING",
"active_agent": "05_dev_frontend",
"current_ticket_id": "TASK-108",
"sub_step_index": 8,
"current_ticket_id": "TASK-109",
"sub_step_index": 9,
"total_sub_steps": 10
},
"execution_guards": {
@ -16,11 +16,11 @@
"token_usage_total": 0
},
"git_state": {
"active_branch": "feature/TASK-107",
"active_branch": "feature/TASK-108",
"last_healthy_commit": "HEAD"
},
"context_buffer": {
"last_agent_summary": "TASK-107 (Next.js Image component optimization for SafeImage and media galleries) completed and verified."
"last_agent_summary": "TASK-108 (app/loading.tsx and app/error.tsx Boundaries) successfully created and verified."
},
"last_updated": "2026-07-26T14:55:00Z"
"last_updated": "2026-07-26T14:57:00Z"
}

View File

@ -0,0 +1,17 @@
"use client";
import React, { useEffect } from "react";
import { ServerErrorPage } from "../components/ErrorPages";
export default function ErrorBoundary({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
console.error("Global Application Error:", error);
}, [error]);
return <ServerErrorPage onRetry={reset} />;
}

View File

@ -0,0 +1,32 @@
import React from "react";
import { Skeleton } from "../components/Skeleton";
export default function GlobalLoading() {
return (
<div className="min-h-screen bg-medical-gray-50 py-16 px-4 font-vazir" dir="rtl">
<div className="max-w-7xl mx-auto space-y-12">
{/* Header Skeleton */}
<div className="flex flex-col items-center text-center space-y-4">
<Skeleton className="w-48 h-8 rounded-full" />
<Skeleton className="w-96 h-12 rounded-2xl" />
<Skeleton className="w-80 h-6 rounded-xl" />
</div>
{/* Product Cards Grid Skeleton */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{Array.from({ length: 8 }).map((_, i) => (
<div key={i} className="bg-white rounded-3xl p-6 border border-medical-gray-100 space-y-4 shadow-sm">
<Skeleton className="w-full aspect-square rounded-2xl" />
<Skeleton className="w-3/4 h-6 rounded-lg" />
<Skeleton className="w-1/2 h-4 rounded-lg" />
<div className="flex items-center justify-between pt-4 border-t border-medical-gray-50">
<Skeleton className="w-24 h-6 rounded-lg" />
<Skeleton className="w-10 h-10 rounded-full" />
</div>
</div>
))}
</div>
</div>
</div>
);
}