diff --git a/public/imgsFinalPractice/auditorium.jpg b/public/imgsFinalPractice/auditorium.jpg
new file mode 100644
index 00000000..ec301d44
Binary files /dev/null and b/public/imgsFinalPractice/auditorium.jpg differ
diff --git a/public/imgsFinalPractice/conferenceRoom.jpg b/public/imgsFinalPractice/conferenceRoom.jpg
new file mode 100644
index 00000000..a8d500a4
Binary files /dev/null and b/public/imgsFinalPractice/conferenceRoom.jpg differ
diff --git a/public/imgsFinalPractice/meetingRoom.jpg b/public/imgsFinalPractice/meetingRoom.jpg
new file mode 100644
index 00000000..f1a05957
Binary files /dev/null and b/public/imgsFinalPractice/meetingRoom.jpg differ
diff --git a/public/imgsFinalPractice/microphone.jpg b/public/imgsFinalPractice/microphone.jpg
new file mode 100644
index 00000000..162c9a5f
Binary files /dev/null and b/public/imgsFinalPractice/microphone.jpg differ
diff --git a/public/imgsFinalPractice/presentationRoom.jpg b/public/imgsFinalPractice/presentationRoom.jpg
new file mode 100644
index 00000000..77e1d30e
Binary files /dev/null and b/public/imgsFinalPractice/presentationRoom.jpg differ
diff --git a/public/imgsFinalPractice/projector.jpg b/public/imgsFinalPractice/projector.jpg
new file mode 100644
index 00000000..28b46697
Binary files /dev/null and b/public/imgsFinalPractice/projector.jpg differ
diff --git a/public/imgsFinalPractice/signpost.jpg b/public/imgsFinalPractice/signpost.jpg
new file mode 100644
index 00000000..07c775d1
Binary files /dev/null and b/public/imgsFinalPractice/signpost.jpg differ
diff --git a/public/imgsFinalPractice/smallMeetingRoom.jpg b/public/imgsFinalPractice/smallMeetingRoom.jpg
new file mode 100644
index 00000000..f57a9cf0
Binary files /dev/null and b/public/imgsFinalPractice/smallMeetingRoom.jpg differ
diff --git a/public/imgsFinalPractice/speakers.jpg b/public/imgsFinalPractice/speakers.jpg
new file mode 100644
index 00000000..55f71bb2
Binary files /dev/null and b/public/imgsFinalPractice/speakers.jpg differ
diff --git a/public/imgsFinalPractice/whiteboard.png b/public/imgsFinalPractice/whiteboard.png
new file mode 100644
index 00000000..ef496a02
Binary files /dev/null and b/public/imgsFinalPractice/whiteboard.png differ
diff --git a/src/ConferenceEvent.jsx b/src/ConferenceEvent.jsx
index 612a4648..d337a29d 100644
--- a/src/ConferenceEvent.jsx
+++ b/src/ConferenceEvent.jsx
@@ -1,16 +1,27 @@
-import React, { useState } from "react";
+import { useState } from "react";
import "./ConferenceEvent.css";
import TotalCost from "./TotalCost";
import { useSelector, useDispatch } from "react-redux";
import { incrementQuantity, decrementQuantity } from "./venueSlice";
+import { incrementAvQuantity, decrementAvQuantity } from "./avSlice.js";
+import { toggleMealSelection } from './mealsSlice.js';
+
const ConferenceEvent = () => {
const [showItems, setShowItems] = useState(false);
const [numberOfPeople, setNumberOfPeople] = useState(1);
+
+ // venue:
const venueItems = useSelector((state) => state.venue);
- const dispatch = useDispatch();
+ const dispatch = useDispatch(); // used by all slices
const remainingAuditoriumQuantity = 3 - venueItems.find(item => item.name === "Auditorium Hall (Capacity:200)").quantity;
-
+ // av:
+ const avItems = useSelector((state) => state.av);
+
+ // meals:
+ const mealsItems = useSelector((state) => state.meals);
+
+
const handleToggleItems = () => {
console.log("handleToggleItems called");
setShowItems(!showItems);
@@ -23,29 +34,93 @@ const ConferenceEvent = () => {
dispatch(incrementQuantity(index));
};
- const handleRemoveFromCart = (index) => {
- if (venueItems[index].quantity > 0) {
- dispatch(decrementQuantity(index));
- }
- };
+ const handleRemoveFromCart = (index) => {
+ if (venueItems[index].quantity > 0) {
+ dispatch(decrementQuantity(index));
+ }
+ };
+
+ // av:
const handleIncrementAvQuantity = (index) => {
+ dispatch(incrementAvQuantity(index));
};
-
+ // av:
const handleDecrementAvQuantity = (index) => {
+ dispatch(decrementAvQuantity(index));
};
+ // meals:
const handleMealSelection = (index) => {
-
+ const item = mealsItems[index];
+ if(item.selected && item.type === 'mealForPeople'){
+ const newNumberOfPeople = item.selected ? numberOfPeople : 0;
+ dispatch(toggleMealSelection(index, newNumberOfPeople));
+ }else{
+ dispatch(toggleMealSelection(index));
+ }
};
const getItemsFromTotalCost = () => {
const items = [];
+ venueItems.forEach((item) => {
+ if(item.quantity > 0){
+ items.push({...item, type: "venue"});
+ }
+ });
+ avItems.forEach((item) => {
+ if(
+ item.quantity && !items.some((i) => i.name === item.name && i.type === "av")
+ ) {
+ items.push({...item, type: "av"});
+ }
+ });
+ mealsItems.forEach((item) => {
+ if(item.selected){
+ const itemForDisplay = { ...item, type: "meals" };
+ if(item.numberOfPeople){
+ itemForDisplay.numberOfPeople = numberOfPeople;
+ }
+ items.push(itemForDisplay);
+ }
+ });
+
+ return items;
};
const items = getItemsFromTotalCost();
const ItemsDisplay = ({ items }) => {
-
+ console.log(items);
+ return <>
+
+ {items.length === 0 &&
No items selected
}
+
+
+
+ | Name |
+ Unit Cost |
+ Quantity |
+ Subtotal |
+
+
+
+ {items.map((item, index) => (
+
+ | {item.name} |
+ {item.cost} |
+
+ {item.type === "meals" || item.numberOfPeople ?
+ ` For ${numberOfPeople} people` : item.quantity}
+ |
+ {item.type === "meals" || item.numberOfPeople ?
+ `${item.cost * numberOfPeople}` : `${item.cost * item.quantity}`}
+ |
+
+ ))}
+
+
+
+ >
};
const calculateTotalCost = (section) => {
let totalCost = 0;
@@ -53,11 +128,30 @@ const ConferenceEvent = () => {
venueItems.forEach((item) => {
totalCost += item.cost * item.quantity;
});
+ }else if(section === "av"){ // adding the costs of the data from the av items
+ avItems.forEach((item) => {
+ totalCost += item.cost * item.quantity;
+ });
+ }else if(section == "meals"){
+ mealsItems.forEach((item) => {
+ if(item.selected){
+ totalCost += item.cost * numberOfPeople; // if item is selected, its cost is multiplied by the numberOfPeople
+ }
+ });
}
+
return totalCost;
};
+
+ // venue:
const venueTotalCost = calculateTotalCost("venue");
+ // av:
+ const avTotalCost = calculateTotalCost("av");
+
+ // meals:
+ const mealsTotalCost = calculateTotalCost("meals");
+
const navigateToProducts = (idType) => {
if (idType == '#venue' || idType == '#addons' || idType == '#meals') {
if (showItems) { // Check if showItems is false
@@ -66,6 +160,13 @@ const ConferenceEvent = () => {
}
}
+ // object that include the all three subtotals in the totalcost
+ const totalCosts = {
+ venue: venueTotalCost,
+ av: avTotalCost,
+ meals: mealsTotalCost,
+ };
+
return (
<>
@@ -146,21 +247,29 @@ const ConferenceEvent = () => {
Total Cost: ${venueTotalCost}
-
{/*Necessary Add-ons*/}
-
-
Add-ons Selection
-
-
+ {avItems.map((item, index) => (
+
+
+

+
+
{item.name}
+
${item.cost}
+
+
+ {item.quantity}
+
+
+
+ ))}
-
Total Cost:
-
+
Total Cost: {avTotalCost}
{/* Meal Section */}
@@ -168,18 +277,33 @@ const ConferenceEvent = () => {
-
Meals Selection
+
+ {mealsItems.map((item, index) => (
+
+
+ handleMealSelection(index)}
+ />
+
+
+
${item.cost}
+
+ ))}
+
-
+
+ setNumberOfPeople(parseInt(e.target.value))}
+ min="1" />
-
Total Cost:
-
+
Total Cost: {mealsTotalCost}
@@ -190,9 +314,6 @@ const ConferenceEvent = () => {
)
}
-
-
-
>
@@ -200,3 +321,15 @@ const ConferenceEvent = () => {
};
export default ConferenceEvent;
+
+/*
+ tip added from copilot suggestions
+ TIP: For optimal code quality and easier debugging,
+ consider adding PropTypes to validate component props.
+ Example:
+ import PropTypes from 'prop-types';
+ MyComponent.propTypes = {
+ items: PropTypes.array.isRequired,
+ };
+ This helps catch bugs early and documents expected prop types.
+*/
\ No newline at end of file
diff --git a/src/TotalCost.jsx b/src/TotalCost.jsx
index 845abca9..4e4102ac 100644
--- a/src/TotalCost.jsx
+++ b/src/TotalCost.jsx
@@ -2,7 +2,8 @@ import React, { useState, useEffect } from 'react';
import "./TotalCost.css";
const TotalCost = ({ totalCosts, ItemsDisplay }) => {
-
+
+ const total_amount = totalCosts.venue + totalCosts.av + totalCosts.meals;
return (
@@ -12,11 +13,10 @@ const TotalCost = ({ totalCosts, ItemsDisplay }) => {
diff --git a/src/avSlice.js b/src/avSlice.js
index cdd79aac..7cfff684 100644
--- a/src/avSlice.js
+++ b/src/avSlice.js
@@ -1,19 +1,59 @@
import { createSlice } from "@reduxjs/toolkit";
-
+// 1. adding objects to provide data structure
+// 2. create logic for incrementAvQuantity() and decrementAvQuantity() functions
+// 3. export all reducer functions and actions (ln-61 and ln-63)
export const avSlice = createSlice({
name: "av",
initialState: [
-
+ {
+ img: "./imgsFinalPractice/projector.jpg",
+ name: "Projectors",
+ cost: 200,
+ quantity: 0,
+ },
+ {
+ img: "./imgsFinalPractice/speakers.jpg",
+ name: "Speaker",
+ cost: 35,
+ quantity: 0,
+ },
+ {
+ img: "./imgsFinalPractice/microphone.jpg",
+ name: "Microphones",
+ cost: 45,
+ quantity: 0,
+ },
+ {
+ img: "./imgsFinalPractice/whiteboard.png",
+ name: "Whiteboards",
+ cost: 80,
+ quantity: 0,
+ },
+ {
+ img: "./imgsFinalPractice/signpost.jpg",
+ name: "Signage",
+ cost: 80,
+ quantity: 0,
+ },
+
],
- reducers: {
+ reducers: { // reducer functions:
+
incrementAvQuantity: (state, action) => {
-
+ const item = state[action.payload];
+ if(item){
+ item.quantity++;
+ }
},
decrementAvQuantity: (state, action) => {
-
+ const item = state[action.payload];
+ if(item && item.quantity > 0){
+ item.quantity--;
+ }
},
+
},
});
diff --git a/src/mealsSlice.js b/src/mealsSlice.js
index faf8138a..fc672863 100644
--- a/src/mealsSlice.js
+++ b/src/mealsSlice.js
@@ -1,13 +1,19 @@
// mealsSlice.js
import { createSlice } from '@reduxjs/toolkit';
-
+// 1. including the meal items inside the initialState array
+// 2. adding the logic needed for function reducer toggleMealSelection
export const mealsSlice = createSlice({
name: 'meals',
initialState: [
-
+ { name: 'Breakfast', cost: 50, selected: false },
+ { name: 'High Tea', cost: 25, selected: false },
+ { name: 'Lunch', cost: 65, selected: false },
+ { name: 'Dinner', cost: 70, selected: false },
],
+ // reducer functions:
reducers: {
toggleMealSelection: (state, action) => {
+ state[action.payload].selected = ! state[action.payload].selected; // uses [action.payload] to identify the item to update
},
},
});
diff --git a/src/store.js b/src/store.js
index f05b9f8f..96cf5937 100644
--- a/src/store.js
+++ b/src/store.js
@@ -1,9 +1,15 @@
// store.js
import { configureStore } from '@reduxjs/toolkit';
import venueReducer from './venueSlice';
+import avReducer from './avSlice.js';
+import mealsReducer from './mealsSlice.js';
+// 3. adding into the redux store the avSlice
+// 3.2 adding into the redux store the mealsSlice
export default configureStore({
reducer: {
- venue: venueReducer,
+ venue: venueReducer,
+ av: avReducer, // same name as the key-value pair 'name: "av" in avSlice.js
+ meals: mealsReducer,
},
});