@@ -62,7 +64,7 @@ function HSInput({
name={name}
onBlur={onBlurTextArea}
cols={30}
- rows={10}
+ rows={rows}
placeholder={placeholder}
onChange={onChangeTextArea}
value={values}
diff --git a/src/features/Auth/addProductSlice.tsx b/src/features/Auth/addProductSlice.tsx
new file mode 100644
index 00000000..0a63a7a8
--- /dev/null
+++ b/src/features/Auth/addProductSlice.tsx
@@ -0,0 +1,136 @@
+import { createSlice, PayloadAction, createAsyncThunk } from '@reduxjs/toolkit';
+import axios from 'axios';
+import { showSuccessToast, showErrorToast } from '@/utils/ToastConfig';
+
+interface ProductState {
+ name: string;
+ image: string | null;
+ gallery: string[];
+ shortDesc: string;
+ longDesc: string;
+ quantity: number;
+ regularPrice: number;
+ salesPrice: number;
+ tags: string[];
+ type: string;
+ isAvailable: boolean;
+ loading: boolean;
+ error: string | null;
+}
+
+const initialState: ProductState = {
+ name: '',
+ image: null,
+ gallery: [],
+ shortDesc: '',
+ longDesc: '',
+ quantity: 0,
+ regularPrice: 0,
+ salesPrice: 0,
+ tags: [],
+ type: '',
+ isAvailable: true,
+ loading: false,
+ error: null,
+};
+
+const apiUrl = `${import.meta.env.VITE_BASE_URL}/product`;
+
+export const createProduct = createAsyncThunk(
+ 'product/createProduct',
+ async (
+ productData: Omit
,
+ { rejectWithValue }
+ ) => {
+ const token = localStorage.getItem('token');
+ if (!token) {
+ return rejectWithValue('No token found');
+ }
+
+ try {
+ const response = await axios.post(apiUrl, productData, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ });
+ return response.data;
+ } catch (error: any) {
+ return rejectWithValue(
+ error.response?.data?.message || 'Failed to create product'
+ );
+ }
+ }
+);
+
+const addProductSlice = createSlice({
+ name: 'product',
+ initialState,
+ reducers: {
+ setName: (state, action: PayloadAction) => {
+ state.name = action.payload;
+ },
+ setImage: (state, action: PayloadAction) => {
+ state.image = action.payload;
+ },
+ setGallery: (state, action: PayloadAction) => {
+ state.gallery = action.payload;
+ },
+ setShortDesc: (state, action: PayloadAction) => {
+ state.shortDesc = action.payload;
+ },
+ setLongDesc: (state, action: PayloadAction) => {
+ state.longDesc = action.payload;
+ },
+
+ setQuantity: (state, action: PayloadAction) => {
+ state.quantity = action.payload;
+ },
+ setRegularPrice: (state, action: PayloadAction) => {
+ state.regularPrice = action.payload;
+ },
+ setSalesPrice: (state, action: PayloadAction) => {
+ state.salesPrice = action.payload;
+ },
+ setTags: (state, action: PayloadAction) => {
+ state.tags = action.payload;
+ },
+ setType: (state, action: PayloadAction) => {
+ state.type = action.payload;
+ },
+ setAvailability: (state, action: PayloadAction) => {
+ state.isAvailable = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder
+ .addCase(createProduct.pending, (state) => {
+ state.loading = true;
+ state.error = null;
+ })
+ .addCase(createProduct.fulfilled, (state) => {
+ state.loading = false;
+ showSuccessToast('Product created successfully');
+ })
+ .addCase(createProduct.rejected, (state, action) => {
+ state.loading = false;
+ state.error = action.payload as string;
+ showErrorToast(state.error);
+ });
+ },
+});
+
+export const {
+ setName,
+ setImage,
+ setGallery,
+ setShortDesc,
+ setLongDesc,
+ setQuantity,
+ setRegularPrice,
+ setSalesPrice,
+ setTags,
+ setType,
+ setAvailability,
+} = addProductSlice.actions;
+
+export default addProductSlice.reducer;
diff --git a/src/layout/VendorDashbordLayout.tsx b/src/layout/VendorDashbordLayout.tsx
new file mode 100644
index 00000000..2e8bb21f
--- /dev/null
+++ b/src/layout/VendorDashbordLayout.tsx
@@ -0,0 +1,23 @@
+import { Outlet } from 'react-router-dom';
+import VendorDashNav from '@/components/VendorDshboard/VendorDashNav';
+import VendorDashSideBar from '@/components/VendorDshboard/VendorDashSideBar';
+
+function VendorDashboardLayout() {
+ return (
+
+ );
+}
+
+export default VendorDashboardLayout;
diff --git a/src/pages/AdminRoutes.tsx b/src/pages/AdminRoutes.tsx
index 75cc915e..4e1ccd44 100644
--- a/src/pages/AdminRoutes.tsx
+++ b/src/pages/AdminRoutes.tsx
@@ -9,8 +9,7 @@ interface Adminprops {
function AdminRoutes({ children }: Adminprops) {
const user = useAppSelector((state) => state.signIn.user);
- return user?.userType?.name === 'Admin' ||
- user?.userType?.name === 'Vendor' ? (
+ return user?.userType?.name === 'Admin' ? (
children
) : (
diff --git a/src/pages/TwoFactorAuthForm.tsx b/src/pages/TwoFactorAuthForm.tsx
index 268fe6fa..859327ca 100644
--- a/src/pages/TwoFactorAuthForm.tsx
+++ b/src/pages/TwoFactorAuthForm.tsx
@@ -90,7 +90,7 @@ function TwoFactorAuthForm() {
useEffect(() => {
if (token && user?.userType.name === 'Vendor') {
showSuccessToast('Vendor Logged In Sucessfully');
- navigate('/');
+ navigate('/vendor');
}
}, [token, user, navigate]);
diff --git a/src/routes/AppRoutes.tsx b/src/routes/AppRoutes.tsx
index 8662a95d..146dd61f 100644
--- a/src/routes/AppRoutes.tsx
+++ b/src/routes/AppRoutes.tsx
@@ -15,6 +15,9 @@ import EditProductPage from '@/pages/EditPage';
import Shop from '@/pages/Shop';
import Wishlist from '@/pages/Wishlist';
import { Orders } from '@/components/Orders/Orders';
+import VendorDashboardLayout from '@/layout/VendorDashbordLayout';
+import AddProducts from '@/components/VendorDshboard/addProducts';
+import VendorHomeDash from '@/components/VendorDshboard/VendorHomeDash';
function AppRoutes() {
return (
@@ -27,6 +30,11 @@ function AppRoutes() {
} />
} />
} />
+ }>
+ } />
+ } />
+
+ } />
} />
} />
diff --git a/src/utils/UploadImages.ts b/src/utils/cloudinary.tsx
similarity index 82%
rename from src/utils/UploadImages.ts
rename to src/utils/cloudinary.tsx
index 4073daf4..91adfbb9 100644
--- a/src/utils/UploadImages.ts
+++ b/src/utils/cloudinary.tsx
@@ -16,9 +16,9 @@ export const uploadSingleImage = async (file: File): Promise => {
return response.data.secure_url;
} catch (error) {
if (error instanceof AxiosError) {
- throw new Error(`Error uploading image: ${error.message}`);
+ throw error;
} else {
- throw new Error(`Unexpected error occurred: ${error}`);
+ throw error;
}
}
};
@@ -37,9 +37,9 @@ export const uploadGalleryImages = async (files: File[]): Promise => {
return response.data.secure_url;
} catch (error) {
if (error instanceof AxiosError) {
- throw new Error(`Error uploading image: ${error.message}`);
+ throw error;
} else {
- throw new Error(`Unexpected error occurred: ${error}`);
+ throw error;
}
}
});