import React, { useRef, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import imageLogo from '../content/images/Logo.png';
import * as shared from '../scripts/shared.js';
import { jsPDF } from "jspdf";
const PageInvoiceOrEstimate = () => {
const canvasRefs = useRef([]);
const location = useLocation();
console.log("location:", location);
const props = location.state.data;
let styles = {
container: {
flexDirection: 'column',
padding: 20,
},
header: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 20,
},
logo: {
width: 80,
height: 80,
marginRight: 20,
},
line: {
height: 1,
backgroundColor: '#000',
marginVertical: 10,
},
page: {
flexDirection: 'row',
backgroundColor: '#E4E4E4',
width: '100%',
height: '100%',
padding: 20,
},
section: {
margin: 10,
padding: 10,
flexGrow: 1,
},
};
console.log("PageInvoiceOrEstimate");
console.log(props);
const heightA4 = 1123;
const widthA4 = 794;
const borderPage = 75;
const marginTable = 50;
const spacingLabel = marginTable - 20;
const heightLine = 25;
// positioning
const heightMyBusiness = 180;
const heightIssue = 325;
const heightBankMyBusiness = 420;
const heightBillToSite = 560;
const heightHeadTable = 800;
const heightRowMax = 1200; // update this !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
const maxRows = Math.floor((heightRowMax - heightHeadTable - heightLine) / (heightLine + spacingLabel));
console.log("maxRows:", maxRows);
const xPositionTableColumns = [120, 420, 520, 620];
const typeForm = props.typeForm == "1" ? "Invoice" : "Estimate";
console.log("typeForm:", typeForm);
let countRowsTemp = 0;
if (props["type" + typeForm] == "0") {
countRowsTemp = props["quantityGoods" + typeForm];
} else {
for (let indexService = 0; indexService < props["quantityServices" + typeForm]; indexService++) {
countRowsTemp += props["quantityBillingPeriodService" + typeForm + (indexService + 1)];
}
}
const countRows = countRowsTemp;
console.log("countRows:", countRows);
const countPages = Math.ceil(props["quantityServices" + typeForm] / maxRows);
console.log("countPages:", countPages);
const nameFont = "Arial";
const downloadPdf = (canvas, index) => {
const pdf = new jsPDF();
pdf.addImage(canvas.toDataURL("image/png"), "PNG", 0, 0);
pdf.save(`canvas${index}.pdf`);
};
const renderCanvases = () => {
const canvases = [];
for (let indexCanvas = 0; indexCanvas < countPages; indexCanvas++) {
canvases.push(
);
}
return canvases;
};
useEffect(() => {
let hasGoods = props["type" + typeForm] == "0";
let hasServices = props["type" + typeForm] == "1";
let countGoods = props["quantityGoods" + typeForm];
let countServices = props["quantityServices" + typeForm];
let indexGoodOrService = -1;
let indexSubservice = -1;
let indexRow = -1;
let pages = [];
let page;
let isRequiredPageNew = true;
while ((hasGoods && indexGoodOrService < countGoods - 1) || (hasServices && indexGoodOrService < countServices && indexRow < countRows - 1)) {
if (isRequiredPageNew) {
page = {
hasServices: hasServices,
hasGoods: hasGoods,
services: [],
goods: [],
total: 0,
hasTotal: false,
};
isRequiredPageNew = false;
}
indexRow++;
if (hasGoods) {
indexGoodOrService++;
let good = {
description: props["descriptionGood" + typeForm + (indexGoodOrService + 1)],
quantity: props["quantityGood" + typeForm + (indexGoodOrService + 1)],
rate: props["rateGood" + typeForm + (indexGoodOrService + 1)],
};
good["subtotal"] = (good.quantity * good.rate).toFixed(2);
page.goods.push(good);
page.total += Number(good.subtotal);
}
if (hasServices) {
indexSubservice++;
if (indexGoodOrService == -1 || indexSubservice == props["quantityBillingPeriodService" + typeForm + (indexGoodOrService + 1)]) {
indexSubservice = -1;
indexGoodOrService++;
indexRow--;
} else {
let service = {
description: props["descriptionIncrementService" + typeForm + (indexGoodOrService + 1) + "s" + (indexSubservice + 1)],
quantity: props["quantityRatePeriodsIncrementService" + typeForm + (indexGoodOrService + 1) + "s" + (indexSubservice + 1)],
rate: props["rateService" + typeForm + (indexGoodOrService + 1)],
};
service["subtotal"] = (service.quantity * service.rate).toFixed(2);
page.services.push(service);
page.total += Number(service.subtotal);
}
}
if (indexRow >= maxRows) {
indexRow = 0;
pages.push(page);
isRequiredPageNew = true;
}
if (indexRow == countRows - 1) {
page.hasTotal = true;
pages.push(page);
break;
}
}
console.log("pages:", pages);
let indexPage = -1;
canvasRefs.current.forEach((canvasRef) => {
indexPage++;
let page = pages[indexPage];
console.log("plotting page:", indexPage, page);
const canvas = canvasRef;
const ctx = canvas.getContext('2d');
// Clear the canvas
ctx.clearRect(0, 0, widthA4, heightA4);
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, widthA4, heightA4);
ctx.fillStyle = '#000';
plot(ctx, page);
});
}, []);
const plot = (context, page) => { // typeForm, do_goods, rows_g, n_goods, do_services, rows_s, n_services, n_subs, ratedisc, date_due, my_ref) {
plotPageLayout(context);
plotPageInterpersonal(context);
plotHeadingsTableInvoiceOrEstimate(context);
let currency = props.currency;
if (page.hasServices) {
context.font = '12px ' + nameFont;
// page.services.map((service, index) => {
let service;
for (let indexService = 0; indexService < page.services.length; indexService++) {
service = page.services[indexService];
context.fillText(service.description, xPositionTableColumns[0], heightHeadTable + (indexService + 1) * heightLine);
context.fillText(service.quantity, xPositionTableColumns[1], heightHeadTable + (indexService + 1) * heightLine);
context.fillText(service.rate, xPositionTableColumns[2], heightHeadTable + (indexService + 1) * heightLine);
context.fillText(service.subtotal, xPositionTableColumns[3], heightHeadTable + (indexService + 1) * heightLine);
};
}
if (page.hasGoods) {
context.font = '12px ' + nameFont;
// page.goods.map((good, index) => {
let good;
for (let indexGood = 0; indexGood < page.goods.length; indexGood++) {
good = page.goods[indexGood];
context.fillText(good.description, xPositionTableColumns[0], heightHeadTable + (indexGood + 1) * heightLine);
context.fillText(good.quantity, xPositionTableColumns[1], heightHeadTable + (indexGood + 1) * heightLine);
context.fillText(good.rate, xPositionTableColumns[2], heightHeadTable + (indexGood + 1) * heightLine);
context.fillText(good.subtotal, xPositionTableColumns[3], heightHeadTable + (indexGood + 1) * heightLine);
};
}
if (page.hasTotal) {
context.font = '12px ' + nameFont;
let heightRowTotal = heightHeadTable + (1 + (page.hasGoods ? page.goods.length : page.services.length)) * heightLine;
console.log("page total: ", page.total);
context.fillText(currency + page.total.toFixed(2), xPositionTableColumns[3] - 10, heightRowTotal);
context.fillText('TOTAL:', xPositionTableColumns[3] - borderPage - 10, heightRowTotal);
}
}
const plotPageLayout = (context) => {
context.beginPath();
context.font = '20px ' + nameFont;
context.fillText(typeForm, borderPage, 100);
// context.fillText('ESTIMATE', borderPage, 100);
context.font = 'bold 12px ' + nameFont;
context.fillText('BANK NAME:', borderPage, heightBankMyBusiness);
context.fillText('ACCOUNT NAME:', borderPage, heightBankMyBusiness + heightLine);
context.fillText('ACCOUNT NUMBER:', borderPage, heightBankMyBusiness + heightLine * 2);
context.fillText('SORT CODE:', borderPage, heightBankMyBusiness + heightLine * 3);
context.font = 'bold 12px ' + nameFont;
context.fillText('ISSUE DATE:', widthA4 / 2 + marginTable, heightIssue);
context.fillText('DUE DATE:', widthA4 / 2 + marginTable, heightIssue + heightLine);
context.fillText('REFERENCE:', widthA4 / 2 + marginTable, heightIssue + heightLine * 2);
context.font = 'bold 12px ' + nameFont;
context.fillText('BILL TO:', borderPage, heightBillToSite);
context.fillText('SITE / LOCATION:', widthA4 / 2 + marginTable, heightBillToSite);
context.stroke();
}
const plotPageInterpersonal = (context) => {
context.font = '14px ' + nameFont;
context.fillText(props.nameMyBusiness, borderPage, heightMyBusiness );
context.font = '12px ' + nameFont;
context.fillText(props.address1MyBusiness, borderPage, heightMyBusiness + heightLine * 1);
context.fillText(props.address2MyBusiness, borderPage, heightMyBusiness + heightLine * 2);
context.fillText(props.address3MyBusiness, borderPage, heightMyBusiness + heightLine * 3);
context.fillText(props.address4MyBusiness, borderPage, heightMyBusiness + heightLine * 4);
context.fillText(props.address5MyBusiness, borderPage, heightMyBusiness + heightLine * 5);
context.fillText(props.emailMyBusiness, borderPage, heightMyBusiness + heightLine * 6);
context.fillText(props.companyNumberMyBusiness, borderPage, heightMyBusiness + heightLine * 7);
// logo
var img = new Image();
img.crossOrigin = "anonymous";
// CORS_ALLOW_ALL_ORIGINS = true;
img.style.border = 'none';
img.src = imageLogo; // "https://raw.githubusercontent.com/Teddy-1024/Neural_Network/master/Deane_logo.png";
let sz_img = 200;
img.onload = function() {
context.drawImage(img, widthA4 - borderPage * 3 / 2 -sz_img, borderPage, sz_img, sz_img); // , 0, 0, 0, 0, borderPage + 25, borderPage + 2, sz_img, sz_img);
context.stroke();
}
context.font = '12px ' + nameFont;
context.fillText(props.nameBankMyBusiness, borderPage + 150, heightBankMyBusiness);
context.fillText(props.accountNameBankMyBusiness, borderPage + 150, heightBankMyBusiness + heightLine);
context.fillText(props.accountNumberBankMyBusiness, borderPage + 150, heightBankMyBusiness + heightLine * 2);
context.fillText(props.sortCodeBankMyBusiness, borderPage + 150, heightBankMyBusiness + heightLine * 3);
context.font = '12px ' + nameFont;
context.fillText(getDateIssue(), widthA4 / 2 + marginTable + 120, heightIssue);
context.fillText(getDateDue(), widthA4 / 2 + marginTable + 120, heightIssue + heightLine);
context.fillText(getReference(), widthA4 / 2 + marginTable + 120, heightIssue + heightLine * 2);
context.font = '12px ' + nameFont;
context.fillText(props.nameTheirBusiness, borderPage, heightBillToSite + heightLine * 1);
context.fillText(props.address1TheirBusiness, borderPage, heightBillToSite + heightLine * 2);
context.fillText(props.address2TheirBusiness, borderPage, heightBillToSite + heightLine * 3);
context.fillText(props.address3TheirBusiness, borderPage, heightBillToSite + heightLine * 4);
context.fillText(props.address4TheirBusiness, borderPage, heightBillToSite + heightLine * 5);
context.fillText(props.address5TheirBusiness, borderPage, heightBillToSite + heightLine * 6);
context.fillText(props.emailTheirBusiness, borderPage, heightBillToSite + heightLine * 7);
context.fillText(props.phoneTheirBusiness, borderPage, heightBillToSite + heightLine * 8);
context.fillText(props.nameContactTheirBusiness, widthA4 / 2 + marginTable, heightBillToSite + heightLine * 1);
context.fillText(props.address1ContactTheirBusiness, widthA4 / 2 + marginTable, heightBillToSite + heightLine * 2);
context.fillText(props.address2ContactTheirBusiness, widthA4 / 2 + marginTable, heightBillToSite + heightLine * 3);
context.fillText(props.address3ContactTheirBusiness, widthA4 / 2 + marginTable, heightBillToSite + heightLine * 4);
context.fillText(props.address4ContactTheirBusiness, widthA4 / 2 + marginTable, heightBillToSite + heightLine * 5);
context.fillText(props.address5ContactTheirBusiness, widthA4 / 2 + marginTable, heightBillToSite + heightLine * 6);
context.stroke();
}
const getDateIssue = () => {
let date = new Date(props["dateBilling" + typeForm]);
return shared.date2str(new Date(date.getFullYear(), date.getMonth(), -1));
}
const getDateDue = () => {
let date_0 = new Date(props.dateBillingInvoice);
let y0 = date_0.getFullYear();
let m0 = date_0.getMonth();
let date_1 = new Date(y0, m0 + 1, 1);
let n_working_days = 1;
let n_days_total = 4;
let date_temp = date_1;
for (let i = 1; i < 6; i++) {
date_temp.setDate(date_temp.getDate() + 1);
let billday = date_temp.getDay();
if (!(billday == 0 || billday == 6)) {
n_working_days++;
}
if (n_working_days == n_days_total) {
break;
}
}
let date_2 = date_temp;
return convertDateToString(date_2);
}
const convertDateToString = (date) => {
return date.getFullYear().toString() + '-' + (date.getMonth() + 1).toString().padStart(2, '0') + '-' + date.getDate().toString().padStart(2, '0');
}
const getReference = (pageHasGoods) => {
let name;
if (pageHasGoods) {
name = "goods" + convertDateToString(new Date());
} else {
let week1 = props["idBillingPeriodFirstIncrementalService" + typeForm + "1"];
let weekN = String(Number(week1) + Number(props["quantityBillingPeriodService" + typeForm + "1"]) - 1);
let year = props["dateBilling" + typeForm].substr(2, 2);// date.getFullYear();
name = year + "_wks_" + week1 + "-" + weekN;
}
return name;
}
function plotHeadingsTableInvoiceOrEstimate(context) {
context.font = 'bold 12px ' + nameFont;
context.fillText('DESCRIPTION', xPositionTableColumns[0] + 30, heightHeadTable);
context.fillText('QUANTITY', xPositionTableColumns[1] - 20, heightHeadTable);
context.fillText('UNIT COST [' + props.currency + ']', xPositionTableColumns[2] - 12, heightHeadTable);
context.fillText('SUBTOTAL', xPositionTableColumns[3] - 10, heightHeadTable);
}
return (
{renderCanvases()}
);
};
export default PageInvoiceOrEstimate;