editing card details

This commit is contained in:
ahmadherafi 2023-11-21 16:18:58 +03:00
parent 5a2f57f714
commit dc864eb2f7
24 changed files with 14453 additions and 579 deletions

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 404 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 307 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 342 KiB

View File

@ -23,4 +23,5 @@ class EndPoint {
static String favorite = 'favorite';
static String editCard(int id) => 'card/$id';
static String search = 'card';
static String rate = 'rate';
}

View File

@ -161,11 +161,11 @@ class RoutingManager {
),
GetPage(
name: RouteName.feedback,
page: () => const FeedbackScreen(),
page: () => FeedbackScreen(),
),
GetPage(
name: RouteName.reviewForm,
page: () => const ReviewFormScreen(),
page: () => ReviewFormScreen(),
),
GetPage(
name: RouteName.imageView,

View File

@ -163,30 +163,30 @@ class AccountScreen extends StatelessWidget {
// ).paddingOnly(bottom: 0),
// ],
// ),
AccountWidget(
icon: "my cards.svg",
title: "my_cards".tr,
).onTap(() async {
if (authController.isGuest.value) {
Get.defaultDialog(
title: '',
content: Column(
children: [
BoldTextWidget('you_have_to_sign_in'.tr),
const SizedBox(
height: 20,
),
ButtonWidget(
onTap: () {
RoutingManager.off(RouteName.login);
},
title: 'sign_in'.tr)
],
));
return;
}
RoutingManager.to(RouteName.myCards);
}),
// AccountWidget(
// icon: "my cards.svg",
// title: "my_cards".tr,
// ).onTap(() async {
// if (authController.isGuest.value) {
// Get.defaultDialog(
// title: '',
// content: Column(
// children: [
// BoldTextWidget('you_have_to_sign_in'.tr),
// const SizedBox(
// height: 20,
// ),
// ButtonWidget(
// onTap: () {
// RoutingManager.off(RouteName.login);
// },
// title: 'sign_in'.tr)
// ],
// ));
// return;
// }
// RoutingManager.to(RouteName.myCards);
// }),
AccountWidget(
icon: "about us.svg",
title: "about_us".tr,

View File

@ -10,6 +10,8 @@ import 'package:taafee_mobile/features/card/data_layer/model/add_card.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_images.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
import 'package:taafee_mobile/features/card/data_layer/model/edit_card.dart';
import 'package:taafee_mobile/features/card/data_layer/model/feedback.dart';
import 'package:taafee_mobile/features/card/data_layer/model/rate.dart';
import 'package:taafee_mobile/features/card/data_layer/source/card_service.dart';
import 'package:rx_future/rx_future.dart';
@ -244,4 +246,19 @@ class CardController extends GetxController {
void changeCurrentIndex(int index) {
currentIndex.value = index;
}
RateModel rateModel = RateModel.zero();
RxFuture<void> sendRatingState = RxFuture(null);
Future<void> sendRating() async {
await sendRatingState.observe((p0) async {
await cardService.sendRating(rateModel);
});
}
RxFuture<List<FeedbackModel>> feedbackState = RxFuture(<FeedbackModel>[]);
Future<void> getFeedback(int cardId) async {
await feedbackState.observe((p0) async {
return await cardService.getFeedback(cardId);
});
}
}

View File

@ -1,3 +1,4 @@
import 'package:taafee_mobile/features/card/data_layer/model/work_schedules.dart';
import 'package:taafee_mobile/features/home/data_layer/model/city.dart';
import 'card_images.dart';
@ -17,6 +18,11 @@ class CardModel {
String additionalData;
List<CardImages> cardImages;
bool isFav;
int price;
String lat;
String lan;
WorkScheduleModel? workScheduleModel;
int avgRating;
CardModel(
{required this.id,
@ -31,22 +37,33 @@ class CardModel {
required this.website,
required this.additionalData,
required this.cardImages,
required this.isFav});
required this.isFav,
required this.price,
required this.lat,
required this.lan,
this.workScheduleModel,
required this.avgRating});
factory CardModel.fromJson(Map<String, dynamic> json) => CardModel(
id: json["id"],
name: json["name"],
cityModel: CityModel.fromJson(json["city"]),
address: json["address"],
postalCode: json["postal_code"],
phoneNumber: json["phone_number1"],
services: json["services"],
categoryId: json["category_id"] ?? json['category']['id'],
user: User.fromJson(json["user"]),
website: json["website"],
additionalData: json["additional_data"],
cardImages: CardImages.fromJsonList(json),
isFav: json["isFav"] == 1 ? true : false);
id: json["id"],
name: json["name"],
cityModel: CityModel.fromJson(json["city"]),
address: json["address"],
postalCode: json["postal_code"],
phoneNumber: json["phone_number1"],
services: json["services"],
categoryId: json["category_id"] ?? json['category']['id'],
user: User.fromJson(json["user"]),
website: json["website"],
additionalData: json["additional_data"],
cardImages: CardImages.fromJsonList(json),
isFav: json["isFav"] == 1 ? true : false,
price: json["price"],
lan: json["lan"],
lat: json["lat"],
workScheduleModel: json["work_schedules"] == null ? null : WorkScheduleModel.fromJson(json),
avgRating: json["avg_rating"],
);
static List<CardModel> fromJsonList(Map<String, dynamic> json) {
List<CardModel> cards = [];

View File

@ -0,0 +1,35 @@
import 'package:taafee_mobile/features/auth/data_layer/model/user.dart';
class FeedbackModel {
int id;
int stars;
String feedback;
User user;
int cardId;
FeedbackModel({
required this.id,
required this.stars,
required this.feedback,
required this.user,
required this.cardId,
});
factory FeedbackModel.fromJson(Map<String, dynamic> json) => FeedbackModel(
id: json["id"],
stars: json["stars"],
feedback: json["feedback"].toString(),
user: User.fromJson(json["user"]),
cardId: json["card_id"],
);
static List<FeedbackModel> fromJsonList(Map<String, dynamic> json) {
List<FeedbackModel> feedback = [];
json["data"].forEach(
(element) => feedback.add(
FeedbackModel.fromJson(element),
),
);
return feedback;
}
}

View File

@ -0,0 +1,15 @@
class RateModel {
int cardId;
double stars;
String? feedback;
RateModel({required this.cardId, required this.stars, this.feedback});
factory RateModel.zero() => RateModel(cardId: 0, stars: 0);
Map<String, dynamic> toJson() => {
'card_id': cardId,
'stars': stars * 2,
if (feedback != null) 'feedback': feedback,
};
}

View File

@ -0,0 +1,65 @@
class WorkScheduleModel {
List<Day> days;
WorkScheduleModel({
required this.days,
});
factory WorkScheduleModel.fromJson(Map<String, dynamic> json) {
List<Day> days = [];
json["work_schedules"].forEach((key, value) {
days.add(
Day(
day: key,
workTime: workTimeModel.fromJsonList(value),
),
);
});
return WorkScheduleModel(days: days);
}
}
class Day {
String day;
List<workTimeModel> workTime;
Day({
required this.day,
required this.workTime,
});
factory Day.zero() => Day(
day: "",
workTime: [],
);
}
class workTimeModel {
String name;
String startTime;
String endTime;
workTimeModel({
required this.name,
required this.startTime,
required this.endTime,
});
factory workTimeModel.fromJson(Map<String, dynamic> json) => workTimeModel(
name: json["name"],
startTime: json["start"],
endTime: json["end"],
);
static List<workTimeModel> fromJsonList(List<dynamic> json) {
List<workTimeModel> days = [];
for (var day in json) {
days.add(
workTimeModel.fromJson(day),
);
}
// json[key].forEach(
// (element) => days.add(
// workTimeModel.fromJson(element),
// ),
// );
return days;
}
}

View File

@ -1,11 +1,11 @@
class WorkingTimeModel {
String type;
String startTime;
String endTime;
// class WorkingTimeModel {
// String type;
// String startTime;
// String endTime;
WorkingTimeModel({
required this.type,
required this.startTime,
required this.endTime,
});
}
// WorkingTimeModel({
// required this.type,
// required this.startTime,
// required this.endTime,
// });
// }

View File

@ -8,6 +8,8 @@ import 'package:taafee_mobile/core/local_storage/local_storage.dart';
import 'package:taafee_mobile/core/network/http.dart';
import 'package:taafee_mobile/features/card/data_layer/model/add_card.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_images.dart';
import 'package:taafee_mobile/features/card/data_layer/model/feedback.dart';
import 'package:taafee_mobile/features/card/data_layer/model/rate.dart';
import '../model/card_model.dart';
import '../model/edit_card.dart';
@ -15,33 +17,25 @@ import '../model/edit_card.dart';
class CardService {
LocalStorage localStorage = LocalStorage();
Future<void> addCard(AddCardModel addCardModel) async {
Request request = Request(EndPoint.card, RequestMethod.post,
body: addCardModel.toJson(), isFormData: true, authorized: true);
Request request =
Request(EndPoint.card, RequestMethod.post, body: addCardModel.toJson(), isFormData: true, authorized: true);
//no need to use variable
await request.sendRequest();
}
Future<List<CardModel>> getCards(
{int? page,
int? categoryId,
void Function(Object)? onConnectionError}) async {
Future<List<CardModel>> getCards({int? page, int? categoryId, void Function(Object)? onConnectionError}) async {
Request request = Request(EndPoint.card, RequestMethod.get,
authorized: true,
cacheable: true,
queryParams: {
"page": page,
if (categoryId != null) 'category_id': categoryId
});
queryParams: {"page": page, if (categoryId != null) 'category_id': categoryId});
Map<String, dynamic> response =
await request.sendRequest(onConnectionError: onConnectionError);
Map<String, dynamic> response = await request.sendRequest(onConnectionError: onConnectionError);
return CardModel.fromJsonList(response);
}
Future<CardModel> showCard({required int cardId}) async {
Request request = Request('${EndPoint.card}/$cardId', RequestMethod.get,
authorized: true);
Request request = Request('${EndPoint.card}/$cardId', RequestMethod.get, authorized: true);
Map<String, dynamic> response = await request.sendRequest();
return CardModel.fromJson(response['data']);
}
@ -71,15 +65,11 @@ class CardService {
await request.sendRequest();
}
Future<List<CardModel>> getMyCards(int userId,
{int? page, void Function(Object)? onConnectionError}) async {
Future<List<CardModel>> getMyCards(int userId, {int? page, void Function(Object)? onConnectionError}) async {
Request request = Request(EndPoint.card, RequestMethod.get,
cacheable: true,
authorized: true,
queryParams: {"user_id": userId, 'page': page});
cacheable: true, authorized: true, queryParams: {"user_id": userId, 'page': page});
Map<String, dynamic> response =
await request.sendRequest(onConnectionError: onConnectionError);
Map<String, dynamic> response = await request.sendRequest(onConnectionError: onConnectionError);
return CardModel.fromJsonList(response);
}
@ -148,4 +138,23 @@ class CardService {
));
return Uint8List.fromList(response.data);
}
Future<void> sendRating(RateModel rateModel) async {
Request request = Request(EndPoint.rate, RequestMethod.post, authorized: true, body: rateModel.toJson());
Map<String, dynamic> response = await request.sendRequest();
}
Future<List<FeedbackModel>> getFeedback(int cardId) async {
Request request = Request(
EndPoint.rate,
RequestMethod.get,
authorized: true,
queryParams: {
"card_id": cardId,
},
);
Map<String, dynamic> response = await request.sendRequest();
return FeedbackModel.fromJsonList(response);
}
}

View File

@ -142,13 +142,15 @@ class CardDetailsScreen extends StatelessWidget {
radius: 60,
backgroundColor: AppColors.secondaryColor,
),
const Positioned(
Positioned(
top: 15,
child: CircleAvatar(
radius: 50,
backgroundImage: AssetImage(
"assets/images/Ellipse 8.png",
),
backgroundImage: cardModel.user.avatarImage == null
? const AssetImage(
"assets/images/default_user_avatar.png",
)
: NetworkImage(cardModel.user.avatarImage!) as ImageProvider,
),
),
],
@ -162,16 +164,20 @@ class CardDetailsScreen extends StatelessWidget {
child: ListViewWidget(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: 4,
itemCount: cardModel.cardImages.length,
childBuilder: (index) {
if (index == 3) {
return const ImageWidget(
return ImageWidget(
numberOfImages: 5,
cardImages: cardModel.cardImages[index],
).onTap(() {
RoutingManager.to(RouteName.imageView);
});
}
return const ImageWidget(numberOfImages: 1);
return ImageWidget(
numberOfImages: 1,
cardImages: cardModel.cardImages[index],
);
},
),
),
@ -184,11 +190,15 @@ class CardDetailsScreen extends StatelessWidget {
const SizedBox(
height: 20,
),
WorkingTimeWidget(),
WorkingTimeWidget(
workScheduleModel: cardModel.workScheduleModel,
),
const SizedBox(
height: 20,
),
RateWidget(),
RateWidget(
cardModel: cardModel,
),
const SizedBox(
height: 20,
),
@ -200,21 +210,13 @@ class CardDetailsScreen extends StatelessWidget {
// ),
child: FlutterMap(
options: MapOptions(
center: const location.LatLng(51.509364, -0.128928),
center: location.LatLng(double.parse(cardModel.lat), double.parse(cardModel.lan)),
),
children: [
TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
userAgentPackageName: 'com.example.app',
),
// RichAttributionWidget(
// attributions: [
// TextSourceAttribution(
// 'OpenStreetMap contributors',
// onTap: () => launchUrl(Uri.parse('https://openstreetmap.org/copyright')),
// ),
// ],
// ),
],
),
),
@ -243,161 +245,28 @@ class CardDetailsScreen extends StatelessWidget {
const SizedBox(
height: 20,
),
// Row(
// children: [
// ButtonWidget(
// color: AppColors.callColor,
// haveIcon: true,
// onTap: () async {
// await UrlLauncherService.makePhoneCall(cardModel.phoneNumber);
// },
// title: "call_owner".tr,
// textColor: Colors.white,
// child: SvgPicture.asset(
// "assets/icons/phone.svg",
// colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
// ),
// ).paddingSymmetric(horizontal: 4).expanded(Responsive.isTablet() ? 1 : 5),
// ButtonWidget(
// color: AppColors.emailColor,
// haveIcon: true,
// onTap: () async {
// await UrlLauncherService.sendEmail(cardModel.user.email);
// },
// title: "email".tr,
// textColor: Colors.white,
// child: SvgPicture.asset("assets/icons/Email.svg"),
// ).paddingSymmetric(horizontal: 4).expanded(Responsive.isTablet() ? 1 : 5),
// if (Responsive.isTablet())
// Visibility(
// visible: chatController.chatUser.id != cardModel.user.chatUserId,
// child: Obx(() {
// return ButtonWidget(
// isLoading: chatController.createRoomState.loading,
// textColor: Colors.white,
// color: AppColors.messageColor,
// haveIcon: true,
// onTap: () {
// if (chatController.connectionState.value == SocketConnectionState.connected) {
// chatController.createRoom(
// chatUserId: cardModel.user.chatUserId,
// onSuccess: (room) {
// RoutingManager.to(RouteName.chatDetails, arguments: {
// "room": room,
// });
// });
// } else {
// Toast.showToast('you_have_no_internet_connection.'.tr);
// }
// },
// title: "start_conversation".tr,
// fontSize: 13,
// child: SvgPicture.asset("assets/icons/message.svg"),
// ).expanded(Responsive.isTablet() ? 1 : 5);
// }),
// ),
// if (Responsive.isTablet())
// Obx(() {
// return Visibility(
// visible: homeController.user.value!.id != cardModel.user.id,
// child: (homeController.currentCardAppointment.value != null)
// ? ButtonWidget(
// haveIcon: true,
// onTap: () {
// appointmentDialog(context);
// },
// fontSize: 13,
// color: AppColors.secondaryColor,
// title: 'you_have_an_appointment'.tr,
// child: const Icon(
// Icons.schedule,
// color: Colors.white,
// ),
// ).paddingSymmetric(horizontal: 4).expanded(Responsive.isTablet() ? 1 : 5)
// : ButtonWidget(
// onTap: () {
// cardController.getAvailableAppointments();
// appointmentSchedulingDialog(context);
// },
// haveIcon: true,
// fontSize: 12,
// title: 'schedule_an_appointment'.tr,
// color: AppColors.secondaryColor,
// child: const Icon(
// Icons.schedule,
// color: Colors.white,
// ),
// ).paddingSymmetric(horizontal: 4).expanded(Responsive.isTablet() ? 1 : 5),
// );
// }),
// ],
// ).paddingSymmetric(vertical: Responsive.isTablet() ? 20 : 4, horizontal: Responsive.isTablet() ? 40 : 10),
// if (!Responsive.isTablet())
// Obx(() {
// return Row(
// children: [
// Obx(() {
// return Visibility(
// visible: homeController.user.value!.id != cardModel.user.id,
// child: (homeController.currentCardAppointment.value != null)
// ? ButtonWidget(
// haveIcon: true,
// onTap: () {
// appointmentDialog(context);
// },
// fontSize: 12,
// color: AppColors.secondaryColor,
// title: 'you_have_an_appointment'.tr,
// child: const Icon(
// Icons.schedule,
// color: Colors.white,
// ),
// ).paddingSymmetric(horizontal: 4).expanded(Responsive.isTablet() ? 1 : 5)
// : ButtonWidget(
// onTap: () {
// cardController.getAvailableAppointments();
// appointmentSchedulingDialog(context);
// },
// haveIcon: true,
// fontSize: 12,
// title: 'schedule_an_appointment'.tr,
// color: AppColors.secondaryColor,
// child: const Icon(
// Icons.schedule,
// color: Colors.white,
// ),
// ).paddingSymmetric(horizontal: 4).expanded(Responsive.isTablet() ? 1 : 5),
// );
// }),
// Visibility(
// visible: chatController.chatUser.id != cardModel.user.chatUserId,
// child: ButtonWidget(
// isLoading: chatController.createRoomState.loading,
// textColor: Colors.white,
// color: AppColors.messageColor,
// haveIcon: true,
// onTap: () {
// if (chatController.connectionState.value == SocketConnectionState.connected) {
// chatController.createRoom(
// chatUserId: cardModel.user.chatUserId,
// onSuccess: (room) {
// RoutingManager.to(RouteName.chatDetails, arguments: {"room": room});
// });
// } else {
// Toast.showToast('you_have_no_internet_connection'.tr);
// }
// },
// title: "start_conversation".tr,
// fontSize: 12,
// child: SvgPicture.asset("assets/icons/message.svg"),
// ).paddingSymmetric(horizontal: 4).expanded(Responsive.isTablet() ? 1 : 5),
// ),
// ],
// ).paddingSymmetric(vertical: Responsive.isTablet() ? 20 : 4, horizontal: Responsive.isTablet() ? 40 : 10);
// }),
// const SizedBox(
// height: 60,
// ),
Container(
width: Get.width * .89,
height: 200,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const RegularTextWidget(
"Insurance companies",
color: Colors.grey,
fontSize: 14,
).paddingSymmetric(horizontal: 30),
RegularTextWidget(cardModel.additionalData).paddingSymmetric(horizontal: 10, vertical: 5)
],
),
),
const SizedBox(
height: 20,
),
],
).paddingSymmetric(horizontal: Responsive.isTablet() ? 20 : 0)),
).makeSafeArea();

View File

@ -3,10 +3,13 @@ import 'package:get/get.dart';
import 'package:taafee_mobile/common/extensions/widget_extension.dart';
import 'package:taafee_mobile/common/widgets/header_screen.dart';
import 'package:taafee_mobile/common/widgets/listview.dart';
import 'package:taafee_mobile/common/widgets/rx_viewer.dart';
import 'package:taafee_mobile/features/card/business_logic_layer/card_controller.dart';
import 'package:taafee_mobile/features/card/presentation_layer/widgets/feedback_widget.dart';
class FeedbackScreen extends StatelessWidget {
const FeedbackScreen({super.key});
final CardController cardController = Get.find<CardController>();
FeedbackScreen({super.key});
@override
Widget build(BuildContext context) {
@ -16,13 +19,18 @@ class FeedbackScreen extends StatelessWidget {
HeaderScreen(
"Feedback",
).paddingOnly(top: 20),
SizedBox(
width: Get.width,
child: ListViewWidget(
itemCount: 10,
childBuilder: (index) {
return const FeedbackWidget();
}),
RxViewer(
rxFuture: cardController.feedbackState,
child: () => SizedBox(
width: Get.width,
child: ListViewWidget(
itemCount: cardController.feedbackState.result.length,
childBuilder: (index) {
return FeedbackWidget(
feedbackModel: cardController.feedbackState.result[index],
);
}),
),
)
],
),

View File

@ -7,11 +7,13 @@ import 'package:taafee_mobile/common/widgets/button.dart';
import 'package:taafee_mobile/common/widgets/header_screen.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/common/widgets/textfiled.dart';
import 'package:taafee_mobile/features/card/business_logic_layer/card_controller.dart';
import '../../../../core/routing/routing_manager.dart';
class ReviewFormScreen extends StatelessWidget {
const ReviewFormScreen({super.key});
final CardController cardController = Get.find<CardController>();
ReviewFormScreen({super.key});
@override
Widget build(BuildContext context) {
@ -45,7 +47,7 @@ class ReviewFormScreen extends StatelessWidget {
minRating: 1,
itemSize: 40,
direction: Axis.horizontal,
allowHalfRating: false,
allowHalfRating: true,
glow: false,
itemCount: 5,
// glowColor: ,
@ -54,13 +56,17 @@ class ReviewFormScreen extends StatelessWidget {
Icons.star_rounded,
color: Colors.amber,
),
onRatingUpdate: (rating) {},
onRatingUpdate: (rating) {
cardController.rateModel.stars = rating;
},
),
),
TextFieldWidget(
maxLines: 7,
textInputAction: TextInputAction.newline,
onChange: (value) {},
onChange: (value) {
cardController.rateModel.feedback = value;
},
keyboardType: TextInputType.multiline,
label: "",
validate: (value) {
@ -68,13 +74,17 @@ class ReviewFormScreen extends StatelessWidget {
},
height: Get.height * .3,
).paddingOnly(top: 30),
ButtonWidget(
onTap: () {
RoutingManager.back();
},
title: "Done",
width: Get.width * .3,
).center()
Obx(() {
return ButtonWidget(
isLoading: cardController.sendRatingState.loading,
onTap: () async {
await cardController.sendRating();
RoutingManager.back();
},
title: "Done",
width: Get.width * .3,
).center();
})
],
).paddingSymmetric(horizontal: 30, vertical: 20),
],

View File

@ -23,7 +23,7 @@ class CardWidget extends StatelessWidget {
width: Get.width,
height: 175,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
),

View File

@ -37,7 +37,7 @@ class ConsultationPriceWidget extends StatelessWidget {
color: Colors.grey,
),
BoldTextWidget(
"400 SP".tr,
"${cardModel.price} SP".tr,
fontSize: 20,
color: Colors.grey,
),

View File

@ -1,24 +1,28 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/features/card/data_layer/model/feedback.dart';
class FeedbackWidget extends StatelessWidget {
const FeedbackWidget({super.key});
final FeedbackModel feedbackModel;
const FeedbackWidget({super.key, required this.feedbackModel});
@override
Widget build(BuildContext context) {
return const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
RegularTextWidget(
"Zakoor",
fontSize: 16,
),
RegularTextWidget(
"ggggggggggggggggggg",
fontSize: 14,
),
],
).paddingSymmetric(horizontal: 20, vertical: 8);
return feedbackModel.feedback != "null"
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
RegularTextWidget(
"${feedbackModel.user.firstName} ${feedbackModel.user.lastName}",
fontSize: 16,
),
RegularTextWidget(
feedbackModel.feedback,
fontSize: 14,
),
],
).paddingSymmetric(horizontal: 20, vertical: 8)
: Container();
}
}

View File

@ -1,14 +1,16 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:taafee_mobile/common/const/const.dart';
import 'package:taafee_mobile/common/extensions/widget_extension.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_images.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
class ImageWidget extends StatelessWidget {
final int numberOfImages;
const ImageWidget({
super.key,
required this.numberOfImages,
});
final CardImages cardImages;
const ImageWidget({super.key, required this.numberOfImages, required this.cardImages});
@override
Widget build(BuildContext context) {
@ -18,8 +20,9 @@ class ImageWidget extends StatelessWidget {
height: Get.width * .2,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: const DecorationImage(
image: AssetImage("assets/images/download.jpg"),
image: DecorationImage(
image: CachedNetworkImageProvider(Domain.domain + cardImages.url.substring(6)),
// image: AssetImage("assets/images/download.jpg"),
fit: BoxFit.cover,
),
),

View File

@ -8,6 +8,7 @@ import 'package:taafee_mobile/common/widgets/button.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/core/routing/routing_manager.dart';
import 'package:taafee_mobile/features/card/business_logic_layer/card_controller.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
import 'package:taafee_mobile/features/card/presentation_layer/widgets/star.dart';
import 'package:taafee_mobile/features/card/presentation_layer/widgets/view_ratings.dart';
@ -15,14 +16,15 @@ import '../../../../common/const/const.dart';
import '../../../../common/widgets/textfiled.dart';
class RateWidget extends StatelessWidget {
final CardModel cardModel;
final CardController cardController = Get.find<CardController>();
RateWidget({super.key});
RateWidget({super.key, required this.cardModel});
@override
Widget build(BuildContext context) {
return Container(
width: Get.width * .89,
height: 150,
height: 200,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
@ -34,6 +36,7 @@ class RateWidget extends StatelessWidget {
children: [
const RegularTextWidget("Rates"),
Container(
margin: const EdgeInsets.only(top: 5),
alignment: Alignment.center,
width: 100,
height: 25,
@ -46,199 +49,20 @@ class RateWidget extends StatelessWidget {
color: Colors.white,
),
).onTap(() {
cardController.rateModel.cardId = cardModel.id;
RoutingManager.to(RouteName.reviewForm);
}),
],
).paddingSymmetric(horizontal: 20, vertical: 5),
const ViewRatingsWidget(),
ViewRatingsWidget(
cardModel: cardModel,
),
],
),
// child: Column(
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Row(
// children: [
// RegularTextWidget("Number of users who rate this : ".tr),
// RegularTextWidget("10".tr),
// ],
// ),
// Container(
// alignment: Alignment.center,
// width: 100,
// height: 25,
// decoration: BoxDecoration(
// color: AppColors.primeColor,
// borderRadius: BorderRadius.circular(25),
// ),
// child: RegularTextWidget(
// "Rate Now".tr,
// color: Colors.white,
// ),
// ).onTap(() {
// dialog();
// cardController.currentIndex(0);
// })
// ],
// ),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Column(
// children: [
// const Stack(
// alignment: Alignment.center,
// children: [
// StarWidget(maxRating: 1, starSize: 60, readOnly: true),
// RegularTextWidget(
// "2.5",
// color: Colors.black,
// ),
// ],
// ),
// RegularTextWidget("Waiting".tr),
// ],
// ),
// Column(
// children: [
// const Stack(
// alignment: Alignment.center,
// children: [
// StarWidget(maxRating: 1, starSize: 60, readOnly: true),
// RegularTextWidget(
// "2.5",
// color: Colors.black,
// ),
// ],
// ),
// RegularTextWidget("Performance".tr),
// ],
// ),
// Column(
// children: [
// const Stack(
// alignment: Alignment.center,
// children: [
// StarWidget(maxRating: 1, starSize: 60, readOnly: true),
// RegularTextWidget(
// "2.5",
// color: Colors.black,
// ),
// ],
// ),
// RegularTextWidget("Price".tr),
// ],
// )
// ],
// ).paddingOnly(top: 10).paddingSymmetric(horizontal: 20),
// ],
// ).paddingSymmetric(horizontal: 10, vertical: 10),
).onTap(() {
).onTap(() async {
cardController.getFeedback(cardModel.id);
RoutingManager.to(RouteName.feedback);
log("message");
});
}
final PageController pageController = PageController();
final List<String> rate = [
"waiting?",
"Performance?",
"Price?",
"Feedback",
];
final List<Widget> stars = [
const StarWidget(maxRating: 5, starSize: 30, readOnly: false),
const StarWidget(maxRating: 5, starSize: 30, readOnly: false),
const StarWidget(maxRating: 5, starSize: 30, readOnly: false),
Container(
alignment: Alignment.topCenter,
width: Get.width * .5,
height: 55,
child: TextFormField(
onChanged: (value) {},
maxLines: 4,
textInputAction: TextInputAction.newline,
keyboardType: TextInputType.multiline,
),
),
// TextFieldWidget(
// keyboardType: TextInputType.multiline,
// label: "",
// onChange: (value) {},
// maxLines: 5,
// textInputAction: TextInputAction.newline,
// validate: (p0) {
// return null;
// },
// ),
];
void dialog() {
Get.defaultDialog(
onWillPop: () async {
cardController.currentIndex(0);
return true;
},
confirm: Obx(() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
RegularTextWidget(
"back".tr,
color: Colors.black,
).onTap(() {
if (cardController.currentIndex.value == 0) {
RoutingManager.back();
}
pageController.animateToPage(cardController.currentIndex.value - 1,
duration: const Duration(milliseconds: 250), curve: Curves.easeIn);
}),
ButtonWidget(
width: 80,
onTap: () {
if (cardController.currentIndex.value == 3) {
RoutingManager.back();
}
pageController.animateToPage(cardController.currentIndex.value + 1,
duration: const Duration(milliseconds: 250), curve: Curves.easeIn);
},
title: cardController.currentIndex.value == 3 ? "OK".tr : "Next".tr),
],
).paddingSymmetric(horizontal: 20);
}),
backgroundColor: Colors.white,
title: "",
middleText: "",
content: SizedBox(
width: Get.width * .5,
height: Get.height * .15,
child: PageView.builder(
physics: const BouncingScrollPhysics(),
controller: pageController,
onPageChanged: (value) {
cardController.changeCurrentIndex(value);
},
itemCount: 4,
itemBuilder: (BuildContext context, index) {
return Column(
children: [
BoldTextWidget(rate[index].tr).paddingOnly(bottom: 30),
stars[index],
// SizedBox(
// width: Get.width * .8,
// child: RegularTextWidget(
// textAlign: TextAlign.center,
// text[index].tr,
// color: Colors.black,
// ),
// )
],
);
},
),
));
}
}

