Files
2026-10-01 16:03:32 +05:30

169 lines
5.4 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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),
],
);
}
}