parent
a334320c80
commit
b07033dda7
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 945 B |
@ -1,408 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:supplier_new/common/settings.dart';
|
|
||||||
void main() => runApp(const MaterialApp(home: ResourcesScreen()));
|
|
||||||
|
|
||||||
|
|
||||||
class ResourcesScreen extends StatefulWidget {
|
|
||||||
const ResourcesScreen({super.key});
|
|
||||||
@override
|
|
||||||
State<ResourcesScreen> createState() => _ResourcesScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ResourcesScreenState extends State<ResourcesScreen> {
|
|
||||||
int selectedTab = 0;
|
|
||||||
String search = '';
|
|
||||||
|
|
||||||
final List<Map<String, dynamic>> items = [
|
|
||||||
{
|
|
||||||
'title': 'Tanker Name',
|
|
||||||
'subtitle': 'Drinking water - 10,000 L',
|
|
||||||
'status': ['filled', 'available'],
|
|
||||||
'code': 'TS 07 J 3492',
|
|
||||||
'owner': 'Ramesh Krishna'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'title': 'Drinking Water - 15,000L',
|
|
||||||
'subtitle': 'Drinking water - 15,000 L',
|
|
||||||
'status': ['empty', 'available'],
|
|
||||||
'code': 'TS 07 J 3492',
|
|
||||||
'owner': 'Ramesh Krishna'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'title': 'Tanker Name',
|
|
||||||
'subtitle': 'Drinking water - 10,000 L',
|
|
||||||
'status': ['filled', 'in-use'],
|
|
||||||
'code': 'TS 07 J 3492',
|
|
||||||
'owner': 'Ramesh Krishna'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'title': 'Drinking Water - 15,000L',
|
|
||||||
'subtitle': 'Drinking water - 15,000 L',
|
|
||||||
'status': ['empty', 'in-use'],
|
|
||||||
'code': 'TS 07 J 3492',
|
|
||||||
'owner': 'Ramesh Krishna'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'title': 'Tanker Name',
|
|
||||||
'subtitle': 'Drinking water - 10,000 L',
|
|
||||||
'status': ['filled', 'maintenance'],
|
|
||||||
'code': 'TS 07 J 3492',
|
|
||||||
'owner': 'Ramesh Krishna'
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final filtered = items.where((it) {
|
|
||||||
final q = search.trim().toLowerCase();
|
|
||||||
if (q.isEmpty) return true;
|
|
||||||
return it['title'].toLowerCase().contains(q) ||
|
|
||||||
it['subtitle'].toLowerCase().contains(q) ||
|
|
||||||
it['owner'].toLowerCase().contains(q);
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: const Color(0xFFF6F6F7),
|
|
||||||
appBar: AppBar(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
elevation: 0.7,
|
|
||||||
leading: IconButton(
|
|
||||||
icon: const Icon(Icons.arrow_back, color: Colors.black87),
|
|
||||||
onPressed: () => Navigator.of(context).maybePop(),
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
'Resources',
|
|
||||||
style: fontTextStyle(16, const Color(0xFF2A2A2A), FontWeight.w600),
|
|
||||||
),
|
|
||||||
centerTitle: false,
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {},
|
|
||||||
child: Text('HELP', style: fontTextStyle(12, const Color(0xFF8270DB), FontWeight.w600)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
body: SafeArea(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 0),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
// Segmented tabs
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(6),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFFF1F1F3),
|
|
||||||
borderRadius: BorderRadius.circular(24),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: List.generate(3, (i) {
|
|
||||||
final labels = ['Fleet', 'Drivers', 'Sources'];
|
|
||||||
final isSelected = selectedTab == i;
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: () => setState(() => selectedTab = i),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
|
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: isSelected ? Colors.white : Colors.transparent,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
labels[i],
|
|
||||||
style: TextStyle(
|
|
||||||
color: isSelected ? Colors.black87 : Colors.grey.shade700,
|
|
||||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Summary card and small stats row
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
// Big card
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 6, offset: const Offset(0, 3))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color(0xFFF6F0FF),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: const Icon(Icons.local_shipping_outlined, color: Color(0xFF6F5FBA)),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: const [
|
|
||||||
Text('Total Tankers', style: TextStyle(fontSize: 14, color: Colors.black87)),
|
|
||||||
SizedBox(height: 6),
|
|
||||||
Text('14', style: TextStyle(fontSize: 28, fontWeight: FontWeight.w700, color: Color(0xFF173F5F))),
|
|
||||||
SizedBox(height: 2),
|
|
||||||
Text('+2 since last month', style: TextStyle(fontSize: 12, color: Colors.grey)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
|
|
||||||
// Small stat cards
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
StatCard(title: 'Active', value: '2'),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
StatCard(title: 'Inactive', value: '3'),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
StatCard(title: 'Under\nMaintenances', value: '1'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Search and filter row
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.search, color: Colors.grey),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: TextField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: 'Search',
|
|
||||||
border: InputBorder.none,
|
|
||||||
isDense: true,
|
|
||||||
),
|
|
||||||
onChanged: (v) => setState(() => search = v),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {},
|
|
||||||
icon: const Icon(Icons.filter_list, color: Colors.grey),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {},
|
|
||||||
icon: const Icon(Icons.swap_vert, color: Colors.grey),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
|
|
||||||
// List
|
|
||||||
Expanded(
|
|
||||||
child: ListView.separated(
|
|
||||||
itemCount: filtered.length,
|
|
||||||
separatorBuilder: (_, __) => const SizedBox(height: 10),
|
|
||||||
itemBuilder: (context, idx) {
|
|
||||||
final it = filtered[idx];
|
|
||||||
return TankCard(
|
|
||||||
title: it['title'],
|
|
||||||
subtitle: it['subtitle'],
|
|
||||||
code: it['code'],
|
|
||||||
owner: it['owner'],
|
|
||||||
status: List<String>.from(it['status']),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: () {},
|
|
||||||
backgroundColor: const Color(0xFF2E2B5F),
|
|
||||||
child: const Icon(Icons.add),
|
|
||||||
),
|
|
||||||
|
|
||||||
bottomNavigationBar: BottomNavigationBar(
|
|
||||||
type: BottomNavigationBarType.fixed,
|
|
||||||
currentIndex: 0,
|
|
||||||
selectedItemColor: const Color(0xFF6F5FBA),
|
|
||||||
unselectedItemColor: Colors.grey,
|
|
||||||
items: const [
|
|
||||||
BottomNavigationBarItem(icon: Icon(Icons.home_outlined), label: 'Home'),
|
|
||||||
BottomNavigationBarItem(icon: Icon(Icons.receipt_long_outlined), label: 'Orders'),
|
|
||||||
BottomNavigationBarItem(icon: Icon(Icons.calendar_month), label: 'Plans'),
|
|
||||||
BottomNavigationBarItem(icon: Icon(Icons.group_outlined), label: 'Resources'),
|
|
||||||
BottomNavigationBarItem(icon: Icon(Icons.menu), label: 'More'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StatCard extends StatelessWidget {
|
|
||||||
final String title;
|
|
||||||
final String value;
|
|
||||||
const StatCard({super.key, required this.title, required this.value});
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
height: 58,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
border: Border.all(color: Colors.grey.shade200),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Text(title, style: const TextStyle(fontSize: 13, color: Colors.black87))),
|
|
||||||
Text(value, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w700, color: Color(0xFF173F5F))),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TankCard extends StatelessWidget {
|
|
||||||
final String title;
|
|
||||||
final String subtitle;
|
|
||||||
final String code;
|
|
||||||
final String owner;
|
|
||||||
final List<String> status;
|
|
||||||
const TankCard({
|
|
||||||
super.key,
|
|
||||||
required this.title,
|
|
||||||
required this.subtitle,
|
|
||||||
required this.code,
|
|
||||||
required this.owner,
|
|
||||||
required this.status,
|
|
||||||
});
|
|
||||||
|
|
||||||
Color _chipColor(String s) {
|
|
||||||
switch (s) {
|
|
||||||
case 'filled':
|
|
||||||
return const Color(0xFFE8F7F1);
|
|
||||||
case 'available':
|
|
||||||
return const Color(0xFFE8F0FF);
|
|
||||||
case 'empty':
|
|
||||||
return const Color(0xFFFFEEEE);
|
|
||||||
case 'in-use':
|
|
||||||
return const Color(0xFFFFF0E6);
|
|
||||||
case 'maintenance':
|
|
||||||
return const Color(0xFFFFF4E6);
|
|
||||||
default:
|
|
||||||
return const Color(0xFFECECEC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Color _chipTextColor(String s) {
|
|
||||||
switch (s) {
|
|
||||||
case 'filled':
|
|
||||||
return Colors.green.shade700;
|
|
||||||
case 'available':
|
|
||||||
return const Color(0xFF2E2B5F);
|
|
||||||
case 'empty':
|
|
||||||
return Colors.red.shade600;
|
|
||||||
case 'in-use':
|
|
||||||
return Colors.orange.shade700;
|
|
||||||
case 'maintenance':
|
|
||||||
return Colors.orange.shade700;
|
|
||||||
default:
|
|
||||||
return Colors.black87;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(color: Colors.grey.shade100),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
// left column: chips + texts
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
// chips
|
|
||||||
Row(
|
|
||||||
children: status.map((s) {
|
|
||||||
return Container(
|
|
||||||
margin: const EdgeInsets.only(right: 6),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: _chipColor(s),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
border: Border.all(color: Colors.grey.withOpacity(0.12)),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
s,
|
|
||||||
style: TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: _chipTextColor(s)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w700)),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
Text(subtitle, style: const TextStyle(fontSize: 13, color: Colors.grey)),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
CircleAvatar(radius: 10, backgroundColor: const Color(0xFFEEF5FF), child: const Icon(Icons.person, size: 12, color: Color(0xFF6F5FBA))),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
Expanded(child: Text(owner, style: const TextStyle(fontSize: 12, color: Colors.grey))),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// right column: code
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
Text(code, style: const TextStyle(fontSize: 12, color: Colors.grey)),
|
|
||||||
const SizedBox(height: 28),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,469 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:supplier_new/common/settings.dart';
|
||||||
|
import 'package:supplier_new/resources/resources_sources.dart';
|
||||||
|
import 'fleet.dart';
|
||||||
|
import 'resources_drivers.dart';
|
||||||
|
import 'resources_sources.dart';
|
||||||
|
|
||||||
|
|
||||||
|
import 'employees.dart';
|
||||||
|
|
||||||
|
void main() => runApp(const MaterialApp(home: ResourcesDriverScreen()));
|
||||||
|
|
||||||
|
class ResourcesDriverScreen extends StatefulWidget {
|
||||||
|
const ResourcesDriverScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ResourcesDriverScreen> createState() => _ResourcesDriverScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ResourcesDriverScreenState extends State<ResourcesDriverScreen> {
|
||||||
|
int selectedTab = 1; // default "Drivers"
|
||||||
|
String search = '';
|
||||||
|
|
||||||
|
final List<Map<String, dynamic>> drivers = [
|
||||||
|
{
|
||||||
|
'name': 'Ravi Kumar',
|
||||||
|
'status': 'available',
|
||||||
|
'location': 'Gandipet',
|
||||||
|
'deliveries': 134,
|
||||||
|
'commission': '₹500/day',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'Ravi Kumar',
|
||||||
|
'status': 'offline',
|
||||||
|
'location': 'Gandipet',
|
||||||
|
'deliveries': 134,
|
||||||
|
'commission': '₹500/day',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
elevation: 0.7,
|
||||||
|
leading: IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back, color: Colors.black87),
|
||||||
|
onPressed: () => Navigator.of(context).maybePop(),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
'Resources',
|
||||||
|
style: fontTextStyle(16, Color(0xFF2A2A2A), FontWeight.w600),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: Text(
|
||||||
|
'HELP',
|
||||||
|
style: fontTextStyle(12, Color(0xFF8270DB), FontWeight.w600),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
// Segmented pill
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
child: Row(
|
||||||
|
children: List.generate(3, (i) {
|
||||||
|
final labels = ['Fleet', 'Drivers', 'Sources'];
|
||||||
|
final isSelected = selectedTab == i;
|
||||||
|
return Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => setState(() => selectedTab = i),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isSelected
|
||||||
|
? const Color(0xFFF1F1F1)
|
||||||
|
: Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
labels[i],
|
||||||
|
style: TextStyle(
|
||||||
|
color: isSelected
|
||||||
|
? const Color(0xFF101214)
|
||||||
|
: const Color(0xFF646464),
|
||||||
|
fontWeight:
|
||||||
|
isSelected ? FontWeight.w600 : FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Total Drivers card
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: const Color(0xFF939495)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Color(0xFFF6F0FF),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Image.asset('images/drivers.png',
|
||||||
|
fit: BoxFit.contain),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text('Total Drivers',
|
||||||
|
style: fontTextStyle(
|
||||||
|
12, const Color(0xFF2D2E30), FontWeight.w500)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text('09',
|
||||||
|
style: fontTextStyle(
|
||||||
|
24, const Color(0xFF0D3771), FontWeight.w500)),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text('+1 since last month',
|
||||||
|
style: fontTextStyle(
|
||||||
|
10, const Color(0xFF646566), FontWeight.w400)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Metrics row
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: Row(
|
||||||
|
children: const [
|
||||||
|
Expanded(
|
||||||
|
child: SmallMetricBox(title: 'On delivery', value: '2')),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: SmallMetricBox(title: 'Available', value: '3')),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Expanded(child: SmallMetricBox(title: 'Offline', value: '1')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
|
// Gray background with search and list
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: const Color(0xFFF5F5F5),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: const Color(0xFF939495), width: 0.5),
|
||||||
|
borderRadius: BorderRadius.circular(22),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Image.asset('images/search.png',
|
||||||
|
width: 18, height: 18),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Search',
|
||||||
|
hintStyle: fontTextStyle(12,
|
||||||
|
Color(0xFF939495), FontWeight.w400),
|
||||||
|
border: InputBorder.none,
|
||||||
|
isDense: true,
|
||||||
|
),
|
||||||
|
onChanged: (v) =>
|
||||||
|
setState(() => search = v),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Image.asset("images/icon_tune.png",
|
||||||
|
width: 24, height: 24),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Image.asset("images/up_down arrow.png",
|
||||||
|
width: 24, height: 24),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
|
// Driver list
|
||||||
|
Expanded(
|
||||||
|
child: ListView.separated(
|
||||||
|
itemCount: drivers.length,
|
||||||
|
separatorBuilder: (_, __) => const SizedBox(height: 12),
|
||||||
|
itemBuilder: (context, idx) {
|
||||||
|
final d = drivers[idx];
|
||||||
|
return DriverCard(
|
||||||
|
name: d['name'],
|
||||||
|
status: d['status'],
|
||||||
|
location: d['location'],
|
||||||
|
deliveries: d['deliveries'],
|
||||||
|
commission: d['commission'],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
// Floating Action Button
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () {
|
||||||
|
// TODO: Navigate to the next step/screen
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (_) => FleetEmployees()));
|
||||||
|
|
||||||
|
},
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
shape: const CircleBorder(),
|
||||||
|
child: const Icon(Icons.add, color: Colors.white),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metric Box widget
|
||||||
|
class SmallMetricBox extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
const SmallMetricBox({super.key, required this.title, required this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: const Color(0xFF939495)),
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(title,
|
||||||
|
style:
|
||||||
|
fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500)),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(value,
|
||||||
|
style:
|
||||||
|
fontTextStyle(24, const Color(0xFF0D3771), FontWeight.w500)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Driver Card widget
|
||||||
|
class DriverCard extends StatelessWidget {
|
||||||
|
final String name;
|
||||||
|
final String status;
|
||||||
|
final String location;
|
||||||
|
final int deliveries;
|
||||||
|
final String commission;
|
||||||
|
|
||||||
|
const DriverCard({
|
||||||
|
super.key,
|
||||||
|
required this.name,
|
||||||
|
required this.status,
|
||||||
|
required this.location,
|
||||||
|
required this.deliveries,
|
||||||
|
required this.commission,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: Colors.grey.shade300),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// Row with name + phone
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
ClipOval(
|
||||||
|
child: Image.asset("images/profile_pic.png",
|
||||||
|
height: 36, width: 36, fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(name,
|
||||||
|
style: fontTextStyle(
|
||||||
|
14, const Color(0xFF2D2E30), FontWeight.w500)),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 6, vertical: 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
border: Border.all(
|
||||||
|
color: status == "available"
|
||||||
|
? Colors.green
|
||||||
|
: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
status,
|
||||||
|
style: fontTextStyle(
|
||||||
|
10,
|
||||||
|
status == "available" ? Colors.green : Colors.grey,
|
||||||
|
FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(8), // spacing around the icon
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Color(0xFFF5F6F6), // background color
|
||||||
|
shape: BoxShape.circle, // makes it perfectly round
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
"images/phone_icon.png",
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: "Location\n", style: fontTextStyle(8, Color(0xFF939495), FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: location, style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w500,),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: "Deliveries\n", style: fontTextStyle(8, const Color(0xFF939495), FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: deliveries.toString(), style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w500,),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
|
||||||
|
// Commission
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: "Commission\n", style: fontTextStyle(8, Color(0xFF939495), FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: commission, style: fontTextStyle(12, Color(0xFF515253), FontWeight.w500,),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
|
// Buttons row
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
OutlinedButton(
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
side: const BorderSide(color: Color(0xFF939495)),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(16)),
|
||||||
|
),
|
||||||
|
onPressed: () {},
|
||||||
|
child: Text("View Schedule",
|
||||||
|
style: fontTextStyle(
|
||||||
|
12, Color(0xFF515253), FontWeight.w400)),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: const Color(0xFF8270DB),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(16)),
|
||||||
|
),
|
||||||
|
onPressed: () {},
|
||||||
|
|
||||||
|
child: Text("Assign", style: fontTextStyle(12, Color(0xFFFFFFFF), FontWeight.w400)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,504 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:supplier_new/common/settings.dart';
|
||||||
|
import 'fleet.dart';
|
||||||
|
import 'resources_drivers.dart';
|
||||||
|
import 'resources_sources.dart';
|
||||||
|
|
||||||
|
import 'package:supplier_new/resources/resources_drivers.dart';
|
||||||
|
|
||||||
|
|
||||||
|
import 'package:supplier_new/resources/resources_sources.dart';
|
||||||
|
|
||||||
|
import 'fleet.dart';void main() => runApp(const MaterialApp(home: ResourcesFleetScreen()));
|
||||||
|
|
||||||
|
class ResourcesFleetScreen extends StatefulWidget {
|
||||||
|
const ResourcesFleetScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ResourcesFleetScreen> createState() => _ResourcesFleetScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
|
||||||
|
int selectedTab = 0;
|
||||||
|
String search = '';
|
||||||
|
|
||||||
|
final List<Map<String, dynamic>> items = [
|
||||||
|
{
|
||||||
|
'title': 'Tanker Name',
|
||||||
|
'subtitle': 'Drinking water - 10,000 L',
|
||||||
|
'status': ['filled', 'available'],
|
||||||
|
'code': 'TS 07 J 3492',
|
||||||
|
'owner': 'Ramesh Krishna'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Drinking Water - 15,000L',
|
||||||
|
'subtitle': 'Drinking water - 15,000 L',
|
||||||
|
'status': ['empty', 'available'],
|
||||||
|
'code': 'TS 07 J 3492',
|
||||||
|
'owner': 'Ramesh Krishna'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Tanker Name',
|
||||||
|
'subtitle': 'Drinking water - 10,000 L',
|
||||||
|
'status': ['filled', 'in-use'],
|
||||||
|
'code': 'TS 07 J 3492',
|
||||||
|
'owner': 'Ramesh Krishna'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Drinking Water - 15,000L',
|
||||||
|
'subtitle': 'Drinking water - 15,000 L',
|
||||||
|
'status': ['empty', 'in-use'],
|
||||||
|
'code': 'TS 07 J 3492',
|
||||||
|
'owner': 'Ramesh Krishna'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Tanker Name',
|
||||||
|
'subtitle': 'Drinking water - 10,000 L',
|
||||||
|
'status': ['filled', 'maintenance'],
|
||||||
|
'code': 'TS 07 J 3492',
|
||||||
|
'owner': 'Ramesh Krishna'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final filtered = items.where((it) {
|
||||||
|
final q = search.trim().toLowerCase();
|
||||||
|
if (q.isEmpty) return true;
|
||||||
|
return it['title'].toLowerCase().contains(q) ||
|
||||||
|
it['subtitle'].toLowerCase().contains(q) ||
|
||||||
|
it['owner'].toLowerCase().contains(q);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
elevation: 0.7,
|
||||||
|
leading: IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back, color: Colors.black87),
|
||||||
|
onPressed: () => Navigator.of(context).maybePop(),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
'Resources',
|
||||||
|
style: fontTextStyle(16, const Color(0xFF2A2A2A), FontWeight.w600),
|
||||||
|
),
|
||||||
|
centerTitle: false,
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: Text('HELP',
|
||||||
|
style: fontTextStyle(
|
||||||
|
12, const Color(0xFF8270DB), FontWeight.w600)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
color: Colors.white,
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 12),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// Segmented pill
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
child: Row(
|
||||||
|
children: List.generate(3, (i) {
|
||||||
|
final labels = ['Fleet', 'Drivers', 'Sources'];
|
||||||
|
final isSelected = selectedTab == i;
|
||||||
|
return Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => setState(() => selectedTab = i),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isSelected
|
||||||
|
? const Color(0xFFF1F1F1)
|
||||||
|
: Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
labels[i],
|
||||||
|
style: TextStyle(
|
||||||
|
color: isSelected
|
||||||
|
? const Color(0xFF101214)
|
||||||
|
: const Color(0xFF646464),
|
||||||
|
fontWeight: isSelected
|
||||||
|
? FontWeight.w600
|
||||||
|
: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: Color(0xFF939495)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Color(0xFFF6F0FF),
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Image.asset(
|
||||||
|
'images/truck.png',
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text('Total Tankers', style: fontTextStyle(12, Color(0xFF2D2E30), FontWeight.w500, // or w500 if you want slightly bolder
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [Text('14', style: fontTextStyle(24, const Color(0xFF0D3771), FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 6),
|
||||||
|
Text('+2 since last month',
|
||||||
|
style: fontTextStyle(10, Color(0xFF646566), FontWeight.w400,)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
|
IntrinsicHeight(
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SmallMetricBox(title: 'Active', value: '2')),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: SmallMetricBox(title: 'Inactive', value: '3')),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: SmallMetricBox(
|
||||||
|
title: 'Under Maintenances', value: '1')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// -------- SECOND SECTION (gray background) ----------
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: const Color(0xFFF5F5F5), // Gray background
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 270,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: Color(0xFF939495), // 👈 border color
|
||||||
|
width: 0.5, // 👈 border width
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(22),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('images/search.png'),
|
||||||
|
fit: BoxFit.contain),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Search',
|
||||||
|
hintStyle: fontTextStyle(
|
||||||
|
12,
|
||||||
|
const Color(0xFF939495),
|
||||||
|
FontWeight.w400),
|
||||||
|
border: InputBorder.none,
|
||||||
|
isDense: true,
|
||||||
|
),
|
||||||
|
onChanged: (v) =>
|
||||||
|
setState(() => search = v),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Container(
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('images/icon_tune.png'),
|
||||||
|
fit: BoxFit.contain),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Container(
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('images/up_down arrow.png'),
|
||||||
|
fit: BoxFit.contain),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
|
// Cards List
|
||||||
|
Expanded(
|
||||||
|
child: ListView.separated(
|
||||||
|
itemCount: filtered.length,
|
||||||
|
separatorBuilder: (_, __) => const SizedBox(height: 10),
|
||||||
|
itemBuilder: (context, idx) {
|
||||||
|
final it = filtered[idx];
|
||||||
|
return TankCard(
|
||||||
|
title: it['title'],
|
||||||
|
subtitle: it['subtitle'],
|
||||||
|
code: it['code'],
|
||||||
|
owner: it['owner'],
|
||||||
|
status: List<String>.from(it['status']),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () {
|
||||||
|
// TODO: Navigate to the next step/screen
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (_) => const FleetStep1Page()));
|
||||||
|
|
||||||
|
},
|
||||||
|
backgroundColor: const Color(0xFF000000),
|
||||||
|
shape: const CircleBorder(), // ✅ ensures circle
|
||||||
|
child: const Icon(Icons.add,color: Colors.white,),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== SmallMetricBox ======
|
||||||
|
class SmallMetricBox extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
const SmallMetricBox({super.key, required this.title, required this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: Color(0xFF939495)),
|
||||||
|
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(title,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style:
|
||||||
|
fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500)),
|
||||||
|
Text(value,
|
||||||
|
style:
|
||||||
|
fontTextStyle(24, const Color(0xFF0D3771), FontWeight.w500)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== TankCard ======
|
||||||
|
class TankCard extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final String subtitle;
|
||||||
|
final String code;
|
||||||
|
final String owner;
|
||||||
|
final List<String> status;
|
||||||
|
|
||||||
|
const TankCard({
|
||||||
|
super.key,
|
||||||
|
required this.title,
|
||||||
|
required this.subtitle,
|
||||||
|
required this.code,
|
||||||
|
required this.owner,
|
||||||
|
required this.status,
|
||||||
|
});
|
||||||
|
|
||||||
|
Color _chipColor(String s) {
|
||||||
|
switch (s) {
|
||||||
|
case 'filled':
|
||||||
|
return const Color(0xFFFFFFFF);
|
||||||
|
case 'available':
|
||||||
|
return const Color(0xFFE8F0FF);
|
||||||
|
case 'empty':
|
||||||
|
return const Color(0xFFFFEEEE);
|
||||||
|
case 'in-use':
|
||||||
|
return const Color(0xFFFFF0E6);
|
||||||
|
case 'maintenance':
|
||||||
|
return const Color(0xFFFFF4E6);
|
||||||
|
default:
|
||||||
|
return const Color(0xFFECECEC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color _chipTextColor(String s) {
|
||||||
|
switch (s) {
|
||||||
|
case 'filled':
|
||||||
|
return const Color(0xFF1D7AFC);
|
||||||
|
case 'available':
|
||||||
|
return const Color(0xFF0A9E04);
|
||||||
|
case 'empty':
|
||||||
|
return const Color(0xFFE2483D);
|
||||||
|
case 'in-use':
|
||||||
|
return const Color(0xFFEA843B);
|
||||||
|
case 'maintenance':
|
||||||
|
return const Color(0xFFD0AE3C);
|
||||||
|
default:
|
||||||
|
return Colors.black87;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: Colors.grey.shade200),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: status.map((s) {
|
||||||
|
final chipTextColor = _chipTextColor(s);
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.only(right: 6),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8, vertical: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: _chipColor(s),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
border: Border.all(color: chipTextColor, width: 1),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
s, style:
|
||||||
|
fontTextStyle(10, chipTextColor, FontWeight.w400),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(title,
|
||||||
|
style: fontTextStyle(
|
||||||
|
14, const Color(0xFF343637), FontWeight.w600)),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(subtitle,
|
||||||
|
style: fontTextStyle(
|
||||||
|
10, const Color(0xFF515253), FontWeight.w600)),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
ClipOval(
|
||||||
|
child: Container(
|
||||||
|
height: 12,
|
||||||
|
width: 12,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
image: DecorationImage(
|
||||||
|
image: (AppSettings.profilePictureUrl != '' &&
|
||||||
|
AppSettings.profilePictureUrl != 'null')
|
||||||
|
? NetworkImage(AppSettings.profilePictureUrl)
|
||||||
|
as ImageProvider
|
||||||
|
: const AssetImage("images/profile_pic.png"),
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Expanded(
|
||||||
|
child: Text(owner,
|
||||||
|
style: fontTextStyle(
|
||||||
|
8, const Color(0xFF646566), FontWeight.w400)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text(code,
|
||||||
|
style: fontTextStyle(
|
||||||
|
10, const Color(0xFF515253), FontWeight.w400)),
|
||||||
|
const SizedBox(height: 28),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,392 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:supplier_new/common/settings.dart';
|
||||||
|
import 'package:supplier_new/resources/source_location.dart';
|
||||||
|
import 'fleet.dart';
|
||||||
|
import 'resources_drivers.dart';
|
||||||
|
import 'resources_sources.dart';
|
||||||
|
|
||||||
|
|
||||||
|
void main() => runApp(const MaterialApp(home: ResourcesSourceScreen()));
|
||||||
|
|
||||||
|
class ResourcesSourceScreen extends StatefulWidget {
|
||||||
|
const ResourcesSourceScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ResourcesSourceScreen> createState() => _ResourcesSourceScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ResourcesSourceScreenState extends State<ResourcesSourceScreen> {
|
||||||
|
int selectedTab = 2;
|
||||||
|
String search = '';
|
||||||
|
|
||||||
|
final List<Map<String, dynamic>> items = [
|
||||||
|
{
|
||||||
|
'title': 'Gandipet Water Supply',
|
||||||
|
'subtitle': 'Road No.34, Blah',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Gandipet Water Supply',
|
||||||
|
'subtitle': 'Road No.34, Blah',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Gandipet Water Supply',
|
||||||
|
'subtitle': 'Road No.34, Blah',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Gandipet Water Supply',
|
||||||
|
'subtitle': 'Road No.34, Blah',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Gandipet Water Supply',
|
||||||
|
'subtitle': 'Road No.34, Blah',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final filtered = items.where((it) {
|
||||||
|
final q = search.trim().toLowerCase();
|
||||||
|
if (q.isEmpty) return true;
|
||||||
|
return it['title'].toLowerCase().contains(q) ||
|
||||||
|
it['subtitle'].toLowerCase().contains(q) ||
|
||||||
|
(it['owner']?.toLowerCase() ?? '').contains(q);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
elevation: 0.7,
|
||||||
|
leading: IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back, color: Colors.black87),
|
||||||
|
onPressed: () => Navigator.of(context).maybePop(),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
'Resources',
|
||||||
|
style: fontTextStyle(16, const Color(0xFF2A2A2A), FontWeight.w600),
|
||||||
|
),
|
||||||
|
centerTitle: false,
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: Text('HELP',
|
||||||
|
style: fontTextStyle(
|
||||||
|
12, const Color(0xFF8270DB), FontWeight.w600)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
// Top card section
|
||||||
|
Container(
|
||||||
|
color: Colors.white,
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 12),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// Segmented pill
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
child: Row(
|
||||||
|
children: List.generate(3, (i) {
|
||||||
|
final labels = ['Fleet', 'Drivers', 'Sources'];
|
||||||
|
final isSelected = selectedTab == i;
|
||||||
|
return Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => setState(() => selectedTab = i),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isSelected
|
||||||
|
? const Color(0xFFF1F1F1)
|
||||||
|
: Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
labels[i],
|
||||||
|
style: TextStyle(
|
||||||
|
color: isSelected
|
||||||
|
? const Color(0xFF101214)
|
||||||
|
: const Color(0xFF646464),
|
||||||
|
fontWeight: isSelected
|
||||||
|
? FontWeight.w600
|
||||||
|
: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
// Total Source Locations card
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: const Color(0xFF939495)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Color(0xFFF6F0FF),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Image.asset(
|
||||||
|
'images/drivers.png',
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
'Total Source Locations',
|
||||||
|
style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'04',
|
||||||
|
style: fontTextStyle(24, const Color(0xFF0D3771), FontWeight.w500),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text('no recent changes',
|
||||||
|
style: fontTextStyle(10, const Color(0xFF646566), FontWeight.w400)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
// Metrics boxes
|
||||||
|
IntrinsicHeight(
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Expanded(child: SmallMetricBox(title: 'Drinking water', value: '2')),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(child: SmallMetricBox(title: 'Bore water', value: '3')),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(child: SmallMetricBox(title: 'Both', value: '1')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// SECOND SECTION (gray background)
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: const Color(0xFFF5F5F5),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// Search row
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 270,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: const Color(0xFF939495),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(22),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('images/search.png'),
|
||||||
|
fit: BoxFit.contain),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Search',
|
||||||
|
hintStyle: fontTextStyle(12, const Color(0xFF939495), FontWeight.w400),
|
||||||
|
border: InputBorder.none,
|
||||||
|
isDense: true,
|
||||||
|
),
|
||||||
|
onChanged: (v) => setState(() => search = v),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Container(
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('images/icon_tune.png'),
|
||||||
|
fit: BoxFit.contain),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Container(
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('images/up_down arrow.png'),
|
||||||
|
fit: BoxFit.contain),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
|
// Cards List
|
||||||
|
Expanded(
|
||||||
|
child: ListView.separated(
|
||||||
|
itemCount: filtered.length,
|
||||||
|
separatorBuilder: (_, __) => const SizedBox(height: 10),
|
||||||
|
itemBuilder: (context, idx) {
|
||||||
|
final it = filtered[idx];
|
||||||
|
return TankCard(
|
||||||
|
title: it['title'],
|
||||||
|
subtitle: it['subtitle'],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () {
|
||||||
|
// TODO: Navigate to the next step/screen
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (_) => const SourceLocation()));
|
||||||
|
|
||||||
|
},
|
||||||
|
backgroundColor: const Color(0xFF000000),
|
||||||
|
shape: const CircleBorder(),
|
||||||
|
child: const Icon(Icons.add, color: Colors.white),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== SmallMetricBox ======
|
||||||
|
class SmallMetricBox extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
const SmallMetricBox({super.key, required this.title, required this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: const Color(0xFF939495)),
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(title,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500)),
|
||||||
|
Text(value,
|
||||||
|
style: fontTextStyle(24, const Color(0xFF0D3771), FontWeight.w500)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== TankCard (with phone icon inside) ======
|
||||||
|
class TankCard extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final String subtitle;
|
||||||
|
|
||||||
|
const TankCard({
|
||||||
|
super.key,
|
||||||
|
required this.title,
|
||||||
|
required this.subtitle,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: Colors.grey.shade200),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
// Title and subtitle
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(title,
|
||||||
|
style: fontTextStyle(14, const Color(0xFF343637), FontWeight.w600)),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(subtitle,
|
||||||
|
style: fontTextStyle(10, const Color(0xFF515253), FontWeight.w600)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
// Phone icon inside card
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Color(0xFFF5F6F6),
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
"images/phone_icon.png",
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in new issue