basta localizzazioni per ora
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||
import 'package:flux/core/data/constants.dart';
|
||||
import 'package:flux/core/utils/app_message.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
part 'auth_state.dart';
|
||||
@@ -41,7 +42,9 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: AuthStatus.initial,
|
||||
infoMessage: "Controlla la tua email per confermare l'account!",
|
||||
infoMessage: AppMessage(
|
||||
key: 'authCubitCheckEmailToConfirmAccount',
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@@ -82,7 +85,10 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: AuthStatus.pwResetSent,
|
||||
infoMessage: "Email per reset password inviata a $email!",
|
||||
infoMessage: AppMessage(
|
||||
key: 'authCubitResetPasswordEmailSentTo',
|
||||
argument: email,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ class AuthState extends Equatable {
|
||||
final AuthStatus status;
|
||||
final bool isLoginMode;
|
||||
final String? errorMessage;
|
||||
final String? infoMessage;
|
||||
final AppMessage? infoMessage;
|
||||
|
||||
const AuthState({
|
||||
this.status = AuthStatus.initial,
|
||||
@@ -19,7 +19,7 @@ class AuthState extends Equatable {
|
||||
AuthStatus? status,
|
||||
bool? isLoginMode,
|
||||
String? errorMessage,
|
||||
String? infoMessage,
|
||||
AppMessage? infoMessage,
|
||||
}) {
|
||||
return AuthState(
|
||||
status: status ?? this.status,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flux/core/theme/theme.dart';
|
||||
import 'package:flux/core/utils/extensions.dart';
|
||||
import 'package:flux/core/widgets/flux_logo.dart';
|
||||
import 'package:flux/core/widgets/flux_text_field.dart';
|
||||
import 'package:flux/features/auth/bloc/auth_cubit.dart';
|
||||
@@ -55,7 +56,7 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
if (state.infoMessage != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(state.infoMessage!),
|
||||
content: Text(state.infoMessage!.translatedMessage(context)),
|
||||
backgroundColor: Colors.blueAccent, // O context.accent
|
||||
),
|
||||
);
|
||||
@@ -77,7 +78,9 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
|
||||
// --- TITOLO DINAMICO ---
|
||||
Text(
|
||||
state.isLoginMode ? 'BENTORNATO' : 'CREA ACCOUNT',
|
||||
state.isLoginMode
|
||||
? context.l10n.authScreenWelcomeBack
|
||||
: context.l10n.authScreenCreateAccount,
|
||||
style: TextStyle(
|
||||
color: context.primaryText,
|
||||
fontSize: 24,
|
||||
@@ -88,8 +91,10 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
state.isLoginMode
|
||||
? 'Accedi per gestire il tuo business'
|
||||
: 'Inizia oggi a digitalizzare il tuo negozio',
|
||||
? context.l10n.authScreenLoginToManageYourBusiness
|
||||
: context
|
||||
.l10n
|
||||
.authScreenStartTodayToDigitalizeYourStore,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: context.secondaryText),
|
||||
),
|
||||
@@ -97,7 +102,7 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
|
||||
// --- CAMPI INPUT ---
|
||||
FluxTextField(
|
||||
label: 'Email Aziendale',
|
||||
label: context.l10n.authScreenBusinessEmail,
|
||||
icon: Icons.email_outlined,
|
||||
controller: _emailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
@@ -130,7 +135,9 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
state.isLoginMode ? 'ACCEDI' : 'REGISTRATI',
|
||||
state.isLoginMode
|
||||
? context.l10n.authScreenLogin
|
||||
: context.l10n.authScreenSignUp,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
@@ -147,12 +154,15 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
text: state.isLoginMode
|
||||
? "Non hai un account? "
|
||||
: "Hai già un account? ",
|
||||
? context.l10n.authScreenDontHaveAccount
|
||||
: context.l10n.authScreenAlreadyHaveAccount,
|
||||
style: TextStyle(color: context.secondaryText),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: state.isLoginMode ? "Registrati" : "Accedi",
|
||||
text: state.isLoginMode
|
||||
? context.l10n.authScreenSignUp
|
||||
: context.l10n.authScreenLogin,
|
||||
|
||||
style: TextStyle(
|
||||
color: context.accent,
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -169,7 +179,7 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
.read<AuthCubit>()
|
||||
.requestPasswordReset(_emailController.text.trim()),
|
||||
child: Text(
|
||||
'Pw dimenticata/Invito scaduto?',
|
||||
context.l10n.authScreenForgotPassword,
|
||||
style: TextStyle(
|
||||
color: context.accent,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
||||
@@ -22,5 +22,5 @@ class CompanyState extends Equatable {
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [status, errorMessage];
|
||||
List<Object?> get props => [status, errorMessage, company];
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class CompanyRepository {
|
||||
} on PostgrestException catch (e) {
|
||||
throw e.message;
|
||||
} catch (e) {
|
||||
throw 'Errore imprevisto durante la creazione dell\'azienda';
|
||||
throw e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flux/core/utils/extensions.dart';
|
||||
import 'package:flux/features/company/bloc/company_bloc.dart';
|
||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||
import 'package:flux/core/theme/theme.dart';
|
||||
@@ -69,7 +70,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Configurazione Azienda'),
|
||||
title: Text(context.l10n.createCompanyScreenCompanyConfiguration),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.logout_rounded),
|
||||
@@ -98,7 +99,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
state.errorMessage ?? 'Errore durante il salvataggio',
|
||||
state.errorMessage ?? context.l10n.commonSavingError,
|
||||
),
|
||||
backgroundColor: Colors.redAccent,
|
||||
),
|
||||
@@ -118,10 +119,12 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
const SizedBox(height: 32),
|
||||
|
||||
// --- SEZIONE 1: IDENTITÀ FISCALE ---
|
||||
_SectionTitle(title: 'DATI FISCALI'),
|
||||
_SectionTitle(
|
||||
title: context.l10n.createCompanyScreenFiscalData,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FluxTextField(
|
||||
label: 'Ragione Sociale',
|
||||
label: context.l10n.createCompanyScreenCompanyName,
|
||||
icon: Icons.business,
|
||||
controller: _ragioneSocialeController,
|
||||
),
|
||||
@@ -130,7 +133,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: FluxTextField(
|
||||
label: 'Partita IVA',
|
||||
label: context.l10n.createCompanyScreenVatId,
|
||||
icon: Icons.numbers,
|
||||
controller: _pIvaController,
|
||||
),
|
||||
@@ -138,7 +141,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: FluxTextField(
|
||||
label: 'Codice Fiscale',
|
||||
label: context.l10n.createCompanyScreenFiscalCode,
|
||||
icon: Icons.badge_outlined,
|
||||
controller: _cfController,
|
||||
),
|
||||
@@ -147,7 +150,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FluxTextField(
|
||||
label: 'Codice Univoco (SDI) / PEC',
|
||||
label: context.l10n.createCompanyScreenSdiPec,
|
||||
icon: Icons.send_and_archive_outlined,
|
||||
controller: _univocoController,
|
||||
),
|
||||
@@ -155,10 +158,13 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
const SizedBox(height: 32),
|
||||
|
||||
// --- SEZIONE 2: SEDE LEGALE ---
|
||||
_SectionTitle(title: 'SEDE LEGALE'),
|
||||
_SectionTitle(
|
||||
title:
|
||||
context.l10n.createCompanyScreenCompanyLegalAddress,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FluxTextField(
|
||||
label: 'Indirizzo e n. civico',
|
||||
label: context.l10n.commonAddress,
|
||||
icon: Icons.home_work_outlined,
|
||||
controller: _indirizzoController,
|
||||
),
|
||||
@@ -168,7 +174,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: FluxTextField(
|
||||
label: 'Città',
|
||||
label: context.l10n.commonCity,
|
||||
icon: Icons.location_city,
|
||||
controller: _cittaController,
|
||||
),
|
||||
@@ -176,7 +182,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: FluxTextField(
|
||||
label: 'CAP',
|
||||
label: context.l10n.commonZipCode,
|
||||
icon: Icons.map_outlined,
|
||||
controller: _capController,
|
||||
),
|
||||
@@ -184,7 +190,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: FluxTextField(
|
||||
label: 'Prov',
|
||||
label: context.l10n.commonProvince,
|
||||
icon: Icons.explore_outlined,
|
||||
controller: _provinciaController,
|
||||
),
|
||||
@@ -232,7 +238,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
Icon(Icons.cloud_upload_outlined, color: context.accent, size: 32),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'Carica Logo Aziendale',
|
||||
context.l10n.createCompanyScreenUploadLogo,
|
||||
style: TextStyle(
|
||||
color: context.primaryText,
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -240,7 +246,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Verrà usato per le tue stampe e ricevute',
|
||||
context.l10n.createCompanyScreenWillBeUsedForReceipts,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: context.secondaryText, fontSize: 12),
|
||||
),
|
||||
@@ -259,7 +265,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
: () => _onSave(),
|
||||
child: state.status == CompanyStatus.loading
|
||||
? const CircularProgressIndicator()
|
||||
: const Text('SALVA AZIENDA'),
|
||||
: Text(context.l10n.createCompanyScreenSaveCompany),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -282,7 +288,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
'Configura la tua Azienda',
|
||||
context.l10n.createCompanyScreenSetupYourCompany,
|
||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: context.primaryText,
|
||||
@@ -290,7 +296,7 @@ class _CreateCompanyScreenState extends State<CreateCompanyScreen> {
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'FLUX ha bisogno dei tuoi dati fiscali per gestire correttamente le fatturazioni e le attivazioni dei tuoi negozi.',
|
||||
context.l10n.createCompanyScreenFluxNeedsYourFiscalData,
|
||||
style: TextStyle(
|
||||
color: context.secondaryText,
|
||||
fontSize: 15,
|
||||
|
||||
@@ -21,7 +21,7 @@ class CustomerRepository {
|
||||
.single();
|
||||
return CustomerModel.fromMap(response);
|
||||
} catch (e) {
|
||||
throw 'Errore durante il salvataggio del cliente: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class CustomerRepository {
|
||||
.single();
|
||||
return CustomerModel.fromMap(response);
|
||||
} catch (e) {
|
||||
throw 'Errore durante la modifica del cliente: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class CustomerRepository {
|
||||
|
||||
return (response as List).map((c) => CustomerModel.fromMap(c)).toList();
|
||||
} catch (e) {
|
||||
throw 'Errore nel recupero clienti';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ class CustomerRepository {
|
||||
.map((f) => CustomerFileModel.fromMap(f))
|
||||
.toList();
|
||||
} catch (e) {
|
||||
throw 'Errore recupero file: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ class CustomerRepository {
|
||||
try {
|
||||
// Usiamo bytes invece del path per massima compatibilità
|
||||
if (pickedFile.bytes == null && pickedFile.path == null) {
|
||||
throw 'Impossibile leggere il contenuto del file';
|
||||
throw 'File read error';
|
||||
}
|
||||
|
||||
// Se siamo su desktop/mobile abbiamo il path, su web abbiamo i bytes
|
||||
@@ -153,7 +153,7 @@ class CustomerRepository {
|
||||
|
||||
return CustomerFileModel.fromMap(response);
|
||||
} catch (e) {
|
||||
throw 'Errore durante l\'upload: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,14 +186,10 @@ class CustomerRepository {
|
||||
|
||||
// 3. Cancellazione MASSIVA dallo Storage
|
||||
await _supabase.storage.from('documents').remove(storagePaths);
|
||||
|
||||
debugPrint("Eliminati con successo ${files.length} file.");
|
||||
} on PostgrestException catch (e) {
|
||||
debugPrint("Errore DB: ${e.message}");
|
||||
throw 'Errore database: ${e.message}';
|
||||
throw e.message;
|
||||
} catch (e) {
|
||||
debugPrint("Errore generico: $e");
|
||||
throw 'Errore durante l\'eliminazione dei file: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,31 +58,31 @@ class HomeScreen extends StatelessWidget {
|
||||
),
|
||||
delegate: SliverChildListDelegate([
|
||||
_buildDashboardWidget(
|
||||
title: context.l10n.expiring_contracts,
|
||||
title: context.l10n.homeExpiringContracts,
|
||||
icon: Icons.assignment_late_outlined,
|
||||
color: Colors.orange,
|
||||
context: context,
|
||||
),
|
||||
_buildDashboardWidget(
|
||||
title: context.l10n.sticky_notes,
|
||||
title: context.l10n.commonStickyNotes,
|
||||
icon: Icons.sticky_note_2_outlined,
|
||||
color: Colors.yellow.shade700,
|
||||
context: context,
|
||||
),
|
||||
_buildDashboardWidget(
|
||||
title: context.l10n.my_tasks,
|
||||
title: context.l10n.homeMyTasks,
|
||||
icon: Icons.check_box_outlined,
|
||||
color: Colors.green,
|
||||
context: context,
|
||||
),
|
||||
_buildDashboardWidget(
|
||||
title: context.l10n.latestServices,
|
||||
title: context.l10n.homeLatestServices,
|
||||
icon: Icons.design_services_outlined,
|
||||
color: Colors.blue,
|
||||
context: context,
|
||||
),
|
||||
_buildDashboardWidget(
|
||||
title: 'Ultime Assistenze',
|
||||
title: context.l10n.homeLatestServiceTickets,
|
||||
icon: Icons.support_agent_outlined,
|
||||
color: Colors.purple,
|
||||
context: context,
|
||||
@@ -118,7 +118,7 @@ class HomeScreen extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Bentornato, ${user!.name}! 👋",
|
||||
context.l10n.homeWelcomeBack(user?.name ?? "Utente"),
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: -0.5,
|
||||
@@ -152,7 +152,7 @@ class HomeScreen extends StatelessWidget {
|
||||
Icon(Icons.storefront, size: 16, color: context.primary),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
currentStore?.nome ?? "Nessun negozio",
|
||||
currentStore?.nome ?? context.l10n.homeNoStoreFound,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: context.primary,
|
||||
@@ -184,7 +184,7 @@ class HomeScreen extends StatelessWidget {
|
||||
children: [
|
||||
QuickActionButton(
|
||||
icon: Icons.add,
|
||||
label: "Servizio",
|
||||
label: context.l10n.commonService,
|
||||
color: Colors.blue,
|
||||
onTap: () {
|
||||
// Entriamo nel form! Nessun parametro extra = Nuovo Servizio
|
||||
@@ -194,7 +194,7 @@ class HomeScreen extends StatelessWidget {
|
||||
const SizedBox(width: 12),
|
||||
QuickActionButton(
|
||||
icon: Icons.handyman,
|
||||
label: "Assistenza",
|
||||
label: context.l10n.homeNewServiceTicket,
|
||||
color: Colors.redAccent,
|
||||
onTap: () {
|
||||
// TODO: Quando avrai la rotta per la nuova assistenza
|
||||
@@ -204,7 +204,7 @@ class HomeScreen extends StatelessWidget {
|
||||
const SizedBox(width: 12),
|
||||
QuickActionButton(
|
||||
icon: Icons.note_add,
|
||||
label: "Nota",
|
||||
label: context.l10n.commonNote,
|
||||
color: Colors.amber,
|
||||
onTap: () {
|
||||
// TODO: Quando faremo il modale/pagina delle note
|
||||
@@ -213,7 +213,7 @@ class HomeScreen extends StatelessWidget {
|
||||
const SizedBox(width: 12),
|
||||
QuickActionButton(
|
||||
icon: Icons.task_alt,
|
||||
label: "Task",
|
||||
label: context.l10n.commonTask,
|
||||
color: Colors.teal,
|
||||
onTap: () {
|
||||
// TODO: Quando faremo i task
|
||||
@@ -281,7 +281,7 @@ class HomeScreen extends StatelessWidget {
|
||||
const Spacer(),
|
||||
Center(
|
||||
child: Text(
|
||||
"(Coming Soon)",
|
||||
context.l10n.commonComingSoon,
|
||||
style: TextStyle(
|
||||
color: context.secondaryText.withValues(alpha: 0.7),
|
||||
fontStyle: FontStyle.italic,
|
||||
|
||||
Reference in New Issue
Block a user