fixed bugs

This commit is contained in:
2026-08-21 13:11:55 +02:00
parent ab36215b7a
commit 64eade33f3
16 changed files with 367 additions and 361 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

+2 -2
View File
@@ -3,7 +3,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/date_symbol_data_local.dart'; import 'package:intl/date_symbol_data_local.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'screens/login_page.dart'; import 'screens/splash_page.dart';
import 'state/app_state.dart'; import 'state/app_state.dart';
Future<void> main() async { Future<void> main() async {
@@ -32,7 +32,7 @@ class MyApp extends StatelessWidget {
supportedLocales: const [Locale('it', 'IT'), Locale('en', 'US')], supportedLocales: const [Locale('it', 'IT'), Locale('en', 'US')],
locale: const Locale('it', 'IT'), locale: const Locale('it', 'IT'),
home: const LoginPage(), home: const SplashPage(),
); );
} }
} }
+7
View File
@@ -5,6 +5,7 @@ import 'package:image_picker/image_picker.dart';
import '../models/school.dart'; import '../models/school.dart';
import '../services/vanguard_api.dart'; import '../services/vanguard_api.dart';
import '../widgets/yogibook_background.dart'; import '../widgets/yogibook_background.dart';
import '../widgets/app_bottom_nav.dart';
class AccountPage extends StatefulWidget { class AccountPage extends StatefulWidget {
final String token; final String token;
@@ -238,6 +239,12 @@ class _AccountPageState extends State<AccountPage> {
style: TextStyle(fontWeight: FontWeight.w800, fontSize: 18), style: TextStyle(fontWeight: FontWeight.w800, fontSize: 18),
), ),
), ),
bottomNavigationBar: AppBottomNav(
currentIndex: 2,
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
body: YogibookBackground( body: YogibookBackground(
child: SafeArea( child: SafeArea(
top: false, top: false,
+19 -46
View File
@@ -35,8 +35,6 @@ class _HomePageState extends State<HomePage> {
static const Color kBg = Color(0xFFF6F6FB); static const Color kBg = Color(0xFFF6F6FB);
static const Color kGreen = Color(0xFF10B981); static const Color kGreen = Color(0xFF10B981);
int bottomIndex = 0; // Home
late final String zenQuote; late final String zenQuote;
@override @override
@@ -224,44 +222,6 @@ class _HomePageState extends State<HomePage> {
); );
} }
void _handleBottomNav(int i) {
setState(() => bottomIndex = i);
if (i == 0) return;
if (i == 1) {
_goLessons();
return;
}
if (i == 2) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => AccountPage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
),
).then((_) {
if (mounted) setState(() => bottomIndex = 0);
});
return;
}
if (i == 3) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => MeditationPage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
),
);
return;
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@@ -299,8 +259,10 @@ class _HomePageState extends State<HomePage> {
), ),
bottomNavigationBar: AppBottomNav( bottomNavigationBar: AppBottomNav(
currentIndex: bottomIndex, currentIndex: 0,
onTap: _handleBottomNav, token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
), ),
body: YogibookBackground( body: YogibookBackground(
@@ -378,16 +340,27 @@ class _HomePageState extends State<HomePage> {
onTap: () => Navigator.push( onTap: () => Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (_) => OrdersDetailPage(token: widget.token), builder: (_) => OrdersDetailPage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
), ),
), ),
), ),
_HomeTile( _HomeTile(
icon: Icons.person_rounded, icon: Icons.person_rounded,
title: 'Account', title: 'Account',
subtitle: 'Profilo e impostazioni (TODO)', subtitle: 'Profilo e impostazioni',
onTap: () => ScaffoldMessenger.of(context).showSnackBar( onTap: () => Navigator.push(
const SnackBar(content: Text('TODO: Account')), context,
MaterialPageRoute(
builder: (_) => AccountPage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
),
), ),
), ),
+22 -58
View File
@@ -37,8 +37,6 @@ class _LessonsPageState extends State<LessonsPage> {
LessonsSummary? summary; LessonsSummary? summary;
List<Lesson> lessons = []; List<Lesson> lessons = [];
int bottomIndex = 1;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -104,48 +102,6 @@ class _LessonsPageState extends State<LessonsPage> {
String get _name => (widget.userFirstName ?? '').trim(); String get _name => (widget.userFirstName ?? '').trim();
String get _avatarLetter => _name.isNotEmpty ? _name[0].toUpperCase() : 'U'; String get _avatarLetter => _name.isNotEmpty ? _name[0].toUpperCase() : 'U';
void _handleBottomNav(int i) {
if (i == bottomIndex) return;
setState(() => bottomIndex = i);
if (i == 0) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => HomePage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
),
);
return;
}
if (i == 1) return; // sei già su Lezioni
if (i == 2) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('TODO: vai ad Account')));
return;
}
if (i == 3) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => MeditationPage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
),
);
return;
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@@ -195,8 +151,10 @@ class _LessonsPageState extends State<LessonsPage> {
], ],
), ),
bottomNavigationBar: AppBottomNav( bottomNavigationBar: AppBottomNav(
currentIndex: bottomIndex, currentIndex: 1,
onTap: _handleBottomNav, token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
), ),
body: YogibookBackground( body: YogibookBackground(
@@ -388,17 +346,22 @@ class _SummaryStrip extends StatelessWidget {
_SummaryItem('Perse', summary.lost, const Color(0xFFFBC7C4)), _SummaryItem('Perse', summary.lost, const Color(0xFFFBC7C4)),
]; ];
return SizedBox( // 3 colonne, spaziatura tra i box
height: 76, const spacing = 8.0;
child: ListView.separated( const columns = 3;
scrollDirection: Axis.horizontal,
itemCount: items.length, return LayoutBuilder(
separatorBuilder: (_, __) => const SizedBox(width: 8), builder: (context, constraints) {
itemBuilder: (_, i) { final boxWidth =
final it = items[i]; (constraints.maxWidth - spacing * (columns - 1)) / columns;
return Wrap(
spacing: spacing,
runSpacing: spacing,
children: items.map((it) {
return Container( return Container(
width: 96, width: boxWidth,
padding: const EdgeInsets.all(8), padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 6),
decoration: BoxDecoration( decoration: BoxDecoration(
color: it.color, color: it.color,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
@@ -418,7 +381,7 @@ class _SummaryStrip extends StatelessWidget {
it.label, it.label,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: const TextStyle(
fontSize: 10, fontSize: 11,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
), ),
maxLines: 2, maxLines: 2,
@@ -427,8 +390,9 @@ class _SummaryStrip extends StatelessWidget {
], ],
), ),
); );
}).toList(),
);
}, },
),
); );
} }
} }
+34 -19
View File
@@ -18,6 +18,7 @@ class _LoginPageState extends State<LoginPage> {
// ---- UI state // ---- UI state
bool loading = false; bool loading = false;
String error = ''; String error = '';
bool _obscurePassword = true;
// Scuola unica (YogaSoul). Il DB non ha il concetto di scuola: // Scuola unica (YogaSoul). Il DB non ha il concetto di scuola:
// questo oggetto serve solo a soddisfare le pagine che mostrano nome/indirizzo. // questo oggetto serve solo a soddisfare le pagine che mostrano nome/indirizzo.
@@ -61,7 +62,21 @@ class _LoginPageState extends State<LoginPage> {
), ),
); );
} catch (e) { } catch (e) {
setState(() => error = 'Errore login: $e'); final msg = e.toString();
String friendly;
if (msg.contains('401') || msg.contains('403')) {
friendly = 'Email o password non corretti.';
} else if (msg.contains('SocketException') ||
msg.contains('Failed host lookup') ||
msg.contains('Connection')) {
friendly = 'Nessuna connessione. Controlla la rete e riprova.';
} else if (msg.contains('timed out') ||
msg.contains('TimeoutException')) {
friendly = 'Il server non risponde. Riprova tra poco.';
} else {
friendly = 'Accesso non riuscito. Riprova.';
}
setState(() => error = friendly);
} finally { } finally {
if (mounted) setState(() => loading = false); if (mounted) setState(() => loading = false);
} }
@@ -175,44 +190,44 @@ class _LoginPageState extends State<LoginPage> {
controller: emailController, controller: emailController,
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: InputDecoration( decoration: const InputDecoration(
labelText: 'Email / Username', labelText: 'Email / Username',
border: const OutlineInputBorder(), border: OutlineInputBorder(),
enabled: !loading,
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
TextField( TextField(
controller: passwordController, controller: passwordController,
obscureText: true, obscureText: _obscurePassword,
textInputAction: TextInputAction.done, textInputAction: TextInputAction.done,
onSubmitted: (_) => loading ? null : doLogin(), onSubmitted: (_) => loading ? null : doLogin(),
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Password', labelText: 'Password',
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
enabled: !loading, enabled: !loading,
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility
: Icons.visibility_off,
),
onPressed: loading
? null
: () => setState(
() => _obscurePassword = !_obscurePassword,
),
),
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
Row( Align(
mainAxisAlignment: MainAxisAlignment.spaceBetween, alignment: Alignment.centerRight,
children: [ child: TextButton(
TextButton(
onPressed: loading ? null : forgotPassword, onPressed: loading ? null : forgotPassword,
child: const Text('Recupero password'), child: const Text('Recupero password'),
), ),
TextButton(
onPressed: () =>
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Registrazione: dopo.'),
),
),
child: const Text('Registrati'),
),
],
), ),
if (error.isNotEmpty) ...[ if (error.isNotEmpty) ...[
+4 -54
View File
@@ -50,9 +50,6 @@ class _MedicalCertificatesPageState extends State<MedicalCertificatesPage> {
DateTime? expiryDate; DateTime? expiryDate;
bool uploading = false; bool uploading = false;
// ✅ questa pagina è "sezione account"
int bottomIndex = 2;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -286,54 +283,6 @@ class _MedicalCertificatesPageState extends State<MedicalCertificatesPage> {
bool _isPdfPath(String p) => p.toLowerCase().endsWith('.pdf'); bool _isPdfPath(String p) => p.toLowerCase().endsWith('.pdf');
Future<void> _goTo(Widget page) async {
if (!mounted) return;
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => page));
}
void _handleBottomNav(int i) {
if (i == bottomIndex) return;
setState(() => bottomIndex = i);
if (i == 0) {
_goTo(
HomePage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
);
return;
}
if (i == 1) {
_goTo(
LessonsPage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
);
return;
}
if (i == 2) {
// siamo già in "area account", non facciamo nulla (o TODO)
return;
}
if (i == 3) {
_goTo(
MeditationPage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
);
return;
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@@ -359,10 +308,11 @@ class _MedicalCertificatesPageState extends State<MedicalCertificatesPage> {
], ],
), ),
// ✅ Bottom nav standard (come MeditationPage)
bottomNavigationBar: AppBottomNav( bottomNavigationBar: AppBottomNav(
currentIndex: bottomIndex, currentIndex: 2,
onTap: _handleBottomNav, token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
), ),
body: YogibookBackground( body: YogibookBackground(
+9 -63
View File
@@ -64,8 +64,6 @@ class _MeditationPageState extends State<MeditationPage>
late final AnimationController _pulseCtrl; late final AnimationController _pulseCtrl;
late final AnimationController _squareCtrl; late final AnimationController _squareCtrl;
int bottomIndex = 3; // Meditazione
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -256,42 +254,6 @@ class _MeditationPageState extends State<MeditationPage>
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => page)); Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => page));
} }
void _handleBottomNav(int i) {
if (i == bottomIndex) return;
setState(() => bottomIndex = i);
if (i == 0) {
_goTo(
HomePage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
);
return;
}
if (i == 1) {
_goTo(
LessonsPage(
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
);
return;
}
if (i == 2) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('TODO: vai ad Account')));
return;
}
// i == 3 => già qui
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final bubbleScale = Tween<double>( final bubbleScale = Tween<double>(
@@ -340,31 +302,15 @@ class _MeditationPageState extends State<MeditationPage>
), ),
], ],
), ),
bottomNavigationBar: BottomNavigationBar( bottomNavigationBar: AppBottomNav(
type: BottomNavigationBarType.fixed, currentIndex: 3,
backgroundColor: Colors.white, token: widget.token,
selectedItemColor: kGreen, school: widget.school,
unselectedItemColor: Colors.black54, userFirstName: widget.userFirstName,
currentIndex: bottomIndex, onBeforeLeave: () async {
onTap: _handleBottomNav, _pause();
items: const [ await _stopMusic();
BottomNavigationBarItem( },
icon: Icon(Icons.home_rounded),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.event_note_rounded),
label: 'Lezioni',
),
BottomNavigationBarItem(
icon: Icon(Icons.person_rounded),
label: 'Account',
),
BottomNavigationBarItem(
icon: Icon(Icons.self_improvement_rounded),
label: 'Meditazione',
),
],
), ),
body: YogibookBackground( body: YogibookBackground(
child: SafeArea( child: SafeArea(
+16 -1
View File
@@ -1,15 +1,24 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import '../models/lesson.dart'; import '../models/lesson.dart';
import '../models/school.dart';
import '../services/lessons_api.dart'; import '../services/lessons_api.dart';
import '../widgets/yogibook_background.dart'; import '../widgets/yogibook_background.dart';
import '../widgets/app_bottom_nav.dart';
/// Schermata "I miei ordini": lista ordini con conteggi. /// Schermata "I miei ordini": lista ordini con conteggi.
/// Toccando un ordine si apre il dettaglio (box + lezioni). /// Toccando un ordine si apre il dettaglio (box + lezioni).
class OrdersDetailPage extends StatefulWidget { class OrdersDetailPage extends StatefulWidget {
final String token; final String token;
final School school;
final String? userFirstName;
const OrdersDetailPage({super.key, required this.token}); const OrdersDetailPage({
super.key,
required this.token,
required this.school,
this.userFirstName,
});
@override @override
State<OrdersDetailPage> createState() => _OrdersDetailPageState(); State<OrdersDetailPage> createState() => _OrdersDetailPageState();
@@ -63,6 +72,12 @@ class _OrdersDetailPageState extends State<OrdersDetailPage> {
style: TextStyle(fontWeight: FontWeight.w800, fontSize: 18), style: TextStyle(fontWeight: FontWeight.w800, fontSize: 18),
), ),
), ),
bottomNavigationBar: AppBottomNav(
currentIndex: 1,
token: widget.token,
school: widget.school,
userFirstName: widget.userFirstName,
),
body: YogibookBackground( body: YogibookBackground(
child: SafeArea( child: SafeArea(
top: false, top: false,
+150
View File
@@ -0,0 +1,150 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'login_page.dart';
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
@override
State<SplashPage> createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> {
// rosso bordeaux ripreso dal cuore del logo YogaSoul
static const Color kRed = Color(0xFFB01E28);
Timer? _timer;
@override
void initState() {
super.initState();
// dopo ~2.5s vai al login
_timer = Timer(const Duration(milliseconds: 5000), _goToLogin);
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
void _goToLogin() {
if (!mounted) return;
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => const LoginPage()),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
// tocca lo schermo per saltare subito al login
body: GestureDetector(
onTap: _goToLogin,
child: Stack(
fit: StackFit.expand,
children: [
// ---- Foto di sfondo full-screen
Image.asset('assets/images/splash_bg.png', fit: BoxFit.cover),
// ---- Contenuto (logo + testo) in alto
SafeArea(
child: Padding(
padding: const EdgeInsets.fromLTRB(24, 10, 24, 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 8),
// Logo YogaSoul
Image.asset(
'assets/images/yogasoul_logo.png',
height: 90,
fit: BoxFit.contain,
),
const SizedBox(height: 26),
// ---- Blocco testo su velo bianco morbido per leggibilità
Container(
padding: const EdgeInsets.symmetric(
horizontal: 18,
vertical: 16,
),
decoration: BoxDecoration(
// velo bianco semitrasparente: stacca il testo dal cielo
color: Colors.white.withOpacity(0.42),
borderRadius: BorderRadius.circular(20),
),
child: Column(
children: [
// Titolo riga 1 (scuro)
const Text(
'Il tuo spazio.',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 30,
height: 1.1,
fontWeight: FontWeight.w900,
color: Color(0xFF1F1F1F),
),
),
// Titolo riga 2 (rosso bordeaux)
const Text(
'La tua energia.',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 30,
height: 1.1,
fontWeight: FontWeight.w900,
color: kRed,
),
),
const SizedBox(height: 14),
// Sottotitolo
const Text(
'Ti diamo il benvenuto in YogiBook,\n'
'lapp della scuola YogaSoul — Seregno.\n'
'Ti accompagna nelle tue lezioni e nei tuoi pacchetti.',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
height: 1.4,
fontWeight: FontWeight.w600,
color: Color(0xFF2A2A2A),
),
),
],
),
),
],
),
),
),
// ---- Indicatore caricamento in basso
const Positioned(
left: 0,
right: 0,
bottom: 34,
child: Center(
child: SizedBox(
width: 26,
height: 26,
child: CircularProgressIndicator(
strokeWidth: 2.4,
valueColor: AlwaysStoppedAnimation(Colors.white),
),
),
),
),
],
),
),
);
}
}
-84
View File
@@ -1,84 +0,0 @@
import 'package:flutter/material.dart';
import 'main.dart'; // per VanguardApi
class SelectSchoolPage extends StatefulWidget {
final String token;
const SelectSchoolPage({super.key, required this.token});
@override
State<SelectSchoolPage> createState() => _SelectSchoolPageState();
}
class _SelectSchoolPageState extends State<SelectSchoolPage> {
bool loading = true;
String error = '';
List schools = [];
@override
void initState() {
super.initState();
_loadSchools();
}
Future<void> _loadSchools() async {
try {
final data = await VanguardApi.getUserSchools(token: widget.token);
if (data['success'] != true) {
throw Exception(data['message'] ?? 'Errore sconosciuto');
}
final List list = data['schools'] ?? [];
// Auto select
if (data['auto_select'] == true && list.length == 1) {
_enterSchool(list.first);
return;
}
setState(() {
schools = list;
loading = false;
});
} catch (e) {
setState(() {
error = e.toString();
loading = false;
});
}
}
void _enterSchool(Map school) {
// per ora debug
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => SuccessPage(token: widget.token)),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Scegli la scuola')),
body: loading
? const Center(child: CircularProgressIndicator())
: error.isNotEmpty
? Center(child: Text(error))
: ListView.builder(
itemCount: schools.length,
itemBuilder: (context, i) {
final s = schools[i];
return ListTile(
leading: s['logo'] != null
? Image.network(s['logo'], width: 40)
: const Icon(Icons.school),
title: Text(s['name']),
subtitle: Text(s['address_full'] ?? ''),
onTap: () => _enterSchool(s),
);
},
),
);
}
}
+67 -3
View File
@@ -1,15 +1,79 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../models/school.dart';
import '../screens/home_page.dart';
import '../screens/lessons_page.dart';
import '../screens/account_page.dart';
import '../screens/meditation_page.dart';
/// Bottom navigation centralizzata.
/// Gestisce da sé la navigazione tra le 4 tab principali.
/// Ogni pagina passa solo il proprio [currentIndex] e i dati utente.
///
/// [onBeforeLeave] è opzionale: le pagine che devono fare pulizia prima di
/// uscire (es. Meditazione che ferma musica/timer) lo passano.
class AppBottomNav extends StatelessWidget { class AppBottomNav extends StatelessWidget {
final int currentIndex; final int currentIndex;
final ValueChanged<int> onTap; final String token;
final School school;
final String? userFirstName;
final Future<void> Function()? onBeforeLeave;
const AppBottomNav({ const AppBottomNav({
super.key, super.key,
required this.currentIndex, required this.currentIndex,
required this.onTap, required this.token,
required this.school,
this.userFirstName,
this.onBeforeLeave,
}); });
Future<void> _go(BuildContext context, int i) async {
if (i == currentIndex) return;
// pulizia eventuale (musica/timer) prima di lasciare la pagina
if (onBeforeLeave != null) {
await onBeforeLeave!();
}
if (!context.mounted) return;
Widget page;
switch (i) {
case 0:
page = HomePage(
token: token,
school: school,
userFirstName: userFirstName,
);
break;
case 1:
page = LessonsPage(
token: token,
school: school,
userFirstName: userFirstName,
);
break;
case 2:
page = AccountPage(
token: token,
school: school,
userFirstName: userFirstName,
);
break;
case 3:
page = MeditationPage(
token: token,
school: school,
userFirstName: userFirstName,
);
break;
default:
return;
}
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => page));
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BottomNavigationBar( return BottomNavigationBar(
@@ -18,7 +82,7 @@ class AppBottomNav extends StatelessWidget {
selectedItemColor: const Color(0xFF10B981), selectedItemColor: const Color(0xFF10B981),
unselectedItemColor: Colors.black54, unselectedItemColor: Colors.black54,
currentIndex: currentIndex, currentIndex: currentIndex,
onTap: onTap, onTap: (i) => _go(context, i),
items: const [ items: const [
BottomNavigationBarItem(icon: Icon(Icons.home_rounded), label: 'Home'), BottomNavigationBarItem(icon: Icon(Icons.home_rounded), label: 'Home'),
BottomNavigationBarItem( BottomNavigationBarItem(
+5 -1
View File
@@ -127,7 +127,11 @@ class AppDrawer extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (_) => OrdersDetailPage(token: token), builder: (_) => OrdersDetailPage(
token: token,
school: school,
userFirstName: userFirstName,
),
), ),
); );
}, },
+2
View File
@@ -67,6 +67,8 @@ flutter:
uses-material-design: true uses-material-design: true
assets: assets:
- assets/images/yogibook_logo.png - assets/images/yogibook_logo.png
- assets/images/splash_bg.png
- assets/images/yogasoul_logo.png
- assets/audio/meditation.mp3 - assets/audio/meditation.mp3
# To add assets to your application, add an assets section, like this: # To add assets to your application, add an assets section, like this: