Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
13 kB
4
Indexable
Never
import { format, utcToZonedTime } from 'date-fns-tz';
import { jsPDF as JsPDF } from 'jspdf';
import Cookies from 'universal-cookie';

import { DELIVERY_HANDOFF_ID } from '../../constants';
import { formatPrice } from '../../utils';
import getDateWithoutOffset from '../../utils/getDateWithoutOffset';

const generateOrderPDF = (data) => {
  const cookies = new Cookies();
  const doc = new JsPDF();

  const mainTitleFontSize = 20; // ~40px
  const cartTitleFontSize = 16; // ~32px
  const subtitleFontSize = 10; // ~20px
  const itemNameFontSize = 9; // ~18px
  const itemDescriptionFontSize = 8; // ~16px
  const xAxisMainLayoutStart = 20;
  const xAxisInnerLayoutStart = xAxisMainLayoutStart + 5;
  const yAxisMainTitlePosition = 20;
  const yAxisSubtitlePosition = 30;
  const yAxisCartTitlePosition = 50;
  const yAxisCartItemsPosition = 55;
  const generalTextSpacingValue = 5;
  const cartItemContainerHeight = 20;

  const {
    address,
    additionalCharge,
    category,
    couponAmount,
    expected,
    handoff,
    lineConnection,
    location,
    quoteId,
    subtotalPrice,
    taxes,
    tip,
    totalPrice,
  } = data;

  const numberOfCartItems = lineConnection?.totalCount;
  const timeOfPDFCreation = format(new Date(), 'MMMM dd, yyyy hh:mm a');

  doc.setTextColor(1, 1, 1); // #010101
  // Title
  doc.setFontSize(mainTitleFontSize);
  doc.setFont('helvetica', 'normal', 'bold');
  doc.text('Dickey’s Barbecue Pit', xAxisMainLayoutStart, yAxisMainTitlePosition);

  // Subtitle
  doc.setFontSize(subtitleFontSize);
  doc.setFont('helvetica', 'normal', 'normal');
  doc.text('This Is Not A Finished Order!', xAxisMainLayoutStart, yAxisSubtitlePosition);
  doc.text('Pricing Is Subject To Change.', xAxisMainLayoutStart, yAxisSubtitlePosition + 7);

  // Date and time
  doc.text(`#${quoteId}`, 199, yAxisMainTitlePosition, { align: 'right' });
  doc.text(timeOfPDFCreation, 199, yAxisMainTitlePosition + generalTextSpacingValue, {
    align: 'right',
  });

  // Cart title
  doc.setFontSize(cartTitleFontSize);
  doc.setFont('helvetica', 'normal', 'bold');
  doc.text('Cart', xAxisMainLayoutStart, yAxisCartTitlePosition);
  if (numberOfCartItems > 0) {
    doc.setFontSize(subtitleFontSize);
    doc.setFont('helvetica', 'normal', 'normal');
    doc.text(
      `(${numberOfCartItems} ${numberOfCartItems > 1 ? 'items' : 'item'})`,
      xAxisMainLayoutStart + 12,
      yAxisCartTitlePosition,
    );
  }

  const generateCartItems = (remainingItems, docPage = 0) => {
    const maxItemsPerPage = docPage === 0 ? 9 : 15;
    const totalNumberOfCartItemsOnPage =
      numberOfCartItems <= maxItemsPerPage ? numberOfCartItems : numberOfCartItems - remainingItems;
    console.log('TOTAL NUMBER ', totalNumberOfCartItemsOnPage);
    const maxItemDescriptionLength = 210;
    const yAxisCartItemsPositionStart =
      docPage === 0 ? yAxisCartItemsPosition : yAxisMainTitlePosition;

    doc.setDrawColor(200, 201, 217);
    doc.roundedRect(
      xAxisMainLayoutStart,
      yAxisCartItemsPositionStart,
      180,
      cartItemContainerHeight * totalNumberOfCartItemsOnPage,
      1,
      1,
    );

    if (lineConnection?.edges.length > 0) {
      data?.lineConnection?.edges.slice(docPage * remainingItems).forEach((line, index) => {
        if (!line?.node?.id || !line?.node?.item?.id) return;

        if (index < totalNumberOfCartItemsOnPage - 1) {
          const yItemsSeparatorPosition = 75 + cartItemContainerHeight * index;
          doc.line(xAxisMainLayoutStart, yItemsSeparatorPosition, 200, yItemsSeparatorPosition);
        }

        const yItemPosition = 58 + cartItemContainerHeight * index;
        const image = document
          .getElementById(line.node.item.itemimageConnection?.edges[0]?.node?.id)
          ?.getAttribute('src');
        const itemName = line.node.item.label;
        const itemPrice =
          line?.node?.item?.id === cookies.get('couponItemId')?.couponItemId
            ? 'FREE'
            : `$${formatPrice(line.node.totalPrice)}`;
        const itemDescription = line.node.lineMultipleConnection?.edges
          ?.map(
            (edge) =>
              `${edge.node?.quantity > 1 ? `${edge.node?.quantity} x ` : ''}${
                edge.node?.choice?.label
              }`,
          )
          .join(', ');
        const itemQuantity = line.node.quantity;

        doc.addImage(image || '', 'JPEG', xAxisInnerLayoutStart, yItemPosition, 22, 14);

        doc.setFontSize(itemNameFontSize);
        doc.setFont('helvetica', 'normal', 'bold');
        doc.text(itemName, 50, yItemPosition + 4);

        doc.setFontSize(itemDescriptionFontSize);
        doc.setTextColor(87, 87, 87);
        doc.setFont('helvetica', 'normal', 'normal');
        if (itemDescription.length > maxItemDescriptionLength) {
          const truncatedItemDescription = `${itemDescription.substring(
            0,
            maxItemDescriptionLength,
          )}...`;
          const splitItemDescription = doc.splitTextToSize(truncatedItemDescription, 100);
          doc.text(splitItemDescription, 50, yItemPosition + 8);
        } else {
          const splitItemDescription = doc.splitTextToSize(itemDescription, 100);
          doc.text(splitItemDescription, 50, yItemPosition + 10);
        }

        doc.setTextColor(1, 1, 1);
        doc.setFillColor(255, 247, 208);
        doc.roundedRect(150, yItemPosition + 2, 25, 10, 5, 5, 'F');
        doc.text(`Quantity: ${itemQuantity}`, 155, yItemPosition + 8);

        doc.setFontSize(itemNameFontSize);
        doc.setFont('helvetica', 'normal', 'bold');
        doc.text(itemPrice, 195, yItemPosition + 8, { align: 'right' });
      });
    }
    
  };

  // Cart items
  generateCartItems(0);

  // Cart total
  const yAxisCartTotalStartPosition =
    yAxisCartItemsPosition + cartItemContainerHeight * numberOfCartItems + 10;
  if (numberOfCartItems >= 10) {
    doc.addPage();
  }
  const cartTotalWidth = 80;
  const cartTotalInitialHeight = 20;
  const yAxisCartTotalTitlePosition = yAxisCartTotalStartPosition + 7;
  const yAxisCartTotalItemsStart = yAxisCartTotalTitlePosition + 7;
  const xAxisCartTotalPriceDisplay = cartTotalWidth + 15;
  let currentCartTotalTextSpacingValue = 0;

  doc.setFontSize(subtitleFontSize + 1);
  doc.setFont('helvetica', 'normal', 'bold');
  doc.text('Cart total', xAxisInnerLayoutStart, yAxisCartTotalTitlePosition);

  doc.setFontSize(itemNameFontSize);
  doc.setFont('helvetica', 'normal', 'normal');
  doc.setTextColor(88, 88, 90); // #58585A
  doc.text('Subtotal:', xAxisInnerLayoutStart, yAxisCartTotalItemsStart);
  doc.text(`$${formatPrice(subtotalPrice)}`, xAxisCartTotalPriceDisplay, yAxisCartTotalItemsStart, {
    align: 'right',
  });
  currentCartTotalTextSpacingValue += generalTextSpacingValue;

  taxes.forEach((tax, index) => {
    const yAxisTaxPosition =
      yAxisCartTotalItemsStart + generalTextSpacingValue + generalTextSpacingValue * index;
    doc.text(`${tax.label}:`, xAxisInnerLayoutStart, yAxisTaxPosition);
    doc.text(`$${formatPrice(tax.amount)}`, xAxisCartTotalPriceDisplay, yAxisTaxPosition, {
      align: 'right',
    });
    currentCartTotalTextSpacingValue += generalTextSpacingValue;
  });

  if (additionalCharge > 0) {
    doc.text(
      'Additional Charge:',
      xAxisInnerLayoutStart,
      yAxisCartTotalItemsStart + currentCartTotalTextSpacingValue,
    );
    doc.text(
      `$${formatPrice(additionalCharge)}`,
      xAxisCartTotalPriceDisplay,
      yAxisCartTotalItemsStart + currentCartTotalTextSpacingValue,
      {
        align: 'right',
      },
    );
    currentCartTotalTextSpacingValue += generalTextSpacingValue;
  }

  if (couponAmount > 0) {
    doc.text(
      'Discount:',
      xAxisInnerLayoutStart,
      yAxisCartTotalItemsStart + currentCartTotalTextSpacingValue,
    );
    doc.text(
      `$${formatPrice(couponAmount)}`,
      xAxisCartTotalPriceDisplay,
      yAxisCartTotalItemsStart + currentCartTotalTextSpacingValue,
      {
        align: 'right',
      },
    );
    currentCartTotalTextSpacingValue += generalTextSpacingValue;
  }

  doc.text(
    'Tip:',
    xAxisInnerLayoutStart,
    yAxisCartTotalItemsStart + currentCartTotalTextSpacingValue,
  );
  doc.text(
    `$${formatPrice(tip)}`,
    xAxisCartTotalPriceDisplay,
    yAxisCartTotalItemsStart + currentCartTotalTextSpacingValue,
    {
      align: 'right',
    },
  );
  currentCartTotalTextSpacingValue += generalTextSpacingValue;
  doc.setFont('helvetica', 'normal', 'bold');
  doc.setTextColor(1, 1, 1);
  doc.text(
    'Total:',
    xAxisInnerLayoutStart,
    yAxisCartTotalItemsStart + currentCartTotalTextSpacingValue,
  );
  doc.text(
    `$${formatPrice(totalPrice)}`,
    xAxisCartTotalPriceDisplay,
    yAxisCartTotalItemsStart + currentCartTotalTextSpacingValue,
    {
      align: 'right',
    },
  );

  doc.setDrawColor(200, 201, 217);
  doc.roundedRect(
    xAxisMainLayoutStart,
    yAxisCartTotalStartPosition,
    cartTotalWidth,
    cartTotalInitialHeight + currentCartTotalTextSpacingValue,
    1,
    1,
  );

  // Order / Delivery options
  const yAxisOrderOptionsStart = yAxisCartTotalTitlePosition;
  const xAxisOrderOptionsStart = xAxisCartTotalPriceDisplay + 20;
  const orderOptionsTextSpacingValue = 7;
  let currentOrderOptionsTextSpacingValue = orderOptionsTextSpacingValue;
  const inlineTextSpacing = 15;

  doc.setFontSize(subtitleFontSize + 1);
  doc.setFont('helvetica', 'normal', 'bold');
  doc.text('Order options', xAxisOrderOptionsStart, yAxisOrderOptionsStart);

  doc.setFontSize(itemDescriptionFontSize);

  if (handoff?.id === DELIVERY_HANDOFF_ID) {
    const deliveryAddress = `${address?.address}, ${address?.city}, ${address?.state?.abbreviation} ${address?.zip}`;
    doc.setTextColor(1, 1, 1);
    doc.setFont('helvetica', 'normal', 'bold');
    doc.text(
      'Address',
      xAxisOrderOptionsStart,
      yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
    );

    doc.setTextColor(88, 88, 90);
    doc.setFont('helvetica', 'normal', 'normal');
    doc.text(
      deliveryAddress,
      xAxisOrderOptionsStart + inlineTextSpacing,
      yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
    );
    currentOrderOptionsTextSpacingValue += orderOptionsTextSpacingValue;
  }

  const storeAddress = location
    ? `${location?.label}, ${location?.address?.address}, ${location?.address?.city}, ${location?.address?.state?.abbreviation} ${location?.address?.zip}`
    : null;
  if (storeAddress) {
    doc.text(
      'Location',
      xAxisOrderOptionsStart,
      yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
    );

    doc.setTextColor(88, 88, 90);
    doc.setFont('helvetica', 'normal', 'normal');
    doc.text(
      storeAddress,
      xAxisOrderOptionsStart + inlineTextSpacing,
      yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
    );
    currentOrderOptionsTextSpacingValue += orderOptionsTextSpacingValue;
  }

  doc.setTextColor(1, 1, 1);
  doc.setFont('helvetica', 'normal', 'bold');
  doc.text(
    'Handoff',
    xAxisOrderOptionsStart,
    yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
  );

  doc.setTextColor(88, 88, 90);
  doc.setFont('helvetica', 'normal', 'normal');
  doc.text(
    handoff?.label,
    xAxisOrderOptionsStart + inlineTextSpacing,
    yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
  );
  currentOrderOptionsTextSpacingValue += orderOptionsTextSpacingValue;

  doc.setTextColor(1, 1, 1);
  doc.setFont('helvetica', 'normal', 'bold');
  doc.text(
    'Menu',
    xAxisOrderOptionsStart,
    yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
  );

  doc.setTextColor(88, 88, 90);
  doc.setFont('helvetica', 'normal', 'normal');
  doc.text(
    category?.label,
    xAxisOrderOptionsStart + inlineTextSpacing,
    yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
  );
  currentOrderOptionsTextSpacingValue += orderOptionsTextSpacingValue;

  if (expected && location?.timezone?.label) {
    doc.setTextColor(1, 1, 1);
    doc.setFont('helvetica', 'normal', 'bold');
    doc.text(
      'Date & Time',
      xAxisOrderOptionsStart,
      yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
    );

    doc.setTextColor(88, 88, 90);
    doc.setFont('helvetica', 'normal', 'normal');
    doc.text(
      `${format(
        utcToZonedTime(getDateWithoutOffset(expected), location.timezone.label),
        'MMMM dd, yyyy',
      )} | ${format(
        utcToZonedTime(getDateWithoutOffset(expected), location.timezone.label),
        'hh:mm a',
      )}`,
      xAxisOrderOptionsStart + inlineTextSpacing + generalTextSpacingValue,
      yAxisOrderOptionsStart + currentOrderOptionsTextSpacingValue,
    );
    currentOrderOptionsTextSpacingValue += orderOptionsTextSpacingValue;
  }

  doc.output('dataurlnewwindow');
};

export default generateOrderPDF;