You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
353 lines
13 KiB
353 lines
13 KiB
1 day ago
|
import 'package:flutter/material.dart';
|
||
|
import 'package:supplier_new/common/settings.dart';
|
||
|
import 'package:supplier_new/resources/resources.dart';
|
||
|
import 'package:supplier_new/resources/source_location2.dart';
|
||
|
|
||
|
void main() => runApp(const MaterialApp(home: AvailabilityScreen()));
|
||
|
|
||
|
class AvailabilityScreen extends StatefulWidget {
|
||
|
const AvailabilityScreen({super.key});
|
||
|
|
||
|
@override
|
||
|
_AvailabilityScreenState createState() => _AvailabilityScreenState();
|
||
|
}
|
||
|
|
||
|
class _AvailabilityScreenState extends State<AvailabilityScreen> {
|
||
|
final TextEditingController _advanceNoticeController =
|
||
|
TextEditingController();
|
||
|
final TextEditingController _minDeliveriesController =
|
||
|
TextEditingController();
|
||
|
final TextEditingController _phoneController = TextEditingController();
|
||
|
TimeOfDay? _weekdayStartTime;
|
||
|
TimeOfDay? _weekdayEndTime;
|
||
|
TimeOfDay? _weekendStartTime;
|
||
|
TimeOfDay? _weekendEndTime;
|
||
|
|
||
|
|
||
|
final List<String> _days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
||
|
List<bool> _selectedDays = List.generate(7, (index) => false);
|
||
|
|
||
|
Future<void> _pickTime({required int slot}) async {
|
||
|
final TimeOfDay initialTime = TimeOfDay.now();
|
||
|
final TimeOfDay? picked =
|
||
|
await showTimePicker(context: context, initialTime: initialTime);
|
||
|
if (picked == null) return;
|
||
|
setState(() {
|
||
|
switch (slot) {
|
||
|
case 0:
|
||
|
_weekdayStartTime = picked;
|
||
|
break;
|
||
|
case 1:
|
||
|
_weekdayEndTime = picked;
|
||
|
break;
|
||
|
case 2:
|
||
|
_weekendStartTime = picked;
|
||
|
break;
|
||
|
case 3:
|
||
|
_weekendEndTime = picked;
|
||
|
break;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return Scaffold(
|
||
|
backgroundColor: Colors.white,
|
||
|
appBar: AppBar(
|
||
|
backgroundColor: Colors.white,
|
||
|
surfaceTintColor: Colors.transparent,
|
||
|
elevation: 0,
|
||
|
scrolledUnderElevation: 0,
|
||
|
title: const Text("Complete Profile"),
|
||
|
actions: [
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.fromLTRB(10, 10, 0, 10),
|
||
|
child: IconButton(
|
||
|
splashRadius: 20,
|
||
|
padding: EdgeInsets.zero,
|
||
|
icon: const Image(
|
||
|
image: AssetImage('images/calendar_appbar.png'),
|
||
|
width: 22,
|
||
|
height: 22,
|
||
|
),
|
||
|
onPressed: () {},
|
||
|
),
|
||
|
),
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.fromLTRB(0, 10, 10, 10),
|
||
|
child: IconButton(
|
||
|
splashRadius: 20,
|
||
|
padding: EdgeInsets.zero,
|
||
|
icon: Image.asset('images/notification_appbar.png',
|
||
|
width: 22, height: 22),
|
||
|
onPressed: () {},
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
body: SingleChildScrollView(
|
||
|
padding: const EdgeInsets.all(16),
|
||
|
child: Column(
|
||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
children: [
|
||
|
// Step indicator
|
||
|
Text('Step 5/5',
|
||
|
style: fontTextStyle(14, Colors.grey, FontWeight.normal)),
|
||
|
const SizedBox(height: 4),
|
||
|
Row(
|
||
|
children: List.generate(4, (index) {
|
||
|
return Expanded(
|
||
|
child: Container(
|
||
|
margin: const EdgeInsets.symmetric(horizontal: 2),
|
||
|
height: 5,
|
||
|
decoration: BoxDecoration(
|
||
|
color: index < 4 ? const Color(0xFFC3C4C4) : Colors.grey,
|
||
|
borderRadius: BorderRadius.circular(2),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}),
|
||
|
),
|
||
|
const SizedBox(height: 20),
|
||
|
|
||
|
// Availability
|
||
|
Text('AVAILABILITY',
|
||
|
style: fontTextStyle(
|
||
|
16, const Color(0xFF2D2E30), FontWeight.w500)),
|
||
|
const SizedBox(height: 12),
|
||
|
Container(
|
||
|
width: 24,
|
||
|
height: 24,
|
||
|
decoration: const BoxDecoration(
|
||
|
image: DecorationImage(
|
||
|
image: AssetImage('images/calendar_check.png'),
|
||
|
fit: BoxFit.contain),
|
||
|
),
|
||
|
),
|
||
|
const SizedBox(height: 5),
|
||
|
Text('Set your operating schedule',
|
||
|
style: fontTextStyle(
|
||
|
14, const Color(0xFF939495), FontWeight.w500)),
|
||
|
const SizedBox(height: 10),
|
||
|
|
||
|
Text('AVAILABILITY',
|
||
|
style: fontTextStyle(
|
||
|
14, const Color(0xFF8270DB), FontWeight.w600)),
|
||
|
const SizedBox(height: 12),
|
||
|
Text('Advance Notice Required (hours) *',
|
||
|
style: fontTextStyle(
|
||
|
12, const Color(0xFF2F3036), FontWeight.w600)),
|
||
|
const SizedBox(height: 5),
|
||
|
TextField(
|
||
|
controller: _advanceNoticeController,
|
||
|
keyboardType: TextInputType.number,
|
||
|
decoration: InputDecoration(
|
||
|
border: OutlineInputBorder(),
|
||
|
hintText: "1",
|
||
|
hintStyle:
|
||
|
fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
|
||
|
),
|
||
|
),
|
||
|
|
||
|
const SizedBox(height: 10),
|
||
|
|
||
|
// Minimum Deliveries
|
||
|
Text('Minimum Deliveries (per day) *',
|
||
|
style: fontTextStyle(
|
||
|
12, const Color(0xFF2F3036), FontWeight.w600)),
|
||
|
const SizedBox(height: 5),
|
||
|
TextField(
|
||
|
controller: _minDeliveriesController,
|
||
|
keyboardType: TextInputType.number,
|
||
|
decoration: InputDecoration(
|
||
|
border: OutlineInputBorder(),
|
||
|
hintText: '10',
|
||
|
hintStyle:
|
||
|
fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
|
||
|
),
|
||
|
),
|
||
|
const SizedBox(height: 10),
|
||
|
|
||
|
// Days of Availability
|
||
|
Text(
|
||
|
'Days of Availability *',
|
||
|
style:
|
||
|
fontTextStyle(12, const Color(0xFF251525), FontWeight.w600),
|
||
|
),
|
||
|
const SizedBox(height: 5),
|
||
|
// Place this inside your build() where you want the row of day boxes
|
||
|
// Place this where you want the row of day boxes
|
||
|
Theme(
|
||
|
data: Theme.of(context).copyWith(
|
||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||
|
visualDensity: VisualDensity.compact,
|
||
|
),
|
||
|
child: SingleChildScrollView(
|
||
|
scrollDirection: Axis.horizontal,
|
||
|
child: Row(
|
||
|
children: List.generate(_days.length, (index) {
|
||
|
final day = _days[index];
|
||
|
final selected = _selectedDays[index];
|
||
|
|
||
|
return Padding(
|
||
|
padding: const EdgeInsets.only(right: 7.0), // gap 10px
|
||
|
child: GestureDetector(
|
||
|
onTap: () => setState(
|
||
|
() => _selectedDays[index] = !_selectedDays[index]),
|
||
|
onSecondaryTap: () {},
|
||
|
// swallow right-click / context menu
|
||
|
child: SizedBox(
|
||
|
width: 44, // fixed width
|
||
|
height: 42, // fixed height
|
||
|
child: Container(
|
||
|
padding: const EdgeInsets.all(8),
|
||
|
// inner padding 8px
|
||
|
decoration: BoxDecoration(
|
||
|
color: selected
|
||
|
? const Color(0xFF6F5FBA)
|
||
|
: Colors.white,
|
||
|
// selected background
|
||
|
borderRadius: BorderRadius.circular(9),
|
||
|
// radius 9px
|
||
|
border: Border.all(
|
||
|
color: const Color(0xFF6F5FBA),
|
||
|
width: 0.5, // border 0.5px
|
||
|
),
|
||
|
),
|
||
|
alignment: Alignment.center,
|
||
|
child: Text(
|
||
|
day,
|
||
|
textAlign: TextAlign.center,
|
||
|
style: fontTextStyle(
|
||
|
12,
|
||
|
selected
|
||
|
? Colors.white
|
||
|
: const Color(0xFF515253),
|
||
|
FontWeight.w600,
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
|
||
|
const SizedBox(height: 10),
|
||
|
|
||
|
// Phone Number
|
||
|
Text('Phone Number *',
|
||
|
style: fontTextStyle(
|
||
|
12, const Color(0xFF2F3036), FontWeight.w600)),
|
||
|
const SizedBox(height: 5),
|
||
|
TextField(
|
||
|
controller: _phoneController,
|
||
|
keyboardType: TextInputType.phone,
|
||
|
decoration: InputDecoration(
|
||
|
border: OutlineInputBorder(),
|
||
|
hintText: '+91 | Mobile Number',
|
||
|
hintStyle:
|
||
|
fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
|
||
|
),
|
||
|
),
|
||
|
const SizedBox(height: 20),
|
||
|
|
||
|
// Operating Hours
|
||
|
Text('Operating Hours',
|
||
|
style: fontTextStyle(
|
||
|
14, const Color(0xFF8270DB), FontWeight.w600)),
|
||
|
const SizedBox(height: 5),
|
||
|
LayoutBuilder(
|
||
|
builder: (context, constraints) {
|
||
|
// compute width for 2 columns with 10px gap and 16px padding (adjust if needed)
|
||
|
final double totalGap = 10.0;
|
||
|
final double itemWidth = (constraints.maxWidth - totalGap) / 2;
|
||
|
|
||
|
Widget buildTimeBox({
|
||
|
required String label,
|
||
|
required TimeOfDay? time,
|
||
|
required int slotIndex,
|
||
|
}) {
|
||
|
return SizedBox(
|
||
|
width: itemWidth,
|
||
|
// smaller height than before
|
||
|
child: Column(
|
||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
children: [
|
||
|
Text(label, style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600)),
|
||
|
const SizedBox(height: 5),
|
||
|
GestureDetector(
|
||
|
onTap: () => _pickTime(slot: slotIndex),
|
||
|
child: Container(
|
||
|
height: 42, // smaller height
|
||
|
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||
|
decoration: BoxDecoration(
|
||
|
border: Border.all(color: Colors.grey.shade400),
|
||
|
borderRadius: BorderRadius.circular(6),
|
||
|
),
|
||
|
alignment: Alignment.centerLeft,
|
||
|
child: Text(
|
||
|
time != null ? time.format(context) : '--:--',
|
||
|
style: fontTextStyle(14, Colors.black, FontWeight.normal),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return Column(
|
||
|
children: [
|
||
|
Row(
|
||
|
children: [
|
||
|
buildTimeBox(label: 'Weekday Start Time *', time: _weekdayStartTime, slotIndex: 0),
|
||
|
const SizedBox(width: 10),
|
||
|
buildTimeBox(label: 'Weekday End Time *', time: _weekdayEndTime, slotIndex: 1),
|
||
|
],
|
||
|
),
|
||
|
const SizedBox(height: 12),
|
||
|
Row(
|
||
|
children: [
|
||
|
buildTimeBox(label: 'Weekend Start Time', time: _weekendStartTime, slotIndex: 2),
|
||
|
const SizedBox(width: 10),
|
||
|
buildTimeBox(label: 'Weekend End Time', time: _weekendEndTime, slotIndex: 3),
|
||
|
],
|
||
|
),
|
||
|
],
|
||
|
);
|
||
|
},
|
||
|
),
|
||
|
|
||
|
const SizedBox(height: 12),
|
||
|
SizedBox(
|
||
|
width: double.infinity,
|
||
|
child: ElevatedButton(
|
||
|
style: ElevatedButton.styleFrom(
|
||
|
backgroundColor: const Color(0xFF8270DB),
|
||
|
foregroundColor: Colors.white,
|
||
|
padding: const EdgeInsets.symmetric(vertical: 14),
|
||
|
shape: RoundedRectangleBorder(
|
||
|
borderRadius: BorderRadius.circular(24)),
|
||
|
),
|
||
|
onPressed: () {
|
||
|
// TODO: Navigate to the next step/screen
|
||
|
Navigator.push(context, MaterialPageRoute(builder: (_) => const ResourcesScreen()));
|
||
|
|
||
|
},
|
||
|
child: Text(
|
||
|
" Save \$ Continue",
|
||
|
style: fontTextStyle(14, Colors.white, FontWeight.w400),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|