diff --git a/alimento-nextjs/app/(PublicRoutes)/customer/[customerId]/[vendorId]/(chat)/[dishId]/page.tsx b/alimento-nextjs/app/(PublicRoutes)/customer/[customerId]/[vendorId]/(chat)/[dishId]/page.tsx new file mode 100644 index 0000000..c6844b0 --- /dev/null +++ b/alimento-nextjs/app/(PublicRoutes)/customer/[customerId]/[vendorId]/(chat)/[dishId]/page.tsx @@ -0,0 +1,251 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Spinner } from '@/components/ui/spinner'; // Assuming you have a Spinner component +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { useParams } from 'next/navigation'; +import toast from 'react-hot-toast'; +import DishCardFE from '@/app/(PublicRoutes)/dishes/components/dishCardFE'; + +const ChatPage = () => { + const params = useParams<{ + customerId: string; + vendorId: string; + dishId: string; + }>(); + + const { customerId, vendorId, dishId } = params; + const [chat, setChat] = useState(null); // Holds the chat data + const [isLoading, setIsLoading] = useState(true); + const [message, setMessage] = useState(''); + const [error, setError] = useState(null); + const [sending, setSending] = useState(false); + + useEffect(() => { + if (!customerId || !vendorId || !dishId) { + setIsLoading(false); + return; + } + + const fetchChat = async () => { + try { + const res = await fetch('/data/chat.json'); + const data = await res.json(); + + const foundChat = data.chats.find( + (chat: any) => + chat.customerId === customerId && + chat.vendorId === vendorId && + chat.dishId === dishId + ); + + if (foundChat) { + setChat(foundChat); + } else { + setChat({ + customerId, + vendorId, + dishId, + messages: [], + }); + } + } catch (error) { + setError('Failed to load chat.'); + } finally { + setIsLoading(false); + } + }; + + fetchChat(); + }, [customerId, vendorId, dishId]); + + const handleSendMessage = async () => { + if (!message.trim()) return; + + setSending(true); + try { + if (!chat) { + toast.error('Error creating chat'); + } else { + const updatedChat = { + ...chat, + messages: [...chat.messages, { senderId: customerId, content: message }], + }; + setChat(updatedChat); + } + setMessage(''); + } catch (error) { + setError('Failed to send message'); + } finally { + setSending(false); + } + }; + + if (isLoading) { + return ; + } + + return ( +
+
+ {/* dish Info */} +
+ +
+ + {/* Chat Box */} +
+

+ Chat with vendor +

