Added manufacturing index

This commit is contained in:
seranjivi 2026-04-30 16:30:33 +05:30
parent d7bd261cea
commit 3bcd609ce3
10 changed files with 120 additions and 79 deletions

View File

@ -1180,6 +1180,14 @@ const CompanyProfile = () => {
pattern="[0-9]*"
readOnly={modalMode === 'view'}
/>
<TextField
label="Zone (Area name)"
value={form.contactZone || ''}
onChange={handleFormChange('contactZone')}
placeholder="Enter zone"
width="100%"
readOnly={modalMode === 'view'}
/>
<TextField
label="PO Box"
value={form.contactPoBox}

View File

@ -1574,7 +1574,7 @@ const handleExportCSV = () => {
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
<div className="grid grid-cols-2 gap-4 mt-4">
<div>
<label className="block text-sm font-medium text-[#374151] mb-1">
Unit <span className="text-[#EF4444]">*</span>
@ -1606,32 +1606,30 @@ const handleExportCSV = () => {
<div>
<label className="block text-sm font-medium text-[#374151] mb-1">
Description
Weight
</label>
<textarea
value={form.description || ''}
onChange={handleFormChange("description")}
disabled={modalMode === "view"}
rows={1}
className="w-full px-3 py-2 text-sm border border-[#CBA344] rounded-md focus:outline-none focus:ring-1 focus:ring-[#92722A] focus:border-[#92722A] min-h-[38px] resize-y"
placeholder="Enter product description"
/>
</div>
{/* <div>
<label className="block text-sm font-medium text-[#374151] mb-1">
Status <span className="text-[#EF4444]">*</span>
</label>
<select
value={form.status}
onChange={handleFormChange("status")}
<input
type="text"
value={form.weight || ''}
onChange={handleFormChange("weight")}
disabled={modalMode === "view"}
className="w-full px-3 py-2 text-sm border border-[#CBA344] rounded-md focus:outline-none focus:ring-1 focus:ring-[#92722A] focus:border-[#92722A]"
>
<option value="">Select</option>
<option value="Active">Active</option>
<option value="Inactive">Inactive</option>
</select>
</div> */}
placeholder="Enter weight"
/>
</div>
</div>
<div className="mt-4">
<label className="block text-sm font-medium text-[#374151] mb-1">
Description
</label>
<textarea
value={form.description || ''}
onChange={handleFormChange("description")}
disabled={modalMode === "view"}
rows={2}
className="w-full px-3 py-2 text-sm border border-[#CBA344] rounded-md focus:outline-none focus:ring-1 focus:ring-[#92722A] focus:border-[#92722A] min-h-[38px] resize-y"
placeholder="Enter product description"
/>
</div>
</div>

View File

@ -121,6 +121,11 @@ const ManufacturingIndex = () => {
dataArray = [];
}
// Debug: Log the actual data structure
console.log('API Response:', response);
console.log('Data Array:', dataArray);
console.log('Sample item:', dataArray[0]);
// Format the data
const formattedData = dataArray.map((item, index) => {
// Create a date object from reference_date or other date fields
@ -151,17 +156,17 @@ const ManufacturingIndex = () => {
monthName: monthName,
year: year,
monthNumber: monthNumber,
index: item.manufacturing_index?.toString() || item.index?.toString() || item.manufacturingIndex?.toString() || 'N/A',
index: item.manufacturing_index?.toString() || item.index?.toString() || item.manufacturingIndex?.toString() || '-',
mom: item.mom_change || item.mom || item.momChange ?
(parseFloat(item.mom_change || item.mom || item.momChange) > 0 ?
`+${item.mom_change || item.mom || item.momChange}` :
(item.mom_change || item.mom || item.momChange).toString()) :
'N/A',
'-',
yoy: item.yoy_change || item.yoy || item.yoyChange ?
(parseFloat(item.yoy_change || item.yoy || item.yoyChange) > 0 ?
`+${item.yoy_change || item.yoy || item.yoyChange}` :
(item.yoy_change || item.yoy || item.yoyChange).toString()) :
'N/A',
'-',
generated: item.generated_on || item.generatedOn || item.generated_at ?
new Date(item.generated_on || item.generatedOn || item.generated_at).toLocaleString('en-US', {
year: 'numeric',
@ -171,7 +176,9 @@ const ManufacturingIndex = () => {
minute: '2-digit',
timeZone: 'Asia/Dubai',
timeZoneName: 'short'
}) : 'N/A',
}) : '-',
quarter: item.quarter || item.quarter_name || '-',
totalWeight: item.total_weight || '-',
status: item.status || 'Completed',
rawData: item
};
@ -242,7 +249,7 @@ const ManufacturingIndex = () => {
setApiLoading(true);
// API CALL
const apiResponse = await getManufacturingMonthlyOverview(yearNumber, monthNumber);
const apiResponse = await getManufacturingMonthlyOverview(yearNumber, row.quarter);
// Extract data from the response structure
// Note: Your API returns {status, message, manufacturing_total, isic_2digit, isic_3digit, isic_4digit}
@ -309,12 +316,14 @@ const ManufacturingIndex = () => {
};
const handleExportCSV = () => {
const headers = ['Month', 'Index', 'MoM Change', 'YoY Change', 'Generated On', 'Status'];
const headers = ['Month', 'Quarter', 'Index', 'Total Weight', 'MoM Change', 'YoY Change', 'Generated On', 'Status'];
const csvContent = [
headers.join(','),
...filteredMonths.map(month => [
`"${month.month}"`,
`"${month.quarter}"`,
month.index,
month.totalWeight,
month.mom,
month.yoy,
`"${month.generated}"`,
@ -391,8 +400,7 @@ const ManufacturingIndex = () => {
className="relative"
>
<DialogTitle className="bg-[#F9F5E8] text-[#92722A] flex justify-between items-center pr-2">
<span>Monthly ISIC breakdown
- {selectedMonth?.month}</span>
<span>Monthly ISIC breakdown {selectedMonth?.quarter} - {selectedMonth?.month}</span>
<IconButton
onClick={handleClosePopup}
size="small"
@ -591,7 +599,9 @@ const ManufacturingIndex = () => {
<Table
headers={[
'Reference Month',
'Quarter',
'Manufacturing Index',
'Total Weight',
'MOM Change',
'YOY Change',
'Generated On',
@ -604,9 +614,15 @@ const ManufacturingIndex = () => {
<div key="month" className={`${isSelected ? 'font-medium' : ''}`}>
{row.month}
</div>,
<span className={isSelected ? 'font-medium' : ''} key="quarter">
{row.quarter}
</span>,
<span className={isSelected ? 'font-medium' : ''} key="index">
{row.index} (2022=100)
</span>,
<span className={isSelected ? 'font-medium' : ''} key="totalWeight">
{row.totalWeight}
</span>,
<span className={`${parseFloat(row.mom) >= 0 ? 'text-green-600' : 'text-red-600'} ${isSelected ? 'font-medium' : ''}`} key="mom">
{row.mom}%
</span>,
@ -636,7 +652,7 @@ const ManufacturingIndex = () => {
</div>
];
})}
columnWidths={['180px', '190px', '130px', '130px', '200px', '120px', '80px']}
columnWidths={['180px', '100px', '190px', '120px', '130px', '130px', '200px', '120px', '80px']}
getRowClass={(index) => {
const isSelected = selectedMonth?.month === filteredMonths[index]?.month;
return isSelected ? 'bg-[#F5F0E1]' : 'hover:bg-gray-50';

View File

@ -35,15 +35,15 @@ const ISIC2Digit = ({ setActiveTab, apiData }) => {
if (filteredData.length === 0) return;
// Create CSV content
const headers = ['ISIC Code', 'Sector', 'Index', 'Weight (%)'];
const headers = ['ISIC Code', 'Index', 'Weight (%)', 'Weighted Index'];
const csvRows = [
headers.join(','),
...filteredData.map(item =>
[
`"${item.isic_2digit_code || ''}"`,
`"${item.isic_description || ''}"`,
item.isic_2digit_index || '',
item.total_weight || ''
item.total_weight || '',
item.weighted_index_sum || ''
].join(',')
)
];
@ -62,7 +62,7 @@ const ISIC2Digit = ({ setActiveTab, apiData }) => {
// Format number with 2 decimal places if needed
const formatNumber = (value) => {
if (value === null || value === undefined || value === '' || value === 'N/A') return 'N/A';
if (value === null || value === undefined || value === '' || value === '-') return '-';
const num = parseFloat(value);
if (isNaN(num)) return value;
@ -81,7 +81,14 @@ const ISIC2Digit = ({ setActiveTab, apiData }) => {
return (
<div className="-mt-4">
<h3 className="text-lg font-semibold text-gray-900">ISIC 2-digit breakdown</h3>
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-900">ISIC 2-digit breakdown</h3>
{/* <div className="bg-gray-100 px-3 py-1 rounded-full">
<span className="text-sm font-medium text-gray-700">
Quarter: {apiData?.[0]?.quarter || '-'}
</span>
</div> */}
</div>
<p className="text-sm mt-2 text-gray-600 mb-4">
The manufacturing index is calculated as a weighted average of ISIC 2-digit groups,
using their relative weights in the manufacturing sector.
@ -117,7 +124,7 @@ const ISIC2Digit = ({ setActiveTab, apiData }) => {
</div>
<input
type="text"
placeholder="Search by sector or code..."
placeholder="Search by code or index..."
className="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#92722A] focus:border-[#92722A] sm:text-sm"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
@ -142,13 +149,10 @@ const ISIC2Digit = ({ setActiveTab, apiData }) => {
<div className="-mx-6">
<Table
headers={['ISIC Code', 'Sector', 'Index', 'Weight (%)']}
headers={['ISIC Code', 'Index', 'Weight (%)', 'Weighted Index']}
rows={filteredData.map((item, index) => [
<span className="font-medium" key={`code-${item.isic_2digit_code || index}`}>
{item.isic_2digit_code || 'N/A'}
</span>,
<span key={`name-${item.isic_2digit_code || index}`}>
{item.isic_description || 'N/A'}
{item.isic_2digit_code || '-'}
</span>,
<span
key={`index-${item.isic_2digit_code || index}`}
@ -158,10 +162,13 @@ const ISIC2Digit = ({ setActiveTab, apiData }) => {
</span>,
<span key={`weight-${item.isic_2digit_code || index}`}>
{formatNumber(item.total_weight)}%
</span>,
<span key={`weighted-index-${item.isic_2digit_code || index}`}>
{formatNumber(item.weighted_index_sum)}
</span>
])}
className="w-full"
columnWidths={['15%', '55%', '15%', '15%']}
columnWidths={['15%', '30%', '25%', '30%']}
getCellClass={(rowIndex, colIndex) => {
const baseClasses = 'px-6 py-4 whitespace-nowrap text-sm';
return colIndex === 0

View File

@ -34,15 +34,15 @@ const ISIC3Digit = ({ setActiveTab, apiData }) => {
if (filteredData.length === 0) return;
// Create CSV content
const headers = ['ISIC Code', 'Sector', 'Index', 'Weight (%)'];
const headers = ['ISIC Code', 'Index', 'Weight (%)', 'Weighted Index'];
const csvRows = [
headers.join(','),
...filteredData.map(item =>
[
`"${item.isic_3digit_code || ''}"`,
`"${item.isic_description || ''}"`,
item.isic_3digit_index || '',
item.total_weight || ''
item.total_weight || '',
item.weighted_index_sum || ''
].join(',')
)
];
@ -61,7 +61,7 @@ const ISIC3Digit = ({ setActiveTab, apiData }) => {
// Format number with 2 decimal places if needed
const formatNumber = (value) => {
if (value === null || value === undefined || value === '' || value === 'N/A') return 'N/A';
if (value === null || value === undefined || value === '' || value === '') return '-';
const num = parseFloat(value);
if (isNaN(num)) return value;
@ -71,7 +71,10 @@ const ISIC3Digit = ({ setActiveTab, apiData }) => {
return (
<div className="-mt-4">
<h3 className="text-lg font-semibold text-gray-900">ISIC 3-digit breakdown</h3>
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-900">ISIC 3-digit breakdown</h3>
</div>
<p className="text-sm mt-2 text-gray-600 mb-4">
Detailed breakdown of manufacturing index by ISIC 3-digit classification.
</p>
@ -105,7 +108,7 @@ const ISIC3Digit = ({ setActiveTab, apiData }) => {
</div>
<input
type="text"
placeholder="Search by sector or code..."
placeholder="Search by code or index..."
className="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#92722A] focus:border-[#92722A] sm:text-sm"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
@ -130,13 +133,10 @@ const ISIC3Digit = ({ setActiveTab, apiData }) => {
<div className="-mx-6">
<Table
headers={['ISIC Code', 'Sector', 'Index', 'Weight (%)']}
headers={['ISIC Code', 'Index', 'Weight (%)', 'Weighted Index']}
rows={filteredData.map((item, index) => [
<span className="font-medium" key={`code-${item.isic_3digit_code || index}`}>
{item.isic_3digit_code || 'N/A'}
</span>,
<span key={`name-${item.isic_3digit_code || index}`}>
{item.isic_description || 'N/A'}
{item.isic_3digit_code || '-'}
</span>,
<span
key={`index-${item.isic_3digit_code || index}`}
@ -146,10 +146,13 @@ const ISIC3Digit = ({ setActiveTab, apiData }) => {
</span>,
<span key={`weight-${item.isic_3digit_code || index}`}>
{formatNumber(item.total_weight)}%
</span>,
<span key={`weighted-index-${item.isic_3digit_code || index}`}>
{formatNumber(item.weighted_index_sum)}
</span>
])}
className="w-full"
columnWidths={['20%', '50%', '15%', '15%']}
columnWidths={['15%', '30%', '25%', '30%']}
getCellClass={(rowIndex, colIndex) => {
const baseClasses = 'px-6 py-4 whitespace-nowrap text-sm text-gray-900';
return colIndex === 0

View File

@ -34,15 +34,15 @@ const ISIC4Digit = ({ setActiveTab, apiData }) => {
if (filteredData.length === 0) return;
// Create CSV content
const headers = ['ISIC Code', 'Sector', 'Index', 'Weight (%)'];
const headers = ['ISIC Code', 'Index', 'Weight (%)', 'Weighted Index'];
const csvRows = [
headers.join(','),
...filteredData.map(item =>
[
`"${item.isic_4digit_code || ''}"`,
`"${item.isic_description || ''}"`,
item.isic_4digit_index || '',
item.total_weight || ''
item.total_weight || '',
item.weighted_index_sum || ''
].join(',')
)
];
@ -61,7 +61,7 @@ const ISIC4Digit = ({ setActiveTab, apiData }) => {
// Format number with 2 decimal places if needed
const formatNumber = (value) => {
if (value === null || value === undefined || value === '' || value === 'N/A') return 'N/A';
if (value === null || value === undefined || value === '' || value === '-') return '-';
const num = parseFloat(value);
if (isNaN(num)) return value;
@ -71,7 +71,10 @@ const ISIC4Digit = ({ setActiveTab, apiData }) => {
return (
<div className="-mt-4">
<h3 className="text-lg font-semibold text-gray-900">ISIC 4-digit breakdown</h3>
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-900">ISIC 4-digit breakdown</h3>
</div>
<p className="text-sm mt-2 text-gray-600 mb-4">
Detailed breakdown of manufacturing index by ISIC 4-digit classification.
</p>
@ -105,7 +108,7 @@ const ISIC4Digit = ({ setActiveTab, apiData }) => {
</div>
<input
type="text"
placeholder="Search by sector or code..."
placeholder="Search by code or index..."
className="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#92722A] focus:border-[#92722A] sm:text-sm"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
@ -130,13 +133,10 @@ const ISIC4Digit = ({ setActiveTab, apiData }) => {
<div className="-mx-6">
<Table
headers={['ISIC Code', 'Sector', 'Index', 'Weight (%)']}
headers={['ISIC Code', 'Index', 'Weight (%)', 'Weighted Index']}
rows={filteredData.map((item, index) => [
<span className="font-medium" key={`code-${item.isic_4digit_code || index}`}>
{item.isic_4digit_code || 'N/A'}
</span>,
<span key={`name-${item.isic_4digit_code || index}`}>
{item.isic_description || 'N/A'}
{item.isic_4digit_code || '-'}
</span>,
<span
key={`index-${item.isic_4digit_code || index}`}
@ -146,10 +146,13 @@ const ISIC4Digit = ({ setActiveTab, apiData }) => {
</span>,
<span key={`weight-${item.isic_4digit_code || index}`}>
{formatNumber(item.total_weight)}%
</span>,
<span key={`weighted-index-${item.isic_4digit_code || index}`}>
{formatNumber(item.weighted_index_sum)}
</span>
])}
className="w-full"
columnWidths={['20%', '50%', '15%', '15%']}
columnWidths={['15%', '30%', '25%', '30%']}
getCellClass={(rowIndex, colIndex) => {
const baseClasses = 'px-6 py-4 whitespace-nowrap text-sm text-gray-900';
return colIndex === 0

View File

@ -23,18 +23,18 @@ const ManufacturingTotal = ({ selectedMonthData, setActiveTab, monthlyOverviewDa
if (apiData) {
// API data has different structure
switch(key) {
case 'index': return apiData.index || apiData.manufacturing_index || 'N/A';
case 'index': return apiData.index || apiData.manufacturing_index || '-';
case 'mom':
const momVal = apiData.mom || apiData.mom_change || 0;
return momVal > 0 ? `+${momVal}%` : `${momVal}%`;
case 'yoy':
const yoyVal = apiData.yoy || apiData.yoy_change || 0;
return yoyVal > 0 ? `+${yoyVal}%` : `${yoyVal}%`;
default: return 'N/A';
default: return '-';
}
} else {
// Table data
return dataSource[key] || 'N/A';
return dataSource[key] || '-';
}
};
@ -48,9 +48,16 @@ const ManufacturingTotal = ({ selectedMonthData, setActiveTab, monthlyOverviewDa
return (
<div className="space-y-5">
<p className="text-xs font-semibold uppercase tracking-wider text-medium-500">
Manufacturing Index (Headline)
</p>
<div className="flex items-center justify-between">
<p className="text-xs font-semibold uppercase tracking-wider text-medium-500">
Manufacturing Index (Headline)
</p>
{/* <div className="bg-gray-100 px-3 py-1 rounded-full"> */}
{/* <span className="text-sm font-medium text-gray-700">
Quarter: {selectedMonthData?.quarter || '-'}
</span> */}
{/* </div> */}
</div>
<div className="flex items-baseline gap-2">
<h3 className="text-3xl font-semibold text-gray-900">

View File

@ -57,7 +57,7 @@ export const getSubmissions = async (params = {}) => {
}
};
/** 🔹 Fetch a single submission by ID */
/** Fetch a single submission by ID */
export const getSubmissionById = async (id) => {
const response = await apiClient.get(`/submissions/view/${id}`);
return response.data;

View File

@ -12,7 +12,7 @@ export const getManufacturingIndex = async () => {
}
};
export const getManufacturingMonthlyOverview = async (year, month) => {
export const getManufacturingMonthlyOverview = async (year, quarter) => {
try {
const response = await getRequest(
@ -20,7 +20,7 @@ export const getManufacturingMonthlyOverview = async (year, month) => {
{
params: {
year: year.toString(),
month: month.toString(),
quarter: quarter.toString(),
},
}
);