-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | Product |
- SKU |
- Category |
- Qty |
- Action |
-
-
-
-
- |
-
-
-
-
-
- Nike Jordan
-
-
- |
- PT002 |
- Nike |
-
-
-
-
-
-
-
- +
-
-
-
- |
-
-
-
-
-
-
-
-
-
- |
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
diff --git a/src/core/redux/actions/inventoryActions.js b/src/core/redux/actions/inventoryActions.js
new file mode 100644
index 0000000..bd6f214
--- /dev/null
+++ b/src/core/redux/actions/inventoryActions.js
@@ -0,0 +1,143 @@
+import { inventoryApi } from '../../../services/inventoriesApi';
+
+// Action Types
+export const INVENTORY_ACTIONS = {
+ // Fetch Inventories
+ FETCH_INVENTORIES_REQUEST: 'FETCH_INVENTORIES_REQUEST',
+ FETCH_INVENTORIES_SUCCESS: 'FETCH_INVENTORIES_SUCCESS',
+ FETCH_INVENTORIES_FAILURE: 'FETCH_INVENTORIES_FAILURE',
+
+ // Fetch Single Inventory
+ FETCH_INVENTORY_REQUEST: 'FETCH_INVENTORY_REQUEST',
+ FETCH_INVENTORY_SUCCESS: 'FETCH_INVENTORY_SUCCESS',
+ FETCH_INVENTORY_FAILURE: 'FETCH_INVENTORY_FAILURE',
+
+ // Create Inventory
+ CREATE_INVENTORY_REQUEST: 'CREATE_INVENTORY_REQUEST',
+ CREATE_INVENTORY_SUCCESS: 'CREATE_INVENTORY_SUCCESS',
+ CREATE_INVENTORY_FAILURE: 'CREATE_INVENTORY_FAILURE',
+
+ // Update Inventory
+ UPDATE_INVENTORY_REQUEST: 'UPDATE_INVENTORY_REQUEST',
+ UPDATE_INVENTORY_SUCCESS: 'UPDATE_INVENTORY_SUCCESS',
+ UPDATE_INVENTORY_FAILURE: 'UPDATE_INVENTORY_FAILURE',
+
+ // Delete Inventory
+ DELETE_INVENTORY_REQUEST: 'DELETE_INVENTORY_REQUEST',
+ DELETE_INVENTORY_SUCCESS: 'DELETE_INVENTORY_SUCCESS',
+ DELETE_INVENTORY_FAILURE: 'DELETE_INVENTORY_FAILURE',
+
+ // Search Inventories
+ SEARCH_INVENTORIES_REQUEST: 'SEARCH_INVENTORIES_REQUEST',
+ SEARCH_INVENTORIES_SUCCESS: 'SEARCH_INVENTORIES_SUCCESS',
+ SEARCH_INVENTORIES_FAILURE: 'SEARCH_INVENTORIES_FAILURE',
+
+ // Clear States
+ CLEAR_INVENTORY_ERROR: 'CLEAR_INVENTORY_ERROR',
+ CLEAR_CURRENT_INVENTORY: 'CLEAR_CURRENT_INVENTORY',
+};
+
+// Action Creators
+
+export const fetchInventories = (params = {}) => async (dispatch) => {
+ dispatch({ type: INVENTORY_ACTIONS.FETCH_INVENTORIES_REQUEST });
+
+ try {
+ const data = await inventoryApi.getAllInventories(params);
+ dispatch({
+ type: INVENTORY_ACTIONS.FETCH_INVENTORIES_SUCCESS,
+ payload: data,
+ });
+ return data;
+ } catch (error) {
+ dispatch({
+ type: INVENTORY_ACTIONS.FETCH_INVENTORIES_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to fetch inventories',
+ });
+ throw error;
+ }
+};
+
+export const fetchInventory = (id) => async (dispatch) => {
+ dispatch({ type: INVENTORY_ACTIONS.FETCH_INVENTORY_REQUEST });
+
+ try {
+ const data = await inventoryApi.getInventoryById(id);
+ dispatch({
+ type: INVENTORY_ACTIONS.FETCH_INVENTORY_SUCCESS,
+ payload: data,
+ });
+ return data;
+ } catch (error) {
+ dispatch({
+ type: INVENTORY_ACTIONS.FETCH_INVENTORY_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to fetch inventory',
+ });
+ throw error;
+ }
+};
+
+export const createInventory = (inventoryData) => async (dispatch) => {
+ dispatch({ type: INVENTORY_ACTIONS.CREATE_INVENTORY_REQUEST });
+
+ try {
+ const data = await inventoryApi.createInventory(inventoryData);
+ dispatch({
+ type: INVENTORY_ACTIONS.CREATE_INVENTORY_SUCCESS,
+ payload: data,
+ });
+ return data;
+ } catch (error) {
+ dispatch({
+ type: INVENTORY_ACTIONS.CREATE_INVENTORY_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to create inventory',
+ });
+ throw error;
+ }
+};
+
+export const updateInventory = (id, inventoryData) => async (dispatch) => {
+ dispatch({ type: INVENTORY_ACTIONS.UPDATE_INVENTORY_REQUEST });
+
+ try {
+ const data = await inventoryApi.updateInventory(id, inventoryData);
+ dispatch({
+ type: INVENTORY_ACTIONS.UPDATE_INVENTORY_SUCCESS,
+ payload: { id, data },
+ });
+ return data;
+ } catch (error) {
+ dispatch({
+ type: INVENTORY_ACTIONS.UPDATE_INVENTORY_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to update inventory',
+ });
+ throw error;
+ }
+};
+
+export const deleteInventory = (id) => async (dispatch) => {
+ dispatch({ type: INVENTORY_ACTIONS.DELETE_INVENTORY_REQUEST });
+
+ try {
+ await inventoryApi.deleteInventory(id);
+ dispatch({
+ type: INVENTORY_ACTIONS.DELETE_INVENTORY_SUCCESS,
+ payload: id,
+ });
+ return id;
+ } catch (error) {
+ dispatch({
+ type: INVENTORY_ACTIONS.DELETE_INVENTORY_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to delete inventory',
+ });
+ throw error;
+ }
+};
+
+export const clearInventoryError = () => ({
+ type: INVENTORY_ACTIONS.CLEAR_INVENTORY_ERROR,
+});
+
+export const clearCurrentInventory = () => ({
+ type: INVENTORY_ACTIONS.CLEAR_CURRENT_INVENTORY,
+});
diff --git a/src/core/redux/actions/outletActions.js b/src/core/redux/actions/outletActions.js
new file mode 100644
index 0000000..3a6185e
--- /dev/null
+++ b/src/core/redux/actions/outletActions.js
@@ -0,0 +1,138 @@
+import { outletsApi } from '../../../services/outletsApi';
+
+// Action Types
+export const OUTLET_ACTIONS = {
+ // Fetch Outlets
+ FETCH_OUTLETS_REQUEST: 'FETCH_OUTLETS_REQUEST',
+ FETCH_OUTLETS_SUCCESS: 'FETCH_OUTLETS_SUCCESS',
+ FETCH_OUTLETS_FAILURE: 'FETCH_OUTLETS_FAILURE',
+
+ // Fetch Single Outlet
+ FETCH_OUTLET_REQUEST: 'FETCH_OUTLET_REQUEST',
+ FETCH_OUTLET_SUCCESS: 'FETCH_OUTLET_SUCCESS',
+ FETCH_OUTLET_FAILURE: 'FETCH_OUTLET_FAILURE',
+
+ // Create Outlet
+ CREATE_OUTLET_REQUEST: 'CREATE_OUTLET_REQUEST',
+ CREATE_OUTLET_SUCCESS: 'CREATE_OUTLET_SUCCESS',
+ CREATE_OUTLET_FAILURE: 'CREATE_OUTLET_FAILURE',
+
+ // Update Outlet
+ UPDATE_OUTLET_REQUEST: 'UPDATE_OUTLET_REQUEST',
+ UPDATE_OUTLET_SUCCESS: 'UPDATE_OUTLET_SUCCESS',
+ UPDATE_OUTLET_FAILURE: 'UPDATE_OUTLET_FAILURE',
+
+ // Delete Outlet
+ DELETE_OUTLET_REQUEST: 'DELETE_OUTLET_REQUEST',
+ DELETE_OUTLET_SUCCESS: 'DELETE_OUTLET_SUCCESS',
+ DELETE_OUTLET_FAILURE: 'DELETE_OUTLET_FAILURE',
+
+ // Clear States
+ CLEAR_OUTLET_ERROR: 'CLEAR_OUTLET_ERROR',
+ CLEAR_CURRENT_OUTLET: 'CLEAR_CURRENT_OUTLET',
+};
+
+// Action Creators
+
+export const fetchOutlets = (params = {}) => async (dispatch) => {
+ dispatch({ type: OUTLET_ACTIONS.FETCH_OUTLETS_REQUEST });
+
+ try {
+ const data = await outletsApi.getAllOutlets(params);
+ dispatch({
+ type: OUTLET_ACTIONS.FETCH_OUTLETS_SUCCESS,
+ payload: data,
+ });
+ return data;
+ } catch (error) {
+ dispatch({
+ type: OUTLET_ACTIONS.FETCH_OUTLETS_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to fetch outlets',
+ });
+ throw error;
+ }
+};
+
+export const fetchOutlet = (id) => async (dispatch) => {
+ dispatch({ type: OUTLET_ACTIONS.FETCH_OUTLET_REQUEST });
+
+ try {
+ const data = await outletsApi.getOutletById(id);
+ dispatch({
+ type: OUTLET_ACTIONS.FETCH_OUTLET_SUCCESS,
+ payload: data,
+ });
+ return data;
+ } catch (error) {
+ dispatch({
+ type: OUTLET_ACTIONS.FETCH_OUTLET_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to fetch outlet',
+ });
+ throw error;
+ }
+};
+
+export const createOutlet = (outletData) => async (dispatch) => {
+ dispatch({ type: OUTLET_ACTIONS.CREATE_OUTLET_REQUEST });
+
+ try {
+ const data = await outletsApi.createOutlet(outletData);
+ dispatch({
+ type: OUTLET_ACTIONS.CREATE_OUTLET_SUCCESS,
+ payload: data,
+ });
+ return data;
+ } catch (error) {
+ dispatch({
+ type: OUTLET_ACTIONS.CREATE_OUTLET_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to create outlet',
+ });
+ throw error;
+ }
+};
+
+export const updateOutlet = (id, outletData) => async (dispatch) => {
+ dispatch({ type: OUTLET_ACTIONS.UPDATE_OUTLET_REQUEST });
+
+ try {
+ const data = await outletsApi.updateOutlet(id, outletData);
+ dispatch({
+ type: OUTLET_ACTIONS.UPDATE_OUTLET_SUCCESS,
+ payload: { id, data },
+ });
+ return data;
+ } catch (error) {
+ dispatch({
+ type: OUTLET_ACTIONS.UPDATE_OUTLET_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to update outlet',
+ });
+ throw error;
+ }
+};
+
+export const deleteOutlet = (id) => async (dispatch) => {
+ dispatch({ type: OUTLET_ACTIONS.DELETE_OUTLET_REQUEST });
+
+ try {
+ await outletsApi.deleteOutlet(id);
+ dispatch({
+ type: OUTLET_ACTIONS.DELETE_OUTLET_SUCCESS,
+ payload: id,
+ });
+ return id;
+ } catch (error) {
+ dispatch({
+ type: OUTLET_ACTIONS.DELETE_OUTLET_FAILURE,
+ payload: error.response?.data?.message || error.message || 'Failed to delete outlet',
+ });
+ throw error;
+ }
+};
+
+export const clearOutletError = () => ({
+ type: OUTLET_ACTIONS.CLEAR_OUTLET_ERROR,
+});
+
+export const clearCurrentOutlet = () => ({
+ type: OUTLET_ACTIONS.CLEAR_CURRENT_OUTLET,
+});
diff --git a/src/core/redux/reducer.jsx b/src/core/redux/reducer.jsx
index e3f10a9..9633017 100644
--- a/src/core/redux/reducer.jsx
+++ b/src/core/redux/reducer.jsx
@@ -6,6 +6,8 @@ import categoryReducer from './reducers/categoryReducer';
import orderReducer from './reducers/orderReducer';
import paymentMethodReducer from './reducers/paymentMethodReducer';
import organizationReducer from './reducers/organizationReducer';
+import inventoryReducer from './reducers/inventoryReducer';
+import outletReducer from './reducers/outletReducer';
// Legacy reducer for existing functionality
const legacyReducer = (state = initialState, action) => {
@@ -82,7 +84,9 @@ const rootReducer = combineReducers({
categories: categoryReducer,
orders: orderReducer,
paymentMethods: paymentMethodReducer,
- organizations: organizationReducer
+ organizations: organizationReducer,
+ inventories: inventoryReducer,
+ outlets: outletReducer
});
export default rootReducer;
diff --git a/src/core/redux/reducers/authReducer.js b/src/core/redux/reducers/authReducer.js
index 71d8d05..20cf6da 100644
--- a/src/core/redux/reducers/authReducer.js
+++ b/src/core/redux/reducers/authReducer.js
@@ -18,17 +18,17 @@ const authSlice = createSlice({
},
loginSuccess: (state, action) => {
state.isAuthenticated = true;
- state.user = action.payload.user;
- state.token = action.payload.token;
+ state.user = action.payload.data.user;
+ state.token = action.payload.data.token;
state.loading = false;
state.error = null;
// Store token in localStorage
- localStorage.setItem('authToken', action.payload.token);
- localStorage.setItem('user', JSON.stringify(action.payload.user));
+ localStorage.setItem('authToken', action.payload.data.token);
+ localStorage.setItem('user', JSON.stringify(action.payload.data.user));
},
loginFailure: (state, action) => {
state.loading = false;
- state.error = action.payload;
+ state.error = action.payload.error;
state.isAuthenticated = false;
state.user = null;
state.token = null;
diff --git a/src/core/redux/reducers/inventoryReducer.js b/src/core/redux/reducers/inventoryReducer.js
new file mode 100644
index 0000000..f41ef42
--- /dev/null
+++ b/src/core/redux/reducers/inventoryReducer.js
@@ -0,0 +1,189 @@
+import { INVENTORY_ACTIONS } from '../actions/inventoryActions';
+
+const initialState = {
+ // Inventory list
+ inventories: [],
+ totalInventories: 0,
+ currentPage: 1,
+ totalPages: 1,
+ pageSize: 10,
+ hasPrevious: false,
+ hasNext: false,
+
+ // Current inventory (for edit/view)
+ currentInventory: null,
+
+ // Search results
+ searchResults: [],
+ searchQuery: '',
+
+ // Loading states
+ loading: false,
+ inventoryLoading: false,
+ searchLoading: false,
+
+ // Error states
+ error: null,
+ inventoryError: null,
+ searchError: null,
+
+ // Operation states
+ creating: false,
+ updating: false,
+ deleting: false,
+};
+
+const inventoryReducer = (state = initialState, action) => {
+ switch (action.type) {
+ // Fetch Inventories
+ case INVENTORY_ACTIONS.FETCH_INVENTORIES_REQUEST:
+ return {
+ ...state,
+ loading: true,
+ error: null,
+ };
+
+ case INVENTORY_ACTIONS.FETCH_INVENTORIES_SUCCESS: {
+ const { inventory, total_count, page, total_pages, limit } =
+ action.payload.data;
+
+ return {
+ ...state,
+ loading: false,
+ inventories: inventory,
+ totalInventories: total_count || inventory.length,
+ currentPage: page || 1,
+ totalPages: total_pages || 1,
+ pageSize: limit || 10,
+ hasPrevious: false,
+ hasNext: false,
+ error: null,
+ };
+ }
+
+ case INVENTORY_ACTIONS.FETCH_INVENTORIES_FAILURE:
+ return {
+ ...state,
+ loading: false,
+ error: action.payload,
+ };
+
+ // Fetch Single Inventory
+ case INVENTORY_ACTIONS.FETCH_INVENTORY_REQUEST:
+ return {
+ ...state,
+ inventoryLoading: true,
+ inventoryError: null,
+ };
+
+ case INVENTORY_ACTIONS.FETCH_INVENTORY_SUCCESS:
+ return {
+ ...state,
+ inventoryLoading: false,
+ currentInventory: action.payload.data,
+ inventoryError: null,
+ };
+
+ case INVENTORY_ACTIONS.FETCH_INVENTORY_FAILURE:
+ return {
+ ...state,
+ inventoryLoading: false,
+ inventoryError: action.payload,
+ };
+
+ // Create Inventory
+ case INVENTORY_ACTIONS.CREATE_INVENTORY_REQUEST:
+ return {
+ ...state,
+ creating: true,
+ error: null,
+ };
+
+ case INVENTORY_ACTIONS.CREATE_INVENTORY_SUCCESS:
+ return {
+ ...state,
+ creating: false,
+ inventories: [action.payload.data, ...state.inventories],
+ totalInventories: state.totalInventories + 1,
+ error: null,
+ };
+
+ case INVENTORY_ACTIONS.CREATE_INVENTORY_FAILURE:
+ return {
+ ...state,
+ creating: false,
+ error: action.payload,
+ };
+
+ // Update Inventory
+ case INVENTORY_ACTIONS.UPDATE_INVENTORY_REQUEST:
+ return {
+ ...state,
+ updating: true,
+ error: null,
+ };
+
+ case INVENTORY_ACTIONS.UPDATE_INVENTORY_SUCCESS:
+ return {
+ ...state,
+ updating: false,
+ inventories: state.inventories.map(inv =>
+ inv.id === action.payload.data.id ? action.payload.data : inv
+ ),
+ currentInventory: action.payload.data,
+ error: null,
+ };
+
+ case INVENTORY_ACTIONS.UPDATE_INVENTORY_FAILURE:
+ return {
+ ...state,
+ updating: false,
+ error: action.payload,
+ };
+
+ // Delete Inventory
+ case INVENTORY_ACTIONS.DELETE_INVENTORY_REQUEST:
+ return {
+ ...state,
+ deleting: true,
+ error: null,
+ };
+
+ case INVENTORY_ACTIONS.DELETE_INVENTORY_SUCCESS:
+ return {
+ ...state,
+ deleting: false,
+ inventories: state.inventories.filter(inv => inv.id !== action.payload),
+ totalInventories: state.totalInventories - 1,
+ error: null,
+ };
+
+ case INVENTORY_ACTIONS.DELETE_INVENTORY_FAILURE:
+ return {
+ ...state,
+ deleting: false,
+ error: action.payload,
+ };
+
+ // Clear states
+ case INVENTORY_ACTIONS.CLEAR_INVENTORY_ERROR:
+ return {
+ ...state,
+ error: null,
+ inventoryError: null,
+ searchError: null,
+ };
+
+ case INVENTORY_ACTIONS.CLEAR_CURRENT_INVENTORY:
+ return {
+ ...state,
+ currentInventory: null,
+ inventoryError: null,
+ };
+
+ default:
+ return state;
+ }
+};
+
+export default inventoryReducer;
diff --git a/src/core/redux/reducers/outletReducer.js b/src/core/redux/reducers/outletReducer.js
new file mode 100644
index 0000000..fec3365
--- /dev/null
+++ b/src/core/redux/reducers/outletReducer.js
@@ -0,0 +1,212 @@
+import { OUTLET_ACTIONS } from '../actions/outletActions';
+
+const initialState = {
+ // Outlets list
+ outlets: [],
+ totalOutlets: 0,
+ currentPage: 1,
+ totalPages: 1,
+ pageSize: 10,
+ hasPrevious: false,
+ hasNext: false,
+
+ // Current outlet (for edit/view)
+ currentOutlet: null,
+
+ // Search results
+ searchResults: [],
+ searchQuery: '',
+
+ // Loading states
+ loading: false,
+ outletLoading: false,
+ searchLoading: false,
+
+ // Error states
+ error: null,
+ outletError: null,
+ searchError: null,
+
+ // Operation states
+ creating: false,
+ updating: false,
+ deleting: false,
+};
+
+const outletReducer = (state = initialState, action) => {
+ switch (action.type) {
+ // Fetch Outlets
+ case OUTLET_ACTIONS.FETCH_OUTLETS_REQUEST:
+ return {
+ ...state,
+ loading: true,
+ error: null,
+ };
+
+ case OUTLET_ACTIONS.FETCH_OUTLETS_SUCCESS: {
+ const { outlets, total_count, page, total_pages, limit } = action.payload.data;
+
+ return {
+ ...state,
+ loading: false,
+ outlets: outlets,
+ totalOutlets: total_count || outlets.length,
+ currentPage: page || 1,
+ totalPages: total_pages || 1,
+ pageSize: limit || 10,
+ hasPrevious: false,
+ hasNext: false,
+ error: null,
+ };
+ }
+
+ case OUTLET_ACTIONS.FETCH_OUTLETS_FAILURE:
+ return {
+ ...state,
+ loading: false,
+ error: action.payload,
+ };
+
+ // Fetch Single Outlet
+ case OUTLET_ACTIONS.FETCH_OUTLET_REQUEST:
+ return {
+ ...state,
+ outletLoading: true,
+ outletError: null,
+ };
+
+ case OUTLET_ACTIONS.FETCH_OUTLET_SUCCESS:
+ return {
+ ...state,
+ outletLoading: false,
+ currentOutlet: action.payload.data,
+ outletError: null,
+ };
+
+ case OUTLET_ACTIONS.FETCH_OUTLET_FAILURE:
+ return {
+ ...state,
+ outletLoading: false,
+ outletError: action.payload,
+ };
+
+ // Create Outlet
+ case OUTLET_ACTIONS.CREATE_OUTLET_REQUEST:
+ return {
+ ...state,
+ creating: true,
+ error: null,
+ };
+
+ case OUTLET_ACTIONS.CREATE_OUTLET_SUCCESS:
+ return {
+ ...state,
+ creating: false,
+ outlets: [action.payload.data, ...state.outlets],
+ totalOutlets: state.totalOutlets + 1,
+ error: null,
+ };
+
+ case OUTLET_ACTIONS.CREATE_OUTLET_FAILURE:
+ return {
+ ...state,
+ creating: false,
+ error: action.payload,
+ };
+
+ // Update Outlet
+ case OUTLET_ACTIONS.UPDATE_OUTLET_REQUEST:
+ return {
+ ...state,
+ updating: true,
+ error: null,
+ };
+
+ case OUTLET_ACTIONS.UPDATE_OUTLET_SUCCESS:
+ return {
+ ...state,
+ updating: false,
+ outlets: state.outlets.map((outlet) =>
+ outlet.id === action.payload.data.id ? action.payload.data : outlet
+ ),
+ currentOutlet: action.payload.data,
+ error: null,
+ };
+
+ case OUTLET_ACTIONS.UPDATE_OUTLET_FAILURE:
+ return {
+ ...state,
+ updating: false,
+ error: action.payload,
+ };
+
+ // Delete Outlet
+ case OUTLET_ACTIONS.DELETE_OUTLET_REQUEST:
+ return {
+ ...state,
+ deleting: true,
+ error: null,
+ };
+
+ case OUTLET_ACTIONS.DELETE_OUTLET_SUCCESS:
+ return {
+ ...state,
+ deleting: false,
+ outlets: state.outlets.filter((outlet) => outlet.id !== action.payload),
+ totalOutlets: state.totalOutlets - 1,
+ error: null,
+ };
+
+ case OUTLET_ACTIONS.DELETE_OUTLET_FAILURE:
+ return {
+ ...state,
+ deleting: false,
+ error: action.payload,
+ };
+
+ // Search Outlets
+ case OUTLET_ACTIONS.SEARCH_OUTLETS_REQUEST:
+ return {
+ ...state,
+ searchLoading: true,
+ searchError: null,
+ };
+
+ case OUTLET_ACTIONS.SEARCH_OUTLETS_SUCCESS:
+ return {
+ ...state,
+ searchLoading: false,
+ searchResults: action.payload.data || action.payload,
+ searchQuery: action.payload.query || '',
+ searchError: null,
+ };
+
+ case OUTLET_ACTIONS.SEARCH_OUTLETS_FAILURE:
+ return {
+ ...state,
+ searchLoading: false,
+ searchError: action.payload,
+ };
+
+ // Clear States
+ case OUTLET_ACTIONS.CLEAR_OUTLET_ERROR:
+ return {
+ ...state,
+ error: null,
+ outletError: null,
+ searchError: null,
+ };
+
+ case OUTLET_ACTIONS.CLEAR_CURRENT_OUTLET:
+ return {
+ ...state,
+ currentOutlet: null,
+ outletError: null,
+ };
+
+ default:
+ return state;
+ }
+};
+
+export default outletReducer;
diff --git a/src/feature-module/inventory/addproduct.jsx b/src/feature-module/inventory/addproduct.jsx
index be9b0b9..65fb835 100644
--- a/src/feature-module/inventory/addproduct.jsx
+++ b/src/feature-module/inventory/addproduct.jsx
@@ -20,13 +20,12 @@ import { Link, useNavigate } from "react-router-dom";
import Select from "react-select";
import Swal from "sweetalert2";
import ImageWithBasePath from "../../core/img/imagewithbasebath";
-import AddBrand from "../../core/modals/addbrand";
import AddCategory from "../../core/modals/inventory/addcategory";
-import Addunits from "../../core/modals/inventory/addunits";
import { setToogleHeader } from "../../core/redux/action";
import { createProduct } from "../../core/redux/actions/productActions";
import { all_routes } from "../../Router/all_routes";
import { categoriesApi } from "../../services/categoriesApi";
+import { filesApi } from "../../services/filesApi";
const AddProduct = () => {
const route = all_routes;
@@ -48,14 +47,19 @@ const AddProduct = () => {
const [formData, setFormData] = useState({
name: "",
sku: "",
+ barcode: "",
description: "",
price: 0,
cost: 0,
category_id: "",
+ printer_type: "",
+ image_url: "",
});
+ const [tempImage, setTempImage] = useState(null);
+ const [uploading, setUploading] = useState(false);
const [variants, setVariants] = useState([
- { name: "", price_modifier: 0, cost: 0 },
+ { name: "", price_modifier: '', cost: '' },
]);
const handleInputChange = (e) => {
@@ -65,6 +69,38 @@ const AddProduct = () => {
});
};
+ const handleFileChange = async (e) => {
+ setTempImage(e.target.files[0]);
+ };
+
+ useEffect(() => {
+ const loadImage = async () => {
+ setUploading(true);
+
+ try {
+ const uploads = new FormData();
+
+ uploads.append("file", tempImage);
+ uploads.append("file_type", "image");
+ uploads.append("description", "Product image");
+
+ const response = await filesApi.uploadFile(uploads);
+
+ setFormData({
+ ...formData,
+ image_url: response?.data?.file_url,
+ });
+
+ setUploading(false);
+ } catch (error) {
+ console.error("Error fetching image:", error);
+ setUploading(false);
+ }
+ };
+
+ loadImage();
+ }, [tempImage]);
+
useEffect(() => {
const loadCategories = async () => {
try {
@@ -90,32 +126,11 @@ const AddProduct = () => {
{ value: "rasmussen", label: "Rasmussen" },
{ value: "fredJohn", label: "Fred John" },
];
- const warehouse = [
- { value: "choose", label: "Choose" },
- { value: "legendary", label: "Legendary" },
+ const printerTypes = [
+ { value: "Kitchen", label: "Kitchen" },
{ value: "determined", label: "Determined" },
{ value: "sincere", label: "Sincere" },
];
- const subcategory = [
- { value: "choose", label: "Choose" },
- { value: "lenovo", label: "Lenovo" },
- { value: "electronics", label: "Electronics" },
- ];
- const brand = [
- { value: "choose", label: "Choose" },
- { value: "nike", label: "Nike" },
- { value: "bolt", label: "Bolt" },
- ];
- const unit = [
- { value: "choose", label: "Choose" },
- { value: "kg", label: "Kg" },
- { value: "pc", label: "Pc" },
- ];
- const sellingtype = [
- { value: "choose", label: "Choose" },
- { value: "transactionalSelling", label: "Transactional selling" },
- { value: "solutionSelling", label: "Solution selling" },
- ];
const barcodesymbol = [
{ value: "choose", label: "Choose" },
{ value: "code34", label: "Code34" },
@@ -136,15 +151,9 @@ const AddProduct = () => {
{ value: "percentage", label: "Percentage" },
{ value: "cash", label: "Cash" },
];
- const [isImageVisible, setIsImageVisible] = useState(true);
-
- const handleRemoveProduct = () => {
- setIsImageVisible(false);
- };
- const [isImageVisible1, setIsImageVisible1] = useState(true);
const handleRemoveProduct1 = () => {
- setIsImageVisible1(false);
+ setFormData({ ...formData, image_url: "" });
};
// Handle form submission
@@ -229,11 +238,17 @@ const AddProduct = () => {
Swal.fire({
icon: "error",
title: "Error!",
- text: error?.response?.data?.errors[0].cause || "Failed to create product. Please try again.",
+ text:
+ error?.response?.data?.errors[0].cause ||
+ "Failed to create product. Please try again.",
});
}
};
+ // const handleUploadImage = () => {
+
+ // }
+
// Handle select changes
const handleSelectChange = (field, selectedOption) => {
setFormData({
@@ -350,29 +365,6 @@ const AddProduct = () => {
data-bs-parent="#accordionExample"
>
-
-
@@ -386,12 +378,58 @@ const AddProduct = () => {
/>
+
+
+
+
+
+
+
+
+
+
+
+
@@ -429,164 +467,38 @@ const AddProduct = () => {
-
+
+
+
+
+
Add New
+
+
-
-
-
-
-
-
-
-
-
Add New
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Add New
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Generate
-
-
-
- {/*
-
-
-
-
- Generate Code
-
-
-
*/}
-
{/* Editor */}
@@ -935,17 +847,36 @@ const AddProduct = () => {
-
+
-
-
Add Images
+ {uploading ? (
+ <>
+
+
Uploading...
+ >
+ ) : (
+ <>
+
+
+ {tempImage ? "Edit Image" : "Add Image"}
+
+ >
+ )}
- {isImageVisible1 && (
+ {formData.image_url && (
@@ -956,20 +887,6 @@ const AddProduct = () => {
)}
- {isImageVisible && (
-
-
-
-
-
-
- )}
@@ -1131,9 +1048,7 @@ const AddProduct = () => {
{/* /add */}
-