Skip to content

Commit

Permalink
feat: profile and handle refresh token
Browse files Browse the repository at this point in the history
  • Loading branch information
nhamngo29 committed Nov 29, 2024
1 parent 8a4134d commit 63e1b34
Show file tree
Hide file tree
Showing 27 changed files with 300 additions and 46 deletions.
21 changes: 11 additions & 10 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"arrowParens": "always",
"semi": false,
"trailingComma": "none",
"tabWidth": 2,
"endOfLine": "auto",
"useTabs": false,
"singleQuote": true,
"printWidth": 120,
"jsxSingleQuote": true
}
"arrowParens": "always",
"semi": false,
"trailingComma": "none",
"tabWidth": 2,
"endOfLine": "auto",
"useTabs": false,
"singleQuote": true,
"printWidth": 120,
"jsxSingleQuote": true,
"plugins": ["prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-tailwindcss"]
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0",
"postcss": "^8.4.47",
"prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.8",
"prettier": "^3.4.1",
"prettier-plugin-tailwindcss": "^0.6.9",
"tailwindcss": "^3.4.13",
"typescript": "5.5.4",
"typescript-eslint": "^8.0.1",
Expand Down
10 changes: 10 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { useContext, useEffect } from 'react'
import useRouteElement from './useRouteElements'
import { ToastContainer } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'
import { LocalStorageEventTarget } from './utils/auth'
import { AppContext } from './contexts/app.context'
function App() {
const routeElements = useRouteElement()
const { reset } = useContext(AppContext)
useEffect(() => {
LocalStorageEventTarget.addEventListener('clearFormLS', reset)
return () => {
LocalStorageEventTarget.removeEventListener('clearFormLS', reset)
}
}, [reset])
return (
<div>
{routeElements}
Expand Down
4 changes: 2 additions & 2 deletions src/components/NavHeader/NavHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import Popover from '../Popover'
import { Link } from 'react-router-dom'
import path from 'src/constants/path'
import { AppContext } from 'src/contexts/app.context'
import { useMutation } from '@tanstack/react-query'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import authApi from 'src/apis/auth.api'
import { queryClient } from 'src/main'

export default function NavHeader() {
const { isAuthenticated, setIsAuthenticated, profile, setProfile } = useContext(AppContext)
const queryClient = useQueryClient()
const loginAccountMutation = useMutation({
mutationFn: authApi.logout,
onSuccess: () => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function Input({
const registerResult = register && name ? register(name, rules) : {}
return (
<div className={className}>
<input className={classNameInput} {...registerResult} />
<input className={classNameInput} {...registerResult} {...rest} />
<div className={classNameError}>{errorMessage}</div>
</div>
)
Expand Down
7 changes: 4 additions & 3 deletions src/constants/path.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import ProductDetail from 'src/pages/ProductDetail'

const path = {
home: '/',
profile: '/profile',
profile: '/user/profile',
changPassword: '/user/password',
historyPurchase: '/user/purchase',
login: '/login',
user: '/user',
register: '/register',
logout: '/logout',
productDetail: ':nameId',
Expand Down
10 changes: 8 additions & 2 deletions src/contexts/app.context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,30 @@ interface AppContextInterface {
setIsAuthenticated: React.Dispatch<React.SetStateAction<boolean>>
profile: User | null
setProfile: React.Dispatch<React.SetStateAction<User | null>>
reset: () => void
}
const initialAppContext: AppContextInterface = {
isAuthenticated: Boolean(getRefreshTokenFormLS()),
setIsAuthenticated: () => null,
profile: getProfilefromLS(),
setProfile: () => null
setProfile: () => null,
reset: () => null
}
export const AppContext = createContext<AppContextInterface>(initialAppContext)
export const AppProvider = ({ children }: { children: React.ReactNode }) => {
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(initialAppContext.isAuthenticated)
const [profile, setProfile] = useState<User | null>(initialAppContext.profile)
const reset = () => {
setIsAuthenticated(false), setProfile(null)
}
return (
<AppContext.Provider
value={{
isAuthenticated,
setIsAuthenticated,
profile,
setProfile
setProfile,
reset
}}
>
{children}
Expand Down
5 changes: 3 additions & 2 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { AppProvider } from './contexts/app.context'

export const queryClient = new QueryClient({
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false
refetchOnWindowFocus: false,
retry: 0
}
}
})
Expand Down
4 changes: 2 additions & 2 deletions src/pages/ProductDetail/ProductDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMutation, useQuery } from '@tanstack/react-query'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useParams } from 'react-router-dom'
import productApi from 'src/apis/product.api'
import ProductRating from 'src/components/ProductRating'
Expand All @@ -11,10 +11,10 @@ import 'react-medium-image-zoom/dist/styles.css'
import Product from '../ProductList/components/Product'
import QuantityController from 'src/components/QuantityController'
import cartApi from 'src/apis/cart.api'
import { queryClient } from 'src/main'
import Toast from 'src/components/Toast'

export default function ProductDetail() {
const queryClient = useQueryClient()
const [buyCount, setBuyCount] = useState(1)
const { nameId } = useParams()
const id = getIdFromNameId(nameId as string)
Expand Down
3 changes: 0 additions & 3 deletions src/pages/Profile/Profile.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/pages/Register/Register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function Register() {
//const rules = getRules(getValues)
const onSubmit = handleSubmit((data) => {
registerAccountMutation.mutate(data, {
onSuccess: (data) => {
onSuccess: () => {
setIsAuthenticated(true)
navigate('/')
},
Expand Down
21 changes: 21 additions & 0 deletions src/pages/User/UserLayout/UserLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import UserSideNav from '../components/UserSideNav'

interface LayoutProps {
children?: React.ReactNode
}

export default function UserLayout({ children }: LayoutProps) {
return (
<div className='bg-neutral-100 py-16 text-sm text-gray-600'>
<div className='container'>
<div className='grid grid-cols-1 gap-6 md:grid-cols-12'>
<div className='md:col-span-3 lg:col-span-2'>
<UserSideNav />
</div>

<div className='md:col-span-9 lg:col-span-10'>{children}</div>
</div>
</div>
</div>
)
}
3 changes: 3 additions & 0 deletions src/pages/User/UserLayout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import UserLayout from './UserLayout'

export default UserLayout
66 changes: 66 additions & 0 deletions src/pages/User/components/UserSideNav/UserSideNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Link } from 'react-router-dom'
import path from 'src/constants/path'

export default function UserSideNav() {
return (
<div>
<div className='flex items-center border-b border-b-gray-200 py-4'>
<Link to={path.profile} className='h-12 w-12 flex-shrink-0 overflow-hidden rounded-full border border-black/10'>
<img
src='https://down-vn.img.susercontent.com/file/vn-11134226-7r98o-lsrvn68ui3kp21_tn'
alt='avatar'
className='h-full w-full object-cover'
/>
</Link>
<div className='flex-grow pl-4'>
<div className='mb-1 truncate font-semibold text-gray-600'>Nguyễn Nhâm Ngọ</div>
<Link to={path.profile} className='flex items-center capitalize text-gray-500'>
<svg
width={12}
height={12}
viewBox='0 0 12 12'
xmlns='http://www.w3.org/2000/svg'
style={{ marginRight: 4 }}
>
<path
d='M8.54 0L6.987 1.56l3.46 3.48L12 3.48M0 8.52l.073 3.428L3.46 12l6.21-6.18-3.46-3.48'
fill='#9B9B9B'
fillRule='evenodd'
/>
</svg>
Sửa hồ sơ
</Link>
</div>
</div>
<div className='mt-7'>
<Link to={path.profile} className='flex mt-4 items-center capitalize text-orange transition-colors'>
<div className='mr-3 h-[22px] w-[22px]'>
<img
src='https://down-vn.img.susercontent.com/file/ba61750a46794d8847c3f463c5e71cc4'
className='w-full h-full'
/>
</div>
Tải khoản của tôi
</Link>
<Link to={path.changPassword} className='flex mt-4 items-center capitalize text-gray-600 transition-colors'>
<div className='mr-3 h-[22px] w-[22px]'>
<img
src='https://down-vn.img.susercontent.com/file/ba61750a46794d8847c3f463c5e71cc4'
className='w-full h-full'
/>
</div>
Đổi mật khẩu
</Link>
<Link to={path.historyPurchase} className='flex mt-4 items-center capitalize text-gray-600 transition-colors'>
<div className='mr-3 h-[22px] w-[22px]'>
<img
src='https://down-vn.img.susercontent.com/file/f0049e9df4e536bc3e7f140d071e9078'
className='w-full h-full'
/>
</div>
Đơn mua
</Link>
</div>
</div>
)
}
3 changes: 3 additions & 0 deletions src/pages/User/components/UserSideNav/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import UserSideNav from './UserSideNav'

export default UserSideNav
3 changes: 3 additions & 0 deletions src/pages/User/pages/ChangePassword/ChangePassword.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function ChangePassword() {
return <div>ChangePassword</div>
}
3 changes: 3 additions & 0 deletions src/pages/User/pages/ChangePassword/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ChangePassword from './ChangePassword'

export default ChangePassword
3 changes: 3 additions & 0 deletions src/pages/User/pages/HistoryPurchase/HistoryPurchase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function HistoryPurchase() {
return <div>HistoryPurchase</div>
}
3 changes: 3 additions & 0 deletions src/pages/User/pages/HistoryPurchase/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import HistoryPurchase from './HistoryPurchase'

export default HistoryPurchase
88 changes: 88 additions & 0 deletions src/pages/User/pages/Profile/Profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import Input from 'src/components/Input'

Check failure on line 1 in src/pages/User/pages/Profile/Profile.tsx

View workflow job for this annotation

GitHub Actions / Build

Cannot find module 'src/components/Input' or its corresponding type declarations.

export default function Profile() {
return (
<div className='rounded-sm bg-white px pb-10 md:px-7 md:pb-20 shadow'>
<div className='border-b border-b-gray-200 py-6'>
<h1 className='text-lg font-medium capitalize text-gray-900'>Hồ sở của tôi</h1>
<div className='mt-1 text-sm text-gray-700'>Quản lý thông tin hồ sở để bảo mật tài khoản</div>
</div>
<div className='mt-8 flex flex-col-reverse md:flex-row md:items-start'>
<form className='mt-6 flex-grow pr-5 md:pr-12 md:mt-0'>
<div className='flex flex-wrap flex-col sm:flex-row'>
<div className='sm:w-[20%] truncate pt-3 sm:text-right capitalize'>Email</div>
<div className='sm:w-[80%] sm:pl-5'>
<div className='pt-3 text-gray-700'>nhamngoo*****@gmail.com</div>
</div>
</div>
<div className='mt-6 flex flex-wrap flex-col sm:flex-row'>
<div className='sm:w-[20%] truncate pt-3 sm:text-right'>Họ và tên</div>
<div className='sm:w-[80%] sm:pl-5'>
<Input classNameInput='px-1 py-2 w-full outline-none border border-gray-300 focus:border-gray-500 rounded-sm focus:shadow-sm'></Input>
</div>
</div>
<div className='mt-2 flex flex-wrap flex-col sm:flex-row'>
<div className='sm:w-[20%] truncate pt-3 sm:text-right'>Số điện thoại</div>
<div className='sm:w-[80%] sm:pl-5'>
<Input classNameInput='px-1 py-2 w-full outline-none border border-gray-300 focus:border-gray-500 rounded-sm focus:shadow-sm'></Input>
</div>
</div>
<div className='mt-2 flex flex-wrap flex-col sm:flex-row'>
<div className='sm:w-[20%] truncate pt-3 sm:text-right'>Địa chỉ</div>
<div className='sm:w-[80%] sm:pl-5'>
<Input classNameInput='px-1 py-2 w-full outline-none border border-gray-300 focus:border-gray-500 rounded-sm focus:shadow-sm'></Input>
</div>
</div>
<div className='mt-2 flex flex-wrap flex-col sm:flex-row'>
<div className='sm:w-[20%] truncate pt-3 sm:text-right'>Ngày sinh</div>
<div className='flex justify-between sm:pl-5 sm:w-[50%]'>
<select className='h-10 w-[32%] rounded-sm border border-black/10 px-3 hover:border-orange outline-none'>
<option value='' disabled selected hidden className='text-black/10'>
Ngày
</option>
<option value='1'>Option 1</option>
<option value='2'>Option 2</option>
<option value='3'>Option 3</option>
</select>
<select className='h-10 w-[32%] rounded-sm border border-black/10 px-3 hover:border-orange outline-none'>
<option value='' disabled selected hidden className='text-black/10'>
Tháng
</option>
<option value='1'>Option 1</option>
<option value='2'>Option 2</option>
<option value='3'>Option 3</option>
</select>
<select className='h-10 w-[32%] rounded-sm border border-black/10 px-3 hover:border-orange outline-none'>
<option value='' disabled selected hidden className='text-black/10'>
Năm
</option>
<option value='1'>Option 1</option>
<option value='2'>Option 2</option>
<option value='3'>Option 3</option>
</select>
</div>
</div>
</form>
<div className='flex justify-center md:w-72 md:border-l md:border-l-gray-200'>
<div className='flex flex-col items-center'>
<div className='my-5 h-24 w-24'>
<img
src='https://down-vn.img.susercontent.com/file/vn-11134226-7r98o-lsrvn68ui3kp21_tn'
alt='avatar'
className='w-full h-full rounded-full object-cover'
/>
</div>
<input type='file' className='hidden' accept='.jpg,.jpeg,.png' />
<button className='flex h-10 items-center justify-end rounded-sm border bg-white px-6 text-sm text-gray-600 shadow-sm'>
Chọn ảnh
</button>
<div className='mt-3 text-gray-400'>
<div>Dung lương file tối đa 1 MB</div>
<div>Định dạng: ,JPG, .JPEG, .PNG</div>
</div>
</div>
</div>
</div>
</div>
)
}
File renamed without changes.
Loading

0 comments on commit 63e1b34

Please sign in to comment.