Files
superport_v2/lib/widgets/components/superport_pagination_controls.dart
JiWoong Sul 9beb161527 feat(pagination): 공통 컨트롤 도입과 사용자 관리 가이드 추가
- 테이블 푸터에서 SuperportPaginationControls를 사용하도록 각 관리 페이지 페이지네이션 로직을 정리

- SuperportPaginationControls 위젯을 추가하고 SuperportTable 푸터를 개선해 페이지 사이즈 선택과 이동 버튼을 분리

- 사용자 등록·계정 관리 요구사항을 문서화한 doc/user_setting.md를 작성하고 AGENTS.md 코멘트 규칙을 업데이트

- flutter analyze를 수행해 빌드 경고가 없음을 확인
2025-10-24 16:24:02 +09:00

99 lines
2.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart' as lucide;
import 'package:shadcn_ui/shadcn_ui.dart';
/// 페이지 이동용 <<, <, >, >> 버튼을 공통 스타일로 제공하는 위젯.
class SuperportPaginationControls extends StatelessWidget {
const SuperportPaginationControls({
super.key,
required this.currentPage,
required this.totalPages,
this.onPageSelected,
this.isBusy = false,
this.size = ShadButtonSize.sm,
this.spacing = 8,
this.mainAxisSize = MainAxisSize.min,
});
/// 현재 선택된 페이지 번호(1-base).
final int currentPage;
/// 전체 페이지 수.
final int totalPages;
/// 페이지 변경 콜백. `null`이면 모든 버튼을 비활성화한다.
final void Function(int page)? onPageSelected;
/// 비동기 작업 중 여부. `true`면 버튼이 비활성화된다.
final bool isBusy;
/// 버튼 크기 옵션.
final ShadButtonSize size;
/// 버튼 간 간격.
final double spacing;
/// 내부 Row의 MainAxisSize.
final MainAxisSize mainAxisSize;
@override
Widget build(BuildContext context) {
final int safeTotal = totalPages <= 0 ? 1 : totalPages;
final int safeCurrent = currentPage < 1
? 1
: (currentPage > safeTotal ? safeTotal : currentPage);
final bool canInteract = onPageSelected != null && !isBusy;
final bool canGoPrev = canInteract && safeCurrent > 1;
final bool canGoNext = canInteract && safeCurrent < safeTotal;
return Row(
mainAxisSize: mainAxisSize,
children: _withSpacing([
_buildButton(
icon: lucide.LucideIcons.chevronsLeft,
enabled: canGoPrev,
onTap: () => onPageSelected?.call(1),
),
_buildButton(
icon: lucide.LucideIcons.chevronLeft,
enabled: canGoPrev,
onTap: () => onPageSelected?.call(safeCurrent - 1),
),
_buildButton(
icon: lucide.LucideIcons.chevronRight,
enabled: canGoNext,
onTap: () => onPageSelected?.call(safeCurrent + 1),
),
_buildButton(
icon: lucide.LucideIcons.chevronsRight,
enabled: canGoNext,
onTap: () => onPageSelected?.call(safeTotal),
),
]),
);
}
List<Widget> _withSpacing(List<Widget> children) {
final result = <Widget>[];
for (var i = 0; i < children.length; i++) {
if (i > 0) {
result.add(SizedBox(width: spacing));
}
result.add(children[i]);
}
return result;
}
Widget _buildButton({
required IconData icon,
required bool enabled,
required VoidCallback onTap,
}) {
return ShadButton.ghost(
size: size,
onPressed: enabled ? onTap : null,
child: Icon(icon, size: 16),
);
}
}