View File

@ -1,41 +1,41 @@
import 'package:animated_rating_stars/animated_rating_stars.dart';
import 'package:flutter/material.dart';
// import 'package:animated_rating_stars/animated_rating_stars.dart';
// import 'package:flutter/material.dart';
class StarWidget extends StatelessWidget {
final double maxRating;
final double starSize;
final bool readOnly;
const StarWidget({
super.key,
required this.maxRating,
required this.starSize,
required this.readOnly,
});
// class StarWidget extends StatelessWidget {
// final double maxRating;
// final double starSize;
// final bool readOnly;
// const StarWidget({
// super.key,
// required this.maxRating,
// required this.starSize,
// required this.readOnly,
// });
@override
Widget build(BuildContext context) {
return AnimatedRatingStars(
initialRating: 1,
minRating: 0,
maxRating: maxRating,
filledColor: Colors.amber,
emptyColor: Colors.grey,
filledIcon: Icons.star_border_rounded,
halfFilledIcon: Icons.star_half_rounded,
emptyIcon: Icons.star_border_rounded,
onChanged: (double rating) {
// Handle the rating change here
print('Rating: $rating');
},
displayRatingValue: true,
interactiveTooltips: true,
customFilledIcon: Icons.star_border_rounded,
customHalfFilledIcon: Icons.star_half_rounded,
customEmptyIcon: Icons.star_border_rounded,
starSize: starSize,
animationDuration: const Duration(milliseconds: 300),
animationCurve: Curves.easeInOut,
readOnly: readOnly,
);
}
}
// @override
// Widget build(BuildContext context) {
// return AnimatedRatingStars(
// initialRating: 1,
// minRating: 0,
// maxRating: maxRating,
// filledColor: Colors.amber,
// emptyColor: Colors.grey,
// filledIcon: Icons.star_border_rounded,
// halfFilledIcon: Icons.star_half_rounded,
// emptyIcon: Icons.star_border_rounded,
// onChanged: (double rating) {
// // Handle the rating change here
// print('Rating: $rating');
// },
// displayRatingValue: true,
// interactiveTooltips: true,
// customFilledIcon: Icons.star_border_rounded,
// customHalfFilledIcon: Icons.star_half_rounded,
// customEmptyIcon: Icons.star_border_rounded,
// starSize: starSize,
// animationDuration: const Duration(milliseconds: 300),
// animationCurve: Curves.easeInOut,
// readOnly: readOnly,
// );
// }
// }

