Initialized Counter login and fixed bugs in the edit products option

This commit is contained in:
Sidharth Prabhu
2026-04-16 10:42:43 +05:30
parent d4cef8d241
commit 9af9f0599a
39 changed files with 1115 additions and 85 deletions

View File

@@ -30,6 +30,7 @@ const BaseMenu = () => {
const [currentPage, setCurrentPage] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [totalElements, setTotalElements] = useState(0);
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
// Associated Products State
const [selectedBaseItem, setSelectedBaseItem] = useState<BaseItem | null>(null);
@@ -39,9 +40,24 @@ const BaseMenu = () => {
const menuRef = useRef<HTMLDivElement>(null);
// Debounce search term
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedSearchTerm(searchTerm);
}, 500);
return () => clearTimeout(timer);
}, [searchTerm]);
// Reset to first page when search changes
useEffect(() => {
setCurrentPage(0);
}, [debouncedSearchTerm]);
useEffect(() => {
fetchItems();
}, [currentPage, pageSize, debouncedSearchTerm]);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
setOpenMenuId(null);
@@ -49,13 +65,20 @@ const BaseMenu = () => {
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [currentPage, pageSize]);
}, []);
const fetchItems = async () => {
setLoading(true);
try {
const host = window.location.hostname;
const response = await fetch(`http://${host}:8080/api/base-items?page=${currentPage}&size=${pageSize}`);
const params = new URLSearchParams();
params.append('page', currentPage.toString());
params.append('size', pageSize.toString());
if (debouncedSearchTerm) {
params.append('search', debouncedSearchTerm);
}
const response = await fetch(`http://${host}:8080/api/base-items?${params.toString()}`);
const data = await response.json();
if (data && data.content) {
setItems(data.content);
@@ -200,17 +223,15 @@ const BaseMenu = () => {
</div>
</td>
</tr>
) : items.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase())).length === 0 ? (
) : items.length === 0 ? (
<tr>
<td colSpan={6} className="px-6 py-12 text-center text-[#64748b]">
<p className="text-lg font-medium mb-1">No items found</p>
<p className="text-sm">Click "Add New Item" to create your first item.</p>
<p className="text-sm">Try adjusting your search or add a new item.</p>
</td>
</tr>
) : (
items
.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase()))
.map((item) => (
items.map((item) => (
<tr key={item.id} className="hover:bg-gray-50/50 transition-all group">
<td className="px-6 py-4 text-sm font-medium text-[#64748b]">#{item.id}</td>
<td className="px-6 py-4">

View File

@@ -19,6 +19,7 @@ const Customers: React.FC = () => {
const [currentPage, setCurrentPage] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [totalElements, setTotalElements] = useState(0);
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
// Edit Modal State
const [showEditModal, setShowEditModal] = useState(false);
@@ -34,15 +35,33 @@ const Customers: React.FC = () => {
// Action Menu State
const [openMenuId, setOpenMenuId] = useState<number | null>(null);
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedSearchTerm(searchTerm);
}, 500);
return () => clearTimeout(timer);
}, [searchTerm]);
useEffect(() => {
setCurrentPage(0);
}, [debouncedSearchTerm]);
useEffect(() => {
fetchUsers();
}, [currentPage, pageSize]);
}, [currentPage, pageSize, debouncedSearchTerm]);
const fetchUsers = async () => {
try {
setIsLoading(true);
const host = window.location.hostname;
const response = await fetch(`http://${host}:8080/api/auth/users?page=${currentPage}&size=${pageSize}`);
const params = new URLSearchParams();
params.append('page', currentPage.toString());
params.append('size', pageSize.toString());
if (debouncedSearchTerm) {
params.append('search', debouncedSearchTerm);
}
const response = await fetch(`http://${host}:8080/api/auth/users?${params.toString()}`);
if (response.ok) {
const data = await response.json();
if (data && data.content) {
@@ -146,11 +165,6 @@ const Customers: React.FC = () => {
return name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2);
};
const filteredUsers = users.filter(user =>
user.name?.toLowerCase().includes(searchTerm.toLowerCase()) ||
user.mobileNumber?.includes(searchTerm)
);
return (
<>
{/* Toast Notification - Moved outside animation trapping */}
@@ -232,8 +246,8 @@ const Customers: React.FC = () => {
</tr>
</thead>
<tbody className="divide-y divide-[#e2e8f0]">
{filteredUsers.length > 0 ? (
filteredUsers.map((user) => (
{users.length > 0 ? (
users.map((user) => (
<tr key={user.id} className="hover:bg-gray-50/50 transition-all">
<td className="px-6 py-4">
<div className="flex items-center gap-3">
@@ -300,7 +314,7 @@ const Customers: React.FC = () => {
</div>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6 p-6">
{filteredUsers.map(user => (
{users.map(user => (
<div key={user.id} className="group relative p-6 bg-white border border-[#e2e8f0] rounded-xl flex flex-col items-center text-center transition-all hover:shadow-lg hover:-translate-y-1">
<div className="absolute top-4 right-4">
<button onClick={() => setOpenMenuId(openMenuId === user.id ? null : user.id)} className="p-1.5 text-[#94a3b8] hover:text-[#231651] rounded-lg">

View File

@@ -66,6 +66,7 @@ const Orders: React.FC = () => {
const [currentPage, setCurrentPage] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [totalElements, setTotalElements] = useState(0);
const [debouncedSearchQuery, setDebouncedSearchQuery] = useState('');
// Action Menu & Edit Modal States
const [showActionMenu, setShowActionMenu] = useState(false);
@@ -75,10 +76,26 @@ const Orders: React.FC = () => {
const [editingItems, setEditingItems] = useState<OrderItem[]>([]);
const [isUpdatingOrder, setIsUpdatingOrder] = useState(false);
// Debounce search query
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedSearchQuery(searchQuery);
}, 500);
return () => clearTimeout(timer);
}, [searchQuery]);
// Reset to first page when search changes
useEffect(() => {
setCurrentPage(0);
}, [debouncedSearchQuery]);
useEffect(() => {
fetchOrders();
}, [startDate, endDate, statusFilter, paymentFilter, currentPage, pageSize, debouncedSearchQuery]);
useEffect(() => {
fetchProducts();
}, [startDate, endDate, statusFilter, paymentFilter, currentPage, pageSize]);
}, []);
const fetchProducts = async () => {
try {
@@ -102,7 +119,7 @@ const Orders: React.FC = () => {
if (endDate) params.append('endDate', `${endDate}T23:59:59`);
if (statusFilter) params.append('status', statusFilter);
if (paymentFilter) params.append('paymentType', paymentFilter);
if (searchQuery) params.append('search', searchQuery);
if (debouncedSearchQuery) params.append('search', debouncedSearchQuery);
params.append('page', currentPage.toString());
params.append('size', pageSize.toString());

View File

@@ -94,14 +94,32 @@ const Products = () => {
const [currentPage, setCurrentPage] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [totalElements, setTotalElements] = useState(0);
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
const menuRef = useRef<HTMLDivElement>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
// Debounce search term
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedSearchTerm(searchTerm);
}, 500);
return () => clearTimeout(timer);
}, [searchTerm]);
// Reset to first page when search changes
useEffect(() => {
setCurrentPage(0);
}, [debouncedSearchTerm]);
useEffect(() => {
fetchProducts();
}, [currentPage, pageSize, debouncedSearchTerm]);
useEffect(() => {
fetchBaseItems();
fetchAllStalls();
const handleClickOutside = (event: MouseEvent) => {
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
setOpenMenuId(null);
@@ -109,13 +127,20 @@ const Products = () => {
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [currentPage, pageSize]);
}, []);
const fetchProducts = async () => {
setLoading(true);
try {
const host = window.location.hostname;
const response = await fetch(`http://${host}:8080/api/products?page=${currentPage}&size=${pageSize}`);
const params = new URLSearchParams();
params.append('page', currentPage.toString());
params.append('size', pageSize.toString());
if (debouncedSearchTerm) {
params.append('search', debouncedSearchTerm);
}
const response = await fetch(`http://${host}:8080/api/products?${params.toString()}`);
const data = await response.json();
if (data && data.content) {
setProducts(data.content);
@@ -133,9 +158,9 @@ const Products = () => {
const fetchBaseItems = async () => {
try {
const response = await fetch('http://localhost:8080/api/base-items');
const response = await fetch('http://localhost:8080/api/base-items?size=100');
const data = await response.json();
setBaseItems(data);
setBaseItems(data.content || data);
} catch (error) {
console.error('Error fetching base items:', error);
}
@@ -303,9 +328,9 @@ const Products = () => {
<tbody className="divide-y divide-[#e2e8f0]">
{loading ? (
<tr><td colSpan={6} className="px-6 py-12 text-center text-[#64748b]"><RefreshCw className="animate-spin inline mr-2" />Loading...</td></tr>
) : products.filter(p => p.name.toLowerCase().includes(searchTerm.toLowerCase()) || p.category.toLowerCase().includes(searchTerm.toLowerCase())).length === 0 ? (
) : products.length === 0 ? (
<tr><td colSpan={6} className="px-6 py-12 text-center text-[#64748b]">No products found</td></tr>
) : products.filter(p => p.name.toLowerCase().includes(searchTerm.toLowerCase()) || p.category.toLowerCase().includes(searchTerm.toLowerCase())).map((product) => (
) : products.map((product) => (
<tr key={product.id} className="hover:bg-gray-50/50 transition-all">
<td className="px-6 py-4">
<div className="flex items-center gap-3">

View File

@@ -194,12 +194,18 @@ const Stalls: React.FC = () => {
try {
const host = window.location.hostname;
const [prodRes, baseRes] = await Promise.all([
fetch(`http://${host}:8080/api/products`),
fetch(`http://${host}:8080/api/base-items`)
fetch(`http://${host}:8080/api/products?size=1000`),
fetch(`http://${host}:8080/api/base-items?size=100`)
]);
if (prodRes.ok) setAllProducts(await prodRes.json());
if (baseRes.ok) setAllBaseItems(await baseRes.json());
if (prodRes.ok) {
const data = await prodRes.json();
setAllProducts(data.content || data);
}
if (baseRes.ok) {
const data = await baseRes.json();
setAllBaseItems(data.content || data);
}
} catch (error) {
console.error('Error fetching available items:', error);
}