- Add Security room accessible from main navigation - Implement Users list page with DataGrid (fetches from /auth/users) - Implement Groups list page with DataGrid (fetches from /auth/groups) - Move user/group management from Control Room to dedicated Security room - Remove Authentik section from Control Room navigation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
75 lines
2.8 KiB
Dart
75 lines
2.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:tatlock_ui/features/control_room/router.dart';
|
|
import 'package:tatlock_ui/features/security/router.dart';
|
|
import 'package:tatlock_ui/routing/app_router.dart';
|
|
import 'package:tatlock_ui/shared/layouts/widgets/top_header_bar.dart';
|
|
|
|
/// Main application scaffold with top header navigation.
|
|
///
|
|
/// Layout structure per UI_LAYOUT.md:
|
|
/// ```
|
|
/// ┌─────────────────────────────────────────────────────────────────┐
|
|
/// │ HEADER: [Logo] [Room Tabs] [Profile] │
|
|
/// ├─────────────────────────────────────────────────────────────────┤
|
|
/// │ BODY: Room page content (may include room-specific sidebar) │
|
|
/// └─────────────────────────────────────────────────────────────────┘
|
|
/// ```
|
|
class AppScaffold extends StatelessWidget {
|
|
const AppScaffold({super.key, required this.child});
|
|
|
|
final Widget child;
|
|
|
|
// Header height must match TopHeaderBar._headerHeight
|
|
static const double _headerHeight = 56.0;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: Stack(
|
|
children: [
|
|
// Main content area with top padding for header
|
|
Positioned.fill(
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(top: _headerHeight),
|
|
child: child,
|
|
),
|
|
),
|
|
|
|
// Top header overlays content (bulge extends into content area)
|
|
Positioned(
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
child: TopHeaderBar(
|
|
selectedIndex: _selectedIndex(context),
|
|
onRoomSelected: (index) => _onNavSelected(context, index),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
int _selectedIndex(BuildContext context) {
|
|
final location = GoRouterState.of(context).matchedLocation;
|
|
|
|
if (location.startsWith(ControlRoomRoutes.base)) return 1;
|
|
if (location.startsWith(SecurityRoutes.base)) return 2;
|
|
if (location.startsWith(AppRoutes.parlor)) return 3;
|
|
// Settings is no longer in main nav (accessed via Profile dropdown)
|
|
return 0; // Front Hall
|
|
}
|
|
|
|
void _onNavSelected(BuildContext context, int index) {
|
|
final route = switch (index) {
|
|
0 => AppRoutes.frontHall,
|
|
1 => ControlRoomRoutes.containers,
|
|
2 => SecurityRoutes.users,
|
|
3 => AppRoutes.parlor,
|
|
_ => AppRoutes.frontHall,
|
|
};
|
|
context.go(route);
|
|
}
|
|
}
|