Create file constant
This commit is contained in:
@@ -4,11 +4,6 @@ import withPWA from "next-pwa";
|
|||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
poweredByHeader: false,
|
poweredByHeader: false,
|
||||||
env: {
|
|
||||||
NEXT_PUBLIC_API_BASE_URL: process.env.NEXT_PUBLIC_API_BASE_URL,
|
|
||||||
NEXT_PUBLIC_TOKEN_NAME: process.env.NEXT_PUBLIC_TOKEN_NAME,
|
|
||||||
NEXT_PUBLIC_REFRESH_TOKEN_NAME: process.env.NEXT_PUBLIC_REFRESH_TOKEN_NAME,
|
|
||||||
},
|
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,32 +1,67 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useGetAddresses } from '@/app/[name]/(Profile)/profile/address/hooks/useAddressData';
|
import { useGetAddresses } from '@/app/[name]/(Profile)/profile/address/hooks/useAddressData';
|
||||||
|
import { Address } from '@/app/[name]/(Profile)/profile/address/types/Types';
|
||||||
|
import PrimaryButton from '@/components/button/PrimaryButton';
|
||||||
import { ChevronLeft } from 'lucide-react';
|
import { ChevronLeft } from 'lucide-react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
type AddressSectionProps = {
|
const formatAddress = (address: Address) => {
|
||||||
address: string;
|
return `${address.address}، ${address.city}، ${address.province}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AddressSection = ({ address }: AddressSectionProps) => {
|
export const AddressSection = () => {
|
||||||
|
|
||||||
const params = useParams<{ name: string; id: string }>();
|
const params = useParams<{ name: string; id: string }>();
|
||||||
const { t } = useTranslation('parallels', { keyPrefix: 'OrderDetail' });
|
const { t } = useTranslation('parallels', { keyPrefix: 'OrderDetail' });
|
||||||
const { data: addresses } = useGetAddresses();
|
const { data: addressesResponse, isLoading } = useGetAddresses();
|
||||||
|
const addresses = addressesResponse?.data || [];
|
||||||
|
const redirectUrl = `/${params.name}/order/checkout/${params.id}`;
|
||||||
|
|
||||||
console.log(addresses);
|
// اگر در حال بارگذاری است، چیزی نمایش نده
|
||||||
|
if (isLoading) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// اگر آدرس ندارد
|
||||||
|
if (addresses.length === 0) {
|
||||||
|
return (
|
||||||
|
<section className="bg-container rounded-container box-shadow-normal p-4">
|
||||||
|
<div className="py-3">
|
||||||
|
<h3 className="text-sm2 font-medium leading-5 mb-4">{t("SectionAddress.Title")}</h3>
|
||||||
|
<p className='text-sm2 text-disabled-text mb-4'>
|
||||||
|
آدرسی ثبت نشده است
|
||||||
|
</p>
|
||||||
|
<Link href={`/${params.name}/profile/address/new?redirect=${encodeURIComponent(redirectUrl)}`}>
|
||||||
|
<PrimaryButton>
|
||||||
|
افزودن آدرس جدید
|
||||||
|
</PrimaryButton>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// فیلتر کردن آدرسهای غیر پیشفرض
|
||||||
|
const nonDefaultAddresses = addresses.filter(addr => !addr.isDefault);
|
||||||
|
|
||||||
|
// اگر فقط آدرس پیشفرض دارد، نمایش نده
|
||||||
|
if (nonDefaultAddresses.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// آدرس اول غیر پیشفرض را نمایش بده
|
||||||
|
const firstNonDefaultAddress = nonDefaultAddresses[0];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="bg-container rounded-container box-shadow-normal p-4">
|
<section className="bg-container rounded-container box-shadow-normal p-4">
|
||||||
<div className="py-3">
|
<div className="py-3">
|
||||||
<div className='w-full flex justify-between items-center gap-2'>
|
<div className='w-full flex justify-between items-center gap-2'>
|
||||||
<h3 className="text-sm2 font-medium leading-5 inline-block">{t("SectionAddress.Title")}</h3>
|
<h3 className="text-sm2 font-medium leading-5 inline-block">{t("SectionAddress.Title")}</h3>
|
||||||
<Link href={`/${params.name}/profile/address?redirect=/${params.name}/order/checkout/${params.id}`}>
|
<Link href={`/${params.name}/profile/address?redirect=${encodeURIComponent(redirectUrl)}`}>
|
||||||
<button
|
<button
|
||||||
className='text-sm2 text-primary dark:text-foreground cursor-pointer'
|
className='text-sm2 text-primary dark:text-foreground cursor-pointer'
|
||||||
onClick={() => { /* Handle address change */ }}
|
|
||||||
>
|
>
|
||||||
{t("SectionAddress.ButtonChangeAddress")}
|
{t("SectionAddress.ButtonChangeAddress")}
|
||||||
<ChevronLeft className='inline-block mr-1 mb-0.5 stroke-primary dark:stroke-foreground' size='16' />
|
<ChevronLeft className='inline-block mr-1 mb-0.5 stroke-primary dark:stroke-foreground' size='16' />
|
||||||
@@ -34,7 +69,7 @@ export const AddressSection = ({ address }: AddressSectionProps) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<p className='mt-6 text-sm2'>
|
<p className='mt-6 text-sm2'>
|
||||||
{address}
|
{formatAddress(firstNonDefaultAddress)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ function OrderDetailInex() {
|
|||||||
const [couponCode, setCouponCode] = React.useState<string>('');
|
const [couponCode, setCouponCode] = React.useState<string>('');
|
||||||
const [couponCodeError, setCouponCodeError] = React.useState<string>('');
|
const [couponCodeError, setCouponCodeError] = React.useState<string>('');
|
||||||
const [tableNumber, setTableNumber] = useState(0);
|
const [tableNumber, setTableNumber] = useState(0);
|
||||||
const address = "اراک، مصطفی خمینی، خیابان سینا کوچه چمران ساختمان شهرزاد";
|
|
||||||
const { state: cartModal, toggle: toggleCartModal } = useToggle();
|
const { state: cartModal, toggle: toggleCartModal } = useToggle();
|
||||||
|
|
||||||
const incrementTableNumber = () => setTableNumber((prev) => prev + 1);
|
const incrementTableNumber = () => setTableNumber((prev) => prev + 1);
|
||||||
@@ -51,7 +50,7 @@ function OrderDetailInex() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{deliveryType === '0' && (
|
{deliveryType === '0' && (
|
||||||
<AddressSection address={address} />
|
<AddressSection />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{deliveryType === '1' && (
|
{deliveryType === '1' && (
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
import { useCreateAddress, useUpdateAddress } from '../../hooks/useAddressData';
|
import { useCreateAddress, useUpdateAddress } from '../../hooks/useAddressData';
|
||||||
import { toast } from '@/components/Toast';
|
import { toast } from '@/components/Toast';
|
||||||
import { CreateAddressType, UpdateAddressType, NominatimReverseGeocodingResponse, Address } from '../../types/Types';
|
import { CreateAddressType, UpdateAddressType, NominatimReverseGeocodingResponse, Address } from '../../types/Types';
|
||||||
@@ -20,6 +20,8 @@ export const useAddressForm = ({
|
|||||||
addressData = null,
|
addressData = null,
|
||||||
}: UseAddressFormProps) => {
|
}: UseAddressFormProps) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const redirect = searchParams.get('redirect');
|
||||||
const { mutate: createAddress, isPending: isCreating } = useCreateAddress();
|
const { mutate: createAddress, isPending: isCreating } = useCreateAddress();
|
||||||
const { mutate: updateAddress, isPending: isUpdating } = useUpdateAddress();
|
const { mutate: updateAddress, isPending: isUpdating } = useUpdateAddress();
|
||||||
const isPending = isCreating || isUpdating;
|
const isPending = isCreating || isUpdating;
|
||||||
@@ -92,7 +94,11 @@ export const useAddressForm = ({
|
|||||||
updateAddress(updateData, {
|
updateAddress(updateData, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast('آدرس با موفقیت بهروزرسانی شد', 'success');
|
toast('آدرس با موفقیت بهروزرسانی شد', 'success');
|
||||||
router.back();
|
if (redirect) {
|
||||||
|
router.replace(redirect);
|
||||||
|
} else {
|
||||||
|
router.back();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'خطا در بهروزرسانی آدرس';
|
const errorMessage = error instanceof Error ? error.message : 'خطا در بهروزرسانی آدرس';
|
||||||
@@ -105,7 +111,11 @@ export const useAddressForm = ({
|
|||||||
createAddress(createData, {
|
createAddress(createData, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast('آدرس با موفقیت ثبت شد', 'success');
|
toast('آدرس با موفقیت ثبت شد', 'success');
|
||||||
router.back();
|
if (redirect) {
|
||||||
|
router.replace(redirect);
|
||||||
|
} else {
|
||||||
|
router.back();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'خطا در ثبت آدرس';
|
const errorMessage = error instanceof Error ? error.message : 'خطا در ثبت آدرس';
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export const API_BASE_URL = "https://dmenuplus-api.dev.danakcorp.com";
|
||||||
|
export const TOKEN_NAME = "dmenu-t";
|
||||||
|
export const REFRESH_TOKEN_NAME = "dmenu-rt";
|
||||||
@@ -10,6 +10,7 @@ import Button from '@/components/button/PrimaryButton'
|
|||||||
import { extractErrorMessage } from '@/lib/func'
|
import { extractErrorMessage } from '@/lib/func'
|
||||||
import { useReceiptStore } from '@/zustand/receiptStore'
|
import { useReceiptStore } from '@/zustand/receiptStore'
|
||||||
import { useBulkCart } from '@/app/[name]/(Dialogs)/cart/hooks/useCartData'
|
import { useBulkCart } from '@/app/[name]/(Dialogs)/cart/hooks/useCartData'
|
||||||
|
import { setRefreshToken, setToken } from '@/lib/api/func'
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -38,8 +39,8 @@ const StepOtp = ({ phone, slug }: Props) => {
|
|||||||
mutateOtpVerify(values, {
|
mutateOtpVerify(values, {
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
toast(t('otp_verified'), 'success')
|
toast(t('otp_verified'), 'success')
|
||||||
localStorage.setItem(process.env.NEXT_PUBLIC_TOKEN_NAME as string, data?.data?.tokens?.accessToken?.token as string)
|
setToken(data?.data?.tokens?.accessToken?.token as string)
|
||||||
localStorage.setItem(process.env.NEXT_PUBLIC_REFRESH_TOKEN_NAME as string, data?.data?.tokens?.refreshToken?.token as string)
|
setRefreshToken(data?.data?.tokens?.refreshToken?.token as string)
|
||||||
|
|
||||||
if (Object.keys(items).length > 0) {
|
if (Object.keys(items).length > 0) {
|
||||||
const bulkCartItems = Object.entries(items).map(([key, value]) => {
|
const bulkCartItems = Object.entries(items).map(([key, value]) => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { API_BASE_URL } from "@/config/const";
|
||||||
|
|
||||||
export type RefreshTokenRequestModel = {
|
export type RefreshTokenRequestModel = {
|
||||||
token: string;
|
token: string;
|
||||||
@@ -6,7 +7,7 @@ export type RefreshTokenRequestModel = {
|
|||||||
|
|
||||||
export const refreshToken = async (model: RefreshTokenRequestModel) => {
|
export const refreshToken = async (model: RefreshTokenRequestModel) => {
|
||||||
const res = await axios.post(
|
const res = await axios.post(
|
||||||
`${process.env.NEXT_PUBLIC_API_BASE_URL}/public/auth/refresh`,
|
`${API_BASE_URL}/public/auth/refresh`,
|
||||||
{ refreshToken: model.token },
|
{ refreshToken: model.token },
|
||||||
{
|
{
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
removeRefreshToken,
|
removeRefreshToken,
|
||||||
} from "./func";
|
} from "./func";
|
||||||
import { refreshToken } from "./auth/refresh-token";
|
import { refreshToken } from "./auth/refresh-token";
|
||||||
|
import { API_BASE_URL } from "@/config/const";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@@ -16,7 +17,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const axiosInstance = axios.create({
|
const axiosInstance = axios.create({
|
||||||
baseURL: process.env.NEXT_PUBLIC_API_BASE_URL,
|
baseURL: API_BASE_URL,
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+8
-19
@@ -1,42 +1,31 @@
|
|||||||
|
import { REFRESH_TOKEN_NAME, TOKEN_NAME } from "@/config/const";
|
||||||
|
|
||||||
export const getToken = async (): Promise<string | null> => {
|
export const getToken = async (): Promise<string | null> => {
|
||||||
if (typeof window === "undefined") return null;
|
if (typeof window === "undefined") return null;
|
||||||
return localStorage.getItem(
|
return localStorage.getItem(TOKEN_NAME);
|
||||||
process.env.NEXT_PUBLIC_TOKEN_NAME as string
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getRefreshToken = async (): Promise<string | null> => {
|
export const getRefreshToken = async (): Promise<string | null> => {
|
||||||
if (typeof window === "undefined") return null;
|
if (typeof window === "undefined") return null;
|
||||||
return localStorage.getItem(
|
return localStorage.getItem(REFRESH_TOKEN_NAME);
|
||||||
process.env.NEXT_PUBLIC_REFRESH_TOKEN_NAME as string
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setToken = async (token: string): Promise<void> => {
|
export const setToken = async (token: string): Promise<void> => {
|
||||||
if (typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
localStorage.setItem(
|
localStorage.setItem(TOKEN_NAME, token);
|
||||||
process.env.NEXT_PUBLIC_TOKEN_NAME as string,
|
|
||||||
token
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setRefreshToken = async (token: string): Promise<void> => {
|
export const setRefreshToken = async (token: string): Promise<void> => {
|
||||||
if (typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
localStorage.setItem(
|
localStorage.setItem(REFRESH_TOKEN_NAME, token);
|
||||||
process.env.NEXT_PUBLIC_REFRESH_TOKEN_NAME as string,
|
|
||||||
token
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeToken = async (): Promise<void> => {
|
export const removeToken = async (): Promise<void> => {
|
||||||
if (typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
localStorage.removeItem(process.env.NEXT_PUBLIC_TOKEN_NAME as string);
|
localStorage.removeItem(TOKEN_NAME);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeRefreshToken = async (): Promise<void> => {
|
export const removeRefreshToken = async (): Promise<void> => {
|
||||||
if (typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
localStorage.removeItem(
|
localStorage.removeItem(REFRESH_TOKEN_NAME);
|
||||||
process.env.NEXT_PUBLIC_REFRESH_TOKEN_NAME as string
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user