6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 2975407d

AuthorMikkel Thygesen<mikkelet@gmail.com>
Date2026-02-27 15:26:56 +0100
2930: refined receipt screen

Changed files

.../presentation/app/cart_cubit.freezed.dart       | 43 ++++++-----
 concierge/lib/concierge_app.dart                   |  6 +-
 .../domain/repositories/property_repository.dart   |  7 +-
 concierge/lib/presentation/app/cart_cubit.dart     |  6 ++
 .../widgets/confirm_order_product_list_tile.dart   |  2 +-
 .../bloc/hotel_overview_page_cubit.dart            | 12 ++-
 .../hotel_overview_page_route.dart                 |  6 +-
 .../hotel_overview_page/widgets/cart_app_bar.dart  |  5 +-
 .../screens/payment/bloc/payment_cubit.dart        |  5 +-
 .../screens/receipt/bloc/receipt_cubit.dart        | 34 +++++++-
 .../screens/receipt/receipt_screen.dart            | 54 +++++++++----
 .../receipt/widgets/receipt_action_bar.dart        | 25 ++++++
 .../screens/receipt/widgets/receipt_card.dart      | 90 ++++++++++++++++++++++
 13 files changed, 241 insertions(+), 54 deletions(-)

Diff

diff --git a/concierge/lib/_generated/presentation/app/cart_cubit.freezed.dart b/concierge/lib/_generated/presentation/app/cart_cubit.freezed.dart
index 4f886948..fff55b45 100644
--- a/concierge/lib/_generated/presentation/app/cart_cubit.freezed.dart
+++ b/concierge/lib/_generated/presentation/app/cart_cubit.freezed.dart
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$CartState {
- bool get isLoading; AppError get error; Map<int, ProductInCart> get productsWithQuantity; bool get isDelivery; String get comment; String get readyTime;
+ bool get isLoading; AppError get error; Map<int, ProductInCart> get productsWithQuantity; bool get isDelivery; String get comment; String get readyTime; AreaDetails? get selectedArea;
/// Create a copy of CartState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -25,16 +25,16 @@ $CartStateCopyWith<CartState> get copyWith => _$CartStateCopyWithImpl<CartState>
@override
bool operator ==(Object other) {
- return identical(this, other) || (other.runtimeType == runtimeType&&other is CartState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other.productsWithQuantity, productsWithQuantity)&&(identical(other.isDelivery, isDelivery) || other.isDelivery == isDelivery)&&(identical(other.comment, comment) || other.comment == comment)&&(identical(other.readyTime, readyTime) || other.readyTime == readyTime));
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is CartState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other.productsWithQuantity, productsWithQuantity)&&(identical(other.isDelivery, isDelivery) || other.isDelivery == isDelivery)&&(identical(other.comment, comment) || other.comment == comment)&&(identical(other.readyTime, readyTime) || other.readyTime == readyTime)&&(identical(other.selectedArea, selectedArea) || other.selectedArea == selectedArea));
}
@override
-int get hashCode => Object.hash(runtimeType,isLoading,error,const DeepCollectionEquality().hash(productsWithQuantity),isDelivery,comment,readyTime);
+int get hashCode => Object.hash(runtimeType,isLoading,error,const DeepCollectionEquality().hash(productsWithQuantity),isDelivery,comment,readyTime,selectedArea);
@override
String toString() {
- return 'CartState(isLoading: $isLoading, error: $error, productsWithQuantity: $productsWithQuantity, isDelivery: $isDelivery, comment: $comment, readyTime: $readyTime)';
+ return 'CartState(isLoading: $isLoading, error: $error, productsWithQuantity: $productsWithQuantity, isDelivery: $isDelivery, comment: $comment, readyTime: $readyTime, selectedArea: $selectedArea)';
}
@@ -45,7 +45,7 @@ abstract mixin class $CartStateCopyWith<$Res> {
factory $CartStateCopyWith(CartState value, $Res Function(CartState) _then) = _$CartStateCopyWithImpl;
@useResult
$Res call({
- bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime
+ bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime, AreaDetails? selectedArea
});
@@ -62,7 +62,7 @@ class _$CartStateCopyWithImpl<$Res>
/// Create a copy of CartState
/// with the given fields replaced by the non-null parameter values.
-@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? error = null,Object? productsWithQuantity = null,Object? isDelivery = null,Object? comment = null,Object? readyTime = null,}) {
+@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? error = null,Object? productsWithQuantity = null,Object? isDelivery = null,Object? comment = null,Object? readyTime = null,Object? selectedArea = freezed,}) {
return _then(_self.copyWith(
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
as bool,error: null == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
@@ -70,7 +70,8 @@ as AppError,productsWithQuantity: null == productsWithQuantity ? _self.productsW
as Map<int, ProductInCart>,isDelivery: null == isDelivery ? _self.isDelivery : isDelivery // ignore: cast_nullable_to_non_nullable
as bool,comment: null == comment ? _self.comment : comment // ignore: cast_nullable_to_non_nullable
as String,readyTime: null == readyTime ? _self.readyTime : readyTime // ignore: cast_nullable_to_non_nullable
-as String,
+as String,selectedArea: freezed == selectedArea ? _self.selectedArea : selectedArea // ignore: cast_nullable_to_non_nullable
+as AreaDetails?,
));
}
@@ -155,10 +156,10 @@ return $default(_that);case _:
/// }
/// ```
-@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime)? $default,{required TResult orElse(),}) {final _that = this;
+@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime, AreaDetails? selectedArea)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _CartState() when $default != null:
-return $default(_that.isLoading,_that.error,_that.productsWithQuantity,_that.isDelivery,_that.comment,_that.readyTime);case _:
+return $default(_that.isLoading,_that.error,_that.productsWithQuantity,_that.isDelivery,_that.comment,_that.readyTime,_that.selectedArea);case _:
return orElse();
}
@@ -176,10 +177,10 @@ return $default(_that.isLoading,_that.error,_that.productsWithQuantity,_that.isD
/// }
/// ```
-@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime) $default,) {final _that = this;
+@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime, AreaDetails? selectedArea) $default,) {final _that = this;
switch (_that) {
case _CartState():
-return $default(_that.isLoading,_that.error,_that.productsWithQuantity,_that.isDelivery,_that.comment,_that.readyTime);case _:
+return $default(_that.isLoading,_that.error,_that.productsWithQuantity,_that.isDelivery,_that.comment,_that.readyTime,_that.selectedArea);case _:
throw StateError('Unexpected subclass');
}
@@ -196,10 +197,10 @@ return $default(_that.isLoading,_that.error,_that.productsWithQuantity,_that.isD
/// }
/// ```
-@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime)? $default,) {final _that = this;
+@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime, AreaDetails? selectedArea)? $default,) {final _that = this;
switch (_that) {
case _CartState() when $default != null:
-return $default(_that.isLoading,_that.error,_that.productsWithQuantity,_that.isDelivery,_that.comment,_that.readyTime);case _:
+return $default(_that.isLoading,_that.error,_that.productsWithQuantity,_that.isDelivery,_that.comment,_that.readyTime,_that.selectedArea);case _:
return null;
}
@@ -211,7 +212,7 @@ return $default(_that.isLoading,_that.error,_that.productsWithQuantity,_that.isD
class _CartState extends CartState {
- const _CartState({this.isLoading = false, this.error = AppError.none, final Map<int, ProductInCart> productsWithQuantity = const {}, this.isDelivery = false, this.comment = "", this.readyTime = ""}): _productsWithQuantity = productsWithQuantity,super._();
+ const _CartState({this.isLoading = false, this.error = AppError.none, final Map<int, ProductInCart> productsWithQuantity = const {}, this.isDelivery = false, this.comment = "", this.readyTime = "", this.selectedArea}): _productsWithQuantity = productsWithQuantity,super._();
@override@JsonKey() final bool isLoading;
@@ -226,6 +227,7 @@ class _CartState extends CartState {
@override@JsonKey() final bool isDelivery;
@override@JsonKey() final String comment;
@override@JsonKey() final String readyTime;
+@override final AreaDetails? selectedArea;
/// Create a copy of CartState
/// with the given fields replaced by the non-null parameter values.
@@ -237,16 +239,16 @@ _$CartStateCopyWith<_CartState> get copyWith => __$CartStateCopyWithImpl<_CartSt
@override
bool operator ==(Object other) {
- return identical(this, other) || (other.runtimeType == runtimeType&&other is _CartState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other._productsWithQuantity, _productsWithQuantity)&&(identical(other.isDelivery, isDelivery) || other.isDelivery == isDelivery)&&(identical(other.comment, comment) || other.comment == comment)&&(identical(other.readyTime, readyTime) || other.readyTime == readyTime));
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is _CartState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.error, error) || other.error == error)&&const DeepCollectionEquality().equals(other._productsWithQuantity, _productsWithQuantity)&&(identical(other.isDelivery, isDelivery) || other.isDelivery == isDelivery)&&(identical(other.comment, comment) || other.comment == comment)&&(identical(other.readyTime, readyTime) || other.readyTime == readyTime)&&(identical(other.selectedArea, selectedArea) || other.selectedArea == selectedArea));
}
@override
-int get hashCode => Object.hash(runtimeType,isLoading,error,const DeepCollectionEquality().hash(_productsWithQuantity),isDelivery,comment,readyTime);
+int get hashCode => Object.hash(runtimeType,isLoading,error,const DeepCollectionEquality().hash(_productsWithQuantity),isDelivery,comment,readyTime,selectedArea);
@override
String toString() {
- return 'CartState(isLoading: $isLoading, error: $error, productsWithQuantity: $productsWithQuantity, isDelivery: $isDelivery, comment: $comment, readyTime: $readyTime)';
+ return 'CartState(isLoading: $isLoading, error: $error, productsWithQuantity: $productsWithQuantity, isDelivery: $isDelivery, comment: $comment, readyTime: $readyTime, selectedArea: $selectedArea)';
}
@@ -257,7 +259,7 @@ abstract mixin class _$CartStateCopyWith<$Res> implements $CartStateCopyWith<$Re
factory _$CartStateCopyWith(_CartState value, $Res Function(_CartState) _then) = __$CartStateCopyWithImpl;
@override @useResult
$Res call({
- bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime
+ bool isLoading, AppError error, Map<int, ProductInCart> productsWithQuantity, bool isDelivery, String comment, String readyTime, AreaDetails? selectedArea
});
@@ -274,7 +276,7 @@ class __$CartStateCopyWithImpl<$Res>
/// Create a copy of CartState
/// with the given fields replaced by the non-null parameter values.
-@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? error = null,Object? productsWithQuantity = null,Object? isDelivery = null,Object? comment = null,Object? readyTime = null,}) {
+@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? error = null,Object? productsWithQuantity = null,Object? isDelivery = null,Object? comment = null,Object? readyTime = null,Object? selectedArea = freezed,}) {
return _then(_CartState(
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
as bool,error: null == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
@@ -282,7 +284,8 @@ as AppError,productsWithQuantity: null == productsWithQuantity ? _self._products
as Map<int, ProductInCart>,isDelivery: null == isDelivery ? _self.isDelivery : isDelivery // ignore: cast_nullable_to_non_nullable
as bool,comment: null == comment ? _self.comment : comment // ignore: cast_nullable_to_non_nullable
as String,readyTime: null == readyTime ? _self.readyTime : readyTime // ignore: cast_nullable_to_non_nullable
-as String,
+as String,selectedArea: freezed == selectedArea ? _self.selectedArea : selectedArea // ignore: cast_nullable_to_non_nullable
+as AreaDetails?,
));
}
diff --git a/concierge/lib/concierge_app.dart b/concierge/lib/concierge_app.dart
index 9ca6e1a3..d19522d1 100644
--- a/concierge/lib/concierge_app.dart
+++ b/concierge/lib/concierge_app.dart
@@ -95,7 +95,11 @@ class ConciergeApp extends StatelessWidget {
child: MultiBlocProvider(
providers: [
BlocProvider(
- create: (context) => HotelOverviewPageCubit(context.read(), hotelCode: hotelCode),
+ create: (context) => HotelOverviewPageCubit(
+ context.read(),
+ context.read(),
+ hotelCode: hotelCode,
+ ),
),
],
child: Builder(
diff --git a/concierge/lib/domain/repositories/property_repository.dart b/concierge/lib/domain/repositories/property_repository.dart
index 624fa865..aa4839e5 100644
--- a/concierge/lib/domain/repositories/property_repository.dart
+++ b/concierge/lib/domain/repositories/property_repository.dart
@@ -32,8 +32,6 @@ class PropertyRepository {
required String locationCode,
required bool isDelivery,
required String readyTime,
- required String fullName,
- required int customerId,
required String comment,
}) async {
final body = {
@@ -43,10 +41,7 @@ class PropertyRepository {
"delivery": isDelivery,
"requested_delivery_time": readyTime.isEmpty ? "ASAP" : readyTime,
"payment_type": "WAITER",
- "full_name": fullName,
- "customer_id": customerId,
- "customer_name": "King",
- "customer_comment": "",
+ "customer_comment": comment,
"order_type": "PRODUCT",
"ga_client_id": "GA1.2.1247178081.1736166148",
};
diff --git a/concierge/lib/presentation/app/cart_cubit.dart b/concierge/lib/presentation/app/cart_cubit.dart
index a5d30240..6a696c82 100644
--- a/concierge/lib/presentation/app/cart_cubit.dart
+++ b/concierge/lib/presentation/app/cart_cubit.dart
@@ -1,3 +1,4 @@
+import 'package:concierge/data/remote/models/area_details.dart';
import 'package:concierge/data/remote/models/product.dart';
import 'package:concierge/domain/models/data_state.dart';
import 'package:concierge/presentation/app/concierge_cubit.dart';
@@ -44,6 +45,10 @@ class CartCubit extends BaseCubit<CartState> {
safeEmit(state.copyWith(readyTime: time));
}
+ void updateSelectedArea(AreaDetails area) {
+ safeEmit(state.copyWith(selectedArea: area, productsWithQuantity: {}));
+ }
+
int get totalItems {
if (state.productsWithQuantity.isEmpty) return 0;
return state.productsWithQuantity.values
@@ -77,6 +82,7 @@ abstract class CartState with _$CartState {
@Default(false) bool isDelivery,
@Default("") String comment,
@Default("") String readyTime,
+ AreaDetails? selectedArea,
}) = _CartState;
const CartState._();
diff --git a/concierge/lib/presentation/screens/confirm_order/widgets/confirm_order_product_list_tile.dart b/concierge/lib/presentation/screens/confirm_order/widgets/confirm_order_product_list_tile.dart
index b9d797a0..bab9ee0c 100644
--- a/concierge/lib/presentation/screens/confirm_order/widgets/confirm_order_product_list_tile.dart
+++ b/concierge/lib/presentation/screens/confirm_order/widgets/confirm_order_product_list_tile.dart
@@ -5,7 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gap/gap.dart';
class ConfirmOrderProductListTile extends StatelessWidget {
- const ConfirmOrderProductListTile({super.key, required this.product});
+ const ConfirmOrderProductListTile({super.key, required this.product});
final Product product;
diff --git a/concierge/lib/presentation/screens/hotel_overview_page/bloc/hotel_overview_page_cubit.dart b/concierge/lib/presentation/screens/hotel_overview_page/bloc/hotel_overview_page_cubit.dart
index 01acf044..b1d25acf 100644
--- a/concierge/lib/presentation/screens/hotel_overview_page/bloc/hotel_overview_page_cubit.dart
+++ b/concierge/lib/presentation/screens/hotel_overview_page/bloc/hotel_overview_page_cubit.dart
@@ -1,15 +1,20 @@
import 'package:concierge/domain/models/app_error.dart';
import 'package:concierge/domain/models/data_state.dart';
import 'package:concierge/domain/repositories/property_repository.dart';
+import 'package:concierge/presentation/app/cart_cubit.dart';
import 'package:concierge/presentation/base/base_cubit.dart';
import 'package:concierge/presentation/screens/hotel_overview_page/bloc/hotel_overview_page_state.dart';
class HotelOverviewPageCubit extends BaseCubit<HotelOverviewPageState> {
final String hotelCode;
final PropertyRepository _propertyRepository;
+ final CartCubit _cartCubit;
- HotelOverviewPageCubit(this._propertyRepository, {required this.hotelCode})
- : super(const HotelOverviewPageState()) {
+ HotelOverviewPageCubit(
+ this._propertyRepository,
+ this._cartCubit, {
+ required this.hotelCode,
+ }) : super(const HotelOverviewPageState()) {
init();
}
@@ -40,6 +45,9 @@ class HotelOverviewPageCubit extends BaseCubit<HotelOverviewPageState> {
_updateAreaDataState(areaId, DataState.loading);
final response = await _propertyRepository.getArea(areaId);
_updateAreaDataState(areaId, DataState.success(response));
+ if (state.selectedAreaId == areaId) {
+ _cartCubit.updateSelectedArea(response);
+ }
} catch (e, st) {
handleError(e, st);
_updateAreaDataState(areaId, DataState.failure(AppError.unknown(e.toString())));
diff --git a/concierge/lib/presentation/screens/hotel_overview_page/hotel_overview_page_route.dart b/concierge/lib/presentation/screens/hotel_overview_page/hotel_overview_page_route.dart
index 1c04a124..5673df61 100644
--- a/concierge/lib/presentation/screens/hotel_overview_page/hotel_overview_page_route.dart
+++ b/concierge/lib/presentation/screens/hotel_overview_page/hotel_overview_page_route.dart
@@ -21,7 +21,11 @@ class HotelOverviewPageRoute extends GoRouteData with $HotelOverviewPageRoute {
return slideUpTransition(
state: state,
child: BlocProvider(
- create: (context) => HotelOverviewPageCubit(context.read(), hotelCode: hotelCode),
+ create: (context) => HotelOverviewPageCubit(
+ context.read(),
+ context.read(),
+ hotelCode: hotelCode,
+ ),
child: HotelOverviewPageScreen(),
),
);
diff --git a/concierge/lib/presentation/screens/hotel_overview_page/widgets/cart_app_bar.dart b/concierge/lib/presentation/screens/hotel_overview_page/widgets/cart_app_bar.dart
index d2a5bce2..983f5f8a 100644
--- a/concierge/lib/presentation/screens/hotel_overview_page/widgets/cart_app_bar.dart
+++ b/concierge/lib/presentation/screens/hotel_overview_page/widgets/cart_app_bar.dart
@@ -57,7 +57,10 @@ class CartAppBar extends StatelessWidget {
onPressed: () {
ReviewOrderRoute().push(context);
},
- icon: Icon(Icons.keyboard_arrow_up),
+ icon: Icon(
+ Icons.keyboard_arrow_up,
+ color: Colors.white,
+ ),
),
],
),
diff --git a/concierge/lib/presentation/screens/payment/bloc/payment_cubit.dart b/concierge/lib/presentation/screens/payment/bloc/payment_cubit.dart
index 721a1ae7..5ca61a43 100644
--- a/concierge/lib/presentation/screens/payment/bloc/payment_cubit.dart
+++ b/concierge/lib/presentation/screens/payment/bloc/payment_cubit.dart
@@ -29,11 +29,10 @@ class PaymentCubit extends BaseCubit<PaymentState> {
],
},
);
+ final area = _cartCubit.state.selectedArea!;
final response = await _propertyRepository.createOrder(
products: products.toList(),
- areaId: 0,
- customerId: 0,
- fullName: "",
+ areaId: area.id,
isDelivery: _cartCubit.state.isDelivery,
locationCode: "_cartCubit.state",
readyTime: _cartCubit.state.readyTime,
diff --git a/concierge/lib/presentation/screens/receipt/bloc/receipt_cubit.dart b/concierge/lib/presentation/screens/receipt/bloc/receipt_cubit.dart
index cec1eb70..f54f869f 100644
--- a/concierge/lib/presentation/screens/receipt/bloc/receipt_cubit.dart
+++ b/concierge/lib/presentation/screens/receipt/bloc/receipt_cubit.dart
@@ -1,3 +1,4 @@
+import 'package:concierge/data/remote/models/product.dart';
import 'package:concierge/presentation/base/base_cubit.dart';
import 'package:concierge/presentation/screens/receipt/bloc/receipt_state.dart';
@@ -6,7 +7,32 @@ class ReceiptCubit extends BaseCubit<ReceiptState> {
init();
}
- Future<void> init() async {
-
- }
-}
\ No newline at end of file
+ Product get product => Product.fromJson({
+ "id": 1603,
+ "title": "Pepsi",
+ "sub_title": "25 cl",
+ "body": "<div>Pepsi er en velsmagende sodavand med sukker.</div>",
+ "allergies": "",
+ "price": 43,
+ "price_comwell_club": null,
+ "estimated_delivery_time": "15 min.",
+ "is_new": 0,
+ "images": [
+ {
+ "url":
+ "https://admin-stage.concierge.comwell.com/storage/media/2515/Comwell_Consierge_RAIS1706.jpg",
+ "preload":
+ "https://admin-stage.concierge.comwell.com/storage/media/2515/conversi ons/Comwell_Consierge_RAIS1706-preload.jpg",
+ "thumbnail":
+ "https://admin-stage.concierge.comwell.com/storage/media/2515/conversions/Comwell_Consierge_RAIS1706-thumbnail.jpg",
+ "product_hero":
+ "https://admin-stage.concierge.comwell.com/storage/media/2515/conversions/Comwell_Consierge_RAIS1706-product_hero.jpg",
+ "alt": "Comwell_Consierge_RAIS1706.jpg",
+ },
+ ],
+ "options": [],
+ "type": "PRODUCT",
+ });
+
+ Future<void> init() async {}
+}
diff --git a/concierge/lib/presentation/screens/receipt/receipt_screen.dart b/concierge/lib/presentation/screens/receipt/receipt_screen.dart
index 74c14557..a12731b6 100644
--- a/concierge/lib/presentation/screens/receipt/receipt_screen.dart
+++ b/concierge/lib/presentation/screens/receipt/receipt_screen.dart
@@ -1,7 +1,11 @@
+import 'package:concierge/presentation/screens/receipt/widgets/receipt_action_bar.dart';
+import 'package:concierge/presentation/screens/receipt/widgets/receipt_card.dart';
+import 'package:concierge/presentation/theme/app_colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:concierge/presentation/screens/receipt/bloc/receipt_cubit.dart';
import 'package:concierge/presentation/screens/receipt/bloc/receipt_state.dart';
+import 'package:gap/gap.dart';
class ReceiptScreen extends StatelessWidget {
const ReceiptScreen({super.key});
@@ -14,24 +18,44 @@ class ReceiptScreen extends StatelessWidget {
return MultiBlocListener(
listeners: [
BlocListener<ReceiptCubit, ReceiptState>(
- listenWhen: (prev, curr) =>
- prev.isLoading && curr.error.isError,
- listener: (context, state) {
- },
- )
+ listenWhen: (prev, curr) => prev.isLoading && curr.error.isError,
+ listener: (context, state) {},
+ ),
],
child: Scaffold(
- appBar: AppBar(),
+ backgroundColor: AppColors.sandColor,
+ bottomNavigationBar: ReceiptActionBar(),
body: Center(
child: Column(
children: [
- Text("Receipt"),
- TextButton(
- onPressed: () {
-
- },
- child: Text("OK"),
- )
+ SafeArea(
+ child: Row(
+ children: [
+ Spacer(),
+ CloseButton(
+ color: Colors.black,
+ style: ButtonStyle(backgroundColor: WidgetStatePropertyAll(Colors.white)),
+ ),
+ ],
+ ),
+ ),
+ Gap(32),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 50.0),
+ child: ReceiptCard(),
+ ),
+ Gap(32),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 100),
+ child: Text(
+ "Kontakt Comwells personale for ændringer på tlf. nr. 42 43 44 45",
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ fontSize: 12,
+ color: Colors.white.withAlpha((0.65 * 255).toInt()),
+ ),
+ ),
+ ),
],
),
),
@@ -39,5 +63,5 @@ class ReceiptScreen extends StatelessWidget {
);
},
);
- }
-}
\ No newline at end of file
+ }
+}
diff --git a/concierge/lib/presentation/screens/receipt/widgets/receipt_action_bar.dart b/concierge/lib/presentation/screens/receipt/widgets/receipt_action_bar.dart
new file mode 100644
index 00000000..e1367ecd
--- /dev/null
+++ b/concierge/lib/presentation/screens/receipt/widgets/receipt_action_bar.dart
@@ -0,0 +1,25 @@
+import 'package:flutter/material.dart';
+
+class ReceiptActionBar extends StatelessWidget {
+ const ReceiptActionBar({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return SafeArea(
+ child: Padding(
+ padding: EdgeInsets.all(16),
+ child: TextButton(
+ onPressed: () {},
+ style: ButtonStyle(
+ minimumSize: WidgetStatePropertyAll(Size(0, 50)),
+ backgroundColor: WidgetStatePropertyAll(Colors.white),
+ ),
+ child: Text(
+ "Gå til forsiden",
+ style: TextStyle(color: Colors.black),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/concierge/lib/presentation/screens/receipt/widgets/receipt_card.dart b/concierge/lib/presentation/screens/receipt/widgets/receipt_card.dart
new file mode 100644
index 00000000..7e681229
--- /dev/null
+++ b/concierge/lib/presentation/screens/receipt/widgets/receipt_card.dart
@@ -0,0 +1,90 @@
+import 'package:concierge/presentation/app/cart_cubit.dart';
+import 'package:concierge/presentation/screens/confirm_order/widgets/confirm_order_product_list_tile.dart';
+import 'package:concierge/presentation/widgets/padded_column.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:gap/gap.dart';
+
+class ReceiptCard extends StatelessWidget {
+ const ReceiptCard({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final cubit = context.read<CartCubit>();
+
+ return Container(
+ height: 500,
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(16),
+ ),
+ clipBehavior: Clip.antiAlias,
+ child: SingleChildScrollView(
+ child: Column(
+ children: [
+ SizedBox(
+ height: 200,
+ child: Stack(
+ alignment: Alignment.topLeft,
+ children: [
+ Image.network(cubit.products.first.images.first.url),
+ Padding(
+ padding: EdgeInsets.all(12),
+ child: Text(
+ "Bestilling til værelse 108",
+ style: TextStyle(fontSize: 20, color: Colors.white),
+ ),
+ ),
+ ],
+ ),
+ ),
+ PaddedColumn(
+ padding: EdgeInsets.symmetric(horizontal: 12),
+ children: [
+ const Gap(16),
+ Text(
+ "Status på bestilling",
+ style: TextStyle(fontSize: 14, color: Colors.grey),
+ ),
+ const Gap(8),
+ Text("Din bestilling leveres"),
+ const Gap(16),
+ Text(
+ "Bestilling klar",
+ style: TextStyle(fontSize: 14, color: Colors.grey),
+ ),
+ const Gap(4),
+ Text("14:55"),
+ const Gap(16),
+ Row(
+ children: [
+ Icon(
+ Icons.restaurant_outlined,
+ color: Colors.grey,
+ size: 16,
+ ),
+ Gap(4),
+ Text(
+ "Din bestilling",
+ style: TextStyle(fontSize: 14, color: Colors.grey),
+ ),
+ ],
+ ),
+ ...buildOrder(context),
+ ],
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ Iterable<Widget> buildOrder(BuildContext context) sync* {
+ final cubit = context.read<CartCubit>();
+ yield Divider(color: Colors.grey.shade300);
+ for (final product in cubit.products) {
+ yield ConfirmOrderProductListTile(product: product);
+ yield Divider(color: Colors.grey.shade300);
+ }
+ }
+}