initial commit

54736fa680
Herwig Birke 4 months ago
parent 27a89e57dd
commit 073ced647c

@ -52,16 +52,32 @@ class _MonthlyViewState extends State<MonthlyView> {
DateTime.sunday: 0,
};
late final ScrollController _hCtrl;
late final ScrollController _vCtrl;
// Scroll-Controller
late final ScrollController _hHeaderCtrl; // Header (nur mitgeführt)
late final ScrollController _hBodyCtrl; // Body (führend)
late final ScrollController _vCtrl; // Body vertikal
bool _syncingH = false;
@override
void initState() {
super.initState();
final now = DateTime.now();
_monthStart = DateTime(now.year, now.month, 1);
_hCtrl = ScrollController();
_hHeaderCtrl = ScrollController();
_hBodyCtrl = ScrollController();
_vCtrl = ScrollController();
// Body scrollt -> Header folgt
_hBodyCtrl.addListener(() {
if (_syncingH) return;
_syncingH = true;
if (_hHeaderCtrl.hasClients) {
_hHeaderCtrl.jumpTo(_hBodyCtrl.offset);
}
_syncingH = false;
});
_client = http.Client();
_bookingApi = BookingApi(client: _client);
_dailyApi = DailyWorkingApi(client: _client);
@ -76,7 +92,8 @@ class _MonthlyViewState extends State<MonthlyView> {
for (final c in _controllers.values) {
c.dispose();
}
_hCtrl.dispose();
_hHeaderCtrl.dispose();
_hBodyCtrl.dispose();
_vCtrl.dispose();
_client.close();
super.dispose();
@ -235,42 +252,34 @@ class _MonthlyViewState extends State<MonthlyView> {
),
),
// FIXIERTE KOPFZEILE
Scrollbar(
controller: _hCtrl,
notificationPredicate: (n) => n.metrics.axis == Axis.horizontal,
thumbVisibility: true,
child: SingleChildScrollView(
controller: _hCtrl,
scrollDirection: Axis.horizontal,
child: ConstrainedBox(
constraints: BoxConstraints(minWidth: _tableMinWidth),
child: DataTableTheme(
data: DataTableThemeData(
headingRowHeight: 30,
columnSpacing: 10,
headingTextStyle: const TextStyle(fontWeight: FontWeight.w700).copyWith(
fontSize: _fontSize,
),
),
child: DataTable(
showCheckboxColumn: false,
columns: headerColumns,
rows: const <DataRow>[],
// FIXIERTE KOPFZEILE (mitgeführt, nicht interaktiv)
SingleChildScrollView(
controller: _hHeaderCtrl,
physics: const NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
child: ConstrainedBox(
constraints: BoxConstraints(minWidth: _tableMinWidth),
child: DataTableTheme(
data: DataTableThemeData(
headingRowHeight: 30,
columnSpacing: 10,
headingTextStyle: const TextStyle(fontWeight: FontWeight.w700).copyWith(
fontSize: _fontSize,
),
),
child: const _HeaderOnlyDataTable(),
),
),
),
// BODY
// BODY (horiz. & vert. Scroll; horizontale Scrollbar hier)
Expanded(
child: Scrollbar(
controller: _hCtrl,
controller: _hBodyCtrl,
notificationPredicate: (n) => n.metrics.axis == Axis.horizontal,
thumbVisibility: true,
child: SingleChildScrollView(
controller: _hCtrl,
controller: _hBodyCtrl,
padding: const EdgeInsets.only(bottom: 16),
scrollDirection: Axis.horizontal,
child: ConstrainedBox(
@ -283,7 +292,7 @@ class _MonthlyViewState extends State<MonthlyView> {
controller: _vCtrl,
child: DataTableTheme(
data: const DataTableThemeData(
headingRowHeight: 0,
headingRowHeight: 0, // Header im Body ausblenden
dataRowMinHeight: 30,
dataRowMaxHeight: 34,
columnSpacing: 10,
@ -498,6 +507,15 @@ class _MonthlyViewState extends State<MonthlyView> {
return cells;
}
// kleines Mono-Text-Widget für Zahlen
Widget _monoSmall(String s) => Text(
s,
style: const TextStyle(
fontSize: _fontSize,
fontFeatures: [FontFeature.tabularFigures()],
),
);
Widget _codeDropdown(int dayIndex, WorkDay day) {
final value = day.code;
final values = <String?>[null, ...kAbsenceCodes];
@ -672,14 +690,6 @@ class _MonthlyViewState extends State<MonthlyView> {
);
}
Widget _monoSmall(String s) => Text(
s,
style: const TextStyle(
fontSize: _fontSize,
fontFeatures: [FontFeature.tabularFigures()],
),
);
TextAlign _toTextAlign(Alignment a) {
if (a == Alignment.centerRight) return TextAlign.right;
if (a == Alignment.centerLeft) return TextAlign.left;
@ -687,6 +697,23 @@ Widget _monoSmall(String s) => Text(
}
}
/// Minimaler Header-Table, damit die Kopfzeile fixiert bleiben kann.
/// Nutzt die gleichen Spalten wie der Body, aber ohne Rows.
class _HeaderOnlyDataTable extends StatelessWidget {
const _HeaderOnlyDataTable();
@override
Widget build(BuildContext context) {
final state = context.findAncestorStateOfType<_MonthlyViewState>()!;
final cols = state._buildColumns();
return DataTable(
showCheckboxColumn: false,
columns: cols,
rows: const <DataRow>[],
);
}
}
class _MonthHeader extends StatelessWidget {
final DateTime month;
final VoidCallback onPrev;

Loading…
Cancel
Save