feat(pagination): 공통 컨트롤 도입과 사용자 관리 가이드 추가
- 테이블 푸터에서 SuperportPaginationControls를 사용하도록 각 관리 페이지 페이지네이션 로직을 정리 - SuperportPaginationControls 위젯을 추가하고 SuperportTable 푸터를 개선해 페이지 사이즈 선택과 이동 버튼을 분리 - 사용자 등록·계정 관리 요구사항을 문서화한 doc/user_setting.md를 작성하고 AGENTS.md 코멘트 규칙을 업데이트 - flutter analyze를 수행해 빌드 경고가 없음을 확인
This commit is contained in:
@@ -645,10 +645,10 @@ class _InboundPageState extends State<InboundPage> {
|
||||
return records;
|
||||
}
|
||||
|
||||
List<String> _buildRecordRow(InboundRecord record) {
|
||||
List<String> _buildRecordRow(InboundRecord record, int displayIndex) {
|
||||
final primaryItem = record.items.isNotEmpty ? record.items.first : null;
|
||||
return [
|
||||
record.number.split('-').last,
|
||||
displayIndex.toString(),
|
||||
_dateFormatter.format(record.processedAt),
|
||||
record.warehouse,
|
||||
record.transactionNumber,
|
||||
@@ -670,13 +670,15 @@ class _InboundPageState extends State<InboundPage> {
|
||||
DeviceBreakpoint breakpoint,
|
||||
) {
|
||||
final visibleColumns = _visibleColumnsFor(breakpoint);
|
||||
final baseOffset = _rowNumberOffset(records.length);
|
||||
return ShadTable.list(
|
||||
header: [
|
||||
for (final index in visibleColumns)
|
||||
ShadTableCell.header(child: Text(InboundTableSpec.headers[index])),
|
||||
],
|
||||
children: [
|
||||
for (final record in records) _buildTableCells(record, visibleColumns),
|
||||
for (var i = 0; i < records.length; i++)
|
||||
_buildTableCells(records[i], visibleColumns, baseOffset + i + 1),
|
||||
],
|
||||
columnSpanExtent: (index) =>
|
||||
const FixedTableSpanExtent(InboundTableSpec.columnSpanWidth),
|
||||
@@ -718,8 +720,9 @@ class _InboundPageState extends State<InboundPage> {
|
||||
List<ShadTableCell> _buildTableCells(
|
||||
InboundRecord record,
|
||||
List<int> visibleColumns,
|
||||
int displayIndex,
|
||||
) {
|
||||
final values = _buildRecordRow(record);
|
||||
final values = _buildRecordRow(record, displayIndex);
|
||||
return [
|
||||
for (final index in visibleColumns)
|
||||
ShadTableCell(
|
||||
@@ -728,6 +731,16 @@ class _InboundPageState extends State<InboundPage> {
|
||||
];
|
||||
}
|
||||
|
||||
int _rowNumberOffset(int currentCount) {
|
||||
final page = _result?.page ?? _currentPage;
|
||||
final pageSize = _result?.pageSize ?? _pageSize;
|
||||
final safePage = page > 0 ? page : 1;
|
||||
final safePageSize = pageSize > 0
|
||||
? pageSize
|
||||
: (currentCount > 0 ? currentCount : 1);
|
||||
return (safePage - 1) * safePageSize;
|
||||
}
|
||||
|
||||
Future<void> _showDetailDialog(InboundRecord record) async {
|
||||
await showInventoryTransactionDetailDialog<void>(
|
||||
context: context,
|
||||
|
||||
@@ -574,39 +574,46 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
style: theme.textTheme.muted,
|
||||
),
|
||||
)
|
||||
: ShadTable.list(
|
||||
header: OutboundTableSpec.headers
|
||||
.map(
|
||||
(header) =>
|
||||
ShadTableCell.header(child: Text(header)),
|
||||
)
|
||||
.toList(),
|
||||
children: [
|
||||
for (final row in visibleRecords.map(
|
||||
_buildRecordRow,
|
||||
))
|
||||
[
|
||||
for (final value in row)
|
||||
ShadTableCell(
|
||||
child: Text(
|
||||
value,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
: () {
|
||||
final baseOffset = _rowNumberOffset(
|
||||
visibleRecords.length,
|
||||
);
|
||||
return ShadTable.list(
|
||||
header: OutboundTableSpec.headers
|
||||
.map(
|
||||
(header) =>
|
||||
ShadTableCell.header(child: Text(header)),
|
||||
)
|
||||
.toList(),
|
||||
children: [
|
||||
for (var i = 0; i < visibleRecords.length; i++)
|
||||
[
|
||||
for (final value in _buildRecordRow(
|
||||
visibleRecords[i],
|
||||
baseOffset + i + 1,
|
||||
))
|
||||
ShadTableCell(
|
||||
child: Text(
|
||||
value,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
columnSpanExtent: (index) =>
|
||||
const FixedTableSpanExtent(
|
||||
OutboundTableSpec.columnSpanWidth,
|
||||
),
|
||||
rowSpanExtent: (index) => const FixedTableSpanExtent(
|
||||
OutboundTableSpec.rowSpanHeight,
|
||||
),
|
||||
onRowTap: (rowIndex) {
|
||||
final record = visibleRecords[rowIndex];
|
||||
_selectRecord(record, openDetail: true);
|
||||
},
|
||||
),
|
||||
],
|
||||
],
|
||||
columnSpanExtent: (index) =>
|
||||
const FixedTableSpanExtent(
|
||||
OutboundTableSpec.columnSpanWidth,
|
||||
),
|
||||
rowSpanExtent: (index) =>
|
||||
const FixedTableSpanExtent(
|
||||
OutboundTableSpec.rowSpanHeight,
|
||||
),
|
||||
onRowTap: (rowIndex) {
|
||||
final record = visibleRecords[rowIndex];
|
||||
_selectRecord(record, openDetail: true);
|
||||
},
|
||||
);
|
||||
}(),
|
||||
),
|
||||
if (filtered.isNotEmpty) ...[
|
||||
const SizedBox(height: 12),
|
||||
@@ -787,10 +794,10 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
}
|
||||
}
|
||||
|
||||
List<String> _buildRecordRow(OutboundRecord record) {
|
||||
List<String> _buildRecordRow(OutboundRecord record, int displayIndex) {
|
||||
final primaryItem = record.items.isNotEmpty ? record.items.first : null;
|
||||
return [
|
||||
record.number.split('-').last,
|
||||
displayIndex.toString(),
|
||||
_dateFormatter.format(record.processedAt),
|
||||
record.warehouse,
|
||||
record.transactionNumber,
|
||||
@@ -808,6 +815,16 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
];
|
||||
}
|
||||
|
||||
int _rowNumberOffset(int currentCount) {
|
||||
final page = _result?.page ?? _currentPage;
|
||||
final pageSize = _result?.pageSize ?? _pageSize;
|
||||
final safePage = page > 0 ? page : 1;
|
||||
final safePageSize = pageSize > 0
|
||||
? pageSize
|
||||
: (currentCount > 0 ? currentCount : 1);
|
||||
return (safePage - 1) * safePageSize;
|
||||
}
|
||||
|
||||
Future<void> _showDetailDialog(OutboundRecord record) async {
|
||||
await showInventoryTransactionDetailDialog<void>(
|
||||
context: context,
|
||||
|
||||
@@ -522,36 +522,45 @@ class _RentalPageState extends State<RentalPage> {
|
||||
: '대여 데이터가 없습니다.',
|
||||
description: _errorMessage ?? '검색 조건을 조정해 다시 시도하세요.',
|
||||
)
|
||||
: ShadTable.list(
|
||||
header: RentalTableSpec.headers
|
||||
.map(
|
||||
(header) =>
|
||||
ShadTableCell.header(child: Text(header)),
|
||||
)
|
||||
.toList(),
|
||||
children: [
|
||||
for (final record in visibleRecords)
|
||||
_buildRecordRow(record).map(
|
||||
(value) => ShadTableCell(
|
||||
child: Text(
|
||||
value,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
: () {
|
||||
final baseOffset = _rowNumberOffset(
|
||||
visibleRecords.length,
|
||||
);
|
||||
return ShadTable.list(
|
||||
header: RentalTableSpec.headers
|
||||
.map(
|
||||
(header) =>
|
||||
ShadTableCell.header(child: Text(header)),
|
||||
)
|
||||
.toList(),
|
||||
children: [
|
||||
for (var i = 0; i < visibleRecords.length; i++)
|
||||
_buildRecordRow(
|
||||
visibleRecords[i],
|
||||
baseOffset + i + 1,
|
||||
).map(
|
||||
(value) => ShadTableCell(
|
||||
child: Text(
|
||||
value,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
columnSpanExtent: (index) =>
|
||||
const FixedTableSpanExtent(
|
||||
RentalTableSpec.columnSpanWidth,
|
||||
),
|
||||
rowSpanExtent: (index) => const FixedTableSpanExtent(
|
||||
RentalTableSpec.rowSpanHeight,
|
||||
),
|
||||
onRowTap: (rowIndex) {
|
||||
final record = visibleRecords[rowIndex];
|
||||
_selectRecord(record, openDetail: true);
|
||||
},
|
||||
),
|
||||
],
|
||||
columnSpanExtent: (index) =>
|
||||
const FixedTableSpanExtent(
|
||||
RentalTableSpec.columnSpanWidth,
|
||||
),
|
||||
rowSpanExtent: (index) =>
|
||||
const FixedTableSpanExtent(
|
||||
RentalTableSpec.rowSpanHeight,
|
||||
),
|
||||
onRowTap: (rowIndex) {
|
||||
final record = visibleRecords[rowIndex];
|
||||
_selectRecord(record, openDetail: true);
|
||||
},
|
||||
);
|
||||
}(),
|
||||
),
|
||||
if (filtered.isNotEmpty) ...[
|
||||
const SizedBox(height: 12),
|
||||
@@ -747,9 +756,9 @@ class _RentalPageState extends State<RentalPage> {
|
||||
}
|
||||
}
|
||||
|
||||
List<String> _buildRecordRow(RentalRecord record) {
|
||||
List<String> _buildRecordRow(RentalRecord record, int displayIndex) {
|
||||
return [
|
||||
record.number.split('-').last,
|
||||
displayIndex.toString(),
|
||||
_dateFormatter.format(record.processedAt),
|
||||
record.warehouse,
|
||||
record.rentalType,
|
||||
@@ -765,6 +774,16 @@ class _RentalPageState extends State<RentalPage> {
|
||||
];
|
||||
}
|
||||
|
||||
int _rowNumberOffset(int currentCount) {
|
||||
final page = _result?.page ?? _currentPage;
|
||||
final pageSize = _result?.pageSize ?? _pageSize;
|
||||
final safePage = page > 0 ? page : 1;
|
||||
final safePageSize = pageSize > 0
|
||||
? pageSize
|
||||
: (currentCount > 0 ? currentCount : 1);
|
||||
return (safePage - 1) * safePageSize;
|
||||
}
|
||||
|
||||
Future<void> _showDetailDialog(RentalRecord record) async {
|
||||
await showInventoryTransactionDetailDialog<void>(
|
||||
context: context,
|
||||
|
||||
Reference in New Issue
Block a user