Skip to content

Commit f4f8bd3

Browse files
committed
Add loading skeletons for improved user experience in various pages
- Introduced loading skeletons in the Dashboard, Bills, and Proceedings pages to enhance the user experience during data fetching. - Added a new loading component for Bill and Proceeding detail pages to provide visual feedback while content is being loaded. - Updated package.json to include a new script for scraping orders of the day, enhancing data ingestion capabilities.
1 parent dcd9224 commit f4f8bd3

File tree

9 files changed

+820
-33
lines changed

9 files changed

+820
-33
lines changed

app/admin/dashboard/page.tsx

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from "@/components/ui/table";
1313
import { Badge } from "@/components/ui/badge";
1414
import { Progress } from "@/components/ui/progress";
15+
import { Skeleton } from "@/components/ui/skeleton";
1516
import { formatDistanceToNow } from 'date-fns';
1617

1718
type UploadStatus = 'pending' | 'processing' | 'completed' | 'failed';
@@ -30,6 +31,7 @@ interface DocumentUpload {
3031

3132
export default function DashboardPage() {
3233
const [uploads, setUploads] = useState<DocumentUpload[]>([]);
34+
const [loading, setLoading] = useState(false);
3335
const [isAuthorized, setIsAuthorized] = useState(false);
3436
const [password, setPassword] = useState('');
3537
const [error, setError] = useState('');
@@ -58,11 +60,14 @@ export default function DashboardPage() {
5860

5961
const fetchUploads = async () => {
6062
try {
63+
setLoading(true);
6164
const response = await fetch('/api/admin/uploads');
6265
const data = await response.json();
6366
setUploads(data);
6467
} catch (error) {
6568
console.error('Failed to fetch uploads:', error);
69+
} finally {
70+
setLoading(false);
6671
}
6772
};
6873

@@ -141,25 +146,39 @@ export default function DashboardPage() {
141146
</TableRow>
142147
</TableHeader>
143148
<TableBody>
144-
{uploads.map((upload) => (
145-
<TableRow key={upload.id}>
146-
<TableCell className="font-medium">{upload.originalFileName}</TableCell>
147-
<TableCell>{getStatusBadge(upload.status)}</TableCell>
148-
<TableCell>{formatFileSize(upload.fileSize)}</TableCell>
149-
<TableCell>
150-
<Progress value={upload.uploadProgress} className="w-[100px]" />
151-
</TableCell>
152-
<TableCell>
153-
<Progress value={upload.processingProgress} className="w-[100px]" />
154-
</TableCell>
155-
<TableCell>
156-
{formatDistanceToNow(new Date(upload.createdAt), { addSuffix: true })}
157-
</TableCell>
158-
<TableCell className="text-red-500">
159-
{upload.error || '-'}
160-
</TableCell>
161-
</TableRow>
162-
))}
149+
{loading ? (
150+
[...Array(5)].map((_, index) => (
151+
<TableRow key={index}>
152+
<TableCell><Skeleton className="h-4 w-40" /></TableCell>
153+
<TableCell><Skeleton className="h-5 w-20 rounded-full" /></TableCell>
154+
<TableCell><Skeleton className="h-4 w-16" /></TableCell>
155+
<TableCell><Skeleton className="h-3 w-[100px]" /></TableCell>
156+
<TableCell><Skeleton className="h-3 w-[100px]" /></TableCell>
157+
<TableCell><Skeleton className="h-4 w-24" /></TableCell>
158+
<TableCell><Skeleton className="h-4 w-8" /></TableCell>
159+
</TableRow>
160+
))
161+
) : (
162+
uploads.map((upload) => (
163+
<TableRow key={upload.id}>
164+
<TableCell className="font-medium">{upload.originalFileName}</TableCell>
165+
<TableCell>{getStatusBadge(upload.status)}</TableCell>
166+
<TableCell>{formatFileSize(upload.fileSize)}</TableCell>
167+
<TableCell>
168+
<Progress value={upload.uploadProgress} className="w-[100px]" />
169+
</TableCell>
170+
<TableCell>
171+
<Progress value={upload.processingProgress} className="w-[100px]" />
172+
</TableCell>
173+
<TableCell>
174+
{formatDistanceToNow(new Date(upload.createdAt), { addSuffix: true })}
175+
</TableCell>
176+
<TableCell className="text-red-500">
177+
{upload.error || '-'}
178+
</TableCell>
179+
</TableRow>
180+
))
181+
)}
163182
</TableBody>
164183
</Table>
165184
</div>

app/bills/[id]/loading.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Skeleton } from "@/components/ui/skeleton"
2+
3+
export default function BillDetailLoading() {
4+
return (
5+
<div className="container mx-auto py-8">
6+
<div className="mx-auto max-w-3xl">
7+
{/* Title */}
8+
<Skeleton className="mb-6 h-9 w-3/4" />
9+
10+
{/* Status + Passage Date grid */}
11+
<div className="grid grid-cols-2 gap-4 mb-6">
12+
<div>
13+
<Skeleton className="mb-1 h-4 w-12" />
14+
<Skeleton className="h-7 w-20 rounded-full" />
15+
</div>
16+
<div>
17+
<Skeleton className="mb-1 h-4 w-24" />
18+
<Skeleton className="h-5 w-32" />
19+
</div>
20+
</div>
21+
22+
{/* Summary section */}
23+
<div>
24+
<Skeleton className="mb-4 h-7 w-28" />
25+
<div className="space-y-3">
26+
<Skeleton className="h-4 w-full" />
27+
<Skeleton className="h-4 w-full" />
28+
<Skeleton className="h-4 w-5/6" />
29+
<Skeleton className="h-4 w-full" />
30+
<Skeleton className="h-4 w-4/6" />
31+
<Skeleton className="h-4 w-full" />
32+
<Skeleton className="h-4 w-3/4" />
33+
</div>
34+
</div>
35+
</div>
36+
</div>
37+
)
38+
}

app/bills/page.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ export default function BillsPage() {
103103
{loading && (
104104
<div className="grid gap-4">
105105
{[...Array(3)].map((_, index) => (
106-
<Skeleton key={index} className="h-24 w-full rounded-lg" />
106+
<div key={index} className="p-6 rounded-lg border bg-card shadow-sm">
107+
<Skeleton className="mb-2 h-6 w-3/4" />
108+
<Skeleton className="h-5 w-16 rounded-full" />
109+
</div>
107110
))}
108111
</div>
109112
)}

app/proceedings/[id]/loading.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Skeleton } from "@/components/ui/skeleton"
2+
3+
export default function ProceedingDetailLoading() {
4+
return (
5+
<div className="container mx-auto py-8">
6+
<div className="mx-auto max-w-3xl">
7+
{/* Back arrow */}
8+
<Skeleton className="mb-6 h-4 w-4" />
9+
10+
{/* Title + Date */}
11+
<div className="mb-6">
12+
<Skeleton className="mb-2 h-9 w-3/4" />
13+
<Skeleton className="h-5 w-40" />
14+
</div>
15+
16+
{/* Summary section */}
17+
<div>
18+
<Skeleton className="mb-4 h-7 w-28" />
19+
<div className="space-y-3">
20+
<Skeleton className="h-4 w-full" />
21+
<Skeleton className="h-4 w-full" />
22+
<Skeleton className="h-4 w-5/6" />
23+
<Skeleton className="h-4 w-full" />
24+
<Skeleton className="h-4 w-4/6" />
25+
<Skeleton className="h-4 w-full" />
26+
<Skeleton className="h-4 w-3/4" />
27+
</div>
28+
</div>
29+
</div>
30+
</div>
31+
)
32+
}

app/proceedings/page.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,12 @@ export default function ProceedingsPage() {
9494
{loading && (
9595
<div className="space-y-4">
9696
{[...Array(3)].map((_, index) => (
97-
<Skeleton key={index} className="h-16 w-full rounded-lg" />
97+
<div key={index} className="rounded-lg border p-4">
98+
<div className="flex items-center justify-between">
99+
<Skeleton className="h-6 w-2/3" />
100+
<Skeleton className="h-5 w-32" />
101+
</div>
102+
</div>
98103
))}
99104
</div>
100105
)}

app/representatives/[id]/page.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,14 @@ export default function RepresentativeDetailPage({
190190
</CardTitle>
191191
</CardHeader>
192192
<CardContent className="space-y-3">
193-
<div>
194-
<p className="text-sm font-medium text-muted-foreground">Constituency</p>
195-
<p className="text-base">
196-
{representative.constituencyCode}
197-
{representative.constituencyName &&
198-
` - ${representative.constituencyName}`}
199-
</p>
200-
</div>
193+
{representative.constituencyName && (
194+
<div>
195+
<p className="text-sm font-medium text-muted-foreground">Constituency</p>
196+
<p className="text-base">
197+
{representative.constituencyName}
198+
</p>
199+
</div>
200+
)}
201201
{representative.district && (
202202
<div>
203203
<p className="text-sm font-medium text-muted-foreground">District</p>

app/representatives/page.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -366,10 +366,11 @@ export default function RepresentativesPage() {
366366
</div>
367367
<div className="flex-1 min-w-0">
368368
<h3 className="font-semibold leading-tight">{rep.nameClean}</h3>
369-
<p className="text-sm text-muted-foreground">
370-
{rep.constituencyCode}
371-
{rep.constituencyName && ` - ${rep.constituencyName}`}
372-
</p>
369+
{rep.constituencyName && (
370+
<p className="text-sm text-muted-foreground">
371+
{rep.constituencyName}
372+
</p>
373+
)}
373374
<div className="mt-2 flex flex-wrap gap-1">
374375
<Badge variant="secondary">{rep.party}</Badge>
375376
{rep.province && <Badge variant="outline">{rep.province}</Badge>}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"ingest:batch": "tsx scripts/batch-ingest.ts",
2626
"fix-titles": "tsx scripts/fix-document-titles.ts",
2727
"scrape:representatives": "tsx scripts/scrape-representatives.ts",
28+
"scrape:orders": "tsx scripts/scrape-orders-of-the-day.ts",
2829
"download:high-res-images": "tsx scripts/download-high-res-images.ts",
2930
"import:representatives": "tsx scripts/import-representatives.ts",
3031
"generate:embeddings": "tsx scripts/generate-representative-embeddings.ts",

0 commit comments

Comments
 (0)