Files
superport/lib/screens/common/widgets/standard_action_bar.dart

236 lines
6.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:superport/screens/common/theme_shadcn.dart';
import 'package:superport/screens/common/components/shadcn_components.dart';
/// 표준 액션바 위젯
///
/// 모든 리스트 화면에서 일관된 액션 버튼 배치와 상태 표시 제공
class StandardActionBar extends StatelessWidget {
final List<Widget> leftActions; // 왼쪽 액션 버튼들
final List<Widget> rightActions; // 오른쪽 액션 버튼들
final int? selectedCount; // 선택된 항목 수
final int totalCount; // 전체 항목 수
final VoidCallback? onRefresh; // 새로고침 콜백
final String? statusMessage; // 추가 상태 메시지
const StandardActionBar({
super.key,
this.leftActions = const [],
this.rightActions = const [],
this.selectedCount,
required this.totalCount,
this.onRefresh,
this.statusMessage,
});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 왼쪽 액션 버튼들
Row(
children: [
...leftActions.map((action) => Padding(
padding: const EdgeInsets.only(right: ShadcnTheme.spacing2),
child: action,
)),
],
),
// 오른쪽 상태 표시 및 액션들
Row(
children: [
// 추가 상태 메시지 (작은 글자 크기로 통일)
if (statusMessage != null) ...[
Text(statusMessage!, style: ShadcnTheme.bodySmall),
const SizedBox(width: ShadcnTheme.spacing3),
],
// 선택된 항목 수 표시
if (selectedCount != null && selectedCount! > 0) ...[
Container(
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 16,
),
decoration: BoxDecoration(
color: ShadcnTheme.primary.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(ShadcnTheme.radiusSm),
border: Border.all(color: ShadcnTheme.primary.withValues(alpha: 0.3)),
),
child: Text(
'$selectedCount개 선택됨',
style: TextStyle(
fontWeight: FontWeight.bold,
color: ShadcnTheme.primary,
),
),
),
const SizedBox(width: ShadcnTheme.spacing3),
],
// 전체 항목 수 표시 (statusMessage에 "총 X개"가 없을 때만 표시)
if (statusMessage == null || !statusMessage!.contains(''))
Container(
padding: const EdgeInsets.symmetric(
vertical: 6,
horizontal: 12,
),
decoration: BoxDecoration(
color: ShadcnTheme.muted.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(ShadcnTheme.radiusSm),
),
child: Text(
'$totalCount개',
style: ShadcnTheme.bodySmall,
),
),
// 새로고침 버튼
if (onRefresh != null) ...[
const SizedBox(width: ShadcnTheme.spacing3),
IconButton(
icon: const Icon(Icons.refresh),
onPressed: onRefresh,
tooltip: '새로고침',
iconSize: 20,
),
],
// 오른쪽 액션 버튼들
...rightActions.map((action) => Padding(
padding: const EdgeInsets.only(left: ShadcnTheme.spacing2),
child: action,
)),
],
),
],
);
}
}
/// 표준 액션 버튼 그룹
class StandardActionButtons {
/// 추가 버튼
static Widget addButton({
required String text,
required VoidCallback onPressed,
IconData icon = Icons.add,
}) {
return ShadcnButton(
text: text,
onPressed: onPressed,
variant: ShadcnButtonVariant.primary,
textColor: Colors.white,
icon: Icon(icon, size: 16),
);
}
/// 삭제 버튼
static Widget deleteButton({
required VoidCallback? onPressed,
bool enabled = true,
String text = '삭제',
}) {
return ShadcnButton(
text: text,
onPressed: enabled ? onPressed : null,
variant: enabled
? ShadcnButtonVariant.destructive
: ShadcnButtonVariant.secondary,
icon: const Icon(Icons.delete, size: 16),
);
}
/// 엑셀 내보내기 버튼
static Widget exportButton({
required VoidCallback onPressed,
String text = '엑셀 내보내기',
}) {
return ShadcnButton(
text: text,
onPressed: onPressed,
variant: ShadcnButtonVariant.secondary,
icon: const Icon(Icons.download, size: 16),
);
}
/// 엑셀 가져오기 버튼
static Widget importButton({
required VoidCallback onPressed,
String text = '엑셀 가져오기',
}) {
return ShadcnButton(
text: text,
onPressed: onPressed,
variant: ShadcnButtonVariant.secondary,
icon: const Icon(Icons.upload, size: 16),
);
}
/// 새로고침 버튼
static Widget refreshButton({
required VoidCallback onPressed,
String text = '새로고침',
}) {
return ShadcnButton(
text: text,
onPressed: onPressed,
variant: ShadcnButtonVariant.secondary,
icon: const Icon(Icons.refresh, size: 16),
);
}
/// 필터 초기화 버튼
static Widget clearFiltersButton({
required VoidCallback onPressed,
String text = '필터 초기화',
}) {
return ShadcnButton(
text: text,
onPressed: onPressed,
variant: ShadcnButtonVariant.ghost,
icon: const Icon(Icons.clear_all, size: 16),
);
}
}
/// 표준 필터 드롭다운
class StandardFilterDropdown<T> extends StatelessWidget {
final T value;
final List<DropdownMenuItem<T>> items;
final ValueChanged<T?> onChanged;
final String? hint;
const StandardFilterDropdown({
super.key,
required this.value,
required this.items,
required this.onChanged,
this.hint,
});
@override
Widget build(BuildContext context) {
return Container(
height: 40,
padding: const EdgeInsets.symmetric(horizontal: 12),
decoration: BoxDecoration(
color: ShadcnTheme.card,
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.circular(ShadcnTheme.radiusMd),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<T>(
value: value,
items: items,
onChanged: onChanged,
hint: hint != null ? Text(hint!) : null,
style: ShadcnTheme.bodySmall,
icon: const Icon(Icons.arrow_drop_down, size: 20),
),
),
);
}
}