prova per inviti
Some checks failed
Build and Release FLUX (Multi-Platform) / build-android (push) Successful in 2m28s
Build and Release FLUX (Multi-Platform) / build-web (push) Successful in 1m31s
Build and Release FLUX (Multi-Platform) / build-windows (push) Has been cancelled

This commit is contained in:
2026-06-02 09:32:30 +02:00
parent 67a56f2954
commit 618cbc0396
9 changed files with 236 additions and 146 deletions

View File

@@ -0,0 +1,207 @@
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
class SetPasswordScreen extends StatefulWidget {
const SetPasswordScreen({super.key});
@override
State<SetPasswordScreen> createState() => _SetPasswordScreenState();
}
class _SetPasswordScreenState extends State<SetPasswordScreen> {
final _formKey = GlobalKey<FormState>();
final _passwordController = TextEditingController();
final _confirmPasswordController = TextEditingController();
bool _isLoading = false;
bool _obscurePassword = true;
String? _errorMessage;
@override
void dispose() {
_passwordController.dispose();
_confirmPasswordController.dispose();
super.dispose();
}
Future<void> _submitNewPassword() async {
if (!_formKey.currentState!.validate()) return;
setState(() {
_isLoading = true;
_errorMessage = null;
});
try {
// 🥷 LA MOFFA DEL NINJA: Aggiorniamo la password dell'utente corrente
// che si è loggato in automatico grazie al token nell'URL
await Supabase.instance.client.auth.updateUser(
UserAttributes(password: _passwordController.text.trim()),
);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Password impostata con successo! Benvenuto in FLUX.',
),
backgroundColor: Colors.green,
),
);
// Non serve forzare i redirect qui!
// Il SessionCubit nel costruttore ha un listener su 'onAuthStateChange'.
// Sentirà che l'utente ora è perfettamente valido, richiamerà 'initializeSession()'
// e lo scaricherà automaticamente nella pagina di Onboarding corretta.
}
} on AuthException catch (e) {
setState(() {
_errorMessage = e.message;
});
} catch (e) {
setState(() {
_errorMessage = "Si è verificato un errore imprevisto. Riprova.";
});
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
@override
Widget build(BuildContext context) {
// Rendiamo la schermata responsive ed elegante per il Web (Cloudflare)
final size = MediaQuery.of(context).size;
final isWebContainer = size.width > 600;
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Container(
width: isWebContainer ? 450 : size.width,
padding: const EdgeInsets.all(32.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Logo o Brand FLUX
Text(
'FLUX',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
letterSpacing: -1,
),
),
const SizedBox(height: 8),
Text(
'Configura la tua chiave di accesso per iniziare a collaborare.',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.grey[600], fontSize: 14),
),
const SizedBox(height: 32),
if (_errorMessage != null) ...[
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.red.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
),
child: Text(
_errorMessage!,
style: const TextStyle(color: Colors.red, fontSize: 13),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 16),
],
// Campo Password
TextFormField(
controller: _passwordController,
obscureText: _obscurePassword,
decoration: InputDecoration(
labelText: 'Nuova Password',
prefixIcon: const Icon(Icons.lock_outline),
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility_off
: Icons.visibility,
),
onPressed: () => setState(
() => _obscurePassword = !_obscurePassword,
),
),
border: const OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Inserisci una password';
}
if (value.length < 6) {
return 'La password deve avere almeno 6 caratteri';
}
return null;
},
),
const SizedBox(height: 16),
// Campo Conferma Password
TextFormField(
controller: _confirmPasswordController,
obscureText: _obscurePassword,
decoration: const InputDecoration(
labelText: 'Conferma Password',
prefixIcon: Icon(Icons.lock_reset_rounded),
border: OutlineInputBorder(),
),
validator: (value) {
if (value != _passwordController.text) {
return 'Le password non coincidono';
}
return null;
},
),
const SizedBox(height: 24),
// Bottone di Invio
ElevatedButton(
onPressed: _isLoading ? null : _submitNewPassword,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Colors.black,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: _isLoading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
Colors.white,
),
),
)
: const Text(
'Conferma e Accedi',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
),
);
}
}