Skip to content

Commit 3f1ce1a

Browse files
author
Marvin Zhang
committed
refactor: update default pagination limit to 20; enhance DevlogList layout and improve loading state handling
1 parent 00c86eb commit 3f1ce1a

File tree

4 files changed

+109
-116
lines changed

4 files changed

+109
-116
lines changed

.husky/pre-commit

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
#!/usr/bin/env sh
2-
. "$(dirname -- "$0")/_/husky.sh"
3-
41
echo "🔍 Running pre-commit validations..."
52

6-
# Run lint-staged for efficient checking of staged files
7-
npx lint-staged
8-
93
# Run custom import pattern validation
104
echo "🔗 Validating import patterns..."
115
npm run validate:imports

packages/web/app/components/common/Pagination.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export function Pagination({
8484
<span className="text-sm text-muted-foreground">Show</span>
8585
<Select
8686
value={limit.toString()}
87+
disabled={disabled}
8788
onValueChange={(value) => onPageSizeChange(parseInt(value))}
8889
>
8990
<SelectTrigger className="w-16">

packages/web/app/components/features/devlogs/DevlogList.tsx

Lines changed: 107 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -218,116 +218,114 @@ export function DevlogList({
218218
const isIndeterminate = selectedRowKeys.length > 0 && selectedRowKeys.length < devlogs.length;
219219

220220
return (
221-
<div className="relative h-full px-6 pb-4">
221+
<div className="relative h-full px-6">
222222
{/* Header with search, filters, and actions - Sticky */}
223-
<div className="sticky top-0 z-20 bg-background border-b py-4">
224-
<div className="flex items-center justify-between">
225-
<div className="font-semibold leading-none tracking-tight">Devlogs</div>
226-
<div className="flex items-center space-x-2">
227-
{/* Batch Operations */}
228-
{selectedRowKeys.length > 0 && (
229-
<>
230-
<span className="text-sm text-muted-foreground whitespace-nowrap">
231-
{selectedRowKeys.length} selected
232-
</span>
233-
<Button
234-
size="sm"
235-
variant="outline"
236-
onClick={() =>
237-
setBatchOperationModal({ visible: true, type: 'update', title: 'Batch Update' })
238-
}
239-
disabled={!onBatchUpdate}
240-
>
241-
<Edit className="h-3 w-3 mr-1" />
242-
Update
243-
</Button>
244-
<Button
245-
size="sm"
246-
variant="destructive"
247-
onClick={() => setDeleteConfirmVisible(true)}
248-
disabled={!onBatchDelete}
249-
>
250-
<Trash2 className="h-3 w-3 mr-1" />
251-
Delete
252-
</Button>
253-
<Button size="sm" variant="ghost" onClick={() => setSelectedRowKeys([])}>
254-
<X className="h-3 w-3" />
255-
</Button>
256-
<div className="h-6 w-px bg-border mx-2" />
257-
</>
258-
)}
223+
<div className="sticky top-0 z-20 bg-background border-b h-16 flex items-center justify-between">
224+
<div className="font-semibold leading-none tracking-tight">Devlogs</div>
225+
<div className="flex items-center space-x-2">
226+
{/* Batch Operations */}
227+
{selectedRowKeys.length > 0 && (
228+
<>
229+
<span className="text-sm text-muted-foreground whitespace-nowrap">
230+
{selectedRowKeys.length} selected
231+
</span>
232+
<Button
233+
size="sm"
234+
variant="outline"
235+
onClick={() =>
236+
setBatchOperationModal({ visible: true, type: 'update', title: 'Batch Update' })
237+
}
238+
disabled={!onBatchUpdate}
239+
>
240+
<Edit className="h-3 w-3 mr-1" />
241+
Update
242+
</Button>
243+
<Button
244+
size="sm"
245+
variant="destructive"
246+
onClick={() => setDeleteConfirmVisible(true)}
247+
disabled={!onBatchDelete}
248+
>
249+
<Trash2 className="h-3 w-3 mr-1" />
250+
Delete
251+
</Button>
252+
<Button size="sm" variant="ghost" onClick={() => setSelectedRowKeys([])}>
253+
<X className="h-3 w-3" />
254+
</Button>
255+
<div className="h-6 w-px bg-border mx-2" />
256+
</>
257+
)}
259258

260-
{/* Search */}
261-
<div className="relative">
262-
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
263-
<Input
264-
placeholder="Search devlogs..."
265-
value={searchText}
266-
onChange={(e) => handleSearch(e.target.value)}
267-
className="pl-8 w-64"
268-
/>
269-
</div>
259+
{/* Search */}
260+
<div className="relative">
261+
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
262+
<Input
263+
placeholder="Search devlogs..."
264+
value={searchText}
265+
onChange={(e) => handleSearch(e.target.value)}
266+
className="pl-8 w-64"
267+
/>
268+
</div>
270269

271-
{/* Status Filter */}
272-
<Select
273-
value={filters?.status?.[0] || 'all'}
274-
onValueChange={(value) =>
275-
handleFilterChange('status', value === 'all' ? undefined : value)
276-
}
277-
>
278-
<SelectTrigger className="w-32">
279-
<SelectValue placeholder="Status" />
280-
</SelectTrigger>
281-
<SelectContent>
282-
<SelectItem value="all">All Status</SelectItem>
283-
{statusOptions.map((option) => (
284-
<SelectItem key={option.value} value={option.value}>
285-
{option.label}
286-
</SelectItem>
287-
))}
288-
</SelectContent>
289-
</Select>
270+
{/* Status Filter */}
271+
<Select
272+
value={filters?.status?.[0] || 'all'}
273+
onValueChange={(value) =>
274+
handleFilterChange('status', value === 'all' ? undefined : value)
275+
}
276+
>
277+
<SelectTrigger className="w-32">
278+
<SelectValue placeholder="Status" />
279+
</SelectTrigger>
280+
<SelectContent>
281+
<SelectItem value="all">All Status</SelectItem>
282+
{statusOptions.map((option) => (
283+
<SelectItem key={option.value} value={option.value}>
284+
{option.label}
285+
</SelectItem>
286+
))}
287+
</SelectContent>
288+
</Select>
290289

291-
{/* Priority Filter */}
292-
<Select
293-
value={filters?.priority?.[0] || 'all'}
294-
onValueChange={(value) =>
295-
handleFilterChange('priority', value === 'all' ? undefined : value)
296-
}
297-
>
298-
<SelectTrigger className="w-32">
299-
<SelectValue placeholder="Priority" />
300-
</SelectTrigger>
301-
<SelectContent>
302-
<SelectItem value="all">All Priority</SelectItem>
303-
{priorityOptions.map((option) => (
304-
<SelectItem key={option.value} value={option.value}>
305-
{option.label}
306-
</SelectItem>
307-
))}
308-
</SelectContent>
309-
</Select>
290+
{/* Priority Filter */}
291+
<Select
292+
value={filters?.priority?.[0] || 'all'}
293+
onValueChange={(value) =>
294+
handleFilterChange('priority', value === 'all' ? undefined : value)
295+
}
296+
>
297+
<SelectTrigger className="w-32">
298+
<SelectValue placeholder="Priority" />
299+
</SelectTrigger>
300+
<SelectContent>
301+
<SelectItem value="all">All Priority</SelectItem>
302+
{priorityOptions.map((option) => (
303+
<SelectItem key={option.value} value={option.value}>
304+
{option.label}
305+
</SelectItem>
306+
))}
307+
</SelectContent>
308+
</Select>
310309

311-
{/* Type Filter */}
312-
<Select
313-
value={filters?.type?.[0] || 'all'}
314-
onValueChange={(value) =>
315-
handleFilterChange('type', value === 'all' ? undefined : value)
316-
}
317-
>
318-
<SelectTrigger className="w-32">
319-
<SelectValue placeholder="Type" />
320-
</SelectTrigger>
321-
<SelectContent>
322-
<SelectItem value="all">All Types</SelectItem>
323-
{typeOptions.map((option) => (
324-
<SelectItem key={option.value} value={option.value}>
325-
{option.label}
326-
</SelectItem>
327-
))}
328-
</SelectContent>
329-
</Select>
330-
</div>
310+
{/* Type Filter */}
311+
<Select
312+
value={filters?.type?.[0] || 'all'}
313+
onValueChange={(value) =>
314+
handleFilterChange('type', value === 'all' ? undefined : value)
315+
}
316+
>
317+
<SelectTrigger className="w-32">
318+
<SelectValue placeholder="Type" />
319+
</SelectTrigger>
320+
<SelectContent>
321+
<SelectItem value="all">All Types</SelectItem>
322+
{typeOptions.map((option) => (
323+
<SelectItem key={option.value} value={option.value}>
324+
{option.label}
325+
</SelectItem>
326+
))}
327+
</SelectContent>
328+
</Select>
331329
</div>
332330
</div>
333331

@@ -337,8 +335,8 @@ export function DevlogList({
337335
<p className="text-muted-foreground mb-4">No devlogs found</p>
338336
</div>
339337
) : (
340-
<div className="h-[calc(100vh-7rem)] overflow-y-auto">
341-
<Table>
338+
<div className={`h-[calc(100%-4rem)] ${loading ? 'overflow-y-hidden' : 'overflow-y-auto'}`}>
339+
<Table className="h-[calc(100%-3rem)]">
342340
<TableHeader className="sticky top-0 z-10 bg-background after:absolute after:left-0 after:right-0 after:bottom-0 after:h-px after:bg-border">
343341
<TableRow>
344342
<TableHead className="w-12">
@@ -364,9 +362,9 @@ export function DevlogList({
364362
<TableHead className="w-32">Actions</TableHead>
365363
</TableRow>
366364
</TableHeader>
367-
<TableBody>
365+
<TableBody className="min-h-[calc(100%-6rem)]">
368366
{loading
369-
? Array.from({ length: 12 }).map((_, i) => (
367+
? Array.from({ length: 20 }).map((_, i) => (
370368
<TableRow key={`skeleton-${i}`}>
371369
<TableCell>
372370
<Skeleton className="w-4 h-4" />

packages/web/app/stores/base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export function getDefaultTableDataContext<T, F>(): TableDataContext<T, F> {
3232
export function getDefaultPagination(): PaginationMeta {
3333
return {
3434
page: 1,
35-
limit: 10,
35+
limit: 20,
3636
};
3737
}
3838

0 commit comments

Comments
 (0)