Created
April 26, 2019 23:46
-
-
Save john-raymon/a28a4927881817b45f08e41ff5cb9f1b to your computer and use it in GitHub Desktop.
Component responsible for rendering PDF document using React-PDF
This file contains hidden or 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
| import React, { Component, PureComponent } from 'react' | |
| import { connect } from 'react-redux' | |
| import { Page, Text, View, Document, StyleSheet, PDFViewer, Image } from '@react-pdf/renderer'; | |
| // Utils | |
| import createUUID from '../util/createUUID' | |
| import agent from '../util/agent' | |
| // Images | |
| import logo from '../images/small_logo.png'; | |
| // Selectors | |
| import getSettings from '../state/selectors/getSettings' | |
| // Redux Actions | |
| import { fetchSettings } from '../state/actions/applicationActions' | |
| const calculateRoomMeasurements = (length, width, height) => { | |
| let SFFloor = 0 | |
| let SFCeiling = 0 | |
| let SFWalls = 0 | |
| let SFWallsCeiling = 0 | |
| let SFWallsFloorCeiling = 0 | |
| let LFFloorPerim = 0 | |
| let LFCeilingPerim = 0 | |
| let LFFloorCeilingPerim = 0 | |
| SFFloor = length * width | |
| SFCeiling = length * width | |
| SFWalls = ((length * height) + (width * height)) * 2 | |
| SFWallsCeiling = SFWalls + SFCeiling | |
| SFWallsFloorCeiling = SFWalls + SFFloor + SFCeiling | |
| LFFloorPerim = (length * 2) + (width * 2) | |
| LFCeilingPerim = (length * 2) + (width * 2) | |
| LFFloorCeilingPerim = LFFloorPerim + LFCeilingPerim | |
| return { | |
| SFFloor, | |
| SFCeiling, | |
| SFWalls, | |
| SFWallsCeiling, | |
| SFWallsFloorCeiling, | |
| LFFloorPerim, | |
| LFCeilingPerim, | |
| LFFloorCeilingPerim | |
| } | |
| } | |
| const styles = StyleSheet.create({ | |
| page: { | |
| flexDirection: 'column', | |
| }, | |
| headerContainer: { | |
| flexDirection: "row", | |
| padding: 40, | |
| width: "100%", | |
| alignItems: 'center' | |
| }, | |
| smallText: { | |
| fontSize: 10, | |
| paddingBottom: 1, | |
| } | |
| }); | |
| const PDFdocument = ({ | |
| companyName, | |
| companyPhoneNumber, | |
| companyEmail, | |
| companyZip, | |
| companyAddress, | |
| companyCityState, | |
| companyOpeningStatement, | |
| allRooms | |
| }) => { | |
| return ( | |
| <Document> | |
| <Page size="A4" style={styles.page}> | |
| <View style={styles.headerContainer} fixed> | |
| <View style={{ width: "10%"}}> | |
| <Image | |
| src={logo} | |
| style={{width: "100%"}} | |
| /> | |
| </View> | |
| <View style={{ marginLeft: "2%" }}> | |
| <Text | |
| style={styles.smallText} | |
| > | |
| { companyName } | |
| </Text> | |
| <Text style={styles.smallText}> | |
| {`Telephone | ${companyPhoneNumber}`} | |
| </Text> | |
| <Text style={styles.smallText}> | |
| {`Billing Email | ${companyEmail}`} | |
| </Text> | |
| <Text style={styles.smallText}> | |
| {`Mailing Address | ${companyAddress} ${companyCityState} ${companyZip}`} | |
| </Text> | |
| </View> | |
| </View> | |
| <View style={{ flexDirection: "column", justifyContent: "center", flexGrow: 1 }}> | |
| <View style={{flexDirection: "row", width: "80%", alignSelf: "center", paddingVertical: 20}}> | |
| <Text style={[styles.smallText, {width: "30%"}]}> | |
| Customer Name | |
| </Text> | |
| <Text style={[styles.smallText, {width: "70%", flexWrap: "wrap"}]}> | |
| { "John Mendez" } | |
| </Text> | |
| </View> | |
| <View style={{flexDirection: "row", width: "80%", alignSelf: "center", paddingVertical: 20}}> | |
| <Text style={[styles.smallText, {width: "30%"}]}> | |
| Property Address | |
| </Text> | |
| <View style={{flexDirection: "column", width: "70%"}}> | |
| <Text style={styles.smallText}> | |
| { "11 ChestNut Circle" } | |
| </Text> | |
| <Text style={styles.smallText}> | |
| { "HollyWood, Fl 33026 " } | |
| </Text> | |
| </View> | |
| </View> | |
| <View style={{flexDirection: "row", width: "80%", alignSelf: "center", paddingVertical: 20}}> | |
| <Text style={[styles.smallText, {width: "30%"}]}> | |
| Insurance Carrier | |
| </Text> | |
| <Text style={[styles.smallText, {width: "70%", flexWrap: "wrap"}]}> | |
| { "Gieco" } | |
| </Text> | |
| </View> | |
| <View style={{flexDirection: "row", width: "80%", alignSelf: "center", paddingVertical: 20}}> | |
| <Text style={[styles.smallText, {width: "30%"}]}> | |
| Policy Number | |
| </Text> | |
| <Text style={[styles.smallText, {width: "70%", flexWrap: "wrap"}]}> | |
| { "555555" } | |
| </Text> | |
| </View> | |
| <Text style={[styles.smallText, { width: "80%", borderTop: "1 solid black", alignSelf: "center", paddingTop: 10 }]}> | |
| { companyOpeningStatement } | |
| </Text> | |
| </View> | |
| <View style={{ flexDirection: "column", width: "90%", alignSelf: "center", minHeight: 500 }} break> | |
| { | |
| allRooms.map((room) => { | |
| return ( | |
| <View style={{ flexDirection: "column", width:"100%", marginBottom: 30}}> | |
| <View style={{flexDirection: "row", justifyContent: "space-between", borderBottom: "1 solid black", paddingBottom: 5, marginBottom: 5 }}> | |
| <Text style={styles.smallText}> | |
| { room.name } | |
| </Text> | |
| <Text style={styles.smallText}> | |
| {`L: ${room.length} | W: ${room.width } | H: ${room.height}` } | |
| </Text> | |
| </View> | |
| <View style={{ flexDirection: "row", justifyContent: "center", borderBottom: "1 solid gray", paddingBottom: 5, marginBottom: 5}}> | |
| <Text style={[styles.smallText, {width: "20%"}]}> | |
| Qty | |
| </Text> | |
| <Text style={[styles.smallText, {width: "50%"}]}> | |
| Description | |
| </Text> | |
| <Text style={[styles.smallText, {width: "10%"}]}> | |
| Labor Cost | |
| </Text> | |
| <Text style={[styles.smallText, {width: "10%"}]}> | |
| Unit Cost | |
| </Text> | |
| <Text style={[styles.smallText, {width: "10%", textAlign: "right"}]}> | |
| Total | |
| </Text> | |
| </View> | |
| { | |
| room.lineItems.map((item) => { | |
| return ( | |
| <View style={{ flexDirection: "row", justifyContent: "center", paddingBottom: 10}}> | |
| <Text style={[styles.smallText, {width: "20%"}]}> | |
| {`${item.quantity} ${item.uom}`} | |
| </Text> | |
| <Text style={[styles.smallText, {width: "50%", flexWrap: "wrap", paddingRight: 1 }]}> | |
| { item.description } | |
| </Text> | |
| <Text style={[styles.smallText, {width: "10%"}]}> | |
| { item.laborCost } | |
| </Text> | |
| <Text style={[styles.smallText, {width: "10%"}]}> | |
| { item.materialCost } | |
| </Text> | |
| <Text style={[styles.smallText, {width: "10%", textAlign: "right"}]}> | |
| { item.total } | |
| </Text> | |
| </View> | |
| ) | |
| }) | |
| } | |
| <View style={{flexDirection: "row", justifyContent: "space-between", borderBottom: "1 solid black", paddingBottom: 5, marginBottom: 5 }}> | |
| <Text style={styles.smallText}> | |
| {`Totals - ${room.name}`} | |
| </Text> | |
| <Text style={styles.smallText}> | |
| {`Labor Totals: $${room.roomTotals.totalLabor} | Unit Totals: $${room.roomTotals.totalMaterial} | Totals: $${room.roomTotals.totalCost}`} | |
| </Text> | |
| </View> | |
| </View> | |
| ) | |
| }) | |
| } | |
| </View> | |
| <View style={{ flexDirection: "column", width: "80%", position: "absolute", bottom: 10, borderTop: "1 solid gray", paddingVertical: 10, alignSelf: "center"}} fixed> | |
| <Text style={[styles.smallText, { color: "gray", textAlign: "center" }]} render={({ pageNumber, totalPages }) => ( | |
| `Invoice for Customer Name` | |
| )} /> | |
| </View> | |
| </Page> | |
| </Document> | |
| ) | |
| } | |
| class PDFInvoice extends Component { | |
| constructor(props) { | |
| super(props) | |
| this.state = { | |
| invoice: null | |
| } | |
| } | |
| componentDidMount() { | |
| console.log('the invoiceid is', this.props.match.params) | |
| agent.setToken(this.props.token) | |
| agent.requests.get(`invoices/${this.props.match.params.invoiceId}`).then(({invoice}) => { | |
| // succesfully updated invoice | |
| this.setState({ | |
| invoice | |
| }) | |
| }).catch((err) => { | |
| if (err.status === 404) { | |
| // redirect to pdf detailed version since invoice can no longer be updated | |
| this.setState({ | |
| invoice: null | |
| }) | |
| } | |
| }) | |
| } | |
| render() { | |
| const { companyName, companyPhoneNumber } = this.props.globals.settings | |
| let allRooms = [] | |
| if (this.state.invoice) { | |
| const roomIds = Object.keys(this.state.invoice.rooms || {}) | |
| const roomsById = this.state.invoice.rooms | |
| allRooms = roomIds.map((uuid) => { | |
| const room = roomsById[uuid] | |
| const roomLineItemsIds = Object.keys(room.lineItems) | |
| const roomLineItemsById = room.lineItems | |
| const roomLineItems = roomLineItemsIds.map((uuid) => roomLineItemsById[uuid]) | |
| const roomMeasurements = calculateRoomMeasurements(room.length, room.width, room.height) | |
| return { | |
| ...roomMeasurements, | |
| ...room, | |
| lineItems: roomLineItems | |
| } | |
| }) | |
| } | |
| return ( | |
| <div className="flex justify-center pv4"> | |
| <PDFViewer height="800px" className="center w-60" key={createUUID()}> | |
| <PDFdocument | |
| {...this.props.globals.settings} | |
| allRooms={allRooms || []} | |
| /> | |
| </PDFViewer> | |
| </div> | |
| ) | |
| } | |
| } | |
| const mapStateToProps = (state) => { | |
| const { status, errors, auth } = state | |
| const { settings: settingsStatus } = status.globals | |
| const { settings: settingsError } = errors.globals | |
| return { | |
| isLoading: { | |
| globals: { | |
| settings: settingsStatus | |
| } | |
| }, | |
| isError: { | |
| globals: { | |
| settings:settingsError | |
| } | |
| }, | |
| globals: { | |
| settings: getSettings(state) | |
| }, | |
| token: auth.token | |
| } | |
| } | |
| export default connect(mapStateToProps, { fetchSettings })(PDFInvoice) | |
| // export default PDFInvoice |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment