169 lines
5.4 KiB
Dart
169 lines
5.4 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:provider/provider.dart';
|
||
|
||
import '../models/models.dart';
|
||
import '../services/auth_controller.dart';
|
||
import '../theme/app_theme.dart';
|
||
import '../ui/feedback.dart';
|
||
import 'dealer_stock_screen.dart';
|
||
import 'stock_form_screen.dart';
|
||
|
||
class StockScreen extends StatefulWidget {
|
||
const StockScreen({super.key});
|
||
|
||
@override
|
||
State<StockScreen> createState() => _StockScreenState();
|
||
}
|
||
|
||
class _StockScreenState extends State<StockScreen> {
|
||
List<Dealer> _dealers = [];
|
||
List<StockItem> _stocks = [];
|
||
bool _loading = true;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_load();
|
||
}
|
||
|
||
Future<void> _load() async {
|
||
final api = context.read<AuthController>().api;
|
||
try {
|
||
final results = await Future.wait([
|
||
api.dealers(),
|
||
api.stocks(),
|
||
]);
|
||
if (!mounted) return;
|
||
setState(() {
|
||
_dealers = results[0] as List<Dealer>;
|
||
_stocks = results[1] as List<StockItem>;
|
||
_loading = false;
|
||
});
|
||
} catch (error) {
|
||
if (!mounted) return;
|
||
setState(() => _loading = false);
|
||
showError(context, error);
|
||
}
|
||
}
|
||
|
||
int _count(String dealerId, String badge) {
|
||
return _stocks.where((item) => item.currentDealerId == dealerId && item.badge == badge).length;
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final role = context.watch<AuthController>().user?.role;
|
||
final canAdd = role == 'dealer' || role == 'salesRep' || role == 'superAdmin';
|
||
|
||
if (_loading && _dealers.isEmpty && _stocks.isEmpty) {
|
||
return const Center(child: CircularProgressIndicator());
|
||
}
|
||
|
||
return Scaffold(
|
||
floatingActionButton: canAdd
|
||
? FloatingActionButton.extended(
|
||
onPressed: () async {
|
||
final created = await Navigator.of(context).push<bool>(
|
||
MaterialPageRoute(builder: (_) => StockFormScreen(dealers: _dealers)),
|
||
);
|
||
if (created == true) _load();
|
||
},
|
||
icon: const Icon(Icons.add),
|
||
label: const Text('Add stock'),
|
||
)
|
||
: null,
|
||
body: RefreshIndicator(
|
||
onRefresh: _load,
|
||
child: ListView(
|
||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 96),
|
||
children: [
|
||
if (_dealers.isEmpty)
|
||
const Padding(
|
||
padding: EdgeInsets.symmetric(vertical: 32),
|
||
child: Center(child: Text('No dealers to show.')),
|
||
),
|
||
for (final dealer in _dealers)
|
||
Card(
|
||
clipBehavior: Clip.antiAlias,
|
||
child: InkWell(
|
||
onTap: () async {
|
||
await Navigator.of(context).push<bool>(
|
||
MaterialPageRoute(
|
||
builder: (_) => DealerStockScreen(dealer: dealer, dealers: _dealers),
|
||
),
|
||
);
|
||
if (mounted) _load();
|
||
},
|
||
child: Padding(
|
||
padding: const EdgeInsets.all(16),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(dealer.name, style: Theme.of(context).textTheme.titleMedium),
|
||
const SizedBox(height: 2),
|
||
Text(
|
||
dealer.district == null || dealer.district!.isEmpty
|
||
? dealer.code
|
||
: '${dealer.code} · ${dealer.district}',
|
||
style: Theme.of(context).textTheme.bodySmall,
|
||
),
|
||
const SizedBox(height: 12),
|
||
Row(
|
||
children: [
|
||
Expanded(
|
||
child: _AgeCount(
|
||
label: 'Under 30',
|
||
count: _count(dealer.id, 'green'),
|
||
badge: 'green',
|
||
),
|
||
),
|
||
Expanded(
|
||
child: _AgeCount(
|
||
label: '30–45',
|
||
count: _count(dealer.id, 'yellow'),
|
||
badge: 'yellow',
|
||
),
|
||
),
|
||
Expanded(
|
||
child: _AgeCount(
|
||
label: 'Over 45',
|
||
count: _count(dealer.id, 'red'),
|
||
badge: 'red',
|
||
),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
class _AgeCount extends StatelessWidget {
|
||
const _AgeCount({required this.label, required this.count, required this.badge});
|
||
|
||
final String label;
|
||
final int count;
|
||
final String badge;
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Column(
|
||
children: [
|
||
Text(
|
||
'$count',
|
||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: badgeColor(badge)),
|
||
),
|
||
const SizedBox(height: 2),
|
||
Text(label, style: Theme.of(context).textTheme.bodySmall, textAlign: TextAlign.center),
|
||
],
|
||
);
|
||
}
|
||
}
|