diff --git a/apps/web/app/(public)/search/error.tsx b/apps/web/app/(public)/search/error.tsx
new file mode 100644
index 0000000..61d3054
--- /dev/null
+++ b/apps/web/app/(public)/search/error.tsx
@@ -0,0 +1,60 @@
+'use client';
+
+import { useEffect } from 'react';
+
+export default function SearchError({
+ error,
+ reset,
+}: {
+ error: Error & { digest?: string };
+ reset: () => void;
+}) {
+ useEffect(() => {
+ console.error('Search error:', error);
+ }, [error]);
+
+ return (
+
+
+
+
+
Lỗi tìm kiếm
+
+ Không thể thực hiện tìm kiếm. Vui lòng thử lại hoặc thay đổi bộ lọc.
+
+ {error.digest && (
+
Mã lỗi: {error.digest}
+ )}
+
+
+
+
+ );
+}
diff --git a/apps/web/app/(public)/search/loading.tsx b/apps/web/app/(public)/search/loading.tsx
new file mode 100644
index 0000000..7cd33f2
--- /dev/null
+++ b/apps/web/app/(public)/search/loading.tsx
@@ -0,0 +1,72 @@
+export default function SearchLoading() {
+ return (
+
+ {/* Header skeleton */}
+
+
+ {/* View mode toggle skeleton */}
+
+
+ {/* Filter bar skeleton (desktop) */}
+
+
+ {Array.from({ length: 5 }).map((_, i) => (
+
+ ))}
+
+
+
+
+ {/* Content area skeleton */}
+
+ {/* Sidebar skeleton (desktop) */}
+
+
+ {/* Results grid skeleton */}
+
+
+
+ {Array.from({ length: 6 }).map((_, i) => (
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
index 44ce3b0..e31d5b0 100644
--- a/apps/web/app/layout.tsx
+++ b/apps/web/app/layout.tsx
@@ -72,6 +72,12 @@ export default function RootLayout({ children }: { children: React.ReactNode })
return (
+
+ Chuyển đến nội dung chính
+
{children}