diff --git a/adventure-rental-app/package-lock.json b/adventure-rental-app/package-lock.json
index a639fbe..36188da 100644
--- a/adventure-rental-app/package-lock.json
+++ b/adventure-rental-app/package-lock.json
@@ -11,6 +11,7 @@
"axios": "^1.11.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
+ "react-icons": "^5.5.0",
"react-router-dom": "^7.7.1"
},
"devDependencies": {
@@ -3580,6 +3581,15 @@
"react": "^19.1.1"
}
},
+ "node_modules/react-icons": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
+ "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
"node_modules/react-refresh": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
diff --git a/adventure-rental-app/package.json b/adventure-rental-app/package.json
index fd7a4d8..eae0c45 100644
--- a/adventure-rental-app/package.json
+++ b/adventure-rental-app/package.json
@@ -13,6 +13,7 @@
"axios": "^1.11.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
+ "react-icons": "^5.5.0",
"react-router-dom": "^7.7.1"
},
"devDependencies": {
diff --git a/adventure-rental-app/src/App.jsx b/adventure-rental-app/src/App.jsx
index e817b11..f8f8fa8 100644
--- a/adventure-rental-app/src/App.jsx
+++ b/adventure-rental-app/src/App.jsx
@@ -1,9 +1,16 @@
-import AuthPage from './AuthPage'
+import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
+import AuthPage from './AuthPage';
+import ChatbotPage from './ChatbotPage';
function App() {
return (
-
- )
+
+
+ } />
+ } />
+
+
+ );
}
export default App
diff --git a/adventure-rental-app/src/ChatbotPage.jsx b/adventure-rental-app/src/ChatbotPage.jsx
new file mode 100644
index 0000000..316f7af
--- /dev/null
+++ b/adventure-rental-app/src/ChatbotPage.jsx
@@ -0,0 +1,121 @@
+import React, { useState } from 'react';
+import { FiCamera, FiSend, FiUser } from 'react-icons/fi';
+
+const ChatbotPage = () => {
+ const [messages, setMessages] = useState([
+ { id: 1, text: 'Halo Kak! 👋 Selamat datang di Adventure Rental. Saya Maya, asisten virtual yang siap membantu Anda. Ada yang bisa saya bantu?', sender: 'bot', timestamp: '10:30' },
+ ]);
+ const [inputMessage, setInputMessage] = useState('');
+ const [isTyping, setIsTyping] = useState(false);
+
+ const handleSendMessage = () => {
+ if (inputMessage.trim() === '') return;
+
+ const newMessage = {
+ id: messages.length + 1,
+ text: inputMessage,
+ sender: 'user',
+ timestamp: new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }),
+ };
+ setMessages((prevMessages) => [...prevMessages, newMessage]);
+ setInputMessage('');
+ setIsTyping(true);
+
+ // Simulate bot response
+ setTimeout(() => {
+ const botResponse = {
+ id: messages.length + 3, // Adjusted for the new message and typing indicator
+ text: `Anda mengirim: "${inputMessage}"`,
+ sender: 'bot',
+ timestamp: new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }),
+ };
+ setIsTyping(false);
+ setMessages((prevMessages) => [...prevMessages, botResponse]);
+ }, 2000);
+ };
+
+ const handleKeyPress = (e) => {
+ if (e.key === 'Enter') {
+ handleSendMessage();
+ }
+ };
+
+ return (
+
+
+ {/* Header */}
+
+
+ M
+
+
+
Maya
+
Adventure Assistant
+
+
+
+ {/* Chat Window */}
+
+ {messages.map((message) => (
+
+
+
+
{message.text}
+
{message.timestamp}
+
+
+ {message.sender === 'bot' && (
+
+ M
+
+ )}
+ {message.sender === 'user' && (
+
+
+
+ )}
+
+ ))}
+ {isTyping && (
+
+ )}
+
+
+ {/* Input Area */}
+
+
+ setInputMessage(e.target.value)}
+ onKeyPress={handleKeyPress}
+ />
+
+
+
+
+
+ );
+};
+
+export default ChatbotPage;
\ No newline at end of file
diff --git a/adventure-rental-app/src/index.css b/adventure-rental-app/src/index.css
index 58559a9..bd9ab4f 100644
--- a/adventure-rental-app/src/index.css
+++ b/adventure-rental-app/src/index.css
@@ -17,3 +17,35 @@ input:-webkit-autofill:active {
transition: background-color 5000s ease-in-out 0s;
}
+
+.typing-indicator {
+ display: flex;
+ align-items: center;
+}
+
+.typing-indicator span {
+ height: 8px;
+ width: 8px;
+ background-color: #9E9E9E;
+ border-radius: 50%;
+ display: inline-block;
+ margin: 0 2px;
+ animation: typing-wave 1.4s infinite ease-in-out both;
+}
+
+.typing-indicator span:nth-child(1) {
+ animation-delay: -0.32s;
+}
+
+.typing-indicator span:nth-child(2) {
+ animation-delay: -0.16s;
+}
+
+@keyframes typing-wave {
+ 0%, 80%, 100% {
+ transform: scale(0);
+ }
+ 40% {
+ transform: scale(1.0);
+ }
+}
diff --git a/adventure-rental-app/tailwind.config.js b/adventure-rental-app/tailwind.config.js
index 83f7b3c..1368b89 100644
--- a/adventure-rental-app/tailwind.config.js
+++ b/adventure-rental-app/tailwind.config.js
@@ -12,6 +12,9 @@ export default {
'brand-light': '#F5F5DC',
'brand-gray': '#A9A9A9',
'brand-orange': '#D97706', // Adventure Orange
+ 'chat-header': '#003C5A',
+ 'chat-bg': '#0084A8',
+ 'chat-input-bg': '#0A192F',
},
fontFamily: {
sans: ['Poppins', 'sans-serif'],