resources added

master
gitadmin 3 months ago
parent a334320c80
commit b07033dda7

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/resources/resources.dart'; import 'package:supplier_new/resources/resources_fleet.dart';
import 'package:supplier_new/resources/source_location2.dart'; import 'package:supplier_new/resources/source_location2.dart';
void main() => runApp(const MaterialApp(home: AvailabilityScreen())); void main() => runApp(const MaterialApp(home: AvailabilityScreen()));
@ -335,7 +335,7 @@ class _AvailabilityScreenState extends State<AvailabilityScreen> {
), ),
onPressed: () { onPressed: () {
// TODO: Navigate to the next step/screen // TODO: Navigate to the next step/screen
Navigator.push(context, MaterialPageRoute(builder: (_) => const ResourcesScreen())); Navigator.push(context, MaterialPageRoute(builder: (_) => const ResourcesFleetScreen()));
}, },
child: Text( child: Text(

@ -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…
Cancel
Save