Repository: illusia-ry-organization/illusia_ry
Pull request #98: Fixed bug by adding a fetchBooking to the useEffect
Author: login: JonathanGian
Created: 2025-05-16T08:50:47Z | Merged: 2025-05-19T14:41:33Z

This pull request introduces internationalization (i18n) support for the cart functionality in the application. It includes updates to translation files for English and Finnish, refactors the `Cart` component to use the `react-i18next` library for dynamic translations, and ensures all user-facing text in the cart is translatable. Additionally, it simplifies the `SingleBooking` component's logic for fetching booking details.

### Internationalization Updates:

* Added new translation keys for cart-related text in the English (`frontend/public/locales/en/translations.json`) and Finnish (`frontend/public/locales/fi/translations.json`) localization files. These include keys for "Your Cart," "Items," "Remove," "Booking Summary," and other cart-related terms. [[1]](diffhunk://#diff-25452c785154164374e1e52b288cfb9e51f3ff5308b500f90705660e4f55a414R18-R32) [[2]](diffhunk://#diff-d0ee4afc6ef0f427735f69eb5c939c4dffc66010899511a705624e24fa277ed1R18-R32)

* Refactored the `Cart` component (`frontend/src/pages/Cart.tsx`) to use the `useTranslation` hook from `react-i18next` for dynamic translations. Replaced hardcoded text with calls to the `t` function or `Trans` component for translatable strings such as "Your Cart," "Items," and "Book items." [[1]](diffhunk://#diff-b57780abc525196e7a5e703887e7d18a7b2355b2a57182499c94cd27fb6fbdf8R36) [[2]](diffhunk://#diff-b57780abc525196e7a5e703887e7d18a7b2355b2a57182499c94cd27fb6fbdf8L262-R264) [[3]](diffhunk://#diff-b57780abc525196e7a5e703887e7d18a7b2355b2a57182499c94cd27fb6fbdf8L279-R283) [[4]](diffhunk://#diff-b57780abc525196e7a5e703887e7d18a7b2355b2a57182499c94cd27fb6fbdf8L380-R382) [[5]](diffhunk://#diff-b57780abc525196e7a5e703887e7d18a7b2355b2a57182499c94cd27fb6fbdf8L416-R421) [[6]](diffhunk://#diff-b57780abc525196e7a5e703887e7d18a7b2355b2a57182499c94cd27fb6fbdf8L452-R454) [[7]](diffhunk://#diff-b57780abc525196e7a5e703887e7d18a7b2355b2a57182499c94cd27fb6fbdf8L468-R470) [[8]](diffhunk://#diff-b57780abc525196e7a5e703887e7d18a7b2355b2a57182499c94cd27fb6fbdf8L483-R491) [[9]](diffhunk://#diff-b57780abc525196e7a5e703887e7d18a7b2355b2a57182499c94cd27fb6fbdf8L507-R520)

### Code Simplifications:

* Simplified the logic in the `SingleBooking` component (`frontend/src/components/Booking.tsx`) by consolidating the `useEffect` hooks. It now ensures fresh booking details are fetched whenever the booking ID changes.

### Bug Fixes:

* Fixed an issue in the `Cart` component where the `image_path` property was accessed incorrectly. Updated the code to use the first element of the `image_path` array to prevent potential errors.


Diff:
diff --git a/frontend/public/locales/en/translations.json b/frontend/public/locales/en/translations.json
index 93203b05..7d9dcff6 100644
--- a/frontend/public/locales/en/translations.json
+++ b/frontend/public/locales/en/translations.json
@@ -15,6 +15,21 @@
     "myAccount": "My account",
     "logOut": "Log out"
   },
+  "cart": {
+    "yourCart": "Your Cart",
+    "items": "Items",
+    "quantity": "Qty",
+    "action": "Action",
+    "remove": "Remove",
+    "bookingSummary": "Booking Summary",
+    "dates": "Dates",
+    "changeDates": "Change the booking dates",
+    "confirmDates": "Confirm new dates",
+    "cancel": "Cancel",
+    "totalItems": "Total items",
+    "bookItems": "Book items",
+    "empty": "Your cart is currently empty! <1>Browse Items</1>"
+  },
   "home": {
     "heroTitle": "Home for live-action role-playing games props",
     "heroDescription": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla fringilla nunc in molestie feugiat. Nunc auctor consectetur elit, quis pulvina. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla fringilla nunc in molestie feugiat",
diff --git a/frontend/public/locales/fi/translations.json b/frontend/public/locales/fi/translations.json
index d964dd7c..87e4f9df 100644
--- a/frontend/public/locales/fi/translations.json
+++ b/frontend/public/locales/fi/translations.json
@@ -15,6 +15,21 @@
     "myAccount": "Oma tili",
     "logOut": "Kirjaudu ulos"
   },
+  "cart": {
+    "yourCart": "Ostoskorisi",
+    "items": "Tuotteet",
+    "quantity": "Määrä",
+    "action": "Toiminnot",
+    "remove": "Poista",
+    "bookingSummary": "Varausyhteenveto",
+    "dates": "Päivämäärät",
+    "changeDates": "Vaihda varauksen päivämäärät",
+    "confirmDates": "Vahvista uudet päivämäärät",
+    "cancel": "Peruuta",
+    "totalItems": "Tuotteita yhteensä",
+    "bookItems": "Varaa tuotteet",
+    "empty": "Ostoskori on tyhjä! <1>Selaa tuotteita</1>"
+  },
   "home": {
     "heroTitle": "Live action -roolipelien rekvisiittakoti",
     "heroDescription": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ahdistelussa ei ole nyt mitään hienostelua. Nyt artikkelin kirjoittaja on nero, joka on tyyny. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nyt ahdistetussa feugiatissa ei ole fringillaa.",
diff --git a/frontend/src/components/Booking.tsx b/frontend/src/components/Booking.tsx
index 84f75a7b..8735fd7d 100644
--- a/frontend/src/components/Booking.tsx
+++ b/frontend/src/components/Booking.tsx
@@ -54,17 +54,14 @@ function SingleBooking() {
   }
 
 
-  useEffect(() => {
-    if (!booking_id) {
-      navigate('/bookings');
-    }
-  }, [booking_id, navigate]);
-
-  useEffect(() => {
-    if (!booking_id) return;
-    if (!booking_selector) dispatch(fetchBooking(booking_id));
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [dispatch]);
+useEffect(() => {
+  if (!booking_id) {
+    navigate('/bookings');
+    return;
+  }
+  // Always fetch fresh booking details when the ID changes
+  dispatch(fetchBooking(booking_id));
+}, [booking_id, dispatch, navigate]);
 
   if (loading)
     return (
diff --git a/frontend/src/pages/Cart.tsx b/frontend/src/pages/Cart.tsx
index 647c3cb6..cc957774 100644
--- a/frontend/src/pages/Cart.tsx
+++ b/frontend/src/pages/Cart.tsx
@@ -33,6 +33,7 @@ import { showCustomSnackbar } from '../components/CustomSnackbar';
 import { store } from '../store/store';
 import { checkAvailabilityForItemOnDates } from '../selectors/availabilitySelector';
 import { useEffect, useState } from 'react';
+import { useTranslation, Trans } from 'react-i18next';
 import { DateValue, getLocalTimeZone, parseDate, today } from '@internationalized/date';
 import { RangeValue } from '@react-types/shared';
 import { DateRangePicker, defaultTheme, Provider } from '@adobe/react-spectrum';
@@ -50,9 +51,10 @@ function Cart() {
 	const [incorrectCart, setIncorrectCart] = useState(false);
 	const [localCart, setLocalCart] = useState<ItemWithQuantity[]>([]);
 	const navigate = useNavigate()
+	const { t } = useTranslation();
 
 	useEffect(() => {
-		updateRangeWithSelectedRange();
+		updateRangeWithSelectedRange(); // These need to be changed around. Your calling on something that is not set yet.
 	}, [selectedDateRange]);
 
 	useEffect(() => {
@@ -259,7 +261,7 @@ function Cart() {
 				px: 2,
 			}}
 		>
-			<Typography variant="heading_secondary_bold">Your Cart</Typography>
+			<Typography variant="heading_secondary_bold">{t('cart.yourCart', { defaultValue: 'Your Cart' })}</Typography>
 
 			{cart.length > 0 ? (
 				<Stack
@@ -276,9 +278,9 @@ function Cart() {
 						<Table aria-label="simple table">
 							<TableHead>
 								<TableRow>
-									<TableCell>Items ({totalItems})</TableCell>
-									<TableCell align="center">Qty</TableCell>
-									<TableCell align="right">Action</TableCell>
+									<TableCell>{t('cart.items', { defaultValue: 'Items' })} ({totalItems})</TableCell>
+									<TableCell align="center">{t('cart.quantity', { defaultValue: 'Qty' })}</TableCell>
+									<TableCell align="right">{t('cart.action', { defaultValue: 'Action' })}</TableCell>
 								</TableRow>
 							</TableHead>
 							<TableBody>
@@ -297,7 +299,7 @@ function Cart() {
 													<CardMedia
 														component="img"
 														image={
-															item.image_path || '/src/assets/broken_img.png'
+															item.image_path[0] || '/src/assets/broken_img.png'
 														}
 														onError={handleBrokenImg}
 														style={{ width: 78, borderRadius: 14 }}
@@ -377,7 +379,7 @@ function Cart() {
 													handleRemove(item.item_id, item.quantity);
 												}}
 											>
-												Remove
+												{t('cart.remove', { defaultValue: 'Remove' })}
 												<CloseIcon sx={{ fill: '#414141' }} />
 											</Button>
 										</TableCell>
@@ -413,10 +415,10 @@ function Cart() {
 								fontWeight: 500,
 							}}
 						>
-							Booking Summary
+							{t('cart.bookingSummary', { defaultValue: 'Booking Summary' })}
 						</Typography>
 						<Stack direction={'row'} justifyContent={'space-between'}>
-							<Typography variant="body2">Dates</Typography>
+							<Typography variant="body2">{t('cart.dates', { defaultValue: 'Dates' })}</Typography>
 							{!editingCart ?
 								<Typography variant="body2">
 									{selectedDateRange.start_date} - {selectedDateRange.end_date}
@@ -449,7 +451,7 @@ function Cart() {
 									}}
 									onClick={handleStartDateEdit}
 								>
-									Change the booking dates
+									{t('cart.changeDates', { defaultValue: 'Change the booking dates' })}
 								</Button>
 								:
 								<>
@@ -465,7 +467,7 @@ function Cart() {
 										}}
 										onClick={handleCompleteDateEdit}
 									>
-										Confirm new dates
+										{t('cart.confirmDates', { defaultValue: 'Confirm new dates' })}
 									</Button>
 
 									<Button
@@ -480,13 +482,13 @@ function Cart() {
 										}}
 										onClick={handleCancelDateEdit}
 									>
-										Cancel
+										{t('cart.cancel', { defaultValue: 'Cancel' })}
 									</Button>
 								</>
 							}
 						</Stack>
 						<Stack direction={'row'} justifyContent={'space-between'}>
-							<Typography variant="body2">Total items</Typography>
+							<Typography variant="body2">{t('cart.totalItems', { defaultValue: 'Total items' })}</Typography>
 							<Typography variant="body2">{totalItems}</Typography>
 						</Stack>
 						{!user && <Stack sx={{ border: '1px solid #E2E2E2', flexDirection: 'row', padding: '20px 24px', gap: '10px' }}>
@@ -504,13 +506,18 @@ function Cart() {
 							onClick={handleAddBooking}
 							disabled={editingCart}
 						>
-							Book items
+							{t('cart.bookItems', { defaultValue: 'Book items' })}
 						</Button>
 					</Stack>
 				</Stack>
 			) : (
 				<Typography>
-					Your cart is currently empty! <Link to="/items">Browse Items</Link>
+					<Trans
+						i18nKey="cart.empty"
+						defaultValue="Your cart is currently empty! Browse Items"
+					>
+						Your cart is currently empty! <Link to="/items">Browse Items</Link>
+					</Trans>
 				</Typography>
 			)}
 		</Box>


Reviews:
user: login: JonathanGian
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T08:51:10Z
user: login: JonathanGian
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T08:51:24Z
user: login: JonathanGian
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T08:51:44Z
user: login: JonathanGian
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T08:52:14Z
user: login: JonathanGian
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T08:52:29Z
user: login: athinakantis
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-19T06:30:20Z

Review comments:
path: frontend/public/locales/en/translations.json
user: login: JonathanGian
body: Added english version of the cart
created_at: 2025-05-16T08:51:09Z
author_association: COLLABORATOR
path: frontend/public/locales/fi/translations.json
user: login: JonathanGian
body: Added Finnish translations for cart
created_at: 2025-05-16T08:51:24Z
author_association: COLLABORATOR
path: frontend/src/components/Booking.tsx
user: login: JonathanGian
body: Fixed bug with confirmation not refreshing
created_at: 2025-05-16T08:51:43Z
author_association: COLLABORATOR
path: frontend/src/pages/Cart.tsx
user: login: JonathanGian
body: Some potential bugs in the cart but I didnt have time to fix them
created_at: 2025-05-16T08:52:14Z
author_association: COLLABORATOR
path: frontend/src/pages/Cart.tsx
user: login: JonathanGian
body: Added the ability to translate this page
created_at: 2025-05-16T08:52:29Z
author_association: COLLABORATOR

PR comments:
user: login: netlify[bot]
created_at: 2025-05-16T08:51:11Z
body: ### <span aria-hidden="true">❌</span> Deploy Preview for *illusia* failed. **[Why did it fail? →](https://app.netlify.com/projects/illusia/deploys/682b43165349a60008d6c517?deploy_diagnostics=true)**


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 858e14e8675a6251540ae8a85b683feef9248432 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/projects/illusia/deploys/682b43165349a60008d6c517 |
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-05-19T14:42:20Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=illusia-ry-organization_illusia_ry&pullRequest=98) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=illusia-ry-organization_illusia_ry&pullRequest=98&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=illusia-ry-organization_illusia_ry&pullRequest=98&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=illusia-ry-organization_illusia_ry&pullRequest=98&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=illusia-ry-organization_illusia_ry&pullRequest=98&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=illusia-ry-organization_illusia_ry&pullRequest=98&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=illusia-ry-organization_illusia_ry&pullRequest=98)


author_association: NONE