bug fixed

This commit is contained in:
Malini 2025-11-13 09:43:18 +05:30
parent 24fcea6189
commit 2edb38db14
6 changed files with 119 additions and 34 deletions

View File

@ -132,8 +132,9 @@ const SubmissionTable = ({ selectedQuarter, selectedYear }) => {
if (type === 'approve') {
setShowApproveModal(true);
} else {
// Clear previous state
setRejectionReason('');
setShowRejectError(false);
setShowRejectError(false); // Don't show error immediately
setShowRejectModal(true);
}
};
@ -320,22 +321,42 @@ const SubmissionTable = ({ selectedQuarter, selectedYear }) => {
<div className="relative group">
<CheckCircle2
size={22}
className={`${item.status?.toLowerCase() === 'approved' ? 'text-gray-400 cursor-not-allowed' : 'text-green-600 cursor-pointer hover:scale-110'} transition-transform`}
onClick={item.status?.toLowerCase() !== 'approved' ? () => handleActionClick(item, 'approve') : undefined}
className={`${
item.status?.toLowerCase() === 'approved' || item.status?.toLowerCase() === 'rejected'
? 'text-gray-400 cursor-not-allowed'
: 'text-green-600 cursor-pointer hover:scale-110'
} transition-transform`}
onClick={['submitted', 'resubmitted'].includes(item.status?.toLowerCase())
? () => handleActionClick(item, 'approve')
: undefined}
/>
<span className="absolute bottom-full mb-1 left-1/2 -translate-x-1/2 bg-black text-white text-xs px-2 py-[2px] rounded opacity-0 group-hover:opacity-100 transition">
{item.status?.toLowerCase() === 'approved' ? 'Already Approved' : 'Approve'}
{item.status?.toLowerCase() === 'approved'
? 'Already Approved'
: item.status?.toLowerCase() === 'rejected'
? 'Cannot approve rejected'
: 'Approve'}
</span>
</div>
<div className="relative group">
<XCircle
size={22}
className={`${item.status?.toLowerCase() === 'rejected' ? 'text-gray-400 cursor-not-allowed' : 'text-red-600 cursor-pointer hover:scale-110'} transition-transform`}
onClick={item.status?.toLowerCase() !== 'rejected' ? () => handleActionClick(item, 'reject') : undefined}
className={`${
['approved', 'rejected'].includes(item.status?.toLowerCase())
? 'text-gray-400 cursor-not-allowed'
: 'text-red-600 cursor-pointer hover:scale-110'
} transition-transform`}
onClick={!['approved', 'rejected'].includes(item.status?.toLowerCase())
? () => handleActionClick(item, 'reject')
: undefined}
/>
<span className="absolute bottom-full mb-1 left-1/2 -translate-x-1/2 bg-black text-white text-xs px-2 py-[2px] rounded opacity-0 group-hover:opacity-100 transition">
{item.status?.toLowerCase() === 'rejected' ? 'Already Rejected' : 'Reject'}
<span className="absolute bottom-full mb-1 left-1/2 -translate-x-1/2 bg-black text-white text-xs px-2 py-[2px] rounded opacity-0 group-hover:opacity-100 transition whitespace-nowrap">
{item.status?.toLowerCase() === 'rejected'
? 'Already Rejected'
: item.status?.toLowerCase() === 'approved'
? 'Cannot reject approved'
: 'Reject'}
</span>
</div>
@ -486,9 +507,15 @@ const SubmissionTable = ({ selectedQuarter, selectedYear }) => {
</button>
<button
type="button"
onClick={handleRejectConfirm}
className="px-4 py-2 text-sm font-medium text-white bg-[#92722A] border border-transparent rounded-md shadow-sm hover:bg-[#7c5e24] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#92722A] flex items-center gap-2"
disabled={isProcessing || !rejectionReason.trim()}
onClick={() => {
if (!rejectionReason.trim()) {
setShowRejectError(true);
return;
}
handleRejectConfirm();
}}
className="px-4 py-2 text-sm font-medium text-white bg-[#92722A] border border-transparent rounded-md shadow-sm hover:bg-[#7c5e24] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#92722A] flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed"
disabled={isProcessing}
>
{isProcessing ? (
<>

View File

@ -579,7 +579,7 @@ const ValidationReview = () => {
</label>
<textarea
rows="2"
className="w-[1100px] rounded-[10px] border border-[#D1D5DB] bg-[#FFFCF2] px-4 py-2 mb-4 text-sm text-[#232528] focus:ring-2 focus:ring-[#92722A] focus:outline-none"
className="w-[580px] rounded-[10px] border border-[#D1D5DB] bg-[#FFFCF2] px-4 py-2 mb-4 text-sm text-[#232528] focus:ring-2 focus:ring-[#92722A] focus:outline-none"
placeholder="Please enter remarks here"
></textarea>
</div>
@ -727,7 +727,7 @@ const ValidationReview = () => {
<div className="flex justify-end gap-3 mt-6">
<button
type="button"
className="rounded-md border border-gray-300 bg-[#92722A] px-4 py-2 text-sm font-medium text-[#92722A] hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
className="rounded-md border border-gray-300 bg-[#fffff] px-4 py-2 text-sm font-medium text-[#92722A] hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-[#92722A] focus:ring-offset-2"
onClick={() => setIsApproveOpen(false)}
disabled={actionLoading}
>

View File

@ -523,13 +523,13 @@ React.useEffect(() => {
data.forEach((item) => {
const normalized = String(item.status || '').toLowerCase();
let status = '—';
if (normalized === 'pending') status = 'Under Review';
else if (normalized === 'rejected') status = 'Returned';
else if (['submitted', 'approved'].includes(normalized)) status = 'Approved';
if (normalized === 'submitted') status = 'Submitted';
else if (normalized === 'rejected') status = 'Rejected';
else if (['approved'].includes(normalized)) status = 'Approved';
else status = item.status || '—';
const productCount = Number(item.products) || 0;
const products = `${productCount} ${productCount === 1 ? 'product' : 'products'}`;
const products = `${productCount} `;
const row = [
item.establishment || '—',
@ -680,22 +680,42 @@ React.useEffect(() => {
<div className="relative group">
<CheckCircle2
size={22}
className={`${item.status?.toLowerCase() === 'approved' ? 'text-gray-400 cursor-not-allowed' : 'text-green-600 cursor-pointer hover:scale-110'} transition-transform`}
onClick={item.status?.toLowerCase() !== 'approved' ? () => handleApproveClick(item) : undefined}
className={`${
item.status?.toLowerCase() === 'approved' || item.status?.toLowerCase() === 'rejected'
? 'text-gray-400 cursor-not-allowed'
: 'text-green-600 cursor-pointer hover:scale-110'
} transition-transform`}
onClick={['submitted', 'resubmitted'].includes(item.status?.toLowerCase())
? () => handleApproveClick(item)
: undefined}
/>
<span className="absolute bottom-full mb-1 left-1/2 -translate-x-1/2 bg-black text-white text-xs px-2 py-[2px] rounded opacity-0 group-hover:opacity-100 transition">
{item.status?.toLowerCase() === 'approved' ? 'Already Approved' : 'Approve'}
<span className="absolute bottom-full mb-1 left-1/2 -translate-x-1/2 bg-black text-white text-xs px-2 py-[2px] rounded opacity-0 group-hover:opacity-100 transition whitespace-nowrap">
{item.status?.toLowerCase() === 'approved'
? 'Already Approved'
: item.status?.toLowerCase() === 'rejected'
? 'Cannot approve rejected'
: 'Approve'}
</span>
</div>
<div className="relative group">
<XCircle
size={22}
className={`${item.status?.toLowerCase() === 'rejected' ? 'text-gray-400 cursor-not-allowed' : 'text-red-600 cursor-pointer hover:scale-110'} transition-transform`}
onClick={item.status?.toLowerCase() !== 'rejected' ? () => handleRejectClick(item) : undefined}
className={`${
['approved', 'rejected'].includes(item.status?.toLowerCase())
? 'text-gray-400 cursor-not-allowed'
: 'text-red-600 cursor-pointer hover:scale-110'
} transition-transform`}
onClick={!['approved', 'rejected'].includes(item.status?.toLowerCase())
? () => handleRejectClick(item)
: undefined}
/>
<span className="absolute bottom-full mb-1 left-1/2 -translate-x-1/2 bg-black text-white text-xs px-2 py-[2px] rounded opacity-0 group-hover:opacity-100 transition">
{item.status?.toLowerCase() === 'rejected' ? 'Already Rejected' : 'Reject'}
<span className="absolute bottom-full mb-1 left-1/2 -translate-x-1/2 bg-black text-white text-xs px-2 py-[2px] rounded opacity-0 group-hover:opacity-100 transition whitespace-nowrap">
{item.status?.toLowerCase() === 'rejected'
? 'Already Rejected'
: item.status?.toLowerCase() === 'approved'
? 'Cannot reject approved'
: 'Reject'}
</span>
</div>

View File

@ -1943,8 +1943,25 @@ const loadProfiles = async () => {
// Website URL validation
if ((field === 'contactWebsite' || field === 'corporateWebsite') && value) {
if (!/^https?:\/\/.+\..+/.test(value)) {
return 'Please enter a valid URL (e.g., https://example.com)';
// Supports:
// - http://example.com
// - https://example.com
// - www.example.com
// - example.com
// - subdomain.example.com
// - localhost:3000 (for development)
// - IP addresses (e.g., 192.168.1.1)
// - With or without path/query parameters
const urlRegex = /^(https?:\/\/)?(www\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(\.[a-zA-Z]{2,})?(\/\S*)?$/;
// Also allow localhost with optional port for development
// const localhostRegex = /^https?:\/\/localhost(:\d+)?(\/\S*)?$/;
// Also allow IP addresses with optional port
const ipRegex = /^https?:\/\/(\d{1,3}\.){3}\d{1,3}(:\d+)?(\/\S*)?$/;
if (!urlRegex.test(value)&& !ipRegex.test(value)) {
return 'Please enter a valid URL (e.g., https://example.com, example.com, or www.example.com)';
}
}

View File

@ -485,7 +485,7 @@ const IsicHsCodes = () => {
'HS Code',
'Product Name',
'Unit',
'Estimated Mapped',
'Establishment Mapped',
'Created By',
'Last Updated',
'Action',

View File

@ -38,13 +38,13 @@ const CustomToast = ({ message, type, onClose }) => {
const getIcon = () => {
switch (type) {
case 'success':
return '';
return '';
case 'error':
return '';
return '';
case 'warning':
return '⚠️';
return '';
default:
return '';
return '';
}
};
@ -399,11 +399,21 @@ const QuarterlyWindows = () => {
type: 'success'
});
} else {
console.error('Failed to add quarterly window');
// Show error message from API response if available
const errorMessage = response.message || 'Failed to add quarterly window';
setToastData({
message: errorMessage,
type: 'error'
});
console.error('Failed to add quarterly window:', errorMessage);
}
} else if (modalMode === 'edit' && editingRow !== null) {
const itemId = quarterData[editingRow]?.id;
if (!itemId) {
setToastData({
message: 'Error: Could not find the item to update',
type: 'error'
});
console.error('Error: Could not find the item to update');
return;
}
@ -430,11 +440,22 @@ const QuarterlyWindows = () => {
type: 'success'
});
} else {
console.error('Failed to update quarterly window');
// Show error message from API response if available
const errorMessage = response.message || 'Failed to update quarterly window';
setToastData({
message: errorMessage,
type: 'error'
});
console.error('Failed to update quarterly window:', errorMessage);
}
}
handleCloseModal();
} catch (error) {
const errorMessage = error.response?.data?.message || error.message || 'An error occurred while saving';
setToastData({
message: errorMessage,
type: 'error'
});
console.error('Error saving quarterly window:', error);
}
};