checkpoint prima del rename package

This commit is contained in:
2026-08-22 14:59:44 +02:00
parent 770c89ca3f
commit e87292dda7
15 changed files with 271 additions and 46 deletions
+75 -31
View File
@@ -8,6 +8,7 @@ import 'home_page.dart';
import 'meditation_page.dart';
import '../widgets/app_drawer.dart';
import '../widgets/app_bottom_nav.dart';
import 'package:url_launcher/url_launcher.dart';
import '../widgets/yogibook_background.dart';
import 'reschedule_page.dart';
import 'orders_page.dart';
@@ -179,40 +180,83 @@ class _LessonsPageState extends State<LessonsPage> {
),
),
// Bottone "Programma lezioni" (solo se ci sono ticket residui)
if (summary != null && summary!.toSchedule > 0)
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
child: SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF10B981),
padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
icon: const Icon(Icons.add, color: Colors.white),
label: Text(
'Programma lezioni (${summary!.toSchedule} disponibili)',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w800,
),
),
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (_) => OrdersPage(token: widget.token),
// Bottoni azione: Programma (condizionale) + Acquista (sempre)
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
child: Row(
children: [
if (summary != null && summary!.toSchedule > 0) ...[
Expanded(
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF4F46E5),
padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
);
_load();
},
icon: const Icon(Icons.add, color: Colors.white),
label: Text(
'Programma (${summary!.toSchedule})',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w800,
),
),
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (_) => OrdersPage(token: widget.token),
),
);
_load();
},
),
),
const SizedBox(width: 8),
],
Expanded(
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFF59E0B),
padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
icon: const Icon(
Icons.shopping_bag_outlined,
color: Colors.white,
),
label: const Text(
'Acquista pacchetti',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w800,
),
),
onPressed: () async {
final uri = Uri.parse(
'https://yogasoul.it/abbonamenti-prezzi-yoga-seregno/',
);
if (!await launchUrl(
uri,
mode: LaunchMode.externalApplication,
)) {
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Impossibile aprire il link'),
),
);
}
},
),
),
),
],
),
),
Expanded(
child: loading
+1
View File
@@ -0,0 +1 @@
+40 -13
View File
@@ -15,12 +15,20 @@ class _SplashPageState extends State<SplashPage> {
static const Color kRed = Color(0xFFB01E28);
Timer? _timer;
int _seconds = 5; // countdown iniziale
@override
void initState() {
super.initState();
// dopo ~2.5s vai al login
_timer = Timer(const Duration(milliseconds: 5000), _goToLogin);
// countdown 5 → 0, poi vai al login
_timer = Timer.periodic(const Duration(seconds: 1), (t) {
if (!mounted) return;
setState(() => _seconds--);
if (_seconds <= 0) {
t.cancel();
_goToLogin();
}
});
}
@override
@@ -126,20 +134,39 @@ class _SplashPageState extends State<SplashPage> {
),
),
// ---- Indicatore caricamento in basso
const Positioned(
// ---- Logo YogiBook + countdown in basso
Positioned(
left: 0,
right: 0,
bottom: 34,
child: Center(
child: SizedBox(
width: 26,
height: 26,
child: CircularProgressIndicator(
strokeWidth: 2.4,
valueColor: AlwaysStoppedAnimation(Colors.white),
bottom: 30,
child: Column(
children: [
Image.asset(
'assets/images/yogibook_logo.png',
height: 40,
fit: BoxFit.contain,
),
),
const SizedBox(height: 14),
// Countdown numerico dentro un cerchio
Container(
width: 40,
height: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white.withValues(alpha: 0.25),
border: Border.all(color: Colors.white, width: 1.5),
),
child: Text(
'$_seconds',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w900,
fontSize: 18,
),
),
),
],
),
),
],
+1
View File
@@ -0,0 +1 @@
+34
View File
@@ -9,6 +9,7 @@ import '../screens/medical_certificates_page.dart';
import '../screens/lessons_page.dart';
import '../screens/orders_detail_page.dart';
import '../screens/account_page.dart';
import 'package:url_launcher/url_launcher.dart';
class AppDrawer extends StatelessWidget {
final String token;
@@ -33,6 +34,16 @@ class AppDrawer extends StatelessWidget {
return '${ApiConfig.scheme}://${ApiConfig.host}/public/userarea/$raw';
}
Future<void> _openUrl(BuildContext context, String url) async {
final uri = Uri.parse(url);
final ok = await launchUrl(uri, mode: LaunchMode.externalApplication);
if (!ok && context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Impossibile aprire il link.')),
);
}
}
Future<void> _logout(BuildContext context) async {
final ok = await showDialog<bool>(
context: context,
@@ -157,6 +168,29 @@ class AppDrawer extends StatelessWidget {
const Divider(height: 1),
ListTile(
leading: const Icon(Icons.privacy_tip_outlined),
title: const Text('Cookie e Privacy Policy'),
onTap: () {
Navigator.of(context).pop();
_openUrl(context, 'https://yogasoul.it/cookie-policy/');
},
),
ListTile(
leading: const Icon(Icons.description_outlined),
title: const Text('Condizioni generali'),
onTap: () {
Navigator.of(context).pop();
_openUrl(
context,
'https://yogasoul.it/condizioni-generali-di-vendita/',
);
},
),
const Divider(height: 1),
ListTile(
leading: const Icon(Icons.logout),
title: const Text('Logout'),