First commit

This commit is contained in:
2025-05-03 15:43:29 +02:00
commit 6ebb49252e
135 changed files with 5266 additions and 0 deletions

63
lib/main.dart Normal file
View 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
View 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
View 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!')),
);
}
}
}

View 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')),
);
}
}

View 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'),
],
),
),
);
}
}

View 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'),
),
],
);
}
}

View 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))),
),
);
}
}