implemented IconPicker for Car class

This commit is contained in:
2022-11-16 22:54:45 -05:00
parent bc0e5f1fea
commit 4cfffa59f9
89 changed files with 342 additions and 60 deletions

View File

@@ -9,6 +9,7 @@ import 'package:dash/screens/screens.dart';
class CarDetailScreen extends StatefulWidget {
const CarDetailScreen({super.key, required this.carIndex});
final int carIndex;
// late Car car;
@override
State<CarDetailScreen> createState() => _CarDetailScreenState();
@@ -20,13 +21,13 @@ class _CarDetailScreenState extends State<CarDetailScreen> {
@override
Widget build(BuildContext context) {
// late Car car = Provider.of<GarageModel>(context).cars[widget.carIndex];
late Car car = Provider.of<GarageModel>(context).cars[widget.carIndex];
// late Car car = context.watch<GarageModel>()_cars[widget.carIndex];
return Scaffold(
appBar: AppBar(
backgroundColor: const Color.fromARGB(255, 185, 47, 5),
// title: Text(car.nickname ?? ""),
title: const Text("View Car"),
title: Text(car.nickname ?? ""),
// title: const Text("View Car"),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
@@ -36,7 +37,6 @@ class _CarDetailScreenState extends State<CarDetailScreen> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text("plh img picker"),
Center(
// edit car screen
child: Ink(
@@ -58,11 +58,6 @@ class _CarDetailScreenState extends State<CarDetailScreen> {
),
],
),
IconButton(
iconSize: 48.0,
icon: const Icon(Icons.directions_car),
onPressed: (() => VoidCallback),
),
Consumer<GarageModel>(
builder: (context, garage, child) => Column(
children: [
@@ -71,6 +66,11 @@ class _CarDetailScreenState extends State<CarDetailScreen> {
Text("License Plate: ${garage.cars[widget.carIndex].plate}"),
Text(
"Mileage: ${garage.cars[widget.carIndex].mileage.toString()}"),
CircleAvatar(
backgroundImage: AssetImage(
garage.cars[widget.carIndex].icon ??
'images/car.png'),
backgroundColor: Colors.white),
],
),
),
@@ -97,10 +97,10 @@ class CarTxns extends StatefulWidget {
final int carIndex;
@override
State<CarTxns> createState() => _CurrentCar();
State<CarTxns> createState() => _CarTxns();
}
class _CurrentCar extends State<CarTxns> {
class _CarTxns extends State<CarTxns> {
late Future _txns;
late Car car;
@@ -112,10 +112,22 @@ class _CurrentCar extends State<CarTxns> {
super.initState();
}
Icon getIcon(String? txntype) {
if (txntype == 'Gas') {
return (const Icon(Icons.local_gas_station));
} else if (txntype == 'Oil') {
return (const Icon(Icons.water_drop));
} else if (txntype == 'Other') {
return (const Icon(Icons.build));
} else {
return (const Icon(Icons.question_mark));
}
}
@override
Widget build(BuildContext context) {
// car =
// Provider.of<GarageModel>(context, listen: false).cars[widget.carIndex];
// Provider.of<GarageModel>(context, listen: false).cars[widget.carIndex];
// _txns = Provider.of<GarageModel>(context, listen: false).getTxns(car.id!);
return FutureBuilder(
future: _txns,
@@ -139,7 +151,7 @@ class _CurrentCar extends State<CarTxns> {
// dense: true, //only affects text, use visualDensity instead
visualDensity:
const VisualDensity(horizontal: 0, vertical: -4),
leading: const Icon(Icons.local_gas_station),
leading: getIcon(garage.txns[index].txntype),
title: Text(garage.txns[index].txntype ?? "type"),
subtitle: Text(garage.txns[index].note ?? "note"),
onTap: (() => VoidCallback)),

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:dash/utils/garage_model.dart';
import 'package:dash/models/car.dart';
import 'package:dash/screens/iconpicker.dart';
class EditCarScreen extends StatefulWidget {
const EditCarScreen({super.key, required this.carIndex});
@@ -16,6 +17,8 @@ class _EditCarScreenState extends State<EditCarScreen> {
late GarageModel garage;
late Car car;
late int carIndex = widget.carIndex;
late IconPicker ip = IconPicker();
late String selectedIcon = 'images/car.png';
@override
void initState() {
@@ -98,6 +101,22 @@ class _EditCarScreenState extends State<EditCarScreen> {
return null;
},
),
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage(car.icon ?? selectedIcon),
backgroundColor: Colors.white),
title: const Text("Change Icon"),
onTap: () => showDialog(
barrierColor: Colors.black.withOpacity(.5),
context: context,
builder: (BuildContext context) {
return ip;
}).then((value) => setState(
() {
// selectedIcon = ip.selectedIcon;
selectedIcon = value;
},
))),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: ElevatedButton(
@@ -107,6 +126,7 @@ class _EditCarScreenState extends State<EditCarScreen> {
//validate form
updateForm
.save(); //save values (reqd before putting them anywhere)
car.icon = selectedIcon;
garage.update(car, carIndex);
updateForm.reset();
Navigator.pop(context);

View File

@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:dash/utils/garage_model.dart';
import 'package:dash/models/car.dart';
import '../utils/garage_model.dart';
import 'package:dash/screens/screens.dart';
class NewCarScreen extends StatefulWidget {
const NewCarScreen({super.key});
@@ -14,6 +14,8 @@ class NewCarScreen extends StatefulWidget {
class _NewCarScreenState extends State<NewCarScreen> {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Car car = Car(); //initialization is required
late IconPicker ip = IconPicker();
late String selectedIcon = 'images/car.png';
@override
Widget build(BuildContext context) {
@@ -29,7 +31,6 @@ class _NewCarScreenState extends State<NewCarScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//new car form text fields
TextFormField(
decoration: const InputDecoration(
labelText: 'Nickname',
@@ -81,6 +82,22 @@ class _NewCarScreenState extends State<NewCarScreen> {
return null;
},
),
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage(selectedIcon),
backgroundColor: Colors.white),
title: const Text("Change Icon"),
onTap: () => showDialog(
barrierColor: Colors.black.withOpacity(.5),
context: context,
builder: (BuildContext context) {
return ip;
}).then((value) => setState(
() {
// selectedIcon = ip.selectedIcon;
selectedIcon = value;
},
))),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
@@ -96,6 +113,7 @@ class _NewCarScreenState extends State<NewCarScreen> {
vin: car.vin,
nickname: car.nickname,
plate: car.plate,
icon: selectedIcon,
mileage: car.mileage);
});
// var garage = context.read<GarageModel>();

View File

@@ -0,0 +1,97 @@
import 'dart:convert';
import 'dart:async';
import 'package:flutter/material.dart';
class IconPicker extends StatefulWidget {
IconPicker({super.key});
late String selectedIcon = 'images/car.png';
@override
State<IconPicker> createState() => _IconPickerState();
}
class _IconPickerState extends State<IconPicker> {
late Future<String> manifestJson;
late List<String> icons;
late List<String> iconList;
late List<String> items;
TextEditingController editingController = TextEditingController();
@override
void initState() {
super.initState();
loadAssets();
}
Future<List<String>> loadAssets() async {
final manifestJson =
await DefaultAssetBundle.of(context).loadString('AssetManifest.json');
// ignore: no_leading_underscores_for_local_identifiers
final _icons = await json
.decode(manifestJson)
.keys
.where((String key) => key.startsWith('images/car_icons/'))
.toList();
setState(() {
icons = _icons;
items = _icons;
});
return _icons;
}
void runFilter(String query) {
List<String> results = [];
if (query.isEmpty) {
results = icons;
} else {
results = icons
.where((i) => i.substring(17, i.length - 4).contains(query))
.toList();
}
setState(() {
items = results;
});
}
@override
Widget build(BuildContext context) {
return Dialog(
child: Column(children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: const InputDecoration(
prefixIcon: Icon(Icons.search),
hintText: "Search icons",
),
onChanged: (value) {
// filterSearch(value, iconList);
runFilter(value);
print('items found: $items');
},
// controller: editingController,
),
),
Expanded(
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) => ListTile(
leading: CircleAvatar(
// backgroundImage: AssetImage(iconList[index]),
backgroundImage: AssetImage(items[index]),
backgroundColor: Colors.white,
),
title: Text(items[index].substring(17, items[index].length - 4)),
// title: Text(items[index]),
onTap: () =>
Navigator.of(context, rootNavigator: true).pop(items[index]),
// onTap: (() => setState(() {
// widget.selectedIcon = items[index];
// })))),
),
)),
]));
}
}

View File

@@ -4,3 +4,4 @@ export 'package:dash/screens/car_detail.dart';
export 'package:dash/screens/car_edit.dart';
export 'package:dash/screens/txn_new.dart';
export 'package:dash/screens/txn_type.dart';
export 'package:dash/screens/iconpicker.dart';

View File

@@ -79,7 +79,14 @@ class _NewTxnScreenState extends State<NewTxnScreen> {
decoration: const InputDecoration(
labelText: 'Cost',
),
initialValue: "0",
initialValue: "",
onTap: () {
final ft = TextEditingController();
ft.clear();
setState(() {
ft.text = "";
});
},
onSaved: (val) =>
setState(() => txn.cost = double.parse(val ?? "0")),
keyboardType: TextInputType.number,
@@ -117,8 +124,6 @@ class _NewTxnScreenState extends State<NewTxnScreen> {
setState(() {
txn.datetime = DateTime.now().millisecondsSinceEpoch;
txn.txntype = txnType.selectedText;
print(
"txntype set to ${txn.txntype} from radio ${txnType.selectedText}");
txn.carid = car.id;
car.mileage = txn.mileage; // update car mileage too
});

View File

@@ -32,7 +32,9 @@ class TxnTypeState extends State<TxnType> {
Widget rIcon(
{required int index, required String text, required IconData icon}) {
return Container(
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
shape: BoxShape.circle,