ui iniziale fatta con gemini

This commit is contained in:
2026-04-04 17:13:25 +02:00
parent a0cb3ec52a
commit c91415b8b3
13 changed files with 967 additions and 7 deletions

View File

@@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flux/theme.dart';
import 'package:flux/ui/home_screen.dart';
void main() {
runApp(const MainApp());
@@ -9,12 +11,11 @@ class MainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: Text('Hello World!'),
),
),
return MaterialApp(
title: 'FLUX Gestionale',
debugShowCheckedModeBanner: false,
theme: fluxDarkTheme, // Applica il tema FLUX
home: const HomeScreen(),
);
}
}

73
lib/theme.dart Normal file
View File

@@ -0,0 +1,73 @@
// lib/theme.dart
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class FluxColors {
// Palette Tech Dark da loghi generati
static const Color background = Color(0xFF0A0E17); // Nero profondo/Blu scuro
static const Color surface = Color(0xFF161B22); // Pannelli scuri
static const Color primaryBlue = Color(0xFF007BFF); // Blu Elettrico del logo
static const Color accentTurquoise = Color(0xFF17A2B8); // Turchese del flusso
static const Color textPrimary = Colors.white;
static const Color textSecondary = Color(0xFF8B949E); // Grigio fumo
}
ThemeData fluxDarkTheme = ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
primaryColor: FluxColors.primaryBlue,
scaffoldBackgroundColor: FluxColors.background,
colorScheme: const ColorScheme.dark(
primary: FluxColors.primaryBlue,
secondary: FluxColors.accentTurquoise,
surface: FluxColors.surface,
background: FluxColors.background,
onPrimary: Colors.white,
onSurface: FluxColors.textPrimary,
),
// Font moderno sans-serif (es. Montserrat o Poppins coerente con descrizione)
textTheme: GoogleFonts.poppinsTextTheme(ThemeData.dark().textTheme).copyWith(
headlineMedium: GoogleFonts.poppins(
color: FluxColors.textPrimary,
fontWeight: FontWeight.w600,
letterSpacing: 0.5,
),
titleLarge: GoogleFonts.poppins(
color: FluxColors.textPrimary,
fontWeight: FontWeight.w500,
),
bodyMedium: GoogleFonts.poppins(color: FluxColors.textSecondary),
),
appBarTheme: const AppBarTheme(
backgroundColor: FluxColors.background,
elevation: 0,
centerTitle: false,
titleTextStyle: TextStyle(
color: FluxColors.textPrimary,
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
cardTheme: const CardThemeData(
color: FluxColors.surface,
elevation: 2,
margin: EdgeInsets.all(8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
),
// Stile per i pulsanti (es. "Nuova Operazione")
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: FluxColors.primaryBlue,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
textStyle: GoogleFonts.poppins(fontWeight: FontWeight.w500),
),
),
);

View File

@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:flux/theme.dart';
class AnagraficheMainView extends StatelessWidget {
const AnagraficheMainView({super.key});
@override
Widget build(BuildContext context) {
// Controller locale per gestire i Tab
return DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
title: const Text('Anagrafiche'),
bottom: TabBar(
isScrollable: true,
indicatorColor: FluxColors.accentTurquoise,
labelColor: FluxColors.accentTurquoise,
unselectedLabelColor: FluxColors.textSecondary,
tabs: [
Tab(icon: Icon(Icons.storefront), text: 'Negozi'),
Tab(icon: Icon(Icons.support_agent), text: 'Gestori'),
Tab(icon: Icon(Icons.assignment_ind), text: 'Clienti'),
Tab(icon: Icon(Icons.phone_android), text: 'Prodotti'),
],
),
),
body: const TabBarView(
children: [
// Esempi di view iniettate con Bloc dedicati (da implementare)
/* ElencoEntitaView(tipoEntita: 'Negozi'), // Provider<AnagraficaBloc>...
ElencoEntitaView(tipoEntita: 'Gestori'),
ElencoEntitaView(tipoEntita: 'Clienti'),
ElencoEntitaView(tipoEntita: 'Prodotti'), */
Placeholder(),
Placeholder(),
Placeholder(),
Placeholder(),
],
),
),
);
}
}

View File