+ + {error &&

{error}

} + + {/* Chat Messages */} +
+ {chat ? ( + chat.messages.length > 0 ? ( + chat.messages.map((msg: any, index: number) => ( +
+
+ {msg.content} +
+
+ )) + ) : ( +

+ No messages yet. Start a conversation! +

+ ) + ) : ( +

Loading chat...

+ )} +
+ + {/* Message Input */} +
+ setMessage(e.target.value)} + className="flex-1 py-2 md:py-3 px-4 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-pink-500" + /> + +
+
+
+
+ ); +}; + +export default ChatPage; + + +// useEffect(() => { +// if (!customerId || !vendorId || !dishId) { +// setIsLoading(false); +// return; // Wait for query params +// } + +// const fetchChat = async () => { +// try { +// const { success, data, error } = await getSpecificChat( +// customerId as string, +// vendorId as string, +// dishId as string +// ); +// if (success) { +// setChat(data); +// } else { +// if (!error) { +// toast.error('error'); +// return; +// } +// toast.error(error); +// } +// } catch (error) { +// setError('Failed to load chat.'); +// } finally { +// setIsLoading(false); +// } +// }; + +// fetchChat(); +// }, [customerId, vendorId, dishId]); + +// const handleSendMessage = async () => { +// if (!message.trim()) return; + +// setSending(true); +// try { +// if (!chat) { +// // Create a new chat if it doesn't exist +// const { success, data, error } = await createChat( +// customerId as string, +// vendorId as string, +// dishId as string, +// message +// ); +// if (success) { +// setChat(data); +// } else { +// if (!error) { +// toast.error('error'); +// return; +// } +// toast.error(error); +// } +// } else { +// // Add message to the existing chat +// const updatedChat = { +// ...chat, +// messages: [...chat.messages, { senderId: customerId, content: message }], +// }; +// setChat(updatedChat); +// } +// setMessage(''); // Clear message input +// } catch (error) { +// setError('Failed to send message'); +// } finally { +// setSending(false); +// } +// }; diff --git a/alimento-nextjs/app/(PublicRoutes)/customer/[customerId]/[vendorId]/page.tsx b/alimento-nextjs/app/(PublicRoutes)/customer/[customerId]/[vendorId]/page.tsx index 43d00dd..bf5336b 100644 --- a/alimento-nextjs/app/(PublicRoutes)/customer/[customerId]/[vendorId]/page.tsx +++ b/alimento-nextjs/app/(PublicRoutes)/customer/[customerId]/[vendorId]/page.tsx @@ -25,8 +25,8 @@ const DishesByVendor = () => { const [searchQuery, setSearchQuery] = useState(''); const [isMounted, setIsMounted] = useState(false); - const params = useParams<{ userId: string; vendorId: string }>(); - const { userId, vendorId } = params; + const params = useParams<{ customerId: string; vendorId: string }>(); + const { customerId, vendorId } = params; useEffect(() => { const fetchData = async () => { @@ -60,7 +60,7 @@ const DishesByVendor = () => { ); return ( -
+
@@ -89,7 +89,7 @@ const DishesByVendor = () => {
{filteredDishes.length ? ( filteredDishes.map(dish => ( - +
diff --git a/alimento-nextjs/app/(PublicRoutes)/dishes/components/dishCardFE.tsx b/alimento-nextjs/app/(PublicRoutes)/dishes/components/dishCardFE.tsx index 467b79b..c54c765 100644 --- a/alimento-nextjs/app/(PublicRoutes)/dishes/components/dishCardFE.tsx +++ b/alimento-nextjs/app/(PublicRoutes)/dishes/components/dishCardFE.tsx @@ -20,6 +20,7 @@ interface DishCardProps { price: number; description: string; images: ImageInterface[]; + isStatic?: boolean } const DishCardFE: React.FC = ({ @@ -28,6 +29,8 @@ const DishCardFE: React.FC = ({ price, description, images, + isStatic + }) => { const { addToWishlists, isWishlisted } = useWishlist(); const session = useSession(); @@ -83,6 +86,7 @@ const DishCardFE: React.FC = ({

{name}

{description}

Price: ₹{price}

+ {isStatic&&(<>
)}
+ )}
); diff --git a/alimento-nextjs/public/chatbg.png b/alimento-nextjs/public/chatbg.png new file mode 100644 index 0000000..12be842 Binary files /dev/null and b/alimento-nextjs/public/chatbg.png differ diff --git a/alimento-nextjs/public/chatbgLight.png b/alimento-nextjs/public/chatbgLight.png new file mode 100644 index 0000000..301d951 Binary files /dev/null and b/alimento-nextjs/public/chatbgLight.png differ diff --git a/alimento-nextjs/public/data/chat.json b/alimento-nextjs/public/data/chat.json new file mode 100644 index 0000000..4e44624 --- /dev/null +++ b/alimento-nextjs/public/data/chat.json @@ -0,0 +1,112 @@ +{ + "chats": [ + { + "userId": "74a5b406-5321-45f3-b87a-dea188054901", + "vendorId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "dishId": "a1", + "messages": [ + { + "senderId": "74a5b406-5321-45f3-b87a-dea188054901", + "content": "Hi, is this product still available?" + }, + { + "senderId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "content": "Yes, it's still available. Would you like to know more about it?" + }, + { + "senderId": "74a5b406-5321-45f3-b87a-dea188054901", + "content": "Could you send more details or images?" + }, + { + "senderId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "content": "Sure! Here are more details. The product is in excellent condition, and I can share more pictures if you like." + } + ] + }, + { + "userId": "74a5b406-5321-45f3-b87a-dea188054901", + "vendorId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "dishId": "a2", + "messages": [ + { + "senderId": "74a5b406-5321-45f3-b87a-dea188054901", + "content": "Hello, I have a question about this item. Is it negotiable?" + }, + { + "senderId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "content": "Hi! Yes, the price is negotiable. What price are you considering?" + }, + { + "senderId": "74a5b406-5321-45f3-b87a-dea188054901", + "content": "How about 10% off the listed price?" + }, + { + "senderId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "content": "Let me think about it, and I'll get back to you." + } + ] + }, + { + "userId": "74a5b406-5321-45f3-b87a-dea188054901", + "vendorId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "dishId": "a3", + "messages": [ + { + "senderId": "74a5b406-5321-45f3-b87a-dea188054901", + "content": "Hi, is this product compatible with my model?" + }, + { + "senderId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "content": "Yes, it is. It will work perfectly with your model." + }, + { + "senderId": "74a5b406-5321-45f3-b87a-dea188054901", + "content": "Great! Can you ship it to my location?" + }, + { + "senderId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "content": "Absolutely! Please share your shipping address." + } + ] + }, + { + "userId": "74a5b406-5321-45f3-b87a-dea188054901", + "vendorId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "dishId": "b1", + "messages": [ + { + "senderId": "74a5b406-5321-45f3-b87a-dea188054901", + "content": "I'm interested in this item. Can you tell me if it's available?" + }, + { + "senderId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "content": "Yes, it's available. Let me know if you'd like to see more pictures or get more details." + } + ] + }, + { + "userId": "74a5b406-5321-45f3-b87a-dea188054901", + "vendorId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "dishId": "c1", + "messages": [ + { + "senderId": "74a5b406-5321-45f3-b87a-dea188054901", + "content": "Is this product in new condition?" + }, + { + "senderId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "content": "Yes, it's in brand new condition, never used." + }, + { + "senderId": "74a5b406-5321-45f3-b87a-dea188054901", + "content": "Do you offer returns if it doesn't fit?" + }, + { + "senderId": "f42a9a12-3c63-4f75-9b8e-d92896b4c5d1", + "content": "Yes, I offer a 30-day return policy." + } + ] + } + ] + } + \ No newline at end of file diff --git a/alimento-nextjs/public/food2a.jpg b/alimento-nextjs/public/food2a.jpg new file mode 100644 index 0000000..b1f39fb Binary files /dev/null and b/alimento-nextjs/public/food2a.jpg differ diff --git a/alimento-nextjs/public/food2b.avif b/alimento-nextjs/public/food2b.avif new file mode 100644 index 0000000..56ad1c6 Binary files /dev/null and b/alimento-nextjs/public/food2b.avif differ