First commit
This commit is contained in:
63
lib/main.dart
Normal file
63
lib/main.dart
Normal file
@ -0,0 +1,63 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'screens/home_screen.dart';
|
||||
import 'screens/add_screen.dart';
|
||||
import 'screens/vehicles_screen.dart';
|
||||
import 'screens/history_screen.dart';
|
||||
|
||||
void main() {
|
||||
runApp(FuelStatsApp());
|
||||
}
|
||||
|
||||
class FuelStatsApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Fuel Stats',
|
||||
theme: ThemeData.dark(),
|
||||
themeMode: ThemeMode.dark,
|
||||
home: MainNavigation(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MainNavigation extends StatefulWidget {
|
||||
const MainNavigation({super.key});
|
||||
|
||||
@override
|
||||
_MainNavigationState createState() => _MainNavigationState();
|
||||
}
|
||||
|
||||
class _MainNavigationState extends State<MainNavigation> {
|
||||
int _currentIndex = 0;
|
||||
|
||||
final List<Widget> _screens = [
|
||||
HomeScreen(),
|
||||
AddScreen(),
|
||||
VehiclesScreen(),
|
||||
HistoryScreen(),
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: _screens[_currentIndex],
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: _currentIndex,
|
||||
onTap: (index) => setState(() => _currentIndex = index),
|
||||
backgroundColor: Colors.grey[900],
|
||||
selectedItemColor: Colors.white,
|
||||
unselectedItemColor: Colors.grey,
|
||||
|
||||
items: [
|
||||
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
|
||||
BottomNavigationBarItem(icon: Icon(Icons.add), label: 'Add'),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.directions_car),
|
||||
label: 'Vehicles',
|
||||
),
|
||||
BottomNavigationBarItem(icon: Icon(Icons.history), label: 'History'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
20
lib/main.dart.old2
Normal file
20
lib/main.dart.old2
Normal file
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() {
|
||||
runApp(MaterialApp(home: Home()));
|
||||
}
|
||||
|
||||
class Home extends StatelessWidget {
|
||||
const Home({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("Fuel Stats"),
|
||||
backgroundColor: Colors.blue[700],
|
||||
),
|
||||
body: Column(children: [Text("vim")]),
|
||||
);
|
||||
}
|
||||
}
|
129
lib/screens/add_screen.dart
Normal file
129
lib/screens/add_screen.dart
Normal file
@ -0,0 +1,129 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AddScreen extends StatefulWidget {
|
||||
@override
|
||||
_AddScreenState createState() => _AddScreenState();
|
||||
}
|
||||
|
||||
class _AddScreenState extends State<AddScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
String? _selectedVehicle;
|
||||
String? _selectedFuelType;
|
||||
final TextEditingController _litersController = TextEditingController();
|
||||
final TextEditingController _pricePerLiterController =
|
||||
TextEditingController();
|
||||
final TextEditingController _totalPriceController = TextEditingController();
|
||||
final TextEditingController _mileageController = TextEditingController();
|
||||
final TextEditingController _noteController = TextEditingController();
|
||||
|
||||
final List<String> _vehicles = ['Car A', 'Car B', 'Car C'];
|
||||
final List<String> _fuelTypes = ['Gasoline', 'Diesel', 'Electric'];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('Add Entry')),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
DropdownButtonFormField<String>(
|
||||
decoration: InputDecoration(labelText: 'Vehicle'),
|
||||
value: _selectedVehicle,
|
||||
items:
|
||||
_vehicles.map((vehicle) {
|
||||
return DropdownMenuItem(
|
||||
value: vehicle,
|
||||
child: Text(vehicle),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged:
|
||||
(value) => setState(() => _selectedVehicle = value),
|
||||
validator:
|
||||
(value) =>
|
||||
value == null ? 'Please select a vehicle' : null,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
DropdownButtonFormField<String>(
|
||||
decoration: InputDecoration(labelText: 'Fuel Type'),
|
||||
value: _selectedFuelType,
|
||||
items:
|
||||
_fuelTypes.map((fuel) {
|
||||
return DropdownMenuItem(value: fuel, child: Text(fuel));
|
||||
}).toList(),
|
||||
onChanged:
|
||||
(value) => setState(() => _selectedFuelType = value),
|
||||
validator:
|
||||
(value) =>
|
||||
value == null ? 'Please select a fuel type' : null,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
TextFormField(
|
||||
controller: _litersController,
|
||||
decoration: InputDecoration(labelText: 'Liters'),
|
||||
keyboardType: TextInputType.number,
|
||||
validator: _numberValidator,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
TextFormField(
|
||||
controller: _pricePerLiterController,
|
||||
decoration: InputDecoration(labelText: 'Price per Liter'),
|
||||
keyboardType: TextInputType.number,
|
||||
validator: _numberValidator,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
TextFormField(
|
||||
controller: _totalPriceController,
|
||||
decoration: InputDecoration(labelText: 'Total Price'),
|
||||
keyboardType: TextInputType.number,
|
||||
validator: _numberValidator,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
TextFormField(
|
||||
controller: _mileageController,
|
||||
decoration: InputDecoration(labelText: 'Mileage'),
|
||||
keyboardType: TextInputType.number,
|
||||
validator: _numberValidator,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
TextFormField(
|
||||
controller: _noteController,
|
||||
decoration: InputDecoration(labelText: 'Note'),
|
||||
keyboardType: TextInputType.text,
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: _submitForm,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.green, // green confirm button
|
||||
),
|
||||
child: Text('Create Fuel Record'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String? _numberValidator(String? value) {
|
||||
if (value == null || value.isEmpty) return 'This field cannot be empty';
|
||||
if (double.tryParse(value) == null) return 'Enter a valid number';
|
||||
return null;
|
||||
}
|
||||
|
||||
void _submitForm() {
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
// Here you would save the form data to database or state
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Fuel record created successfully!')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
11
lib/screens/history_screen.dart
Normal file
11
lib/screens/history_screen.dart
Normal file
@ -0,0 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HistoryScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('History')),
|
||||
body: Center(child: Text('History Screen Content')),
|
||||
);
|
||||
}
|
||||
}
|
20
lib/screens/home_screen.dart
Normal file
20
lib/screens/home_screen.dart
Normal file
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../widgets/data_section.dart';
|
||||
|
||||
class HomeScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('Fuel Stats')),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
DataSection(title: 'Fuel Consumption'),
|
||||
DataSection(title: 'Cost Over Time'),
|
||||
DataSection(title: 'Mileage Trends'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
197
lib/screens/vehicles_screen.dart
Normal file
197
lib/screens/vehicles_screen.dart
Normal file
@ -0,0 +1,197 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum FuelType { Diesel, Gasoline95, Gasoline98, Other }
|
||||
|
||||
class Vehicle {
|
||||
final String name;
|
||||
final String registrationPlate;
|
||||
final FuelType fuelType;
|
||||
final String? note;
|
||||
|
||||
Vehicle({
|
||||
required this.name,
|
||||
required this.registrationPlate,
|
||||
required this.fuelType,
|
||||
this.note,
|
||||
});
|
||||
}
|
||||
|
||||
class VehiclesScreen extends StatefulWidget {
|
||||
@override
|
||||
_VehiclesScreenState createState() => _VehiclesScreenState();
|
||||
}
|
||||
|
||||
class _VehiclesScreenState extends State<VehiclesScreen> {
|
||||
final List<Vehicle> _vehicles = [];
|
||||
|
||||
void _addVehicle() async {
|
||||
final newVehicle = await showDialog<Vehicle>(
|
||||
context: context,
|
||||
builder: (context) => _AddVehicleDialog(),
|
||||
);
|
||||
if (newVehicle != null) {
|
||||
setState(() {
|
||||
_vehicles.add(newVehicle);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _removeVehicle(int index) async {
|
||||
final confirm = await showDialog<bool>(
|
||||
context: context,
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text('Confirm Removal'),
|
||||
content: Text('Are you sure you want to delete this vehicle?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: Text('Delete'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (confirm == true) {
|
||||
setState(() {
|
||||
_vehicles.removeAt(index);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
String _fuelTypeToString(FuelType fuelType) {
|
||||
switch (fuelType) {
|
||||
case FuelType.Diesel:
|
||||
return 'Diesel';
|
||||
case FuelType.Gasoline95:
|
||||
return 'Gasoline 95';
|
||||
case FuelType.Gasoline98:
|
||||
return 'Gasoline 98';
|
||||
case FuelType.Other:
|
||||
return 'Other';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('Vehicles')),
|
||||
body:
|
||||
_vehicles.isEmpty
|
||||
? Center(child: Text('No vehicles added yet.'))
|
||||
: ListView.builder(
|
||||
itemCount: _vehicles.length,
|
||||
itemBuilder: (context, index) {
|
||||
final vehicle = _vehicles[index];
|
||||
return ListTile(
|
||||
title: Text(vehicle.name),
|
||||
subtitle: Text(
|
||||
'${vehicle.registrationPlate} • ${_fuelTypeToString(vehicle.fuelType)}${vehicle.note != null ? ' • ${vehicle.note}' : ''}',
|
||||
),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.delete, color: Colors.red),
|
||||
onPressed: () => _removeVehicle(index),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _addVehicle,
|
||||
child: Icon(Icons.add),
|
||||
tooltip: 'Add Vehicle',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AddVehicleDialog extends StatefulWidget {
|
||||
@override
|
||||
_AddVehicleDialogState createState() => _AddVehicleDialogState();
|
||||
}
|
||||
|
||||
class _AddVehicleDialogState extends State<_AddVehicleDialog> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _nameController = TextEditingController();
|
||||
final _plateController = TextEditingController();
|
||||
final _noteController = TextEditingController();
|
||||
FuelType? _selectedFuelType;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Add New Vehicle'),
|
||||
content: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: _nameController,
|
||||
decoration: InputDecoration(labelText: 'Vehicle Name'),
|
||||
validator:
|
||||
(value) =>
|
||||
value == null || value.isEmpty
|
||||
? 'Enter a vehicle name'
|
||||
: null,
|
||||
),
|
||||
TextFormField(
|
||||
controller: _plateController,
|
||||
decoration: InputDecoration(labelText: 'Registration Plate'),
|
||||
validator:
|
||||
(value) =>
|
||||
value == null || value.isEmpty
|
||||
? 'Enter a plate number'
|
||||
: null,
|
||||
),
|
||||
DropdownButtonFormField<FuelType>(
|
||||
decoration: InputDecoration(labelText: 'Fuel Type'),
|
||||
value: _selectedFuelType,
|
||||
items:
|
||||
FuelType.values.map((fuelType) {
|
||||
return DropdownMenuItem(
|
||||
value: fuelType,
|
||||
child: Text(fuelType.name),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) => setState(() => _selectedFuelType = value),
|
||||
validator:
|
||||
(value) =>
|
||||
value == null ? 'Please select a fuel type' : null,
|
||||
),
|
||||
TextFormField(
|
||||
controller: _noteController,
|
||||
decoration: InputDecoration(labelText: 'Note (optional)'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('Cancel'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
final vehicle = Vehicle(
|
||||
name: _nameController.text,
|
||||
registrationPlate: _plateController.text,
|
||||
fuelType: _selectedFuelType!,
|
||||
note:
|
||||
_noteController.text.isEmpty ? null : _noteController.text,
|
||||
);
|
||||
Navigator.pop(context, vehicle);
|
||||
}
|
||||
},
|
||||
child: Text('Add'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
19
lib/widgets/data_section.dart
Normal file
19
lib/widgets/data_section.dart
Normal file
@ -0,0 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DataSection extends StatelessWidget {
|
||||
final String title;
|
||||
|
||||
const DataSection({required this.title});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
margin: EdgeInsets.all(16),
|
||||
child: Container(
|
||||
height: 200,
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Center(child: Text(title, style: TextStyle(fontSize: 18))),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user