diff --git a/public/image/money.svg b/public/image/money.svg
new file mode 100644
index 0000000..7e91fb4
--- /dev/null
+++ b/public/image/money.svg
@@ -0,0 +1,52 @@
+
diff --git a/src/App.tsx b/src/App.tsx
index 66b4cd5..ff85065 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,12 +1,12 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
-import Layout from './Layout'
+import Router from './Router'
const queryClient = new QueryClient()
function App() {
return (
-
+
)
}
diff --git a/src/assets/svg/iconAdd.svg b/src/assets/svg/iconAdd.svg
new file mode 100644
index 0000000..7d9e59d
--- /dev/null
+++ b/src/assets/svg/iconAdd.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/svg/iconBag.svg b/src/assets/svg/iconBags.svg
similarity index 100%
rename from src/assets/svg/iconBag.svg
rename to src/assets/svg/iconBags.svg
diff --git a/src/assets/svg/iconBuy.svg b/src/assets/svg/iconBuy.svg
new file mode 100644
index 0000000..0787eaf
--- /dev/null
+++ b/src/assets/svg/iconBuy.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/assets/svg/iconDebt.svg b/src/assets/svg/iconDebt.svg
new file mode 100644
index 0000000..d3ecaca
--- /dev/null
+++ b/src/assets/svg/iconDebt.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/assets/svg/iconDelete.svg b/src/assets/svg/iconDelete.svg
new file mode 100644
index 0000000..8cb9b20
--- /dev/null
+++ b/src/assets/svg/iconDelete.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/assets/svg/iconEdit.svg b/src/assets/svg/iconEdit.svg
new file mode 100644
index 0000000..003f466
--- /dev/null
+++ b/src/assets/svg/iconEdit.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/svg/iconFolder.svg b/src/assets/svg/iconFolders.svg
similarity index 100%
rename from src/assets/svg/iconFolder.svg
rename to src/assets/svg/iconFolders.svg
diff --git a/src/assets/svg/iconImage.svg b/src/assets/svg/iconImage.svg
new file mode 100644
index 0000000..37f8128
--- /dev/null
+++ b/src/assets/svg/iconImage.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/assets/svg/iconMoney.svg b/src/assets/svg/iconMoney.svg
new file mode 100644
index 0000000..7e91fb4
--- /dev/null
+++ b/src/assets/svg/iconMoney.svg
@@ -0,0 +1,52 @@
+
diff --git a/src/assets/svg/iconMore.svg b/src/assets/svg/iconMore.svg
new file mode 100644
index 0000000..f797dfa
--- /dev/null
+++ b/src/assets/svg/iconMore.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/svg/iconNotes.svg b/src/assets/svg/iconNotes.svg
new file mode 100644
index 0000000..66b278c
--- /dev/null
+++ b/src/assets/svg/iconNotes.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/svg/iconStar.svg b/src/assets/svg/iconStar.svg
new file mode 100644
index 0000000..a4292bc
--- /dev/null
+++ b/src/assets/svg/iconStar.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/components/LinkDerectory/LinkDerectory.tsx b/src/components/LinkDerectory/LinkDerectory.tsx
new file mode 100644
index 0000000..8a2660c
--- /dev/null
+++ b/src/components/LinkDerectory/LinkDerectory.tsx
@@ -0,0 +1,29 @@
+import { useLocation } from 'react-router-dom'
+import routerList from '../../constants/routes'
+import { Fragment } from 'react'
+interface TitlePageProps {
+ titlePage?: string
+}
+export const LinkDerectory = ({ titlePage }: TitlePageProps) => {
+ const location = useLocation()
+ const link = location.pathname.split('/')[1]
+ const url = routerList.find((data) => data.href === `/${link}`)
+ return (
+
+
+ {titlePage ? titlePage : url?.title}
+
+
+
Trang chủ
+
+
{url?.title}
+ {location.state && (
+
+
+ {location.state}
+
+ )}
+
+
+ )
+}
diff --git a/src/components/LinkDerectory/index.ts b/src/components/LinkDerectory/index.ts
new file mode 100644
index 0000000..8d0ad0c
--- /dev/null
+++ b/src/components/LinkDerectory/index.ts
@@ -0,0 +1 @@
+export * from './LinkDerectory'
diff --git a/src/components/Panigation/Panigation.tsx b/src/components/Panigation/Panigation.tsx
index 1c03d10..cbbb5e6 100644
--- a/src/components/Panigation/Panigation.tsx
+++ b/src/components/Panigation/Panigation.tsx
@@ -12,7 +12,9 @@ export interface IPanigation {
pageSize: number
pageOption: number[]
labelPageOption?: string
+ // eslint-disable-next-line no-unused-vars
onChangePage: (params: number) => void
+ // eslint-disable-next-line no-unused-vars
onChangePageSize: (params: string) => void
}
diff --git a/src/components/Panigation/PanigationQ.tsx b/src/components/Panigation/PanigationQ.tsx
new file mode 100644
index 0000000..da9a93c
--- /dev/null
+++ b/src/components/Panigation/PanigationQ.tsx
@@ -0,0 +1,101 @@
+import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'
+import { useEffect, useRef, useState } from 'react'
+
+export interface ProductProps {
+ title: string
+ price: number
+ image: string
+}
+interface PaginationProps {
+ onListItemChange: (_newList: ProductProps[]) => void
+ listItemRender: ProductProps[]
+}
+export default function PanigationQ(props: PaginationProps) {
+ const { onListItemChange, listItemRender } = props
+ const inputRef = useRef(12)
+ const [pagination, setPagination] = useState(1)
+ const [totalPages, setTotalPages] = useState(
+ Math.ceil(listItemRender.length / 12),
+ )
+ const nextPage = (data: ProductProps[], currentPage: number) => {
+ const totalItem = inputRef.current
+
+ const startIndex = currentPage * totalItem
+ const lastIndex = startIndex + totalItem
+
+ const newData = data.slice(startIndex, lastIndex)
+ return newData
+ }
+ // set listItem to render when the page changes
+ const [listItem, setListItem] = useState(nextPage(listItemRender, 0))
+ onListItemChange(listItem)
+
+ useEffect(() => {
+ setListItem(nextPage(listItemRender, pagination - 1))
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [pagination])
+
+ // nextPage
+ const nextCount = () => {
+ if (pagination >= totalPages) return
+ else {
+ setPagination((pev) => pev + 1)
+ }
+ }
+ // returnPage
+ const reCount = () => {
+ if (pagination === 1) return
+ else {
+ setPagination((pev) => pev - 1)
+ }
+ }
+ //select page 12 24 36
+ const sellectListItem = (number: number) => {
+ const newList = listItemRender.slice(0, number)
+ return newList
+ }
+ const handleNumberValue = (e) => {
+ const numberPage = parseInt(e.target.value)
+ inputRef.current = numberPage
+ const toltalPageCurrent = Math.ceil(listItemRender.length / numberPage)
+ setTotalPages(toltalPageCurrent)
+ setListItem(sellectListItem(numberPage))
+ setPagination(1)
+ }
+
+ return (
+
+
+
+
{pagination}
+
-
+
{totalPages}
+
= totalPages
+ ? 'cursor-not-allowed'
+ : 'cursor-pointer'
+ } text-xl`}
+ />
+
+
+
+ )
+}
diff --git a/src/components/Search/Search.tsx b/src/components/Search/Search.tsx
new file mode 100644
index 0000000..d61194e
--- /dev/null
+++ b/src/components/Search/Search.tsx
@@ -0,0 +1,3 @@
+export default function Search() {
+ return Search
+}
diff --git a/src/components/Search/index.ts b/src/components/Search/index.ts
new file mode 100644
index 0000000..354d403
--- /dev/null
+++ b/src/components/Search/index.ts
@@ -0,0 +1 @@
+export * from './Search'
diff --git a/src/components/TableData/StyledDataGrid.tsx b/src/components/TableData/StyledDataGrid.tsx
index e952ac6..e488a48 100644
--- a/src/components/TableData/StyledDataGrid.tsx
+++ b/src/components/TableData/StyledDataGrid.tsx
@@ -4,7 +4,7 @@ import { IDataGridProps } from './table.interface'
const StyledDataGrid = styled(DataGrid, {
shouldForwardProp: (prop) => prop !== 'checkBox',
-})>(({ checkBox }) => ({
+})>(({ checkBox }) => ({
border: 0,
fontFamily: ['Nunito', 'sans-serif'].join(','),
WebkitFontSmoothing: 'auto',
diff --git a/src/components/TableData/TableData.tsx b/src/components/TableData/TableData.tsx
index bfd0f57..9cc2160 100644
--- a/src/components/TableData/TableData.tsx
+++ b/src/components/TableData/TableData.tsx
@@ -22,6 +22,7 @@ export function TableData(props: IDataGridProps) {
checkBox = true,
loading,
onHandleSearch,
+ onGetRowId,
} = props
const [filteredRows, setFilteredRows] = useState()
@@ -52,7 +53,7 @@ export function TableData(props: IDataGridProps) {
autoHeight={true}
pageSizeOptions={pageSizeOptions}
columnBuffer={0}
- getRowId={(row: GridRowModel) => row.orderId}
+ getRowId={onGetRowId}
checkboxSelection={checkBox}
disableRowSelectionOnClick={!checkBox}
rowHeight={60}
diff --git a/src/components/TableData/table.interface.ts b/src/components/TableData/table.interface.ts
index 73de7d8..60de2d9 100644
--- a/src/components/TableData/table.interface.ts
+++ b/src/components/TableData/table.interface.ts
@@ -1,4 +1,10 @@
-import { DataGridProps, GridColDef, GridActionsColDef } from '@mui/x-data-grid'
+import {
+ DataGridProps,
+ GridColDef,
+ GridActionsColDef,
+ GridRowModel,
+ GridValidRowModel,
+} from '@mui/x-data-grid'
export interface IDataGridProps extends DataGridProps {
pageSize?: number
@@ -7,6 +13,8 @@ export interface IDataGridProps extends DataGridProps {
loading?: boolean
onHandleSearch: () => void
pageSizeOptions: number[]
+ // eslint-disable-next-line no-unused-vars
+ onGetRowId: (params: GridRowModel) => GridValidRowModel[string | symbol]
}
export interface IHandleNameChange {
diff --git a/src/constants/dataCreatOrder.ts b/src/constants/dataCreatOrder.ts
new file mode 100644
index 0000000..54bb34b
--- /dev/null
+++ b/src/constants/dataCreatOrder.ts
@@ -0,0 +1,99 @@
+export const listProduct = [
+ {
+ id: 1,
+ title: 'Mì tôm Omachi',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 2,
+ title: 'Mì tôm hảo hảo1',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 3,
+ title: 'Mì tôm hảo hảo2',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+
+ {
+ id: 4,
+ title: 'Mì tôm hảo hảo3',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 5,
+ title: 'Mì tôm hảo hảo4',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 5,
+ title: 'Mì tôm hảo hảo5',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 6,
+ title: 'Mì tôm hảo hảo6',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 7,
+ title: 'Mì tôm hảo hảo7',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 8,
+ title: 'Mì tôm hảo hảo8',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 9,
+ title: 'Mì tôm hảo hảo9',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 10,
+ title: 'Mì tôm hảo hảo10',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 11,
+ title: 'Mì tôm hảo hảo11',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 12,
+ title: 'Mì tôm hảo hảo12',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 13,
+ title: 'Mì tôm hảo hảo13',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 14,
+ title: 'Mì tôm hảo hảo14',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+ {
+ id: 15,
+ title: 'Mì tôm hảo hảo15',
+ price: 10000,
+ image: 'https://cdn.dribbble.com/users/14268/screenshots/1206054/media/0e77168057d0026aa7b8f30ba2e2c540.png?resize=768x576&vertical=center',
+ },
+]
diff --git a/src/constants/dataProduct.ts b/src/constants/dataProduct.ts
new file mode 100644
index 0000000..b24bc4a
--- /dev/null
+++ b/src/constants/dataProduct.ts
@@ -0,0 +1,59 @@
+import { GridColDef } from '@mui/x-data-grid'
+export const columns: GridColDef[] = [
+ { field: 'name', headerName: 'Tên sản phẩm', width: 200 },
+ { field: 'category', headerName: 'Danh mục', width: 150 },
+ { field: 'unit', headerName: 'Đơn vị tính', width: 150 },
+ {
+ field: 'price',
+ headerName: 'Giá bán',
+ type: 'number',
+ width: 150,
+ },
+ {
+ field: 'available',
+ headerName: 'Hàng sẵn có',
+ type: 'number',
+ width: 150,
+ valueGetter: (params) => {
+ if (params.value > 0) {
+ return params.value
+ }
+ return 'Hết hàng'
+ },
+ },
+ {
+ field: 'edit',
+ headerName: 'Chỉnh sửa',
+ sortable: false,
+ filterable: false,
+ width: 100,
+ },
+]
+
+export const rows = [
+ {
+ id: 1,
+ name: 'Viên thả lẩu La Cunina gói 300g',
+ category: 'Đồ đông lạnh',
+ unit: 'Gói',
+ price: 20000,
+ available: 0,
+ edit: 'x',
+ },
+ {
+ id: 2,
+ name: 'Viên thả lẩu La Cunina gói 300g',
+ category: 'Đồ đông lạnh',
+ unit: 'Gói',
+ price: 20000,
+ available: 675,
+ },
+ {
+ id: 3,
+ name: 'Viên thả lẩu La Cunina gói 300g',
+ category: 'Đồ đông lạnh',
+ unit: 'Gói',
+ price: 20000,
+ available: 675,
+ },
+]
diff --git a/src/constants/handleKeyPressNumber.ts b/src/constants/handleKeyPressNumber.ts
new file mode 100644
index 0000000..251c73f
--- /dev/null
+++ b/src/constants/handleKeyPressNumber.ts
@@ -0,0 +1,9 @@
+export const handleKeyPress = (event) => {
+ // Lấy ký tự đã nhập từ sự kiện
+ const char = String.fromCharCode(event.which)
+
+ // Kiểm tra nếu ký tự không phải là số thì ngăn người dùng nhập
+ if (!/[0-9]/.test(char)) {
+ event.preventDefault()
+ }
+}
diff --git a/src/constants/index.ts b/src/constants/index.ts
index 49800c7..4c03462 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -1 +1,2 @@
export * from './routes'
+export * from './DataCreatOrder'
diff --git a/src/constants/routes.ts b/src/constants/routes.ts
index ff1216c..00956b1 100644
--- a/src/constants/routes.ts
+++ b/src/constants/routes.ts
@@ -7,11 +7,14 @@ import {
IconOrder,
IconWallet,
} from '../svgs'
+import { CategoryProduct } from '../screens/Product/components/CategoryProduct'
+import { CreateProduct } from '../screens/Product/components/CreateProduct'
+import { CreatOrderContextProvider } from '../screens/Order/context/CreatOrderContext'
export const ROUTES = {
HomePage: '/',
Order: '/order',
- POS: '/pos',
+ Product: '/product',
Manage: '/manage',
Money: '/money',
User: '/user',
@@ -31,12 +34,29 @@ const routerList = [
icon: IconOrder,
href: ROUTES.Order,
component: Order,
+ children: [
+ {
+ url: 'order/tao-don-hang',
+ childComponent: CreatOrderContextProvider,
+ },
+ ],
},
{
title: 'Sản phẩm',
+
icon: IconProduct,
- href: ROUTES.POS,
+ href: ROUTES.Product,
component: Product,
+ children: [
+ {
+ url: 'product/danh-muc-san-pham',
+ childComponent: CategoryProduct,
+ },
+ {
+ url: 'product/tao-san-pham',
+ childComponent: CreateProduct,
+ },
+ ],
},
{
title: 'Khách hàng',
@@ -62,7 +82,7 @@ export const defaultTitle = 'Default'
export const routeTitleMapper = {
[ROUTES.HomePage]: 'HomePage',
- [ROUTES.POS]: 'POS',
+ [ROUTES.Product]: 'POS',
[ROUTES.SignUp]: 'SignUp',
[ROUTES.Login]: 'Login',
}
diff --git a/src/hooks/data/useFetchAccounts.ts b/src/hooks/data/useFetchAccounts.ts
index 29bc343..664a072 100644
--- a/src/hooks/data/useFetchAccounts.ts
+++ b/src/hooks/data/useFetchAccounts.ts
@@ -10,4 +10,4 @@ export function useFetchAccounts() {
accounts: data,
...rest,
}
-}
\ No newline at end of file
+}
diff --git a/src/hooks/useDebounce.ts b/src/hooks/useDebounce.ts
new file mode 100644
index 0000000..092fc7c
--- /dev/null
+++ b/src/hooks/useDebounce.ts
@@ -0,0 +1,10 @@
+import { useState, useEffect } from 'react'
+export function useDebounce(value: string, delay: number) {
+ const [debouncedValue, setDebouncedValue] = useState(value)
+ useEffect(() => {
+ const hanler = setTimeout(() => setDebouncedValue(value), delay)
+ return () => clearTimeout(hanler)
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [value])
+ return debouncedValue
+}
diff --git a/src/hooks/useIsMounted.ts b/src/hooks/useIsMounted.ts
index 7468f0b..3ad686b 100644
--- a/src/hooks/useIsMounted.ts
+++ b/src/hooks/useIsMounted.ts
@@ -1,15 +1,15 @@
import { useCallback, useEffect, useRef } from 'react'
export function useIsMounted() {
- const isMounted = useRef(false)
+ const isMounted = useRef(false)
- useEffect(() => {
- isMounted.current = true
+ useEffect(() => {
+ isMounted.current = true
- return () => {
- isMounted.current = false
- }
- }, [])
+ return () => {
+ isMounted.current = false
+ }
+ }, [])
- return useCallback(() => isMounted.current, [])
-}
\ No newline at end of file
+ return useCallback(() => isMounted.current, [])
+}
diff --git a/src/hooks/useLocalStorage.ts b/src/hooks/useLocalStorage.ts
new file mode 100644
index 0000000..5135177
--- /dev/null
+++ b/src/hooks/useLocalStorage.ts
@@ -0,0 +1,20 @@
+import { useEffect, useState } from 'react'
+
+export function useLocalStorage(key: string, initialValue: T | (() => T)) {
+ const [value, setValue] = useState(() => {
+ const jsonValue = localStorage.getItem(key)
+ if (jsonValue != null) return JSON.parse(jsonValue)
+
+ if (typeof initialValue === 'function') {
+ return (initialValue as () => T)()
+ } else {
+ return initialValue
+ }
+ })
+
+ useEffect(() => {
+ localStorage.setItem(key, JSON.stringify(value))
+ }, [key, value])
+
+ return [value, setValue] as [typeof value, typeof setValue]
+}
diff --git a/src/router.tsx b/src/router.tsx
new file mode 100644
index 0000000..c423f9d
--- /dev/null
+++ b/src/router.tsx
@@ -0,0 +1,46 @@
+import { BrowserRouter, Route, Routes } from 'react-router-dom'
+import { MainLayout } from './screens/layouts'
+import { Login } from './screens'
+import { SignUp } from './screens'
+import routerList from './constants/routes'
+import { PageNotFound } from './screens/PageNotFound'
+import { Fragment } from 'react'
+
+function Router() {
+ return (
+
+
+ }>
+ {routerList.map((item, index) => {
+ const Page = item.component
+ const itemChildren = item.children
+ return (
+
+ } />
+ {itemChildren
+ ? itemChildren.map((item, index) => {
+ const ItemChildren =
+ item.childComponent
+ return (
+ }
+ />
+ )
+ })
+ : ''}
+
+ )
+ })}
+
+
+ } />
+ } />
+ } />
+
+
+ )
+}
+
+export default Router
diff --git a/src/routes.tsx b/src/routes.tsx
deleted file mode 100644
index 2d0bfd4..0000000
--- a/src/routes.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { BrowserRouter, Route, Routes } from 'react-router-dom'
-import { HomePage, Login, SignUp, PurchaseOrders } from './screens'
-import { MainLayout } from './screens/layouts'
-import { ROUTES } from './constants'
-import { RouteHandler } from './screens/layouts/RouteHandler/RouteHandler'
-
-export const routes = (
-
-
- }>
- }>
-
- {/* */}
-
-
-
-
-
-
-
-)
diff --git a/src/screens/Dashboard/Dashboard.tsx b/src/screens/Dashboard/Dashboard.tsx
index 0b17bbd..6d48da9 100644
--- a/src/screens/Dashboard/Dashboard.tsx
+++ b/src/screens/Dashboard/Dashboard.tsx
@@ -4,8 +4,8 @@ import Data from './Data'
import { Note } from './components'
export const Dashboard = () => {
return (
-
-
+
+
Dashboard
diff --git a/src/screens/Dashboard/Data.tsx b/src/screens/Dashboard/Data.tsx
index 24eea44..5ef6ba2 100644
--- a/src/screens/Dashboard/Data.tsx
+++ b/src/screens/Dashboard/Data.tsx
@@ -3,11 +3,11 @@ import { ChartPie } from './components/index'
function Data() {
return (
-
+
Tổng hợp số liệu
-
+
@@ -32,23 +32,23 @@ function Data() {
-
+
Tổng kho
Số lượng hàng trong kho
-
-
+
+
-
+
-
+
Hêt hàng
10.8%
@@ -56,7 +56,8 @@ function Data() {
-
+
+
Sản phẩm bán chạy
Các sản phẩm bán chạy trong 7 ngày gần nhất
diff --git a/src/screens/Dashboard/Finance.tsx b/src/screens/Dashboard/Finance.tsx
index 23b47d8..cc29e4d 100644
--- a/src/screens/Dashboard/Finance.tsx
+++ b/src/screens/Dashboard/Finance.tsx
@@ -2,7 +2,7 @@ import { ChartLine } from './components/index'
function Finance() {
return (
-
+
diff --git a/src/screens/Dashboard/Overview.tsx b/src/screens/Dashboard/Overview.tsx
index acf184a..be5ebd7 100644
--- a/src/screens/Dashboard/Overview.tsx
+++ b/src/screens/Dashboard/Overview.tsx
@@ -11,22 +11,22 @@ function Overview() {
Tổng quan
-
-
+
+
Doanh thu tháng hiện tại
7,350,000
Doanh thu
- -1,29%
+ -1,29%
-
+
Lợi nhuận tháng hiện tại
@@ -43,8 +43,8 @@ function Overview() {
- -
-
+
-
+
@@ -54,7 +54,7 @@ function Overview() {
-
+
Đang giao
10
@@ -65,7 +65,7 @@ function Overview() {
-
+
Đã giao
47
diff --git a/src/screens/Dashboard/components/Calendar.tsx b/src/screens/Dashboard/components/Calendar.tsx
index e7bcc29..0e90254 100644
--- a/src/screens/Dashboard/components/Calendar.tsx
+++ b/src/screens/Dashboard/components/Calendar.tsx
@@ -1,5 +1,5 @@
import { useState } from 'react'
-import { Date } from './Date'
+
import { Link } from 'react-router-dom'
import { IconDrop } from '../../../svgs'
@@ -29,15 +29,16 @@ export const Calendar = () => {
setOpenDate(!openDate)
}
return (
-
-
-
+
+
+
ĐƠN GẦN ĐÂY
+
{openDate ? : ''}
diff --git a/src/screens/Dashboard/components/ChartLine.tsx b/src/screens/Dashboard/components/ChartLine.tsx
index 39b6569..dc59e65 100644
--- a/src/screens/Dashboard/components/ChartLine.tsx
+++ b/src/screens/Dashboard/components/ChartLine.tsx
@@ -1,12 +1,4 @@
-import {
- LineChart,
- Line,
- XAxis,
- YAxis,
- CartesianGrid,
- Tooltip,
- Legend,
-} from 'recharts'
+import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip } from 'recharts'
const data = [
{
date: '11/08',
@@ -54,9 +46,9 @@ const data = [
export const ChartLine = () => {
const customYAxisTicks = [2000, 4000, 6000, 8000]
return (
-
-
-
+
+
+
Tổng thu chi tháng này
(+21%) so với tháng trước
@@ -74,8 +66,9 @@ export const ChartLine = () => {
{
-
{
return (
76%
-
+
(
-
+
{properties}
{name}
-
{des}
+
{des}
)
diff --git a/src/screens/Dashboard/components/Date.tsx b/src/screens/Dashboard/components/DayPicker.tsx
similarity index 95%
rename from src/screens/Dashboard/components/Date.tsx
rename to src/screens/Dashboard/components/DayPicker.tsx
index 3df42b1..7cc591e 100644
--- a/src/screens/Dashboard/components/Date.tsx
+++ b/src/screens/Dashboard/components/DayPicker.tsx
@@ -3,7 +3,7 @@ import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'
import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'
import { useState } from 'react'
-export const Date = () => {
+export const DayPicker = () => {
const [value, setValue] = useState
(null)
return (
diff --git a/src/screens/Dashboard/components/Note.tsx b/src/screens/Dashboard/components/Note.tsx
index 68d00ba..38036e4 100644
--- a/src/screens/Dashboard/components/Note.tsx
+++ b/src/screens/Dashboard/components/Note.tsx
@@ -1,38 +1,41 @@
import { Client, Calendar } from './index'
-import ImgMoney from '../../../assets/images/imgMoney.png'
import {
- IconBag,
- IconDrawstringBag,
- IconFolder,
+ IconAdd,
+ IconBags,
+ IconBuy,
+ IconDebt,
+ IconFolders,
+ IconMoney,
IconPinned,
IconSub,
} from '../../../svgs'
export const Note = () => (
-
-
-
+
+
+
Số mặt hàng
-

+
1000
-
+
Lượt mua
-

+
1000
Trả hàng
-

+
1000
+
ĐÃ GHIM
-
-
+
NHẮC NỢ
-
+
-
+
-
-

+
Chưa có giao dịch nào!
-
-
-
+
+
-
+
diff --git a/src/screens/Dashboard/components/index.ts b/src/screens/Dashboard/components/index.ts
index ba92169..db655bc 100644
--- a/src/screens/Dashboard/components/index.ts
+++ b/src/screens/Dashboard/components/index.ts
@@ -2,5 +2,4 @@ export * from './Calendar'
export * from './ChartLine'
export * from './ChartPie'
export * from './Client'
-export * from './Date'
export * from './Note'
diff --git a/src/screens/Money/Money.tsx b/src/screens/Money/Money.tsx
index 4804f31..8fb76b6 100644
--- a/src/screens/Money/Money.tsx
+++ b/src/screens/Money/Money.tsx
@@ -1,3 +1,9 @@
+import { LinkDerectory } from '../../components/LinkDerectory'
+
export const Money = () => {
- return
Money
+ return (
+
+
+
+ )
}
diff --git a/src/screens/Order/Order.tsx b/src/screens/Order/Order.tsx
index ef82889..7c8aea6 100644
--- a/src/screens/Order/Order.tsx
+++ b/src/screens/Order/Order.tsx
@@ -1,10 +1,11 @@
import { Statistics, OrderTable } from './components'
import { IconAddCircle, IconDownload } from '../../svgs'
+import { Link } from 'react-router-dom'
export const Order = () => {
return (
<>
-
+
@@ -14,9 +15,13 @@ export const Order = () => {
Trang chủ • Đơn hàng
-
+
diff --git a/src/screens/Order/component/CreateOrder.tsx b/src/screens/Order/component/CreateOrder.tsx
new file mode 100644
index 0000000..c714938
--- /dev/null
+++ b/src/screens/Order/component/CreateOrder.tsx
@@ -0,0 +1,75 @@
+import { LinkDerectory } from '../../../components/LinkDerectory'
+import { useState } from 'react'
+import UserInfo from './UserInfo'
+import PurchaseOrder from './PurchaseOrder'
+import { useCreatOrderContext } from '../context/CreatOrderContext'
+import { SearchResult } from '../../Product/components/SearchResult'
+import PanigationQ from '../../../components/Panigation/PanigationQ'
+import { listProduct } from '../../../constants'
+import { IconSort } from '../../../svgs'
+interface ProductProps {
+ title: string
+ price: number
+ image: string
+}
+export const CreateOrder = () => {
+ const [listItem, setListItem] = useState([])
+ const { handleAddProductToCart } = useCreatOrderContext()
+ const handleSetListItem = (newList: ProductProps[]) => {
+ setListItem(newList)
+ }
+
+ return (
+
+
+
+
+
+ Danh mục sản phẩm
+
+
+
+
+
+ {listItem.map((item, index) => (
+ -
+
+ {item.title}
+
+ {item.price}
+
+
+
+ ))}
+
+
+
+
+
+
+ )
+}
diff --git a/src/screens/Order/component/PurchaseOrder.tsx b/src/screens/Order/component/PurchaseOrder.tsx
new file mode 100644
index 0000000..35efef4
--- /dev/null
+++ b/src/screens/Order/component/PurchaseOrder.tsx
@@ -0,0 +1,143 @@
+import { useCreatOrderContext } from '../context/CreatOrderContext'
+import { useState } from 'react'
+import { IconDelete, IconMore, IconNotes } from '../../../svgs'
+
+export default function PurchaseOrder() {
+ const [voucherValue, setVoucherValue] = useState(0)
+ const {
+ removeFromCart,
+ listOrder,
+ increaseProductQuantity,
+ decreaseProductQuantity,
+ totalMoney,
+ } = useCreatOrderContext()
+
+ // console.log(parseInt(totalMoney.replace(/\./g, '')))
+ const handleChangeVoucher = (e) => {
+ setVoucherValue(e.target.value)
+ }
+ console.log(voucherValue)
+
+ return (
+
+
+
+
+ Tổng
{listOrder.length}
+ món
+
+
+
+
+
+
Tổng phải trả
+
{totalMoney.toLocaleString()}
+
+
+
+
+
+
+ )
+}
diff --git a/src/screens/Order/component/UserInfo.tsx b/src/screens/Order/component/UserInfo.tsx
new file mode 100644
index 0000000..9efd1d5
--- /dev/null
+++ b/src/screens/Order/component/UserInfo.tsx
@@ -0,0 +1,20 @@
+import { IconEdit } from '../../../svgs'
+
+export default function UserInfo() {
+ return (
+
+
+
+
+
+
+ Huyền Trang
+
+
123 Trần Phú - Di Linh - Lâm Đồng
+
0123.456.789
+
thanhnt@gmail.com
+
+ )
+}
diff --git a/src/screens/Order/components/MoreAction.tsx b/src/screens/Order/components/MoreAction.tsx
index 29759bd..de5673a 100644
--- a/src/screens/Order/components/MoreAction.tsx
+++ b/src/screens/Order/components/MoreAction.tsx
@@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'
export interface IPopupActions {
items: IAction[]
+ // eslint-disable-next-line no-unused-vars
onChange: (params: IAction) => void
children: JSX.Element
id: GridRowId
diff --git a/src/screens/Order/components/OrderTable.tsx b/src/screens/Order/components/OrderTable.tsx
index 5c9d815..104df7c 100644
--- a/src/screens/Order/components/OrderTable.tsx
+++ b/src/screens/Order/components/OrderTable.tsx
@@ -1,5 +1,5 @@
import { useQuery } from '@tanstack/react-query'
-import { GridRowId } from '@mui/x-data-grid'
+import { GridRowId, GridRowModel } from '@mui/x-data-grid'
import { TableData, Status } from '../../../components'
import { IconAction, IconSetting } from '../../../svgs'
import {
@@ -103,7 +103,6 @@ export function OrderTable() {
const handleSelectAction = (action: string, id: GridRowId) => {
console.log(action, id)
}
-
const { data = [], isLoading } = useQuery({
queryKey: ['orders'],
queryFn: getOrders,
@@ -119,7 +118,8 @@ export function OrderTable() {
pageSizeOptions={[5, 10, 20]}
checkBox={true}
loading={isLoading}
- onHandleSearch={() => getOrders()}
+ onHandleSearch={getOrders}
+ onGetRowId={(row: GridRowModel) => row.orderId}
/>
diff --git a/src/screens/Order/context/CreatOrderContext.tsx b/src/screens/Order/context/CreatOrderContext.tsx
new file mode 100644
index 0000000..93a157c
--- /dev/null
+++ b/src/screens/Order/context/CreatOrderContext.tsx
@@ -0,0 +1,120 @@
+import { createContext, useContext } from 'react'
+
+import { CreateOrder } from '../component/CreateOrder'
+import { useLocalStorage } from '../../../hooks/useLocalStorage'
+interface ProductProps {
+ id: number
+ title: string
+ quantity?: number
+ price: number
+ image: string
+}
+type CreatOrderContext = {
+ // eslint-disable-next-line no-unused-vars
+ increaseProductQuantity: (id: number) => void
+ // eslint-disable-next-line no-unused-vars
+ decreaseProductQuantity: (id: number) => void
+ // eslint-disable-next-line no-unused-vars
+ removeFromCart: (id: number) => void
+ // eslint-disable-next-line no-unused-vars
+ handleAddProductToCart: (item: ProductProps) => void
+ totalMoney: number
+ listOrder: ProductProps[]
+}
+const CreatOrderContext = createContext({} as CreatOrderContext)
+export function useCreatOrderContext() {
+ return useContext(CreatOrderContext)
+}
+
+export function CreatOrderContextProvider() {
+ const [listOrder, setListOrder] = useLocalStorage
(
+ 'product-item',
+ [],
+ )
+
+ const increaseProductQuantity = (id: number) => {
+ setListOrder((prevListOrder) => {
+ return prevListOrder.map((item) => {
+ if (item.id === id) {
+ return {
+ ...item,
+ quantity: (item.quantity || 0) + 1,
+ }
+ }
+ return item
+ })
+ })
+ }
+ const decreaseProductQuantity = (id: number) => {
+ setListOrder((prevListOrder) => {
+ const updatedListOrder = prevListOrder.map((item) => {
+ if (
+ item.id === id &&
+ item.quantity !== undefined &&
+ item.quantity > 0
+ ) {
+ return {
+ ...item,
+ quantity: item.quantity - 1,
+ }
+ }
+ return item
+ })
+
+ // Loại bỏ sản phẩm có quantity là 0 khỏi danh sách
+ const newList = updatedListOrder.filter(
+ (item) => item.quantity !== 0,
+ )
+
+ return newList
+ })
+ }
+ const handleAddProductToCart = (item: ProductProps) => {
+ const newList = listOrder.find(
+ (product) => product.title === item.title,
+ )
+ if (!newList) {
+ setListOrder((prevListOrder) => [
+ ...prevListOrder,
+ { ...item, quantity: 1 },
+ ])
+ } else {
+ setListOrder((prevListOrder) => [
+ ...prevListOrder.map((product) => {
+ if (product.title === item.title) {
+ return {
+ ...product,
+ quantity: (product.quantity || 0) + 1,
+ }
+ }
+ return product
+ }),
+ ])
+ }
+ }
+ const removeFromCart = (id: number) => {
+ const newList = listOrder.filter((item) => item.id !== id)
+ setListOrder(newList)
+ }
+ const totalMoney = listOrder.reduce((total, item) => {
+ if (item.quantity !== undefined) {
+ return total + item.price * item.quantity
+ }
+ return total
+ }, 0)
+
+ return (
+
+
+
+ )
+}
diff --git a/src/screens/PageNotFound/PageNotFound.tsx b/src/screens/PageNotFound/PageNotFound.tsx
index c5e4677..70fa305 100644
--- a/src/screens/PageNotFound/PageNotFound.tsx
+++ b/src/screens/PageNotFound/PageNotFound.tsx
@@ -1,4 +1,11 @@
+import { useEffect } from 'react'
+import { useNavigate } from 'react-router-dom'
+
export const PageNotFound = () => {
+ const navigate = useNavigate()
+ useEffect(() => {
+ setTimeout(() => navigate('/'), 2000)
+ }, [navigate])
return (
<>
Page Not Found
diff --git a/src/screens/Product/Product.tsx b/src/screens/Product/Product.tsx
index de26c0a..83995e5 100644
--- a/src/screens/Product/Product.tsx
+++ b/src/screens/Product/Product.tsx
@@ -1,3 +1,37 @@
+import { LinkDerectory } from '../../components/LinkDerectory'
+import { Link } from 'react-router-dom'
+import { IconSum } from '../../svgs'
+import { ProductTable } from './components/ProductTable'
export const Product = () => {
- return Product
+ return (
+
+
+
+
+
+
+
+
+
Danh mục sản phẩm
+
+
+
+
Tạo sản phẩm
+
+
+
+
+
+
+ )
}
diff --git a/src/screens/Product/components/AddCategory.tsx b/src/screens/Product/components/AddCategory.tsx
new file mode 100644
index 0000000..4b5134d
--- /dev/null
+++ b/src/screens/Product/components/AddCategory.tsx
@@ -0,0 +1,149 @@
+import { useForm } from 'react-hook-form'
+import { AiOutlineClose } from 'react-icons/ai'
+import { useState } from 'react'
+import { handleKeyPress } from '../../../constants/handleKeyPressNumber'
+import { IconStar } from '../../../svgs'
+interface AddCategoryProps {
+ title: string
+ quatity: number
+ image: string
+}
+export default function AddCategory({ onClick }) {
+ const [selectedFileURL, setSelectedFileURL] = useState('')
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ reset,
+ } = useForm()
+
+ const handleFileChange = (event: React.ChangeEvent) => {
+ if (event.target.files && event.target.files.length > 0) {
+ if (selectedFileURL) {
+ URL.revokeObjectURL(selectedFileURL)
+ }
+ const file = event.target.files[0]
+ const url = URL.createObjectURL(file)
+ setSelectedFileURL(url)
+ }
+ }
+ const onSubmit = (data: AddCategoryProps) => {
+ if (selectedFileURL) {
+ data.image = selectedFileURL
+ }
+ alert('Bạn đã tạo sản phẩm thành công')
+ console.log(data)
+ reset()
+ }
+ return (
+
+
+
+
+
+ Thêm danh mục sản phẩm
+
+
+
Trang chủ
+
+
Sản phẩm
+
+
Tạo danh mục
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/screens/Product/components/CategoryProduct.tsx b/src/screens/Product/components/CategoryProduct.tsx
new file mode 100644
index 0000000..76f0366
--- /dev/null
+++ b/src/screens/Product/components/CategoryProduct.tsx
@@ -0,0 +1,73 @@
+import { LinkDerectory } from '../../../components/LinkDerectory'
+// import { FilterIcon, SumIcon } from '../../Dashboard/components'
+import { useState } from 'react'
+import AddCategory from './AddCategory'
+import PanigationQ from '../../../components/Panigation/PanigationQ'
+import { listProduct } from '../../../constants'
+import { IconAdd, IconSort } from '../../../svgs'
+interface ProductProps {
+ title: string
+ price: number
+ image: string
+}
+export function CategoryProduct() {
+ const [isAddCategory, setIsAddCategory] = useState(false)
+
+ const [listItem, setListItem] = useState([])
+ const handleListItemChange = (newList: ProductProps[]) => {
+ setListItem(newList)
+ }
+
+ return (
+
+
+
+ {/*
*/}
+
+
+
+
+ {listItem.map((item, index) => (
+ -
+
+
+
+ {item.title}
+
+
+ {item.price}
+ sản phẩm
+
+
+
+ ))}
+
+
+
+ {isAddCategory ? (
+ setIsAddCategory(!isAddCategory)} />
+ ) : (
+ ''
+ )}
+
+ )
+}
diff --git a/src/screens/Product/components/CreateProduct.tsx b/src/screens/Product/components/CreateProduct.tsx
new file mode 100644
index 0000000..ba869ec
--- /dev/null
+++ b/src/screens/Product/components/CreateProduct.tsx
@@ -0,0 +1,244 @@
+import { LinkDerectory } from '../../../components/LinkDerectory'
+import { useForm } from 'react-hook-form'
+import { useState } from 'react'
+import { handleKeyPress } from '../../../constants/handleKeyPressNumber'
+import { IconImage, IconStar, IconSum } from '../../../svgs'
+interface CreateProductProps {
+ nameProduct: string
+ unit: string
+ quatity: number
+ categoryProduct?: string
+ sellPrice: number
+ capitalPrice: number
+ promotionalPrice: number
+ image?: string
+ description?: string
+}
+export const CreateProduct = () => {
+ const [selectedFileURL, setSelectedFileURL] = useState('')
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ reset,
+ } = useForm()
+ const handleFileChange = (event: React.ChangeEvent) => {
+ if (event.target.files && event.target.files.length > 0) {
+ if (selectedFileURL) {
+ URL.revokeObjectURL(selectedFileURL)
+ }
+ const file = event.target.files[0]
+ const url = URL.createObjectURL(file)
+ setSelectedFileURL(url)
+ }
+ }
+
+ const onSubmit = (data: CreateProductProps) => {
+ if (selectedFileURL) {
+ data.image = selectedFileURL
+ }
+ console.log(data)
+ reset()
+ }
+ return (
+
+ )
+}
diff --git a/src/screens/Product/components/ProductTable.tsx b/src/screens/Product/components/ProductTable.tsx
new file mode 100644
index 0000000..7c53a3a
--- /dev/null
+++ b/src/screens/Product/components/ProductTable.tsx
@@ -0,0 +1,121 @@
+import { useQuery } from '@tanstack/react-query'
+import { GridRowId, GridRowModel } from '@mui/x-data-grid'
+import { TableData, Status } from '../../../components'
+import { IconAction, IconSetting } from '../../../svgs'
+import {
+ GridColWithDefaultOptional,
+ defaultGridColValues,
+} from '../../../components/TableData/table.interface'
+import { getProducts } from '../../../services/orderAPI'
+import { MoreAction } from '../../Order/components/MoreAction'
+const actions = [
+ {
+ title: 'Detail',
+ icon: detail
,
+ action: 'detail',
+ },
+ {
+ title: 'Setting',
+ icon: setting
,
+ action: 'setting',
+ },
+ {
+ title: 'Delete',
+ icon: delete
,
+ action: 'delete',
+ },
+]
+
+export function ProductTable() {
+ const columns: GridColWithDefaultOptional[] = [
+ {
+ ...defaultGridColValues,
+ field: 'name',
+ headerName: 'Tên sản phẩm',
+ description: 'Tên sản phẩm',
+ align: 'left',
+ headerAlign: 'left',
+ minWidth: 135,
+ },
+ {
+ ...defaultGridColValues,
+ field: 'category',
+ headerName: 'Danh mục',
+ description: 'Danh mục',
+ minWidth: 130,
+ },
+ {
+ ...defaultGridColValues,
+ field: 'unit',
+ headerName: 'Đơn vị tính',
+ description: 'Đơn vị tính',
+ minWidth: 200,
+ },
+ {
+ ...defaultGridColValues,
+ field: 'price',
+ headerName: 'Giá bán',
+ description: 'Giá bán',
+ minWidth: 150,
+ },
+ {
+ ...defaultGridColValues,
+ field: 'status',
+ headerName: 'Hàng sẵn có',
+ description: 'Hàng sẵn có',
+ minWidth: 160,
+ renderCell: (params) => {
+ return
+ },
+ },
+
+ {
+ ...defaultGridColValues,
+ field: 'action',
+ headerName: 'Action',
+ description: 'Action',
+ type: 'actions',
+ minWidth: 100,
+ renderHeader: () => {
+ return
+ },
+ renderCell: (params) => (
+ {
+ handleSelectAction(action, params.row.id)
+ }}
+ >
+
+
+ ),
+ },
+ ]
+
+ const handleSelectAction = (action: string, id: GridRowId) => {
+ console.log(action, id)
+ }
+
+ const { data = [], isLoading } = useQuery({
+ queryKey: ['products'],
+ queryFn: getProducts,
+ })
+
+ return (
+
+ )
+}
diff --git a/src/screens/Product/components/SearchResult.tsx b/src/screens/Product/components/SearchResult.tsx
new file mode 100644
index 0000000..1f357de
--- /dev/null
+++ b/src/screens/Product/components/SearchResult.tsx
@@ -0,0 +1,97 @@
+// import { CiSearch } from 'react-icons/ci'
+// import { useEffect, useState } from 'react'
+// import { RefObject, createRef } from 'react'
+// import { listProduct } from '../../../constants'
+// import { useDebounce } from '../../../hooks/useDebounce'
+// import HeadlessTippy from '@tippyjs/react/headless'
+// interface ItemProp {
+// title: string
+// price: number
+// image: string
+// }
+// export const SearchResult = () => {
+// const inputRef: RefObject = createRef()
+// const [searchValue, setSearchValue] = useState('')
+// const [showSearchResult, setShowSearchResult] = useState(true)
+// const [searchResult, setSearchResult] = useState([])
+// const debouncedValue = useDebounce(searchValue, 500)
+// useEffect(() => {
+// if (!searchValue.trim()) {
+// setSearchResult([])
+// return
+// }
+// const normalizeString = (str: string) => {
+// return str
+// .toLowerCase()
+// .normalize('NFD')
+// .replace(/[\u0300-\u036f]/g, '')
+// }
+// const searchItembyTitle = (searchValue: string) => {
+// const normalizedSearchValue = normalizeString(searchValue)
+// const regex = new RegExp(normalizedSearchValue, 'i')
+
+// const listItem = listProduct.filter((item) =>
+// regex.test(normalizeString(item.title)),
+// )
+
+// return listItem
+// }
+// setSearchResult(searchItembyTitle(debouncedValue))
+// // eslint-disable-next-line react-hooks/exhaustive-deps
+// }, [debouncedValue])
+// const handleSearchValue = (e) => {
+// setSearchValue(e.target.value)
+// }
+// const handleHideResult = () => {
+// setShowSearchResult(false)
+// }
+
+// return (
+//
+//
0}
+// interactive
+// placement="bottom"
+// offset={[0, 0]}
+// render={(attrs) => (
+//
+// {searchResult.map((item, index) => (
+//
+//

+//
+// {item.title}
+//
+//
+// ))}
+//
+// )}
+// onClickOutside={handleHideResult}
+// >
+//
+//
+// setShowSearchResult(true)}
+// type="text"
+// placeholder="Tìm kiếm danh mục"
+// className="flex-auto border-none pl-2 outline-none"
+// />
+//
+//
+//
+// )
+// }
+export const SearchResult = () => Hello
diff --git a/src/screens/SignUp/SignUp.tsx b/src/screens/SignUp/SignUp.tsx
index 386c8dc..f42a238 100644
--- a/src/screens/SignUp/SignUp.tsx
+++ b/src/screens/SignUp/SignUp.tsx
@@ -94,7 +94,7 @@ export const SignUp = () => {
size="xxl"
borderRadius={40}
>
- Tạo tài khoảnnnnn
+ Tạo tài khoản
diff --git a/src/screens/User/User.tsx b/src/screens/User/User.tsx
index fc1ebc5..32dcfe4 100644
--- a/src/screens/User/User.tsx
+++ b/src/screens/User/User.tsx
@@ -1,3 +1,185 @@
+import { useForm } from 'react-hook-form'
+import { LinkDerectory } from '../../components/LinkDerectory'
+import { useState } from 'react'
+import { handleKeyPress } from '../../constants/handleKeyPressNumber'
+import { IconImage, IconStar } from '../../svgs'
+interface UserProps {
+ nameUser: string
+ numberPhone: number
+ userProperty?: string
+ location: string
+ image?: string
+}
export const User = () => {
- return
User
+ const [selectedFileURL, setSelectedFileURL] = useState('')
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ reset,
+ } = useForm
()
+ const onSubmit = (data: UserProps) => {
+ if (selectedFileURL) {
+ data.image = selectedFileURL
+ }
+ console.log(data)
+
+ reset()
+ }
+ const handleFileChange = (event: React.ChangeEvent) => {
+ if (event.target.files && event.target.files.length > 0) {
+ if (selectedFileURL) {
+ URL.revokeObjectURL(selectedFileURL)
+ }
+ const file = event.target.files[0]
+ const url = URL.createObjectURL(file)
+ setSelectedFileURL(url)
+ }
+ }
+
+ function capitalizeFirstLetter(value: string) {
+ return value.charAt(0).toUpperCase() + value.slice(1)
+ }
+ return (
+
+
+
+
+ )
}
diff --git a/src/screens/layouts/MainLayout/MainLayout.tsx b/src/screens/layouts/MainLayout/MainLayout.tsx
index d433c92..204aacf 100644
--- a/src/screens/layouts/MainLayout/MainLayout.tsx
+++ b/src/screens/layouts/MainLayout/MainLayout.tsx
@@ -6,10 +6,12 @@ export const MainLayout = () => {
return (
-
+
+
-
diff --git a/src/screens/layouts/MainLayout/Siderbar.tsx b/src/screens/layouts/MainLayout/Siderbar.tsx
index 869ee93..0aa7cc3 100644
--- a/src/screens/layouts/MainLayout/Siderbar.tsx
+++ b/src/screens/layouts/MainLayout/Siderbar.tsx
@@ -3,7 +3,7 @@ import routerList from '../../../constants/routes'
export const Siderbar = () => {
return (
-