Actualizacion del programa
This commit is contained in:
121
lib/screens/onboarding/onboarding_screen.dart
Normal file
121
lib/screens/onboarding/onboarding_screen.dart
Normal file
@@ -0,0 +1,121 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../core/app_colors.dart';
|
||||
|
||||
class OnboardingScreen extends StatefulWidget {
|
||||
const OnboardingScreen({super.key});
|
||||
@override State<OnboardingScreen> createState() => _OnboardingScreenState();
|
||||
}
|
||||
|
||||
class _OnboardingScreenState extends State<OnboardingScreen> {
|
||||
final _ctrl = PageController();
|
||||
int _page = 0;
|
||||
|
||||
static const _pages = [
|
||||
_OnboardPage(icon:Icons.delete_sweep_rounded, color:AppColors.guindaPrimary,
|
||||
title:'Bienvenido a Celaya Limpia',
|
||||
subtitle:'El sistema de recoleccion inteligente del H. Ayuntamiento de Celaya.',
|
||||
desc:'Recibe alertas en tiempo real, conoce tu horario y ayuda a mantener tu ciudad limpia.'),
|
||||
_OnboardPage(icon:Icons.notifications_active, color:AppColors.azulInfo,
|
||||
title:'Alertas inteligentes',
|
||||
subtitle:'Te avisamos exactamente cuando debes sacar tu basura.',
|
||||
desc:'Recibiras 3 alertas:\n\n30 min antes: el camion esta en camino.\n15 min antes: saca tus bolsas a la acera.\nAl pasar: confirma que fue recogida.\n\nNunca mas pierdas al camion recolector.'),
|
||||
_OnboardPage(icon:Icons.recycling, color:AppColors.verdeExito,
|
||||
title:'Guia de separacion',
|
||||
subtitle:'Aprende a separar correctamente tus residuos.',
|
||||
desc:'Bolsa verde: organicos (comida, jardin)\nBolsa azul: reciclables (PET, latas)\nBolsa negra: no reciclables\n\nUsa la camara IA para identificar si un residuo es organico o inorganico al instante.'),
|
||||
_OnboardPage(icon:Icons.star, color:Colors.amber,
|
||||
title:'Tu opinion importa',
|
||||
subtitle:'Califica el servicio y ayuda a mejorarlo.',
|
||||
desc:'Despues de cada recoleccion podras:\n\nCalificar de 1 a 5 estrellas\nDejar comentarios al Ayuntamiento\nReportar incidencias con foto\n\nTus reportes son atendidos por el equipo municipal.'),
|
||||
];
|
||||
|
||||
Future<void> _finish() async {
|
||||
final p = await SharedPreferences.getInstance();
|
||||
await p.setBool('onboarding_done', true);
|
||||
if (!mounted) return;
|
||||
Navigator.pushReplacementNamed(context, '/login');
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Stack(children: [
|
||||
PageView.builder(controller:_ctrl, onPageChanged:(p)=>setState(()=>_page=p),
|
||||
itemCount:_pages.length,
|
||||
itemBuilder:(_,i)=>_PageContent(page:_pages[i])),
|
||||
Positioned(bottom:120, left:0, right:0,
|
||||
child:Row(mainAxisAlignment:MainAxisAlignment.center,
|
||||
children:List.generate(_pages.length,(i)=>AnimatedContainer(
|
||||
duration:const Duration(milliseconds:250),
|
||||
margin:const EdgeInsets.symmetric(horizontal:4),
|
||||
width:_page==i?24:8, height:8,
|
||||
decoration:BoxDecoration(
|
||||
color:_page==i?_pages[i].color:Colors.grey.shade300,
|
||||
borderRadius:BorderRadius.circular(4)))))),
|
||||
Positioned(bottom:40, left:24, right:24,
|
||||
child:Row(children:[
|
||||
if (_page>0)
|
||||
TextButton(onPressed:()=>_ctrl.previousPage(
|
||||
duration:const Duration(milliseconds:300),curve:Curves.easeOut),
|
||||
child:const Text('Atras',style:TextStyle(color:AppColors.grisTexto)))
|
||||
else
|
||||
TextButton(onPressed:_finish,
|
||||
child:const Text('Omitir',style:TextStyle(color:AppColors.grisTexto))),
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
onPressed:_page<_pages.length-1
|
||||
?()=>_ctrl.nextPage(duration:const Duration(milliseconds:300),curve:Curves.easeOut)
|
||||
:_finish,
|
||||
style:ElevatedButton.styleFrom(
|
||||
backgroundColor:_pages[_page].color, foregroundColor:Colors.white,
|
||||
padding:const EdgeInsets.symmetric(horizontal:28,vertical:12),
|
||||
shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(25))),
|
||||
child:Text(_page<_pages.length-1?'Siguiente':'Comenzar',
|
||||
style:const TextStyle(fontWeight:FontWeight.bold))),
|
||||
])),
|
||||
]));
|
||||
}
|
||||
@override void dispose(){ _ctrl.dispose(); super.dispose(); }
|
||||
}
|
||||
|
||||
class _OnboardPage {
|
||||
final IconData icon; final Color color;
|
||||
final String title, subtitle, desc;
|
||||
const _OnboardPage({required this.icon,required this.color,
|
||||
required this.title,required this.subtitle,required this.desc});
|
||||
}
|
||||
|
||||
class _PageContent extends StatelessWidget {
|
||||
final _OnboardPage page;
|
||||
const _PageContent({super.key, required this.page});
|
||||
@override
|
||||
Widget build(BuildContext context) => Container(
|
||||
decoration:BoxDecoration(gradient:LinearGradient(
|
||||
begin:Alignment.topCenter, end:Alignment.bottomCenter,
|
||||
colors:[page.color, page.color.withOpacity(0.85), Colors.white],
|
||||
stops:const[0,0.4,0.7])),
|
||||
child:SafeArea(child:Column(children:[
|
||||
const SizedBox(height:48),
|
||||
Container(width:120,height:120,
|
||||
decoration:BoxDecoration(color:Colors.white.withOpacity(0.2),shape:BoxShape.circle,
|
||||
border:Border.all(color:Colors.white.withOpacity(0.5),width:2)),
|
||||
child:Icon(page.icon,size:60,color:Colors.white)),
|
||||
const SizedBox(height:28),
|
||||
Padding(padding:const EdgeInsets.symmetric(horizontal:32),child:Column(children:[
|
||||
Text(page.title,textAlign:TextAlign.center,
|
||||
style:const TextStyle(fontSize:24,fontWeight:FontWeight.bold,color:Colors.white)),
|
||||
const SizedBox(height:10),
|
||||
Text(page.subtitle,textAlign:TextAlign.center,
|
||||
style:TextStyle(fontSize:14,color:Colors.white.withOpacity(0.9))),
|
||||
])),
|
||||
const SizedBox(height:32),
|
||||
Expanded(child:Container(margin:const EdgeInsets.symmetric(horizontal:20),
|
||||
padding:const EdgeInsets.all(22),
|
||||
decoration:BoxDecoration(color:Colors.white,borderRadius:BorderRadius.circular(20),
|
||||
boxShadow:[BoxShadow(color:page.color.withOpacity(0.2),blurRadius:20,offset:const Offset(0,8))]),
|
||||
child:Text(page.desc,textAlign:TextAlign.left,
|
||||
style:const TextStyle(fontSize:13,height:1.7,color:AppColors.negroTexto)))),
|
||||
const SizedBox(height:110),
|
||||
])));
|
||||
}
|
||||
Reference in New Issue
Block a user