View File

@ -5,9 +5,11 @@ import 'package:percent_indicator/linear_percent_indicator.dart';
import 'package:taafee_mobile/common/const/const.dart';
import 'package:taafee_mobile/common/widgets/listview.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
class ViewRatingsWidget extends StatelessWidget {
const ViewRatingsWidget({super.key});
final CardModel cardModel;
const ViewRatingsWidget({super.key, required this.cardModel});
@override
Widget build(BuildContext context) {
@ -23,15 +25,15 @@ class ViewRatingsWidget extends StatelessWidget {
color: AppColors.primeColor,
shape: BoxShape.circle,
),
child: const BoldTextWidget(
"5.0",
child: BoldTextWidget(
(cardModel.avgRating / 2).toString(),
fontSize: 24,
color: Colors.white,
),
),
RatingBar.builder(
itemSize: 15,
initialRating: 3.5,
initialRating: cardModel.avgRating / 2,
minRating: 1,
direction: Axis.horizontal,
allowHalfRating: true,

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:taafee_mobile/features/card/data_layer/model/work_schedules.dart';
import 'package:taafee_mobile/features/card/data_layer/model/working_time.dart';
import '../../../../common/const/const.dart';
@ -7,77 +8,66 @@ import '../../../../common/widgets/listview.dart';
import '../../../../common/widgets/text.dart';
class WorkingTimeWidget extends StatelessWidget {
final List<WorkingTimeModel> list = [
WorkingTimeModel(type: "Sunday", startTime: "8:00", endTime: "10:00"),
WorkingTimeModel(type: "Monday", startTime: "8:00", endTime: "10:00"),
WorkingTimeModel(type: "Sunday", startTime: "8:00", endTime: "10:00"),
];
WorkingTimeWidget({super.key});
WorkScheduleModel? workScheduleModel;
WorkingTimeWidget({super.key, this.workScheduleModel});
@override
Widget build(BuildContext context) {
return Container(
width: Get.width * .89,
height: 270,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: Stack(
children: [
const BoldTextWidget(
"working time",
color: Colors.grey,
).paddingSymmetric(horizontal: 20),
ListViewWidget(
physics: const BouncingScrollPhysics(),
itemCount: 8,
scrollDirection: Axis.horizontal,
childBuilder: (index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const RegularTextWidget("8:00"),
Expanded(
child: Container(
width: 1,
color: AppColors.dividerColor,
),
),
],
).paddingSymmetric(horizontal: 10);
}).paddingOnly(top: 25),
SizedBox(
return workScheduleModel != null
? Container(
width: Get.width * .89,
// height: 270,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: SizedBox(
width: Get.width * .89,
child: ListViewWidget(
itemCount: list.length,
itemCount: workScheduleModel!.days.length,
physics: const BouncingScrollPhysics(),
childBuilder: (index) {
return SizedBox(
width: Get.width * .89,
height: 42,
child: ListViewWidget(
padding: const EdgeInsets.only(top: 20),
scrollDirection: Axis.horizontal,
itemCount: list.length,
childBuilder: (index) {
return Container(
alignment: Alignment.center,
margin: const EdgeInsets.symmetric(horizontal: 10),
width: 100,
decoration: BoxDecoration(
color: AppColors.secondaryColor,
borderRadius: BorderRadius.circular(25),
),
child: RegularTextWidget(
list[index].type,
color: Colors.white,
),
);
}),
return Row(
children: [
SizedBox(
width: 90,
child: BoldTextWidget(workScheduleModel!.days[index].day),
).paddingSymmetric(horizontal: 12),
Expanded(
child: SizedBox(
height: 50,
child: ListViewWidget(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: workScheduleModel!.days[index].workTime.length,
childBuilder: (i) {
return Container(
alignment: Alignment.center,
width: 125,
decoration: BoxDecoration(
color: workScheduleModel!.days[index].workTime[i].name == "عطلة"
? Colors.grey
: AppColors.secondaryColor,
borderRadius: BorderRadius.circular(10),
),
margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
RegularTextWidget(workScheduleModel!.days[index].workTime[i].startTime),
RegularTextWidget(workScheduleModel!.days[index].workTime[i].name),
RegularTextWidget(workScheduleModel!.days[index].workTime[i].endTime),
],
).paddingSymmetric(horizontal: 10),
);
}),
),
)
],
);
}),
).paddingOnly(top: 30)
],
));
),
)
: Container();
}
}