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
+1
View File
@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<application <application
android:label="yogibook_app" android:label="yogibook_app"
android:name="${applicationName}" android:name="${applicationName}"
@@ -1,5 +1,5 @@
package com.example.yogibook_app package com.example.yogibook_app
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity : FlutterActivity() class MainActivity : FlutterFragmentActivity()
+2
View File
@@ -28,6 +28,8 @@
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>
<string>Main</string> <string>Main</string>
<key>NSFaceIDUsageDescription</key>
<string>Usiamo Face ID per accedere rapidamente e in sicurezza al tuo account YogiBook.</string>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
+50 -6
View File
@@ -8,6 +8,7 @@ import 'home_page.dart';
import 'meditation_page.dart'; import 'meditation_page.dart';
import '../widgets/app_drawer.dart'; import '../widgets/app_drawer.dart';
import '../widgets/app_bottom_nav.dart'; import '../widgets/app_bottom_nav.dart';
import 'package:url_launcher/url_launcher.dart';
import '../widgets/yogibook_background.dart'; import '../widgets/yogibook_background.dart';
import 'reschedule_page.dart'; import 'reschedule_page.dart';
import 'orders_page.dart'; import 'orders_page.dart';
@@ -179,15 +180,16 @@ class _LessonsPageState extends State<LessonsPage> {
), ),
), ),
// Bottone "Programma lezioni" (solo se ci sono ticket residui) // Bottoni azione: Programma (condizionale) + Acquista (sempre)
if (summary != null && summary!.toSchedule > 0)
Padding( Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
child: SizedBox( child: Row(
width: double.infinity, children: [
if (summary != null && summary!.toSchedule > 0) ...[
Expanded(
child: ElevatedButton.icon( child: ElevatedButton.icon(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF10B981), backgroundColor: const Color(0xFF4F46E5),
padding: const EdgeInsets.symmetric(vertical: 12), padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14), borderRadius: BorderRadius.circular(14),
@@ -195,7 +197,7 @@ class _LessonsPageState extends State<LessonsPage> {
), ),
icon: const Icon(Icons.add, color: Colors.white), icon: const Icon(Icons.add, color: Colors.white),
label: Text( label: Text(
'Programma lezioni (${summary!.toSchedule} disponibili)', 'Programma (${summary!.toSchedule})',
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
@@ -212,6 +214,48 @@ class _LessonsPageState extends State<LessonsPage> {
}, },
), ),
), ),
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( Expanded(
+1
View File
@@ -0,0 +1 @@
+39 -12
View File
@@ -15,12 +15,20 @@ class _SplashPageState extends State<SplashPage> {
static const Color kRed = Color(0xFFB01E28); static const Color kRed = Color(0xFFB01E28);
Timer? _timer; Timer? _timer;
int _seconds = 5; // countdown iniziale
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// dopo ~2.5s vai al login // countdown 5 → 0, poi vai al login
_timer = Timer(const Duration(milliseconds: 5000), _goToLogin); _timer = Timer.periodic(const Duration(seconds: 1), (t) {
if (!mounted) return;
setState(() => _seconds--);
if (_seconds <= 0) {
t.cancel();
_goToLogin();
}
});
} }
@override @override
@@ -126,21 +134,40 @@ class _SplashPageState extends State<SplashPage> {
), ),
), ),
// ---- Indicatore caricamento in basso // ---- Logo YogiBook + countdown in basso
const Positioned( Positioned(
left: 0, left: 0,
right: 0, right: 0,
bottom: 34, bottom: 30,
child: Center( child: Column(
child: SizedBox( children: [
width: 26, Image.asset(
height: 26, 'assets/images/yogibook_logo.png',
child: CircularProgressIndicator( height: 40,
strokeWidth: 2.4, fit: BoxFit.contain,
valueColor: AlwaysStoppedAnimation(Colors.white), ),
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/lessons_page.dart';
import '../screens/orders_detail_page.dart'; import '../screens/orders_detail_page.dart';
import '../screens/account_page.dart'; import '../screens/account_page.dart';
import 'package:url_launcher/url_launcher.dart';
class AppDrawer extends StatelessWidget { class AppDrawer extends StatelessWidget {
final String token; final String token;
@@ -33,6 +34,16 @@ class AppDrawer extends StatelessWidget {
return '${ApiConfig.scheme}://${ApiConfig.host}/public/userarea/$raw'; 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 { Future<void> _logout(BuildContext context) async {
final ok = await showDialog<bool>( final ok = await showDialog<bool>(
context: context, context: context,
@@ -157,6 +168,29 @@ class AppDrawer extends StatelessWidget {
const Divider(height: 1), 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( ListTile(
leading: const Icon(Icons.logout), leading: const Icon(Icons.logout),
title: const Text('Logout'), title: const Text('Logout'),
@@ -8,6 +8,7 @@
#include <audioplayers_linux/audioplayers_linux_plugin.h> #include <audioplayers_linux/audioplayers_linux_plugin.h>
#include <file_selector_linux/file_selector_plugin.h> #include <file_selector_linux/file_selector_plugin.h>
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
@@ -17,6 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar); file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
+1
View File
@@ -5,6 +5,7 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
audioplayers_linux audioplayers_linux
file_selector_linux file_selector_linux
flutter_secure_storage_linux
url_launcher_linux url_launcher_linux
) )
@@ -8,7 +8,9 @@ import Foundation
import audioplayers_darwin import audioplayers_darwin
import file_picker import file_picker
import file_selector_macos import file_selector_macos
import flutter_secure_storage_macos
import google_sign_in_ios import google_sign_in_ios
import local_auth_darwin
import path_provider_foundation import path_provider_foundation
import shared_preferences_foundation import shared_preferences_foundation
import url_launcher_macos import url_launcher_macos
@@ -17,7 +19,9 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin"))
LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
+96
View File
@@ -219,6 +219,54 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.33" version: "2.0.33"
flutter_secure_storage:
dependency: "direct main"
description:
name: flutter_secure_storage
sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
url: "https://pub.dev"
source: hosted
version: "9.2.4"
flutter_secure_storage_linux:
dependency: transitive
description:
name: flutter_secure_storage_linux
sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688
url: "https://pub.dev"
source: hosted
version: "1.2.3"
flutter_secure_storage_macos:
dependency: transitive
description:
name: flutter_secure_storage_macos
sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247"
url: "https://pub.dev"
source: hosted
version: "3.1.3"
flutter_secure_storage_platform_interface:
dependency: transitive
description:
name: flutter_secure_storage_platform_interface
sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8
url: "https://pub.dev"
source: hosted
version: "1.1.2"
flutter_secure_storage_web:
dependency: transitive
description:
name: flutter_secure_storage_web
sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9
url: "https://pub.dev"
source: hosted
version: "1.2.1"
flutter_secure_storage_windows:
dependency: transitive
description:
name: flutter_secure_storage_windows
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
url: "https://pub.dev"
source: hosted
version: "3.1.2"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@@ -365,6 +413,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.20.2" version: "0.20.2"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
@@ -397,6 +453,46 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.0" version: "6.0.0"
local_auth:
dependency: "direct main"
description:
name: local_auth
sha256: "434d854cf478f17f12ab29a76a02b3067f86a63a6d6c4eb8fbfdcfe4879c1b7b"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
local_auth_android:
dependency: transitive
description:
name: local_auth_android
sha256: a0bdfcc0607050a26ef5b31d6b4b254581c3d3ce3c1816ab4d4f4a9173e84467
url: "https://pub.dev"
source: hosted
version: "1.0.56"
local_auth_darwin:
dependency: transitive
description:
name: local_auth_darwin
sha256: "699873970067a40ef2f2c09b4c72eb1cfef64224ef041b3df9fdc5c4c1f91f49"
url: "https://pub.dev"
source: hosted
version: "1.6.1"
local_auth_platform_interface:
dependency: transitive
description:
name: local_auth_platform_interface
sha256: f98b8e388588583d3f781f6806e4f4c9f9e189d898d27f0c249b93a1973dd122
url: "https://pub.dev"
source: hosted
version: "1.1.0"
local_auth_windows:
dependency: transitive
description:
name: local_auth_windows
sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5
url: "https://pub.dev"
source: hosted
version: "1.0.11"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
+2
View File
@@ -44,6 +44,8 @@ dependencies:
mime: ^2.0.0 mime: ^2.0.0
provider: ^6.1.5+1 provider: ^6.1.5+1
shared_preferences: ^2.2.3 shared_preferences: ^2.2.3
flutter_secure_storage: ^9.2.2
local_auth: ^2.3.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
@@ -8,6 +8,8 @@
#include <audioplayers_windows/audioplayers_windows_plugin.h> #include <audioplayers_windows/audioplayers_windows_plugin.h>
#include <file_selector_windows/file_selector_windows.h> #include <file_selector_windows/file_selector_windows.h>
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
#include <local_auth_windows/local_auth_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
@@ -15,6 +17,10 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
FileSelectorWindowsRegisterWithRegistrar( FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows")); registry->GetRegistrarForPlugin("FileSelectorWindows"));
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
LocalAuthPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows")); registry->GetRegistrarForPlugin("UrlLauncherWindows"));
} }
+2
View File
@@ -5,6 +5,8 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
audioplayers_windows audioplayers_windows
file_selector_windows file_selector_windows
flutter_secure_storage_windows
local_auth_windows
url_launcher_windows url_launcher_windows
) )