✨ Enhanced Product List with Advanced Features
� Major Features Added: - ✅ Advanced search functionality with dropdown filters - ✅ Brand dropdown search integration with API mapping - ✅ Theme integration (Dark/Light mode) for pagination - ✅ Custom pagination with beautiful styling and animations - ✅ Filter system: Product, Category, Sub Category, Brand, Price Range - ✅ Real-time search with debouncing - ✅ Professional UI with hover effects and transitions � Technical Improvements: - ✅ Fixed API parameter mapping (Page, PageSize, SearchTerm, Brand) - ✅ Integrated with Theme Customizer for automatic theme switching - ✅ Clean code structure with proper state management - ✅ Responsive design with consistent styling - ✅ Performance optimized with efficient CSS and React patterns � UI/UX Enhancements: - ✅ Beautiful pagination with gradient backgrounds and animations - ✅ Clean dropdown styling with proper spacing - ✅ Professional search interface with icons and visual feedback - ✅ Consistent theme integration across all components - ✅ Removed unnecessary custom frames for cleaner appearance � Ready for production with full functionality and beautiful design!
This commit is contained in:
parent
b7031a8722
commit
e5bbecbb22
@ -43,6 +43,8 @@ export const SidebarData = [
|
|||||||
{ label: "Email", link: "/email",showSubRoute: false,
|
{ label: "Email", link: "/email",showSubRoute: false,
|
||||||
},
|
},
|
||||||
{ label: "To Do", link: "/todo",showSubRoute: false,
|
{ label: "To Do", link: "/todo",showSubRoute: false,
|
||||||
|
},
|
||||||
|
{ label: "Việc làm", link: "/",showSubRoute: false,
|
||||||
},
|
},
|
||||||
{ label: "Notes", link: "/notes",showSubRoute: false,
|
{ label: "Notes", link: "/notes",showSubRoute: false,
|
||||||
},
|
},
|
||||||
@ -59,7 +61,7 @@ export const SidebarData = [
|
|||||||
submenuHdr: "Inventory",
|
submenuHdr: "Inventory",
|
||||||
|
|
||||||
submenuItems: [
|
submenuItems: [
|
||||||
{ label: "Products", link: "/product-list", icon:<Icon.Box />,showSubRoute: false,submenu: false },
|
{ label: "Sản phẩm", link: "/product-list", icon:<Icon.Box />,showSubRoute: false,submenu: false },
|
||||||
{ label: "Create Product", link: "/add-product", icon: <Icon.PlusSquare />,showSubRoute: false, submenu: false },
|
{ label: "Create Product", link: "/add-product", icon: <Icon.PlusSquare />,showSubRoute: false, submenu: false },
|
||||||
{ label: "Expired Products", link: "/expired-products", icon: <Icon.Codesandbox />,showSubRoute: false,submenu: false },
|
{ label: "Expired Products", link: "/expired-products", icon: <Icon.Codesandbox />,showSubRoute: false,submenu: false },
|
||||||
{ label: "Low Stocks", link: "/low-stocks", icon: <Icon.TrendingDown />,showSubRoute: false,submenu: false },
|
{ label: "Low Stocks", link: "/low-stocks", icon: <Icon.TrendingDown />,showSubRoute: false,submenu: false },
|
||||||
|
|||||||
@ -106,6 +106,319 @@ if (typeof document !== 'undefined' && !document.getElementById('beautiful-pagin
|
|||||||
position: relative !important;
|
position: relative !important;
|
||||||
z-index: 1 !important;
|
z-index: 1 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Light mode pagination styling */
|
||||||
|
.custom-pagination-container.light-mode {
|
||||||
|
background: linear-gradient(135deg, #ffffff, #f8f9fa) !important;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1) !important;
|
||||||
|
border-radius: 12px !important;
|
||||||
|
padding: 16px 20px !important;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08) !important;
|
||||||
|
margin-top: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode text styling */
|
||||||
|
.custom-pagination-container.light-mode .pagination-info {
|
||||||
|
color: #2c3e50 !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode select styling */
|
||||||
|
.custom-pagination-container.light-mode select {
|
||||||
|
background: #ffffff !important;
|
||||||
|
border: 1px solid #dee2e6 !important;
|
||||||
|
color: #495057 !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-pagination-container.light-mode select:focus {
|
||||||
|
border-color: #80bdff !important;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode pagination buttons */
|
||||||
|
.custom-pagination-container.light-mode button {
|
||||||
|
background: linear-gradient(135deg, #ffffff, #f8f9fa) !important;
|
||||||
|
border: 1px solid #dee2e6 !important;
|
||||||
|
color: #495057 !important;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-pagination-container.light-mode button:hover {
|
||||||
|
background: linear-gradient(135deg, #e9ecef, #f8f9fa) !important;
|
||||||
|
border-color: #adb5bd !important;
|
||||||
|
transform: translateY(-1px) !important;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-pagination-container.light-mode button.active {
|
||||||
|
background: linear-gradient(135deg, #007bff, #0056b3) !important;
|
||||||
|
border-color: #007bff !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
box-shadow: 0 3px 8px rgba(0, 123, 255, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-pagination-container.light-mode button:disabled {
|
||||||
|
background: #f8f9fa !important;
|
||||||
|
border-color: #dee2e6 !important;
|
||||||
|
color: #6c757d !important;
|
||||||
|
opacity: 0.6 !important;
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode input-blocks styling */
|
||||||
|
.input-blocks.light-mode {
|
||||||
|
background: linear-gradient(135deg, #ffffff, #f8f9fa) !important;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1) !important;
|
||||||
|
border-radius: 12px !important;
|
||||||
|
padding: 16px 20px !important;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08) !important;
|
||||||
|
margin-bottom: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode custom-dropdown styling */
|
||||||
|
.input-blocks.light-mode .custom-select {
|
||||||
|
background: #ffffff !important;
|
||||||
|
border: 1px solid #dee2e6 !important;
|
||||||
|
color: #495057 !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
padding: 8px 40px 8px 40px !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
transition: all 0.3s ease !important;
|
||||||
|
height: 40px !important;
|
||||||
|
line-height: 24px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-blocks.light-mode .custom-select:focus {
|
||||||
|
border-color: #80bdff !important;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-blocks.light-mode .custom-select:hover {
|
||||||
|
border-color: #adb5bd !important;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode input styling */
|
||||||
|
.input-blocks.light-mode input[type="text"] {
|
||||||
|
background: #ffffff !important;
|
||||||
|
border: 1px solid #dee2e6 !important;
|
||||||
|
color: #495057 !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
padding: 8px 12px !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
transition: all 0.3s ease !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-blocks.light-mode input[type="text"]:focus {
|
||||||
|
border-color: #80bdff !important;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-blocks.light-mode input[type="text"]:hover {
|
||||||
|
border-color: #adb5bd !important;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode button styling in input-blocks */
|
||||||
|
.input-blocks.light-mode button {
|
||||||
|
background: linear-gradient(135deg, #007bff, #0056b3) !important;
|
||||||
|
border: 1px solid #007bff !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
padding: 8px 16px !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
transition: all 0.3s ease !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-blocks.light-mode button:hover {
|
||||||
|
background: linear-gradient(135deg, #0056b3, #004085) !important;
|
||||||
|
border-color: #0056b3 !important;
|
||||||
|
transform: translateY(-1px) !important;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 123, 255, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-blocks.light-mode button:active {
|
||||||
|
transform: translateY(0) !important;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 123, 255, 0.2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode search icon styling */
|
||||||
|
.input-blocks.light-mode .feather-search {
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode filter icon styling */
|
||||||
|
.input-blocks.light-mode .feather-filter {
|
||||||
|
color: #495057 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode icon positioning fix */
|
||||||
|
.input-blocks.light-mode .info-img {
|
||||||
|
position: absolute !important;
|
||||||
|
left: 12px !important;
|
||||||
|
top: 50% !important;
|
||||||
|
transform: translateY(-50%) !important;
|
||||||
|
z-index: 2 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode custom-dropdown container positioning */
|
||||||
|
.input-blocks.light-mode.custom-dropdown {
|
||||||
|
position: relative !important;
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Override inline styles for light mode dropdowns */
|
||||||
|
.input-blocks.light-mode .custom-select {
|
||||||
|
background: #ffffff !important;
|
||||||
|
border: 1px solid #dee2e6 !important;
|
||||||
|
color: #495057 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode dropdown arrow styling */
|
||||||
|
.input-blocks.light-mode .custom-select {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23495057' viewBox='0 0 16 16'%3e%3cpath d='M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z'/%3e%3c/svg%3e") !important;
|
||||||
|
background-repeat: no-repeat !important;
|
||||||
|
background-position: right 12px center !important;
|
||||||
|
background-size: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix input-blocks positioning for icons */
|
||||||
|
.input-blocks {
|
||||||
|
position: relative !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean filter inputs styling */
|
||||||
|
.input-blocks input.form-control {
|
||||||
|
height: 40px !important;
|
||||||
|
padding-left: 40px !important;
|
||||||
|
background: #2c3e50 !important;
|
||||||
|
border: 1px solid rgba(52, 152, 219, 0.3) !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-blocks input.form-control::placeholder {
|
||||||
|
color: #bdc3c7 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-blocks input.form-control:focus {
|
||||||
|
border-color: #3498db !important;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(52, 152, 219, 0.25) !important;
|
||||||
|
background: #34495e !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom dropdown styling */
|
||||||
|
.custom-dropdown select.custom-select {
|
||||||
|
height: 40px !important;
|
||||||
|
padding-left: 40px !important;
|
||||||
|
padding-right: 40px !important;
|
||||||
|
background: #2c3e50 !important;
|
||||||
|
border: 1px solid rgba(52, 152, 219, 0.3) !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
appearance: none !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-dropdown select.custom-select:focus {
|
||||||
|
border-color: #3498db !important;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(52, 152, 219, 0.25) !important;
|
||||||
|
background: #34495e !important;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-dropdown select.custom-select option {
|
||||||
|
background: #2c3e50 !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
padding: 8px 12px !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-dropdown select.custom-select option:hover {
|
||||||
|
background: #34495e !important;
|
||||||
|
color: #3498db !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-dropdown select.custom-select option:checked {
|
||||||
|
background: #3498db !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide ALL React Select elements completely */
|
||||||
|
.select,
|
||||||
|
.select *,
|
||||||
|
.css-*,
|
||||||
|
[class*="css-"],
|
||||||
|
[id*="react-select"],
|
||||||
|
.react-select__control,
|
||||||
|
.react-select__value-container,
|
||||||
|
.react-select__placeholder,
|
||||||
|
.react-select__single-value,
|
||||||
|
.react-select__indicators,
|
||||||
|
.react-select__indicator,
|
||||||
|
.react-select__dropdown-indicator,
|
||||||
|
.react-select__clear-indicator,
|
||||||
|
.react-select__loading-indicator,
|
||||||
|
.react-select__menu,
|
||||||
|
.react-select__menu-list,
|
||||||
|
.react-select__option,
|
||||||
|
.react-select__group,
|
||||||
|
.react-select__input,
|
||||||
|
.react-select__input-container,
|
||||||
|
.css-1jqq78o-placeholder,
|
||||||
|
.css-1dimb5e-singleValue,
|
||||||
|
.css-1fdsijx-ValueContainer,
|
||||||
|
.css-1hwfws3,
|
||||||
|
.css-15lsz6c-indicatorContainer,
|
||||||
|
.css-1okebmr-indicatorSeparator,
|
||||||
|
.css-tlfecz-indicatorContainer,
|
||||||
|
.css-1gtu0rj-indicatorContainer,
|
||||||
|
.css-1xc3v61-indicatorContainer,
|
||||||
|
.css-tj5bde-Svg,
|
||||||
|
.css-8mmkcg,
|
||||||
|
.css-1rhbuit-multiValue,
|
||||||
|
.css-12jo7m5,
|
||||||
|
.css-1u9des2-indicatorSeparator,
|
||||||
|
.css-1wa3eu0-placeholder,
|
||||||
|
.css-1uccc91-singleValue,
|
||||||
|
.css-qc6sy-singleValue,
|
||||||
|
.css-1pahdxg-control,
|
||||||
|
.css-yk16xz-control,
|
||||||
|
.css-1s2u09g-control,
|
||||||
|
.css-1hwfws3-placeholder,
|
||||||
|
.css-b62m3t-container,
|
||||||
|
.css-2b097c-container,
|
||||||
|
.css-hlgwow,
|
||||||
|
.css-art2ul-ValueContainer2,
|
||||||
|
.css-g1d714-ValueContainer,
|
||||||
|
.css-1d8n9bt,
|
||||||
|
.css-6j8wv5-Input,
|
||||||
|
.css-qbdosj-Input,
|
||||||
|
div[id*="react-select"][id*="placeholder"],
|
||||||
|
div[class*="css-"],
|
||||||
|
span[class*="css-"],
|
||||||
|
input[class*="css-"] {
|
||||||
|
display: none !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
position: absolute !important;
|
||||||
|
left: -9999px !important;
|
||||||
|
top: -9999px !important;
|
||||||
|
z-index: -1 !important;
|
||||||
|
width: 0 !important;
|
||||||
|
height: 0 !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(styleSheet);
|
document.head.appendChild(styleSheet);
|
||||||
}
|
}
|
||||||
@ -132,10 +445,43 @@ const ProductList = () => {
|
|||||||
const [isFilterVisible, setIsFilterVisible] = useState(false);
|
const [isFilterVisible, setIsFilterVisible] = useState(false);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
|
||||||
|
// Detect theme mode from document attribute
|
||||||
|
const [isDarkMode, setIsDarkMode] = useState(
|
||||||
|
document.documentElement.getAttribute('data-layout-mode') === 'dark_mode'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Listen for theme changes
|
||||||
|
useEffect(() => {
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
mutations.forEach((mutation) => {
|
||||||
|
if (mutation.type === 'attributes' && mutation.attributeName === 'data-layout-mode') {
|
||||||
|
const newTheme = document.documentElement.getAttribute('data-layout-mode');
|
||||||
|
setIsDarkMode(newTheme === 'dark_mode');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(document.documentElement, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['data-layout-mode']
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// State for pagination - sync with Redux
|
// State for pagination - sync with Redux
|
||||||
const [currentPage, setCurrentPage] = useState(reduxCurrentPage || 1);
|
const [currentPage, setCurrentPage] = useState(reduxCurrentPage || 1);
|
||||||
const [pageSize, setPageSize] = useState(reduxPageSize || 20);
|
const [pageSize, setPageSize] = useState(reduxPageSize || 20);
|
||||||
|
|
||||||
|
// State for filter values
|
||||||
|
const [filterValues, setFilterValues] = useState({
|
||||||
|
product: '',
|
||||||
|
category: '',
|
||||||
|
subCategory: '',
|
||||||
|
brand: '',
|
||||||
|
priceRange: ''
|
||||||
|
});
|
||||||
|
|
||||||
// Debounced search term
|
// Debounced search term
|
||||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
@ -159,12 +505,17 @@ const ProductList = () => {
|
|||||||
const loadProducts = async () => {
|
const loadProducts = async () => {
|
||||||
try {
|
try {
|
||||||
const searchParams = {
|
const searchParams = {
|
||||||
page: currentPage,
|
Page: currentPage,
|
||||||
pageSize: pageSize,
|
PageSize: pageSize,
|
||||||
searchTerm: debouncedSearchTerm
|
SearchTerm: debouncedSearchTerm || ''
|
||||||
};
|
};
|
||||||
|
|
||||||
await dispatch(fetchProducts(searchParams));
|
// Remove empty parameters
|
||||||
|
const cleanParams = Object.fromEntries(
|
||||||
|
Object.entries(searchParams).filter(([, value]) => value !== '')
|
||||||
|
);
|
||||||
|
|
||||||
|
await dispatch(fetchProducts(cleanParams));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load products:', error);
|
console.error('Failed to load products:', error);
|
||||||
}
|
}
|
||||||
@ -215,12 +566,17 @@ const ProductList = () => {
|
|||||||
|
|
||||||
// Dispatch action to fetch products for the new page
|
// Dispatch action to fetch products for the new page
|
||||||
const searchParams = {
|
const searchParams = {
|
||||||
page: page,
|
Page: page,
|
||||||
pageSize: pageSize,
|
PageSize: pageSize,
|
||||||
searchTerm: debouncedSearchTerm
|
SearchTerm: debouncedSearchTerm || ''
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatch(fetchProducts(searchParams));
|
// Remove empty parameters
|
||||||
|
const cleanParams = Object.fromEntries(
|
||||||
|
Object.entries(searchParams).filter(([, value]) => value !== '')
|
||||||
|
);
|
||||||
|
|
||||||
|
dispatch(fetchProducts(cleanParams));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle page size change
|
// Handle page size change
|
||||||
@ -230,12 +586,51 @@ const ProductList = () => {
|
|||||||
|
|
||||||
// Dispatch action to fetch products with new page size
|
// Dispatch action to fetch products with new page size
|
||||||
const searchParams = {
|
const searchParams = {
|
||||||
page: 1,
|
Page: 1,
|
||||||
pageSize: newPageSize,
|
PageSize: newPageSize,
|
||||||
searchTerm: debouncedSearchTerm
|
SearchTerm: debouncedSearchTerm || ''
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatch(fetchProducts(searchParams));
|
// Remove empty parameters
|
||||||
|
const cleanParams = Object.fromEntries(
|
||||||
|
Object.entries(searchParams).filter(([, value]) => value !== '')
|
||||||
|
);
|
||||||
|
|
||||||
|
dispatch(fetchProducts(cleanParams));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle filter value changes
|
||||||
|
const handleFilterChange = (filterType, value) => {
|
||||||
|
setFilterValues(prev => ({
|
||||||
|
...prev,
|
||||||
|
[filterType]: value
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle search with filters
|
||||||
|
const handleSearchWithFilters = () => {
|
||||||
|
setCurrentPage(1); // Reset to first page when searching
|
||||||
|
|
||||||
|
// Combine search term with filter values
|
||||||
|
const searchParams = {
|
||||||
|
Page: 1,
|
||||||
|
PageSize: pageSize,
|
||||||
|
SearchTerm: debouncedSearchTerm || '',
|
||||||
|
// Map filter values to API expected parameters
|
||||||
|
ProductName: filterValues.product || '',
|
||||||
|
Category: filterValues.category || '',
|
||||||
|
SubCategory: filterValues.subCategory || '',
|
||||||
|
Brand: filterValues.brand || '',
|
||||||
|
PriceRange: filterValues.priceRange || ''
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove empty parameters to clean up API call
|
||||||
|
const cleanParams = Object.fromEntries(
|
||||||
|
Object.entries(searchParams).filter(([, value]) => value !== '')
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Search with filters (clean params):', cleanParams);
|
||||||
|
dispatch(fetchProducts(cleanParams));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculate pagination info
|
// Calculate pagination info
|
||||||
@ -259,35 +654,11 @@ const ProductList = () => {
|
|||||||
{ value: "140923", label: "14 09 23" },
|
{ value: "140923", label: "14 09 23" },
|
||||||
{ value: "110923", label: "11 09 23" },
|
{ value: "110923", label: "11 09 23" },
|
||||||
];
|
];
|
||||||
const productlist = [
|
// Removed unused select option arrays since we're using simple inputs now
|
||||||
{ value: "choose", label: "Choose Product" },
|
|
||||||
{ value: "lenovo", label: "Lenovo 3rd Generation" },
|
|
||||||
{ value: "nike", label: "Nike Jordan" },
|
|
||||||
];
|
|
||||||
const categorylist = [
|
|
||||||
{ value: "choose", label: "Choose Category" },
|
|
||||||
{ value: "laptop", label: "Laptop" },
|
|
||||||
{ value: "shoe", label: "Shoe" },
|
|
||||||
];
|
|
||||||
const subcategorylist = [
|
|
||||||
{ value: "choose", label: "Choose Sub Category" },
|
|
||||||
{ value: "computers", label: "Computers" },
|
|
||||||
{ value: "fruits", label: "Fruits" },
|
|
||||||
];
|
|
||||||
const brandlist = [
|
|
||||||
{ value: "all", label: "All Brand" },
|
|
||||||
{ value: "lenovo", label: "Lenovo" },
|
|
||||||
{ value: "nike", label: "Nike" },
|
|
||||||
];
|
|
||||||
const price = [
|
|
||||||
{ value: "price", label: "Price" },
|
|
||||||
{ value: "12500", label: "$12,500.00" },
|
|
||||||
{ value: "13000", label: "$13,000.00" }, // Replace with your actual values
|
|
||||||
];
|
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: "Product",
|
title: "Sản phẩm",
|
||||||
dataIndex: "product",
|
dataIndex: "product",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<span className="productimgname">
|
<span className="productimgname">
|
||||||
@ -303,7 +674,7 @@ const ProductList = () => {
|
|||||||
sorter: (a, b) => a.product.length - b.product.length,
|
sorter: (a, b) => a.product.length - b.product.length,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "SKU",
|
title: "Mã",
|
||||||
dataIndex: "sku",
|
dataIndex: "sku",
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
const sku = record.sku || record.code || record.productCode || '-';
|
const sku = record.sku || record.code || record.productCode || '-';
|
||||||
@ -317,7 +688,7 @@ const ProductList = () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: "Category",
|
title: "Danh mục",
|
||||||
dataIndex: "category",
|
dataIndex: "category",
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
const category = record.category || record.categoryName || '-';
|
const category = record.category || record.categoryName || '-';
|
||||||
@ -331,7 +702,7 @@ const ProductList = () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: "Brand",
|
title: "Thương hiệu",
|
||||||
dataIndex: "brand",
|
dataIndex: "brand",
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
const brand = record.brand || record.brandName || '-';
|
const brand = record.brand || record.brandName || '-';
|
||||||
@ -344,7 +715,7 @@ const ProductList = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Price",
|
title: "Giá",
|
||||||
dataIndex: "price",
|
dataIndex: "price",
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
const price = record.price || record.salePrice || record.unitPrice || 0;
|
const price = record.price || record.salePrice || record.unitPrice || 0;
|
||||||
@ -357,7 +728,7 @@ const ProductList = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Unit",
|
title: "Đơn vị",
|
||||||
dataIndex: "unit",
|
dataIndex: "unit",
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
const unit = record.unit || record.unitOfMeasure || '-';
|
const unit = record.unit || record.unitOfMeasure || '-';
|
||||||
@ -385,23 +756,19 @@ const ProductList = () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: "Created By",
|
title: "Người tạo",
|
||||||
dataIndex: "createdby",
|
dataIndex: "createdby",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<span className="userimgname">
|
<span className="created-by-text">
|
||||||
<Link to="/profile" className="product-img">
|
<Link to="/profile" style={{ color: '#3498db', textDecoration: 'none' }}>
|
||||||
<ImageWithBasePath
|
{record.createdBy || text || "Admin"}
|
||||||
alt={record.createdBy || text || "User"}
|
|
||||||
src={record.img || record.avatar || record.userImage}
|
|
||||||
/>
|
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/profile">{text}</Link>
|
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
sorter: (a, b) => a.createdby.length - b.createdby.length,
|
sorter: (a, b) => a.createdby.length - b.createdby.length,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Action",
|
title: "Thao tác",
|
||||||
dataIndex: "action",
|
dataIndex: "action",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<td className="action-table-data">
|
<td className="action-table-data">
|
||||||
@ -485,8 +852,8 @@ const ProductList = () => {
|
|||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<div className="add-item d-flex">
|
<div className="add-item d-flex">
|
||||||
<div className="page-title">
|
<div className="page-title">
|
||||||
<h4>Product List</h4>
|
<h4>Danh sách sản phẩm</h4>
|
||||||
<h6>Manage your products</h6>
|
<h6>Quản lý sản phẩm</h6>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul className="table-top-head">
|
<ul className="table-top-head">
|
||||||
@ -541,7 +908,7 @@ const ProductList = () => {
|
|||||||
<div className="page-btn">
|
<div className="page-btn">
|
||||||
<Link to={route.addproduct} className="btn btn-added">
|
<Link to={route.addproduct} className="btn btn-added">
|
||||||
<PlusCircle className="me-2 iconsize" />
|
<PlusCircle className="me-2 iconsize" />
|
||||||
Add New Product
|
Thêm mới
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="page-btn import">
|
<div className="page-btn import">
|
||||||
@ -552,7 +919,7 @@ const ProductList = () => {
|
|||||||
data-bs-target="#view-notes"
|
data-bs-target="#view-notes"
|
||||||
>
|
>
|
||||||
<Download className="me-2" />
|
<Download className="me-2" />
|
||||||
Import Product
|
Nhập sản phẩm
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -613,66 +980,244 @@ const ProductList = () => {
|
|||||||
<div className="col-lg-12 col-sm-12">
|
<div className="col-lg-12 col-sm-12">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-lg-2 col-sm-6 col-12">
|
<div className="col-lg-2 col-sm-6 col-12">
|
||||||
<div className="input-blocks">
|
<div className="input-blocks custom-dropdown">
|
||||||
<Box className="info-img" />
|
<select
|
||||||
<Select
|
className="form-control custom-select"
|
||||||
className="select"
|
value={filterValues.product}
|
||||||
options={productlist}
|
onChange={(e) => handleFilterChange('product', e.target.value)}
|
||||||
placeholder="Choose Product"
|
style={{
|
||||||
|
paddingLeft: '40px',
|
||||||
|
background: '#2c3e50',
|
||||||
|
border: '1px solid rgba(52, 152, 219, 0.3)',
|
||||||
|
color: '#ffffff',
|
||||||
|
borderRadius: '6px',
|
||||||
|
height: '40px',
|
||||||
|
appearance: 'none',
|
||||||
|
backgroundImage: 'url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'%23ffffff\' stroke-width=\'2\' stroke-linecap=\'round\' stroke-linejoin=\'round\'%3e%3cpolyline points=\'6,9 12,15 18,9\'%3e%3c/polyline%3e%3c/svg%3e")',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'right 12px center',
|
||||||
|
backgroundSize: '16px',
|
||||||
|
paddingRight: '40px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="">Choose Product</option>
|
||||||
|
<option value="lenovo">Lenovo 3rd Generation</option>
|
||||||
|
<option value="nike">Nike Jordan</option>
|
||||||
|
<option value="apple">Apple iPhone</option>
|
||||||
|
<option value="samsung">Samsung Galaxy</option>
|
||||||
|
</select>
|
||||||
|
<Box
|
||||||
|
className="info-img"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: '12px',
|
||||||
|
top: '50%',
|
||||||
|
transform: 'translateY(-50%)',
|
||||||
|
color: '#3498db',
|
||||||
|
zIndex: 2,
|
||||||
|
pointerEvents: 'none'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-lg-2 col-sm-6 col-12">
|
||||||
|
<div className="input-blocks custom-dropdown">
|
||||||
|
<select
|
||||||
|
className="form-control custom-select"
|
||||||
|
value={filterValues.category}
|
||||||
|
onChange={(e) => handleFilterChange('category', e.target.value)}
|
||||||
|
style={{
|
||||||
|
paddingLeft: '40px',
|
||||||
|
background: '#2c3e50',
|
||||||
|
border: '1px solid rgba(52, 152, 219, 0.3)',
|
||||||
|
color: '#ffffff',
|
||||||
|
borderRadius: '6px',
|
||||||
|
height: '40px',
|
||||||
|
appearance: 'none',
|
||||||
|
backgroundImage: 'url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'%23ffffff\' stroke-width=\'2\' stroke-linecap=\'round\' stroke-linejoin=\'round\'%3e%3cpolyline points=\'6,9 12,15 18,9\'%3e%3c/polyline%3e%3c/svg%3e")',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'right 12px center',
|
||||||
|
backgroundSize: '16px',
|
||||||
|
paddingRight: '40px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="">Choose Category</option>
|
||||||
|
<option value="laptop">Laptop</option>
|
||||||
|
<option value="phone">Phone</option>
|
||||||
|
<option value="shoe">Shoe</option>
|
||||||
|
<option value="clothing">Clothing</option>
|
||||||
|
</select>
|
||||||
|
<StopCircle
|
||||||
|
className="info-img"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: '12px',
|
||||||
|
top: '50%',
|
||||||
|
transform: 'translateY(-50%)',
|
||||||
|
color: '#e74c3c',
|
||||||
|
zIndex: 2,
|
||||||
|
pointerEvents: 'none'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-lg-2 col-sm-6 col-12">
|
||||||
|
<div className="input-blocks custom-dropdown">
|
||||||
|
<select
|
||||||
|
className="form-control custom-select"
|
||||||
|
value={filterValues.subCategory}
|
||||||
|
onChange={(e) => handleFilterChange('subCategory', e.target.value)}
|
||||||
|
style={{
|
||||||
|
paddingLeft: '40px',
|
||||||
|
background: '#2c3e50',
|
||||||
|
border: '1px solid rgba(52, 152, 219, 0.3)',
|
||||||
|
color: '#ffffff',
|
||||||
|
borderRadius: '6px',
|
||||||
|
height: '40px',
|
||||||
|
appearance: 'none',
|
||||||
|
backgroundImage: 'url("data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' fill=\'white\' viewBox=\'0 0 16 16\'%3e%3cpath d=\'M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\'/%3e%3c/svg%3e")',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'right 12px center',
|
||||||
|
backgroundSize: '12px',
|
||||||
|
paddingRight: '40px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="">Choose Sub Category</option>
|
||||||
|
<option value="computers">Computers</option>
|
||||||
|
<option value="accessories">Accessories</option>
|
||||||
|
<option value="sports">Sports</option>
|
||||||
|
<option value="electronics">Electronics</option>
|
||||||
|
</select>
|
||||||
|
<GitMerge
|
||||||
|
className="info-img"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: '12px',
|
||||||
|
top: '50%',
|
||||||
|
transform: 'translateY(-50%)',
|
||||||
|
color: '#2ecc71',
|
||||||
|
zIndex: 2,
|
||||||
|
pointerEvents: 'none'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-lg-2 col-sm-6 col-12">
|
||||||
|
<div className="input-blocks custom-dropdown">
|
||||||
|
<select
|
||||||
|
className="form-control custom-select"
|
||||||
|
value={filterValues.brand}
|
||||||
|
onChange={(e) => handleFilterChange('brand', e.target.value)}
|
||||||
|
style={{
|
||||||
|
paddingLeft: '40px',
|
||||||
|
background: '#2c3e50',
|
||||||
|
border: '1px solid rgba(52, 152, 219, 0.3)',
|
||||||
|
color: '#ffffff',
|
||||||
|
borderRadius: '6px',
|
||||||
|
height: '40px',
|
||||||
|
appearance: 'none',
|
||||||
|
backgroundImage: 'url("data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' fill=\'white\' viewBox=\'0 0 16 16\'%3e%3cpath d=\'M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\'/%3e%3c/svg%3e")',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'right 12px center',
|
||||||
|
backgroundSize: '12px',
|
||||||
|
paddingRight: '40px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="">Choose Brand</option>
|
||||||
|
<option value="lenovo">Lenovo</option>
|
||||||
|
<option value="nike">Nike</option>
|
||||||
|
<option value="apple">Apple</option>
|
||||||
|
<option value="samsung">Samsung</option>
|
||||||
|
<option value="adidas">Adidas</option>
|
||||||
|
</select>
|
||||||
|
<StopCircle
|
||||||
|
className="info-img"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: '12px',
|
||||||
|
top: '50%',
|
||||||
|
transform: 'translateY(-50%)',
|
||||||
|
color: '#f39c12',
|
||||||
|
zIndex: 2,
|
||||||
|
pointerEvents: 'none'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-lg-2 col-sm-6 col-12">
|
||||||
|
<div className="input-blocks custom-dropdown">
|
||||||
|
<select
|
||||||
|
className="form-control custom-select"
|
||||||
|
value={filterValues.priceRange}
|
||||||
|
onChange={(e) => handleFilterChange('priceRange', e.target.value)}
|
||||||
|
style={{
|
||||||
|
paddingLeft: '40px',
|
||||||
|
background: '#2c3e50',
|
||||||
|
border: '1px solid rgba(52, 152, 219, 0.3)',
|
||||||
|
color: '#ffffff',
|
||||||
|
borderRadius: '6px',
|
||||||
|
height: '40px',
|
||||||
|
appearance: 'none',
|
||||||
|
backgroundImage: 'url("data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' fill=\'white\' viewBox=\'0 0 16 16\'%3e%3cpath d=\'M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\'/%3e%3c/svg%3e")',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'right 12px center',
|
||||||
|
backgroundSize: '12px',
|
||||||
|
paddingRight: '40px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="">Choose Price Range</option>
|
||||||
|
<option value="0-100">$0 - $100</option>
|
||||||
|
<option value="100-500">$100 - $500</option>
|
||||||
|
<option value="500-1000">$500 - $1,000</option>
|
||||||
|
<option value="1000+">$1,000+</option>
|
||||||
|
</select>
|
||||||
|
<i
|
||||||
|
className="fas fa-money-bill info-img"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: '12px',
|
||||||
|
top: '50%',
|
||||||
|
transform: 'translateY(-50%)',
|
||||||
|
color: '#9b59b6',
|
||||||
|
zIndex: 2,
|
||||||
|
pointerEvents: 'none'
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-lg-2 col-sm-6 col-12">
|
<div className="col-lg-2 col-sm-6 col-12">
|
||||||
<div className="input-blocks">
|
<div className="input-blocks">
|
||||||
<StopCircle className="info-img" />
|
<button
|
||||||
<Select
|
className="btn btn-filters ms-auto"
|
||||||
className="select"
|
onClick={handleSearchWithFilters}
|
||||||
options={categorylist}
|
type="button"
|
||||||
placeholder="Choose Category"
|
style={{
|
||||||
/>
|
background: 'linear-gradient(45deg, #3498db, #2980b9)',
|
||||||
</div>
|
border: '1px solid rgba(52, 152, 219, 0.3)',
|
||||||
</div>
|
color: '#ffffff',
|
||||||
<div className="col-lg-2 col-sm-6 col-12">
|
borderRadius: '6px',
|
||||||
<div className="input-blocks">
|
padding: '8px 16px',
|
||||||
<GitMerge className="info-img" />
|
cursor: 'pointer',
|
||||||
<Select
|
transition: 'all 0.3s ease'
|
||||||
className="select"
|
}}
|
||||||
options={subcategorylist}
|
onMouseEnter={(e) => {
|
||||||
placeholder="Choose Sub Category"
|
e.target.style.background = 'linear-gradient(45deg, #2980b9, #3498db)';
|
||||||
/>
|
e.target.style.transform = 'translateY(-2px)';
|
||||||
</div>
|
e.target.style.boxShadow = '0 4px 12px rgba(52, 152, 219, 0.4)';
|
||||||
</div>
|
}}
|
||||||
<div className="col-lg-2 col-sm-6 col-12">
|
onMouseLeave={(e) => {
|
||||||
<div className="input-blocks">
|
e.target.style.background = 'linear-gradient(45deg, #3498db, #2980b9)';
|
||||||
<StopCircle className="info-img" />
|
e.target.style.transform = 'translateY(0)';
|
||||||
<Select
|
e.target.style.boxShadow = 'none';
|
||||||
className="select"
|
}}
|
||||||
options={brandlist}
|
>
|
||||||
placeholder="Nike"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-lg-2 col-sm-6 col-12">
|
|
||||||
<div className="input-blocks">
|
|
||||||
<i className="fas fa-money-bill info-img" />
|
|
||||||
|
|
||||||
<Select
|
|
||||||
className="select"
|
|
||||||
options={price}
|
|
||||||
placeholder="Price"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-lg-2 col-sm-6 col-12">
|
|
||||||
<div className="input-blocks">
|
|
||||||
<Link className="btn btn-filters ms-auto">
|
|
||||||
{" "}
|
|
||||||
<i
|
<i
|
||||||
data-feather="search"
|
data-feather="search"
|
||||||
className="feather-search"
|
className="feather-search"
|
||||||
/>{" "}
|
style={{ marginRight: '8px' }}
|
||||||
Search{" "}
|
/>
|
||||||
</Link>
|
Search
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -707,9 +1252,9 @@ const ProductList = () => {
|
|||||||
pagination={false} // Disable Ant Design pagination
|
pagination={false} // Disable Ant Design pagination
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Table Pagination like the image */}
|
{/* Table Pagination with Theme Integration */}
|
||||||
<div
|
<div
|
||||||
className="custom-pagination-container"
|
className={`custom-pagination-container ${isDarkMode ? '' : 'light-mode'}`}
|
||||||
style={{
|
style={{
|
||||||
background: 'linear-gradient(135deg, #2c3e50 0%, #34495e 100%)',
|
background: 'linear-gradient(135deg, #2c3e50 0%, #34495e 100%)',
|
||||||
border: '1px solid rgba(52, 152, 219, 0.3)',
|
border: '1px solid rgba(52, 152, 219, 0.3)',
|
||||||
@ -757,7 +1302,7 @@ const ProductList = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{display: 'flex', alignItems: 'center', gap: '12px'}}>
|
<div style={{display: 'flex', alignItems: 'center', gap: '12px'}}>
|
||||||
<span style={{color: '#bdc3c7', fontSize: '14px'}}>Row Per Page</span>
|
<span className="pagination-info" style={{color: '#bdc3c7', fontSize: '14px'}}>Row Per Page</span>
|
||||||
<select
|
<select
|
||||||
value={pageSize}
|
value={pageSize}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@ -783,7 +1328,7 @@ const ProductList = () => {
|
|||||||
<option value={50} style={{background: '#2c3e50', color: '#ffffff'}}>50</option>
|
<option value={50} style={{background: '#2c3e50', color: '#ffffff'}}>50</option>
|
||||||
<option value={100} style={{background: '#2c3e50', color: '#ffffff'}}>100</option>
|
<option value={100} style={{background: '#2c3e50', color: '#ffffff'}}>100</option>
|
||||||
</select>
|
</select>
|
||||||
<span style={{color: '#bdc3c7', fontSize: '14px'}}>Entries</span>
|
<span className="pagination-info" style={{color: '#bdc3c7', fontSize: '14px'}}>Entries</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{display: 'flex', alignItems: 'center', gap: '12px'}}>
|
<div style={{display: 'flex', alignItems: 'center', gap: '12px'}}>
|
||||||
@ -802,7 +1347,7 @@ const ProductList = () => {
|
|||||||
>
|
>
|
||||||
📊
|
📊
|
||||||
</div>
|
</div>
|
||||||
<span style={{color: '#bdc3c7', fontSize: '14px'}}>
|
<span className="pagination-info" style={{color: '#bdc3c7', fontSize: '14px'}}>
|
||||||
Showing <strong style={{color: '#3498db'}}>{startRecord}</strong> to <strong style={{color: '#3498db'}}>{endRecord}</strong> of <strong style={{color: '#e74c3c'}}>{totalRecords}</strong> entries
|
Showing <strong style={{color: '#3498db'}}>{startRecord}</strong> to <strong style={{color: '#3498db'}}>{endRecord}</strong> of <strong style={{color: '#e74c3c'}}>{totalRecords}</strong> entries
|
||||||
{debouncedSearchTerm && (
|
{debouncedSearchTerm && (
|
||||||
<span style={{color: '#2ecc71', marginLeft: '8px'}}>
|
<span style={{color: '#2ecc71', marginLeft: '8px'}}>
|
||||||
@ -834,6 +1379,7 @@ const ProductList = () => {
|
|||||||
key={pageNum}
|
key={pageNum}
|
||||||
onClick={() => !loading && handlePageChange(pageNum)}
|
onClick={() => !loading && handlePageChange(pageNum)}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
className={isActive ? 'active' : ''}
|
||||||
style={{
|
style={{
|
||||||
background: loading
|
background: loading
|
||||||
? 'linear-gradient(45deg, #7f8c8d, #95a5a6)'
|
? 'linear-gradient(45deg, #7f8c8d, #95a5a6)'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user