init
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
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),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user