diff --git a/src/core/json/siderbar_data.jsx b/src/core/json/siderbar_data.jsx index 3ed1f84..10f464f 100644 --- a/src/core/json/siderbar_data.jsx +++ b/src/core/json/siderbar_data.jsx @@ -43,6 +43,8 @@ export const SidebarData = [ { label: "Email", link: "/email",showSubRoute: false, }, { label: "To Do", link: "/todo",showSubRoute: false, + }, + { label: "Việc làm", link: "/",showSubRoute: false, }, { label: "Notes", link: "/notes",showSubRoute: false, }, @@ -59,7 +61,7 @@ export const SidebarData = [ submenuHdr: "Inventory", submenuItems: [ - { label: "Products", link: "/product-list", icon:,showSubRoute: false,submenu: false }, + { label: "Sản phẩm", link: "/product-list", icon:,showSubRoute: false,submenu: false }, { label: "Create Product", link: "/add-product", icon: ,showSubRoute: false, submenu: false }, { label: "Expired Products", link: "/expired-products", icon: ,showSubRoute: false,submenu: false }, { label: "Low Stocks", link: "/low-stocks", icon: ,showSubRoute: false,submenu: false }, diff --git a/src/feature-module/inventory/productlist.jsx b/src/feature-module/inventory/productlist.jsx index 4287957..fb36df5 100644 --- a/src/feature-module/inventory/productlist.jsx +++ b/src/feature-module/inventory/productlist.jsx @@ -106,6 +106,319 @@ if (typeof document !== 'undefined' && !document.getElementById('beautiful-pagin position: relative !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); } @@ -132,10 +445,43 @@ const ProductList = () => { const [isFilterVisible, setIsFilterVisible] = useState(false); 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 const [currentPage, setCurrentPage] = useState(reduxCurrentPage || 1); const [pageSize, setPageSize] = useState(reduxPageSize || 20); + // State for filter values + const [filterValues, setFilterValues] = useState({ + product: '', + category: '', + subCategory: '', + brand: '', + priceRange: '' + }); + // Debounced search term const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(""); @@ -159,12 +505,17 @@ const ProductList = () => { const loadProducts = async () => { try { const searchParams = { - page: currentPage, - pageSize: pageSize, - searchTerm: debouncedSearchTerm + Page: currentPage, + PageSize: pageSize, + 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) { console.error('Failed to load products:', error); } @@ -215,12 +566,17 @@ const ProductList = () => { // Dispatch action to fetch products for the new page const searchParams = { - page: page, - pageSize: pageSize, - searchTerm: debouncedSearchTerm + Page: page, + PageSize: pageSize, + 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 @@ -230,12 +586,51 @@ const ProductList = () => { // Dispatch action to fetch products with new page size const searchParams = { - page: 1, - pageSize: newPageSize, - searchTerm: debouncedSearchTerm + Page: 1, + PageSize: newPageSize, + 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 @@ -259,35 +654,11 @@ const ProductList = () => { { value: "140923", label: "14 09 23" }, { value: "110923", label: "11 09 23" }, ]; - const productlist = [ - { 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 - ]; + // Removed unused select option arrays since we're using simple inputs now const columns = [ { - title: "Product", + title: "Sản phẩm", dataIndex: "product", render: (text, record) => ( @@ -303,7 +674,7 @@ const ProductList = () => { sorter: (a, b) => a.product.length - b.product.length, }, { - title: "SKU", + title: "Mã", dataIndex: "sku", render: (_, record) => { const sku = record.sku || record.code || record.productCode || '-'; @@ -317,7 +688,7 @@ const ProductList = () => { }, { - title: "Category", + title: "Danh mục", dataIndex: "category", render: (_, record) => { const category = record.category || record.categoryName || '-'; @@ -331,7 +702,7 @@ const ProductList = () => { }, { - title: "Brand", + title: "Thương hiệu", dataIndex: "brand", render: (_, record) => { const brand = record.brand || record.brandName || '-'; @@ -344,7 +715,7 @@ const ProductList = () => { }, }, { - title: "Price", + title: "Giá", dataIndex: "price", render: (_, record) => { const price = record.price || record.salePrice || record.unitPrice || 0; @@ -357,7 +728,7 @@ const ProductList = () => { }, }, { - title: "Unit", + title: "Đơn vị", dataIndex: "unit", render: (_, record) => { const unit = record.unit || record.unitOfMeasure || '-'; @@ -385,23 +756,19 @@ const ProductList = () => { }, { - title: "Created By", + title: "Người tạo", dataIndex: "createdby", render: (text, record) => ( - - - + + + {record.createdBy || text || "Admin"} - {text} ), sorter: (a, b) => a.createdby.length - b.createdby.length, }, { - title: "Action", + title: "Thao tác", dataIndex: "action", render: (text, record) => ( @@ -485,8 +852,8 @@ const ProductList = () => {
-

Product List

-
Manage your products
+

Danh sách sản phẩm

+
Quản lý sản phẩm
    @@ -541,7 +908,7 @@ const ProductList = () => {
    - Add New Product + Thêm mới
    @@ -552,7 +919,7 @@ const ProductList = () => { data-bs-target="#view-notes" > - Import Product + Nhập sản phẩm
@@ -613,66 +980,244 @@ const ProductList = () => {
-
- - handleFilterChange('product', 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' + }} + > + + + + + + + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ +
- - -
-
-
-
- - -
-
-
-
- - {" "} +
@@ -707,9 +1252,9 @@ const ProductList = () => { pagination={false} // Disable Ant Design pagination /> - {/* Table Pagination like the image */} + {/* Table Pagination with Theme Integration */}
{ }} >
- Row Per Page + Row Per Page - Entries + Entries
@@ -802,7 +1347,7 @@ const ProductList = () => { > 📊
- + Showing {startRecord} to {endRecord} of {totalRecords} entries {debouncedSearchTerm && ( @@ -834,6 +1379,7 @@ const ProductList = () => { key={pageNum} onClick={() => !loading && handlePageChange(pageNum)} disabled={loading} + className={isActive ? 'active' : ''} style={{ background: loading ? 'linear-gradient(45deg, #7f8c8d, #95a5a6)'