Skip to content
Snippets Groups Projects
Commit 76ab298e authored by Miguel Angelo Salerno's avatar Miguel Angelo Salerno
Browse files

add download option for tables

parent 2bca6d16
Branches
No related tags found
2 merge requests!41Homologa,!39New fixes
...@@ -38,7 +38,9 @@ function BottomTableComponent(props) { ...@@ -38,7 +38,9 @@ function BottomTableComponent(props) {
const [loadingData, setLoadingData] = useState(true); const [loadingData, setLoadingData] = useState(true);
const [chartData, setChartData] = useState([]); const [chartData, setChartData] = useState([]);
const [tableData, setTableData] = useState([]); const [tableData, setTableData] = useState([]);
const [formattedData, setFormattedData] = useState([]);
const [selectedFilters, setSelectedFilters] = useState([]); const [selectedFilters, setSelectedFilters] = useState([]);
const [downloadFile, setdownloadFile] = useState([]);
useEffect(() => { useEffect(() => {
const chartYearFilters = { const chartYearFilters = {
...@@ -61,10 +63,35 @@ function BottomTableComponent(props) { ...@@ -61,10 +63,35 @@ function BottomTableComponent(props) {
); );
}, [filtersLocation, filtersEducation, chartInfo]); }, [filtersLocation, filtersEducation, chartInfo]);
function CSV(array) {
// Use first element to choose the keys and the order
var keys = Object.keys(array[0])
// Build header
var result = keys.join(";") + "\n"
// Add the rows
array.forEach((obj) => {
result += keys.map(k => obj[k]).join(";") + "\n"
})
return result
}
useEffect(() => { useEffect(() => {
formatData(chartData) setTableData(formatData(chartData))
}, [chartData]) }, [chartData])
useEffect(() => {
setFormattedData(formatDownloadData(tableData))
}, [tableData])
useEffect(() => {
if (formattedData.length !== 0) {
setdownloadFile(CSV(formattedData))
}
}, [formattedData])
useEffect(() => { useEffect(() => {
const filters = Object.entries(filtersEducation) const filters = Object.entries(filtersEducation)
...@@ -139,7 +166,20 @@ function BottomTableComponent(props) { ...@@ -139,7 +166,20 @@ function BottomTableComponent(props) {
} }
} }
setTableData(newTableData) return newTableData
}
function formatDownloadData(data) {
const downloadData = data.map((course) => {
return {
curso: course.course_name,
concluintes: course.finished_total,
nao_concluintes: course.not_finished_total,
total: course.finished_total + course.not_finished_total
}
})
return downloadData
} }
return ( return (
...@@ -165,6 +205,14 @@ function BottomTableComponent(props) { ...@@ -165,6 +205,14 @@ function BottomTableComponent(props) {
{ {
chartData.length === 0 ? chartData.length === 0 ?
<h3 className="no-data">Sem dados</h3> : <h3 className="no-data">Sem dados</h3> :
<>
<a
href={`data:text/csv;charset=utf-8,` + encodeURI(downloadFile)}
download="tabela.csv"
className="download-button"
>
Download
</a>
<div className="table-container"> <div className="table-container">
<div className="table-overflow-container"> <div className="table-overflow-container">
<table cellSpacing="0" cellPadding="0"> <table cellSpacing="0" cellPadding="0">
...@@ -194,6 +242,7 @@ function BottomTableComponent(props) { ...@@ -194,6 +242,7 @@ function BottomTableComponent(props) {
</table> </table>
</div> </div>
</div> </div>
</>
} }
<p>{chartInfo.notes}</p> <p>{chartInfo.notes}</p>
</div> </div>
......
...@@ -37,7 +37,9 @@ function SideTableComponent(props) { ...@@ -37,7 +37,9 @@ function SideTableComponent(props) {
const [loadingData, setLoadingData] = useState(true); const [loadingData, setLoadingData] = useState(true);
const [chartData, setChartData] = useState([]); const [chartData, setChartData] = useState([]);
const [formattedData, setformattedData] = useState([]);
const [selectedFilters, setSelectedFilters] = useState([]); const [selectedFilters, setSelectedFilters] = useState([]);
const [downloadFile, setdownloadFile] = useState([]);
useEffect(() => { useEffect(() => {
const chartYearFilters = { const chartYearFilters = {
...@@ -89,6 +91,45 @@ function SideTableComponent(props) { ...@@ -89,6 +91,45 @@ function SideTableComponent(props) {
setSelectedFilters(formattedFilters) setSelectedFilters(formattedFilters)
}, [filtersEducation]) }, [filtersEducation])
function CSV(array) {
// Use first element to choose the keys and the order
var keys = Object.keys(array[0])
// Build header
var result = keys.join(";") + "\n"
// Add the rows
array.forEach((obj) => {
result += keys.map(k => obj[k]).join(";") + "\n"
})
return result
}
function formatData(data) {
const newData = data.map((course) => {
const lowerName = course.course_name.toLowerCase()
const name = lowerName.charAt(0).toUpperCase() + lowerName.slice(1)
return {
name: name,
total: course.total,
percentage: course.percentage
}
})
return newData
}
useEffect(() => {
setformattedData(formatData(chartData))
}, [chartData])
useEffect(() => {
if (formattedData.length !== 0) {
setdownloadFile(CSV(formattedData))
}
}, [formattedData])
return ( return (
<> <>
{ loadingData ? { loadingData ?
...@@ -105,13 +146,20 @@ function SideTableComponent(props) { ...@@ -105,13 +146,20 @@ function SideTableComponent(props) {
<h3>{chartInfo.title}</h3> <h3>{chartInfo.title}</h3>
<h4>{`${location} - ${chartInfo.years[0]}`}</h4> <h4>{`${location} - ${chartInfo.years[0]}`}</h4>
{ {
selectedFilters !== '' ? selectedFilters === '' ? null :
<h4>{selectedFilters}</h4> : <h4>{selectedFilters}</h4>
null
} }
{ {
chartData.length === 0 ? chartData.length === 0 ?
<h3 className="no-data">Sem dados</h3> : <h3 className="no-data">Sem dados</h3> :
<>
<a
href={`data:text/csv;charset=utf-8,` + encodeURI(downloadFile)}
download="tabela.csv"
className="download-button"
>
Download
</a>
<div className="table-container"> <div className="table-container">
<div className="table-overflow-container"> <div className="table-overflow-container">
<table cellSpacing="0" cellPadding="0"> <table cellSpacing="0" cellPadding="0">
...@@ -123,12 +171,10 @@ function SideTableComponent(props) { ...@@ -123,12 +171,10 @@ function SideTableComponent(props) {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{ chartData.map((course, index) => { { formattedData.map((course, index) => {
const lowerName = course.course_name.toLowerCase()
const name = lowerName.charAt(0).toUpperCase() + lowerName.slice(1)
return ( return (
<tr key={index} className={`${index % 2 !== 0 ? 'tr-alt' : ''}`}> <tr key={index} className={`${index % 2 !== 0 ? 'tr-alt' : ''}`}>
<td>{name}</td> <td>{course.name}</td>
<td>{course.total}</td> <td>{course.total}</td>
<td>{course.percentage}</td> <td>{course.percentage}</td>
</tr> </tr>
...@@ -138,6 +184,7 @@ function SideTableComponent(props) { ...@@ -138,6 +184,7 @@ function SideTableComponent(props) {
</table> </table>
</div> </div>
</div> </div>
</>
} }
<p>{chartInfo.notes}</p> <p>{chartInfo.notes}</p>
</div> </div>
......
.bottom-table-container { .bottom-table-container {
background: #fff; background: #fff;
margin-top: 30px; margin-top: 30px;
padding: 40px; padding: 40px 40px 20px 40px;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
font-family: 'Montserrat'; font-family: 'Montserrat';
.table-content-container { .table-content-container {
text-align: center;
h3 { h3 {
margin: 0; margin: 0;
color: #3c3c3b; color: #3c3c3b;
...@@ -31,6 +33,7 @@ ...@@ -31,6 +33,7 @@
max-height: 440px; max-height: 440px;
border-radius: 10px; border-radius: 10px;
overflow: hidden; overflow: hidden;
margin-top: 10px;
.table-overflow-container { .table-overflow-container {
max-height: 440px; max-height: 440px;
...@@ -77,9 +80,24 @@ ...@@ -77,9 +80,24 @@
} }
} }
.download-button {
padding: 2px 8px;
background-color: #7a60a6;
color: #fff;
text-decoration: none;
font-family: 'Nunito';
font-size: 14px;
font-weight: bold;
border: 0;
border-radius: 8px;
transition: filter 0.2s;
&:hover {
filter: brightness(0.9);
}
}
p { p {
text-align: center;
margin: 30px 0 0 0; margin: 30px 0 0 0;
font-size: 11px; font-size: 11px;
line-height: 14px; line-height: 14px;
...@@ -97,6 +115,18 @@ ...@@ -97,6 +115,18 @@
color: #fff; color: #fff;
} }
.download-button {
background-color: #000;
border: 2px solid #ffff00;
color: #ffff00;
transition: background-color 0.2s;
&:hover {
background-color: #ffff00;
color: #000;
}
}
.table-container { .table-container {
box-shadow: 0 0 0 1px #fff; box-shadow: 0 0 0 1px #fff;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
height: 90%; height: 90%;
padding: 20px; padding: 20px;
position: relative; position: relative;
text-align: center;
h3 { h3 {
margin: 0; margin: 0;
...@@ -36,6 +37,7 @@ ...@@ -36,6 +37,7 @@
max-height: 440px; max-height: 440px;
border-radius: 10px; border-radius: 10px;
overflow: hidden; overflow: hidden;
margin-top: 10px;
.table-overflow-container { .table-overflow-container {
max-height: 440px; max-height: 440px;
...@@ -82,9 +84,26 @@ ...@@ -82,9 +84,26 @@
} }
} }
.download-button {
padding: 2px 8px;
background-color: #7a60a6;
color: #fff;
text-decoration: none;
font-family: 'Nunito';
font-size: 14px;
font-weight: bold;
border: 0;
border-radius: 8px;
transition: filter 0.2s;
&:hover {
filter: brightness(0.9);
}
}
p { p {
position: absolute; position: absolute;
text-align: left;
bottom: 0; bottom: 0;
margin: 30px 0 0 0; margin: 30px 0 0 0;
padding-right: 20px; padding-right: 20px;
...@@ -104,6 +123,18 @@ ...@@ -104,6 +123,18 @@
color: #fff; color: #fff;
} }
.download-button {
background-color: #000;
border: 2px solid #ffff00;
color: #ffff00;
transition: background-color 0.2s;
&:hover {
background-color: #ffff00;
color: #000;
}
}
.table-container { .table-container {
box-shadow: 0 0 0 1px #fff; box-shadow: 0 0 0 1px #fff;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment