feat(frontend): module Articles complet (liste, création, modification, suppression)

- Article model (MP/PSF/PF, stock, seuil alerte)
- ArticleService : fetchAll, fetchByType, create, update, delete
- ArticleProvider : filtrage par type + recherche temps réel
- ArticlesScreen : liste, chips filtres, barre recherche, alertes stock
- ArticleFormScreen : formulaire création/édition avec validation
- Rapport PFE : section 5.6 module Articles

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-20 20:23:06 +01:00
co-authored by Claude Sonnet 4.6
parent 601a7d0373
commit ed21c3cb80
7 changed files with 915 additions and 1 deletions
@@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import '../models/article.dart';
import '../services/article_service.dart';
class ArticleProvider extends ChangeNotifier {
List<Article> _articles = [];
bool _isLoading = false;
String? _error;
String _filterType = 'TOUS';
String _search = '';
List<Article> get articles => _filtered();
bool get isLoading => _isLoading;
String? get error => _error;
String get filterType => _filterType;
List<Article> _filtered() {
return _articles.where((a) {
final matchType = _filterType == 'TOUS' || a.type == _filterType;
final matchSearch = _search.isEmpty ||
a.reference.toLowerCase().contains(_search.toLowerCase()) ||
a.designation.toLowerCase().contains(_search.toLowerCase());
return matchType && matchSearch;
}).toList();
}
void setFilter(String type) {
_filterType = type;
notifyListeners();
}
void setSearch(String q) {
_search = q;
notifyListeners();
}
Future<void> load() async {
_isLoading = true;
_error = null;
notifyListeners();
try {
_articles = await ArticleService.fetchAll();
} catch (_) {
_error = 'Impossible de charger les articles.';
} finally {
_isLoading = false;
notifyListeners();
}
}
Future<bool> create(Article article) async {
try {
final created = await ArticleService.create(article);
_articles.add(created);
notifyListeners();
return true;
} catch (_) {
return false;
}
}
Future<bool> update(int id, Article article) async {
try {
final updated = await ArticleService.update(id, article);
final idx = _articles.indexWhere((a) => a.id == id);
if (idx != -1) _articles[idx] = updated;
notifyListeners();
return true;
} catch (_) {
return false;
}
}
Future<bool> delete(int id) async {
try {
await ArticleService.delete(id);
_articles.removeWhere((a) => a.id == id);
notifyListeners();
return true;
} catch (_) {
return false;
}
}
}