enrollment-app/lib/presentation/claims_overview/claims_overview_pdf_layout.dart

164 lines
4.3 KiB
Dart

import 'package:flutter/material.dart';
import 'claims_overview_scope.dart';
/// Horizontal panel row for dashboard tabs; uses fixed widths during PDF capture.
class ClaimsTabPanelRow extends StatelessWidget {
final List<ClaimsTabPanel> panels;
final double gap;
final CrossAxisAlignment crossAxisAlignment;
const ClaimsTabPanelRow({
super.key,
required this.panels,
this.gap = 16,
this.crossAxisAlignment = CrossAxisAlignment.start,
});
@override
Widget build(BuildContext context) {
final laneWidth = ClaimsPdfExportScope.laneWidthOf(context);
final isPdf = ClaimsPdfExportScope.of(context) && laneWidth != null;
if (!isPdf) {
return Row(
crossAxisAlignment: crossAxisAlignment,
children: _withGaps(
panels
.map((p) => Expanded(flex: p.flex, child: p.child))
.toList(),
),
);
}
final totalFlex = panels.fold<int>(0, (sum, p) => sum + p.flex);
final gaps = gap * (panels.length - 1);
final available = laneWidth! - gaps;
return Row(
crossAxisAlignment: crossAxisAlignment,
children: _withGaps(
panels.map((p) {
return SizedBox(
width: available * p.flex / totalFlex,
child: p.child,
);
}).toList(),
),
);
}
List<Widget> _withGaps(List<Widget> children) {
if (children.isEmpty) return const [];
final out = <Widget>[children.first];
for (var i = 1; i < children.length; i++) {
out.add(SizedBox(width: gap));
out.add(children[i]);
}
return out;
}
}
class ClaimsTabPanel {
final int flex;
final Widget child;
const ClaimsTabPanel({required this.flex, required this.child});
}
/// Mini grid for metric tiles inside section cards.
class ClaimsTabMiniGrid extends StatelessWidget {
final List<Widget> items;
final double gap;
final int columns;
const ClaimsTabMiniGrid({
super.key,
required this.items,
this.gap = 8,
this.columns = 2,
});
@override
Widget build(BuildContext context) {
assert(items.length == 3 || items.length == 4);
assert(columns == 2 || (columns == 3 && items.length == 3));
return LayoutBuilder(
builder: (context, constraints) {
final maxW = constraints.maxWidth;
final isPdf = ClaimsPdfExportScope.of(context);
Widget cell(int index, {bool fullWidth = false, int? rowColumns}) {
final child = items[index];
if (isPdf && maxW.isFinite) {
final cols = rowColumns ?? columns;
final width = fullWidth
? maxW
: (maxW - gap * (cols - 1)) / cols;
return SizedBox(width: width, child: child);
}
return Expanded(child: child);
}
if (items.length == 3 && columns == 3) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
cell(0, rowColumns: 3),
SizedBox(width: gap),
cell(1, rowColumns: 3),
SizedBox(width: gap),
cell(2, rowColumns: 3),
],
);
}
if (items.length == 3) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
cell(0),
SizedBox(width: gap),
cell(1),
],
),
SizedBox(height: gap),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [cell(2, fullWidth: true)],
),
],
);
}
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
cell(0),
SizedBox(width: gap),
cell(1),
],
),
SizedBox(height: gap),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
cell(2),
SizedBox(width: gap),
cell(3),
],
),
],
);
},
);
}
}