190 lines
7.3 KiB
Dart
190 lines
7.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'dart:math';
|
|
import 'admin_post_screen.dart';
|
|
import 'admin_music_screen.dart';
|
|
import 'admin_users_screen.dart';
|
|
import 'admin_artifact_screen.dart';
|
|
import 'admin_event_screen.dart';
|
|
import 'admin_requests_view.dart'; // NEW IMPORT
|
|
|
|
class AdminDashboardView extends StatelessWidget {
|
|
const AdminDashboardView({super.key});
|
|
static const Color terminalGreen = Color(0xFFE87D25);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Colors.black,
|
|
appBar: AppBar(
|
|
title: const Text("SYSTEM_ADMIN_CORE"),
|
|
centerTitle: true,
|
|
leading: IconButton(
|
|
icon: const Icon(Icons.arrow_back_ios, size: 16),
|
|
onPressed: () => Navigator.pop(context),
|
|
),
|
|
),
|
|
body: Padding(
|
|
padding: const EdgeInsets.all(20.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text("ROOT_ACCESS: ENABLED",
|
|
style: TextStyle(fontSize: 12, color: terminalGreen, letterSpacing: 2)),
|
|
const Text("SELECT_MODULE_TO_INITIALIZE:",
|
|
style: TextStyle(color: Colors.white24, fontSize: 10)),
|
|
const SizedBox(height: 30),
|
|
|
|
Expanded(
|
|
child: GridView.count(
|
|
crossAxisCount: 2,
|
|
crossAxisSpacing: 15,
|
|
mainAxisSpacing: 15,
|
|
children: [
|
|
_buildAdminTile(context, "BROADCAST_LOG", Icons.radar, Colors.red,
|
|
() => Navigator.push(context, MaterialPageRoute(builder: (context) => const AdminPostScreen()))),
|
|
|
|
_buildAdminTile(context, "ARCHIVE_SYNC", Icons.upload_file, Colors.blueGrey,
|
|
() => Navigator.push(context, MaterialPageRoute(builder: (context) => const AdminMusicScreen()))),
|
|
|
|
_buildAdminTile(context, "ARTIFACT_REG", Icons.inventory_2, Colors.amber,
|
|
() => Navigator.push(context, MaterialPageRoute(builder: (context) => const AdminArtifactScreen()))),
|
|
|
|
_buildAdminTile(context, "SESSION_INIT", Icons.location_on, Colors.cyan,
|
|
() => Navigator.push(context, MaterialPageRoute(builder: (context) => const AdminEventScreen()))),
|
|
|
|
_buildAdminTile(context, "KEY_GENERATOR", Icons.vpn_key, terminalGreen,
|
|
() => _showTierSelectionDialog(context)),
|
|
|
|
_buildAdminTile(context, "USER_DATABASE", Icons.dns, Colors.orange,
|
|
() => Navigator.push(context, MaterialPageRoute(builder: (context) => const AdminUsersScreen()))),
|
|
|
|
// --- NEW: INCOMING SIGNALS (REQUESTS) TILE ---
|
|
_buildAdminTile(context, "INCOMING_SIGNALS", Icons.satellite_alt, Colors.purpleAccent,
|
|
() => Navigator.push(context, MaterialPageRoute(builder: (context) => const AdminRequestsView()))),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildAdminTile(BuildContext context, String label, IconData icon, Color color, VoidCallback onTap) {
|
|
return InkWell(
|
|
onTap: onTap,
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: color.withValues(alpha: 0.4)),
|
|
color: color.withValues(alpha: 0.05),
|
|
),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(icon, color: color, size: 32),
|
|
const SizedBox(height: 12),
|
|
Text(label,
|
|
style: TextStyle(color: color, fontSize: 9, fontWeight: FontWeight.bold, letterSpacing: 1),
|
|
textAlign: TextAlign.center
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// --- TIERED KEY GENERATION LOGIC ---
|
|
|
|
void _showTierSelectionDialog(BuildContext context) {
|
|
int selectedTier = 1;
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => StatefulBuilder(
|
|
builder: (context, setDialogState) => AlertDialog(
|
|
backgroundColor: Colors.black,
|
|
shape: const RoundedRectangleBorder(side: BorderSide(color: terminalGreen)),
|
|
title: const Text("GENERATE_ACCESS_KEY"),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text("GRANT_LEVEL:", style: TextStyle(color: Colors.white24, fontSize: 10)),
|
|
DropdownButton<int>(
|
|
value: selectedTier,
|
|
isExpanded: true,
|
|
dropdownColor: Colors.black,
|
|
style: const TextStyle(color: terminalGreen, fontFamily: 'ShareTechMono'),
|
|
items: const [
|
|
DropdownMenuItem(value: 1, child: Text("LVL_01: OBSERVER")),
|
|
DropdownMenuItem(value: 2, child: Text("LVL_02: COLLECTOR")),
|
|
DropdownMenuItem(value: 3, child: Text("LVL_03: INVESTOR")),
|
|
],
|
|
onChanged: (val) => setDialogState(() => selectedTier = val!),
|
|
),
|
|
],
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text("[ CANCEL ]", style: TextStyle(color: Colors.white24))
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
Navigator.pop(context);
|
|
_executeKeyGen(context, selectedTier);
|
|
},
|
|
child: const Text("[ EXECUTE ]"),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _executeKeyGen(BuildContext context, int tier) async {
|
|
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
|
String code = String.fromCharCodes(Iterable.generate(6, (_) => chars.codeUnitAt(Random().nextInt(chars.length))));
|
|
|
|
try {
|
|
await FirebaseFirestore.instance.collection('invites').doc(code).set({
|
|
'used': false,
|
|
'grantTier': tier,
|
|
'createdAt': FieldValue.serverTimestamp(),
|
|
});
|
|
|
|
if (!context.mounted) return;
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
backgroundColor: Colors.black,
|
|
shape: const RoundedRectangleBorder(side: BorderSide(color: terminalGreen)),
|
|
title: Text("LVL_0${tier}_KEY_READY"),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Text("ONE-TIME ACCESS KEY:", style: TextStyle(fontSize: 10, color: Colors.white24)),
|
|
const SizedBox(height: 15),
|
|
SelectableText(
|
|
code,
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(fontSize: 32, color: terminalGreen, letterSpacing: 5, fontWeight: FontWeight.bold)
|
|
),
|
|
],
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text("[ DONE ]", style: TextStyle(color: terminalGreen))
|
|
)
|
|
],
|
|
),
|
|
);
|
|
} catch (e) {
|
|
if (!context.mounted) return;
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(backgroundColor: Colors.red, content: Text("DATABASE_ERROR: $e")),
|
|
);
|
|
}
|
|
}
|
|
} |