diff --git a/components/LandingUI.tsx b/components/LandingUI.tsx index 68aa3f1..91f98f1 100644 --- a/components/LandingUI.tsx +++ b/components/LandingUI.tsx @@ -3,40 +3,31 @@ import Image from "next/image" import Product from "./Product/Product" import { FieldTimeOutlined } from '@ant-design/icons'; import Hero from '../public/main/hero.png' -const products = [ - { - id: 1, - name: 'Combo 2 Nem Nướng Xiên Que Giảm 4,000', - price: 24000, - image: 'https://salt.tikicdn.com/cache/280x280/ts/product/1c/1c/1c/0e6b4b1b1b2b1b1b1b1b1b1b1b1b1b1b.jpg' - }, - { - id: 2, - name: 'Combo Cơm Trộn Poke , Tàu Hũ Singapore & 1 Chai Nuớc', - price: 65000, - image: 'https://salt.tikicdn.com/cache/280x280/ts/product/1c/1c/1c/0e6b4b1b1b2b1b1b1b1b1b1b1b1b1b1b.jpg' - }, - { - id: 3, - name: 'Combo Cơm Trộn Poke , Tàu Hũ Singapore & 1 Chai Nuớc', - price: 65000, - image: 'https://salt.tikicdn.com/cache/280x280/ts/product/1c/1c/1c/0e6b4b1b1b2b1b1b1b1b1b1b1b1b1b1b.jpg' - }, - { - id: 4, - name: 'Combo Cơm Trộn Poke , Tàu Hũ Singapore & 1 Chai Nuớc', - price: 65000, - image: 'https://salt.tikicdn.com/cache/280x280/ts/product/1c/1c/1c/0e6b4b1b1b2b1b1b1b1b1b1b1b1b1b1b.jpg' - }, -] - +import { TypeAnimation } from "react-type-animation"; function LandingUI({products} : any) : JSX.Element { return ( - +
Delivery
{/* The Best */} -
The Fastest
+ { + console.log('Done typing!'); // Place optional callbacks anywhere in the array + } + ]} + wrapper="div" + cursor={true} + repeat={Infinity} + style={{ fontSize: '36px', marginTop: '8px' }} + />
Delivery in
Your University
diff --git a/components/MainNavigation.tsx b/components/MainNavigation.tsx index 8f565a4..3a8f02b 100644 --- a/components/MainNavigation.tsx +++ b/components/MainNavigation.tsx @@ -9,11 +9,27 @@ import { signOut } from 'firebase/auth' import { auth } from '../utils/firebase' import { useAuthState } from 'react-firebase-hooks/auth' import CartIcon from './CartIcon' -function MainNavigation({user} : any) : JSX.Element { +import { IProduct } from '../interfaces' +import { useState } from 'react' +import ProductList from './Product/ProductList' +function MainNavigation({user, products} : any) : JSX.Element { + if(!products){ + return <> + } const [loggedInUser, loading, error] = useAuthState(auth); + const [searchTerm, setSearchTerm] = useState(''); + + const handleSearch = (event : any) => { + setSearchTerm(event.target.value); + }; + + const filteredProducts = products.filter((product: IProduct) => { + return product.name.toLowerCase().includes(searchTerm.toLowerCase()) + }); + return ( -
+
logo @@ -26,8 +42,17 @@ function MainNavigation({user} : any) : JSX.Element { }, }} > - } /> + } value={searchTerm} onChange={handleSearch}/> + { + searchTerm && ( +
+ { + + } +
+ ) + }
{/* User */}
diff --git a/components/Order/OrderItemComponent.tsx b/components/Order/OrderItemComponent.tsx index 37b2e34..9de1652 100644 --- a/components/Order/OrderItemComponent.tsx +++ b/components/Order/OrderItemComponent.tsx @@ -21,7 +21,7 @@ function OrderItemComponent(props:Props) { return ( - + { dispatch.user.addProductCart(product); + notification.success({ + message: 'Thêm sản phẩm thành công', + description: 'Bạn đã thêm sản phẩm ' + product.name + ' vào giỏ hàng', + duration: 2, + }); } + + const [isModalOpen, setIsModalOpen] = useState(false); + + const showModal = () => { + setIsModalOpen(true); + }; + + const handleOk = () => { + setIsModalOpen(false); + }; + + const handleCancel = () => { + setIsModalOpen(false); + }; + return ( - product &&
- {"product"} -
- {product.name} -
- {convertToDongString(product.price)} - - -
-
-
+ <> + { + product && (
+ + {"product"} + +
+ {product.name} +
+ {convertToDongString(product.price)} + + +
+
+
) + } + { + product && ( + + + + {"product"} + + + Tên sản phẩm: {product.name} + Số lượng: {product.quantity} + Nhà cung cấp: {product.shop} + Đơn giá: {convertToDongString(product.price)} + + + + + + + + ) + } + ) } diff --git a/components/Product/ProductList.tsx b/components/Product/ProductList.tsx index 0a48d96..8e3767a 100644 --- a/components/Product/ProductList.tsx +++ b/components/Product/ProductList.tsx @@ -1,24 +1,36 @@ import { Skeleton, Typography } from "antd" import { useEffect, useState } from "react" -import { getProductsFromFirebaseBasedOnCategory } from "../../utils/firebase" +import { getProductsFromFirebaseBasedOnShop } from "../../utils/firebase" import Product from "./Product" -function ProductList({category, products} : any) : JSX.Element { +function ProductList({category, products, loadingSkeleton=true} : any) : JSX.Element { return ( -
-
{category}
-
- { - products.length == 0 ? : ( - products.map((product : any) => { - return ( - + <> + {loadingSkeleton && ( +
+
{category}
+ +
+ ) } + { + products.length !== 0 && ( +
+
{category}
+
+ { + products.length == 0 ? : ( + products.map((product : any) => { + return ( + + ) + }) ) - }) + } +
+
) } -
-
+ ) } diff --git a/container/HomeContainer.tsx b/container/HomeContainer.tsx index 2c3cb13..27dd230 100644 --- a/container/HomeContainer.tsx +++ b/container/HomeContainer.tsx @@ -4,10 +4,11 @@ import ProductList from '../components/Product/ProductList' import { useEffect, useState } from 'react'; import { getAllProductsFromFirebase } from '../utils/firebase'; -import { message } from 'antd'; +import { Avatar, message, Segmented } from 'antd'; import { collection, onSnapshot } from 'firebase/firestore'; import { db } from '../utils/firebase'; -function HomeContainer({ user, setUser,products,loading }: any): JSX.Element { +import { UserOutlined } from '@ant-design/icons'; +function HomeContainer({ user, setUser,products,loading, setShopSelect, loadingSkeleton }: any): JSX.Element { @@ -15,6 +16,7 @@ function HomeContainer({ user, setUser,products,loading }: any): JSX.Element { return products.filter((product: any) => product.category === category) } + const randomProducts = products .sort(() => Math.random() - 0.5) // Shuffle the array .slice(0, 4); // Take the first 4 elements @@ -22,17 +24,51 @@ function HomeContainer({ user, setUser,products,loading }: any): JSX.Element { const CategoryTitle = ["Đồ Ăn", "Đồ Uống", "Khác"]; return ( - <> +
+
+ setShopSelect(value)} + options={[ + { + label: ( +
+ +
711
+
+ ), + value: '711', + }, + { + label: ( +
+ +
Laha Coffee
+
+ ), + value: 'Laha Coffee', + }, + { + label: ( +
+ +
Passio
+
+ ), + value: 'Passio', + }, + ]} + /> +
{ CategoryTitle.map((category) => { - console.log("category", category) return ( - + ) }) } - +
) } diff --git a/container/OrderContainer.tsx b/container/OrderContainer.tsx index f47e7e5..acbe152 100644 --- a/container/OrderContainer.tsx +++ b/container/OrderContainer.tsx @@ -1,4 +1,4 @@ -import { Button, Typography } from "antd"; +import { Button, message, Typography } from "antd"; import { useEffect, useState } from "react"; import { connect } from "react-redux"; import OrderDetailsComponent from "../components/Order/OrderDetailsComponent"; @@ -7,7 +7,9 @@ import { ICart, IProduct } from "../interfaces"; import { Dispatch, RootState } from "../store"; import { Modal } from "antd"; import ProductList from "../components/Product/ProductList"; - +import { createOrder } from "../utils/firebase"; +import { useAuthState } from "react-firebase-hooks/auth"; +import { auth } from "../utils/firebase"; export interface Product { price: number; name: string; @@ -37,6 +39,7 @@ const removeItem = (id: string, array: any[]) => { let idRemove : string = ""; function OrderContainer(props: any): JSX.Element { + const [loggedInUser] = useAuthState(auth); const deliveryHeading = { section: "Thông tin giao hàng", @@ -149,7 +152,13 @@ function OrderContainer(props: any): JSX.Element { }; const handleSubmit = () => { - + if(loggedInUser){ + createOrder({ + ...cart, + user: loggedInUser.uid, + }); + } + message.success("Đặt hàng thành công"); } diff --git a/container/SearchContainer.tsx b/container/SearchContainer.tsx index e69de29..b458389 100644 --- a/container/SearchContainer.tsx +++ b/container/SearchContainer.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +function SearchContainer() { + return ( +
SearchContainer
+ ) +} + +export default SearchContainer \ No newline at end of file diff --git a/package.json b/package.json index 634633e..7685a38 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,10 @@ "react-dom": "18.1.0", "react-firebase-hooks": "^5.1.1", "react-redux": "^8.0.5", + "react-type-animation": "^2.1.2", "redux": "^4.2.0", - "sass": "^1.54.9" + "sass": "^1.54.9", + "uuidv4": "^6.2.13" }, "devDependencies": { "@types/node": "17.0.35", diff --git a/pages/client/index.tsx b/pages/client/index.tsx index d211d35..2ccb207 100644 --- a/pages/client/index.tsx +++ b/pages/client/index.tsx @@ -2,7 +2,7 @@ import React from 'react' function ClientPage() { return ( -
hui
+ <> ) } diff --git a/pages/client/search/index.jsx b/pages/client/search/index.jsx deleted file mode 100644 index 462dd33..0000000 --- a/pages/client/search/index.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react' - -function index() { - return ( - <> - - - - - ) -} - -export default index \ No newline at end of file diff --git a/pages/index.tsx b/pages/index.tsx index 9830f08..5c0128c 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,14 +1,16 @@ // Components import -import MainNavigation from '../components/MainNavigation'; -import MainFooter from '../components/MainFooter'; -import { Layout, message } from 'antd'; -import HomeContainer from '../container/HomeContainer'; +import { Layout } from 'antd'; import { useEffect, useState } from 'react'; -import { auth, getAllProductsFromFirebase, getUserFromFirebase } from '../utils/firebase'; import { useAuthState } from 'react-firebase-hooks/auth'; +import MainFooter from '../components/MainFooter'; +import MainNavigation from '../components/MainNavigation'; +import HomeContainer from '../container/HomeContainer'; +import { auth, getProductsFromFirebaseBasedOnShop, getUserFromFirebase } from '../utils/firebase'; function App() { + const [loadingSkeleton, setLoadingSkeleton] = useState(true); const [loggedInUser, loading, error] = useAuthState(auth); + const [shopSelect, setShopSelect] = useState('711'); const [products, setProducts] = useState([]); const [loadingProduct, setLoading] = useState(true); const [user, setUser] = useState({ @@ -19,6 +21,7 @@ function App() { cart: [], phoneNumber: '', }); + console.log('shopSelect', shopSelect) useEffect(() => { if (loggedInUser) { @@ -27,27 +30,31 @@ function App() { console.log(res); if (!res) { - message.error('Get user failed') return; } setUser(res) } ) - + // getProductsFromFirebaseBasedOnShop(shopSelect) + // .then((res) => { + // console.log(res); + // setProducts(res); + // setLoading(false); + // }) } (async () => { - const products = await getAllProductsFromFirebase() + const products = await getProductsFromFirebaseBasedOnShop(shopSelect) setProducts(products); setLoading(loadingProduct); - + setLoadingSkeleton(false); })(); - }, []) + }, [shopSelect]) return <> - - + + ; diff --git a/styles/components/landing-ui.scss b/styles/components/landing-ui.scss index 59fe09d..637d051 100644 --- a/styles/components/landing-ui.scss +++ b/styles/components/landing-ui.scss @@ -1,6 +1,6 @@ .landing-ui{ width: 100%; - height: calc(100vh - 80px); + height: calc(100vh); background-color: white; .slogan{ @@ -24,7 +24,7 @@ &-product{ position: absolute; - top: 50px; + top: 120px; right: 130px; z-index: 1; display: flex; @@ -33,7 +33,7 @@ } &-image{ position: absolute; - top: 20px; + top: 80px; right: 40px; z-index: 0; } diff --git a/styles/components/main-navigation.scss b/styles/components/main-navigation.scss index 863d08e..7b7bb71 100644 --- a/styles/components/main-navigation.scss +++ b/styles/components/main-navigation.scss @@ -1,10 +1,12 @@ .main-navigation{ height: 64; line-height: 64px; - padding: 0 60px; + padding: 0 80px; display: flex; justify-content: space-between; background-color: white; + box-shadow: $box-shadow; + position: relative; .left{ display: flex; @@ -40,4 +42,16 @@ margin-left: 20px; color: #000; } +} + +.search-result{ + position: absolute; + font-weight: 600; + top: 64px; + left: 0; + right: 0; + max-height: calc(100vh - 64px); + z-index: 100; + overflow-y: scroll; + box-shadow: $box-shadow; } \ No newline at end of file diff --git a/styles/components/product.scss b/styles/components/product.scss index 41b5eaf..c79796b 100644 --- a/styles/components/product.scss +++ b/styles/components/product.scss @@ -1,16 +1,22 @@ .product-list{ padding: 10px 60px; + display: flex; + flex-flow: column nowrap; + align-items: center; &-title{ + margin-top: 20px; + text-transform: uppercase; font-family: 'Roboto'; font-style: normal; font-weight: 700; font-size: 25px; line-height: 41px; margin-bottom: 24px; + text-align: center; div{ height: 3px; - width: 100px; + width: 150px; background-color: $color-primary; } } diff --git a/utils/firebase.js b/utils/firebase.js index f08bb5b..95e2b30 100644 --- a/utils/firebase.js +++ b/utils/firebase.js @@ -1,5 +1,6 @@ // Import the functions you need from the SDKs you need import { getApp, getApps, initializeApp } from "firebase/app"; + import { getAuth } from "firebase/auth"; import { collection, @@ -22,6 +23,11 @@ import { } from "firebase/storage"; // import { v4 as uuidv4 } from 'uuid'; +import { getAuth } from 'firebase/auth'; +import { collection, deleteDoc, doc, getDoc, getDocs, getFirestore, query, serverTimestamp, setDoc, updateDoc, where } from 'firebase/firestore'; +import { getDownloadURL, getStorage, ref, uploadBytesResumable } from "firebase/storage"; +import { v4 as uuidv4 } from 'uuid'; + // TODO: Add SDKs for Firebase products that you want to use // https://firebase.google.com/docs/web/setup#available-libraries @@ -130,6 +136,20 @@ export const createAnswer = async (questionID, email) => { return data; }; +export const createOrder = async (cart) => { + const id = uuidv4(); + const orderRef = doc(db, 'Orders' ,`${id}`) + await setDoc(orderRef, { + create: serverTimestamp(), + deviveryFee: cart.DeliveryFee, + location: cart.Location, + status: 'pending', + products: cart.ProductList, + user: cart.user, + id: id, + }); +} + export const getNoteFromFirebase = async (noteID) => { const noteRef = doc(db, "Notes", `${noteID}`); const noteSnap = await getDoc(noteRef); @@ -185,6 +205,10 @@ export const getProductsFromFirebaseBasedOnCategory = async (category) => { where("category", "==", category) ); const output = []; + +export const getProductsFromFirebaseBasedOnShop = async (shop) => { + const queryQuestion = query(collection(db, 'Products'), where("shop", "==", shop)); + const output = [] const querySnapshot = await getDocs(queryQuestion); querySnapshot.forEach((doc) => { output.push(doc.data()); @@ -192,11 +216,7 @@ export const getProductsFromFirebaseBasedOnCategory = async (category) => { return output; }; -<<<<<<< HEAD - -======= ->>>>>>> ee48cc70e9c1a04cc0144b44d28a717ad7a00dc7 export const getOrders = async (id) => { const queryQuestion = doc(db, "Orders", `${id}`); const noteSnap = await getDoc(queryQuestion); diff --git a/yarn.lock b/yarn.lock index c3c2a67..25194a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1052,6 +1052,11 @@ resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== +"@types/uuid@8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== + acorn-node@^1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" @@ -2972,6 +2977,11 @@ react-transition-group@^4.4.1, react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" +react-type-animation@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/react-type-animation/-/react-type-animation-2.1.2.tgz#9a67c87e8e7a5e4ca3411e30cd2fa308365307a4" + integrity sha512-6/t4Whl87sLR0c8kzvJngTrCV6OVy3jEeUZoe2svVu9VaYr951VD7OeUie1rIyeD8JfpBIqZGYrPFHZQ04XHrw== + react@18.1.0: version "18.1.0" resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890" @@ -3343,6 +3353,19 @@ util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +uuid@8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +uuidv4@^6.2.13: + version "6.2.13" + resolved "https://registry.yarnpkg.com/uuidv4/-/uuidv4-6.2.13.tgz#8f95ec5ef22d1f92c8e5d4c70b735d1c89572cb7" + integrity sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ== + dependencies: + "@types/uuid" "8.3.4" + uuid "8.3.2" + warning@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"