2024-09-07 21:56:52 +00:00
|
|
|
import 'package:cdb_ui/api.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:qr_bar_code_scanner_dialog/qr_bar_code_scanner_dialog.dart';
|
|
|
|
|
|
|
|
class SupplyPage extends StatefulWidget {
|
|
|
|
final Item item;
|
2024-09-15 15:49:50 +00:00
|
|
|
final Function refresh;
|
2024-09-07 21:56:52 +00:00
|
|
|
|
2024-09-15 15:49:50 +00:00
|
|
|
const SupplyPage(this.item, this.refresh, {super.key});
|
2024-09-07 21:56:52 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
State<SupplyPage> createState() => _SupplyPageState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _SupplyPageState extends State<SupplyPage> {
|
|
|
|
late String variant;
|
|
|
|
final _formKey = GlobalKey<FormState>();
|
|
|
|
String _selectedOrigin = "";
|
|
|
|
String _selectedLocation = "";
|
|
|
|
String _price = "";
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
variant = widget.item.variants.keys.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _supply() async {
|
|
|
|
if (_formKey.currentState!.validate()) {
|
|
|
|
_formKey.currentState!.save();
|
|
|
|
|
|
|
|
await API().supplyItem(widget.item.name, variant, "${_price} €",
|
|
|
|
_selectedOrigin, _selectedLocation);
|
|
|
|
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
const SnackBar(content: Text('Item added successfully!')),
|
|
|
|
);
|
|
|
|
Navigator.of(context).pop();
|
2024-09-07 22:24:13 +00:00
|
|
|
widget.refresh();
|
2024-09-07 21:56:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Scaffold(
|
|
|
|
appBar: AppBar(
|
|
|
|
title: const Text('Add New Item'),
|
|
|
|
),
|
|
|
|
body: FutureBuilder(
|
|
|
|
future: _fetchData(),
|
|
|
|
builder: (context, snapshot) {
|
|
|
|
if (!snapshot.hasData) {
|
|
|
|
return const Center(child: CircularProgressIndicator());
|
|
|
|
}
|
|
|
|
|
2024-09-15 13:15:46 +00:00
|
|
|
var data = snapshot.data as Map<String, dynamic>;
|
|
|
|
var locations = data['locations']! as Map<String, Location>;
|
2024-09-07 21:56:52 +00:00
|
|
|
var origins = data['origins']! as List<String>;
|
|
|
|
|
|
|
|
return Padding(
|
|
|
|
padding: const EdgeInsets.all(16.0),
|
|
|
|
child: Form(
|
|
|
|
key: _formKey,
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
// Variant Selection
|
|
|
|
DropdownButtonFormField<String>(
|
|
|
|
hint: const Text('Select Variant'),
|
|
|
|
value: variant,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() {
|
|
|
|
variant = value!;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
items: widget.item.variants.entries.map((entry) {
|
|
|
|
return DropdownMenuItem<String>(
|
|
|
|
value: entry.key,
|
|
|
|
child: Text(entry.value.name),
|
|
|
|
);
|
|
|
|
}).toList(),
|
|
|
|
onSaved: (value) {
|
|
|
|
variant = value!;
|
|
|
|
},
|
|
|
|
),
|
|
|
|
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
|
|
|
|
// Origin Field with Dropdown and Text Input
|
|
|
|
Autocomplete<String>(
|
|
|
|
optionsBuilder: (TextEditingValue textEditingValue) {
|
|
|
|
if (textEditingValue.text.isEmpty) {
|
|
|
|
return origins;
|
|
|
|
}
|
|
|
|
return origins.where((String option) {
|
|
|
|
return option
|
|
|
|
.toLowerCase()
|
|
|
|
.contains(textEditingValue.text.toLowerCase());
|
|
|
|
});
|
|
|
|
},
|
2024-09-16 06:35:13 +00:00
|
|
|
onSelected: (String selection) async {
|
2024-09-16 07:34:57 +00:00
|
|
|
var price = _price.isEmpty
|
|
|
|
? await API()
|
|
|
|
.getLatestPrice(widget.item.id, variant)
|
|
|
|
.then((x) => x.value.toStringAsFixed(2))
|
|
|
|
: _price;
|
2024-09-07 21:56:52 +00:00
|
|
|
setState(() {
|
2024-09-16 07:34:57 +00:00
|
|
|
_price = price;
|
2024-09-07 21:56:52 +00:00
|
|
|
_selectedOrigin = selection;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
fieldViewBuilder: (context, textEditingController,
|
|
|
|
focusNode, onFieldSubmitted) {
|
|
|
|
textEditingController.text = _selectedOrigin;
|
|
|
|
return TextFormField(
|
2024-09-07 22:24:13 +00:00
|
|
|
onChanged: (value) {
|
|
|
|
_selectedOrigin = value;
|
|
|
|
},
|
2024-09-07 21:56:52 +00:00
|
|
|
controller: textEditingController,
|
|
|
|
focusNode: focusNode,
|
|
|
|
decoration: const InputDecoration(
|
|
|
|
labelText: 'Origin',
|
|
|
|
border: OutlineInputBorder(),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
|
|
|
|
// Price Field
|
|
|
|
TextFormField(
|
|
|
|
decoration: const InputDecoration(labelText: 'Price'),
|
|
|
|
keyboardType: TextInputType.number,
|
|
|
|
initialValue: _price,
|
|
|
|
validator: (value) {
|
|
|
|
if (value == null || value.isEmpty) {
|
|
|
|
return 'Please enter a price';
|
|
|
|
}
|
|
|
|
if (double.tryParse(value) == null) {
|
|
|
|
return 'Please enter a valid number';
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
onSaved: (value) {
|
|
|
|
_price = value!;
|
|
|
|
},
|
|
|
|
),
|
|
|
|
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
|
|
|
|
// Location Dropdown
|
2024-09-15 13:15:46 +00:00
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
Expanded(
|
|
|
|
child: DropdownButtonFormField<String>(
|
|
|
|
hint: const Text('Select Location'),
|
|
|
|
value: _selectedLocation,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() {
|
|
|
|
_selectedLocation = value!;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
items: locations.keys
|
|
|
|
.map<DropdownMenuItem<String>>((id) {
|
|
|
|
return DropdownMenuItem<String>(
|
|
|
|
value: id,
|
|
|
|
child: Text(
|
|
|
|
locations[id]!.full_name_path(locations)),
|
|
|
|
);
|
|
|
|
}).toList(),
|
|
|
|
onSaved: (value) {
|
|
|
|
_selectedLocation = value!;
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
2024-09-15 15:49:50 +00:00
|
|
|
const SizedBox(
|
2024-09-15 13:15:46 +00:00
|
|
|
width: 12,
|
|
|
|
),
|
|
|
|
IconButton(
|
|
|
|
onPressed: () {
|
|
|
|
QrBarCodeScannerDialog().getScannedQrBarCode(
|
|
|
|
context: context,
|
|
|
|
onCode: (code) {
|
|
|
|
setState(() {
|
|
|
|
_selectedLocation = code!;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
);
|
2024-09-07 21:56:52 +00:00
|
|
|
},
|
2024-09-15 13:15:46 +00:00
|
|
|
icon: const Icon(Icons.qr_code),
|
|
|
|
),
|
|
|
|
],
|
2024-09-07 21:56:52 +00:00
|
|
|
),
|
|
|
|
|
|
|
|
const SizedBox(height: 20),
|
|
|
|
|
|
|
|
// Submit Button
|
|
|
|
ElevatedButton(
|
|
|
|
onPressed: _supply,
|
|
|
|
child: const Text('Add Item'),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-09-15 13:15:46 +00:00
|
|
|
Future<Map<String, dynamic>> _fetchData() async {
|
|
|
|
var locations = await API().getLocations();
|
2024-09-07 21:56:52 +00:00
|
|
|
var origins = await API().getUniqueField(widget.item.id, variant, "origin");
|
|
|
|
origins.insert(0, "");
|
2024-09-15 13:15:46 +00:00
|
|
|
locations[""] = Location.zero();
|
2024-09-07 21:56:52 +00:00
|
|
|
return {'locations': locations, 'origins': origins};
|
|
|
|
}
|
|
|
|
}
|