diff --git a/package-lock.json b/package-lock.json index c1011c5a..665e29e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1211,13 +1211,13 @@ "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "devOptional": true + "dev": true }, "node_modules/@types/react": { "version": "18.2.79", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz", "integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==", - "devOptional": true, + "dev": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1635,7 +1635,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true + "dev": true }, "node_modules/data-view-buffer": { "version": "1.0.1", diff --git a/src/App.css b/src/App.css index 5d4a76ce..85c14030 100644 --- a/src/App.css +++ b/src/App.css @@ -7,7 +7,7 @@ .first_page { display: flex; height: 100vh; - /* background-image: url("https://cdn.pixabay.com/photo/2018/07/05/14/45/conference-3518465_1280.jpg"); */ + background-image: url("https://cdn.pixabay.com/photo/2018/07/05/14/45/conference-3518465_1280.jpg"); background-size: cover; background-position: center; justify-content: center; diff --git a/src/App.jsx b/src/App.jsx index 7073781f..73960ae9 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,10 +1,10 @@ -import React, { useState } from "react"; -import "./App.css"; -import ConferenceEvent from "./ConferenceEvent"; -import AboutUs from "./AboutUs"; +import React, { useState } from "react"; /* need to define this */ +import "./App.css"; /* imports the theme from css file */ +import ConferenceEvent from "./ConferenceEvent"; /* imports the conferenceEvent.jsx file (Conference event planner) */ +import AboutUs from "./AboutUs"; /* imports the about us.jsx file */ -function App() { - const [showVenue, setShowVenue] = useState(false); +function App() { /* Component function */ + const [showVenue, setShowVenue] = useState(false); /* Get started page */ const handleGetStarted = () => { setShowVenue(true); @@ -15,7 +15,7 @@ function App() {
-

Conference Expense Planner

+

Conference Expense Planner

Plan your next major event with us!

-
+
{/* using ConferenceEvent variable */}
diff --git a/src/ConferenceEvent.jsx b/src/ConferenceEvent.jsx index 612a4648..555720fe 100644 --- a/src/ConferenceEvent.jsx +++ b/src/ConferenceEvent.jsx @@ -1,16 +1,20 @@ import React, { useState } from "react"; import "./ConferenceEvent.css"; import TotalCost from "./TotalCost"; +import { toggleMealSelection } from "./mealsSlice"; +import { incrementAvQuantity, decrementAvQuantity } from "./avSlice"; import { useSelector, useDispatch } from "react-redux"; import { incrementQuantity, decrementQuantity } from "./venueSlice"; + const ConferenceEvent = () => { const [showItems, setShowItems] = useState(false); const [numberOfPeople, setNumberOfPeople] = useState(1); const venueItems = useSelector((state) => state.venue); + const avItems = useSelector((state) => state.av); + const mealsItems = useSelector((state) => state.meals); const dispatch = useDispatch(); const remainingAuditoriumQuantity = 3 - venueItems.find(item => item.name === "Auditorium Hall (Capacity:200)").quantity; - const handleToggleItems = () => { console.log("handleToggleItems called"); setShowItems(!showItems); @@ -21,50 +25,133 @@ const ConferenceEvent = () => { return; } dispatch(incrementQuantity(index)); - }; + }; - const handleRemoveFromCart = (index) => { + const handleRemoveFromCart = (index) => { if (venueItems[index].quantity > 0) { dispatch(decrementQuantity(index)); } - }; + }; + const handleIncrementAvQuantity = (index) => { + dispatch(incrementAvQuantity(index)); + console.log(`Incremented ${avItems[index].name} quantity to ${avItems[index].quantity + 1}`); }; const handleDecrementAvQuantity = (index) => { + dispatch(decrementAvQuantity(index)); + console.log(`Decremented ${avItems[index].name} quantity to ${avItems[index].quantity - 1}`); }; 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 > 0 && !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

} + + + + + + + + + + + {items.map((item, index) => ( + + + + + + + ))} + +
NameUnit CostQuantitySubtotal
{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; if (section === "venue") { - venueItems.forEach((item) => { - totalCost += item.cost * item.quantity; - }); + venueItems.forEach((item) => { + totalCost += item.cost * item.quantity; + }); + } else if (section === "av") { + avItems.forEach((item) => { + totalCost += item.cost * item.quantity; + }); + } else if (section === "meals") { + mealsItems.forEach((item) => { + if (item.selected) { + totalCost += item.cost * numberOfPeople; + } + }); } return totalCost; - }; + }; + const venueTotalCost = calculateTotalCost("venue"); + const avTotalCost = calculateTotalCost("av"); + const mealsTotalCost = calculateTotalCost("meals"); const navigateToProducts = (idType) => { - if (idType == '#venue' || idType == '#addons' || idType == '#meals') { - if (showItems) { // Check if showItems is false - setShowItems(!showItems); // Toggle showItems to true only if it's currently false - } + if (idType === '#venue' || idType === '#addons' || idType === '#meals') { + if (showItems) { + setShowItems(!showItems); + } } - } + }; + + const totalCosts = { + venue: venueTotalCost, + av: avTotalCost, + meals: mealsTotalCost, + }; return ( <> @@ -72,7 +159,7 @@ const ConferenceEvent = () => {
Conference Expense Planner
- navigateToProducts("#venue")} >Venue + navigateToProducts("#venue")}>Venue navigateToProducts('#addons')}>Add-ons navigateToProducts('#meals')}>Meals
@@ -82,121 +169,126 @@ const ConferenceEvent = () => {
- {!showItems - ? - ( -
-
-
- -

Venue Room Selection

-
-
- {venueItems.map((item, index) => ( -
-
- {item.name} -
-
{item.name}
-
${item.cost}
-
- {venueItems[index].name === "Auditorium Hall (Capacity:200)" ? ( - - <> - - - {venueItems[index].quantity > 0 ? ` ${venueItems[index].quantity}` : "0"} - - - - ) : ( -
- - - {venueItems[index].quantity > 0 ? ` ${venueItems[index].quantity}` : "0"} - - - - -
- )} -
-
- ))} -
-
Total Cost: ${venueTotalCost}
-
- - {/*Necessary Add-ons*/} -
- - -
- -

Add-ons Selection

- -
-
- -
-
Total Cost:
- + {!showItems ? ( +
+
+
+

Venue Room Selection

- - {/* Meal Section */} - -
- -
- -

Meals Selection

-
- -
- -
-
- -
-
Total Cost:
- - +
+ {venueItems.map((item, index) => ( +
+
+ {item.name} +
+
{item.name}
+
${item.cost}
+
+ {venueItems[index].name === "Auditorium Hall (Capacity:200)" ? ( + <> + + + {venueItems[index].quantity > 0 ? ` ${venueItems[index].quantity}` : "0"} + + + + ) : ( +
+ + + {venueItems[index].quantity > 0 ? ` ${venueItems[index].quantity}` : "0"} + + +
+ )} +
+
+ ))}
+
Total Cost: ${venueTotalCost}
- ) : ( -
- } /> -
- ) - } - - + {/* Necessary Add-ons */} +
+
+

Add-ons Selection

+
+
+ {avItems.map((item, index) => ( +
+
+ {item.name} +
+
{item.name}
+
${item.cost}
+
+ + {item.quantity} + +
+
+ ))} +
+
Total Cost: {avTotalCost}
+
+ {/* Meal Section */} +
+
+

Meals Selection

+
+
+ + setNumberOfPeople(parseInt(e.target.value))} + min="1" + /> +
+
+ {mealsItems.map((item, index) => ( +
+
+ handleMealSelection(index)} + /> + +
+
${item.cost}
+
+ ))} +
+
Total Cost: {mealsTotalCost}
+
+
+ ) : ( +
+ } /> +
+ )}
- ); }; -export default ConferenceEvent; +export default ConferenceEvent; \ No newline at end of file diff --git a/src/TotalCost.jsx b/src/TotalCost.jsx index 845abca9..2e61f229 100644 --- a/src/TotalCost.jsx +++ b/src/TotalCost.jsx @@ -1,27 +1,23 @@ import React, { useState, useEffect } from 'react'; import "./TotalCost.css"; - const TotalCost = ({ totalCosts, ItemsDisplay }) => { - - - return ( -
-
-
-

Total cost for the event

-
-
-

- -

- -
- + const total_amount = totalCosts.venue + totalCosts.av + totalCosts.meals; + return ( +
+
+
+

Total cost for the event

+
+
+

+ ${total_amount} +

+
+ +
+
-
-
- ); + ); }; - -export default TotalCost; +export default TotalCost; \ No newline at end of file diff --git a/src/avSlice.js b/src/avSlice.js index cdd79aac..c67a4a24 100644 --- a/src/avSlice.js +++ b/src/avSlice.js @@ -3,20 +3,57 @@ import { createSlice } from "@reduxjs/toolkit"; export const avSlice = createSlice({ name: "av", initialState: [ - + { + img: "", + name: "Projectors", + cost: 200, + quantity: 0, + }, + { + img: "", + name: "Speaker", + cost: 35, + quantity: 0, + }, + { + img: "", + name: "Microphones", + cost: 45, + quantity: 0, + }, + { + img: "", + name: "Whiteboards", + cost: 80, + quantity: 0, + }, + + { + img: "", + name: "Signage", + cost: 80, + quantity: 0, + }, + ], reducers: { 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--; + } }, }, }); export const { incrementAvQuantity, decrementAvQuantity } = avSlice.actions; -export default avSlice.reducer; +export default avSlice.reducer; \ No newline at end of file diff --git a/src/mealsSlice.js b/src/mealsSlice.js index faf8138a..3aa03073 100644 --- a/src/mealsSlice.js +++ b/src/mealsSlice.js @@ -1,17 +1,19 @@ -// mealsSlice.js import { createSlice } from '@reduxjs/toolkit'; - 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 }, ], reducers: { toggleMealSelection: (state, action) => { - }, + state[action.payload].selected = !state[action.payload].selected; + }, }, }); export const { toggleMealSelection } = mealsSlice.actions; - -export default mealsSlice.reducer; +export default mealsSlice.reducer; \ No newline at end of file diff --git a/src/store.js b/src/store.js index f05b9f8f..10206d56 100644 --- a/src/store.js +++ b/src/store.js @@ -1,9 +1,16 @@ -// store.js import { configureStore } from '@reduxjs/toolkit'; import venueReducer from './venueSlice'; +import avReducer from './avSlice'; +import mealsReducer from './mealsSlice'; + +console.log('venueReducer:', venueReducer); +console.log('avReducer:', avReducer); +console.log('mealsReducer:', mealsReducer); export default configureStore({ reducer: { venue: venueReducer, + av: avReducer, + meals: mealsReducer, }, }); diff --git a/src/venueSlice.js b/src/venueSlice.js index 350d353a..0677b870 100644 --- a/src/venueSlice.js +++ b/src/venueSlice.js @@ -5,31 +5,31 @@ export const venueSlice = createSlice({ name: "venue", initialState: [ { - img: "https://pixabay.com/images/download/chairs-2181916_640.jpg", + img: "", name: "Conference Room (Capacity:15)", cost: 3500, quantity: 0, }, { - img: "https://pixabay.com/images/download/event-venue-1597531_640.jpg", + img: "", name: "Auditorium Hall (Capacity:200)", cost: 5500, quantity: 0, }, { - img: "https://pixabay.com/images/download/convention-center-3908238_640.jpg", + img: "", name: "Presentation Room (Capacity:50)", cost: 700, quantity: 0, }, { - img: "https://pixabay.com/images/download/chairs-2181916_640.jpg", + img: "", name: "Large Meeting Room (Capacity:10)", cost: 900, quantity: 0, }, { - img: "https://pixabay.com/images/download/laptops-593296_640.jpg", + img: "", name: "Small Meeting Room (Capacity:5)", cost: 1100, quantity: 0, @@ -56,5 +56,4 @@ export const venueSlice = createSlice({ }); export const { incrementQuantity, decrementQuantity } = venueSlice.actions; - -export default venueSlice.reducer; +export default venueSlice.reducer; \ No newline at end of file