6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 638da3ab
Changed files
.../lib/hotel_information/components/address.dart | 35 ++++++ .../lib/hotel_information/components/email.dart | 21 ++++ .../components/hotel_information_menu.dart | 59 ----------- .../components/opening_hours.dart | 27 +++++ .../hotel_information/components/page_title.dart | 13 +++ .../components/parking_facility_page.dart | 73 ------------- .../hotel_information/components/phone_number.dart | 21 ++++ .../components/practical_information.dart | 41 +++++++ .../components/restaurant_page.dart | 115 -------------------- .../components/spa_booking_link.dart | 11 ++ .../components/spa_facility_page.dart | 116 -------------------- .../components/structured_text.dart | 29 +++++ .../lib/hotel_information/models/restaurant.dart | 1 + .../pages/hotel_information_menu.dart | 59 +++++++++++ .../pages/parking_facility_page.dart | 77 ++++++++++++++ .../hotel_information/pages/restaurant_page.dart | 102 ++++++++++++++++++ .../hotel_information/pages/spa_facility_page.dart | 118 +++++++++++++++++++++ comwell_key_app/lib/main.dart | 4 +- comwell_key_app/lib/routing/app_router.dart | 8 +- 19 files changed, 560 insertions(+), 370 deletions(-)
Diff
diff --git a/comwell_key_app/lib/hotel_information/components/address.dart b/comwell_key_app/lib/hotel_information/components/address.dart
new file mode 100644
index 00000000..dd09f7dc
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/components/address.dart
@@ -0,0 +1,35 @@
+import 'package:comwell_key_app/hotel_information/components/maps_bottom_modal.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+class Address extends StatelessWidget {
+ final String address;
+ const Address({super.key, required this.address});
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text("restaurant_page_address".tr(),
+ style: theme.textTheme.headlineMedium),
+ const SizedBox(width: 10),
+ GestureDetector(
+ onTap: () => MapsBottomModal.show(context, address),
+ child: Text(
+ address,
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: sandColor,
+ decoration: TextDecoration.underline,
+ decorationColor: sandColor,
+ ),
+ ),
+ ),
+ const SizedBox(height: 20),
+ ],
+ );
+ }
+}
diff --git a/comwell_key_app/lib/hotel_information/components/email.dart b/comwell_key_app/lib/hotel_information/components/email.dart
new file mode 100644
index 00000000..8c6be29c
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/components/email.dart
@@ -0,0 +1,21 @@
+import 'package:comwell_key_app/hotel_information/components/contact_hotel_button.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class Email extends StatelessWidget {
+ final String email;
+ const Email({super.key, required this.email});
+
+ @override
+ Widget build(BuildContext context) {
+ return ContactHotelButton(
+ title: "restaurant_page_send_email".tr(),
+ subtitle: email,
+ iconPath: "assets/icons/ic_send.svg",
+ onClick: () {
+ launchUrl(Uri.parse("mailto:$email"));
+ },
+ );
+ }
+}
\ No newline at end of file
diff --git a/comwell_key_app/lib/hotel_information/components/hotel_information_menu.dart b/comwell_key_app/lib/hotel_information/components/hotel_information_menu.dart
deleted file mode 100644
index 43cbefd3..00000000
--- a/comwell_key_app/lib/hotel_information/components/hotel_information_menu.dart
+++ /dev/null
@@ -1,59 +0,0 @@
-import 'package:comwell_key_app/hotel_information/components/image_widget.dart';
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:go_router/go_router.dart';
-
-import '../../routing/app_routes.dart';
-import '../cubit/hotel_information_cubit.dart';
-import 'hotel_information_list_tile.dart';
-
-class HotelInformationMenu extends StatelessWidget {
- const HotelInformationMenu({super.key});
-
- @override
- Widget build(BuildContext context) {
- final cubit = context.read<HotelInformationCubit>();
- final hotel = cubit.hotel;
- final height = MediaQuery.of(context).size.height;
- return Column(
- children: [
- ImageWidget(image: hotel.image),
- Expanded(
- child: SingleChildScrollView(
- child: Padding(
- padding: const EdgeInsets.all(16.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(hotel.hotelName,
- style: Theme.of(context).textTheme.headlineLarge),
- const SizedBox(height: 16),
- ...hotel.facilities.map((facility) {
- return Padding(
- padding: const EdgeInsets.only(bottom: 6.0),
- child: HotelInformationListTile(
- iconPath: facility.iconPath,
- title: facility.title,
- onClick: () {
- context.pushNamed(
- "${AppRoutes.hotelInformation.name}/${facility.routeName}",
- extra: facility);
- },
- ),
- );
- }),
- HotelInformationListTile(
- iconPath: "assets/icons/ic_info.svg",
- title: "hotel_information_page_menu_other_info_title".tr(),
- onClick: cubit.onMoreInformationClicked,
- ),
- ],
- ),
- ),
- ),
- ),
- ],
- );
- }
-}
diff --git a/comwell_key_app/lib/hotel_information/components/opening_hours.dart b/comwell_key_app/lib/hotel_information/components/opening_hours.dart
new file mode 100644
index 00000000..63e48156
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/components/opening_hours.dart
@@ -0,0 +1,27 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+class OpeningHours extends StatelessWidget {
+ final String openingHours;
+ const OpeningHours({super.key, required this.openingHours});
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ "restaurant_page_opening_hours".tr(),
+ style: theme.textTheme.headlineMedium,
+ ),
+ Text(
+ openingHours,
+ style: theme.textTheme.bodySmall,
+ ),
+ const SizedBox(height: 20),
+ ],
+ );
+ }
+}
diff --git a/comwell_key_app/lib/hotel_information/components/page_title.dart b/comwell_key_app/lib/hotel_information/components/page_title.dart
new file mode 100644
index 00000000..0ea60658
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/components/page_title.dart
@@ -0,0 +1,13 @@
+import 'package:flutter/material.dart';
+
+class PageTitle extends StatelessWidget {
+ final String title;
+ const PageTitle({super.key, required this.title});
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+
+ return Text(title, style: theme.textTheme.headlineLarge);
+ }
+}
\ No newline at end of file
diff --git a/comwell_key_app/lib/hotel_information/components/parking_facility_page.dart b/comwell_key_app/lib/hotel_information/components/parking_facility_page.dart
deleted file mode 100644
index b49deb22..00000000
--- a/comwell_key_app/lib/hotel_information/components/parking_facility_page.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-import 'package:comwell_key_app/hotel_information/components/image_widget.dart';
-import 'package:comwell_key_app/hotel_information/models/parking_info.dart';
-import 'package:flutter/material.dart';
-
-class ParkingFacilityPage extends StatelessWidget {
- final ParkingInfo parkingInfo;
-
- const ParkingFacilityPage({super.key, required this.parkingInfo});
-
- @override
- Widget build(BuildContext context) {
- final theme = Theme.of(context);
-
- return Scaffold(
- backgroundColor: Colors.white,
- body: Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const ImageWidget(image: 'assets/images/parking.png'),
- Expanded(
- child: SingleChildScrollView(
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- const SizedBox(height: 26),
- Text(
- parkingInfo.title,
- style: theme.textTheme.headlineLarge,
- ),
- const SizedBox(height: 20),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
- children: parkingInfo.structuredTextBlocks.map((block) {
- return Padding(
- padding: const EdgeInsets.only(bottom: 16.0),
- child: Text(
- block.data,
- style: block.type == "headerBlock"
- ? theme.textTheme.headlineSmall
- : theme.textTheme.bodySmall?.copyWith(
- color: Colors.black.withValues(alpha: 0.65),
- ),
- ),
- );
- }).toList(),
- ),
- if (parkingInfo.electricCharging) ...[
- const SizedBox(height: 40),
- Text(
- parkingInfo.electricChargingTitle,
- style: theme.textTheme.headlineMedium,
- ),
- const SizedBox(height: 20),
- Text(
- parkingInfo.electricChargingDescription,
- style: theme.textTheme.bodySmall,
- ),
- ],
- ],
- ),
- ),
- ),
- ),
- ],
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/hotel_information/components/phone_number.dart b/comwell_key_app/lib/hotel_information/components/phone_number.dart
new file mode 100644
index 00000000..99419415
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/components/phone_number.dart
@@ -0,0 +1,21 @@
+import 'package:comwell_key_app/hotel_information/components/contact_hotel_button.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class PhoneNumber extends StatelessWidget {
+ final String phoneNumber;
+ const PhoneNumber({super.key, required this.phoneNumber});
+
+ @override
+ Widget build(BuildContext context) {
+ return ContactHotelButton(
+ title: "call_us".tr(),
+ subtitle: phoneNumber,
+ iconPath: "assets/icons/ic_telephone.svg",
+ onClick: () {
+ launchUrl(Uri.parse("tel:$phoneNumber"));
+ },
+ );
+ }
+}
diff --git a/comwell_key_app/lib/hotel_information/components/practical_information.dart b/comwell_key_app/lib/hotel_information/components/practical_information.dart
new file mode 100644
index 00000000..569977dd
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/components/practical_information.dart
@@ -0,0 +1,41 @@
+import 'package:comwell_key_app/hotel_information/components/maps_bottom_modal.dart';
+import 'package:comwell_key_app/hotel_information/models/restaurant.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+class PracticalInformation extends StatelessWidget {
+ final Restaurant restaurant;
+ const PracticalInformation({super.key, required this.restaurant});
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+
+ return Column(
+ children: [
+ const SizedBox(height: 40),
+ Text(
+ "restaurant_page_practical_information".tr(),
+ style: theme.textTheme.headlineLarge,
+ ),
+ const SizedBox(height: 20),
+ Text(
+ "restaurant_page_address".tr(),
+ style: theme.textTheme.headlineMedium,
+ ),
+ GestureDetector(
+ onTap: () => MapsBottomModal.show(context, restaurant.address),
+ child: Text(
+ restaurant.address,
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: sandColor,
+ decoration: TextDecoration.underline,
+ decorationColor: sandColor,
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/comwell_key_app/lib/hotel_information/components/restaurant_page.dart b/comwell_key_app/lib/hotel_information/components/restaurant_page.dart
deleted file mode 100644
index b41faf90..00000000
--- a/comwell_key_app/lib/hotel_information/components/restaurant_page.dart
+++ /dev/null
@@ -1,115 +0,0 @@
-import 'package:comwell_key_app/hotel_information/components/contact_hotel_button.dart';
-import 'package:comwell_key_app/hotel_information/components/image_widget.dart';
-import 'package:comwell_key_app/hotel_information/components/maps_bottom_modal.dart';
-import 'package:comwell_key_app/hotel_information/models/restaurant.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:url_launcher/url_launcher.dart';
-
-class RestaurantPage extends StatelessWidget {
- final Restaurant restaurant;
-
- const RestaurantPage({super.key, required this.restaurant});
-
- @override
- Widget build(BuildContext context) {
- final theme = Theme.of(context);
-
- return Scaffold(
- backgroundColor: Colors.white,
- body: Column(
- children: [
- ImageWidget(image: restaurant.image),
- Expanded(
- child: SingleChildScrollView(
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const SizedBox(height: 26),
- Text(
- restaurant.title,
- style: theme.textTheme.headlineLarge,
- ),
- const SizedBox(height: 20),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: restaurant.structuredTextBlocks.map((block) {
- return Padding(
- padding: const EdgeInsets.only(bottom: 16.0),
- child: Text(
- block.data,
- style: block.type == "headerBlock"
- ? theme.textTheme.headlineSmall
- : theme.textTheme.bodySmall?.copyWith(
- color: Colors.black.withValues(alpha: 0.65),
- ),
- ),
- );
- }).toList(),
- ),
- const SizedBox(height: 40),
- Text(
- "restaurant_page_practical_information".tr(),
- style: theme.textTheme.headlineLarge,
- ),
- const SizedBox(height: 20),
- Text(
- "restaurant_page_address".tr(),
- style: theme.textTheme.headlineMedium,
- ),
- GestureDetector(
- onTap: () =>
- MapsBottomModal.show(context, restaurant.address),
- child: Text(
- restaurant.address,
- style: theme.textTheme.bodySmall?.copyWith(
- color: sandColor,
- decoration: TextDecoration.underline,
- decorationColor: sandColor,
- ),
- ),
- ),
- const SizedBox(height: 20),
- Text(
- "restaurant_page_opening_hours".tr(),
- style: theme.textTheme.headlineMedium,
- ),
- Text(
- restaurant.openingHours,
- style: theme.textTheme.bodySmall,
- ),
- const SizedBox(height: 40),
- Text(
- "restaurant_page_book_table".tr(),
- style: theme.textTheme.headlineMedium,
- ),
- const SizedBox(height: 20),
- ContactHotelButton(
- title: "call_us".tr(),
- subtitle: restaurant.phoneNumber,
- iconPath: "assets/icons/ic_telephone.svg",
- onClick: () {
- launchUrl(Uri.parse("tel:${restaurant.phoneNumber}"));
- }),
- const SizedBox(height: 6),
- ContactHotelButton(
- title: "restaurant_page_send_email".tr(),
- subtitle: restaurant.email,
- iconPath: "assets/icons/ic_send.svg",
- onClick: () {
- launchUrl(Uri.parse("mailto:${restaurant.email}"));
- }),
- const SizedBox(height: 100)
- ],
- ),
- ),
- ),
- ),
- ],
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/hotel_information/components/spa_booking_link.dart b/comwell_key_app/lib/hotel_information/components/spa_booking_link.dart
new file mode 100644
index 00000000..23d5db62
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/components/spa_booking_link.dart
@@ -0,0 +1,11 @@
+import 'package:flutter/material.dart';
+
+class SpaBookingLink extends StatelessWidget {
+ final String link;
+ const SpaBookingLink({super.key, required this.link});
+
+ @override
+ Widget build(BuildContext context) {
+ return const Placeholder();
+ }
+}
\ No newline at end of file
diff --git a/comwell_key_app/lib/hotel_information/components/spa_facility_page.dart b/comwell_key_app/lib/hotel_information/components/spa_facility_page.dart
deleted file mode 100644
index a12b2e17..00000000
--- a/comwell_key_app/lib/hotel_information/components/spa_facility_page.dart
+++ /dev/null
@@ -1,116 +0,0 @@
-import 'package:comwell_key_app/hotel_information/components/image_widget.dart';
-import 'package:comwell_key_app/hotel_information/cubit/hotel_information_cubit.dart';
-import 'package:comwell_key_app/hotel_information/models/spa.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-class SpaFacilityPage extends StatelessWidget {
- final Spa spa;
- const SpaFacilityPage({super.key, required this.spa});
-
- @override
- Widget build(BuildContext context) {
- final cubit = context.read<HotelInformationCubit>();
- final isLoading = cubit.state.spaButtonIsLoading;
- final theme = Theme.of(context);
-
- return Scaffold(
- backgroundColor: Colors.white,
- bottomSheet: Builder(builder: (context) {
- return Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- const Divider(
- color: colorDivider,
- height: 0,
- ),
- Row(
- children: [
- Expanded(
- child: Container(
- color: Colors.white,
- child: Padding(
- padding: const EdgeInsets.all(16.0),
- child: ElevatedButton(
- onPressed: isLoading
- ? null
- : cubit.onBookSpaClicked,
- style: ButtonStyle(
- backgroundColor:
- WidgetStateProperty.resolveWith((states) {
- if (states.contains(WidgetState.disabled)) {
- return Colors.grey;
- }
- return sandColor[80];
- }),
- foregroundColor:
- const WidgetStatePropertyAll(Colors.white)),
- child: Padding(
- padding: const EdgeInsets.symmetric(vertical: 16.0),
- child: Builder(builder: (context) {
- if (isLoading) {
- return const CircularProgressIndicator();
- }
- return Text(
- "hotel_information_page_spa_button".tr(),
- style: theme.textTheme.bodyLarge?.copyWith(
- color: Colors.white,
- fontWeight: FontWeight.bold,
- ),
- );
- }),
- ),
- ),
- ),
- ),
- ),
- ],
- ),
- ],
- );
- }),
- body: Column(
- children: [
- ImageWidget(image: spa.image),
- Expanded(
- child: SingleChildScrollView(
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const SizedBox(height: 26),
- Text(
- spa.title,
- style: theme.textTheme.headlineLarge,
- ),
- const SizedBox(height: 20),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: spa.structuredTextBlocks.map((block) {
- return Padding(
- padding: const EdgeInsets.only(bottom: 16.0),
- child: Text(
- block.data,
- style: block.type == "headerBlock"
- ? theme.textTheme.headlineMedium
- : theme.textTheme.bodySmall?.copyWith(
- color: Colors.black.withValues(alpha: 0.65),
- ),
- ),
- );
- }).toList(),
- ),
- const SizedBox(height: 100),
- ],
- ),
- ),
- ),
- ),
- ],
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/hotel_information/components/structured_text.dart b/comwell_key_app/lib/hotel_information/components/structured_text.dart
new file mode 100644
index 00000000..5a5b3962
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/components/structured_text.dart
@@ -0,0 +1,29 @@
+import 'package:comwell_key_app/hotel_information/models/structured_text.dart';
+import 'package:flutter/material.dart';
+
+class StructuredText extends StatelessWidget {
+ final List<StructuredTextBlock> blocks;
+ const StructuredText({super.key, required this.blocks});
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: blocks.map((block) {
+ return Padding(
+ padding: const EdgeInsets.only(bottom: 16.0),
+ child: Text(
+ block.data,
+ style: block.type == "headerBlock"
+ ? theme.textTheme.headlineMedium
+ : theme.textTheme.bodySmall?.copyWith(
+ color: Colors.black.withValues(alpha: 0.65),
+ ),
+ ),
+ );
+ }).toList(),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/hotel_information/models/restaurant.dart b/comwell_key_app/lib/hotel_information/models/restaurant.dart
index f645ff37..8811ebab 100644
--- a/comwell_key_app/lib/hotel_information/models/restaurant.dart
+++ b/comwell_key_app/lib/hotel_information/models/restaurant.dart
@@ -5,6 +5,7 @@ import 'package:json_annotation/json_annotation.dart';
part '../../.generated/hotel_information/models/restaurant.g.dart';
+
@JsonSerializable()
class Restaurant extends Facility {
final String image;
diff --git a/comwell_key_app/lib/hotel_information/pages/hotel_information_menu.dart b/comwell_key_app/lib/hotel_information/pages/hotel_information_menu.dart
new file mode 100644
index 00000000..bc9c2428
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/pages/hotel_information_menu.dart
@@ -0,0 +1,59 @@
+import 'package:comwell_key_app/hotel_information/components/image_widget.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:go_router/go_router.dart';
+
+import '../../routing/app_routes.dart';
+import '../cubit/hotel_information_cubit.dart';
+import '../components/hotel_information_list_tile.dart';
+
+class HotelInformationMenu extends StatelessWidget {
+ const HotelInformationMenu({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final cubit = context.read<HotelInformationCubit>();
+ final hotel = cubit.hotel;
+
+ return Column(
+ children: [
+ ImageWidget(image: hotel.image),
+ Expanded(
+ child: SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(hotel.hotelName,
+ style: Theme.of(context).textTheme.headlineLarge),
+ const SizedBox(height: 16),
+ ...hotel.facilities.map((facility) {
+ return Padding(
+ padding: const EdgeInsets.only(bottom: 6.0),
+ child: HotelInformationListTile(
+ iconPath: facility.iconPath,
+ title: facility.title,
+ onClick: () {
+ context.pushNamed(
+ "${AppRoutes.hotelInformation.name}/${facility.routeName}",
+ extra: facility);
+ },
+ ),
+ );
+ }),
+ HotelInformationListTile(
+ iconPath: "assets/icons/ic_info.svg",
+ title: "hotel_information_page_menu_other_info_title".tr(),
+ onClick: cubit.onMoreInformationClicked,
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/comwell_key_app/lib/hotel_information/pages/parking_facility_page.dart b/comwell_key_app/lib/hotel_information/pages/parking_facility_page.dart
new file mode 100644
index 00000000..04ba7884
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/pages/parking_facility_page.dart
@@ -0,0 +1,77 @@
+import 'package:comwell_key_app/hotel_information/components/image_widget.dart';
+import 'package:comwell_key_app/hotel_information/components/structured_text.dart';
+import 'package:comwell_key_app/hotel_information/models/parking_info.dart';
+import 'package:flutter/material.dart';
+
+class ParkingFacilityPage extends StatelessWidget {
+ final ParkingInfo parkingInfo;
+
+ const ParkingFacilityPage({super.key, required this.parkingInfo});
+
+ List<Widget> _buildDynamicContent(BuildContext context) {
+ final theme = Theme.of(context);
+ final Map<String, dynamic> parkingData = parkingInfo.toJson();
+ final List<Widget> widgets = [];
+
+ parkingData.forEach((key, value) {
+ switch (key) {
+ case 'title':
+ widgets.add(Text(
+ value as String,
+ style: theme.textTheme.headlineLarge,
+ ));
+ widgets.add(const SizedBox(height: 20));
+ break;
+
+ case 'structuredText':
+ widgets.add(StructuredText(blocks: parkingInfo.structuredTextBlocks));
+ widgets.add(const SizedBox(height: 20));
+ break;
+
+ case 'electricCharging':
+ if (value as bool) {
+ widgets.add(const SizedBox(height: 40));
+ widgets.add(Text(
+ parkingInfo.electricChargingTitle,
+ style: theme.textTheme.headlineMedium,
+ ));
+ widgets.add(const SizedBox(height: 20));
+ widgets.add(Text(
+ parkingInfo.electricChargingDescription,
+ style: theme.textTheme.bodySmall,
+ ));
+ }
+ break;
+ }
+ });
+
+ widgets.add(const SizedBox(height: 100));
+ return widgets;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ backgroundColor: Colors.white,
+ body: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const ImageWidget(image: 'assets/images/parking.png'),
+ Expanded(
+ child: SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 26),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: _buildDynamicContent(context),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/hotel_information/pages/restaurant_page.dart b/comwell_key_app/lib/hotel_information/pages/restaurant_page.dart
new file mode 100644
index 00000000..39247041
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/pages/restaurant_page.dart
@@ -0,0 +1,102 @@
+import 'package:comwell_key_app/hotel_information/components/contact_hotel_button.dart';
+import 'package:comwell_key_app/hotel_information/components/image_widget.dart';
+import 'package:comwell_key_app/hotel_information/components/structured_text.dart';
+import 'package:comwell_key_app/hotel_information/components/address.dart';
+import 'package:comwell_key_app/hotel_information/components/opening_hours.dart';
+import 'package:comwell_key_app/hotel_information/models/restaurant.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class RestaurantPage extends StatelessWidget {
+ final Restaurant restaurant;
+
+ const RestaurantPage({super.key, required this.restaurant});
+
+ List<Widget> _buildDynamicContent(BuildContext context) {
+ final theme = Theme.of(context);
+ final Map<String, dynamic> restaurantData = restaurant.toJson();
+ final List<Widget> widgets = [];
+
+
+ restaurantData.forEach((key, value) {
+
+ switch (key) {
+ case 'title':
+ widgets.add(Text(
+ value as String,
+ style: theme.textTheme.headlineLarge,
+ ));
+ widgets.add(const SizedBox(height: 20));
+ break;
+
+ case 'structuredText':
+ widgets.add(StructuredText(blocks: restaurant.structuredTextBlocks));
+ widgets.add(const SizedBox(height: 20));
+ break;
+
+ case 'address':
+ widgets.add(Address(address: value as String));
+ widgets.add(const SizedBox(height: 20));
+ break;
+
+ case 'openingHours':
+ widgets.add(OpeningHours(openingHours: value as String));
+ widgets.add(const SizedBox(height: 20));
+ break;
+
+ case 'phoneNumber':
+ widgets.add(Text(
+ "restaurant_page_book_table".tr(),
+ style: theme.textTheme.headlineMedium,
+ ));
+ widgets.add(const SizedBox(height: 20));
+ widgets.add(ContactHotelButton(
+ title: "call_us".tr(),
+ subtitle: value as String,
+ iconPath: "assets/icons/ic_telephone.svg",
+ onClick: () => launchUrl(Uri.parse("tel:$value")),
+ ));
+ widgets.add(const SizedBox(height: 6));
+ break;
+
+ case 'email':
+ widgets.add(ContactHotelButton(
+ title: "restaurant_page_send_email".tr(),
+ subtitle: value as String,
+ iconPath: "assets/icons/ic_send.svg",
+ onClick: () => launchUrl(Uri.parse("mailto:$value")),
+ ));
+ widgets.add(const SizedBox(height: 20));
+ break;
+ }
+ });
+
+ widgets.add(const SizedBox(height: 100));
+ return widgets;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ backgroundColor: Colors.white,
+ body: Column(
+ children: [
+ ImageWidget(image: restaurant.image),
+ Expanded(
+ child: SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 26),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: _buildDynamicContent(context),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/hotel_information/pages/spa_facility_page.dart b/comwell_key_app/lib/hotel_information/pages/spa_facility_page.dart
new file mode 100644
index 00000000..671583ea
--- /dev/null
+++ b/comwell_key_app/lib/hotel_information/pages/spa_facility_page.dart
@@ -0,0 +1,118 @@
+import 'package:comwell_key_app/hotel_information/components/image_widget.dart';
+import 'package:comwell_key_app/hotel_information/components/structured_text.dart';
+import 'package:comwell_key_app/hotel_information/cubit/hotel_information_cubit.dart';
+import 'package:comwell_key_app/hotel_information/models/spa.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class SpaFacilityPage extends StatelessWidget {
+ final Spa spa;
+ const SpaFacilityPage({super.key, required this.spa});
+
+ List<Widget> _buildDynamicContent(BuildContext context) {
+ final theme = Theme.of(context);
+ final Map<String, dynamic> spaData = spa.toJson();
+ final List<Widget> widgets = [];
+
+ spaData.forEach((key, value) {
+ if (value == null) return;
+
+ switch (key) {
+ case 'title':
+ widgets.add(Text(
+ value as String,
+ style: theme.textTheme.headlineLarge,
+ ));
+ widgets.add(const SizedBox(height: 20));
+ break;
+
+ case 'structuredText':
+ widgets.add(StructuredText(blocks: spa.structuredTextBlocks));
+ widgets.add(const SizedBox(height: 20));
+ break;
+ }
+ });
+
+ widgets.add(const SizedBox(height: 100));
+ return widgets;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final cubit = context.read<HotelInformationCubit>();
+ final isLoading = cubit.state.spaButtonIsLoading;
+ final theme = Theme.of(context);
+
+ return Scaffold(
+ backgroundColor: Colors.white,
+ bottomSheet: Builder(builder: (context) {
+ return Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ const Divider(
+ color: colorDivider,
+ height: 0,
+ ),
+ Row(
+ children: [
+ Expanded(
+ child: Container(
+ color: Colors.white,
+ child: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: ElevatedButton(
+ onPressed: isLoading ? null : cubit.onBookSpaClicked,
+ style: ButtonStyle(
+ backgroundColor: WidgetStateProperty.resolveWith((states) {
+ if (states.contains(WidgetState.disabled)) {
+ return Colors.grey;
+ }
+ return sandColor[80];
+ }),
+ foregroundColor: const WidgetStatePropertyAll(Colors.white),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 16.0),
+ child: Builder(builder: (context) {
+ if (isLoading) {
+ return const CircularProgressIndicator();
+ }
+ return Text(
+ "hotel_information_page_spa_button".tr(),
+ style: theme.textTheme.bodyLarge?.copyWith(
+ color: Colors.white,
+ fontWeight: FontWeight.bold,
+ ),
+ );
+ }),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ],
+ );
+ }),
+ body: Column(
+ children: [
+ ImageWidget(image: spa.image),
+ Expanded(
+ child: SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 26),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: _buildDynamicContent(context),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/main.dart b/comwell_key_app/lib/main.dart
index ca9628cd..ea1c2150 100644
--- a/comwell_key_app/lib/main.dart
+++ b/comwell_key_app/lib/main.dart
@@ -67,9 +67,7 @@ void runMainApp(FirebaseOptions firebaseOptions) async {
runApp(SentryWidget(
child: EasyLocalization(
supportedLocales: const [Locale('en', 'US'), Locale('da', 'DK')],
- path:
- 'assets/translations', // <-- change the path of the translation files
- //TODO: What should the fallback locale be?
+ path: 'assets/translations',
fallbackLocale: const Locale('da', 'DK'),
child: const ComwellApp())));
}
diff --git a/comwell_key_app/lib/routing/app_router.dart b/comwell_key_app/lib/routing/app_router.dart
index 0cf388b3..60fee55f 100644
--- a/comwell_key_app/lib/routing/app_router.dart
+++ b/comwell_key_app/lib/routing/app_router.dart
@@ -11,10 +11,10 @@ import 'package:comwell_key_app/contact/cubit/contact_cubit.dart';
import 'package:comwell_key_app/contact/repository/contact_repository.dart';
import 'package:comwell_key_app/find_booking/find_booking_page.dart';
import 'package:comwell_key_app/find_booking/loading_page.dart';
-import 'package:comwell_key_app/hotel_information/components/hotel_information_menu.dart';
-import 'package:comwell_key_app/hotel_information/components/parking_facility_page.dart';
-import 'package:comwell_key_app/hotel_information/components/restaurant_page.dart';
-import 'package:comwell_key_app/hotel_information/components/spa_facility_page.dart';
+import 'package:comwell_key_app/hotel_information/pages/hotel_information_menu.dart';
+import 'package:comwell_key_app/hotel_information/pages/parking_facility_page.dart';
+import 'package:comwell_key_app/hotel_information/pages/restaurant_page.dart';
+import 'package:comwell_key_app/hotel_information/pages/spa_facility_page.dart';
import 'package:comwell_key_app/hotel_information/cubit/hotel_information_cubit.dart';
import 'package:comwell_key_app/hotel_information/hotel_information_page.dart';
import 'package:comwell_key_app/hotel_information/models/parking_info.dart';