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.
210 lines
6.5 KiB
Dart
210 lines
6.5 KiB
Dart
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),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|