Skip to content

Commit 4e8decb

Browse files
catomeanclaude
andcommitted
refactor: migrate remaining files to shared LoadingSpinner
Replace inline loading spinners with PageLoading, InlineLoading, and LoadingSpinner components across 10 more files: - app/dashboard/page.tsx - app/documents/page.tsx - app/bots/mine/page.tsx - app/bots/custom/[slug]/page.tsx - app/bots/custom/[slug]/edit/page.tsx - app/infrastructure/page.tsx - app/my-data/page.tsx - app/auth/callback/page.tsx - components/conversations/ConversationList.tsx - components/documents/AddToBotModal.tsx This completes the DRY refactoring for loading spinners. The LoadingSpinner component is now the SSOT for all loading states. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f57bd80 commit 4e8decb

10 files changed

Lines changed: 36 additions & 66 deletions

File tree

app/auth/callback/page.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useSearchParams } from 'next/navigation';
55
import Link from 'next/link';
66
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';
77
import { ROUTES } from '@/lib/routes';
8+
import { LoadingSpinner } from '@/components/shared/LoadingSpinner';
89

910
type CallbackStatus = 'loading' | 'success' | 'error';
1011
type CallbackType = 'signup' | 'recovery' | 'email_change' | 'unknown';
@@ -124,7 +125,9 @@ function AuthCallbackContent() {
124125
<div className="bg-white rounded-xl shadow-lg border border-gray-200 p-8">
125126
{status === 'loading' && (
126127
<div className="text-center">
127-
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4" />
128+
<div className="flex justify-center mb-4">
129+
<LoadingSpinner size="lg" className="h-12 w-12" />
130+
</div>
128131
<h2 className="text-xl font-semibold text-gray-900 mb-2">Verifying...</h2>
129132
<p className="text-gray-600">Please wait while we verify your link.</p>
130133
</div>
@@ -135,7 +138,9 @@ function AuthCallbackContent() {
135138
<div className="text-green-600 text-5xl mb-4"></div>
136139
<h2 className="text-xl font-semibold text-gray-900 mb-2">{getSuccessMessage().title}</h2>
137140
<p className="text-gray-600 mb-6">{getSuccessMessage().description}</p>
138-
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600 mx-auto" />
141+
<div className="flex justify-center">
142+
<LoadingSpinner size="md" />
143+
</div>
139144
</div>
140145
)}
141146

@@ -173,7 +178,9 @@ function LoadingFallback() {
173178
return (
174179
<div className="bg-white rounded-xl shadow-lg border border-gray-200 p-8">
175180
<div className="text-center">
176-
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4" />
181+
<div className="flex justify-center mb-4">
182+
<LoadingSpinner size="lg" className="h-12 w-12" />
183+
</div>
177184
<h2 className="text-xl font-semibold text-gray-900 mb-2">Loading...</h2>
178185
<p className="text-gray-600">Please wait...</p>
179186
</div>

app/bots/custom/[slug]/edit/page.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { useEffect, useState } from 'react';
1111
import Link from 'next/link';
1212
import { useRequireAuth } from '@/lib/auth';
1313
import { botToasts } from '@/lib/toast';
14+
import { PageLoading } from '@/components/shared/LoadingSpinner';
1415
import type { CustomBot } from '@/types/custom-bot';
1516

1617
const ACCENT_COLORS = [
@@ -114,20 +115,8 @@ export default function EditBotPage() {
114115
}
115116
};
116117

117-
if (authLoading || !user) {
118-
return (
119-
<div className="min-h-screen flex items-center justify-center">
120-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
121-
</div>
122-
);
123-
}
124-
125-
if (loading) {
126-
return (
127-
<div className="min-h-screen flex items-center justify-center">
128-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
129-
</div>
130-
);
118+
if (authLoading || !user || loading) {
119+
return <PageLoading />;
131120
}
132121

133122
if (error && !bot) {

app/bots/custom/[slug]/page.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import { useParams, useRouter } from 'next/navigation';
1010
import { useEffect, useState, useRef, useCallback } from 'react';
1111
import type { CustomBot } from '@/types/custom-bot';
12+
import { PageLoading } from '@/components/shared/LoadingSpinner';
1213

1314
interface Message {
1415
id: string;
@@ -199,11 +200,7 @@ export default function CustomBotPage() {
199200
);
200201

201202
if (loading) {
202-
return (
203-
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
204-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
205-
</div>
206-
);
203+
return <PageLoading />;
207204
}
208205

209206
if (error || !bot) {

app/bots/mine/page.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useState, useEffect } from 'react';
44
import Link from 'next/link';
55
import { useRequireAuth } from '@/lib/auth';
66
import { botToasts } from '@/lib/toast';
7+
import { PageLoading, InlineLoading } from '@/components/shared/LoadingSpinner';
78
import type { CustomBotWithStats } from '@/types/custom-bot';
89

910
export default function MyBotsPage() {
@@ -89,11 +90,7 @@ export default function MyBotsPage() {
8990
};
9091

9192
if (authLoading || !user) {
92-
return (
93-
<div className="min-h-screen flex items-center justify-center">
94-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
95-
</div>
96-
);
93+
return <PageLoading />;
9794
}
9895

9996
return (
@@ -123,9 +120,7 @@ export default function MyBotsPage() {
123120

124121
{/* Bots List */}
125122
{loading ? (
126-
<div className="flex justify-center py-12">
127-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
128-
</div>
123+
<InlineLoading className="py-12" />
129124
) : bots.length === 0 ? (
130125
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-12 text-center">
131126
<span className="text-6xl mb-4 block">🤖</span>

app/dashboard/page.tsx

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Link from 'next/link';
55
import type { Route } from 'next';
66
import { useRequireAuth } from '@/lib/auth';
77
import { UserAvatar } from '@/components/shared/UserAvatar';
8+
import { PageLoading, InlineLoading } from '@/components/shared/LoadingSpinner';
89
import { OnboardingChecklist } from '@/components/onboarding';
910
import { DashboardEmptyState } from '@/components/dashboard';
1011
import type { Document } from '@/types/document';
@@ -105,11 +106,7 @@ export default function DashboardPage() {
105106
}, [user]);
106107

107108
if (authLoading || !user) {
108-
return (
109-
<div className="min-h-screen flex items-center justify-center">
110-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
111-
</div>
112-
);
109+
return <PageLoading />;
113110
}
114111

115112
const recentDocuments = documents.slice(0, 3);
@@ -321,9 +318,7 @@ export default function DashboardPage() {
321318
</div>
322319

323320
{loading ? (
324-
<div className="flex justify-center py-8">
325-
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600" />
326-
</div>
321+
<InlineLoading />
327322
) : recentDocuments.length === 0 ? (
328323
<EmptyState
329324
icon={
@@ -373,9 +368,7 @@ export default function DashboardPage() {
373368
</div>
374369

375370
{loading ? (
376-
<div className="flex justify-center py-8">
377-
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600" />
378-
</div>
371+
<InlineLoading />
379372
) : recentBots.length === 0 ? (
380373
<EmptyState
381374
icon={<span className="text-5xl">🤖</span>}

app/documents/page.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useState, useEffect, useRef, useCallback, type FormEvent, type ChangeEv
44
import Link from 'next/link';
55
import { useAuth } from '@/lib/auth';
66
import { documentToasts, conversationToasts } from '@/lib/toast';
7+
import { PageLoading, InlineLoading, LoadingSpinner } from '@/components/shared/LoadingSpinner';
78
import { ConversationList } from '@/components/conversations';
89
import { AddToBotModal } from '@/components/documents';
910
import type { Document } from '@/types/document';
@@ -356,11 +357,7 @@ export default function DocumentsPage() {
356357
};
357358

358359
if (authLoading) {
359-
return (
360-
<div className="min-h-screen flex items-center justify-center">
361-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
362-
</div>
363-
);
360+
return <PageLoading />;
364361
}
365362

366363
if (!user) {
@@ -474,9 +471,7 @@ export default function DocumentsPage() {
474471
<h2 className="text-lg font-semibold text-gray-900 mb-4">Documents</h2>
475472

476473
{loading ? (
477-
<div className="flex justify-center py-8">
478-
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600" />
479-
</div>
474+
<InlineLoading />
480475
) : documents.length === 0 ? (
481476
<div className="text-center py-8 text-gray-500">
482477
<svg
@@ -660,7 +655,7 @@ export default function DocumentsPage() {
660655
{chatLoading && (
661656
<div className="bg-gray-100 p-4 rounded-lg mr-8">
662657
<div className="flex items-center gap-2 text-gray-500">
663-
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-gray-600" />
658+
<LoadingSpinner size="sm" className="border-gray-600" />
664659
Thinking...
665660
</div>
666661
</div>

app/infrastructure/page.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
type StorageId,
1212
type ConnectionStatus,
1313
} from '@/lib/infrastructure';
14+
import { PageLoading } from '@/components/shared/LoadingSpinner';
1415
import { ProviderCard, StorageCard, APIKeyInput } from '@/components/infrastructure';
1516

1617
interface UserSettings {
@@ -170,11 +171,7 @@ export default function InfrastructurePage() {
170171
};
171172

172173
if (authLoading || !user) {
173-
return (
174-
<div className="min-h-screen flex items-center justify-center">
175-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
176-
</div>
177-
);
174+
return <PageLoading />;
178175
}
179176

180177
const selectedProviderData = getProviderById(selectedProvider);

app/my-data/page.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useState, useEffect, useRef, type FormEvent, type ChangeEvent } from 'react';
44
import Link from 'next/link';
55
import { useRequireAuth } from '@/lib/auth';
6+
import { PageLoading, InlineLoading, LoadingSpinner } from '@/components/shared/LoadingSpinner';
67
import type { Document } from '@/types/document';
78

89
interface ChatMessage {
@@ -238,11 +239,7 @@ export default function MyDataPage() {
238239
};
239240

240241
if (authLoading || !user) {
241-
return (
242-
<div className="min-h-screen flex items-center justify-center">
243-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
244-
</div>
245-
);
242+
return <PageLoading />;
246243
}
247244

248245
const readyDocuments = (documents || []).filter((d) => d.status === 'ready');
@@ -360,9 +357,7 @@ export default function MyDataPage() {
360357
<h2 className="text-lg font-semibold text-gray-900 mb-4">Your Documents</h2>
361358

362359
{loading ? (
363-
<div className="flex justify-center py-8">
364-
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600" />
365-
</div>
360+
<InlineLoading />
366361
) : documents.length === 0 ? (
367362
<div className="text-center py-8 text-gray-500">
368363
<svg
@@ -528,7 +523,7 @@ export default function MyDataPage() {
528523
{chatLoading && (
529524
<div className="bg-gray-100 p-4 rounded-lg mr-8">
530525
<div className="flex items-center gap-2 text-gray-500">
531-
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-gray-600" />
526+
<LoadingSpinner size="sm" className="border-gray-600" />
532527
Thinking...
533528
</div>
534529
</div>

components/conversations/ConversationList.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useState, useEffect, useCallback } from 'react';
44
import type { Conversation, ConversationBotType } from '@/types/conversation';
55
import { ConversationItem } from './ConversationItem';
6+
import { LoadingSpinner } from '@/components/shared/LoadingSpinner';
67

78
interface ConversationListProps {
89
botType?: ConversationBotType;
@@ -106,7 +107,7 @@ export const ConversationList = ({
106107
<div className="p-2 max-h-64 overflow-y-auto">
107108
{loading ? (
108109
<div className="flex justify-center py-4">
109-
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-blue-600" />
110+
<LoadingSpinner size="sm" />
110111
</div>
111112
) : conversations.length === 0 ? (
112113
<div className="text-center py-4 text-gray-500 text-sm">

components/documents/AddToBotModal.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { useState, useEffect } from 'react';
44
import { documentToasts } from '@/lib/toast';
5+
import { LoadingSpinner } from '@/components/shared/LoadingSpinner';
56

67
interface Bot {
78
id: string;
@@ -121,7 +122,7 @@ export const AddToBotModal = ({
121122

122123
{loading ? (
123124
<div className="flex items-center justify-center py-8">
124-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
125+
<LoadingSpinner size="lg" />
125126
</div>
126127
) : bots.length === 0 ? (
127128
<div className="text-center py-8">

0 commit comments

Comments
 (0)