diff --git a/package-lock.json b/package-lock.json
index e49778e..2098e2f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,7 +21,7 @@
"autoprefixer": "10.4.15",
"axios": "^1.5.1",
"class-variance-authority": "^0.7.0",
- "clsx": "^2.0.0",
+ "clsx": "^2.1.0",
"eslint": "8.47.0",
"eslint-config-next": "^14.1.0",
"lucide-react": "^0.298.0",
@@ -33,7 +33,7 @@
"react-dom": "^18.2.0",
"react-icons": "^4.12.0",
"react-redux": "^8.1.3",
- "tailwind-merge": "^2.1.0",
+ "tailwind-merge": "^2.2.1",
"tailwindcss": "3.3.3",
"tailwindcss-animate": "^1.0.7",
"typescript": "5.1.6"
@@ -62,9 +62,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.23.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz",
- "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
+ "version": "7.23.9",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
+ "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -1616,15 +1616,23 @@
"url": "https://joebell.co.uk"
}
},
+ "node_modules/class-variance-authority/node_modules/clsx": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+ "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
"node_modules/clsx": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
- "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
+ "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
"engines": {
"node": ">=6"
}
@@ -4625,11 +4633,11 @@
}
},
"node_modules/tailwind-merge": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.1.0.tgz",
- "integrity": "sha512-l11VvI4nSwW7MtLSLYT4ldidDEUwQAMWuSHk7l4zcXZDgnCRa0V3OdCwFfM7DCzakVXMNRwAeje9maFFXT71dQ==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.1.tgz",
+ "integrity": "sha512-o+2GTLkthfa5YUt4JxPfzMIpQzZ3adD1vLVkvKE1Twl9UAhGsEbIZhHHZVRttyW177S8PDJI3bTQNaebyofK3Q==",
"dependencies": {
- "@babel/runtime": "^7.23.5"
+ "@babel/runtime": "^7.23.7"
},
"funding": {
"type": "github",
@@ -5129,9 +5137,9 @@
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="
},
"@babel/runtime": {
- "version": "7.23.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz",
- "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
+ "version": "7.23.9",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
+ "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
"requires": {
"regenerator-runtime": "^0.14.0"
}
@@ -6055,6 +6063,13 @@
"integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==",
"requires": {
"clsx": "2.0.0"
+ },
+ "dependencies": {
+ "clsx": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+ "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q=="
+ }
}
},
"client-only": {
@@ -6063,9 +6078,9 @@
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
"clsx": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
- "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q=="
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
+ "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg=="
},
"color-convert": {
"version": "2.0.1",
@@ -8120,11 +8135,11 @@
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
},
"tailwind-merge": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.1.0.tgz",
- "integrity": "sha512-l11VvI4nSwW7MtLSLYT4ldidDEUwQAMWuSHk7l4zcXZDgnCRa0V3OdCwFfM7DCzakVXMNRwAeje9maFFXT71dQ==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.1.tgz",
+ "integrity": "sha512-o+2GTLkthfa5YUt4JxPfzMIpQzZ3adD1vLVkvKE1Twl9UAhGsEbIZhHHZVRttyW177S8PDJI3bTQNaebyofK3Q==",
"requires": {
- "@babel/runtime": "^7.23.5"
+ "@babel/runtime": "^7.23.7"
}
},
"tailwindcss": {
diff --git a/package.json b/package.json
index 5bcca79..515f843 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
"autoprefixer": "10.4.15",
"axios": "^1.5.1",
"class-variance-authority": "^0.7.0",
- "clsx": "^2.0.0",
+ "clsx": "^2.1.0",
"eslint": "8.47.0",
"eslint-config-next": "^14.1.0",
"lucide-react": "^0.298.0",
@@ -34,7 +34,7 @@
"react-dom": "^18.2.0",
"react-icons": "^4.12.0",
"react-redux": "^8.1.3",
- "tailwind-merge": "^2.1.0",
+ "tailwind-merge": "^2.2.1",
"tailwindcss": "3.3.3",
"tailwindcss-animate": "^1.0.7",
"typescript": "5.1.6"
diff --git a/src/app/(index)/page.tsx b/src/app/(index)/page.tsx
index bd5beb2..39fd368 100644
--- a/src/app/(index)/page.tsx
+++ b/src/app/(index)/page.tsx
@@ -1,11 +1,14 @@
import { Fragment } from "react"
import { headers } from 'next/headers';
import Link from "next/link";
+import { redirect } from 'next/navigation'
+
const Page = ()=>{
const headersList = headers();
const activePath = headersList.get('x-invoke-path');
+ redirect('/shop')
return (
<>
@@ -44,7 +47,7 @@ const Page = ()=>{
: null }
-
+
>
)
diff --git a/src/app/(index)/shop/product/[id]/page.tsx b/src/app/(index)/shop/product/[id]/page.tsx
index b8b5507..4f85852 100644
--- a/src/app/(index)/shop/product/[id]/page.tsx
+++ b/src/app/(index)/shop/product/[id]/page.tsx
@@ -6,18 +6,30 @@ import { useRouter } from 'next/navigation'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import axiosInstance from '@/axios/axiosInstance'
import { useState } from 'react'
-
+import {
+ Table,
+ TableBody,
+ TableCaption,
+ TableCell,
+ TableFooter,
+ TableHead,
+ TableHeader,
+ TableRow,
+ } from "@/components/ui/table"
const Page = ({ params }: { params: { id: string } })=>{
const router = useRouter();
- const [products, setProducts] = useState<{category_name: string, category_img: string, products:[{id:number, name:string, price: number}]}>()
+ const [products, setProducts] = useState<{category_name: string, category_img: string,
+ products:[{id:number, name:string, price: number, view_only: boolean}],
+ view_only_products:[{id:number, name:string, price: number, view_only: boolean}]
+ }>()
const query = useQuery({ queryKey: ['productListByCat'], queryFn: async ()=>{
return await axiosInstance.get(`shop/product/list/${params.id}/`)
- }, onSuccess(data:any) {
- setProducts(data.data)
+ }, onSuccess(result:any) {
+ setProducts(result.data)
}, });
if(query.isLoading){
@@ -33,41 +45,64 @@ const Page = ({ params }: { params: { id: string } })=>{
return (
<>
-
+
-
+
{products?.category_name}
- { router.push('/shop', { scroll: false }) }} className='cursor-pointer bg-cyan-700 pr-1 pl-1 text-white text-[0.9rem] rounded'>بازگشت
+ { router.push('/shop', { scroll: false }) }} className='disable-select cursor-pointer bg-cyan-700 pr-1 pl-1 text-white text-[0.9rem] rounded'>بازگشت
-
-
+
+
{products?.products.map((iteam)=>{
- return (
)
+ if (iteam.view_only!=true){
+ return (
)
+ }
})}
-
-
-
+ {products?.view_only_products ? (
-
محصول زیر فقط بر مبنای سفارش قابل تولید است
+
+
+
محصولات زیر فقط بر مبنای سفارش قابل تولید است
+
+
+
+
+ کد محصول
+ نام محصول
+
+
+
+
+ {products?.view_only_products.map((iteam:any, key:any)=>{
+ return (
+
+ -----
+ {iteam.name}
+
+ )
+ })}
+
+
+
-
-
-
+
+ ) : null}
+
-
{ router.push('/shop', { scroll: false }) }} className='w-full text-center bg-gray-800 text-white rounded mt-2 p-2'>
+
{ router.push('/shop', { scroll: false }) }} className='disable-select w-full text-center bg-gray-800 text-white rounded mt-2 p-2'>
بازگشت به صفحه قبل
diff --git a/src/app/components/layout/customer-info.tsx b/src/app/components/layout/customer-info.tsx
index 9499ef3..b9d77a7 100644
--- a/src/app/components/layout/customer-info.tsx
+++ b/src/app/components/layout/customer-info.tsx
@@ -26,8 +26,8 @@ const CustomerInfo = ()=>{
return (
-
{nameFamily}
-
خروج
+
{nameFamily}
+
خروج
)
}
diff --git a/src/app/components/layout/hamber-menu.tsx b/src/app/components/layout/hamber-menu.tsx
index 7d03c3d..c558179 100644
--- a/src/app/components/layout/hamber-menu.tsx
+++ b/src/app/components/layout/hamber-menu.tsx
@@ -1,13 +1,16 @@
'use client'
import { useState } from "react"
import TopMenu from "./top-menu"
+import { IoMenu } from "react-icons/io5";
const HamberMenu = ()=>{
const [showMenu, setShowMenu] = useState(false)
return (
- { setShowMenu(!showMenu) }} >منو
+ { setShowMenu(!showMenu) }} >
+
+
)
diff --git a/src/app/components/layout/shop/orders-list.tsx b/src/app/components/layout/shop/orders-list.tsx
index e282725..9c3cbfb 100644
--- a/src/app/components/layout/shop/orders-list.tsx
+++ b/src/app/components/layout/shop/orders-list.tsx
@@ -10,12 +10,14 @@ import { RootState } from "@/app/redux/store"
import axiosInstance from "@/axios/axiosInstance"
import { addAllToCars, removeAllFromCart } from '@/app/redux/features/cartSlice';
import { useState } from 'react'
+import {useRouter} from "next/navigation";
const OrdersList = ()=>{
const {orderList} = useOrderContext()
const cartData = useSelector((state: RootState) => state.cart)
const dispatch = useDispatch()
+ const router = useRouter()
const query = useQuery({ queryKey: ['cartList1'], queryFn: async ()=>{
return await axiosInstance.get(`shop/cart/`)
@@ -24,8 +26,12 @@ const OrdersList = ()=>{
}, });
const [cartIsOpen, setCartIsOpen ] = useState
(false)
+ const [disableSubmit, setDisableSubmit] = useState(false)
const submitOrder = async ()=>{
+
+
+ setDisableSubmit(true)
const orderData = await cartData.map((item)=>{
return {
product_id: item.product.id,
@@ -38,8 +44,11 @@ const OrdersList = ()=>{
})
if(newOrder.status == 201){
+ setDisableSubmit(false)
alert("ثبت سفارش انجام شد")
dispatch(removeAllFromCart())
+ router.push('/orders')
+ //window.location.reload()
}
@@ -51,7 +60,7 @@ const OrdersList = ()=>{
- سبد خرید شما
+ سبد خرید شما
{ setCartIsOpen(false) }} className="md:hidden bg-slate-900 rounded-lg pr-2 pl-2 pt-1 pb-1">بستن
@@ -59,25 +68,44 @@ const OrdersList = ()=>{
{cartData?cartData.map((iteam, key)=>{
return
}):null }
+
+
+
مشاهده کامل سبد خرید
+
+ {!disableSubmit ? (
+
+ ثبت نهایی
+
+ ) : null}
+
+
-
+
+
+
مشاهده کامل سبد خرید
+
+ {!disableSubmit ? (
+
+ ثبت نهایی
+
+ ) : null}
+
-
مشاهده کامل سبد خرید
-
- ثبت نهایی
-
{cartData.length > 0 ? (
-
+
{ setCartIsOpen(true) }} className='bg-cyan-800 cursor-pointer text-white rounded-lg pt-2 pb-2 pr-4 pl-4'>
- مشاهده سبد خرید
- {cartData ? cartData.length : null}
+ مشاهده سبد خرید
+ {cartData ? cartData.length : null}
) : null}
diff --git a/src/app/components/layout/shop/products-cat.tsx b/src/app/components/layout/shop/products-cat.tsx
index b00cec5..4f63055 100644
--- a/src/app/components/layout/shop/products-cat.tsx
+++ b/src/app/components/layout/shop/products-cat.tsx
@@ -17,17 +17,17 @@ const ProductCategoryBox: any = (props:any)=>{
}
return (
-
{props.iteam.name}
+
{props.iteam.name}
-
+
-
+
{`${props.iteam.product_count} نوع`}
-
+
مشاهده
diff --git a/src/app/components/layout/shop/products.tsx b/src/app/components/layout/shop/products.tsx
index 5fed9b9..fef6b8e 100644
--- a/src/app/components/layout/shop/products.tsx
+++ b/src/app/components/layout/shop/products.tsx
@@ -70,13 +70,13 @@ const Products = (props:any)=>{
- {props.iteam.name}
+ {props.iteam.name}
-
-
{formatCurrency(props.iteam.price)}
-
تومان
+
+ {formatCurrency(props.iteam.price)}
+ تومان
@@ -84,8 +84,8 @@ const Products = (props:any)=>{
-
-
{ addIteamToCart(props.iteam) }} className='cursor-pointer bg-lime-600 text-white rounded pt-1 pb-1 w-full text-center'>
+
+ { addIteamToCart(props.iteam) }} className='disable-select cursor-pointer bg-lime-600 text-white rounded pt-1 pb-1 w-full text-center'>
{isInCart? "ویرایش":"ثبت"}
diff --git a/src/app/components/layout/top-menu.tsx b/src/app/components/layout/top-menu.tsx
index 2d450ef..54011d1 100644
--- a/src/app/components/layout/top-menu.tsx
+++ b/src/app/components/layout/top-menu.tsx
@@ -1,5 +1,6 @@
import Link from 'next/link'
+
interface TopMenuProps {
showMenu: boolean,
setShowMenu: Function,
@@ -7,15 +8,20 @@ interface TopMenuProps {
const TopMenu = (props: TopMenuProps)=>{
return (
-
- { props.setShowMenu(false) }} href={"/"}>
+
+
+ { props.setShowMenu(false) }} href={"/shop"}>
- صفحه اصلی
- - سفارشات
- - تیکت ها
- - چک ها
- - واریزی ها
- - صورت حساب
+
+ { props.setShowMenu(false) }} href={"/orders"}>
+ - سفارشات
+
+
+ { props.setShowMenu(false) }} href={"/tickets"}>
+ - تیکت ها
+
+
)
}
diff --git a/src/app/globals.css b/src/app/globals.css
index 6a75725..0760c1c 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -73,4 +73,12 @@
body {
@apply bg-background text-foreground;
}
+ .disable-select {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ }
}
\ No newline at end of file
diff --git a/src/axios/axiosInstance.ts b/src/axios/axiosInstance.ts
index 5912d78..169ef40 100644
--- a/src/axios/axiosInstance.ts
+++ b/src/axios/axiosInstance.ts
@@ -39,31 +39,47 @@ axiosInstance.interceptors.response.use((response)=> {
try {
- const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/token/refresh/`, {
- method: "POST",
- headers: {
- 'Content-Type': 'application/json; charset=UTF-8',
- },
- body: JSON.stringify({
- 'refresh': localStorage.getItem('refresh')
- })
- });
+ if (localStorage.getItem('refresh') != 'undefined'){
+ const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/token/refresh/`, {
+ method: "POST",
+ headers: {
+ 'Content-Type': 'application/json; charset=UTF-8',
+ },
+ body: JSON.stringify({
+ 'refresh': localStorage.getItem('refresh')
+ })
+ });
+
+ if(res.status==200){
+ setCookieFn('isAuth', 'true', 365)
+ const tokenData = await res.json()
+ localStorage.setItem('access', tokenData.access)
+ localStorage.setItem('refresh',tokenData.refresh)
+ originalRequest.headers.Authorization = `Bearer ${tokenData.access}`
+ return axiosInstance(originalRequest)
+ }else{
+
+ }
+ } else {
+
+ localStorage.removeItem('access');
+ localStorage.removeItem('refresh');
+ document.cookie = "isAuth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
+ setTimeout(()=>{
+ window.location.replace('/login')
+ }, 200)
- if(res.status==200){
- setCookieFn('isAuth', 'true', 365)
- const tokenData = await res.json()
- localStorage.setItem('access', tokenData.access)
- localStorage.setItem('refresh',tokenData.refresh)
- originalRequest.headers.Authorization = `Bearer ${tokenData.access}`
- return axiosInstance(originalRequest)
- }else{
-
}
-
-
} catch(refreshError) {
-
+
+ localStorage.removeItem('access');
+ localStorage.removeItem('refresh');
+ document.cookie = "isAuth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
+ setTimeout(()=>{
+ window.location.replace('/login')
+ }, 200)
+
throw refreshError;
}
}
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index ec79801..d084cca 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -1,6 +1,6 @@
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
-
+
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 0377ea1..84287e8 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -1,5 +1,6 @@
-/** @type {import('tailwindcss').Config} */
-module.exports = {
+import type { Config } from "tailwindcss"
+
+const config = {
darkMode: ["class"],
content: [
'./pages/**/*.{ts,tsx}',
@@ -7,6 +8,7 @@ module.exports = {
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
+ prefix: "",
theme: {
container: {
center: true,
@@ -58,12 +60,12 @@ module.exports = {
},
keyframes: {
"accordion-down": {
- from: { height: 0 },
+ from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
- to: { height: 0 },
+ to: { height: "0" },
},
},
animation: {
@@ -73,4 +75,6 @@ module.exports = {
},
},
plugins: [require("tailwindcss-animate")],
-}
\ No newline at end of file
+} satisfies Config
+
+export default config
\ No newline at end of file