Add vendor selection and rates to order creation flow

Introduces a Vendor entity and integrates vendor selection into the one-time order creation and order editing flows. Vendor-specific rates are now displayed and used for position roles, and UI components have been updated to allow users to select a vendor and see corresponding rates. Mock vendor data is used for demonstration purposes.
This commit is contained in:
Achintha Isuru
2026-01-23 12:42:26 -05:00
parent 4e8373b2e5
commit 45d6710183
8 changed files with 344 additions and 222 deletions

View File

@@ -643,6 +643,9 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
late List<Map<String, dynamic>> _positions;
List<Vendor> _vendors = const <Vendor>[];
Vendor? _selectedVendor;
@override
void initState() {
super.initState();
@@ -661,6 +664,39 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
'location': null,
},
];
// Mock vendors initialization
_vendors = const <Vendor>[
Vendor(
id: 'v1',
name: 'Elite Staffing',
rates: <String, double>{
'Server': 25.0,
'Bartender': 30.0,
'Cook': 28.0,
'Busser': 18.0,
'Host': 20.0,
'Barista': 22.0,
'Dishwasher': 17.0,
'Event Staff': 19.0,
},
),
Vendor(
id: 'v2',
name: 'Premier Workforce',
rates: <String, double>{
'Server': 22.0,
'Bartender': 28.0,
'Cook': 25.0,
'Busser': 16.0,
'Host': 18.0,
'Barista': 20.0,
'Dishwasher': 15.0,
'Event Staff': 18.0,
},
),
];
_selectedVendor = _vendors.first;
}
@override
@@ -707,7 +743,10 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
hours = endH - startH;
if (hours < 0) hours += 24;
} catch (_) {}
total += hours * widget.order.hourlyRate * (pos['count'] as int);
final double rate =
_selectedVendor?.rates[pos['role']] ?? widget.order.hourlyRate;
total += hours * rate * (pos['count'] as int);
}
return total;
}
@@ -741,6 +780,45 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
),
const SizedBox(height: UiConstants.space4),
_buildSectionHeader('VENDOR'),
Container(
padding: const EdgeInsets.symmetric(
horizontal: UiConstants.space3,
),
height: 48,
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: UiConstants.radiusMd,
border: Border.all(color: UiColors.border),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<Vendor>(
isExpanded: true,
value: _selectedVendor,
icon: const Icon(
UiIcons.chevronDown,
size: 18,
color: UiColors.iconSecondary,
),
onChanged: (Vendor? vendor) {
if (vendor != null) {
setState(() => _selectedVendor = vendor);
}
},
items: _vendors.map((Vendor vendor) {
return DropdownMenuItem<Vendor>(
value: vendor,
child: Text(
vendor.name,
style: UiTypography.body2m.textPrimary,
),
);
}).toList(),
),
),
),
const SizedBox(height: UiConstants.space4),
_buildSectionHeader('DATE'),
UiTextField(
controller: _dateController,
@@ -902,17 +980,8 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
hint: 'Select role',
value: pos['role'],
items: <String>[
'Server',
'Bartender',
'Cook',
'Busser',
'Host',
'Barista',
'Dishwasher',
'Event Staff',
if (pos['role'] != null &&
pos['role'].toString().isNotEmpty &&
!<String>[
...(_selectedVendor?.rates.keys.toList() ??
<String>[
'Server',
'Bartender',
'Cook',
@@ -921,9 +990,17 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
'Barista',
'Dishwasher',
'Event Staff',
].contains(pos['role']))
]),
if (pos['role'] != null &&
pos['role'].toString().isNotEmpty &&
!(_selectedVendor?.rates.keys.contains(pos['role']) ?? false))
pos['role'].toString(),
],
itemBuilder: (dynamic role) {
final double? rate = _selectedVendor?.rates[role];
if (rate == null) return role.toString();
return '$role - \$${rate.toStringAsFixed(0)}/hr';
},
onChanged: (dynamic val) => _updatePosition(index, 'role', val),
),
@@ -1358,6 +1435,9 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
}
Widget _buildReviewPositionCard(Map<String, dynamic> pos) {
final double rate =
_selectedVendor?.rates[pos['role']] ?? widget.order.hourlyRate;
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(16),
@@ -1387,7 +1467,7 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
],
),
Text(
'\$${widget.order.hourlyRate.round()}/hr',
'\$${rate.round()}/hr',
style: UiTypography.body2b.copyWith(color: UiColors.primary),
),
],