Add full app source

Adds the Flutter inventory app source, cleaned up for a shared repo:
generic package name, no hardcoded ERP endpoints (moved to gitignored
local config), no dead auth code, no debug logging of session data.
This commit is contained in:
BACHIR SOULDI
2026-07-16 14:37:28 +01:00
parent 37b0762921
commit 5a483da01d
110 changed files with 8081 additions and 0 deletions

209
lib/views/profile.dart Normal file
View File

@@ -0,0 +1,209 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter/services.dart';
import 'package:inventory_app/controllers/user_controller.dart';
import 'package:inventory_app/home.dart';
import 'package:inventory_app/widgets/glass_widgets.dart';
import 'package:inventory_app/service/axelor_client.dart';
import 'package:inventory_app/controllers/theme_controller.dart';
import '../constants.dart';
class ProfilePage extends StatefulWidget {
const ProfilePage({Key? key}) : super(key: key);
@override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
Map<String, dynamic>? userData;
bool loading = true;
@override
void initState() {
super.initState();
Get.find<UserController>().loadUser();
// loadProfile();
}
Future<void> loadProfile() async {
setState(() => loading = true);
try {
final client = await AxelorClient.create();
final data = await client.fetchUserProfile();
setState(() {
userData = data;
loading = false;
});
} catch (e) {
setState(() => loading = false);
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text("Failed to load profile: $e")));
}
}
@override
Widget build(BuildContext context) {
final userController = Get.find<UserController>();
final primary = Colors.blue;
return Scaffold(
drawer: FancyDrawer(primary: primary, onLogout: () {}),
body: Stack(
children: [
const FancyBackground(),
Obx(() {
if (userController.isLoading.value) {
return const Center(child: CircularProgressIndicator());
}
final user = userController.user.value;
if (user == null) {
return const Center(
child: Text("Impossible de charger le profil."),
);
}
return _buildContent(primary, user);
}),
],
),
);
}
Widget _buildContent(MaterialColor primary, Map<String, dynamic> userData) {
final themeController = Get.find<ThemeController>();
final isDark = themeController.isDarkMode.value;
return SafeArea(
child: Column(
children: [
GlassAppBar(
title: "Mon Profil",
primary: primary,
onLogout: () {},
onCamera: null,
),
Expanded(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.fromLTRB(16, 6, 16, 50),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SectionHeader(
icon: Icons.person_rounded,
title: "Informations personnelles",
accent: primary,
),
const SizedBox(height: 8),
GlassCard(
child: Column(
children: [
_profileField(
icon: Icons.person,
label: "Nom complet",
value: userData?["fullName"],
color: isDark ? Colors.white : primary.shade700,
),
_profileField(
icon: Icons.badge_rounded,
label: "Login",
value: userData?["code"],
color: isDark ? Colors.white : primary.shade700,
),
_profileField(
icon: Icons.email_rounded,
label: "Email",
value: userData?["email"],
color: isDark ? Colors.white : primary.shade700,
),
_profileField(
icon: Icons.language_rounded,
label: "Langue",
value: userData?["language"],
color: isDark ? Colors.white : primary.shade700,
),
_profileField(
icon: Icons.group,
label: "Groupe",
value: userData?["group"]?["name"],
color: isDark ? Colors.white : primary.shade700,
),
_profileField(
icon: Icons.lock_person_rounded,
label: "Bloqué",
value: userData?["blocked"] == true ? "Oui" : "Non",
color: isDark ? Colors.white : primary.shade700,
),
],
),
),
const SizedBox(height: 25),
Center(
child: ElevatedButton.icon(
icon: const Icon(
Icons.refresh_rounded,
color: Colors.white,
),
label: const Text(
"Actualiser",
style: TextStyle(color: Colors.white),
),
style: ElevatedButton.styleFrom(
backgroundColor: primary,
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
onPressed: () {
HapticFeedback.lightImpact();
Get.find<UserController>().loadUser(); // ✅ correct
},
),
),
const SizedBox(height: 40),
],
),
),
),
],
),
);
}
Widget _profileField({
required IconData icon,
required String label,
required String? value,
required Color color,
}) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
children: [
Icon(icon, color: Colors.blue),
const SizedBox(width: 12),
Expanded(
child: Text(
"$label : ${value ?? 'N/A'}",
style: kTextFormFieldStyle(fontSize: 16.0, color: color),
),
),
],
),
);
}
}