diff --git a/client/public/images/chat-2.png b/client/public/images/chat-2.png new file mode 100644 index 0000000..89c3281 Binary files /dev/null and b/client/public/images/chat-2.png differ diff --git a/client/public/images/chat-3.png b/client/public/images/chat-3.png new file mode 100644 index 0000000..e59780f Binary files /dev/null and b/client/public/images/chat-3.png differ diff --git a/client/public/images/chat-4.png b/client/public/images/chat-4.png new file mode 100644 index 0000000..f7ae71c Binary files /dev/null and b/client/public/images/chat-4.png differ diff --git a/client/public/images/chat.png b/client/public/images/chat.png new file mode 100644 index 0000000..6ac2b4d Binary files /dev/null and b/client/public/images/chat.png differ diff --git a/client/public/index.html b/client/public/index.html index 25058bd..8383bd0 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -1,21 +1,19 @@ - - - - - - - - - - - - - - CINEMAGIC - - - - - -
- + + + + + + CINEMAGIC + + + + + + +
+ - - + + + \ No newline at end of file diff --git a/client/src/App.css b/client/src/App.css index 6dd827a..b6f42d0 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -4,6 +4,7 @@ padding: 0; font-family: 'Cinzel', serif; } + .home, .about, .contact-page { @@ -15,8 +16,20 @@ font-size: 100px; } -.about-cover, .contact-cover { +.about-cover, +.contact-cover { background-position: center; background-size: cover; background-repeat: no-repeat; } + + + +input, +textarea { + font-family: 'Roboto', sans-serif !important; +} + +input:focus { + outline: none; +} \ No newline at end of file diff --git a/client/src/App.js b/client/src/App.js index ef23a19..8bfa052 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -35,6 +35,7 @@ import UserProfile from "./components/pages/UserProfile"; import NotFound from "./components/pages/NotFound"; import PaymentSuccess from "./components/pages/PaymentSuccess"; import PaymentCancel from "./components/pages/PaymentCancel"; + import { useSelector } from "react-redux"; import { useDispatch } from "react-redux"; diff --git a/client/src/components/Chat.js b/client/src/components/Chat.js new file mode 100644 index 0000000..19b7bd6 --- /dev/null +++ b/client/src/components/Chat.js @@ -0,0 +1,72 @@ +import React, { useState } from 'react'; +import './css/Chat.css'; // Path to CSS file + +const Chat = () => { + const [isOpen, setIsOpen] = useState(false); + const [messages, setMessages] = useState([]); + const [input, setInput] = useState(''); + + const sendMessage = (event) => { + event.preventDefault(); + if (input.trim()) { + setMessages([...messages, { text: input, sender: 'client' }]); + setInput(''); + } + }; + + const toggleChat = () => { + setIsOpen(!isOpen); + }; + + const faqs = [ + "What are the opening hours?", + "How to book a ticket?", + "Are there any discounts available?", + // ... more FAQs + ]; + + const sendFaqMessage = (faq) => { + setMessages([...messages, { text: faq, sender: 'client' }]); + }; + + return ( +
+ {isOpen && ( +
+
+ CINEMAGIC +
+
+ {faqs.map((faq, index) => ( +
sendFaqMessage(faq)}> + {faq} +
+ ))} +
+
+ {messages.map((message, index) => ( +
+ {message.text} +
+ ))} +
+
+ setInput(e.target.value)} + placeholder="Type a message..." + /> + +
+
+ )} + +
+ ); +}; + +export default Chat; diff --git a/client/src/components/css/Chat.css b/client/src/components/css/Chat.css new file mode 100644 index 0000000..61316f3 --- /dev/null +++ b/client/src/components/css/Chat.css @@ -0,0 +1,120 @@ +.chat-container { + position: fixed; + bottom: 0; + right: 0; + z-index: 1001; + margin: 0; + padding: 0; +} + +.chat-interface { + position: fixed; + bottom: 100px; + right: 20px; + width: 300px; + height: 400px; + background-color: #525252; + border-radius: 15px; + box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); + display: flex; + flex-direction: column; + justify-content: space-between; + padding: 15px 10px; + z-index: 2; + overflow: hidden; +} + +.chat-header { + background-color: #ffd700; + color: #333; + text-align: center; + padding: 10px; + border-radius: 15px 15px 0 0; +} + +.faq-container { + overflow-y: auto; + flex-grow: 1; + margin-top: 10px; +} + +.faq { + padding: 8px; + margin: 10px 0; + background-color: none; + border: 1px solid #ffd700; + border-radius: 5px; + cursor: pointer; + font-size: 14px; + color: #ffd700; +} + +.faq:hover { + background-color: #ffd700; + color: #525252; + transition: 0.5s; +} + +.chat-messages { + overflow-y: auto; + flex-grow: 1; +} + +.message { + margin: 5px 0; + padding: 8px 12px; + background-color: #007bff; + color: white; + border-radius: 15px; + max-width: 80%; + align-self: flex-end; +} + +.message.admin { + background-color: #f1f0f0; + color: black; + align-self: flex-start; +} + +.message-input-container { + display: flex; +} + +.message-input { + flex-grow: 1; + border-radius: 15px; + padding: 10px; + border: 1px solid #ddd; +} + +.send-button { + background-color: #ffd700; + color: #333; + border: none; + padding: 10px 15px; + margin-left: 5px; + border-radius: 15px; + +} + +.chat-toggle { + position: fixed; + bottom: 20px; + right: 20px; + background-color: #ffd700; + width: 50px; + height: 50px; + border: none; + border-radius: 50%; + box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + z-index: 3; +} + +.chat-icon { + width: 40px; + height: 40px; +} \ No newline at end of file diff --git a/client/src/components/pages/About.js b/client/src/components/pages/About.js index 764e57c..b329cd9 100644 --- a/client/src/components/pages/About.js +++ b/client/src/components/pages/About.js @@ -1,5 +1,6 @@ import React from "react"; import "../css/About.css"; +import Chat from "../Chat"; const About = () => { return ( @@ -41,6 +42,7 @@ const About = () => { + ); }; diff --git a/client/src/components/pages/Booking.js b/client/src/components/pages/Booking.js index e3af93a..f02cad1 100644 --- a/client/src/components/pages/Booking.js +++ b/client/src/components/pages/Booking.js @@ -4,6 +4,7 @@ import { Link, useParams } from "react-router-dom"; import axios from "axios"; import { useLoading } from "../LoadingContext.js"; import { TailSpin } from "react-loader-spinner"; +import Chat from "../Chat"; const Booking = () => { const { id } = useParams(); @@ -127,6 +128,7 @@ const Booking = () => { )} + ); }; diff --git a/client/src/components/pages/Contact.js b/client/src/components/pages/Contact.js index 703316b..dabb32f 100644 --- a/client/src/components/pages/Contact.js +++ b/client/src/components/pages/Contact.js @@ -5,6 +5,8 @@ import axios from "axios"; import Swal from "sweetalert2"; import { TailSpin } from "react-loader-spinner"; import { useLoading } from "../LoadingContext.js"; +import Chat from "../Chat"; + const ContactPage = () => { const { loading, setLoading } = useLoading(); const [formData, setFormData] = useState({ @@ -132,6 +134,7 @@ const ContactPage = () => { {" "} + ); }; diff --git a/client/src/components/pages/Home.js b/client/src/components/pages/Home.js index 34b8fd3..500c955 100644 --- a/client/src/components/pages/Home.js +++ b/client/src/components/pages/Home.js @@ -3,6 +3,7 @@ import "../../App.css"; import Section from "../Section"; import Cards from "../Cards"; import SliderSection from "../SliderSection"; +import Chat from "../Chat"; function Home() { return ( @@ -10,6 +11,7 @@ function Home() {
+ ); } diff --git a/client/src/components/pages/Movie.js b/client/src/components/pages/Movie.js index 25ad171..11abea6 100644 --- a/client/src/components/pages/Movie.js +++ b/client/src/components/pages/Movie.js @@ -7,12 +7,13 @@ import { TailSpin } from "react-loader-spinner"; import { useLoading } from "../LoadingContext.js"; import { Link } from "react-router-dom"; import Swal from "sweetalert2"; +import Chat from "../Chat"; const MovieFeedbackForm = () => { var { id } = useParams(); const [message, setMessage] = useState(""); const [rating, setRating] = useState(0); - const [hover, setHover] = useState(0); + const [hover, setHover] = useState(0); const handleFeedbackChange = (event) => { setMessage(event.target.value); @@ -77,7 +78,7 @@ const MovieFeedbackForm = () => { onChange={handleFeedbackChange} value={message} > -
+
{[...Array(5)].map((_, index) => { const ratingValue = index + 1; return ( @@ -227,6 +228,7 @@ function MoviePage() {
)} +
); } diff --git a/client/src/components/pages/Seating.js b/client/src/components/pages/Seating.js index cb81c39..ecd485b 100644 --- a/client/src/components/pages/Seating.js +++ b/client/src/components/pages/Seating.js @@ -8,6 +8,7 @@ import { TailSpin } from "react-loader-spinner"; import { useLoading } from "../LoadingContext.js"; import { UserContext } from "../UserContext"; import Swal from "sweetalert2"; +import Chat from "../Chat"; export default function Seating() { const [selectedSeats, setSelectedSeats] = useState([]); @@ -127,7 +128,7 @@ export default function Seating() { const totalPrice = selectedSeats.length * seatPrice; // Check if userData is empty, and if so, navigate to the login page - useEffect(() => {}, [userData, navigate]); + useEffect(() => { }, [userData, navigate]); return (
@@ -218,31 +219,35 @@ function Cinema({ bookedSeats, selectedSeats, onSelectedSeatsChange }) { } return ( -
-
-
- {Array.from({ length: 64 }, (_, i) => i).map((seat) => { - const isSelected = selectedSeats.includes(seat); - const isBooked = bookedSeats.includes(seat); - return ( - handleSelectedState(seat) : null} - onKeyPress={ - !isBooked - ? (e) => e.key === "Enter" && handleSelectedState(seat) - : null - } - /> - ); - })} +
+
+
+
+ {Array.from({ length: 64 }, (_, i) => i).map((seat) => { + const isSelected = selectedSeats.includes(seat); + const isBooked = bookedSeats.includes(seat); + return ( + handleSelectedState(seat) : null} + onKeyPress={ + !isBooked + ? (e) => e.key === "Enter" && handleSelectedState(seat) + : null + } + /> + ); + })} +
+
+
); }