-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #73 from fga-eps-mds/142-gerar-relatorios-de-movim…
…entacoes 142 gerar relatorios de movimentacoes
- Loading branch information
Showing
9 changed files
with
582 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
import { | ||
Document, | ||
Page, | ||
Text, | ||
View, | ||
StyleSheet, | ||
Image, | ||
Font, | ||
} from '@react-pdf/renderer'; | ||
import { movement } from '@/pages/movements/MovementControl'; | ||
import { formatDate } from '@/utils/format-date'; | ||
|
||
interface MovementsPdfProps { | ||
movements: movement[]; | ||
title: string; | ||
} | ||
|
||
Font.register({ | ||
family: 'Arial', | ||
fonts: [ | ||
{ | ||
src: 'https://fonts.cdnfonts.com/s/29107/ARIALMTMEDIUM.woff', | ||
fontStyle: 'normal', | ||
fontWeight: 400, | ||
}, | ||
{ | ||
src: 'https://fonts.cdnfonts.com/s/29107/ARIALBOLDMT.woff', | ||
fontStyle: 'bold', | ||
fontWeight: 700, | ||
}, | ||
], | ||
}); | ||
|
||
export function MovementsPDF({ title, movements }: MovementsPdfProps) { | ||
const styles = StyleSheet.create({ | ||
page: { | ||
flexDirection: 'column', | ||
padding: 20, | ||
fontFamily: 'Arial', | ||
}, | ||
header: { | ||
display: 'flex', | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
}, | ||
caption: { | ||
fontSize: 8, | ||
}, | ||
title: { | ||
paddingTop: 24, | ||
textTransform: 'uppercase', | ||
fontSize: 20, | ||
fontWeight: 700, | ||
}, | ||
subtitle: { | ||
fontSize: 12, | ||
paddingBottom: 24, | ||
}, | ||
locale: { | ||
paddingBottom: 16, | ||
fontSize: 12, | ||
fontWeight: 700, | ||
}, | ||
logo: { | ||
width: 50, | ||
height: 66, | ||
marginBottom: 4, | ||
}, | ||
tableHeader: { | ||
backgroundColor: '#D8D8D8', | ||
flexDirection: 'row', | ||
marginTop: 8, | ||
borderBottomWidth: 1, | ||
borderTopWidth: 1, | ||
borderBottomColor: '#000', | ||
minHeight: 24, | ||
alignItems: 'center', | ||
}, | ||
columnHeader: { | ||
color: '#000', | ||
flex: 1, | ||
textAlign: 'center', | ||
fontSize: 8, | ||
fontWeight: 'bold', | ||
}, | ||
tableRow: { | ||
flexDirection: 'row', | ||
borderBottomWidth: 1, | ||
borderBottomColor: '#000', | ||
minHeight: 24, | ||
alignItems: 'center', | ||
}, | ||
rowData: { | ||
fontSize: 8, | ||
flex: 1, | ||
textAlign: 'center', | ||
paddingRight: 15, | ||
}, | ||
signature: { | ||
marginTop: 200, | ||
display: 'flex', | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
}, | ||
}); | ||
|
||
const formattedEmissionDate = (): string => { | ||
const currentEmissionDate = new Date(); | ||
const emissionDay = currentEmissionDate | ||
.getDate() | ||
.toString() | ||
.padStart(2, '0'); | ||
const emissionMonth = (currentEmissionDate.getMonth() + 1) | ||
.toString() | ||
.padStart(2, '0'); | ||
const emissionYear = currentEmissionDate | ||
.getFullYear() | ||
.toString() | ||
.padStart(4, '0'); | ||
|
||
const emissionHours = currentEmissionDate | ||
.getHours() | ||
.toString() | ||
.padStart(2, '0'); | ||
const emissionMinutes = currentEmissionDate | ||
.getMinutes() | ||
.toString() | ||
.padStart(2, '0'); | ||
const emissionSeconds = currentEmissionDate | ||
.getSeconds() | ||
.toString() | ||
.padStart(2, '0'); | ||
|
||
return `${emissionDay}/${emissionMonth}/${emissionYear} - ${emissionHours}:${emissionMinutes}:${emissionSeconds}`; | ||
}; | ||
|
||
return ( | ||
<Document> | ||
<Page size="A4" style={styles.page} orientation="landscape"> | ||
<View style={styles.header}> | ||
<Image src="/PoliciaCivilLogo.jpeg" style={styles.logo} /> | ||
<Text style={styles.caption}>ESTADO DE GOIÁS</Text> | ||
<Text style={styles.caption}>DIRETORIA GERAL DA POLÍCIA CIVIL</Text> | ||
<Text style={styles.caption}> | ||
SUPERINTENDÊNCIA DE GESTÃO INTEGRADA | ||
</Text> | ||
<Text style={styles.caption}> | ||
DIVISÃO DE SUPORTE TÉCNICO EM INFORMÁTICA | ||
</Text> | ||
<Text style={styles.title}>{title}</Text> | ||
<Text style={styles.subtitle}> | ||
Sistema de Controle Interno da DSTI | ||
</Text> | ||
</View> | ||
<Text style={styles.caption}> | ||
Data da emissão: {formattedEmissionDate()} | ||
</Text> | ||
<View style={styles.tableHeader}> | ||
<Text style={{ ...styles.columnHeader, maxWidth: 24 }}>Item</Text> | ||
<Text style={{ ...styles.columnHeader, minWidth: 80, maxWidth: 100 }}> | ||
Tombamento | ||
</Text> | ||
<Text style={{ ...styles.columnHeader, minWidth: 60, maxWidth: 80 }}> | ||
Tipo | ||
</Text> | ||
<Text style={{ ...styles.columnHeader, minWidth: 45, maxWidth: 55 }}> | ||
Marca | ||
</Text> | ||
<Text style={{ ...styles.columnHeader, minWidth: 70 }}> | ||
Descrição | ||
</Text> | ||
<Text style={{ ...styles.columnHeader, minWidth: 70, maxWidth: 90 }}> | ||
Lotação | ||
</Text> | ||
<Text style={{ ...styles.columnHeader, minWidth: 60, maxWidth: 80 }}> | ||
Status | ||
</Text> | ||
<Text style={{ ...styles.columnHeader, maxWidth: 56 }}> | ||
Data da Movimentação | ||
</Text> | ||
</View> | ||
{movements.map((move: movement, moveIndex: number) => | ||
move.equipments.map((equipment: any, equipmentIndex: number) => ( | ||
<View style={styles.tableRow} key={equipment?.id}> | ||
<Text style={{ ...styles.rowData, maxWidth: 24 }}> | ||
{equipmentIndex + 1} | ||
</Text> | ||
<Text style={{ ...styles.rowData, minWidth: 80, maxWidth: 100 }}> | ||
{equipment?.tippingNumber} | ||
</Text> | ||
<Text style={{ ...styles.rowData, minWidth: 60, maxWidth: 80 }}> | ||
{equipment?.type?.name} | ||
</Text> | ||
<Text style={{ ...styles.rowData, minWidth: 45, maxWidth: 55 }}> | ||
{equipment?.brand?.name} | ||
</Text> | ||
<Text style={{ ...styles.rowData, textAlign: 'center' }}> | ||
{equipment?.description} | ||
</Text> | ||
<Text style={{ ...styles.rowData, minWidth: 70, maxWidth: 90 }}> | ||
{move.destination.name} | ||
</Text> | ||
<Text style={{ ...styles.rowData, minWidth: 60, maxWidth: 80 }}> | ||
{equipment?.situacao} | ||
</Text> | ||
<Text style={{ ...styles.rowData, maxWidth: 56 }}> | ||
{formatDate(move?.date)} | ||
</Text> | ||
</View> | ||
)) | ||
)} | ||
</Page> | ||
</Document> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { Flex, Text, Button } from '@chakra-ui/react'; | ||
import { PDFDownloadLink } from '@react-pdf/renderer'; | ||
import { MdDescription } from 'react-icons/md'; | ||
import { useCallback } from 'react'; | ||
import { CSVLink } from 'react-csv'; | ||
import { utils, writeFile } from 'xlsx'; | ||
import { Modal } from '@/components/modal'; | ||
import { movement } from '@/pages/movements/MovementControl'; | ||
import { formatDate } from '@/utils/format-date'; | ||
import { MovementsPDF } from './document'; | ||
|
||
type ReportModalProps = { | ||
isOpen: boolean; | ||
onClose(): void; | ||
type: string; | ||
movements: movement[]; | ||
}; | ||
|
||
export function ReportModal({ | ||
isOpen, | ||
onClose, | ||
type, | ||
movements, | ||
}: ReportModalProps) { | ||
const onCloseCallback = () => { | ||
onClose(); | ||
}; | ||
|
||
const formattedDate = formatDate(new Date()); | ||
|
||
const exportFile = useCallback(() => { | ||
const ws = utils.json_to_sheet(movements); | ||
const wb = utils.book_new(); | ||
utils.book_append_sheet(wb, ws, 'Data'); | ||
writeFile(wb, `relatorio_movimentacoes_${formattedDate}.xls`); | ||
}, [formattedDate, movements]); | ||
|
||
return ( | ||
<Modal | ||
title="Relatório de movimentações" | ||
isOpen={isOpen} | ||
onClose={onCloseCallback} | ||
size="2xl" | ||
> | ||
<Text | ||
textAlign="center" | ||
mt="1rem" | ||
style={{ display: 'flex', alignItems: 'center' }} | ||
fontWeight="bold" | ||
fontSize="larger" | ||
> | ||
<MdDescription size={40} /> | ||
{`Relatório em ${type}`} | ||
</Text> | ||
<Flex gap="4rem" mt="2rem" mb="1rem" justify="center"> | ||
<Button variant="secondary" onClick={onCloseCallback}> | ||
Cancelar | ||
</Button> | ||
{type === 'pdf' && ( | ||
<PDFDownloadLink | ||
document={ | ||
<MovementsPDF | ||
title="Relatório de movimentações" | ||
movements={movements} | ||
/> | ||
} | ||
fileName={`relatorio_movimentacoes_${formattedDate}`} | ||
> | ||
<Button>Imprimir</Button> | ||
</PDFDownloadLink> | ||
)} | ||
{type === 'csv' && ( | ||
<CSVLink | ||
data={movements} | ||
type="csv" | ||
target="_blank" | ||
filename={`relatorio_movimentacoes_${formattedDate}.csv`} | ||
separator=";" | ||
> | ||
<Button>Imprimir</Button> | ||
</CSVLink> | ||
)} | ||
|
||
{type === 'xls' && <Button onClick={exportFile}>Imprimir</Button>} | ||
</Flex> | ||
</Modal> | ||
); | ||
} |
Oops, something went wrong.