sojorn/sojorn_app/lib/screens/admin/admin_scaffold.dart
2026-02-15 00:33:24 -06:00

161 lines
4.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class AdminScaffold extends StatelessWidget {
final Widget child;
final int selectedIndex;
const AdminScaffold({
super.key,
required this.child,
required this.selectedIndex,
});
static const _routes = [
'/admin',
'/admin/moderation',
'/admin/users',
'/admin/content-tools',
];
static ThemeData _adminTheme() {
const bg = Color(0xFF0B0F1A);
const surface = Color(0xFF121826);
const panel = Color(0xFF0F1626);
const accent = Color(0xFF58A6FF);
const muted = Color(0xFF9AA4BF);
return ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
scaffoldBackgroundColor: bg,
colorScheme: const ColorScheme.dark(
primary: accent,
secondary: Color(0xFF7C3AED),
surface: surface,
onSurface: const Color(0xFFFFFFFF),
error: Color(0xFFE11D48),
),
appBarTheme: const AppBarTheme(
backgroundColor: panel,
elevation: 0,
surfaceTintColor: const Color(0x00000000),
),
cardTheme: CardThemeData(
color: panel,
elevation: 0,
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: const BorderSide(color: Color(0xFF1F2937)),
),
),
dividerTheme: const DividerThemeData(
color: Color(0xFF1F2937),
thickness: 1,
),
textTheme: const TextTheme(
headlineSmall: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w700,
color: const Color(0xFFFFFFFF),
),
titleMedium: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: const Color(0xFFFFFFFF),
),
bodyMedium: TextStyle(
fontSize: 14,
color: Color(0xFFCBD5F5),
),
bodySmall: TextStyle(
fontSize: 12,
color: muted,
),
),
navigationRailTheme: const NavigationRailThemeData(
backgroundColor: panel,
selectedIconTheme: IconThemeData(color: accent),
selectedLabelTextStyle: TextStyle(color: accent),
unselectedIconTheme: IconThemeData(color: muted),
unselectedLabelTextStyle: TextStyle(color: muted),
indicatorColor: Color(0xFF1E293B),
),
dataTableTheme: DataTableThemeData(
headingTextStyle: const TextStyle(
fontWeight: FontWeight.w700,
color: const Color(0xFFFFFFFF),
),
dataTextStyle: const TextStyle(
color: Color(0xFFCBD5F5),
),
headingRowColor: WidgetStateProperty.all(panel),
dividerThickness: 1,
),
);
}
void _onDestinationSelected(BuildContext context, int index) {
if (index < 0 || index >= _routes.length) return;
context.go(_routes[index]);
}
@override
Widget build(BuildContext context) {
return Theme(
data: _adminTheme(),
child: Builder(
builder: (context) {
return LayoutBuilder(
builder: (context, constraints) {
final bool extendedRail = constraints.maxWidth >= 1100;
return Scaffold(
body: SafeArea(
child: Row(
children: [
NavigationRail(
selectedIndex: selectedIndex,
onDestinationSelected: (index) =>
_onDestinationSelected(context, index),
extended: extendedRail,
minWidth: 72,
destinations: const [
NavigationRailDestination(
icon: Icon(Icons.insights),
label: Text('Dashboard'),
),
NavigationRailDestination(
icon: Icon(Icons.policy),
label: Text('Moderation Queue'),
),
NavigationRailDestination(
icon: Icon(Icons.people_alt_outlined),
label: Text('User Base'),
),
NavigationRailDestination(
icon: Icon(Icons.build_circle_outlined),
label: Text('Content Tools'),
),
],
),
const VerticalDivider(width: 1),
Expanded(
child: Container(
color: Theme.of(context).scaffoldBackgroundColor,
child: child,
),
),
],
),
),
);
},
);
},
),
);
}
}