feat: Implement home screen with navigation and update login flow
This commit is contained in:
@@ -105,7 +105,6 @@
|
||||
45421BF3EE052CE5236E185A /* Pods-RunnerTests.release.xcconfig */,
|
||||
79C02E3489ECFAEE3BBD5226 /* Pods-RunnerTests.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -474,11 +473,14 @@
|
||||
DEVELOPMENT_TEAM = R9PZGUCNJ3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mcbeno;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = lol.devbeni.mcbeno;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -657,11 +659,14 @@
|
||||
DEVELOPMENT_TEAM = R9PZGUCNJ3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mcbeno;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = lol.devbeni.mcbeno;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -680,11 +685,14 @@
|
||||
DEVELOPMENT_TEAM = R9PZGUCNJ3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mcbeno;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = lol.devbeni.mcbeno;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
@@ -24,6 +26,8 @@
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
@@ -41,9 +45,5 @@
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'screens/login_screen.dart';
|
||||
import 'screens/profile_screen.dart';
|
||||
import 'screens/schedule_screen.dart';
|
||||
import 'screens/splash_screen.dart';
|
||||
import 'screens/home_screen.dart';
|
||||
import 'services/auth_service.dart';
|
||||
|
||||
void main() {
|
||||
@@ -26,6 +27,7 @@ class MyApp extends StatelessWidget {
|
||||
routes: {
|
||||
'/splash': (context) => SplashScreen(),
|
||||
'/': (context) => LoginScreen(),
|
||||
'/home': (context) => HomeScreen(),
|
||||
'/profile': (context) => ProfileScreen(),
|
||||
'/schedule': (context) => ScheduleScreen(),
|
||||
},
|
||||
|
||||
31
lib/screens/home_screen.dart
Normal file
31
lib/screens/home_screen.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'schedule_screen.dart';
|
||||
import 'profile_screen.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
@override
|
||||
_HomeScreenState createState() => _HomeScreenState();
|
||||
}
|
||||
|
||||
class _HomeScreenState extends State<HomeScreen> {
|
||||
int _idx = 0;
|
||||
final _pages = [ScheduleScreen(), ProfileScreen()];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: _pages[_idx],
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: _idx,
|
||||
backgroundColor: Color(0xFF0c0a0a),
|
||||
selectedItemColor: Color(0xFFA24BFA),
|
||||
unselectedItemColor: Colors.white70,
|
||||
items: [
|
||||
BottomNavigationBarItem(icon: Icon(Icons.calendar_today), label: 'Beosztás'),
|
||||
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profil'),
|
||||
],
|
||||
onTap: (i) => setState(() { _idx = i; }),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
setState(() { _loading = true; });
|
||||
final ok = await auth.login(username, password);
|
||||
setState(() { _loading = false; });
|
||||
if (ok) Navigator.pushReplacementNamed(context, '/profile');
|
||||
if (ok) Navigator.pushReplacementNamed(context, '/home');
|
||||
else ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Bejelentkezés sikertelen')));
|
||||
},
|
||||
child: _loading ? SizedBox(height: 16, width: 16, child: CircularProgressIndicator(strokeWidth: 2)) : Text('Bejelentkezés'),
|
||||
|
||||
@@ -13,9 +13,9 @@ class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderSt
|
||||
void initState() {
|
||||
super.initState();
|
||||
_ctrl = AnimationController(vsync: this, duration: Duration(seconds: 3))..repeat(reverse: true);
|
||||
// simulate load then navigate
|
||||
Timer(Duration(seconds: 2), () {
|
||||
Navigator.pushReplacementNamed(context, '/');
|
||||
// simulate load then navigate depending on token presence
|
||||
Timer(Duration(seconds: 1), () {
|
||||
Navigator.pushReplacementNamed(context, '/home');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,24 @@ class AuthService extends ChangeNotifier {
|
||||
|
||||
Future<void> loadProfile() async {
|
||||
if (token == null) return;
|
||||
try {
|
||||
final res = await http.get(
|
||||
Uri.parse('https://menuapi.devbeni.lol/api/me'),
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
);
|
||||
if (res.statusCode == 200) {
|
||||
profile = jsonDecode(res.body)['data'];
|
||||
final body = jsonDecode(res.body);
|
||||
// Try common shapes: { data: {...} } or { user: {...} } or the whole body
|
||||
if (body is Map && body['data'] is Map) profile = Map<String, dynamic>.from(body['data']);
|
||||
else if (body is Map && body['user'] is Map) profile = Map<String, dynamic>.from(body['user']);
|
||||
else if (body is Map && body['FullName'] != null) profile = Map<String, dynamic>.from(body);
|
||||
else profile = {'raw': body};
|
||||
notifyListeners();
|
||||
} else {
|
||||
if (kDebugMode) print('[AuthService] loadProfile failed ${res.statusCode}: ${res.body}');
|
||||
}
|
||||
} catch (e) {
|
||||
if (kDebugMode) print('[AuthService] loadProfile error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user