182 lines
6.5 KiB
Dart
182 lines
6.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../api/LoginApi.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
const _bg = Color(0xFFF9FAFB);
|
|
const _bg1 = Color(0xFFFFFFFF);
|
|
const _bg2 = Color(0xFFF3F4F6);
|
|
const _green = Color(0xFF10B981);
|
|
const _greenDim = Color(0x1A10B981);
|
|
const _rose = Color(0xFFEF4444);
|
|
const _t1 = Color(0xFF111827);
|
|
const _t2 = Color(0xFF6B7280);
|
|
const _t3 = Color(0xFF9CA3AF);
|
|
const _line2 = Color(0xFFE5E7EB);
|
|
|
|
class ProfilScreen extends StatefulWidget {
|
|
const ProfilScreen({super.key});
|
|
|
|
@override
|
|
State<ProfilScreen> createState() => _ProfilScreenState();
|
|
}
|
|
|
|
class _ProfilScreenState extends State<ProfilScreen> {
|
|
final ApiService _apiService = ApiService();
|
|
Map<String, dynamic>? _userData;
|
|
bool _isLoading = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadProfile();
|
|
}
|
|
|
|
Future<void> _loadProfile() async {
|
|
setState(() => _isLoading = true);
|
|
final res = await _apiService.getProfile();
|
|
if (mounted) {
|
|
setState(() {
|
|
_isLoading = false;
|
|
if (res['success'] == true) _userData = res['data'];
|
|
});
|
|
}
|
|
}
|
|
|
|
String _fmtDate(dynamic date) {
|
|
if (date == null) return '-';
|
|
try {
|
|
final dt = DateTime.parse(date.toString());
|
|
return DateFormat('dd MMM yyyy').format(dt);
|
|
} catch (e) {
|
|
return date.toString();
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final teknisi = _userData?['teknisi'];
|
|
final user = _userData;
|
|
final nama = teknisi?['nama'] ?? 'Teknisi';
|
|
final initial = nama.isNotEmpty ? nama[0].toUpperCase() : 'T';
|
|
|
|
return Scaffold(
|
|
backgroundColor: _bg,
|
|
appBar: AppBar(
|
|
elevation: 0,
|
|
backgroundColor: _bg,
|
|
title: const Text('Profil Saya', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w800, color: _t1)),
|
|
centerTitle: true,
|
|
),
|
|
body: _isLoading
|
|
? const Center(child: CircularProgressIndicator(color: _green))
|
|
: SingleChildScrollView(
|
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32),
|
|
child: Column(
|
|
children: [
|
|
// Header Profile
|
|
Container(
|
|
padding: const EdgeInsets.all(24),
|
|
decoration: BoxDecoration(
|
|
color: _bg1,
|
|
borderRadius: BorderRadius.circular(32),
|
|
border: Border.all(color: _line2),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
width: 80, height: 80,
|
|
decoration: BoxDecoration(
|
|
gradient: const LinearGradient(colors: [_green, Color(0xFF00c960)]),
|
|
borderRadius: BorderRadius.circular(24),
|
|
),
|
|
child: Center(child: Text(initial, style: const TextStyle(fontSize: 32, fontWeight: FontWeight.w900, color: Colors.black))),
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(nama, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w800, color: _t1)),
|
|
const SizedBox(height: 6),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
|
decoration: BoxDecoration(color: _greenDim, borderRadius: BorderRadius.circular(100)),
|
|
child: const Text('TEKNISI AKTIF', style: TextStyle(fontSize: 9, fontWeight: FontWeight.w900, color: _green, letterSpacing: 1)),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
|
|
// Data Lengkap Teknisi (Sesuai Admin)
|
|
_buildInfoGroup('DATA PEGAWAI', [
|
|
_infoTile(Icons.badge_outlined, 'ID TEKNISI', 'ID: ${teknisi?['id_teknisi'] ?? '-'}'),
|
|
_infoTile(Icons.email_outlined, 'KONTAK EMAIL', user?['email'] ?? teknisi?['email'] ?? '-'),
|
|
_infoTile(Icons.phone_iphone_rounded, 'NO. TELEPON', teknisi?['no_telephone'] ?? '-'),
|
|
_infoTile(Icons.location_on_outlined, 'ALAMAT', teknisi?['alamat'] ?? '-'),
|
|
]),
|
|
|
|
const SizedBox(height: 32),
|
|
|
|
// Logout
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: TextButton.icon(
|
|
onPressed: () => _handleLogout(context),
|
|
icon: const Icon(Icons.logout_rounded, size: 18),
|
|
label: const Text('Keluar dari Akun', style: TextStyle(fontWeight: FontWeight.w800)),
|
|
style: TextButton.styleFrom(
|
|
foregroundColor: _rose,
|
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildInfoGroup(String title, List<Widget> children) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 4, bottom: 8),
|
|
child: Text(title, style: const TextStyle(fontSize: 10, fontWeight: FontWeight.w800, color: _t3, letterSpacing: 1.2)),
|
|
),
|
|
Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(color: _bg1, borderRadius: BorderRadius.circular(24), border: Border.all(color: _line2)),
|
|
child: Column(children: children),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _infoTile(IconData icon, String label, String value) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
|
child: Row(
|
|
children: [
|
|
Icon(icon, color: _green.withOpacity(0.7), size: 18),
|
|
const SizedBox(width: 16),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(label, style: const TextStyle(color: _t3, fontSize: 9, fontWeight: FontWeight.w800)),
|
|
const SizedBox(height: 2),
|
|
Text(value, style: const TextStyle(color: _t1, fontSize: 13, fontWeight: FontWeight.w600)),
|
|
],
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _handleLogout(BuildContext context) async {
|
|
Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);
|
|
}
|
|
}
|