BASE: Update Icons & Name Of The App.
This commit is contained in:
@@ -11,7 +11,7 @@ import 'package:customer/themes/app_them_data.dart';
|
||||
import 'package:customer/themes/round_button_fill.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
|
||||
class FavouriteOndemandScreen extends StatelessWidget {
|
||||
const FavouriteOndemandScreen({super.key});
|
||||
@@ -24,7 +24,8 @@ class FavouriteOndemandScreen extends StatelessWidget {
|
||||
init: FavouriteOndemmandController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
backgroundColor:
|
||||
isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
backgroundColor: AppThemeData.onDemand300,
|
||||
@@ -33,7 +34,15 @@ class FavouriteOndemandScreen extends StatelessWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(width: 10),
|
||||
Text("Favourite Services".tr(), style: TextStyle(fontFamily: AppThemeData.semiBold, color: isDark ? AppThemeData.grey900 : AppThemeData.grey900, fontSize: 20)),
|
||||
Text(
|
||||
"Favourite Services".tr(),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color:
|
||||
isDark ? AppThemeData.grey900 : AppThemeData.grey900,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -50,12 +59,30 @@ class FavouriteOndemandScreen extends StatelessWidget {
|
||||
children: [
|
||||
Image.asset("assets/images/login.gif", height: 120),
|
||||
const SizedBox(height: 12),
|
||||
Text("Please Log In to Continue".tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)),
|
||||
Text(
|
||||
"Please Log In to Continue".tr(),
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey100
|
||||
: AppThemeData.grey800,
|
||||
fontSize: 22,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
"You’re not logged in. Please sign in to access your account and explore all features.".tr(),
|
||||
"You’re not logged in. Please sign in to access your account and explore all features."
|
||||
.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold),
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey50
|
||||
: AppThemeData.grey500,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
RoundedButtonFill(
|
||||
@@ -72,10 +99,15 @@ class FavouriteOndemandScreen extends StatelessWidget {
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
child:
|
||||
controller.lstFav.isEmpty
|
||||
? Constant.showEmptyView(message: "Favourite Service not found.".tr())
|
||||
? Constant.showEmptyView(
|
||||
message: "Favourite Service not found.".tr(),
|
||||
)
|
||||
: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
@@ -83,86 +115,231 @@ class FavouriteOndemandScreen extends StatelessWidget {
|
||||
physics: const BouncingScrollPhysics(),
|
||||
itemCount: controller.lstFav.length,
|
||||
itemBuilder: (context, index) {
|
||||
return FutureBuilder<List<ProviderServiceModel>>(
|
||||
future: FireStoreUtils.getCurrentProviderService(controller.lstFav[index]),
|
||||
return FutureBuilder<
|
||||
List<ProviderServiceModel>
|
||||
>(
|
||||
future:
|
||||
FireStoreUtils.getCurrentProviderService(
|
||||
controller.lstFav[index],
|
||||
),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
if (snapshot.connectionState ==
|
||||
ConnectionState.waiting) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
|
||||
if (!snapshot.hasData || snapshot.data == null || snapshot.data!.isEmpty) {
|
||||
if (!snapshot.hasData ||
|
||||
snapshot.data == null ||
|
||||
snapshot.data!.isEmpty) {
|
||||
return const SizedBox(); // or a placeholder widget
|
||||
}
|
||||
|
||||
final provider = snapshot.data!.first; // safer way than [0]
|
||||
final provider =
|
||||
snapshot
|
||||
.data!
|
||||
.first; // safer way than [0]
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(() => OnDemandDetailsScreen(), arguments: {'providerModel': provider});
|
||||
Get.to(
|
||||
() => OnDemandDetailsScreen(),
|
||||
arguments: {
|
||||
'providerModel': provider,
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 5,
|
||||
),
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).size.height * 0.16,
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height *
|
||||
0.16,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade100, width: 1),
|
||||
color: isDark ? AppThemeData.grey900 : Colors.white,
|
||||
borderRadius: BorderRadius.circular(
|
||||
10,
|
||||
),
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey500
|
||||
: Colors.grey.shade100,
|
||||
width: 1,
|
||||
),
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey900
|
||||
: Colors.white,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(10), topLeft: Radius.circular(10)),
|
||||
borderRadius:
|
||||
const BorderRadius.only(
|
||||
bottomLeft:
|
||||
Radius.circular(10),
|
||||
topLeft: Radius.circular(
|
||||
10,
|
||||
),
|
||||
),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: provider.photos.isNotEmpty ? provider.photos.first : Constant.placeHolderImage,
|
||||
height: MediaQuery.of(context).size.height * 0.16,
|
||||
imageUrl:
|
||||
provider.photos.isNotEmpty
|
||||
? provider
|
||||
.photos
|
||||
.first
|
||||
: Constant
|
||||
.placeHolderImage,
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height *
|
||||
0.16,
|
||||
width: 110,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))),
|
||||
errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover),
|
||||
placeholder:
|
||||
(context, url) => Center(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation(
|
||||
AppThemeData
|
||||
.primary300,
|
||||
),
|
||||
),
|
||||
),
|
||||
errorWidget:
|
||||
(
|
||||
context,
|
||||
url,
|
||||
error,
|
||||
) => Image.network(
|
||||
Constant
|
||||
.placeHolderImage,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment
|
||||
.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment
|
||||
.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
provider.title ?? "",
|
||||
provider.title ??
|
||||
"",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black),
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight:
|
||||
FontWeight
|
||||
.bold,
|
||||
color:
|
||||
isDark
|
||||
? Colors
|
||||
.white
|
||||
: Colors
|
||||
.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => GestureDetector(
|
||||
onTap: () => controller.toggleFavourite(provider),
|
||||
onTap:
|
||||
() => controller
|
||||
.toggleFavourite(
|
||||
provider,
|
||||
),
|
||||
child: Icon(
|
||||
controller.lstFav.where((element) => element.service_id == provider.id).isNotEmpty ? Icons.favorite : Icons.favorite_border,
|
||||
controller
|
||||
.lstFav
|
||||
.where(
|
||||
(
|
||||
element,
|
||||
) =>
|
||||
element.service_id ==
|
||||
provider.id,
|
||||
)
|
||||
.isNotEmpty
|
||||
? Icons
|
||||
.favorite
|
||||
: Icons
|
||||
.favorite_border,
|
||||
size: 24,
|
||||
color:
|
||||
controller.lstFav.where((element) => element.service_id == provider.id).isNotEmpty
|
||||
? AppThemeData.primary300
|
||||
: (isDark ? Colors.white38 : Colors.black38),
|
||||
controller
|
||||
.lstFav
|
||||
.where(
|
||||
(
|
||||
element,
|
||||
) =>
|
||||
element.service_id ==
|
||||
provider.id,
|
||||
)
|
||||
.isNotEmpty
|
||||
? AppThemeData
|
||||
.primary300
|
||||
: (isDark
|
||||
? Colors.white38
|
||||
: Colors.black38),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
FutureBuilder<CategoryModel?>(
|
||||
future: controller.getCategory(provider.categoryId ?? ""),
|
||||
FutureBuilder<
|
||||
CategoryModel?
|
||||
>(
|
||||
future: controller
|
||||
.getCategory(
|
||||
provider.categoryId ??
|
||||
"",
|
||||
),
|
||||
builder: (ctx, snap) {
|
||||
if (!snap.hasData) return const SizedBox();
|
||||
return Text(snap.data?.title ?? "", style: TextStyle(fontSize: 14, color: isDark ? Colors.white : Colors.black));
|
||||
if (!snap.hasData)
|
||||
return const SizedBox();
|
||||
return Text(
|
||||
snap.data?.title ??
|
||||
"",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark
|
||||
? Colors
|
||||
.white
|
||||
: Colors
|
||||
.black,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildPrice(provider, isDark: isDark),
|
||||
_buildPrice(
|
||||
provider,
|
||||
isDark: isDark,
|
||||
),
|
||||
_buildRating(provider),
|
||||
],
|
||||
),
|
||||
@@ -176,79 +353,231 @@ class FavouriteOndemandScreen extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
FutureBuilder<List<ProviderServiceModel>>(
|
||||
future: FireStoreUtils.getCurrentProviderService(controller.lstFav[index]),
|
||||
future:
|
||||
FireStoreUtils.getCurrentProviderService(
|
||||
controller.lstFav[index],
|
||||
),
|
||||
builder: (context, snapshot) {
|
||||
return snapshot.data != null
|
||||
? GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(() => OnDemandDetailsScreen(), arguments: {'providerModel': snapshot.data![0]});
|
||||
Get.to(
|
||||
() => OnDemandDetailsScreen(),
|
||||
arguments: {
|
||||
'providerModel':
|
||||
snapshot.data![0],
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 5,
|
||||
),
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).size.height * 0.16,
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height *
|
||||
0.16,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade100, width: 1),
|
||||
color: isDark ? AppThemeData.grey900 : Colors.white,
|
||||
borderRadius:
|
||||
BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey500
|
||||
: Colors
|
||||
.grey
|
||||
.shade100,
|
||||
width: 1,
|
||||
),
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey900
|
||||
: Colors.white,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(10), topLeft: Radius.circular(10)),
|
||||
borderRadius:
|
||||
const BorderRadius.only(
|
||||
bottomLeft:
|
||||
Radius.circular(
|
||||
10,
|
||||
),
|
||||
topLeft:
|
||||
Radius.circular(
|
||||
10,
|
||||
),
|
||||
),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: snapshot.data![0].photos.isNotEmpty ? snapshot.data![0].photos[0] : Constant.placeHolderImage,
|
||||
height: MediaQuery.of(context).size.height * 0.16,
|
||||
imageUrl:
|
||||
snapshot
|
||||
.data![0]
|
||||
.photos
|
||||
.isNotEmpty
|
||||
? snapshot
|
||||
.data![0]
|
||||
.photos[0]
|
||||
: Constant
|
||||
.placeHolderImage,
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height *
|
||||
0.16,
|
||||
width: 110,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))),
|
||||
errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover),
|
||||
placeholder:
|
||||
(
|
||||
context,
|
||||
url,
|
||||
) => Center(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation(
|
||||
AppThemeData
|
||||
.primary300,
|
||||
),
|
||||
),
|
||||
),
|
||||
errorWidget:
|
||||
(
|
||||
context,
|
||||
url,
|
||||
error,
|
||||
) => Image.network(
|
||||
Constant
|
||||
.placeHolderImage,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment
|
||||
.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment
|
||||
.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
snapshot.data![0].title ?? "",
|
||||
snapshot
|
||||
.data![0]
|
||||
.title ??
|
||||
"",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black),
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
18,
|
||||
fontWeight:
|
||||
FontWeight
|
||||
.bold,
|
||||
color:
|
||||
isDark
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => GestureDetector(
|
||||
onTap: () => controller.toggleFavourite(snapshot.data![0]),
|
||||
onTap:
|
||||
() => controller.toggleFavourite(
|
||||
snapshot
|
||||
.data![0],
|
||||
),
|
||||
child: Icon(
|
||||
controller.lstFav.where((element) => element.service_id == snapshot.data![0].id).isNotEmpty
|
||||
? Icons.favorite
|
||||
: Icons.favorite_border,
|
||||
controller
|
||||
.lstFav
|
||||
.where(
|
||||
(
|
||||
element,
|
||||
) =>
|
||||
element.service_id ==
|
||||
snapshot.data![0].id,
|
||||
)
|
||||
.isNotEmpty
|
||||
? Icons
|
||||
.favorite
|
||||
: Icons
|
||||
.favorite_border,
|
||||
size: 24,
|
||||
color:
|
||||
controller.lstFav.where((element) => element.service_id == snapshot.data![0].id).isNotEmpty
|
||||
controller.lstFav
|
||||
.where(
|
||||
(
|
||||
element,
|
||||
) =>
|
||||
element.service_id ==
|
||||
snapshot.data![0].id,
|
||||
)
|
||||
.isNotEmpty
|
||||
? AppThemeData.primary300
|
||||
: (isDark ? Colors.white38 : Colors.black38),
|
||||
: (isDark
|
||||
? Colors.white38
|
||||
: Colors.black38),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
FutureBuilder<CategoryModel?>(
|
||||
future: controller.getCategory(snapshot.data![0].categoryId ?? ""),
|
||||
builder: (ctx, snap) {
|
||||
if (!snap.hasData) return const SizedBox();
|
||||
return Text(snap.data?.title ?? "", style: TextStyle(fontSize: 14, color: isDark ? Colors.white : Colors.black));
|
||||
FutureBuilder<
|
||||
CategoryModel?
|
||||
>(
|
||||
future: controller
|
||||
.getCategory(
|
||||
snapshot
|
||||
.data![0]
|
||||
.categoryId ??
|
||||
"",
|
||||
),
|
||||
builder: (
|
||||
ctx,
|
||||
snap,
|
||||
) {
|
||||
if (!snap.hasData)
|
||||
return const SizedBox();
|
||||
return Text(
|
||||
snap
|
||||
.data
|
||||
?.title ??
|
||||
"",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark
|
||||
? Colors
|
||||
.white
|
||||
: Colors
|
||||
.black,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildPrice(snapshot.data![0], isDark: isDark),
|
||||
_buildRating(snapshot.data![0]),
|
||||
_buildPrice(
|
||||
snapshot.data![0],
|
||||
isDark: isDark,
|
||||
),
|
||||
_buildRating(
|
||||
snapshot.data![0],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -272,20 +601,38 @@ class FavouriteOndemandScreen extends StatelessWidget {
|
||||
Widget _buildPrice(ProviderServiceModel provider, {bool isDark = false}) {
|
||||
if (provider.disPrice == "" || provider.disPrice == "0") {
|
||||
return Text(
|
||||
provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price) : '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}',
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300),
|
||||
provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(amount: provider.price)
|
||||
: '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isDark ? Colors.white : AppThemeData.primary300,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.disPrice ?? '0') : '${Constant.amountShow(amount: provider.disPrice)}/${'hr'.tr()}',
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300),
|
||||
provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(amount: provider.disPrice ?? '0')
|
||||
: '${Constant.amountShow(amount: provider.disPrice)}/${'hr'.tr()}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isDark ? Colors.white : AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price) : '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}',
|
||||
style: const TextStyle(fontSize: 12, color: Colors.grey, decoration: TextDecoration.lineThrough),
|
||||
provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(amount: provider.price)
|
||||
: '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}',
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -298,14 +645,24 @@ class FavouriteOndemandScreen extends StatelessWidget {
|
||||
rating = (provider.reviewsSum ?? 0) / (provider.reviewsCount ?? 1);
|
||||
}
|
||||
return Container(
|
||||
decoration: BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.circular(16)),
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.warning400,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.star, size: 16, color: Colors.white),
|
||||
const SizedBox(width: 3),
|
||||
Text(rating.toStringAsFixed(1), style: const TextStyle(letterSpacing: 0.5, fontSize: 12, color: Colors.white)),
|
||||
Text(
|
||||
rating.toStringAsFixed(1),
|
||||
style: const TextStyle(
|
||||
letterSpacing: 0.5,
|
||||
fontSize: 12,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import 'package:intl/intl.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/my_booking_on_demand_controller.dart';
|
||||
@@ -24,13 +24,24 @@ class MyBookingOnDemandScreen extends StatelessWidget {
|
||||
builder: (controller) {
|
||||
return DefaultTabController(
|
||||
length: controller.tabTitles.length,
|
||||
initialIndex: controller.tabTitles.indexOf(controller.selectedTab.value),
|
||||
initialIndex: controller.tabTitles.indexOf(
|
||||
controller.selectedTab.value,
|
||||
),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
backgroundColor: AppThemeData.primary300,
|
||||
centerTitle: false,
|
||||
title: Padding(padding: const EdgeInsets.only(bottom: 10), child: Text("Booking History".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900))),
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Text(
|
||||
"Booking History".tr(),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(48),
|
||||
child: TabBar(
|
||||
@@ -41,8 +52,15 @@ class MyBookingOnDemandScreen extends StatelessWidget {
|
||||
labelColor: AppThemeData.grey900,
|
||||
unselectedLabelColor: AppThemeData.grey900,
|
||||
labelStyle: AppThemeData.boldTextStyle(fontSize: 16),
|
||||
unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 16),
|
||||
tabs: controller.tabTitles.map((title) => Tab(child: Center(child: Text(title)))).toList(),
|
||||
unselectedLabelStyle: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
tabs:
|
||||
controller.tabTitles
|
||||
.map(
|
||||
(title) => Tab(child: Center(child: Text(title))),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -55,78 +73,217 @@ class MyBookingOnDemandScreen extends StatelessWidget {
|
||||
final orders = controller.getOrdersForTab(title);
|
||||
|
||||
if (orders.isEmpty) {
|
||||
return Center(child: Text("No ride found".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)));
|
||||
return Center(
|
||||
child: Text(
|
||||
"No ride found".tr(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: orders.length,
|
||||
itemBuilder: (context, index) {
|
||||
OnProviderOrderModel onProviderOrder = orders[index];
|
||||
WorkerModel? worker = controller.getWorker(onProviderOrder.workerId);
|
||||
OnProviderOrderModel onProviderOrder =
|
||||
orders[index];
|
||||
WorkerModel? worker = controller.getWorker(
|
||||
onProviderOrder.workerId,
|
||||
);
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => OnDemandOrderDetailsScreen(), arguments: onProviderOrder);
|
||||
Get.to(
|
||||
() => OnDemandOrderDetailsScreen(),
|
||||
arguments: onProviderOrder,
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 5,
|
||||
vertical: 5,
|
||||
),
|
||||
margin: const EdgeInsets.only(bottom: 15),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade100, width: 1),
|
||||
color: isDark ? AppThemeData.grey500 : Colors.white,
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey500
|
||||
: Colors.grey.shade100,
|
||||
width: 1,
|
||||
),
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey500
|
||||
: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: onProviderOrder.provider.photos.first,
|
||||
imageUrl:
|
||||
onProviderOrder
|
||||
.provider
|
||||
.photos
|
||||
.first,
|
||||
height: 80,
|
||||
width: 80,
|
||||
imageBuilder:
|
||||
(context, imageProvider) =>
|
||||
Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), image: DecorationImage(image: imageProvider, fit: BoxFit.cover))),
|
||||
placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))),
|
||||
(
|
||||
context,
|
||||
imageProvider,
|
||||
) => Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
10,
|
||||
),
|
||||
image: DecorationImage(
|
||||
image: imageProvider,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
placeholder:
|
||||
(context, url) => Center(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation(
|
||||
AppThemeData
|
||||
.primary300,
|
||||
),
|
||||
),
|
||||
),
|
||||
errorWidget:
|
||||
(context, url, error) => ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Image.network(Constant.placeHolderImage, fit: BoxFit.cover, cacheHeight: 80, cacheWidth: 80),
|
||||
(
|
||||
context,
|
||||
url,
|
||||
error,
|
||||
) => ClipRRect(
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
10,
|
||||
),
|
||||
child: Image.network(
|
||||
Constant
|
||||
.placeHolderImage,
|
||||
fit: BoxFit.cover,
|
||||
cacheHeight: 80,
|
||||
cacheWidth: 80,
|
||||
),
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||
decoration: BoxDecoration(color: AppThemeData.info50, border: Border.all(color: AppThemeData.info300), borderRadius: BorderRadius.circular(12)),
|
||||
child: Text(onProviderOrder.status, style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.info500)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 6),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
vertical: 6,
|
||||
horizontal: 12,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
AppThemeData.info50,
|
||||
border: Border.all(
|
||||
color:
|
||||
AppThemeData
|
||||
.info300,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
onProviderOrder.provider.title.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
onProviderOrder.status,
|
||||
style:
|
||||
AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
AppThemeData
|
||||
.info500,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(
|
||||
top: 6,
|
||||
),
|
||||
child: Text(
|
||||
onProviderOrder
|
||||
.provider
|
||||
.title
|
||||
.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData
|
||||
.greyDark900
|
||||
: AppThemeData
|
||||
.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(
|
||||
top: 6,
|
||||
),
|
||||
child: buildPriceText(
|
||||
onProviderOrder,
|
||||
),
|
||||
),
|
||||
Padding(padding: const EdgeInsets.only(top: 6), child: buildPriceText(onProviderOrder)),
|
||||
const SizedBox(height: 6),
|
||||
if (onProviderOrder.status != Constant.orderCompleted &&
|
||||
onProviderOrder.status != Constant.orderCancelled &&
|
||||
onProviderOrder.otp != null &&
|
||||
onProviderOrder.otp!.isNotEmpty)
|
||||
if (onProviderOrder
|
||||
.status !=
|
||||
Constant
|
||||
.orderCompleted &&
|
||||
onProviderOrder
|
||||
.status !=
|
||||
Constant
|
||||
.orderCancelled &&
|
||||
onProviderOrder.otp !=
|
||||
null &&
|
||||
onProviderOrder
|
||||
.otp!
|
||||
.isNotEmpty)
|
||||
Text(
|
||||
"${'OTP :'.tr()} ${onProviderOrder.otp}",
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData
|
||||
.greyDark900
|
||||
: AppThemeData
|
||||
.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -136,7 +293,12 @@ class MyBookingOnDemandScreen extends StatelessWidget {
|
||||
),
|
||||
|
||||
/// Bottom Details (Date, Provider, Worker)
|
||||
buildBottomDetails(context, onProviderOrder, isDark, worker),
|
||||
buildBottomDetails(
|
||||
context,
|
||||
onProviderOrder,
|
||||
isDark,
|
||||
worker,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -152,37 +314,81 @@ class MyBookingOnDemandScreen extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget buildPriceText(OnProviderOrderModel order) {
|
||||
final hasDiscount = order.provider.disPrice != "" && order.provider.disPrice != "0";
|
||||
final price = hasDiscount ? order.provider.disPrice.toString() : order.provider.price.toString();
|
||||
final hasDiscount =
|
||||
order.provider.disPrice != "" && order.provider.disPrice != "0";
|
||||
final price =
|
||||
hasDiscount
|
||||
? order.provider.disPrice.toString()
|
||||
: order.provider.price.toString();
|
||||
|
||||
return Text(
|
||||
order.provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: price) : "${Constant.amountShow(amount: price)}/${'hr'.tr()}",
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 16, color: AppThemeData.primary300),
|
||||
order.provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(amount: price)
|
||||
: "${Constant.amountShow(amount: price)}/${'hr'.tr()}",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color: AppThemeData.primary300,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildBottomDetails(BuildContext context, OnProviderOrderModel order, bool isDark, WorkerModel? worker) {
|
||||
Widget buildBottomDetails(
|
||||
BuildContext context,
|
||||
OnProviderOrderModel order,
|
||||
bool isDark,
|
||||
WorkerModel? worker,
|
||||
) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.grey400 : AppThemeData.grey100, width: 1),
|
||||
border: Border.all(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey100,
|
||||
width: 1,
|
||||
),
|
||||
color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
detailRow("Date & Time", DateFormat('dd-MMM-yyyy hh:mm a').format(order.scheduleDateTime!.toDate()), isDark),
|
||||
detailRow(
|
||||
"Date & Time",
|
||||
DateFormat(
|
||||
'dd-MMM-yyyy hh:mm a',
|
||||
).format(order.scheduleDateTime!.toDate()),
|
||||
isDark,
|
||||
),
|
||||
const Divider(thickness: 1),
|
||||
detailRow("Provider", order.provider.authorName.toString(), isDark),
|
||||
|
||||
if (order.provider.priceUnit == "Hourly") ...[
|
||||
if (order.startTime != null) ...[const Divider(thickness: 1), detailRow("Start Time", DateFormat('dd-MMM-yyyy hh:mm a').format(order.startTime!.toDate()), isDark)],
|
||||
if (order.endTime != null) ...[const Divider(thickness: 1), detailRow("End Time", DateFormat('dd-MMM-yyyy hh:mm a').format(order.endTime!.toDate()), isDark)],
|
||||
if (order.startTime != null) ...[
|
||||
const Divider(thickness: 1),
|
||||
detailRow(
|
||||
"Start Time",
|
||||
DateFormat(
|
||||
'dd-MMM-yyyy hh:mm a',
|
||||
).format(order.startTime!.toDate()),
|
||||
isDark,
|
||||
),
|
||||
],
|
||||
if (order.endTime != null) ...[
|
||||
const Divider(thickness: 1),
|
||||
detailRow(
|
||||
"End Time",
|
||||
DateFormat(
|
||||
'dd-MMM-yyyy hh:mm a',
|
||||
).format(order.endTime!.toDate()),
|
||||
isDark,
|
||||
),
|
||||
],
|
||||
],
|
||||
|
||||
if (worker != null) ...[const Divider(thickness: 1), detailRow("Worker", worker.fullName().toString(), isDark)],
|
||||
if (worker != null) ...[
|
||||
const Divider(thickness: 1),
|
||||
detailRow("Worker", worker.fullName().toString(), isDark),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -195,8 +401,20 @@ class MyBookingOnDemandScreen extends StatelessWidget {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(label.tr(), style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(value.tr(), style: AppThemeData.regularTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(
|
||||
label.tr(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
value.tr(),
|
||||
style: AppThemeData.regularTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/theme_controller.dart';
|
||||
import '../../controllers/on_demand_booking_controller.dart';
|
||||
@@ -42,12 +42,30 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 42,
|
||||
width: 42,
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50),
|
||||
child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: AppThemeData.grey900,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text("Book Service".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)),
|
||||
Text(
|
||||
"Book Service".tr(),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -58,13 +76,28 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Services Section
|
||||
Text("Services".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(
|
||||
"Services".tr(),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 18,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark400
|
||||
: AppThemeData.grey100,
|
||||
),
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Row(
|
||||
@@ -73,18 +106,60 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(controller.provider.value?.title ?? '', style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(
|
||||
controller.provider.value?.title ?? '',
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(controller.categoryTitle.value, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
if (controller.provider.value?.priceUnit == "Fixed") ...[
|
||||
Text(
|
||||
controller.categoryTitle.value,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
if (controller.provider.value?.priceUnit ==
|
||||
"Fixed") ...[
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
GestureDetector(onTap: controller.decrementQuantity, child: Icon(Icons.remove_circle_outline, color: AppThemeData.primary300, size: 30)),
|
||||
GestureDetector(
|
||||
onTap: controller.decrementQuantity,
|
||||
child: Icon(
|
||||
Icons.remove_circle_outline,
|
||||
color: AppThemeData.primary300,
|
||||
size: 30,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text('${controller.quantity.value}', style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(
|
||||
'${controller.quantity.value}',
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 18,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
GestureDetector(onTap: controller.incrementQuantity, child: Icon(Icons.add_circle_outline, color: AppThemeData.primary300, size: 30)),
|
||||
GestureDetector(
|
||||
onTap: controller.incrementQuantity,
|
||||
child: Icon(
|
||||
Icons.add_circle_outline,
|
||||
color: AppThemeData.primary300,
|
||||
size: 30,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -98,7 +173,15 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: Colors.grey.shade300,
|
||||
image: controller.provider.value!.photos.isNotEmpty ? DecorationImage(image: NetworkImage(controller.provider.value?.photos.first), fit: BoxFit.cover) : null,
|
||||
image:
|
||||
controller.provider.value!.photos.isNotEmpty
|
||||
? DecorationImage(
|
||||
image: NetworkImage(
|
||||
controller.provider.value?.photos.first,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -109,8 +192,14 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark400
|
||||
: AppThemeData.grey100,
|
||||
),
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
@@ -119,7 +208,16 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Address".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(
|
||||
"Address".tr(),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 18,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
@@ -127,20 +225,32 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
Get.to(AddressListScreen())!.then((value) {
|
||||
if (value != null) {
|
||||
ShippingAddress shippingAddress = value;
|
||||
if (Constant.checkZoneCheck(shippingAddress.location!.latitude ?? 0.0, shippingAddress.location!.longitude ?? 0.0)) {
|
||||
controller.selectedAddress.value = shippingAddress;
|
||||
if (Constant.checkZoneCheck(
|
||||
shippingAddress.location!.latitude ??
|
||||
0.0,
|
||||
shippingAddress.location!.longitude ??
|
||||
0.0,
|
||||
)) {
|
||||
controller.selectedAddress.value =
|
||||
shippingAddress;
|
||||
controller.calculatePrice();
|
||||
} else {
|
||||
ShowToastDialog.showToast("Service not available in this area".tr());
|
||||
ShowToastDialog.showToast(
|
||||
"Service not available in this area"
|
||||
.tr(),
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Constant.checkPermission(
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait...".tr());
|
||||
ShowToastDialog.showLoader(
|
||||
"Please wait...".tr(),
|
||||
);
|
||||
|
||||
ShippingAddress shippingAddress = ShippingAddress();
|
||||
ShippingAddress shippingAddress =
|
||||
ShippingAddress();
|
||||
|
||||
try {
|
||||
await Geolocator.requestPermission();
|
||||
@@ -148,43 +258,81 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
if (Constant.selectedMapType == 'osm') {
|
||||
final result = await Get.to(() => MapPickerPage());
|
||||
final result = await Get.to(
|
||||
() => MapPickerPage(),
|
||||
);
|
||||
if (result != null) {
|
||||
final firstPlace = result;
|
||||
final lat = firstPlace.coordinates.latitude;
|
||||
final lng = firstPlace.coordinates.longitude;
|
||||
final lat =
|
||||
firstPlace.coordinates.latitude;
|
||||
final lng =
|
||||
firstPlace
|
||||
.coordinates
|
||||
.longitude;
|
||||
final address = firstPlace.address;
|
||||
|
||||
shippingAddress.addressAs = "Home";
|
||||
shippingAddress.locality = address.toString();
|
||||
shippingAddress.location = UserLocation(latitude: lat, longitude: lng);
|
||||
shippingAddress.locality =
|
||||
address.toString();
|
||||
shippingAddress
|
||||
.location = UserLocation(
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
);
|
||||
|
||||
controller.selectedAddress.value = shippingAddress;
|
||||
controller.selectedAddress.value =
|
||||
shippingAddress;
|
||||
Get.back();
|
||||
}
|
||||
} else {
|
||||
Get.to(LocationPickerScreen())!.then((value) async {
|
||||
Get.to(LocationPickerScreen())!.then((
|
||||
value,
|
||||
) async {
|
||||
if (value != null) {
|
||||
SelectedLocationModel selectedLocationModel = value;
|
||||
SelectedLocationModel
|
||||
selectedLocationModel = value;
|
||||
|
||||
shippingAddress.addressAs = "Home";
|
||||
shippingAddress.location = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude);
|
||||
shippingAddress.locality = "Picked from Map";
|
||||
shippingAddress.addressAs =
|
||||
"Home";
|
||||
shippingAddress
|
||||
.location = UserLocation(
|
||||
latitude:
|
||||
selectedLocationModel
|
||||
.latLng!
|
||||
.latitude,
|
||||
longitude:
|
||||
selectedLocationModel
|
||||
.latLng!
|
||||
.longitude,
|
||||
);
|
||||
shippingAddress.locality =
|
||||
"Picked from Map";
|
||||
|
||||
controller.selectedAddress.value = shippingAddress;
|
||||
controller.selectedAddress.value =
|
||||
shippingAddress;
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
await placemarkFromCoordinates(19.228825, 72.854118).then((valuePlaceMaker) {
|
||||
Placemark placeMark = valuePlaceMaker[0];
|
||||
shippingAddress.location = UserLocation(latitude: 19.228825, longitude: 72.854118);
|
||||
await placemarkFromCoordinates(
|
||||
19.228825,
|
||||
72.854118,
|
||||
).then((valuePlaceMaker) {
|
||||
Placemark placeMark =
|
||||
valuePlaceMaker[0];
|
||||
shippingAddress
|
||||
.location = UserLocation(
|
||||
latitude: 19.228825,
|
||||
longitude: 72.854118,
|
||||
);
|
||||
String currentLocation =
|
||||
"${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}";
|
||||
shippingAddress.locality = currentLocation;
|
||||
shippingAddress.locality =
|
||||
currentLocation;
|
||||
});
|
||||
|
||||
controller.selectedAddress.value = shippingAddress;
|
||||
controller.selectedAddress.value =
|
||||
shippingAddress;
|
||||
ShowToastDialog.closeLoader();
|
||||
}
|
||||
},
|
||||
@@ -193,10 +341,17 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
controller.selectedAddress.value.getFullAddress(),
|
||||
controller.selectedAddress.value
|
||||
.getFullAddress(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -206,7 +361,12 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
TextFieldWidget(title: "Description".tr(), hintText: "Enter Description".tr(), controller: controller.descriptionController.value, maxLine: 5),
|
||||
TextFieldWidget(
|
||||
title: "Description".tr(),
|
||||
hintText: "Enter Description".tr(),
|
||||
controller: controller.descriptionController.value,
|
||||
maxLine: 5,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
@@ -220,13 +380,36 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
buttonSingleColor: AppThemeData.primary300,
|
||||
buttonPadding: 10,
|
||||
buttonWidth: 70,
|
||||
pickerTitle: Text("", style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
backgroundColor: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
pickerTextStyle: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
pickerTitle: Text(
|
||||
"",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
backgroundColor:
|
||||
isDark
|
||||
? AppThemeData.greyDark50
|
||||
: AppThemeData.grey50,
|
||||
pickerTextStyle: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
closeIconColor: isDark ? Colors.white : Colors.black,
|
||||
).show(context);
|
||||
},
|
||||
child: TextFieldWidget(title: "Booking Date & Slot".tr(), hintText: "Choose Date and Time".tr(), controller: controller.dateTimeController.value, enable: false),
|
||||
child: TextFieldWidget(
|
||||
title: "Booking Date & Slot".tr(),
|
||||
hintText: "Choose Date and Time".tr(),
|
||||
controller: controller.dateTimeController.value,
|
||||
enable: false,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
controller.provider.value?.priceUnit == "Fixed"
|
||||
@@ -241,7 +424,14 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
final coupon = controller.couponList[index];
|
||||
return GestureDetector(onTap: () => controller.applyCoupon(coupon), child: buildOfferItem(controller, index, isDark));
|
||||
return GestureDetector(
|
||||
onTap: () => controller.applyCoupon(coupon),
|
||||
child: buildOfferItem(
|
||||
controller,
|
||||
index,
|
||||
isDark,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
@@ -249,7 +439,16 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
buildPromoCode(controller, isDark),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text("Price Detail".tr(), style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
child: Text(
|
||||
"Price Detail".tr(),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
priceTotalRow(controller, isDark),
|
||||
],
|
||||
@@ -260,14 +459,23 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
),
|
||||
bottomNavigationBar: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: RoundedButtonFill(title: "Confirm".tr(), color: AppThemeData.primary300, textColor: AppThemeData.grey50, onPress: () => controller.confirmBooking(context)),
|
||||
child: RoundedButtonFill(
|
||||
title: "Confirm".tr(),
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () => controller.confirmBooking(context),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildOfferItem(OnDemandBookingController controller, int index, bool isDark) {
|
||||
Widget buildOfferItem(
|
||||
OnDemandBookingController controller,
|
||||
int index,
|
||||
bool isDark,
|
||||
) {
|
||||
return Obx(() {
|
||||
final coupon = controller.couponList[index];
|
||||
|
||||
@@ -275,7 +483,11 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
margin: const EdgeInsets.fromLTRB(7, 10, 7, 10),
|
||||
height: 85,
|
||||
child: DottedBorder(
|
||||
options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(10), color: AppThemeData.primary300),
|
||||
options: RoundedRectDottedBorderOptions(
|
||||
strokeWidth: 1,
|
||||
radius: const Radius.circular(10),
|
||||
color: AppThemeData.primary300,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(12, 5, 12, 0),
|
||||
child: Column(
|
||||
@@ -284,13 +496,26 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Image(image: AssetImage('assets/images/offer_icon.png'), height: 25, width: 25),
|
||||
const Image(
|
||||
image: AssetImage('assets/images/offer_icon.png'),
|
||||
height: 25,
|
||||
width: 25,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 3),
|
||||
child: Text(
|
||||
coupon.discountType == "Fix Price" ? "${Constant.amountShow(amount: coupon.discount.toString())} ${'OFF'.tr()}" : "${coupon.discount} ${'% Off'.tr()}",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, letterSpacing: 0.7, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
coupon.discountType == "Fix Price"
|
||||
? "${Constant.amountShow(amount: coupon.discount.toString())} ${'OFF'.tr()}"
|
||||
: "${coupon.discount} ${'% Off'.tr()}",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 0.7,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -299,11 +524,36 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(coupon.code ?? '', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.normal, letterSpacing: 0.5, color: Colors.orange)),
|
||||
Container(margin: const EdgeInsets.only(left: 15, right: 15, top: 3), width: 1, color: AppThemeData.grey50),
|
||||
Text(
|
||||
"valid till ".tr() + controller.getDate(coupon.expiresAt!.toDate().toString()),
|
||||
style: TextStyle(letterSpacing: 0.5, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
coupon.code ?? '',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.normal,
|
||||
letterSpacing: 0.5,
|
||||
color: Colors.orange,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(
|
||||
left: 15,
|
||||
right: 15,
|
||||
top: 3,
|
||||
),
|
||||
width: 1,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
Text(
|
||||
"valid till ".tr() +
|
||||
controller.getDate(
|
||||
coupon.expiresAt!.toDate().toString(),
|
||||
),
|
||||
style: TextStyle(
|
||||
letterSpacing: 0.5,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -321,7 +571,9 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
margin: const EdgeInsets.only(top: 10, bottom: 13),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100),
|
||||
border: Border.all(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100,
|
||||
),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
),
|
||||
child: Padding(
|
||||
@@ -332,17 +584,37 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset("assets/images/reedem.png", height: 50, width: 50),
|
||||
Image.asset(
|
||||
"assets/images/reedem.png",
|
||||
height: 50,
|
||||
width: 50,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Promo Code".tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), overflow: TextOverflow.ellipsis),
|
||||
Text(
|
||||
"Promo Code".tr(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 18,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
"Apply promo code".tr(),
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 15,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
@@ -353,7 +625,13 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
),
|
||||
FloatingActionButton(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(promoCodeSheet(controller, isDark), isScrollControlled: true, isDismissible: true, backgroundColor: Colors.transparent, enableDrag: true);
|
||||
Get.bottomSheet(
|
||||
promoCodeSheet(controller, isDark),
|
||||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
enableDrag: true,
|
||||
);
|
||||
},
|
||||
mini: true,
|
||||
backgroundColor: Colors.blueGrey.shade50,
|
||||
@@ -371,7 +649,10 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(bottom: Get.height / 4.3, left: 25, right: 25),
|
||||
height: Get.height * 0.88,
|
||||
decoration: BoxDecoration(color: Colors.transparent, border: Border.all(style: BorderStyle.none)),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.transparent,
|
||||
border: Border.all(style: BorderStyle.none),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
InkWell(
|
||||
@@ -379,14 +660,21 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 45,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100, width: 0.3),
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark400 : AppThemeData.grey100,
|
||||
width: 0.3,
|
||||
),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, // ✅ visible color
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900, // ✅ visible color
|
||||
size: 28,
|
||||
),
|
||||
),
|
||||
@@ -395,40 +683,93 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
const SizedBox(height: 25),
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(padding: const EdgeInsets.only(top: 30), child: const Image(image: AssetImage('assets/images/redeem_coupon.png'), width: 100)),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Text('Redeem Your Coupons'.tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 16)),
|
||||
),
|
||||
Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(top: 10, left: 22, right: 22),
|
||||
child: Text("Voucher or Coupon code".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
padding: const EdgeInsets.only(top: 30),
|
||||
child: const Image(
|
||||
image: AssetImage('assets/images/redeem_coupon.png'),
|
||||
width: 100,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 20, right: 20, top: 20),
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Text(
|
||||
'Redeem Your Coupons'.tr(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
left: 22,
|
||||
right: 22,
|
||||
),
|
||||
child: Text(
|
||||
"Voucher or Coupon code".tr(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 20,
|
||||
right: 20,
|
||||
top: 20,
|
||||
),
|
||||
child: DottedBorder(
|
||||
options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(12), color: AppThemeData.primary300),
|
||||
options: RoundedRectDottedBorderOptions(
|
||||
strokeWidth: 1,
|
||||
radius: const Radius.circular(12),
|
||||
color: AppThemeData.primary300,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(12),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark50
|
||||
: AppThemeData.grey50,
|
||||
alignment: Alignment.center,
|
||||
child: TextFormField(
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
controller: controller.couponTextController.value,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: "Write Coupon Code".tr(),
|
||||
hintStyle: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
hintStyle: AppThemeData.mediumTextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark400
|
||||
: AppThemeData.grey400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -436,21 +777,34 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 30, bottom: 30, left: 15, right: 15),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 30,
|
||||
bottom: 30,
|
||||
left: 15,
|
||||
right: 15,
|
||||
),
|
||||
child: RoundedButtonFill(
|
||||
title: "REDEEM NOW".tr(),
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () {
|
||||
final inputCode = controller.couponTextController.value.text.trim().toLowerCase();
|
||||
final inputCode =
|
||||
controller.couponTextController.value.text
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
final matchingCoupon = controller.couponList.firstWhereOrNull((c) => c.code?.toLowerCase() == inputCode);
|
||||
final matchingCoupon = controller.couponList
|
||||
.firstWhereOrNull(
|
||||
(c) => c.code?.toLowerCase() == inputCode,
|
||||
);
|
||||
|
||||
if (matchingCoupon != null) {
|
||||
controller.applyCoupon(matchingCoupon);
|
||||
Get.back();
|
||||
} else {
|
||||
ShowToastDialog.showToast("Applied coupon not valid.".tr());
|
||||
ShowToastDialog.showToast(
|
||||
"Applied coupon not valid.".tr(),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -470,14 +824,22 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100),
|
||||
border: Border.all(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey100,
|
||||
),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 5),
|
||||
rowText("Price".tr(), Constant.amountShow(amount: controller.price.value.toString()), isDark),
|
||||
controller.discountAmount.value != 0 ? const Divider() : const SizedBox(),
|
||||
rowText(
|
||||
"Price".tr(),
|
||||
Constant.amountShow(amount: controller.price.value.toString()),
|
||||
isDark,
|
||||
),
|
||||
controller.discountAmount.value != 0
|
||||
? const Divider()
|
||||
: const SizedBox(),
|
||||
controller.discountAmount.value != 0
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
@@ -490,19 +852,39 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
"${"Discount".tr()} ${controller.discountType.value == 'Percentage' || controller.discountType.value == 'Percent' ? "(${controller.discountLabel.value}%)" : "(${Constant.amountShow(amount: controller.discountLabel.value)})"}",
|
||||
style: TextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.offerCode.value,
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(controller.offerCode.value, style: TextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("(-${Constant.amountShow(amount: controller.discountAmount.value.toString())})", style: const TextStyle(color: Colors.red)),
|
||||
Text(
|
||||
"(-${Constant.amountShow(amount: controller.discountAmount.value.toString())})",
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: const SizedBox(),
|
||||
const Divider(),
|
||||
rowText("SubTotal".tr(), Constant.amountShow(amount: controller.subTotal.value.toString()), isDark),
|
||||
rowText(
|
||||
"SubTotal".tr(),
|
||||
Constant.amountShow(amount: controller.subTotal.value.toString()),
|
||||
isDark,
|
||||
),
|
||||
const Divider(),
|
||||
ListView.builder(
|
||||
itemCount: Constant.taxList.length,
|
||||
@@ -513,19 +895,39 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 10,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${taxModel.title} (${taxModel.type == "fix" ? Constant.amountShow(amount: taxModel.tax) : "${taxModel.tax}%"})",
|
||||
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: Constant.getTaxValue(amount: controller.subTotal.value.toString(), taxModel: taxModel).toString()),
|
||||
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
Constant.amountShow(
|
||||
amount:
|
||||
Constant.getTaxValue(
|
||||
amount:
|
||||
controller.subTotal.value.toString(),
|
||||
taxModel: taxModel,
|
||||
).toString(),
|
||||
),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -535,7 +937,13 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
rowText("Total Amount".tr(), Constant.amountShow(amount: controller.totalAmount.value.toString()), isDark),
|
||||
rowText(
|
||||
"Total Amount".tr(),
|
||||
Constant.amountShow(
|
||||
amount: controller.totalAmount.value.toString(),
|
||||
),
|
||||
isDark,
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
],
|
||||
),
|
||||
@@ -549,8 +957,18 @@ class OnDemandBookingScreen extends StatelessWidget {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(title.tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(value.tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(
|
||||
title.tr(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
value.tr(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:customer/screen_ui/on_demand_service/view_category_service_screen.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/on_demand_category_controller.dart';
|
||||
import '../../controllers/theme_controller.dart';
|
||||
@@ -33,8 +33,20 @@ class OnDemandCategoryScreen extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 42,
|
||||
width: 42,
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50),
|
||||
child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: AppThemeData.grey900,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
@@ -42,12 +54,22 @@ class OnDemandCategoryScreen extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Explore services".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)),
|
||||
Text(
|
||||
"Explore services tailored for you—quick, easy, and personalized.".tr(),
|
||||
"Explore services".tr(),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Explore services tailored for you—quick, easy, and personalized."
|
||||
.tr(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey900),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -60,7 +82,10 @@ class OnDemandCategoryScreen extends StatelessWidget {
|
||||
controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 20,
|
||||
horizontal: 15,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -71,9 +96,17 @@ class OnDemandCategoryScreen extends StatelessWidget {
|
||||
itemCount: controller.categories.length,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return categoriesCell(context, controller.categories[index], index, isDark);
|
||||
return categoriesCell(
|
||||
context,
|
||||
controller.categories[index],
|
||||
index,
|
||||
isDark,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
@@ -85,16 +118,42 @@ class OnDemandCategoryScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget categoriesCell(BuildContext context, CategoryModel category, int index, bool isDark) {
|
||||
Widget categoriesCell(
|
||||
BuildContext context,
|
||||
CategoryModel category,
|
||||
int index,
|
||||
bool isDark,
|
||||
) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(() => ViewCategoryServiceListScreen(), arguments: {'categoryId': category.id, 'categoryTitle': category.title});
|
||||
Get.to(
|
||||
() => ViewCategoryServiceListScreen(),
|
||||
arguments: {
|
||||
'categoryId': category.id,
|
||||
'categoryTitle': category.title,
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
ClipRRect(borderRadius: BorderRadius.circular(12), child: CachedNetworkImage(imageUrl: category.image ?? "", height: 60, width: 60, fit: BoxFit.cover)),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: category.image ?? "",
|
||||
height: 60,
|
||||
width: 60,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(category.title ?? "", style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), textAlign: TextAlign.center),
|
||||
Text(
|
||||
category.title ?? "",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 12,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -5,8 +5,7 @@ import 'package:customer/themes/app_them_data.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../controllers/on_demand_dashboard_controller.dart';
|
||||
|
||||
class OnDemandDashboardScreen extends StatelessWidget {
|
||||
@@ -27,12 +26,19 @@ class OnDemandDashboardScreen extends StatelessWidget {
|
||||
showUnselectedLabels: true,
|
||||
showSelectedLabels: true,
|
||||
selectedFontSize: 12,
|
||||
selectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold),
|
||||
unselectedLabelStyle: const TextStyle(fontFamily: AppThemeData.bold),
|
||||
selectedLabelStyle: const TextStyle(
|
||||
fontFamily: AppThemeData.bold,
|
||||
),
|
||||
unselectedLabelStyle: const TextStyle(
|
||||
fontFamily: AppThemeData.bold,
|
||||
),
|
||||
currentIndex: controller.selectedIndex.value,
|
||||
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
selectedItemColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
unselectedItemColor: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
backgroundColor:
|
||||
isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
selectedItemColor:
|
||||
isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
unselectedItemColor:
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
onTap: (int index) {
|
||||
if (index == 0) {
|
||||
Get.put(CabDashboardController());
|
||||
@@ -42,18 +48,72 @@ class OnDemandDashboardScreen extends StatelessWidget {
|
||||
items:
|
||||
Constant.walletSetting == false
|
||||
? [
|
||||
navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home_cab.svg", label: 'Home'.tr(), controller: controller),
|
||||
navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_fav.svg", label: 'Favourites'.tr(), controller: controller),
|
||||
navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_booking_cab.svg", label: 'My Bookings'.tr(), controller: controller),
|
||||
navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller),
|
||||
navigationBarItem(
|
||||
isDark,
|
||||
index: 0,
|
||||
assetIcon: "assets/icons/ic_home_cab.svg",
|
||||
label: 'Home'.tr(),
|
||||
controller: controller,
|
||||
),
|
||||
navigationBarItem(
|
||||
isDark,
|
||||
index: 1,
|
||||
assetIcon: "assets/icons/ic_fav.svg",
|
||||
label: 'Favourites'.tr(),
|
||||
controller: controller,
|
||||
),
|
||||
navigationBarItem(
|
||||
isDark,
|
||||
index: 2,
|
||||
assetIcon: "assets/icons/ic_booking_cab.svg",
|
||||
label: 'My Bookings'.tr(),
|
||||
controller: controller,
|
||||
),
|
||||
navigationBarItem(
|
||||
isDark,
|
||||
index: 3,
|
||||
assetIcon: "assets/icons/ic_profile.svg",
|
||||
label: 'Profile'.tr(),
|
||||
controller: controller,
|
||||
),
|
||||
]
|
||||
: [
|
||||
navigationBarItem(isDark, index: 0, assetIcon: "assets/icons/ic_home_cab.svg", label: 'Home'.tr(), controller: controller),
|
||||
navigationBarItem(isDark, index: 1, assetIcon: "assets/icons/ic_fav.svg", label: 'Favourites'.tr(), controller: controller),
|
||||
navigationBarItem(
|
||||
isDark,
|
||||
index: 0,
|
||||
assetIcon: "assets/icons/ic_home_cab.svg",
|
||||
label: 'Home'.tr(),
|
||||
controller: controller,
|
||||
),
|
||||
navigationBarItem(
|
||||
isDark,
|
||||
index: 1,
|
||||
assetIcon: "assets/icons/ic_fav.svg",
|
||||
label: 'Favourites'.tr(),
|
||||
controller: controller,
|
||||
),
|
||||
|
||||
navigationBarItem(isDark, index: 2, assetIcon: "assets/icons/ic_booking_cab.svg", label: 'My Bookings'.tr(), controller: controller),
|
||||
navigationBarItem(isDark, index: 3, assetIcon: "assets/icons/ic_wallet_cab.svg", label: 'Wallet'.tr(), controller: controller),
|
||||
navigationBarItem(isDark, index: 4, assetIcon: "assets/icons/ic_profile.svg", label: 'Profile'.tr(), controller: controller),
|
||||
navigationBarItem(
|
||||
isDark,
|
||||
index: 2,
|
||||
assetIcon: "assets/icons/ic_booking_cab.svg",
|
||||
label: 'My Bookings'.tr(),
|
||||
controller: controller,
|
||||
),
|
||||
navigationBarItem(
|
||||
isDark,
|
||||
index: 3,
|
||||
assetIcon: "assets/icons/ic_wallet_cab.svg",
|
||||
label: 'Wallet'.tr(),
|
||||
controller: controller,
|
||||
),
|
||||
navigationBarItem(
|
||||
isDark,
|
||||
index: 4,
|
||||
assetIcon: "assets/icons/ic_profile.svg",
|
||||
label: 'Profile'.tr(),
|
||||
controller: controller,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -62,7 +122,13 @@ class OnDemandDashboardScreen extends StatelessWidget {
|
||||
});
|
||||
}
|
||||
|
||||
BottomNavigationBarItem navigationBarItem(isDark, {required int index, required String label, required String assetIcon, required OnDemandDashboardController controller}) {
|
||||
BottomNavigationBarItem navigationBarItem(
|
||||
isDark, {
|
||||
required int index,
|
||||
required String label,
|
||||
required String assetIcon,
|
||||
required OnDemandDashboardController controller,
|
||||
}) {
|
||||
return BottomNavigationBarItem(
|
||||
icon: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:customer/screen_ui/on_demand_service/provider_screen.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import 'package:intl/intl.dart';
|
||||
import '../../controllers/theme_controller.dart';
|
||||
import '../../models/provider_serivce_model.dart';
|
||||
@@ -25,7 +25,13 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
init: OnDemandDetailsController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
body: buildSliverScrollView(context, controller, controller.provider, controller.userModel, isDark),
|
||||
body: buildSliverScrollView(
|
||||
context,
|
||||
controller,
|
||||
controller.provider,
|
||||
controller.userModel,
|
||||
isDark,
|
||||
),
|
||||
bottomNavigationBar:
|
||||
controller.isOpen.value == false
|
||||
? SizedBox()
|
||||
@@ -43,9 +49,20 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
if (Constant.userModel == null) {
|
||||
Get.offAll(const LoginScreen());
|
||||
} else {
|
||||
print("providerModel ::::::::${controller.provider.title ?? 'No provider'}");
|
||||
print("categoryTitle ::::::: ${controller.categoryTitle.value}");
|
||||
Get.to(() => OnDemandBookingScreen(), arguments: {'providerModel': controller.provider, 'categoryTitle': controller.categoryTitle.value});
|
||||
print(
|
||||
"providerModel ::::::::${controller.provider.title ?? 'No provider'}",
|
||||
);
|
||||
print(
|
||||
"categoryTitle ::::::: ${controller.categoryTitle.value}",
|
||||
);
|
||||
Get.to(
|
||||
() => OnDemandBookingScreen(),
|
||||
arguments: {
|
||||
'providerModel': controller.provider,
|
||||
'categoryTitle':
|
||||
controller.categoryTitle.value,
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -57,7 +74,13 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
SingleChildScrollView buildSliverScrollView(BuildContext context, OnDemandDetailsController controller, ProviderServiceModel provider, user, isDark) {
|
||||
SingleChildScrollView buildSliverScrollView(
|
||||
BuildContext context,
|
||||
OnDemandDetailsController controller,
|
||||
ProviderServiceModel provider,
|
||||
user,
|
||||
isDark,
|
||||
) {
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
final height = MediaQuery.of(context).size.height;
|
||||
|
||||
@@ -68,21 +91,54 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
Stack(
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
imageUrl: provider.photos.isNotEmpty ? provider.photos.first : "",
|
||||
placeholder: (context, url) => Center(child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))),
|
||||
errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.fitWidth),
|
||||
imageUrl:
|
||||
provider.photos.isNotEmpty ? provider.photos.first : "",
|
||||
placeholder:
|
||||
(context, url) => Center(
|
||||
child: CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation(
|
||||
AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
),
|
||||
errorWidget:
|
||||
(context, url, error) => Image.network(
|
||||
Constant.placeHolderImage,
|
||||
fit: BoxFit.fitWidth,
|
||||
),
|
||||
fit: BoxFit.fitWidth,
|
||||
width: width,
|
||||
height: height * 0.45,
|
||||
),
|
||||
Positioned(top: height * 0.05, left: width * 0.03, child: _circleButton(context, icon: Icons.arrow_back, onTap: () => Get.back())),
|
||||
Positioned(
|
||||
top: height * 0.05,
|
||||
left: width * 0.03,
|
||||
child: _circleButton(
|
||||
context,
|
||||
icon: Icons.arrow_back,
|
||||
onTap: () => Get.back(),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: height * 0.05,
|
||||
right: width * 0.03,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(40), color: controller.isOpen.value ? Colors.green : Colors.red),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Text(controller.isOpen.value ? "Open".tr() : "Close".tr(), style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 14)),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
color: controller.isOpen.value ? Colors.green : Colors.red,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
child: Text(
|
||||
controller.isOpen.value ? "Open".tr() : "Close".tr(),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -105,27 +161,66 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Text(
|
||||
provider.title.toString(),
|
||||
style: TextStyle(fontSize: 20, fontFamily: AppThemeData.regular, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black),
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
provider.disPrice == "" || provider.disPrice == "0"
|
||||
? Text(
|
||||
provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price ?? '0') : '${Constant.amountShow(amount: provider.price ?? '0')}/${'hr'.tr()}',
|
||||
style: TextStyle(fontSize: 18, fontFamily: AppThemeData.regular, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300),
|
||||
provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(
|
||||
amount: provider.price ?? '0',
|
||||
)
|
||||
: '${Constant.amountShow(amount: provider.price ?? '0')}/${'hr'.tr()}',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.bold,
|
||||
color:
|
||||
isDark
|
||||
? Colors.white
|
||||
: AppThemeData.primary300,
|
||||
),
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Text(
|
||||
provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.disPrice ?? '0') : '${Constant.amountShow(amount: provider.disPrice ?? '0')}/${'hr'.tr()}',
|
||||
style: TextStyle(fontSize: 18, fontFamily: AppThemeData.regular, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300),
|
||||
provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(
|
||||
amount: provider.disPrice ?? '0',
|
||||
)
|
||||
: '${Constant.amountShow(amount: provider.disPrice ?? '0')}/${'hr'.tr()}',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.bold,
|
||||
color:
|
||||
isDark
|
||||
? Colors.white
|
||||
: AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price ?? '0') : '${Constant.amountShow(amount: provider.price ?? '0')}/${'hr'.tr()}',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.grey, decoration: TextDecoration.lineThrough),
|
||||
provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(
|
||||
amount: provider.price ?? '0',
|
||||
)
|
||||
: '${Constant.amountShow(amount: provider.price ?? '0')}/${'hr'.tr()}',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
color: Colors.grey,
|
||||
decoration:
|
||||
TextDecoration.lineThrough,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -139,23 +234,51 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
child: Text(categoryTitle, style: TextStyle(fontSize: 14, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400, color: isDark ? Colors.white : Colors.black)),
|
||||
child: Text(
|
||||
categoryTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.star, size: 16, color: AppThemeData.warning400),
|
||||
const Icon(
|
||||
Icons.star,
|
||||
size: 16,
|
||||
color: AppThemeData.warning400,
|
||||
),
|
||||
const SizedBox(width: 3),
|
||||
Text(
|
||||
provider.reviewsCount != 0 ? ((provider.reviewsSum ?? 0.0) / (provider.reviewsCount ?? 0.0)).toStringAsFixed(1) : '0',
|
||||
style: const TextStyle(letterSpacing: 0.5, fontSize: 16, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: AppThemeData.warning400),
|
||||
provider.reviewsCount != 0
|
||||
? ((provider.reviewsSum ?? 0.0) /
|
||||
(provider.reviewsCount ?? 0.0))
|
||||
.toStringAsFixed(1)
|
||||
: '0',
|
||||
style: const TextStyle(
|
||||
letterSpacing: 0.5,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppThemeData.warning400,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
"(${provider.reviewsCount} ${'Reviews'.tr()})",
|
||||
style: TextStyle(letterSpacing: 0.5, fontSize: 16, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: isDark ? Colors.white : Colors.black),
|
||||
style: TextStyle(
|
||||
letterSpacing: 0.5,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -168,18 +291,40 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
children: [
|
||||
subCategoryTitle.isNotEmpty
|
||||
? Container(
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: AppThemeData.primary300.withOpacity(0.20)),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: AppThemeData.primary300.withOpacity(
|
||||
0.20,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Text(subCategoryTitle, style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, fontFamily: AppThemeData.regular, color: AppThemeData.primary300)),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
child: Text(
|
||||
subCategoryTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
const SizedBox(width: 10),
|
||||
Container(
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.green.withOpacity(0.20)),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: Colors.green.withOpacity(0.20),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
@@ -188,10 +333,22 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
context: context,
|
||||
backgroundColor: Colors.transparent,
|
||||
enableDrag: true,
|
||||
builder: (context) => showTiming(context, controller, isDark),
|
||||
builder:
|
||||
(context) => showTiming(
|
||||
context,
|
||||
controller,
|
||||
isDark,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text("View Timing".tr(), style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.green, letterSpacing: 0.5)),
|
||||
child: Text(
|
||||
"View Timing".tr(),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.green,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -201,14 +358,22 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Icons.location_on_outlined, color: isDark ? Colors.white : Colors.black, size: 20),
|
||||
Icon(
|
||||
Icons.location_on_outlined,
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Expanded(
|
||||
child: Text(
|
||||
provider.address.toString(),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontFamily: AppThemeData.regular, fontWeight: FontWeight.w400, color: isDark ? Colors.white : Colors.black),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -219,7 +384,11 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
_tabBar(controller),
|
||||
Obx(() {
|
||||
if (controller.tabString.value == "About") {
|
||||
return aboutTabViewWidget(controller, controller.provider, isDark);
|
||||
return aboutTabViewWidget(
|
||||
controller,
|
||||
controller.provider,
|
||||
isDark,
|
||||
);
|
||||
} else if (controller.tabString.value == "Gallery") {
|
||||
return galleryTabViewWidget(controller);
|
||||
} else {
|
||||
@@ -237,14 +406,35 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _circleButton(BuildContext context, {required IconData icon, required VoidCallback onTap}) {
|
||||
Widget _circleButton(
|
||||
BuildContext context, {
|
||||
required IconData icon,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return ClipOval(
|
||||
child: Container(color: Colors.black.withOpacity(0.7), child: InkWell(onTap: onTap, child: Padding(padding: const EdgeInsets.all(8.0), child: Icon(icon, size: 30, color: Colors.white)))),
|
||||
child: Container(
|
||||
color: Colors.black.withOpacity(0.7),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Icon(icon, size: 30, color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _tabBar(OnDemandDetailsController controller) {
|
||||
return Obx(() => Row(children: [_tabItem("About", controller), _tabItem("Gallery", controller), _tabItem("Review", controller)]));
|
||||
return Obx(
|
||||
() => Row(
|
||||
children: [
|
||||
_tabItem("About", controller),
|
||||
_tabItem("Gallery", controller),
|
||||
_tabItem("Review", controller),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _tabItem(String title, OnDemandDetailsController controller) {
|
||||
@@ -253,33 +443,67 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(right: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
decoration: BoxDecoration(color: controller.tabString.value == title ? AppThemeData.primary300 : Colors.grey.shade200, borderRadius: BorderRadius.circular(10)),
|
||||
child: Text(title.tr(), style: TextStyle(fontWeight: FontWeight.bold, color: controller.tabString.value == title ? Colors.white : Colors.black)),
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
controller.tabString.value == title
|
||||
? AppThemeData.primary300
|
||||
: Colors.grey.shade200,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Text(
|
||||
title.tr(),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color:
|
||||
controller.tabString.value == title
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget aboutTabViewWidget(OnDemandDetailsController controller, ProviderServiceModel providerModel, bool isDark) {
|
||||
Widget aboutTabViewWidget(
|
||||
OnDemandDetailsController controller,
|
||||
ProviderServiceModel providerModel,
|
||||
bool isDark,
|
||||
) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text((providerModel.description ?? '').tr(), style: TextStyle(color: isDark ? Colors.white : Colors.black, fontSize: 14, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500)),
|
||||
Text(
|
||||
(providerModel.description ?? '').tr(),
|
||||
style: TextStyle(
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Obx(() {
|
||||
final user = controller.userModel.value;
|
||||
if (user == null) return const SizedBox();
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => ProviderScreen(), arguments: {'providerId': user.id});
|
||||
Get.to(
|
||||
() => ProviderScreen(),
|
||||
arguments: {'providerId': user.id},
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade100, width: 1),
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark ? AppThemeData.grey500 : Colors.grey.shade100,
|
||||
width: 1,
|
||||
),
|
||||
color: isDark ? AppThemeData.grey500 : Colors.white,
|
||||
),
|
||||
child: Padding(
|
||||
@@ -289,30 +513,86 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
CircleAvatar(radius: 30, backgroundImage: NetworkImage(user.profilePictureURL?.isNotEmpty == true ? user.profilePictureURL! : Constant.placeHolderImage)),
|
||||
CircleAvatar(
|
||||
radius: 30,
|
||||
backgroundImage: NetworkImage(
|
||||
user.profilePictureURL?.isNotEmpty == true
|
||||
? user.profilePictureURL!
|
||||
: Constant.placeHolderImage,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(user.fullName(), style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14, fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
user.fullName(),
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(user.email ?? '', style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14)),
|
||||
Text(
|
||||
user.email ?? '',
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// Rating Box
|
||||
Container(
|
||||
decoration: BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.circular(16)),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.warning400,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.star, size: 16, color: Colors.white),
|
||||
const Icon(
|
||||
Icons.star,
|
||||
size: 16,
|
||||
color: Colors.white,
|
||||
),
|
||||
const SizedBox(width: 3),
|
||||
Text(
|
||||
double.parse(user.reviewsCount.toString()) != 0
|
||||
? (double.parse(user.reviewsSum.toString()) / double.parse(user.reviewsCount.toString())).toStringAsFixed(1)
|
||||
double.parse(
|
||||
user.reviewsCount
|
||||
.toString(),
|
||||
) !=
|
||||
0
|
||||
? (double.parse(
|
||||
user.reviewsSum
|
||||
.toString(),
|
||||
) /
|
||||
double.parse(
|
||||
user.reviewsCount
|
||||
.toString(),
|
||||
))
|
||||
.toStringAsFixed(1)
|
||||
: '0',
|
||||
style: const TextStyle(letterSpacing: 0.5, fontSize: 12, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: Colors.white),
|
||||
style: const TextStyle(
|
||||
letterSpacing: 0.5,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -348,7 +628,12 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, mainAxisSpacing: 0, crossAxisSpacing: 8, mainAxisExtent: 180),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 0,
|
||||
crossAxisSpacing: 8,
|
||||
mainAxisExtent: 180,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
final imageUrl = photos[index];
|
||||
return Padding(
|
||||
@@ -359,9 +644,29 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
imageUrl: imageUrl,
|
||||
height: 60,
|
||||
width: 60,
|
||||
imageBuilder: (context, imageProvider) => Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), image: DecorationImage(image: imageProvider, fit: BoxFit.cover))),
|
||||
placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))),
|
||||
errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover),
|
||||
imageBuilder:
|
||||
(context, imageProvider) => Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
image: DecorationImage(
|
||||
image: imageProvider,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
placeholder:
|
||||
(context, url) => Center(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
valueColor: AlwaysStoppedAnimation(
|
||||
AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
),
|
||||
errorWidget:
|
||||
(context, url, error) => Image.network(
|
||||
Constant.placeHolderImage,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
@@ -370,11 +675,24 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget reviewTabViewWidget(OnDemandDetailsController controller, bool isDark) {
|
||||
Widget reviewTabViewWidget(
|
||||
OnDemandDetailsController controller,
|
||||
bool isDark,
|
||||
) {
|
||||
final reviews = controller.ratingService;
|
||||
|
||||
if (reviews.isEmpty) {
|
||||
return SizedBox(height: 200, child: Center(child: Text("No review Found".tr(), style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))));
|
||||
return SizedBox(
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: Text(
|
||||
"No review Found".tr(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
@@ -390,8 +708,17 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
shadows: const [BoxShadow(color: Color(0x0A000000), blurRadius: 32, offset: Offset(0, 0), spreadRadius: 0)],
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
shadows: const [
|
||||
BoxShadow(
|
||||
color: Color(0x0A000000),
|
||||
blurRadius: 32,
|
||||
offset: Offset(0, 0),
|
||||
spreadRadius: 0,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
@@ -401,26 +728,58 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(review.uname ?? '', style: TextStyle(fontSize: 16, letterSpacing: 1, fontWeight: FontWeight.w600, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(
|
||||
review.createdAt != null ? DateFormat('dd MMM').format(review.createdAt!.toDate()) : '',
|
||||
style: TextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
review.uname ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
letterSpacing: 1,
|
||||
fontWeight: FontWeight.w600,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
review.createdAt != null
|
||||
? DateFormat(
|
||||
'dd MMM',
|
||||
).format(review.createdAt!.toDate())
|
||||
: '',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
RatingBar.builder(
|
||||
initialRating: double.tryParse(review.rating.toString()) ?? 0,
|
||||
initialRating:
|
||||
double.tryParse(review.rating.toString()) ?? 0,
|
||||
direction: Axis.horizontal,
|
||||
itemSize: 20,
|
||||
ignoreGestures: true,
|
||||
itemPadding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
itemBuilder: (context, _) => Icon(Icons.star, color: AppThemeData.primary300),
|
||||
itemBuilder:
|
||||
(context, _) =>
|
||||
Icon(Icons.star, color: AppThemeData.primary300),
|
||||
onRatingUpdate: (rate) {},
|
||||
),
|
||||
const Divider(),
|
||||
const SizedBox(height: 5),
|
||||
Text(review.comment ?? '', style: TextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(
|
||||
review.comment ?? '',
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -430,31 +789,71 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget showTiming(BuildContext context, OnDemandDetailsController controller, bool isDark) {
|
||||
Widget showTiming(
|
||||
BuildContext context,
|
||||
OnDemandDetailsController controller,
|
||||
bool isDark,
|
||||
) {
|
||||
final provider = controller.provider;
|
||||
return Container(
|
||||
decoration: BoxDecoration(color: isDark ? AppThemeData.grey300 : Colors.white, borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))),
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.grey300 : Colors.white,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||
child: Text("Service Timing".tr(), style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, fontFamily: AppThemeData.regular, color: AppThemeData.primary300)),
|
||||
child: Text(
|
||||
"Service Timing".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: _timeCard(context, "Start Time : ".tr(), provider.startTime.toString(), isDark)),
|
||||
Expanded(
|
||||
child: _timeCard(
|
||||
context,
|
||||
"Start Time : ".tr(),
|
||||
provider.startTime.toString(),
|
||||
isDark,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: _timeCard(context, "End Time : ".tr(), provider.endTime.toString(), isDark)),
|
||||
Expanded(
|
||||
child: _timeCard(
|
||||
context,
|
||||
"End Time : ".tr(),
|
||||
provider.endTime.toString(),
|
||||
isDark,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||
child: Text("Service Days".tr(), style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, fontFamily: AppThemeData.regular, color: AppThemeData.primary300)),
|
||||
child: Text(
|
||||
"Service Days".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
@@ -466,10 +865,30 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
.map(
|
||||
(day) => Card(
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6), side: BorderSide(color: isDark ? const Color(0XFF3c3a2e) : const Color(0XFFC3C5D1), width: 1)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
side: BorderSide(
|
||||
color:
|
||||
isDark
|
||||
? const Color(0XFF3c3a2e)
|
||||
: const Color(0XFFC3C5D1),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 20),
|
||||
child: Text(day, style: TextStyle(color: isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D))),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 7,
|
||||
horizontal: 20,
|
||||
),
|
||||
child: Text(
|
||||
day,
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? const Color(0XFFa5a292)
|
||||
: const Color(0XFF5A5D6D),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -482,16 +901,39 @@ class OnDemandDetailsScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _timeCard(BuildContext context, String title, String value, bool isDark) {
|
||||
Widget _timeCard(
|
||||
BuildContext context,
|
||||
String title,
|
||||
String value,
|
||||
bool isDark,
|
||||
) {
|
||||
return Card(
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6), side: BorderSide(color: isDark ? const Color(0XFF3c3a2e) : const Color(0XFFC3C5D1), width: 1)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
side: BorderSide(
|
||||
color: isDark ? const Color(0XFF3c3a2e) : const Color(0XFFC3C5D1),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 20),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(title, style: TextStyle(color: isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D))),
|
||||
Text(value, style: TextStyle(color: isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D))),
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark ? const Color(0XFFa5a292) : const Color(0XFF5A5D6D),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -20,7 +20,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../controllers/on_demand_home_controller.dart';
|
||||
import '../../models/category_model.dart';
|
||||
import '../../models/provider_serivce_model.dart';
|
||||
@@ -51,8 +51,20 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 42,
|
||||
width: 42,
|
||||
decoration: const BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50),
|
||||
child: const Center(child: Padding(padding: EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))),
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
child: const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 5),
|
||||
child: Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: AppThemeData.grey900,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
@@ -61,8 +73,23 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Constant.userModel == null
|
||||
? InkWell(onTap: () => Get.offAll(const LoginScreen()), child: Text("Login".tr(), style: AppThemeData.boldTextStyle(color: AppThemeData.grey900, fontSize: 12)))
|
||||
: Text(Constant.userModel!.fullName(), style: AppThemeData.boldTextStyle(color: AppThemeData.grey900, fontSize: 12)),
|
||||
? InkWell(
|
||||
onTap: () => Get.offAll(const LoginScreen()),
|
||||
child: Text(
|
||||
"Login".tr(),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
color: AppThemeData.grey900,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
Constant.userModel!.fullName(),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
color: AppThemeData.grey900,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
if (Constant.userModel != null) {
|
||||
@@ -76,10 +103,13 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
} else {
|
||||
Constant.checkPermission(
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait...".tr());
|
||||
ShowToastDialog.showLoader(
|
||||
"Please wait...".tr(),
|
||||
);
|
||||
|
||||
// ✅ declare it once here!
|
||||
ShippingAddress shippingAddress = ShippingAddress();
|
||||
ShippingAddress shippingAddress =
|
||||
ShippingAddress();
|
||||
|
||||
try {
|
||||
await Geolocator.requestPermission();
|
||||
@@ -87,41 +117,72 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
if (Constant.selectedMapType == 'osm') {
|
||||
final result = await Get.to(() => MapPickerPage());
|
||||
final result = await Get.to(
|
||||
() => MapPickerPage(),
|
||||
);
|
||||
if (result != null) {
|
||||
final firstPlace = result;
|
||||
final lat = firstPlace.coordinates.latitude;
|
||||
final lng = firstPlace.coordinates.longitude;
|
||||
final lat =
|
||||
firstPlace.coordinates.latitude;
|
||||
final lng =
|
||||
firstPlace.coordinates.longitude;
|
||||
final address = firstPlace.address;
|
||||
|
||||
shippingAddress.addressAs = "Home";
|
||||
shippingAddress.locality = address.toString();
|
||||
shippingAddress.location = UserLocation(latitude: lat, longitude: lng);
|
||||
Constant.selectedLocation = shippingAddress;
|
||||
shippingAddress.locality =
|
||||
address.toString();
|
||||
shippingAddress.location = UserLocation(
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
);
|
||||
Constant.selectedLocation =
|
||||
shippingAddress;
|
||||
controller.getData();
|
||||
Get.back();
|
||||
}
|
||||
} else {
|
||||
Get.to(LocationPickerScreen())!.then((value) async {
|
||||
Get.to(LocationPickerScreen())!.then((
|
||||
value,
|
||||
) async {
|
||||
if (value != null) {
|
||||
SelectedLocationModel selectedLocationModel = value;
|
||||
SelectedLocationModel
|
||||
selectedLocationModel = value;
|
||||
|
||||
shippingAddress.addressAs = "Home";
|
||||
shippingAddress.location = UserLocation(latitude: selectedLocationModel.latLng!.latitude, longitude: selectedLocationModel.latLng!.longitude);
|
||||
shippingAddress.locality = "Picked from Map"; // You can reverse-geocode
|
||||
shippingAddress
|
||||
.location = UserLocation(
|
||||
latitude:
|
||||
selectedLocationModel
|
||||
.latLng!
|
||||
.latitude,
|
||||
longitude:
|
||||
selectedLocationModel
|
||||
.latLng!
|
||||
.longitude,
|
||||
);
|
||||
shippingAddress.locality =
|
||||
"Picked from Map"; // You can reverse-geocode
|
||||
|
||||
Constant.selectedLocation = shippingAddress;
|
||||
Constant.selectedLocation =
|
||||
shippingAddress;
|
||||
controller.getData();
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
await placemarkFromCoordinates(19.228825, 72.854118).then((valuePlaceMaker) {
|
||||
await placemarkFromCoordinates(
|
||||
19.228825,
|
||||
72.854118,
|
||||
).then((valuePlaceMaker) {
|
||||
Placemark placeMark = valuePlaceMaker[0];
|
||||
shippingAddress.location = UserLocation(latitude: 19.228825, longitude: 72.854118);
|
||||
shippingAddress.location = UserLocation(
|
||||
latitude: 19.228825,
|
||||
longitude: 72.854118,
|
||||
);
|
||||
String currentLocation =
|
||||
"${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}";
|
||||
shippingAddress.locality = currentLocation;
|
||||
shippingAddress.locality =
|
||||
currentLocation;
|
||||
});
|
||||
|
||||
Constant.selectedLocation = shippingAddress;
|
||||
@@ -139,10 +200,21 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: Constant.selectedLocation.getFullAddress(),
|
||||
style: TextStyle(fontFamily: AppThemeData.medium, overflow: TextOverflow.ellipsis, color: AppThemeData.grey900, fontSize: 14),
|
||||
text:
|
||||
Constant.selectedLocation
|
||||
.getFullAddress(),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: AppThemeData.grey900,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
WidgetSpan(
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_down.svg",
|
||||
),
|
||||
),
|
||||
WidgetSpan(child: SvgPicture.asset("assets/icons/ic_down.svg")),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -157,7 +229,8 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
body:
|
||||
controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Constant.isZoneAvailable == false || controller.providerList.isEmpty
|
||||
: Constant.isZoneAvailable == false ||
|
||||
controller.providerList.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
@@ -166,12 +239,30 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
children: [
|
||||
Image.asset("assets/images/location.gif", height: 120),
|
||||
const SizedBox(height: 12),
|
||||
Text("No Store Found in Your Area".tr(), style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold)),
|
||||
Text(
|
||||
"No Store Found in Your Area".tr(),
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey100
|
||||
: AppThemeData.grey800,
|
||||
fontSize: 22,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
"Currently, there are no available store in your zone. Try changing your location to find nearby options.".tr(),
|
||||
"Currently, there are no available store in your zone. Try changing your location to find nearby options."
|
||||
.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold),
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey50
|
||||
: AppThemeData.grey500,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
RoundedButtonFill(
|
||||
@@ -188,7 +279,10 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 20,
|
||||
horizontal: 15,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -199,42 +293,95 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
height: MediaQuery.of(context).size.height * 0.12,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark600 : AppThemeData.greyDark600, width: 1),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark600
|
||||
: AppThemeData.greyDark600,
|
||||
width: 1,
|
||||
),
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark50
|
||||
: AppThemeData.grey50,
|
||||
),
|
||||
child:
|
||||
controller.categories.isEmpty
|
||||
? Constant.showEmptyView(message: "No Categories".tr())
|
||||
? Constant.showEmptyView(
|
||||
message: "No Categories".tr(),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: controller.categories.length > 3 ? 3 : controller.categories.length,
|
||||
itemCount:
|
||||
controller.categories.length >
|
||||
3
|
||||
? 3
|
||||
: controller
|
||||
.categories
|
||||
.length,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
final category = controller.categories[index];
|
||||
final category =
|
||||
controller
|
||||
.categories[index];
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => ViewCategoryServiceListScreen(), arguments: {'categoryId': category.id, 'categoryTitle': category.title});
|
||||
Get.to(
|
||||
() =>
|
||||
ViewCategoryServiceListScreen(),
|
||||
arguments: {
|
||||
'categoryId':
|
||||
category.id,
|
||||
'categoryTitle':
|
||||
category.title,
|
||||
},
|
||||
);
|
||||
},
|
||||
child: CategoryView(category: category, index: index, isDark: isDark),
|
||||
child: CategoryView(
|
||||
category: category,
|
||||
index: index,
|
||||
isDark: isDark,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
if (controller.categories.length > 3)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => const OnDemandCategoryScreen());
|
||||
Get.to(
|
||||
() =>
|
||||
const OnDemandCategoryScreen(),
|
||||
);
|
||||
},
|
||||
child: ClipOval(child: Container(width: 50, height: 50, color: AppThemeData.grey200, child: const Center(child: Icon(Icons.chevron_right)))),
|
||||
child: ClipOval(
|
||||
child: Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
color:
|
||||
AppThemeData
|
||||
.grey200,
|
||||
child: const Center(
|
||||
child: Icon(
|
||||
Icons.chevron_right,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
SizedBox(
|
||||
@@ -242,9 +389,17 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
child: Center(
|
||||
child: Text(
|
||||
"View All".tr(),
|
||||
textAlign: TextAlign.center,
|
||||
textAlign:
|
||||
TextAlign.center,
|
||||
maxLines: 1,
|
||||
style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData
|
||||
.greyDark900
|
||||
: AppThemeData
|
||||
.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -262,14 +417,28 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Most Popular services".tr(),
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black, fontSize: 18, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w600),
|
||||
style: TextStyle(
|
||||
color:
|
||||
isDark ? Colors.white : Colors.black,
|
||||
fontSize: 18,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => ViewAllPopularServiceScreen());
|
||||
},
|
||||
child: Text("View all".tr(), style: TextStyle(color: AppThemeData.primary300, fontSize: 14, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w600)),
|
||||
child: Text(
|
||||
"View all".tr(),
|
||||
style: TextStyle(
|
||||
color: AppThemeData.primary300,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -280,9 +449,16 @@ class OnDemandHomeScreen extends StatelessWidget {
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: controller.providerList.length >= 6 ? 6 : controller.providerList.length,
|
||||
itemCount:
|
||||
controller.providerList.length >= 6
|
||||
? 6
|
||||
: controller.providerList.length,
|
||||
itemBuilder: (_, index) {
|
||||
return ServiceView(provider: controller.providerList[index], controller: controller, isDark: isDark);
|
||||
return ServiceView(
|
||||
provider: controller.providerList[index],
|
||||
controller: controller,
|
||||
isDark: isDark,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
@@ -334,7 +510,13 @@ class BannerView extends StatelessWidget {
|
||||
final banner = bannerList[index];
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
child: SizedBox(width: MediaQuery.of(context).size.width * 0.8, child: NetworkImageWidget(imageUrl: banner.photo ?? '', fit: BoxFit.cover)),
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.8,
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: banner.photo ?? '',
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -344,7 +526,18 @@ class BannerView extends StatelessWidget {
|
||||
return Row(
|
||||
children: List.generate(bannerList.length, (index) {
|
||||
bool isSelected = currentPage.value == index;
|
||||
return Expanded(child: Container(height: 4, decoration: BoxDecoration(color: isSelected ? AppThemeData.grey300 : AppThemeData.grey100, borderRadius: BorderRadius.circular(5))));
|
||||
return Expanded(
|
||||
child: Container(
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
isSelected
|
||||
? AppThemeData.grey300
|
||||
: AppThemeData.grey100,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}),
|
||||
@@ -358,7 +551,12 @@ class CategoryView extends StatelessWidget {
|
||||
final int index;
|
||||
final bool isDark;
|
||||
|
||||
const CategoryView({super.key, required this.category, required this.index, required this.isDark});
|
||||
const CategoryView({
|
||||
super.key,
|
||||
required this.category,
|
||||
required this.index,
|
||||
required this.isDark,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -370,11 +568,21 @@ class CategoryView extends StatelessWidget {
|
||||
Container(
|
||||
height: 55,
|
||||
width: 55,
|
||||
decoration: BoxDecoration(color: Constant.colorList[index % Constant.colorList.length], borderRadius: BorderRadius.circular(50)),
|
||||
decoration: BoxDecoration(
|
||||
color: Constant.colorList[index % Constant.colorList.length],
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
child: ClipOval(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(14.0),
|
||||
child: CachedNetworkImage(imageUrl: category.image.toString(), errorWidget: (_, __, ___) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover)),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: category.image.toString(),
|
||||
errorWidget:
|
||||
(_, __, ___) => Image.network(
|
||||
Constant.placeHolderImage,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -382,7 +590,15 @@ class CategoryView extends StatelessWidget {
|
||||
SizedBox(
|
||||
width: 70,
|
||||
child: Center(
|
||||
child: Text(category.title ?? "", textAlign: TextAlign.center, maxLines: 1, style: AppThemeData.semiBoldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
child: Text(
|
||||
category.title ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 1,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -396,40 +612,70 @@ class ServiceView extends StatelessWidget {
|
||||
final bool isDark;
|
||||
final OnDemandHomeController? controller;
|
||||
|
||||
const ServiceView({super.key, required this.provider, this.isDark = false, this.controller});
|
||||
const ServiceView({
|
||||
super.key,
|
||||
required this.provider,
|
||||
this.isDark = false,
|
||||
this.controller,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(() => OnDemandDetailsScreen(), arguments: {'providerModel': provider});
|
||||
Get.to(
|
||||
() => OnDemandDetailsScreen(),
|
||||
arguments: {'providerModel': provider},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: isDark ? AppThemeData.grey500 : Colors.grey.shade200),
|
||||
border: Border.all(
|
||||
color: isDark ? AppThemeData.grey500 : Colors.grey.shade200,
|
||||
),
|
||||
color: isDark ? AppThemeData.grey900 : Colors.white,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// --- Left Image ---
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(10),
|
||||
bottomLeft: Radius.circular(10),
|
||||
),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: provider.photos.isNotEmpty ? provider.photos[0] : Constant.placeHolderImage,
|
||||
imageUrl:
|
||||
provider.photos.isNotEmpty
|
||||
? provider.photos[0]
|
||||
: Constant.placeHolderImage,
|
||||
width: 110,
|
||||
height: MediaQuery.of(context).size.height * 0.16,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (context, url) => Center(child: CircularProgressIndicator.adaptive(valueColor: AlwaysStoppedAnimation(AppThemeData.primary300))),
|
||||
errorWidget: (context, url, error) => Image.network(Constant.placeHolderImage, fit: BoxFit.cover),
|
||||
placeholder:
|
||||
(context, url) => Center(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
valueColor: AlwaysStoppedAnimation(
|
||||
AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
),
|
||||
errorWidget:
|
||||
(context, url, error) => Image.network(
|
||||
Constant.placeHolderImage,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// --- Right Content ---
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 10,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -442,17 +688,40 @@ class ServiceView extends StatelessWidget {
|
||||
provider.title ?? "",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (controller != null)
|
||||
Obx(
|
||||
() => GestureDetector(
|
||||
onTap: () => controller!.toggleFavourite(provider),
|
||||
onTap:
|
||||
() => controller!.toggleFavourite(provider),
|
||||
child: Icon(
|
||||
controller!.lstFav.where((element) => element.service_id == provider.id).isNotEmpty ? Icons.favorite : Icons.favorite_border,
|
||||
controller!.lstFav
|
||||
.where(
|
||||
(element) =>
|
||||
element.service_id == provider.id,
|
||||
)
|
||||
.isNotEmpty
|
||||
? Icons.favorite
|
||||
: Icons.favorite_border,
|
||||
size: 24,
|
||||
color: controller!.lstFav.where((element) => element.service_id == provider.id).isNotEmpty ? AppThemeData.primary300 : (isDark ? Colors.white38 : Colors.black38),
|
||||
color:
|
||||
controller!.lstFav
|
||||
.where(
|
||||
(element) =>
|
||||
element.service_id ==
|
||||
provider.id,
|
||||
)
|
||||
.isNotEmpty
|
||||
? AppThemeData.primary300
|
||||
: (isDark
|
||||
? Colors.white38
|
||||
: Colors.black38),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -464,10 +733,18 @@ class ServiceView extends StatelessWidget {
|
||||
// Category
|
||||
if (controller != null)
|
||||
FutureBuilder<CategoryModel?>(
|
||||
future: controller!.getCategory(provider.categoryId ?? ""),
|
||||
future: controller!.getCategory(
|
||||
provider.categoryId ?? "",
|
||||
),
|
||||
builder: (ctx, snap) {
|
||||
if (!snap.hasData) return const SizedBox.shrink();
|
||||
return Text(snap.data?.title ?? "", style: TextStyle(fontSize: 13, color: isDark ? Colors.white70 : Colors.black54));
|
||||
return Text(
|
||||
snap.data?.title ?? "",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: isDark ? Colors.white70 : Colors.black54,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -493,21 +770,39 @@ class ServiceView extends StatelessWidget {
|
||||
Widget _buildPrice() {
|
||||
if (provider.disPrice == "" || provider.disPrice == "0") {
|
||||
return Text(
|
||||
provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price) : '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}',
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300),
|
||||
provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(amount: provider.price)
|
||||
: '${Constant.amountShow(amount: provider.price ?? "0")}/${'hr'.tr()}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isDark ? Colors.white : AppThemeData.primary300,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.disPrice ?? '0') : '${Constant.amountShow(amount: provider.disPrice)}/${'hr'.tr()}',
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isDark ? Colors.white : AppThemeData.primary300),
|
||||
provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(amount: provider.disPrice ?? '0')
|
||||
: '${Constant.amountShow(amount: provider.disPrice)}/${'hr'.tr()}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isDark ? Colors.white : AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Flexible(
|
||||
child: Text(
|
||||
provider.priceUnit == 'Fixed' ? Constant.amountShow(amount: provider.price) : '${Constant.amountShow(amount: provider.price ?? "0")}/hr',
|
||||
style: const TextStyle(fontSize: 12, color: Colors.grey, decoration: TextDecoration.lineThrough),
|
||||
provider.priceUnit == 'Fixed'
|
||||
? Constant.amountShow(amount: provider.price)
|
||||
: '${Constant.amountShow(amount: provider.price ?? "0")}/hr',
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
@@ -522,11 +817,21 @@ class ServiceView extends StatelessWidget {
|
||||
rating = (provider.reviewsSum ?? 0) / (provider.reviewsCount ?? 1);
|
||||
}
|
||||
return Container(
|
||||
decoration: BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.circular(12)),
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.warning400,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [const Icon(Icons.star, size: 14, color: Colors.white), const SizedBox(width: 3), Text(rating.toStringAsFixed(1), style: const TextStyle(fontSize: 12, color: Colors.white))],
|
||||
children: [
|
||||
const Icon(Icons.star, size: 14, color: Colors.white),
|
||||
const SizedBox(width: 3),
|
||||
Text(
|
||||
rating.toStringAsFixed(1),
|
||||
style: const TextStyle(fontSize: 12, color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
import 'package:customer/constant/constant.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../controllers/0n_demand_payment_controller.dart';
|
||||
import '../../controllers/theme_controller.dart';
|
||||
import '../../payment/createRazorPayOrderModel.dart';
|
||||
@@ -35,12 +35,30 @@ class OnDemandPaymentScreen extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 42,
|
||||
width: 42,
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50),
|
||||
child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: AppThemeData.grey900,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text("Select Payment Method".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)),
|
||||
Text(
|
||||
"Select Payment Method".tr(),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -49,45 +67,106 @@ class OnDemandPaymentScreen extends StatelessWidget {
|
||||
controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||||
decoration: BoxDecoration(color: isDark ? AppThemeData.greyDark200 : Colors.white),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 20,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.greyDark200 : Colors.white,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Preferred Payment".tr(), textAlign: TextAlign.start, style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)),
|
||||
Text(
|
||||
"Preferred Payment".tr(),
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 15,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark500
|
||||
: AppThemeData.grey500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true)
|
||||
if (controller.walletSettingModel.value.isEnabled ==
|
||||
true ||
|
||||
controller
|
||||
.cashOnDeliverySettingModel
|
||||
.value
|
||||
.isEnabled ==
|
||||
true)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark50
|
||||
: AppThemeData.grey50,
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark200
|
||||
: AppThemeData.grey200,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Visibility(
|
||||
visible: controller.walletSettingModel.value.isEnabled == true,
|
||||
child: cardDecoration(controller, PaymentGateway.wallet, isDark, "assets/images/ic_wallet.png"),
|
||||
visible:
|
||||
controller
|
||||
.walletSettingModel
|
||||
.value
|
||||
.isEnabled ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.wallet,
|
||||
isDark,
|
||||
"assets/images/ic_wallet.png",
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.cashOnDeliverySettingModel.value.isEnabled == true,
|
||||
child: cardDecoration(controller, PaymentGateway.cod, isDark, "assets/images/ic_cash.png"),
|
||||
visible:
|
||||
controller
|
||||
.cashOnDeliverySettingModel
|
||||
.value
|
||||
.isEnabled ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.cod,
|
||||
isDark,
|
||||
"assets/images/ic_cash.png",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (controller.walletSettingModel.value.isEnabled == true || controller.cashOnDeliverySettingModel.value.isEnabled == true)
|
||||
if (controller.walletSettingModel.value.isEnabled ==
|
||||
true ||
|
||||
controller
|
||||
.cashOnDeliverySettingModel
|
||||
.value
|
||||
.isEnabled ==
|
||||
true)
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Other Payment Options".tr(),
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(fontSize: 15, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 15,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark500
|
||||
: AppThemeData.grey500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
@@ -95,38 +174,155 @@ class OnDemandPaymentScreen extends StatelessWidget {
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark50
|
||||
: AppThemeData.grey50,
|
||||
border: Border.all(
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark200
|
||||
: AppThemeData.grey200,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Visibility(visible: controller.stripeModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png")),
|
||||
Visibility(visible: controller.payPalModel.value.isEnabled == true, child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png")),
|
||||
Visibility(
|
||||
visible: controller.payStackModel.value.isEnable == true,
|
||||
child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png"),
|
||||
visible:
|
||||
controller
|
||||
.stripeModel
|
||||
.value
|
||||
.isEnabled ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.stripe,
|
||||
isDark,
|
||||
"assets/images/stripe.png",
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.mercadoPagoModel.value.isEnabled == true,
|
||||
child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"),
|
||||
visible:
|
||||
controller
|
||||
.payPalModel
|
||||
.value
|
||||
.isEnabled ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.paypal,
|
||||
isDark,
|
||||
"assets/images/paypal.png",
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.flutterWaveModel.value.isEnable == true,
|
||||
child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"),
|
||||
visible:
|
||||
controller
|
||||
.payStackModel
|
||||
.value
|
||||
.isEnable ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.payStack,
|
||||
isDark,
|
||||
"assets/images/paystack.png",
|
||||
),
|
||||
),
|
||||
Visibility(visible: controller.payFastModel.value.isEnable == true, child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png")),
|
||||
Visibility(
|
||||
visible: controller.razorPayModel.value.isEnabled == true,
|
||||
child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png"),
|
||||
visible:
|
||||
controller
|
||||
.mercadoPagoModel
|
||||
.value
|
||||
.isEnabled ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.mercadoPago,
|
||||
isDark,
|
||||
"assets/images/mercado-pago.png",
|
||||
),
|
||||
),
|
||||
Visibility(visible: controller.midTransModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png")),
|
||||
Visibility(
|
||||
visible: controller.orangeMoneyModel.value.enable == true,
|
||||
child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png"),
|
||||
visible:
|
||||
controller
|
||||
.flutterWaveModel
|
||||
.value
|
||||
.isEnable ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.flutterWave,
|
||||
isDark,
|
||||
"assets/images/flutterwave_logo.png",
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible:
|
||||
controller
|
||||
.payFastModel
|
||||
.value
|
||||
.isEnable ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.payFast,
|
||||
isDark,
|
||||
"assets/images/payfast.png",
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible:
|
||||
controller
|
||||
.razorPayModel
|
||||
.value
|
||||
.isEnabled ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.razorpay,
|
||||
isDark,
|
||||
"assets/images/razorpay.png",
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible:
|
||||
controller.midTransModel.value.enable ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.midTrans,
|
||||
isDark,
|
||||
"assets/images/midtrans.png",
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible:
|
||||
controller
|
||||
.orangeMoneyModel
|
||||
.value
|
||||
.enable ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.orangeMoney,
|
||||
isDark,
|
||||
"assets/images/orange_money.png",
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible:
|
||||
controller.xenditModel.value.enable ==
|
||||
true,
|
||||
child: cardDecoration(
|
||||
controller,
|
||||
PaymentGateway.xendit,
|
||||
isDark,
|
||||
"assets/images/xendit.png",
|
||||
),
|
||||
),
|
||||
Visibility(visible: controller.xenditModel.value.enable == true, child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png")),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -137,55 +333,151 @@ class OnDemandPaymentScreen extends StatelessWidget {
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey900,
|
||||
onPress: () async {
|
||||
print("getTotalAmount :::::::: ${"${controller.totalAmount.value}"}");
|
||||
print(
|
||||
"getTotalAmount :::::::: ${"${controller.totalAmount.value}"}",
|
||||
);
|
||||
if (controller.isOrderPlaced.value == false) {
|
||||
controller.isOrderPlaced.value = true;
|
||||
if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) {
|
||||
controller.stripeMakePayment(amount: "${controller.totalAmount.value}");
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) {
|
||||
controller.paypalPaymentSheet("${controller.totalAmount.value}", context);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) {
|
||||
controller.payStackPayment("${controller.totalAmount.value}");
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) {
|
||||
controller.mercadoPagoMakePayment(context: context, amount: "${controller.totalAmount.value}");
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) {
|
||||
controller.flutterWaveInitiatePayment(context: context, amount: "${controller.totalAmount.value}");
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) {
|
||||
controller.payFastPayment(context: context, amount: "${controller.totalAmount.value}");
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) {
|
||||
double totalAmount = double.parse("${controller.totalAmount.value}");
|
||||
double walletAmount = double.tryParse(Constant.userModel?.walletAmount?.toString() ?? "0") ?? 0;
|
||||
if (controller.selectedPaymentMethod.value ==
|
||||
PaymentGateway.stripe.name) {
|
||||
controller.stripeMakePayment(
|
||||
amount: "${controller.totalAmount.value}",
|
||||
);
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.paypal.name) {
|
||||
controller.paypalPaymentSheet(
|
||||
"${controller.totalAmount.value}",
|
||||
context,
|
||||
);
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.payStack.name) {
|
||||
controller.payStackPayment(
|
||||
"${controller.totalAmount.value}",
|
||||
);
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.mercadoPago.name) {
|
||||
controller.mercadoPagoMakePayment(
|
||||
context: context,
|
||||
amount: "${controller.totalAmount.value}",
|
||||
);
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.flutterWave.name) {
|
||||
controller.flutterWaveInitiatePayment(
|
||||
context: context,
|
||||
amount: "${controller.totalAmount.value}",
|
||||
);
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.payFast.name) {
|
||||
controller.payFastPayment(
|
||||
context: context,
|
||||
amount: "${controller.totalAmount.value}",
|
||||
);
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.wallet.name) {
|
||||
double totalAmount = double.parse(
|
||||
"${controller.totalAmount.value}",
|
||||
);
|
||||
double walletAmount =
|
||||
double.tryParse(
|
||||
Constant.userModel?.walletAmount
|
||||
?.toString() ??
|
||||
"0",
|
||||
) ??
|
||||
0;
|
||||
|
||||
if (walletAmount == 0) {
|
||||
ShowToastDialog.showToast("Wallet balance is 0. Please recharge wallet.".tr());
|
||||
ShowToastDialog.showToast(
|
||||
"Wallet balance is 0. Please recharge wallet."
|
||||
.tr(),
|
||||
);
|
||||
} else if (walletAmount < totalAmount) {
|
||||
ShowToastDialog.showToast("Insufficient wallet balance. Please add funds.".tr());
|
||||
ShowToastDialog.showToast(
|
||||
"Insufficient wallet balance. Please add funds."
|
||||
.tr(),
|
||||
);
|
||||
} else {
|
||||
controller.placeOrder();
|
||||
}
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.cod.name) {
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.cod.name) {
|
||||
controller.placeOrder();
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.wallet.name) {
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.wallet.name) {
|
||||
controller.placeOrder();
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) {
|
||||
controller.midtransMakePayment(context: context, amount: "${controller.totalAmount.value}");
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) {
|
||||
controller.orangeMakePayment(context: context, amount: "${controller.totalAmount.value}");
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) {
|
||||
controller.xenditPayment(context, "${controller.totalAmount.value}");
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) {
|
||||
RazorPayController().createOrderRazorPay(amount: double.parse("${controller.totalAmount.value}"), razorpayModel: controller.razorPayModel.value).then((value) {
|
||||
if (value == null) {
|
||||
Get.back();
|
||||
ShowToastDialog.showToast("Something went wrong, please contact admin.".tr());
|
||||
} else {
|
||||
CreateRazorPayOrderModel result = value;
|
||||
controller.openCheckout(amount: "${controller.totalAmount.value}", orderId: result.id);
|
||||
}
|
||||
});
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.midTrans.name) {
|
||||
controller.midtransMakePayment(
|
||||
context: context,
|
||||
amount: "${controller.totalAmount.value}",
|
||||
);
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.orangeMoney.name) {
|
||||
controller.orangeMakePayment(
|
||||
context: context,
|
||||
amount: "${controller.totalAmount.value}",
|
||||
);
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.xendit.name) {
|
||||
controller.xenditPayment(
|
||||
context,
|
||||
"${controller.totalAmount.value}",
|
||||
);
|
||||
} else if (controller
|
||||
.selectedPaymentMethod
|
||||
.value ==
|
||||
PaymentGateway.razorpay.name) {
|
||||
RazorPayController()
|
||||
.createOrderRazorPay(
|
||||
amount: double.parse(
|
||||
"${controller.totalAmount.value}",
|
||||
),
|
||||
razorpayModel:
|
||||
controller.razorPayModel.value,
|
||||
)
|
||||
.then((value) {
|
||||
if (value == null) {
|
||||
Get.back();
|
||||
ShowToastDialog.showToast(
|
||||
"Something went wrong, please contact admin."
|
||||
.tr(),
|
||||
);
|
||||
} else {
|
||||
CreateRazorPayOrderModel result =
|
||||
value;
|
||||
controller.openCheckout(
|
||||
amount:
|
||||
"${controller.totalAmount.value}",
|
||||
orderId: result.id,
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
controller.isOrderPlaced.value = false;
|
||||
ShowToastDialog.showToast("Please select payment method".tr());
|
||||
ShowToastDialog.showToast(
|
||||
"Please select payment method".tr(),
|
||||
);
|
||||
}
|
||||
controller.isOrderPlaced.value = false;
|
||||
}
|
||||
@@ -215,8 +507,21 @@ class OnDemandPaymentScreen extends StatelessWidget {
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: ShapeDecoration(shape: RoundedRectangleBorder(side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)), borderRadius: BorderRadius.circular(8))),
|
||||
child: Padding(padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0), child: Image.asset(image)),
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: const BorderSide(
|
||||
width: 1,
|
||||
color: Color(0xFFE5E7EB),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(
|
||||
value.name == "payFast" ? 0 : 8.0,
|
||||
),
|
||||
child: Image.asset(image),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
value.name == "wallet"
|
||||
@@ -227,12 +532,30 @@ class OnDemandPaymentScreen extends StatelessWidget {
|
||||
Text(
|
||||
value.name.capitalizeString(),
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey50
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: Constant.userModel?.walletAmount == null ? '0.0' : Constant.userModel?.walletAmount.toString()),
|
||||
Constant.amountShow(
|
||||
amount:
|
||||
Constant.userModel?.walletAmount == null
|
||||
? '0.0'
|
||||
: Constant.userModel?.walletAmount
|
||||
.toString(),
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.primary300
|
||||
: AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -241,14 +564,23 @@ class OnDemandPaymentScreen extends StatelessWidget {
|
||||
child: Text(
|
||||
value.name.capitalizeString(),
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey50
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Expanded(child: SizedBox()),
|
||||
Radio(
|
||||
value: value.name,
|
||||
groupValue: controller.selectedPaymentMethod.value,
|
||||
activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
activeColor:
|
||||
isDark
|
||||
? AppThemeData.primary300
|
||||
: AppThemeData.primary300,
|
||||
onChanged: (value) {
|
||||
controller.selectedPaymentMethod.value = value.toString();
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/on_demand_review_controller.dart';
|
||||
import '../../controllers/theme_controller.dart';
|
||||
@@ -34,61 +34,139 @@ class OnDemandReviewScreen extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 42,
|
||||
width: 42,
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50),
|
||||
child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: AppThemeData.grey900,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(controller.ratingModel.value != null ? "Update Review".tr() : "Add Review".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)),
|
||||
Text(
|
||||
controller.ratingModel.value != null
|
||||
? "Update Review".tr()
|
||||
: "Add Review".tr(),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Obx(
|
||||
() =>
|
||||
(controller.reviewFor.value == "Worker" && controller.workerModel.value == null) || (controller.reviewFor.value == "Provider" && controller.provider.value == null)
|
||||
(controller.reviewFor.value == "Worker" &&
|
||||
controller.workerModel.value == null) ||
|
||||
(controller.reviewFor.value == "Provider" &&
|
||||
controller.provider.value == null)
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 50.0),
|
||||
child: Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 20, right: 20, top: 42, bottom: 20),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 20,
|
||||
right: 20,
|
||||
top: 42,
|
||||
bottom: 20,
|
||||
),
|
||||
child: Card(
|
||||
elevation: 2,
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark50
|
||||
: AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 65),
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Rate for'.tr(), style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(
|
||||
controller.reviewFor.value == "Provider" ? controller.order.value!.provider.authorName ?? "" : controller.workerModel.value!.fullName(),
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
'Rate for'.tr(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 18,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.reviewFor.value == "Provider"
|
||||
? controller
|
||||
.order
|
||||
.value!
|
||||
.provider
|
||||
.authorName ??
|
||||
""
|
||||
: controller.workerModel.value!
|
||||
.fullName(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 18,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.greyDark900
|
||||
: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: RatingBar.builder(
|
||||
initialRating: controller.ratings.value,
|
||||
initialRating:
|
||||
controller.ratings.value,
|
||||
minRating: 1,
|
||||
direction: Axis.horizontal,
|
||||
allowHalfRating: true,
|
||||
itemCount: 5,
|
||||
itemPadding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
itemBuilder: (context, _) => const Icon(Icons.star, color: Colors.amber),
|
||||
unratedColor: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400,
|
||||
itemPadding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 4.0,
|
||||
),
|
||||
itemBuilder:
|
||||
(context, _) => const Icon(
|
||||
Icons.star,
|
||||
color: Colors.amber,
|
||||
),
|
||||
unratedColor:
|
||||
isDark
|
||||
? AppThemeData.greyDark400
|
||||
: AppThemeData.grey400,
|
||||
onRatingUpdate: (rating) {
|
||||
controller.ratings.value = rating;
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(20.0), child: TextFieldWidget(hintText: "Type comment....".tr(), controller: controller.comment, maxLine: 5)),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(20.0),
|
||||
child: TextFieldWidget(
|
||||
hintText: "Type comment....".tr(),
|
||||
controller: controller.comment,
|
||||
maxLine: 5,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: RoundedButtonFill(
|
||||
title: controller.ratingModel.value != null ? "Update Review".tr() : "Add Review".tr(),
|
||||
title:
|
||||
controller.ratingModel.value !=
|
||||
null
|
||||
? "Update Review".tr()
|
||||
: "Add Review".tr(),
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: controller.submitReview,
|
||||
@@ -105,7 +183,19 @@ class OnDemandReviewScreen extends StatelessWidget {
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: controller.reviewFor.value == "Provider" ? controller.order.value?.provider.authorProfilePic ?? '' : controller.workerModel.value?.profilePictureURL ?? '',
|
||||
imageUrl:
|
||||
controller.reviewFor.value == "Provider"
|
||||
? controller
|
||||
.order
|
||||
.value
|
||||
?.provider
|
||||
.authorProfilePic ??
|
||||
''
|
||||
: controller
|
||||
.workerModel
|
||||
.value
|
||||
?.profilePictureURL ??
|
||||
'',
|
||||
fit: BoxFit.cover,
|
||||
height: 100,
|
||||
width: 100,
|
||||
|
||||
@@ -10,8 +10,7 @@ import 'package:customer/widget/firebase_pagination/src/fireStore_pagination.dar
|
||||
import 'package:customer/widget/firebase_pagination/src/models/view_type.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../../controllers/theme_controller.dart';
|
||||
import '../../../service/fire_store_utils.dart';
|
||||
import '../../../themes/show_toast_dialog.dart';
|
||||
@@ -25,10 +24,19 @@ class ProviderInboxScreen extends StatelessWidget {
|
||||
final isDark = themeController.isDark.value;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
backgroundColor:
|
||||
isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
centerTitle: false,
|
||||
titleSpacing: 0,
|
||||
title: Text("Provider Inbox".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)),
|
||||
title: Text(
|
||||
"Provider Inbox".tr(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: FirestorePagination(
|
||||
//item builder type is compulsory.
|
||||
@@ -40,8 +48,12 @@ class ProviderInboxScreen extends StatelessWidget {
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait...".tr());
|
||||
|
||||
UserModel? customer = await FireStoreUtils.getUserProfile(inboxModel.customerId.toString());
|
||||
UserModel? restaurantUser = await FireStoreUtils.getUserProfile(inboxModel.restaurantId.toString());
|
||||
UserModel? customer = await FireStoreUtils.getUserProfile(
|
||||
inboxModel.customerId.toString(),
|
||||
);
|
||||
UserModel? restaurantUser = await FireStoreUtils.getUserProfile(
|
||||
inboxModel.restaurantId.toString(),
|
||||
);
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
Get.to(
|
||||
@@ -62,15 +74,23 @@ class ProviderInboxScreen extends StatelessWidget {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))),
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(10),
|
||||
),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: inboxModel.restaurantProfileImage.toString(),
|
||||
imageUrl:
|
||||
inboxModel.restaurantProfileImage.toString(),
|
||||
fit: BoxFit.cover,
|
||||
height: Responsive.height(6, context),
|
||||
width: Responsive.width(12, context),
|
||||
@@ -87,13 +107,29 @@ class ProviderInboxScreen extends StatelessWidget {
|
||||
child: Text(
|
||||
"${inboxModel.restaurantName}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey100
|
||||
: AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.timestampToDate(inboxModel.createdAt!),
|
||||
Constant.timestampToDate(
|
||||
inboxModel.createdAt!,
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(fontFamily: AppThemeData.regular, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey400
|
||||
: AppThemeData.grey500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -101,7 +137,14 @@ class ProviderInboxScreen extends StatelessWidget {
|
||||
Text(
|
||||
"${inboxModel.lastMessage}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey200
|
||||
: AppThemeData.grey700,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -116,7 +159,10 @@ class ProviderInboxScreen extends StatelessWidget {
|
||||
shrinkWrap: true,
|
||||
onEmpty: Constant.showEmptyView(message: "No Conversion found".tr()),
|
||||
// orderBy is compulsory to enable pagination
|
||||
query: FirebaseFirestore.instance.collection('chat_provider').where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()).orderBy('createdAt', descending: true),
|
||||
query: FirebaseFirestore.instance
|
||||
.collection('chat_provider')
|
||||
.where("customerId", isEqualTo: FireStoreUtils.getCurrentUid())
|
||||
.orderBy('createdAt', descending: true),
|
||||
//Change types customerId
|
||||
viewType: ViewType.list,
|
||||
initialLoader: Constant.loader(),
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:customer/screen_ui/on_demand_service/on_demand_home_screen.dart'
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../controllers/provider_controller.dart';
|
||||
import '../../controllers/theme_controller.dart';
|
||||
import '../../models/provider_serivce_model.dart';
|
||||
@@ -26,58 +26,114 @@ class ProviderScreen extends StatelessWidget {
|
||||
controller.isLoading.value
|
||||
? Center(child: Constant.loader())
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 50),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 50,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Center(
|
||||
child:
|
||||
(controller.userModel.value?.profilePictureURL ?? "").isNotEmpty
|
||||
? CircleAvatar(backgroundImage: NetworkImage(controller.userModel.value?.profilePictureURL ?? ''), radius: 50.0)
|
||||
: CircleAvatar(backgroundImage: NetworkImage(Constant.placeHolderImage), radius: 50.0),
|
||||
(controller.userModel.value?.profilePictureURL ??
|
||||
"")
|
||||
.isNotEmpty
|
||||
? CircleAvatar(
|
||||
backgroundImage: NetworkImage(
|
||||
controller
|
||||
.userModel
|
||||
.value
|
||||
?.profilePictureURL ??
|
||||
'',
|
||||
),
|
||||
radius: 50.0,
|
||||
)
|
||||
: CircleAvatar(
|
||||
backgroundImage: NetworkImage(
|
||||
Constant.placeHolderImage,
|
||||
),
|
||||
radius: 50.0,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
controller.userModel.value?.fullName() ?? '',
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 20, fontWeight: FontWeight.w900),
|
||||
style: TextStyle(
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_mail.svg", color: isDark ? Colors.white : Colors.black),
|
||||
SvgPicture.asset(
|
||||
"assets/icons/ic_mail.svg",
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
controller.userModel.value?.email ?? '',
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14, fontWeight: FontWeight.w500),
|
||||
style: TextStyle(
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_mobile.svg", color: isDark ? Colors.white : Colors.black),
|
||||
SvgPicture.asset(
|
||||
"assets/icons/ic_mobile.svg",
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
controller.userModel.value?.phoneNumber ?? '',
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black, fontFamily: AppThemeData.regular, fontSize: 14, fontWeight: FontWeight.w500),
|
||||
style: TextStyle(
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
decoration: const BoxDecoration(color: AppThemeData.warning400, borderRadius: BorderRadius.all(Radius.circular(16))),
|
||||
decoration: const BoxDecoration(
|
||||
color: AppThemeData.warning400,
|
||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.star, size: 16, color: Colors.white),
|
||||
const Icon(
|
||||
Icons.star,
|
||||
size: 16,
|
||||
color: Colors.white,
|
||||
),
|
||||
const SizedBox(width: 3),
|
||||
Text(
|
||||
_getRating(controller),
|
||||
style: const TextStyle(letterSpacing: 0.5, fontSize: 12, fontFamily: AppThemeData.regular, fontWeight: FontWeight.w500, color: Colors.white),
|
||||
style: const TextStyle(
|
||||
letterSpacing: 0.5,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -93,8 +149,14 @@ class ProviderScreen extends StatelessWidget {
|
||||
itemCount: controller.providerList.length,
|
||||
padding: EdgeInsets.zero,
|
||||
itemBuilder: (context, index) {
|
||||
ProviderServiceModel data = controller.providerList[index];
|
||||
return ServiceView(provider: data, isDark: isDark, controller: controller.onDemandHomeController.value);
|
||||
ProviderServiceModel data =
|
||||
controller.providerList[index];
|
||||
return ServiceView(
|
||||
provider: data,
|
||||
isDark: isDark,
|
||||
controller:
|
||||
controller.onDemandHomeController.value,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -107,8 +169,16 @@ class ProviderScreen extends StatelessWidget {
|
||||
}
|
||||
|
||||
String _getRating(ProviderController controller) {
|
||||
final reviewsCount = double.tryParse(controller.userModel.value?.reviewsCount?.toString() ?? "0") ?? 0;
|
||||
final reviewsSum = double.tryParse(controller.userModel.value?.reviewsSum?.toString() ?? "0") ?? 0;
|
||||
final reviewsCount =
|
||||
double.tryParse(
|
||||
controller.userModel.value?.reviewsCount?.toString() ?? "0",
|
||||
) ??
|
||||
0;
|
||||
final reviewsSum =
|
||||
double.tryParse(
|
||||
controller.userModel.value?.reviewsSum?.toString() ?? "0",
|
||||
) ??
|
||||
0;
|
||||
|
||||
if (reviewsCount == 0) return "0";
|
||||
final avg = reviewsSum / reviewsCount;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:customer/screen_ui/on_demand_service/on_demand_home_screen.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/theme_controller.dart';
|
||||
import '../../controllers/view_all_popular_service_controller.dart';
|
||||
@@ -32,12 +32,30 @@ class ViewAllPopularServiceScreen extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 42,
|
||||
width: 42,
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50),
|
||||
child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: AppThemeData.grey900,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text("All Services".tr(), style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)),
|
||||
Text(
|
||||
"All Services".tr(),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -46,13 +64,29 @@ class ViewAllPopularServiceScreen extends StatelessWidget {
|
||||
controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 20,
|
||||
horizontal: 15,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
TextFieldWidget(hintText: "Search Service".tr(), controller: controller.searchTextFiledController.value, onchange: (value) => controller.getFilterData(value.toString())),
|
||||
TextFieldWidget(
|
||||
hintText: "Search Service".tr(),
|
||||
controller:
|
||||
controller.searchTextFiledController.value,
|
||||
onchange:
|
||||
(value) =>
|
||||
controller.getFilterData(value.toString()),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
controller.providerList.isEmpty
|
||||
? Expanded(child: Center(child: Constant.showEmptyView(message: "No service Found".tr())))
|
||||
? Expanded(
|
||||
child: Center(
|
||||
child: Constant.showEmptyView(
|
||||
message: "No service Found".tr(),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: controller.providerList.length,
|
||||
@@ -60,8 +94,14 @@ class ViewAllPopularServiceScreen extends StatelessWidget {
|
||||
padding: EdgeInsets.zero,
|
||||
scrollDirection: Axis.vertical,
|
||||
itemBuilder: (context, index) {
|
||||
ProviderServiceModel data = controller.providerList[index];
|
||||
return ServiceView(provider: data, isDark: isDark, controller: controller.onDemandHomeController.value);
|
||||
ProviderServiceModel data =
|
||||
controller.providerList[index];
|
||||
return ServiceView(
|
||||
provider: data,
|
||||
isDark: isDark,
|
||||
controller:
|
||||
controller.onDemandHomeController.value,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/theme_controller.dart';
|
||||
import '../../controllers/view_category_service_controller.dart';
|
||||
@@ -32,12 +32,30 @@ class ViewCategoryServiceListScreen extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 42,
|
||||
width: 42,
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50),
|
||||
child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: AppThemeData.grey900,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(controller.categoryTitle.value, style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)),
|
||||
Text(
|
||||
controller.categoryTitle.value,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -48,14 +66,22 @@ class ViewCategoryServiceListScreen extends StatelessWidget {
|
||||
: controller.providerList.isEmpty
|
||||
? Constant.showEmptyView(message: "No Service Found".tr())
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
child: ListView.builder(
|
||||
itemCount: controller.providerList.length,
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
itemBuilder: (context, index) {
|
||||
ProviderServiceModel providerModel = controller.providerList[index];
|
||||
return ServiceView(isDark: isDark, provider: providerModel, controller: controller.onDemandHomeController.value);
|
||||
ProviderServiceModel providerModel =
|
||||
controller.providerList[index];
|
||||
return ServiceView(
|
||||
isDark: isDark,
|
||||
provider: providerModel,
|
||||
controller: controller.onDemandHomeController.value,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -10,8 +10,7 @@ import 'package:customer/widget/firebase_pagination/src/fireStore_pagination.dar
|
||||
import 'package:customer/widget/firebase_pagination/src/models/view_type.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'package:get/get.dart' hide Trans;
|
||||
import '../../../controllers/theme_controller.dart';
|
||||
import '../../../service/fire_store_utils.dart';
|
||||
import '../../../themes/show_toast_dialog.dart';
|
||||
@@ -25,10 +24,19 @@ class WorkerInboxScreen extends StatelessWidget {
|
||||
final isDark = themeController.isDark.value;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
backgroundColor:
|
||||
isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
centerTitle: false,
|
||||
titleSpacing: 0,
|
||||
title: Text("Worker Inbox".tr(), textAlign: TextAlign.start, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 16, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)),
|
||||
title: Text(
|
||||
"Worker Inbox".tr(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: FirestorePagination(
|
||||
//item builder type is compulsory.
|
||||
@@ -40,11 +48,17 @@ class WorkerInboxScreen extends StatelessWidget {
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait...".tr());
|
||||
|
||||
UserModel? customer = await FireStoreUtils.getUserProfile(inboxModel.customerId.toString());
|
||||
UserModel? restaurantUser = await FireStoreUtils.getUserProfile(inboxModel.restaurantId.toString());
|
||||
UserModel? customer = await FireStoreUtils.getUserProfile(
|
||||
inboxModel.customerId.toString(),
|
||||
);
|
||||
UserModel? restaurantUser = await FireStoreUtils.getUserProfile(
|
||||
inboxModel.restaurantId.toString(),
|
||||
);
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
print("customerId: ${inboxModel.customerId}, restaurantId: ${inboxModel.restaurantId}");
|
||||
print(
|
||||
"customerId: ${inboxModel.customerId}, restaurantId: ${inboxModel.restaurantId}",
|
||||
);
|
||||
Get.to(
|
||||
const ChatScreen(),
|
||||
arguments: {
|
||||
@@ -63,15 +77,23 @@ class WorkerInboxScreen extends StatelessWidget {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))),
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(10),
|
||||
),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: inboxModel.restaurantProfileImage.toString(),
|
||||
imageUrl:
|
||||
inboxModel.restaurantProfileImage.toString(),
|
||||
fit: BoxFit.cover,
|
||||
height: Responsive.height(6, context),
|
||||
width: Responsive.width(12, context),
|
||||
@@ -88,13 +110,29 @@ class WorkerInboxScreen extends StatelessWidget {
|
||||
child: Text(
|
||||
"${inboxModel.restaurantName}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(fontFamily: AppThemeData.semiBold, fontSize: 16, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey100
|
||||
: AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.timestampToDate(inboxModel.createdAt!),
|
||||
Constant.timestampToDate(
|
||||
inboxModel.createdAt!,
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(fontFamily: AppThemeData.regular, fontSize: 16, color: isDark ? AppThemeData.grey400 : AppThemeData.grey500),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey400
|
||||
: AppThemeData.grey500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -102,7 +140,14 @@ class WorkerInboxScreen extends StatelessWidget {
|
||||
Text(
|
||||
"${inboxModel.lastMessage}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 14, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark
|
||||
? AppThemeData.grey200
|
||||
: AppThemeData.grey700,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -117,7 +162,10 @@ class WorkerInboxScreen extends StatelessWidget {
|
||||
shrinkWrap: true,
|
||||
onEmpty: Constant.showEmptyView(message: "No Conversion found".tr()),
|
||||
// orderBy is compulsory to enable pagination
|
||||
query: FirebaseFirestore.instance.collection('chat_worker').where("customerId", isEqualTo: FireStoreUtils.getCurrentUid()).orderBy('createdAt', descending: true),
|
||||
query: FirebaseFirestore.instance
|
||||
.collection('chat_worker')
|
||||
.where("customerId", isEqualTo: FireStoreUtils.getCurrentUid())
|
||||
.orderBy('createdAt', descending: true),
|
||||
//Change types customerId
|
||||
viewType: ViewType.list,
|
||||
initialLoader: Constant.loader(),
|
||||
|
||||
Reference in New Issue
Block a user