|
|
@ -29,12 +29,13 @@ const TableDashboardV1 = () => { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const [MANPOWERS, SET_MANPOWERS] = useState(0) |
|
|
|
const [MANPOWERS, SET_MANPOWERS] = useState(0) |
|
|
|
|
|
|
|
const [MAXPLANNEDCOST, SET_MAXPLANNEDCOST] = useState(0) |
|
|
|
|
|
|
|
const [MAXACTUALCOST, SET_MAXACTUALCOST] = useState(0) |
|
|
|
|
|
|
|
const [MAXCOSTVARIANCE, SET_MAXCOSTVARIANCE] = useState(0) |
|
|
|
const [dataTable, setDataTable] = useState([]) |
|
|
|
const [dataTable, setDataTable] = useState([]) |
|
|
|
const [searchText, setSearchText] = useState('') |
|
|
|
const [searchText, setSearchText] = useState('') |
|
|
|
const [searchedColumn, setSearchedColumn] = useState('') |
|
|
|
const [searchedColumn, setSearchedColumn] = useState('') |
|
|
|
const searchInput = useRef(null) |
|
|
|
const searchInput = useRef(null) |
|
|
|
const [maxSlider, setMaxSlider] = useState(MANPOWERS) |
|
|
|
|
|
|
|
//const [sliderValue, setSliderValue] = useState([]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleSearch = (selectedKeys, confirm, dataIndex) => { |
|
|
|
const handleSearch = (selectedKeys, confirm, dataIndex) => { |
|
|
|
confirm() |
|
|
|
confirm() |
|
|
@ -46,12 +47,8 @@ const TableDashboardV1 = () => { |
|
|
|
confirm({ closeDropdown: false }); |
|
|
|
confirm({ closeDropdown: false }); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const slider = (dataIndex) => ({ |
|
|
|
const slider = (dataIndex, maxSlider) => ({ |
|
|
|
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => { |
|
|
|
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => { |
|
|
|
if(dataIndex == 'manpower'){ |
|
|
|
|
|
|
|
setMaxSlider(MANPOWERS) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
return ( |
|
|
|
<div |
|
|
|
<div |
|
|
|
className="custom-filter-dropdown ant-table-filter-dropdown" |
|
|
|
className="custom-filter-dropdown ant-table-filter-dropdown" |
|
|
@ -71,6 +68,7 @@ const TableDashboardV1 = () => { |
|
|
|
range={true} |
|
|
|
range={true} |
|
|
|
min={0} |
|
|
|
min={0} |
|
|
|
max={maxSlider} |
|
|
|
max={maxSlider} |
|
|
|
|
|
|
|
defaultValue={[0, maxSlider]} |
|
|
|
onAfterChange={(value) => { |
|
|
|
onAfterChange={(value) => { |
|
|
|
setSelectedKeys([value]) |
|
|
|
setSelectedKeys([value]) |
|
|
|
handleSlide(dataIndex, value, confirm)} |
|
|
|
handleSlide(dataIndex, value, confirm)} |
|
|
@ -82,40 +80,10 @@ const TableDashboardV1 = () => { |
|
|
|
<div> |
|
|
|
<div> |
|
|
|
<strong>Max:</strong> |
|
|
|
<strong>Max:</strong> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div>{maxSlider}</div> |
|
|
|
<div style={{ whitespace: "nowrap", overflow: "hidden" }} ellipsis={true}>{dataIndex == 'manpower' || dataIndex == 'progress' ? maxSlider : formatRibuanDecimal(maxSlider)}</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</Col> |
|
|
|
</Col> |
|
|
|
</Row> |
|
|
|
</Row> |
|
|
|
{/* <Row style={{ marginBottom: "10px" }}> |
|
|
|
|
|
|
|
<Col span={24}> |
|
|
|
|
|
|
|
<InputNumber |
|
|
|
|
|
|
|
min={0} |
|
|
|
|
|
|
|
max={maxSlider} |
|
|
|
|
|
|
|
value={sliderValue[0]} |
|
|
|
|
|
|
|
style={{ width: '100%' }} |
|
|
|
|
|
|
|
placeholder={"Min"} |
|
|
|
|
|
|
|
onChange={(value) => { |
|
|
|
|
|
|
|
setSelectedKeys([value]) |
|
|
|
|
|
|
|
handleSlide(dataIndex, value, confirm)} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</Col> |
|
|
|
|
|
|
|
</Row> */} |
|
|
|
|
|
|
|
{/* <Row> |
|
|
|
|
|
|
|
<Col span={24}> |
|
|
|
|
|
|
|
<InputNumber |
|
|
|
|
|
|
|
min={0} |
|
|
|
|
|
|
|
max={maxSlider} |
|
|
|
|
|
|
|
style={{ width: '100%' }} |
|
|
|
|
|
|
|
placeholder={"Max"} |
|
|
|
|
|
|
|
onChange={(value) => { |
|
|
|
|
|
|
|
console.log(value) |
|
|
|
|
|
|
|
setSelectedKeys([value]) |
|
|
|
|
|
|
|
handleSlide(dataIndex, value, confirm)} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</Col> |
|
|
|
|
|
|
|
</Row> */} |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
)}, |
|
|
|
)}, |
|
|
|
onFilter: (value, record) => { |
|
|
|
onFilter: (value, record) => { |
|
|
@ -203,7 +171,7 @@ const TableDashboardV1 = () => { |
|
|
|
setTimeout(() => searchInput.current?.select(), 100); |
|
|
|
setTimeout(() => searchInput.current?.select(), 100); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
render: (text) => |
|
|
|
render: (text, record) => |
|
|
|
searchedColumn === dataIndex ? ( |
|
|
|
searchedColumn === dataIndex ? ( |
|
|
|
<Highlighter |
|
|
|
<Highlighter |
|
|
|
highlightStyle={{ |
|
|
|
highlightStyle={{ |
|
|
@ -215,10 +183,82 @@ const TableDashboardV1 = () => { |
|
|
|
textToHighlight={text ? text.toString() : ''} |
|
|
|
textToHighlight={text ? text.toString() : ''} |
|
|
|
/> |
|
|
|
/> |
|
|
|
) : ( |
|
|
|
) : ( |
|
|
|
text |
|
|
|
<> |
|
|
|
|
|
|
|
<Link to={`/dashboard-project/${record.id}/${record.lastGanttId}`}> |
|
|
|
|
|
|
|
{record.kode_sortname} <br /> {text} |
|
|
|
|
|
|
|
</Link> |
|
|
|
|
|
|
|
</> |
|
|
|
), |
|
|
|
), |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const filterDate = (dataIndex) => ({ |
|
|
|
|
|
|
|
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => { |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<div |
|
|
|
|
|
|
|
style={{ |
|
|
|
|
|
|
|
padding: 8, |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<InputNumber |
|
|
|
|
|
|
|
ref={searchInput} |
|
|
|
|
|
|
|
placeholder={`Year`} |
|
|
|
|
|
|
|
value={selectedKeys[0]} |
|
|
|
|
|
|
|
min={2020} |
|
|
|
|
|
|
|
max={2050} |
|
|
|
|
|
|
|
//onChange={(e) => setSelectedKeys(e.target.value ? [e.target.value] : [])}
|
|
|
|
|
|
|
|
onChange={(e) => console.log(e)} |
|
|
|
|
|
|
|
style={{ |
|
|
|
|
|
|
|
marginBottom: 8, |
|
|
|
|
|
|
|
display: 'block', |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
<Space> |
|
|
|
|
|
|
|
<Button |
|
|
|
|
|
|
|
type="primary" |
|
|
|
|
|
|
|
onClick={() => handleSearch(selectedKeys, confirm, dataIndex)} |
|
|
|
|
|
|
|
icon={<SearchOutlined />} |
|
|
|
|
|
|
|
size="small" |
|
|
|
|
|
|
|
style={{ |
|
|
|
|
|
|
|
width: 90, |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
Search |
|
|
|
|
|
|
|
</Button> |
|
|
|
|
|
|
|
<Button |
|
|
|
|
|
|
|
onClick={() => clearFilters && handleReset(clearFilters)} |
|
|
|
|
|
|
|
size="small" |
|
|
|
|
|
|
|
style={{ |
|
|
|
|
|
|
|
width: 90, |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
Reset |
|
|
|
|
|
|
|
</Button> |
|
|
|
|
|
|
|
<Button |
|
|
|
|
|
|
|
type="link" |
|
|
|
|
|
|
|
size="small" |
|
|
|
|
|
|
|
onClick={() => { |
|
|
|
|
|
|
|
confirm({ |
|
|
|
|
|
|
|
closeDropdown: false, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
setSearchText(selectedKeys[0]); |
|
|
|
|
|
|
|
setSearchedColumn(dataIndex); |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
</Button> |
|
|
|
|
|
|
|
</Space> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
)}, |
|
|
|
|
|
|
|
onFilter: (value, record) => { |
|
|
|
|
|
|
|
return record[dataIndex].toString().toLowerCase().includes(value.toLowerCase()) |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
onFilterDropdownVisibleChange: (visible) => { |
|
|
|
|
|
|
|
if (visible) { |
|
|
|
|
|
|
|
setTimeout(() => searchInput.current?.select(), 100); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const getProjects = async () => { |
|
|
|
const getProjects = async () => { |
|
|
|
const URL = `${BASE_OSPRO}/api/project/list` |
|
|
|
const URL = `${BASE_OSPRO}/api/project/list` |
|
|
|
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response) |
|
|
|
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response) |
|
|
@ -226,6 +266,9 @@ const TableDashboardV1 = () => { |
|
|
|
if (result.data.code == 200) { |
|
|
|
if (result.data.code == 200) { |
|
|
|
setDataTable(result.data.data); |
|
|
|
setDataTable(result.data.data); |
|
|
|
result.data.manpowers != undefined ? SET_MANPOWERS(result.data.manpowers) : SET_MANPOWERS(0) |
|
|
|
result.data.manpowers != undefined ? SET_MANPOWERS(result.data.manpowers) : SET_MANPOWERS(0) |
|
|
|
|
|
|
|
SET_MAXPLANNEDCOST(Math.max(...result.data.data.map(o => o.plannedCost))) |
|
|
|
|
|
|
|
SET_MAXACTUALCOST(Math.max(...result.data.data.map(o => o.actualCost))) |
|
|
|
|
|
|
|
SET_MAXCOSTVARIANCE(Math.max(...result.data.data.map(o => o.costVariance))) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -251,6 +294,7 @@ const TableDashboardV1 = () => { |
|
|
|
title: 'Planned Interval', |
|
|
|
title: 'Planned Interval', |
|
|
|
dataIndex: 'plannedInterval', |
|
|
|
dataIndex: 'plannedInterval', |
|
|
|
key: 'plannedInterval', |
|
|
|
key: 'plannedInterval', |
|
|
|
|
|
|
|
...filterDate('plannedInterval'), |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
{ |
|
|
|
title: 'Manpower', |
|
|
|
title: 'Manpower', |
|
|
@ -259,26 +303,29 @@ const TableDashboardV1 = () => { |
|
|
|
render: (text) => { |
|
|
|
render: (text) => { |
|
|
|
return `${text}/${MANPOWERS}` |
|
|
|
return `${text}/${MANPOWERS}` |
|
|
|
}, |
|
|
|
}, |
|
|
|
...slider('manpower') |
|
|
|
...slider('manpower', MANPOWERS) |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
{ |
|
|
|
title: 'Budget Project', |
|
|
|
title: 'Budget Project', |
|
|
|
dataIndex: 'plannedCost', |
|
|
|
dataIndex: 'plannedCost', |
|
|
|
key: 'plannedCost', |
|
|
|
key: 'plannedCost', |
|
|
|
render: (text) => <a>{formatRibuanDecimal(text)}</a>, |
|
|
|
render: (text) => <a>{formatRibuanDecimal(text)}</a>, |
|
|
|
filterDropdown: slider |
|
|
|
...slider('plannedCost', MAXPLANNEDCOST) |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
{ |
|
|
|
title: 'Actual Cost', |
|
|
|
title: 'Actual Cost', |
|
|
|
dataIndex: 'actualCost', |
|
|
|
dataIndex: 'actualCost', |
|
|
|
key: 'actualCost', |
|
|
|
key: 'actualCost', |
|
|
|
render: (text) => <a>{formatRibuanDecimal(text)}</a>, |
|
|
|
render: (text) => <a>{formatRibuanDecimal(text)}</a>, |
|
|
|
|
|
|
|
...slider('actualCost', MAXACTUALCOST) |
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
{ |
|
|
|
title: 'Cost Variance', |
|
|
|
title: 'Cost Variance', |
|
|
|
dataIndex: 'costVariance', |
|
|
|
dataIndex: 'costVariance', |
|
|
|
key: 'costVariance', |
|
|
|
key: 'costVariance', |
|
|
|
render: (text) => <a>{formatRibuanDecimal(text)}</a>, |
|
|
|
render: (text) => <a>{formatRibuanDecimal(text)}</a>, |
|
|
|
|
|
|
|
...slider('costVariance', MAXCOSTVARIANCE) |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
{ |
|
|
|
title: 'Cost Health', |
|
|
|
title: 'Cost Health', |
|
|
@ -302,7 +349,8 @@ const TableDashboardV1 = () => { |
|
|
|
key: 'progress', |
|
|
|
key: 'progress', |
|
|
|
render: (text) => { |
|
|
|
render: (text) => { |
|
|
|
return <Badge color={parseInt(text) > 74 ? 'success' : text > 49 ? 'warning' : 'danger'}>{text}%</Badge> |
|
|
|
return <Badge color={parseInt(text) > 74 ? 'success' : text > 49 ? 'warning' : 'danger'}>{text}%</Badge> |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
...slider('progress', 100) |
|
|
|
}, |
|
|
|
}, |
|
|
|
]; |
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|