@@ -0,0 +1,117 @@
import 'package:flutter/material.dart';
import 'package:flux/theme.dart';
class DashboardView extends StatelessWidget {
const DashboardView({super.key});
@override
Widget build(BuildContext context) {
// Iniezione del Bloc per la creazione di operazioni (da implementare)
return /* BlocProvider(
create: (context) => OperazioneBloc(), // Implementa la logica nel Bloc
child: */ Scaffold(
appBar: AppBar(title: Text('FLUX')),
body: SingleChildScrollView(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_WelcomeHeader(),
SizedBox(height: 24),
_QuickActions(), // Contiene "Nuova Operazione"
SizedBox(height: 24),
_RecentActivityPreview(),
],
),
),
);
// );
}
}
class _WelcomeHeader extends StatelessWidget {
const _WelcomeHeader();
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Benvenuto,', style: Theme.of(context).textTheme.bodyMedium),
Text(
'Negozio Piacenza Centro',
style: Theme.of(context).textTheme.headlineMedium,
),
],
);
}
}
class _QuickActions extends StatelessWidget {
const _QuickActions();
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'AZIONI RAPIDE',
style: Theme.of(
context,
).textTheme.titleSmall?.copyWith(color: FluxColors.accentTurquoise),
),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: () {
// Emetti evento al Bloc: BlocProvider.of<OperazioneBloc>(context).add(IniziaNuovaOperazione());
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Avvio Nuova Operazione...')),
);
},
icon: const Icon(Icons.add),
label: const Text('NUOVA OPERAZIONE TELCO'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 50),
),
),
],
);
}
}
class _RecentActivityPreview extends StatelessWidget {
const _RecentActivityPreview();
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Attività Recenti',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const Divider(color: FluxColors.textSecondary),
// Sostituire con BlocBuilder
_activityTile('Nuova Linea', 'Mario Rossi', '10 min fa'),
_activityTile('Assistenza Tech', 'iPhone 13', '45 min fa'),
],
),
),
);
}
Widget _activityTile(String title, String subtitle, String time) {
return ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.history, color: FluxColors.accentTurquoise),
title: Text(title, style: const TextStyle(color: FluxColors.textPrimary)),
subtitle: Text(subtitle),
trailing: Text(
time,
style: const TextStyle(color: FluxColors.textSecondary, fontSize: 12),
),
);
}
}

66
lib/ui/home_screen.dart Normal file
View File

@@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import 'package:flux/theme.dart';
import 'package:flux/ui/anagrafiche/anagrafiche_main_view.dart';
import 'package:flux/ui/dashboard/dashboard_view.dart';
import 'package:flux/ui/settings/settings_view.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _selectedIndex = 0;
static const List<Widget> _widgetOptions = <Widget>[
DashboardView(), // Contiene Nuova Operazione
Placeholder(),
AnagraficheMainView(), // Gestisce [negozi, gestori, clienti, prodotti]
SettingsView(),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: _widgetOptions.elementAt(_selectedIndex)),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.dashboard_outlined),
activeIcon: Icon(Icons.dashboard),
label: 'Dashboard',
),
BottomNavigationBarItem(
icon: Icon(Icons.history_edu_outlined),
activeIcon: Icon(Icons.history_edu),
label: 'Operazioni',
),
BottomNavigationBarItem(
icon: Icon(Icons.people_alt_outlined),
activeIcon: Icon(Icons.people_alt),
label: 'Anagrafiche',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings_outlined),
activeIcon: Icon(Icons.settings),
label: 'Impostazioni',
),
],
currentIndex: _selectedIndex,
selectedItemColor: FluxColors.accentTurquoise,
unselectedItemColor: FluxColors.textSecondary,
backgroundColor: FluxColors.surface,
type: BottomNavigationBarType.fixed,
onTap: _onItemTapped,
),
);
}
}

View File

@@ -0,0 +1,72 @@
// lib/ui/impostazioni/impostazioni_view.dart
import 'package:flutter/material.dart';
import 'package:flux/theme.dart';
class SettingsView extends StatelessWidget {
const SettingsView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Impostazioni')),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
_settingsSection('Account', [
_settingsTile(
Icons.person,
'Profilo Utente',
'Configura i tuoi dati',
),
_settingsTile(Icons.store, 'Mio Negozio', 'Piacenza Centro'),
]),
const SizedBox(height: 16),
_settingsSection('Applicazione', [
_settingsTile(Icons.sync, 'Sincronizzazione', 'Ultima: 5 min fa'),
_settingsTile(
Icons.dark_mode,
'Tema (FLUX Dark Active)',
'Configurazione visiva',
),
]),
const SizedBox(height: 24),
TextButton.icon(
onPressed: () {},
icon: const Icon(Icons.exit_to_app, color: Colors.red),
label: const Text('Logout', style: TextStyle(color: Colors.red)),
),
],
),
);
}
Widget _settingsSection(String title, List<Widget> tiles) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title.toUpperCase(),
style: const TextStyle(
color: FluxColors.accentTurquoise,
fontWeight: FontWeight.bold,
letterSpacing: 1,
),
),
const SizedBox(height: 8),
Card(child: Column(children: tiles)),
],
);
}
Widget _settingsTile(IconData icon, String title, String subtitle) {
return ListTile(
leading: Icon(icon, color: FluxColors.primaryBlue),
title: Text(title, style: const TextStyle(color: FluxColors.textPrimary)),
subtitle: Text(subtitle),
trailing: const Icon(
Icons.chevron_right,
color: FluxColors.textSecondary,
),
);
}
}