feat: Implement home screen with navigation and update login flow
This commit is contained in:
@@ -105,7 +105,6 @@
|
|||||||
45421BF3EE052CE5236E185A /* Pods-RunnerTests.release.xcconfig */,
|
45421BF3EE052CE5236E185A /* Pods-RunnerTests.release.xcconfig */,
|
||||||
79C02E3489ECFAEE3BBD5226 /* Pods-RunnerTests.profile.xcconfig */,
|
79C02E3489ECFAEE3BBD5226 /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
name = Pods;
|
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -474,11 +473,14 @@
|
|||||||
DEVELOPMENT_TEAM = R9PZGUCNJ3;
|
DEVELOPMENT_TEAM = R9PZGUCNJ3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "";
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mcbeno;
|
MARKETING_VERSION = 1.0.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = lol.devbeni.mcbeno;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -657,11 +659,14 @@
|
|||||||
DEVELOPMENT_TEAM = R9PZGUCNJ3;
|
DEVELOPMENT_TEAM = R9PZGUCNJ3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "";
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mcbeno;
|
MARKETING_VERSION = 1.0.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = lol.devbeni.mcbeno;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
@@ -680,11 +685,14 @@
|
|||||||
DEVELOPMENT_TEAM = R9PZGUCNJ3;
|
DEVELOPMENT_TEAM = R9PZGUCNJ3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "";
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mcbeno;
|
MARKETING_VERSION = 1.0.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = lol.devbeni.mcbeno;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
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">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
@@ -24,6 +26,8 @@
|
|||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
@@ -41,9 +45,5 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
|
||||||
<true/>
|
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'screens/login_screen.dart';
|
|||||||
import 'screens/profile_screen.dart';
|
import 'screens/profile_screen.dart';
|
||||||
import 'screens/schedule_screen.dart';
|
import 'screens/schedule_screen.dart';
|
||||||
import 'screens/splash_screen.dart';
|
import 'screens/splash_screen.dart';
|
||||||
|
import 'screens/home_screen.dart';
|
||||||
import 'services/auth_service.dart';
|
import 'services/auth_service.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@@ -26,6 +27,7 @@ class MyApp extends StatelessWidget {
|
|||||||
routes: {
|
routes: {
|
||||||
'/splash': (context) => SplashScreen(),
|
'/splash': (context) => SplashScreen(),
|
||||||
'/': (context) => LoginScreen(),
|
'/': (context) => LoginScreen(),
|
||||||
|
'/home': (context) => HomeScreen(),
|
||||||
'/profile': (context) => ProfileScreen(),
|
'/profile': (context) => ProfileScreen(),
|
||||||
'/schedule': (context) => ScheduleScreen(),
|
'/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; });
|
setState(() { _loading = true; });
|
||||||
final ok = await auth.login(username, password);
|
final ok = await auth.login(username, password);
|
||||||
setState(() { _loading = false; });
|
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')));
|
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'),
|
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() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_ctrl = AnimationController(vsync: this, duration: Duration(seconds: 3))..repeat(reverse: true);
|
_ctrl = AnimationController(vsync: this, duration: Duration(seconds: 3))..repeat(reverse: true);
|
||||||
// simulate load then navigate
|
// simulate load then navigate depending on token presence
|
||||||
Timer(Duration(seconds: 2), () {
|
Timer(Duration(seconds: 1), () {
|
||||||
Navigator.pushReplacementNamed(context, '/');
|
Navigator.pushReplacementNamed(context, '/home');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,13 +30,24 @@ class AuthService extends ChangeNotifier {
|
|||||||
|
|
||||||
Future<void> loadProfile() async {
|
Future<void> loadProfile() async {
|
||||||
if (token == null) return;
|
if (token == null) return;
|
||||||
final res = await http.get(
|
try {
|
||||||
Uri.parse('https://menuapi.devbeni.lol/api/me'),
|
final res = await http.get(
|
||||||
headers: {'Authorization': 'Bearer $token'},
|
Uri.parse('https://menuapi.devbeni.lol/api/me'),
|
||||||
);
|
headers: {'Authorization': 'Bearer $token'},
|
||||||
if (res.statusCode == 200) {
|
);
|
||||||
profile = jsonDecode(res.body)['data'];
|
if (res.statusCode == 200) {
|
||||||
notifyListeners();
|
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