import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'src/calendar_screen.dart'; import 'src/education_screen.dart'; import 'src/resume_screen.dart'; import 'src/settings_screen.dart'; void main() { runApp(const MyApp()); } // Color Palette const Color darkJungleGreen = Color(0xFF000505); const Color englishViolet = Color(0xFF3B3355); const Color slateGray = Color(0xFF5D5D81); const Color lightSteelBlue = Color(0xFFBFCDE0); const Color ghostWhite = Color(0xFFFEFCFD); class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override State createState() => _MyAppState(); } class _MyAppState extends State { bool _isDarkMode = false; void _toggleTheme(bool isDark) { setState(() { _isDarkMode = isDark; }); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Connect', theme: ThemeData( brightness: Brightness.light, primaryColor: englishViolet, scaffoldBackgroundColor: ghostWhite, colorScheme: const ColorScheme.light( primary: englishViolet, secondary: slateGray, surface: ghostWhite, background: ghostWhite, onPrimary: ghostWhite, onSecondary: darkJungleGreen, onSurface: darkJungleGreen, onBackground: darkJungleGreen, error: Colors.red, onError: ghostWhite, ), appBarTheme: const AppBarTheme( backgroundColor: englishViolet, foregroundColor: ghostWhite, titleTextStyle: TextStyle(fontFamily: 'Poppins', fontSize: 20, fontWeight: FontWeight.bold), ), textTheme: const TextTheme( bodyLarge: TextStyle(color: darkJungleGreen), titleLarge: TextStyle(color: darkJungleGreen, fontWeight: FontWeight.bold), ), floatingActionButtonTheme: const FloatingActionButtonThemeData( backgroundColor: englishViolet, foregroundColor: ghostWhite, ), ), darkTheme: ThemeData( brightness: Brightness.dark, primaryColor: lightSteelBlue, scaffoldBackgroundColor: darkJungleGreen, colorScheme: const ColorScheme.dark( primary: lightSteelBlue, secondary: slateGray, surface: darkJungleGreen, background: darkJungleGreen, onPrimary: darkJungleGreen, onSecondary: ghostWhite, onSurface: ghostWhite, onBackground: ghostWhite, error: Colors.red, onError: ghostWhite, ), appBarTheme: const AppBarTheme( backgroundColor: slateGray, foregroundColor: ghostWhite, titleTextStyle: TextStyle(fontFamily: 'Poppins', fontSize: 20, fontWeight: FontWeight.bold), ), textTheme: const TextTheme( bodyLarge: TextStyle(color: ghostWhite), titleLarge: TextStyle(color: ghostWhite, fontWeight: FontWeight.bold), ), floatingActionButtonTheme: const FloatingActionButtonThemeData( backgroundColor: lightSteelBlue, foregroundColor: darkJungleGreen, ), ), themeMode: _isDarkMode ? ThemeMode.dark : ThemeMode.light, home: JobListingScreen(isDarkMode: _isDarkMode, onThemeChanged: _toggleTheme), ); } } class JobListingScreen extends StatefulWidget { final bool isDarkMode; final ValueChanged onThemeChanged; const JobListingScreen({ Key? key, required this.isDarkMode, required this.onThemeChanged, }) : super(key: key); @override _JobListingScreenState createState() => _JobListingScreenState(); } class _JobListingScreenState extends State { List jobs = []; bool isLoading = true; String? error; @override void initState() { super.initState(); fetchJobs(); } Future fetchJobs() async { // IMPORTANT: Replace with your actual IP/domain in a real environment. // 10.0.2.2 is the special alias for the host machine's localhost in the Android emulator. const String apiUrl = 'http://10.0.2.2/api.php'; try { final response = await http.get(Uri.parse(apiUrl)); if (response.statusCode == 200) { final result = json.decode(response.body); if (result['success'] == true) { setState(() { jobs = result['data']; isLoading = false; }); } else { setState(() { error = result['error'] ?? 'An unknown error occurred.'; isLoading = false; }); } } else { setState(() { error = 'Failed to load jobs. Status code: ${response.statusCode}'; isLoading = false; }); } } catch (e) { setState(() { error = 'Failed to connect to the server. Please check your network connection and the API endpoint. Details: $e'; isLoading = false; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Connect'), ), drawer: Drawer( // Vertical navigation drawer child: ListView( padding: EdgeInsets.zero, children: [ const DrawerHeader( decoration: BoxDecoration( color: englishViolet, ), child: Text( 'Connect', style: TextStyle(color: Colors.white, fontSize: 24), ), ), ListTile( leading: const Icon(Icons.school), title: const Text('Education/Information'), onTap: () { Navigator.pop(context); Navigator.push(context, MaterialPageRoute(builder: (context) => const EducationScreen())); }, ), ListTile( leading: const Icon(Icons.description), title: const Text('Resume/Job Letter'), onTap: () { Navigator.pop(context); Navigator.push(context, MaterialPageRoute(builder: (context) => const ResumeScreen())); }, ), ListTile( leading: const Icon(Icons.calendar_today), title: const Text('Calendar'), onTap: () { Navigator.pop(context); Navigator.push(context, MaterialPageRoute(builder: (context) => const CalendarScreen())); }, ), ListTile( leading: const Icon(Icons.settings), title: const Text('Settings'), onTap: () { Navigator.pop(context); Navigator.push(context, MaterialPageRoute(builder: (context) => SettingsScreen( isDarkMode: widget.isDarkMode, onThemeChanged: widget.onThemeChanged, ))); }, ), ], ), ), body: buildBody(), floatingActionButton: FloatingActionButton( onPressed: () { // AI Chatbot action }, child: const Icon(Icons.chat), ), ); } Widget buildBody() { if (isLoading) { return const Center(child: CircularProgressIndicator()); } if (error != null) { return Center( child: Padding( padding: const EdgeInsets.all(16.0), child: Text( 'Error: $error', textAlign: TextAlign.center, style: const TextStyle(color: Colors.red, fontSize: 16), ), ), ); } if (jobs.isEmpty) { return const Center(child: Text('No jobs found.')); } return ListView.builder( itemCount: jobs.length, itemBuilder: (context, index) { final job = jobs[index]; return Card( margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), elevation: 4, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: ListTile( title: Text(job['title'] ?? 'No Title', style: Theme.of(context).textTheme.titleLarge), subtitle: Text( '${job['company'] ?? 'No Company'} - ${job['location'] ?? 'No Location'}', style: Theme.of(context).textTheme.bodyLarge, ), trailing: Text( job['salary_range'] ?? '', style: TextStyle(color: Theme.of(context).colorScheme.primary), ), onTap: () { // Show job details }, ), ); }, ); } }