\n
\n \n )\n }\n}\nexport default SalesOrderEdit","import React from \"react\"\nimport { asCurrency, formatDate } from \"../../services/Utils\"\nimport { ChangeOrderService } from \"../../services/ChangeOrderService\"\n\n\nimport { OrderInfo } from \"./OrderInfo\"\nimport { Forecast } from \"./Forecast\"\nimport { SalesOrderItemService } from \"../../services/SalesOrderItemService\"\nimport { QuantitySelect } from \"./QuantitySelect\"\nimport classNames from \"classnames\"\nimport { debounce } from \"lodash\"\nimport { UncontrolledTooltip } from \"reactstrap\"\nimport { toast } from \"react-toastify\"\n\nexport class SalesOrderItemEdit extends React.Component {\n constructor(props) {\n super(props)\n\n this.onChangeQuantity = this.onChangeQuantity.bind(this)\n this.onDelete = this.onDelete.bind(this)\n this.changeOrder = this.changeOrder.bind(this)\n this.onMoveRadioChanged = this.onMoveRadioChanged.bind(this)\n\n this.toggleAdvanced = this.toggleAdvanced.bind(this)\n this.changeSalesOrderItem = this.changeSalesOrderItem.bind(this)\n this.changePriceOverride = this.changePriceOverride.bind(this)\n this.changeSubtotalOverride = this.changeSubtotalOverride.bind(this)\n\n this.copyInternalNote = this.copyInternalNote.bind(this)\n this.save = debounce(this.save, 1000)\n\n this.state = {\n moveRadio: 'backorder-inventory',\n moveType: 'backorder',\n sales_order_item: props.sales_order_item,\n status: 'waiting'\n }\n }\n\n changeOrder(event) {\n let sales_order_item = this.state.sales_order_item\n const existingOrderId = Number(event.currentTarget.name)\n const notes = sales_order_item.note_from_seller\n const moveType = this.state.moveType\n const reason = this.state.reason\n if (moveType == 'backorder') {\n let errorMessages = []\n if ( sales_order_item.quantity == 0 )\n errorMessages.push('the line item requires a quantity')\n if (!notes)\n errorMessages.push('add a note from seller')\n if ( errorMessages.length != 0 ) {\n const message = errorMessages.join(', ')\n this.setState({ errorMessage: `To backorder please ${ message }`})\n return\n }\n sales_order_item.quantity = 0\n }\n this.props.changeOrder(sales_order_item.id, moveType, existingOrderId, notes, reason)\n this.setState({ sales_order_item: sales_order_item, showAdvanced: false})\n }\n\n copyInternalNote(event) {\n let sales_order_item = this.state.sales_order_item\n sales_order_item.internal_seller_note = event.target.value\n this.setState({sales_order_item: sales_order_item}, this.save)\n }\n\n onMoveRadioChanged(event) {\n const newMoveRadio = event.target.value\n let newStateValues = { moveRadio: newMoveRadio }\n if (newMoveRadio == 'move' ) {\n newStateValues.moveType = 'move'\n newStateValues.reason = undefined\n } else if (newMoveRadio == 'backorder-inventory' ) {\n newStateValues.moveType = 'backorder'\n newStateValues.reason = 'inventory'\n } else if (newMoveRadio == 'backorder-deadline' ) {\n newStateValues.moveType = 'backorder'\n newStateValues.reason = 'deadline'\n } else if (newMoveRadio == 'backorder-other' ) {\n newStateValues.moveType = 'backorder'\n newStateValues.reason = 'deadline'\n }\n this.setState(newStateValues)\n }\n\n onDelete() {\n const sales_order_item = this.props.sales_order_item\n\n return SalesOrderItemService.destroy(sales_order_item.id).then(\n (new_sales_order_item) => { this.props.deletedSalesOrderItem(sales_order_item.id) },\n (error) => {\n this.setState({ status: 'failed' })\n toast(error.message, { className: \"bg-danger text-white\" })\n }\n )\n }\n\n onChangeQuantity(newQuantity) {\n let sales_order_item = this.state.sales_order_item\n if (newQuantity) { sales_order_item.quantity = newQuantity }\n const nextStatus = newQuantity == '' ? 'waiting' : 'sending'\n sales_order_item.quantity = newQuantity\n this.setState({ sales_order_item: sales_order_item, status: 'sending' }, this.save)\n }\n\n save() {\n let sales_order_item = this.state.sales_order_item\n return SalesOrderItemService.update(sales_order_item).then((new_sales_order_item) => {\n sales_order_item.calculated_subtotal = new_sales_order_item.calculated_subtotal\n sales_order_item.effective_unit_price = new_sales_order_item.effective_unit_price\n sales_order_item.deposit_average = new_sales_order_item.deposit_average\n sales_order_item.deposit_subtotal = new_sales_order_item.deposit_subtotal\n sales_order_item.original_subtotal = new_sales_order_item.original_subtotal\n sales_order_item.subtotal = new_sales_order_item.subtotal\n\n this.setState({ sales_order_item: sales_order_item, status: 'waiting' })\n this.props.updatedSalesOrderItem(new_sales_order_item)\n },\n (error) => {\n this.setState({ status: 'failed' })\n toast(error.message, { className: \"bg-danger text-white\" })\n }\n )\n }\n\n toggleAdvanced() {\n this.setState({ showAdvanced: !this.state.showAdvanced })\n }\n\n changePriceOverride(event) {\n let sales_order_item = this.state.sales_order_item\n sales_order_item[event.target.name] = event.target.value\n sales_order_item['subtotal_override'] = null\n this.setState({ sales_order_item: sales_order_item, status: 'sending' }, this.save)\n }\n\n changeSubtotalOverride(event) {\n let sales_order_item = this.state.sales_order_item\n sales_order_item[event.target.name] = event.target.value\n sales_order_item['price_override'] = null\n this.setState({ sales_order_item: sales_order_item, status: 'sending' }, this.save)\n }\n\n changeSalesOrderItem(event) {\n let sales_order_item = this.state.sales_order_item\n sales_order_item[event.target.name] = event.target.value\n this.setState({ sales_order_item: sales_order_item, status: 'sending' }, this.save)\n }\n\n renderDeleteButton() {\n if (!this.state.showAdvanced) { return }\n return (\n
\n \n
\n )\n }\n\n renderSticky(lineId, iconLetter, tooltipText) {\n const id = `tooltip-${ lineId }-${ iconLetter }`\n return (\n
\n \n \n { iconLetter }\n \n \n { tooltipText }\n \n
\n )\n }\n\n renderNoteInput() {\n let internalNote\n if (!this.props.isPurchaseOrder) {\n internalNote = (\n
\n { this.renderSticky(this.state.sales_order_item.id, '', 'Internal Note')}\n
\n
\n { this.renderReasonDropdown() }\n \n
\n
\n
\n )\n }\n\n return (\n
\n
\n { this.renderSticky(this.state.sales_order_item.id, 'S', 'Note from seller') }\n
\n \n
\n
\n
\n { this.renderSticky(this.state.sales_order_item.id, 'B', 'Note from buyer')}\n
\n \n
\n
\n { internalNote }\n
\n )\n }\n\n renderMove() {\n const open_orders = this.props.open_orders\n if ( open_orders == undefined ) { return }\n const sales_order_item = this.state.sales_order_item\n\n const draftOrderButtons = open_orders.map((open_order) => {\n return (\n
\n \n \n )\n })\n\n return (\n
\n
\n
\n { draftOrderButtons }\n
\n )\n }\n\n renderCatchWeightDescription() {\n const sales_order_item = this.state.sales_order_item\n if (!sales_order_item.actual_unit_price) { return }\n const catch_weight = sales_order_item.actual_quantity\n const unit = sales_order_item.product_unit.catch_weight_unit\n const item_unit = (unit == 'pound' ? 'lbs' : unit)\n const denominatorUnit = (unit == 'pound' ? 'lb' : unit)\n const rate = asCurrency(sales_order_item.actual_unit_price)\n\n const warningClass = classNames({\n \"text-danger\": !sales_order_item.actual_quantity\n })\n\n return (\n
\n \n { `Actual: ${catch_weight || 'TBD'} ${item_unit} × ${rate} / ${denominatorUnit}` }\n \n
\n )\n }\n\n renderAdvancedEdit() {\n if (!this.state.showAdvanced) { return }\n return (\n
\n { this.renderNoteInput() }\n { this.renderMove() }\n
\n )\n }\n\n renderSellerNote() {\n if (!this.state.sales_order_item.note_from_seller || this.state.showAdvanced) { return }\n return (\n
\n { this.renderSticky(this.state.sales_order_item.id, 'S', 'Note from seller')}\n { this.state.sales_order_item.note_from_seller }\n
\n )\n }\n\n renderReasonDropdown() {\n\n if ( !this.props.commonInternalNotes ) { return }\n\n const reasonButtons = this.props.commonInternalNotes.map((reason) => {\n return (\n
\n )\n })\n\n return (\n
\n
\n \n
\n { reasonButtons }\n
\n
\n
\n )\n }\n\n renderBuyerNote() {\n if (!this.state.sales_order_item.note_from_buyer || this.state.showAdvanced) { return }\n return (\n
\n { this.renderSticky(this.state.sales_order_item.id, 'B', 'Note from buyer')}\n { this.state.sales_order_item.note_from_buyer }\n
\n )\n }\n\n renderInternalSellerNote() {\n const sales_order_item = this.state.sales_order_item\n if (this.props.isPurchaseOrder || !sales_order_item.internal_seller_note || this.state.showAdvanced) { return }\n return (\n
\n { this.renderSticky(this.state.sales_order_item.id, '', 'Internal Seller Note')}\n { sales_order_item.internal_seller_note }\n
\n )\n }\n\n renderSubtotalOverride() {\n if (!this.state.showAdvanced) { return }\n const subtotal_override = this.state.sales_order_item.subtotal_override || ''\n const price_override = this.state.sales_order_item.price_override || ''\n return (\n
\n )\n }\n\n renderDepositOverride() {\n if (!this.state.showAdvanced) { return }\n const deposit_override = this.state.sales_order_item.deposit_override || ''\n return (\n
\n )\n }\n\n renderSubtotal() {\n const sales_order_item = this.state.sales_order_item\n let icon\n if ( sales_order_item.subtotal_override) {\n icon =
\n }\n return (\n
\n { icon }{ asCurrency(sales_order_item.subtotal) }\n
\n )\n }\n\n renderUnitPrice() {\n const sales_order_item = this.state.sales_order_item\n let icon\n if (sales_order_item.price_override) {\n icon =
\n }\n return (\n
\n { icon }{ asCurrency(sales_order_item.effective_unit_price) }\n
\n )\n }\n\n renderOriginalEffectivePrice() {\n const sales_order_item = this.state.sales_order_item\n if ( !sales_order_item.original_effective_price ) { return }\n\n return (\n
\n { asCurrency(sales_order_item.original_effective_price) }\n
\n )\n }\n\n renderDeposit() {\n const sales_order_item = this.state.sales_order_item\n if ( sales_order_item.deposit_average == 0 ) { return }\n\n return (\n
\n \n { asCurrency(sales_order_item.deposit_average) }\n
\n )\n }\n\n renderDepositSubtotal() {\n const sales_order_item = this.state.sales_order_item\n if ( Number(sales_order_item.deposit_subtotal) == 0 && !sales_order_item.deposit_override) { return }\n const overridden = !!sales_order_item.deposit_override\n let icon\n if (overridden) {\n icon =
\n }\n return (\n
\n { icon }\n \n { asCurrency(sales_order_item.deposit_subtotal) }\n
\n )\n }\n\n renderOriginalSubtotal() {\n const sales_order_item = this.state.sales_order_item\n if ( !sales_order_item.original_subtotal ) { return }\n\n return (\n
\n { asCurrency(sales_order_item.original_subtotal) }\n
\n )\n }\n\n renderCatchWeightInput() {\n if (!this.state.showAdvanced) { return }\n if (!this.state.sales_order_item.actual_unit_price) { return }\n return (\n
\n \n
\n )\n }\n\n renderQuantity() {\n const sales_order_item = this.state.sales_order_item\n return (\n
\n \n { this.renderCatchWeightInput() }\n
\n )\n }\n\n renderDepositDescription() {\n if ( this.state.sales_order_item.deposit_average == 0 ) { return }\n\n let message\n if ( this.state.sales_order_item.deposit_average > 0 ) {\n message = 'This item has a refundable deposit'\n } else {\n message = 'Refundable deposit'\n }\n\n return (\n
\n \n { message }\n
\n )\n }\n\n renderProducerName() {\n if (!this.props.showProducerName) { return }\n\n const product_unit = this.props.sales_order_item.product_unit\n return (\n
{ product_unit.producer_name }
\n )\n }\n\n renderForecast() {\n if (this.props.showForecast) {\n return (\n
\n )\n }\n }\n\n renderBackorder() {\n if (this.props.sales_order_item.src == 'checkout_item') {\n return (\n
\n Checkout Alternative\n
\n )\n }\n }\n renderSrc() {\n if (this.props.sales_order_item.src) {\n const color = this.props.sales_order_item.quantity == 0 ? 'badge-success' : 'badge-info'\n return (\n
\n Customer Backorder\n
\n )\n }\n }\n\n renderUnavailable() {\n const product_unit = this.props.sales_order_item.product_unit\n\n if (product_unit.unavailable_until) {\n var color = product_unit.unavailable_type == 'preorder' ? 'badge-success' : 'badge-warning'\n return (\n
\n \n \n { formatDate(product_unit.unavailable_until) }: {product_unit.unavailable_until_description }\n \n
\n )\n } else if (!product_unit.is_published) {\n return (\n
\n \n \n Currently Unavailable\n \n
\n )\n }\n }\n\n render() {\n const sales_order_item = this.props.sales_order_item\n const product_unit = sales_order_item.product_unit\n const buttonClass = this.state.showAdvanced ? 'btn-dark' : 'btn-outline-secondary'\n\n const status = this.state.status\n const rowClass = classNames({\n \"order-row\": true,\n \"py-2\": true,\n \"save-failed\": status === \"failed\",\n \"save-pending\": status === \"sending\",\n \"save-success\": status === \"success\"\n })\n\n let minimum\n if (product_unit.quantity_minimum > 1) {\n minimum =
{`${product_unit.quantity_minimum} minimum`}\n }\n let maximum\n if (product_unit.quantity_maximum > 1) {\n maximum =
{`${product_unit.quantity_maximum} maximum`}\n }\n let split\n if (product_unit.split_multiplier) {\n split =
\n }\n\n let orderProductUnitCount\n if (this.props.orderProductUnitCount > 1) {\n const id = `order-multiple-${sales_order_item.id}`\n orderProductUnitCount = (\n
\n { this.props.orderProductUnitCount }\n \n This product unit is on { this.props.orderProductUnitCount } line items in this order\n \n \n )\n }\n\n return (\n
\n
\n \n
\n
\n
\n { this.renderQuantity() }\n
\n { this.renderDeleteButton() }\n
\n
\n
\n
\n

\n
\n
\n { this.renderProducerName() }\n
{ product_unit.product_name }
\n
{ product_unit.unit }{minimum}{maximum}{orderProductUnitCount}{split}
\n { this.renderCatchWeightDescription() }\n { this.renderDepositDescription() }\n { this.renderBackorder() }\n { this.renderUnavailable() }\n { this.renderSellerNote() }\n { this.renderBuyerNote() }\n { this.renderInternalSellerNote() }\n\n { this.renderForecast() }\n
\n
\n { this.renderAdvancedEdit() }\n
\n
\n
\n
\n { this.renderUnitPrice() }\n { this.renderOriginalEffectivePrice() }\n { this.renderDeposit() }\n
\n
\n { this.renderSubtotal() }\n { this.renderOriginalSubtotal() }\n { this.renderDepositSubtotal() }\n
\n
\n { this.renderSubtotalOverride() }\n { this.renderDepositOverride() }\n
\n
\n )\n }\n}\nexport default SalesOrderItemEdit","import React from \"react\"\nimport { asCurrency } from \"../../services/Utils\"\nimport { SalesOrderItemService } from \"../../services/SalesOrderItemService\"\nimport { QuantitySelect } from \"./QuantitySelect\"\nimport { ProductUnitSelect } from \"./ProductUnitSelect\"\nimport { CatalogFetcher } from \"../../services/CatalogFetcher\"\n\nexport class SalesOrderItemNew extends React.Component {\n constructor(props) {\n super(props)\n\n this.toggle = this.toggle.bind(this)\n this.onCreate = this.onCreate.bind(this)\n this.productUnitSelect = React.createRef()\n this.addButton = React.createRef()\n this.quantitySelect = React.createRef()\n this.onChangeQuantity = this.onChangeQuantity.bind(this)\n this.onProductUnitSelected = this.onProductUnitSelected.bind(this)\n this.notifyParentOfSubtotalChange = this.notifyParentOfSubtotalChange.bind(this)\n\n const initialQuantity = this.props.sales_order.credit ? -1 : 1\n this.state = {\n sales_order_item: { quantity: initialQuantity, buyer_order_id: this.props.sales_order.id }\n }\n }\n\n\n onCreate() {\n let sales_order_item = this.state.sales_order_item\n sales_order_item.src = 'sales_order_item_new'\n SalesOrderItemService.create(sales_order_item).then((new_sales_order_item) => {\n this.props.createdSalesOrderItem(new_sales_order_item)\n const initialQuantity = this.props.sales_order.credit ? -1 : 1\n this.setState({\n sales_order_item: { quantity: initialQuantity, buyer_order_id: this.props.sales_order.id },\n product_unit: null\n }, () => { this.quantitySelect.current.refocus() })\n })\n }\n\n toggle(event) {\n this.setState({ showUnavailable: !this.state.showUnavailable })\n }\n\n notifyParentOfSubtotalChange() {\n this.props.onSubtotalUpdate(this.calculateSubtotal())\n }\n\n onChangeQuantity(newValue) {\n let sales_order_item = this.state.sales_order_item\n sales_order_item.quantity = newValue\n this.setState({ sales_order_item: sales_order_item }, this.notifyParentOfSubtotalChange)\n }\n\n onProductUnitSelected(product_unit) {\n let sales_order_item = this.state.sales_order_item\n if (!product_unit) {\n delete sales_order_item['product_unit_id']\n this.setState({product_unit: undefined, sales_order_item: sales_order_item})\n return\n }\n sales_order_item.product_unit_id = product_unit.id\n\n if (!this.props.sales_order.credit && product_unit.quantity_minimum > sales_order_item.quantity) {\n sales_order_item.quantity = product_unit.quantity_minimum\n }\n this.setState({ product_unit: product_unit, sales_order_item: sales_order_item },\n () => { this.notifyParentOfSubtotalChange(); this.addButton.current.focus(); }\n )\n }\n\n renderQuantity() {\n const product_unit = this.state.product_unit || { quantity_minimum: 1 }\n return (\n
\n )\n }\n\n renderUnitPrice() {\n const product_unit = this.state.product_unit\n if (!product_unit) { return }\n return (\n
{ asCurrency(product_unit.price) }\n )\n }\n\n calculateSubtotal() {\n const product_unit = this.state.product_unit\n if (!product_unit) { return 0 }\n return (this.state.sales_order_item.quantity * product_unit.price)\n }\n\n renderSubtotal() {\n const product_unit = this.state.product_unit\n if (!product_unit) { return }\n return (\n
{ asCurrency(\"\" + this.calculateSubtotal()) }\n )\n }\n\n render() {\n const product_unit = this.state.product_unit\n let rowClass = \"order-row list-group-item py-2 align-items-end\"\n let buttonClass\n if (product_unit) {\n buttonClass = \"btn-primary\"\n rowClass += ' bg-warning'\n } else {\n buttonClass = \"btn-primary disabled\"\n }\n return (\n
\n
\n
\n \n
\n
\n { this.renderQuantity() }\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n )\n }\n}\nexport default SalesOrderItemNew","import { Application } from \"@hotwired/stimulus\"\n\nconst application = Application.start()\n\n// Configure Stimulus development experience\napplication.debug = false\nwindow.Stimulus = application\n\nexport { application }\n","import { Controller } from '@hotwired/stimulus';\nimport { ajax } from '@rails/ujs'; // Ensure Rails UJS is installed and imported\n\nexport default class extends Controller {\n connect() {\n $(this.element).popover({\n delay: { show: 300, hide: 50 },\n trigger: 'manual',\n html: true\n });\n\n this.hoverState = null;\n this.timeout = null;\n\n this.element.addEventListener('mouseenter', this.showPopover.bind(this));\n this.element.addEventListener('mouseleave', this.hidePopover.bind(this));\n this.element.addEventListener('touchstart', this.showPopover.bind(this));\n this.element.addEventListener('touchleave', this.hidePopover.bind(this));\n\n // Bind Bootstrap's popover show event\n $(this.element).on('show.bs.popover', this.fetchPopoverContent.bind(this));\n }\n\n showPopover() {\n clearTimeout(this.timeout);\n this.hoverState = 'in';\n\n this.timeout = setTimeout(() => {\n if (this.hoverState === 'in') {\n $(this.element).popover('show');\n\n const popoverElement = document.querySelector('.popover');\n if (popoverElement) {\n popoverElement.addEventListener('mouseenter', this.cancelHidePopover.bind(this));\n popoverElement.addEventListener('mouseleave', this.startHidePopover.bind(this));\n }\n }\n }, 300); // Match the show delay\n }\n\n hidePopover() {\n clearTimeout(this.timeout);\n this.hoverState = 'out';\n\n this.timeout = setTimeout(() => {\n if (this.hoverState === 'out') {\n $(this.element).popover('hide');\n }\n }, 50); // Match the hide delay\n }\n\n cancelHidePopover() {\n clearTimeout(this.timeout);\n }\n\n startHidePopover() {\n this.hidePopover();\n }\n\n fetchPopoverContent() {\n const id = this.element.dataset.id;\n\n ajax({\n url: `/admin/product_units/${id}/order_items`,\n type: 'GET',\n dataType: 'script'\n });\n }\n\n disconnect() {\n $(this.element).popover('dispose');\n this.element.removeEventListener('mouseenter', this.showPopover.bind(this));\n this.element.removeEventListener('mouseleave', this.hidePopover.bind(this));\n $(this.element).off('show.bs.popover');\n }\n}","import { Controller } from '@hotwired/stimulus';\nimport \"bootstrap\"; // Ensure Bootstrap is imported\n\nexport default class extends Controller {\n connect() {\n var element = this.element\n $(element).popover();\n }\n\n disconnect() {\n // Clean up popovers when the controller is disconnected\n $(this.element).popover('dispose');\n }\n}","import { Controller } from \"@hotwired/stimulus\";\n\nexport default class extends Controller {\n connect() {\n this.element.addEventListener(\"click\", this.clone.bind(this));\n }\n\n disconnect() {\n this.element.removeEventListener(\"click\", this.clone.bind(this));\n }\n\n clone() {\n const targetForm = this.element.closest('form');\n const cloneFrom = document.querySelector(this.element.dataset.clonerCloneFrom);\n if (targetForm && cloneFrom) {\n const clonedElement = cloneFrom.cloneNode(true);\n targetForm.append(clonedElement);\n }\n }\n}","// This file is auto-generated by ./bin/rails stimulus:manifest:update\n// Run that command whenever you add a new controller or create them with\n// ./bin/rails generate stimulus controllerName\n\nimport { application } from \"./application\"\n\nimport ProductUnitActivityPopoverController from \"./product_unit_activity_popover_controller\"\napplication.register(\"product-unit-activity-popover\", ProductUnitActivityPopoverController)\n\nimport SimplePopoverController from \"./simple_popover_controller\"\napplication.register(\"simple-popover\", SimplePopoverController)\n\nimport ClonerController from \"./cloner_controller\"\napplication.register(\"cloner\", ClonerController)\n","import \"core-js/stable\";\nimport 'regenerator-runtime/runtime'\n\nimport DataTable from 'datatables.net-bs4';\nimport 'datatables.net-bs4/css/dataTables.bootstrap4.css';\nimport 'datatables.net-fixedheader-dt';\nimport 'datatables.net-fixedheader-dt/css/fixedHeader.dataTables.css';\n$.fn.DataTable = DataTable;\n\nrequire(\"../src/datatables_init.js\")\n\nwindow.$ = window.jQuery = require('jquery');\n\nrequire(\"@rails/ujs\").start()\nglobal.Rails = Rails;\n\nimport 'bootstrap'\nrequire(\"../src/bootstrap_init.js\")\n\nimport Sortable from 'sortablejs'\nglobal.Sortable = Sortable;\n\nimport \"@hotwired/turbo-rails\"\n\nimport LocalTime from \"local-time\"\nLocalTime.start()\n\nimport \"chartkick/chart.js\"\nimport { Chart } from \"chart.js\"\nimport ChartDataLabels from 'chartjs-plugin-datalabels';\nChart.register(ChartDataLabels)\nChart.defaults.set('plugins.datalabels', {\n backgroundColor: 'rgba(0, 0, 0, 0)',\n font: { size: 0 }\n});\n\nrequire(\"../app/application.js\")\nrequire(\"../app/stripe_seller_add_card.js\")\nrequire(\"../app/stripe_seller_add_bank_account.js\")\nrequire(\"../app/stripe_buyer_setup_intent.js\")\n\nimport \"../controllers\"\nrequire(\"../css/application.scss\")\n\nimport '@selectize/selectize/dist/js/selectize.min.js'\nimport '@selectize/selectize/dist/css/selectize.bootstrap4.css'\n\nrequire(\"../src/chosen_init.js\")\n\nimport 'timepicker/jquery.timepicker'\nimport 'timepicker/jquery.timepicker.css'\n\nimport flatpickr from \"flatpickr\"\nimport 'flatpickr/dist/flatpickr.min.css'\nimport mapboxgl from \"mapbox-gl\"\nglobal.mapboxgl = mapboxgl\nimport 'mapbox-gl/dist/mapbox-gl.css';\n\nrequire(\"jquery-ui/ui/widgets/sortable\")\nrequire(\"jquery-ui-touch-punch/jquery.ui.touch-punch.min.js\")\n\nrequire(\"../src/ahoy.js\")\nrequire('jquery-sparkline/jquery.sparkline.min.js')\nrequire(\"../src/timeout_poll.js\")\nrequire(\"../src/date_range_picker.js\")\nrequire(\"../src/flatpickr.js\")\nrequire(\"../src/mapbox.js\")\nrequire(\"../src/market_sheet.js\")\nrequire(\"../src/deposits.js\")\nrequire(\"../src/selectall.js\")\nrequire(\"../src/sorting.js\")\nrequire(\"../src/table_to_csv.js\")\n\n// Support component names relative to this directory:\nvar componentRequireContext = require.context(\"../components\", true)\nvar ReactRailsUJS = require(\"react_ujs\")\nReactRailsUJS.useContext(componentRequireContext)\nReactRailsUJS.handleEvent('turbo:load', ReactRailsUJS.handleMount);\nReactRailsUJS.handleEvent('turbo:before-render', ReactRailsUJS.handleUnmount);\n\n","import { HTTP } from \"./Connection\"\n\nexport class CatalogFetcher {\n static queryPublic(sellerId, page, batchSize, params) {\n const base = \"/api/seller/\" + sellerId + '/public_products?'\n return CatalogFetcher.query(base, page, batchSize, params)\n }\n\n static queryAll(sellerId, page, batchSize, params) {\n const base = \"/api/sellers/\" + sellerId + \"/products/with_unavailable?\"\n return CatalogFetcher.query(base, page, batchSize, params)\n }\n\n static queryCatalog(sellerId, catalogId, page, batchSize, params) {\n params.catalogId = catalogId\n const base = \"/api/sellers/\" + sellerId + \"/products/?\"\n return CatalogFetcher.query(base, page, batchSize, params)\n }\n\n static queryAvailable(sellerId, page, batchSize, params) {\n const base = \"/api/sellers/\" + sellerId + \"/products/?\"\n return CatalogFetcher.query(base, page, batchSize, params)\n }\n\n static query(base, page, batchSize, params) {\n let buyer = \"\"\n let privateCatalog = \"\"\n let categoriesSearch = \"\"\n let collectionsSearch = \"\"\n let producersSearch = \"\"\n let textSearch = \"\"\n let productSlug = \"\"\n let count = \"\"\n let localOnly = \"\"\n let isStocked = \"\"\n let sortBy = \"\"\n let isFeatured = \"\"\n\n if ( params.categories && params.categories.length > 0 )\n categoriesSearch = \"&categories=\" + params.categories.join(\"|\")\n if ( params.producers && params.producers.length > 0 )\n producersSearch = \"&producers=\" + params.producers.join(\"|\")\n if ( params.collections && params.collections.length > 0 )\n collectionsSearch = \"&collections=\" + params.collections.join(\"|\")\n if ( params.count )\n count = \"&count=true\"\n if ( params.localOnly )\n localOnly = \"&local_only=true\"\n if ( params.buyerId )\n buyer = \"&buyer_id=\" + params.buyerId\n if ( params.catalogId )\n privateCatalog = \"&private_catalog_id=\" + params.catalogId\n if ( params.isStocked )\n isStocked = \"&is_stocked=true\"\n if ( params.isFeatured )\n isFeatured = \"&featured=true\"\n if ( params.productSlug )\n productSlug = \"&product_slug=\" + encodeURIComponent(params.productSlug)\n if ( params.text )\n textSearch = textSearch + \"&text=\" + encodeURIComponent(params.text)\n if ( params.sortBy )\n sortBy = sortBy + \"&sort_by=\" + params.sortBy\n\n return HTTP.get(\n base +\n \"page=\" +\n page +\n \"&per_page=\" +\n batchSize +\n categoriesSearch +\n collectionsSearch +\n privateCatalog +\n buyer +\n producersSearch +\n localOnly +\n isStocked +\n isFeatured +\n textSearch +\n productSlug +\n sortBy +\n count\n )\n }\n}\n","export class HTTP {\n static handleResponse(status, success, failure) {\n if (status >= 200 && status < 300) {\n success()\n } else if (\n (status >= 300 && status < 400) ||\n status == 401 ||\n status == 403\n ) {\n window.location.href = \"/users/sign_in?return_to=/app/\"\n } else {\n failure()\n }\n }\n\n static get(url) {\n return new Promise(function(resolve, reject) {\n var xhr = new XMLHttpRequest()\n xhr.open(\"GET\", url, true)\n xhr.onload = function() {\n var status = xhr.status\n HTTP.handleResponse(\n status,\n () => {\n resolve(JSON.parse(xhr.responseText))\n },\n () => {\n reject(JSON.parse(xhr.responseText))\n }\n )\n }\n xhr.send()\n })\n }\n\n static post(url, message) {\n return new Promise(function(resolve, reject) {\n var xhr = new XMLHttpRequest()\n xhr.open(\"POST\", url, true)\n xhr.setRequestHeader(\"Content-Type\", \"application/json\")\n\n xhr.onload = function() {\n let status = xhr.status\n\n HTTP.handleResponse(\n status,\n () => {\n resolve(JSON.parse(xhr.responseText))\n },\n () => {\n reject(JSON.parse(xhr.responseText))\n }\n )\n }\n\n xhr.send(JSON.stringify(message))\n })\n }\n\n static delete(url, message) {\n return new Promise(function(resolve, reject) {\n var xhr = new XMLHttpRequest()\n xhr.open(\"DELETE\", url, true)\n xhr.setRequestHeader(\"Content-Type\", \"application/json\")\n\n xhr.onload = function() {\n let status = xhr.status\n\n HTTP.handleResponse(\n status,\n () => {\n resolve(JSON.parse(xhr.responseText || null))\n },\n () => {\n reject(JSON.parse(xhr.responseText))\n }\n )\n }\n\n xhr.send()\n })\n }\n\n static put(url, message) {\n return new Promise(function(resolve, reject) {\n var xhr = new XMLHttpRequest()\n xhr.open(\"PUT\", url, true)\n xhr.setRequestHeader(\"Content-Type\", \"application/json\")\n\n xhr.onload = function() {\n let status = xhr.status\n HTTP.handleResponse(\n status,\n () => {\n resolve(JSON.parse(xhr.responseText || null))\n },\n () => {\n reject(JSON.parse(xhr.responseText))\n }\n )\n }\n\n xhr.send(JSON.stringify(message))\n })\n }\n}\n","import { HTTP } from \"./Connection\"\n\nexport class PurchaseOrderItemService {\n\n static update (purchase_order_item) {\n return new Promise((resolve, reject) => {\n const id = purchase_order_item.id\n HTTP.put(\"/api/purchase_order_items/\" + id, purchase_order_item).then(resolve, reject)\n })\n }\n\n static destroy (id) {\n return new Promise((resolve, reject) => {\n HTTP.delete(\"/api/purchase_order_items/\" + id).then(resolve, reject)\n })\n }\n\n static create (purchase_order_item) {\n return new Promise((resolve, reject) => {\n const url = \"/api/purchase_order_items\"\n HTTP.post(url, purchase_order_item).then(resolve, reject)\n })\n }\n}\n","import { HTTP } from \"./Connection\"\n\nexport class PurchaseOrderService {\n\n static create (buyer_id, seller_id, requested_on) {\n return new Promise((resolve, reject) => {\n const purchase_order = { purchase_order: { seller_id: seller_id,\n buyer_id: buyer_id,\n requested_on: requested_on } }\n const url = \"/api/purchase_orders\"\n\n HTTP.post(url, purchase_order).then(resolve, reject)\n })\n }\n\n static update (purchase_order) {\n return new Promise((resolve, reject) => {\n const payload = { purchase_order: purchase_order }\n const url = \"/api/purchase_orders/\" + purchase_order.id\n\n HTTP.put(url, payload).then(resolve, reject)\n })\n }\n}\n","import { HTTP } from \"./Connection\"\n\nexport class SalesOrderItemService {\n\n static update (sales_order_item) {\n return new Promise((resolve, reject) => {\n const id = sales_order_item.id\n HTTP.put(\"/api/buyer_order_items/\" + id, sales_order_item).then(resolve, reject)\n })\n }\n\n static destroy (id) {\n return new Promise((resolve, reject) => {\n HTTP.delete(\"/api/buyer_order_items/\" + id).then(resolve, reject)\n })\n }\n\n static create (sales_order_item) {\n return new Promise((resolve, reject) => {\n const url = \"/api/buyer_order_items\"\n HTTP.post(url, sales_order_item).then(resolve, reject)\n })\n }\n}\n","const { parseISO, format } = require('date-fns');\n\nexport function asCurrency(price) {\n const numericPrice = Number(price)\n const asCurrency = numericPrice.toLocaleString('en-US', { style: 'currency', currency: 'USD' })\n if (numericPrice < 0)\n return \"(\" + asCurrency.substr(1) + \")\"\n else\n return asCurrency\n}\n\nexport function isTomorrow(dateString) {\n const tomorrowDate = new Date();\n tomorrowDate.setDate(tomorrowDate.getDate() + 1)\n return dateString == tomorrowDate.toLocaleDateString('en-CA', { timeZone: \"America/New_York\" })\n}\n\nexport function isToday(dateString) {\n const tomorrowDate = new Date();\n tomorrowDate.setDate(tomorrowDate.getDate())\n return dateString == tomorrowDate.toLocaleDateString('en-CA', { timeZone: \"America/New_York\" })\n}\n\nexport function stripZeros(numberString) {\n const numericNumber = Number(numberString)\n return parseFloat(numericNumber.toFixed(4));\n}\n\nexport function formatDate(dateString) {\n const date = parseISO(dateString);\n const formattedDate = format(date, 'EEE M/d');\n return formattedDate;\n}","import ahoy from 'ahoy.js';\n\n// override defaults\nahoy.configure({\n visitsUrl: \"/ahoyyy/visits\",\n eventsUrl: \"/ahoyyy/events\"\n})\n\ndocument.addEventListener(\"turbo:load\", function(){\n ahoy.trackClicks(\".dataTable th\");\n});\n","document.addEventListener(\"turbo:load\", function(){\n $('[data-toggle=\"tooltip\"]').tooltip()\n $('.modal.start-open').modal('show')\n});\n\ndocument.addEventListener(\"turbo:before-cache\", function() {\n $('.tooltip.show').remove()\n});\n","document.addEventListener(\"turbo:load\", function(){\n $(function () {\n $(\".chosen-select:not([multiple]\").selectize({ onDropdownOpen: function () {\n this.clear();\n }, selectOnTab: false, allowEmptyOption: true });\n $('.chosen-select[multiple=\"multiple\"]').selectize({ plugins: ['remove_button'], selectOnTab: false, allowEmptyOption: true });\n });\n\n $(\"#existing-order-checker\").selectize({\n onDropdownOpen: function () { this.clear() },\n selectOnTab: false,\n allowEmptyOption: true,\n onChange: function(value) {\n if (value) {\n var path = this.$input.data('path')\n $.get(path, {'buyer_order[buyer_id]':value}, null, 'script' );\n }\n }\n });\n $(\"#chooseAllBuyerCategories\").on('click', function() {\n var options = Object.values($('#buyer_category_id')[0].selectize.options)\n options.sort((a, b) => { return a.$order - b.$order; });\n var optionsArray = options.map(function(obj) { return obj.value })\n var selectized = $('#buyer_category_id')[0].selectize\n selectized.setValue(optionsArray)\n })\n\n $(\"#chooseNoBuyerCategories\").on('click', function() {\n $('#buyer_category_id')[0].selectize.setValue([])\n })\n\n $(\"#chooseAllBuyers\").on('click', function() {\n var options = Object.values($('#buyer_id')[0].selectize.options)\n options.sort((a, b) => { return a.$order - b.$order; });\n var optionsArray = options.map(function(obj) { return obj.value })\n var selectized = $('#buyer_id')[0].selectize\n selectized.setValue(optionsArray)\n })\n\n $(\"#chooseNoBuyers\").on('click', function() {\n $('#buyer_id')[0].selectize.setValue([])\n })\n\n $(\"#chooseAllProducers\").on('click', function() {\n var options = Object.values($('#producer_id')[0].selectize.options)\n options.sort((a, b) => { return a.$order - b.$order; });\n var optionsArray = options.map(function(obj) { return obj.value })\n var selectized = $('#producer_id')[0].selectize\n selectized.setValue(optionsArray)\n })\n\n $(\"#chooseNoProducers\").on('click', function() {\n $('#producer_id')[0].selectize.setValue([])\n })\n $(\"#chooseAllCategories\").on('click', function() {\n var options = Object.values($('#category_id')[0].selectize.options)\n options.sort((a, b) => { return a.$order - b.$order; });\n var optionsArray = options.map(function(obj) { return obj.value })\n var selectized = $('#category_id')[0].selectize\n selectized.setValue(optionsArray)\n })\n $(\"#chooseNoCategories\").on('click', function() {\n $('#category_id')[0].selectize.setValue([])\n })\n\n $(\"#chooseNoSellers\").on('click', function() {\n $('#seller_id')[0].selectize.setValue([])\n })\n $(\"#chooseAllSellers\").on('click', function() {\n var options = Object.values($('#seller_id')[0].selectize.options)\n options.sort((a, b) => { return a.$order - b.$order; });\n var optionsArray = options.map(function(obj) { return obj.value })\n var selectized = $('#seller_id')[0].selectize\n selectized.setValue(optionsArray)\n })\n\n $(\"#chooseMktSellers\").on('click', function(event) {\n var ids = event.target.dataset.ids.split(',')\n var selectized = $('#seller_id')[0].selectize\n\n for (var i = 0; i < ids.length; i++) {\n selectized.addItem(ids[i]);\n }\n })\n});\n\ndocument.addEventListener(\"turbo:before-cache\", function(){\n $('.selectized').each(function () {\n this.selectize.destroy();\n var selectedOption = this.querySelector(\"option[selected]\");\n // destroying removes the selected value, so we have to manually reset it\n if (selectedOption) {\n this.value = selectedOption.value;\n } else if (!this.multiple) {\n this.value = this.options[0].value;\n }\n });\n});\n","document.addEventListener(\"turbo:load\", function(){\n var datatable = $('table.datatable-init').DataTable({ stateSave: true })\n $('#outside-filter-input').on('keyup', function() {\n datatable.api().search($(this).val()).draw();\n });\n\n document.addEventListener(\"turbo:before-cache\", function() {\n datatable.api().destroy()\n })\n});\n","document.addEventListener(\"turbo:load\", function(){\n $(document).on('change', '#range-name-select', function(event) {\n if (event.target.value == 'custom_dates') {\n $(this).closest('.range-name-picker').find('.collapse').collapse('show');\n } else {\n $(this).closest('.range-name-picker').find('.collapse').collapse('hide');\n }\n })\n});","document.addEventListener('turbo:load', () => {\n const inputs = document.querySelectorAll('#deposits-list input[type=checkbox]');\n\n for (let i = 0; i < inputs.length; i++) {\n const input = inputs[i];\n\n input.addEventListener('change', (event) => {\n const totalElement = document.querySelector('#deposit-total')\n const total = parseFloat(totalElement.innerHTML.replace(/[^0-9.-]+/g,\"\"))\n let change = Number(event.target.getAttribute('data-value'))\n\n if (!event.target.checked) { change = -change }\n const newTotal = total + change\n\n const formatted = newTotal.toLocaleString('en-US', { style: 'currency', currency: 'USD' })\n totalElement.innerHTML = formatted\n });\n }\n})\n","document.addEventListener('turbo:load', () => {\n var flatpickr_options = {\n altInput: true,\n altFormat: \"D M j Y\",\n dateFormat: \"Ymd\"\n }\n flatpickr('.flatpickr-init', flatpickr_options)\n})\n\ndocument.addEventListener('turbo:load', () => {\n var flatpickr_options = {\n enableTime: true,\n altInput: true,\n altFormat: \"D M j Y @ h:i K\",\n dateFormat: \"Z\"\n }\n flatpickr('.flatpickr-init-show-time', flatpickr_options)\n})\n\ndocument.addEventListener('turbo:load', () => {\n var flatpickr_options = {\n multiple: true\n }\n flatpickr('.flatpickr-init-multiple', flatpickr_options)\n})\n\ndocument.addEventListener('turbo:load', () => {\n var flatpickr_options = {\n enableTime: true,\n altInput: true,\n altFormat: \"D M j Y @ h:i K\",\n dateFormat: \"YmdHiS\"\n }\n flatpickr('.flatpickr-init-new-show-time', flatpickr_options)\n})\n\ndocument.addEventListener('turbo:load', () => {\n var flatpickr_options = {\n inline: true,\n onChange: function(selectedDates, dateStr, instance) {\n var form = document.querySelector('#expected-on-form');\n Rails.fire(form, \"submit\")\n },\n onDayCreate: function(dObj, dStr, fp, dayElem) {\n var highlightDays = JSON.parse(fp.element.dataset.schedule || null)\n if (highlightDays.indexOf(dayElem.dateObj.toISOString().slice(0,10)) !== -1) {\n dayElem.className += \" route-available\";\n }\n }\n }\n flatpickr('.expected-on-picker-init', flatpickr_options)\n})\n\ndocument.addEventListener('turbo:load', () => {\n var flatpickr_options = {\n minDate: 'today',\n inline: true,\n onChange: function(selectedDates, dateStr, instance) {\n var input = instance._input;\n var form = $(input).closest('form')[0];\n Rails.fire(form, \"submit\")\n }\n }\n flatpickr('.new-po-picker-init', flatpickr_options)\n})\n\ndocument.addEventListener('turbo:load', () => {\n var flatpickr_options = {\n inline: true,\n dateFormat: \"Ymd\",\n onChange: function(selectedDates, dateStr, instance) {\n var input = instance._input;\n var form = $(input).closest('form')[0];\n Rails.fire(form, \"submit\")\n }\n }\n flatpickr('.submit-on-date-picked', flatpickr_options)\n})\n\ndocument.addEventListener('turbo:load', () => {\n $('#main').on('show.bs.dropdown', '.available-on-dropdown', function () {\n var flatpickr_options = {\n inline: true,\n minDate: 'today',\n dateFormat: \"Ymd\"\n }\n flatpickr('.available-on-picker-init', flatpickr_options)\n })\n})\n\ndocument.addEventListener('turbo:load', () => {\n $('#main').on('show.bs.dropdown', '#expires-on-edit-dropdown', function () {\n var flatpickr_options = {\n inline: true,\n altInput: true,\n altFormat: \"D M j Y\",\n dateFormat: \"Ymd\"\n }\n flatpickr('.expires-on-picker-init', flatpickr_options)\n })\n})\n\ndocument.addEventListener('turbo:load', function() {\n $('#order-receiving').on('click', 'button.add-item', function(event) {\n var element = $(this).closest('.receiving-order-item').find('.flatpickr-init2')\n\n if (element.hasClass('flatpickr-input'))\n return\n\n var flatpickr_options = {\n altInput: true,\n minDate: 'today',\n altFormat: \"D M j Y\",\n dateFormat: \"Ymd\"\n }\n\n flatpickr('#order-receiving .flatpickr-init2:not(.flatpickr-input)', flatpickr_options)\n })\n\n var flatpickr_options = {\n altInput: true,\n minDate: 'today',\n altFormat: \"D M j Y\",\n dateFormat: \"Ymd\"\n }\n\n flatpickr('#order-receiving .flatpickr-init2', flatpickr_options)\n\n})\n\ndocument.addEventListener(\"turbo:before-cache\", function() {\n $('.flatpickr-calendar').remove()\n $(\"input.flatpickr-input[type='hidden']\").each(function() {\n $(this).attr('type', 'text')\n $(this).removeClass('flatpickr-input')\n $(this).next('input').remove()\n })\n})\n","document.addEventListener(\"turbo:load\", function(){\n mapboxElement = document.getElementById('mapbox-map');\n if (!mapboxElement) { return }\n\n mapboxgl.accessToken = mapboxElement.dataset.token\n var map = new mapboxgl.Map({\n container: 'mapbox-map',\n style: 'mapbox://styles/mapbox/streets-v12',\n bounds: JSON.parse(mapboxElement.dataset.bounds)\n });\n\n var routes = JSON.parse(mapboxElement.dataset.routeMarkers);\n\n routes.forEach(function(route, index) {\n route.markers.forEach(function(marker) {\n // create a HTML element for each feature\n var el = document.createElement('div');\n el.className = 'marker';\n if ( !marker.coordinates ) { alert( `${ marker.name } has no address`); return }\n // make a marker for each feature and add it to the map\n new mapboxgl.Marker({ color: route.color})\n .setLngLat(marker.coordinates)\n .setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups\n .setHTML(`
${ marker.name }
${ route.name }
`))\n .addTo(map);\n })\n });\n})\n\ndocument.addEventListener(\"turbo:load\", function(){\n mapboxElement = document.getElementById('mapbox-directions');\n if (!mapboxElement) { return }\n\n mapboxgl.accessToken = mapboxElement.dataset.token\n\n var routes = JSON.parse(mapboxElement.dataset.routes)\n\n var map = new mapboxgl.Map({\n container: mapboxElement.id,\n style: 'mapbox://styles/mapbox/streets-v12',\n bounds: JSON.parse(mapboxElement.dataset.bounds)\n });\n\n map.loadImage('https://cdn-icons-png.flaticon.com/128/17470/17470552.png', (error, image) => {\n if (error) throw error;\n map.addImage('arrow', image);\n })\n\n map.on('load', () => {\n routes.forEach(function(solution_route, index) {\n var stops = solution_route.stops;\n\n for (let i = 0; i < stops.length; i += 24) {\n const limited_stops = stops.slice(Math.max(0, i-1), i + 24);\n var coordinates = limited_stops.map(n => n.coordinates )\n const url = `https://api.mapbox.com/directions/v5/mapbox/driving/${coordinates.join(';')}?geometries=geojson&access_token=${mapboxgl.accessToken}`;\n fetch(url)\n .then(response => response.json())\n .then(data => {\n const route = data.routes[0].geometry;\n const sourceName = `route-${ index }-${ i }`\n // Step 5: Add Route to the Map\n map.addSource(sourceName, {\n type: 'geojson',\n data: {\n type: 'Feature',\n properties: {},\n geometry: route\n }\n });\n\n map.addLayer({\n id: `route-line-${ index }-${ i }`,\n type: 'line',\n source: sourceName,\n layout: {\n 'line-join': 'round',\n 'line-cap': 'round'\n },\n paint: {\n 'line-color': solution_route.color,\n 'line-width': 8\n }\n });\n\n map.addLayer({\n id: `route-arrows-${ index }-${ i }'`,\n type: 'symbol',\n source: sourceName,\n layout: {\n 'symbol-placement': 'line',\n 'symbol-spacing': 100, // Adjust spacing between arrows\n 'icon-image': 'arrow',\n 'icon-allow-overlap': true,\n 'icon-ignore-placement': true,\n 'icon-size': 0.15 // Adjust arrow size\n }\n });\n // Step 6: Add Markers for Each Coordinate\n for (let index = stops.length; index > 0; index -= 1) {\n const stop = stops[index-1]\n const el = document.createElement('div');\n el.className = 'map-pin';\n if (stop.type == 'end') { el.className = 'map-pin map-end' }\n if (stop.type == 'start') { el.className = 'map-pin map-start' }\n const numberEl = document.createElement('div');\n numberEl.className = 'map-pin-number';\n numberEl.textContent = index + 1; // Display the index as a label\n el.appendChild(numberEl);\n\n new mapboxgl.Marker(el)\n .setLngLat(stop.coordinates)\n .setPopup(new mapboxgl.Popup({ offset: 25 })\n .setHTML(`
${ stop.name }
${ stop.eta }
`))\n .addTo(map);\n\n }\n })\n }\n })\n })\n})\n","$(document).on('click', '.collapse-open-all', function (e) {\n document.querySelectorAll('.collapse').forEach(\n (col) => { $(col).toggleClass('show') }\n )\n})\n","document.addEventListener('turbo:load', () => {\n // add multiple select / deselect functionality\n const checkAlls = document.querySelectorAll('.selectall');\n checkAlls.forEach((checkAll) => {\n checkAll.addEventListener('change', () => {\n const checkboxes = checkAll.closest('form').querySelectorAll('.case');\n checkboxes.forEach(checkbox => checkbox.checked = checkAll.checked);\n checkboxes.forEach(checkbox => checkbox.dispatchEvent(new Event('change')));\n })\n });\n\n $(\".selectall-new\").on('click', function() {\n var checkAll = $(this).prop('checked');\n if (checkAll) {\n $(this).closest(\".selectall-container\").find(\".case\").prop(\"checked\", true);\n } else {\n $(this).closest(\".selectall-container\").find(\".case\").prop(\"checked\", false);\n }\n });\n\n $('button[data-collect=\"true\"]').on('click', function() {\n var editMultipleForm = $(this).closest(\"form\")\n editMultipleForm[0].querySelectorAll('.selectall-container input[name=\"ids[]\"]').forEach(\n function(existingInput) { existingInput.remove() }\n )\n $(this).closest(\".selectall-container\").find('.case:checked').each(\n function() {\n var value = $(this).val()\n var newInput = '
'\n editMultipleForm.prepend(newInput)\n }\n )\n });\n\n $('button[data-toggle=\"reroute-multiple-modal\"]').on('click', function(event) {\n var contentSection = $('#update-multiple-routes .content')\n\n contentSection.html('')\n $(this).data().orderIds.forEach(\n function(id) {\n var newInput = '
'\n contentSection.prepend(newInput)\n }\n )\n $(this).data().addresses.forEach(\n function(address) {\n var newInput = '
'\n contentSection.prepend(newInput)\n }\n )\n text = '
' + $(this).data().orderIds.length + ' orders
'\n contentSection.prepend(text)\n $('#reroute-multiple-modal').modal()\n });\n\n // if all checkbox are selected, check the selectall checkbox and vice versa\n $(\".case\").click(function(){\n if ($(this).closest(\"form\").find(\".case\").length == $(this).closest(\"form\").find(\".case:checked\").length) {\n $(this).closest(\"form\").find(\".selectall\").prop(\"checked\", true);\n } else {\n $(this).closest(\"form\").find(\".selectall\").prop(\"checked\", false);\n }\n });\n})\n","document.addEventListener('turbo:load', () => {\n if ( !document.getElementById('edit-dashboard') ) { return }\n\n const left = document.getElementById('left-column')\n const center = document.getElementById('center-column')\n const right = document.getElementById('right-column')\n const unused = document.getElementById('unused-column')\n\n const movedDashboard = function (evt) {\n const payload = {\n dashboard: evt.item.dataset.name,\n column: evt.to.dataset.column || '',\n position: evt.newIndex\n }\n\n const data = new URLSearchParams(payload).toString()\n Rails.ajax({\n url: \"/admin/dashboard\",\n type: \"PATCH\",\n data: data\n })\n\t}\n\n new Sortable(left, {\n group: 'shared',\n animation: 150,\n emptyInsertThreshold: 20,\n ghostClass: 'list-group-item-primary',\n onEnd: movedDashboard\n });\n\n new Sortable(center, {\n group: 'shared',\n animation: 150,\n emptyInsertThreshold: 20,\n ghostClass:'list-group-item-primary',\n onEnd: movedDashboard\n });\n\n new Sortable(right, {\n group: 'shared',\n animation: 150,\n emptyInsertThreshold: 20,\n ghostClass: 'list-group-item-primary',\n onEnd: movedDashboard\n });\n\n new Sortable(unused, {\n group: 'shared',\n filter: '.no-drag',\n animation: 150,\n emptyInsertThreshold: 20,\n ghostClass: 'list-group-item-primary',\n onEnd: movedDashboard\n });\n\n})\n","// Quick and simple export target #table_id into a csv\nfunction download_table_as_csv(table_id, separator = ',') {\n // Select rows from table_id\n var rows = document.querySelectorAll(table_id + ' tr');\n // Construct csv\n var csv = [];\n for (var i = 0; i < rows.length; i++) {\n var row = [], cols = rows[i].querySelectorAll('td, th');\n for (var j = 0; j < cols.length; j++) {\n // Clean innertext to remove multiple spaces and jumpline (break csv)\n var data = cols[j].innerText.replace(/(\\r\\n|\\n|\\r)/gm, '').replace(/(\\s\\s)/gm, ' ')\n // Escape double-quote with double-double-quote (see https://stackoverflow.com/questions/17808511/properly-escape-a-double-quote-in-csv)\n data = data.replace(/\"/g, '\"\"');\n // Push escaped string\n row.push('\"' + data + '\"');\n }\n csv.push(row.join(separator));\n }\n var csv_string = csv.join('\\n');\n // Download it\n var filename = 'export_' + table_id + '_' + new Date().toLocaleDateString() + '.csv';\n var link = document.createElement('a');\n link.style.display = 'none';\n link.setAttribute('target', '_blank');\n link.setAttribute('href', 'data:text/csv;charset=utf-8,' + encodeURIComponent(csv_string));\n link.setAttribute('download', filename);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n}\n\ndocument.addEventListener('turbo:load', () => {\n $('body').on('click', '.download-table', (event) => {\n const tableId = event.target.dataset.target;\n download_table_as_csv(tableId)\n })\n})\n","var findAndCreateTimeout = function() {\n var timeoutRequestElement = document.querySelector('.timeout-request')\n if (!timeoutRequestElement) { return }\n\n var pollPath = timeoutRequestElement.dataset.path\n var useTurbo = timeoutRequestElement.dataset.useTurbo\n\n var requestAsync = function() { Rails.ajax({url: pollPath, type: 'GET'}) }\n var requestTurbo = function() { Turbo.visit(pollPath) }\n var request = useTurbo ? requestTurbo : requestAsync\n\n var msDelay = Number(timeoutRequestElement.dataset.msDelay)\n setTimeout(request, msDelay)\n}\n\ndocument.addEventListener('turbo:load', findAndCreateTimeout)\n"],"names":["map","webpackContext","req","id","webpackContextResolve","__webpack_require__","o","e","Error","code","keys","Object","resolve","module","exports","document","addEventListener","$","remove","dropdown","on","this","find","append","modal","window","location","reload","each","formatted","date","seconds","Math","floor","Date","interval","timeSince","data","html","val","trigger","toggleClass","event","target","value","closest","collapse","shiftPressedTimes","shiftTimer","key","clearTimeout","setTimeout","toLowerCase","preventDefault","once","form","laid_in_cost","Number","toFixed","isNaN","Rails","fire","popover","product_unit_id","as_of_date","ajax","url","dataType","type","options","delay","show","hide","self","timeout","hoverState","open","item_id","ClipboardJS","input","icon","removeClass","addClass","change","click","text","siblings","prop","dataset","add","quantityInput","currentQty","max","submit","checked","is","current_value","estimate_value","estimate","updatePaymentTotal","newTotal","expectedTotal","updateRemainingBalance","totalApplied","newValue","sumApplied","remaining","totalRemaining","toSet","min","pk","stripe","Stripe","cardOptions","iconStyle","style","base","fontSize","fontWeight","fontFamily","color","backgroundColor","cardElement","elements","create","mount","cardButton","getElementById","clientSecret","secret","ev","radioButton","querySelector","payload","cardholderName","payment_method","card","billing_details","name","setup_future_usage","slideUp","confirmCardPayment","then","result","error","message","slideDown","setupIntentElement","published_key","fields","billingDetails","billingName","async","confirmSetup","confirmParams","return_url","returnTo","textContent","routing_number","account_number","account_holder_name","account_holder_type","createToken","country","currency","token","hidePostalCode","borderRadius","confirmCardSetup","PurchaseOrderEdit","React","constructor","props","super","onItemCreate","bind","onItemDestroy","onItemUpdate","onNewItemSubtotalUpdate","onChangePurchaseOrder","save","_","toggleName","state","purchase_order","newItemSubtotal","scrubbed_purchase_order","note_from_buyer","PurchaseOrderService","toast","className","setState","showName","calculateTotalDeposit","buyer_order_items","purchase_order_item","deposit_subtotal","reduce","a","b","buyer_order_item","existing","new_buyer_order_items","push","item_to_remove","new_buyer_order_item","indexToReplace","calculateTotal","total","discount","renderItemRows","items","length","item","product_unit","product_name","order_item","PurchaseOrderItemEdit","showCatchWeight","updatedPurchaseOrderItem","deletedPurchaseOrderItem","renderDiscountRow","clasName","asCurrency","renderSubtotalRow","subtotal","renderDepositRow","renderTotalRow","renderName","purchaseOrderName","buttonText","onChange","onClick","renderSubmitButton","status","href","render","PurchaseOrderItemNew","createdPurchaseOrderItem","onSubtotalUpdate","position","autoClose","bodyClassName","hideProgressBar","newestOnTop","closeOnClick","pauseOnHover","onChangeQuantity","onDelete","changePurchaseOrderItem","debounce","PurchaseOrderItemService","newQuantity","quantity","new_purchase_order_item","toggleAdvanced","showAdvanced","renderDeleteButton","renderCatchWeightDescription","actual_unit_price","catch_weight","actual_quantity","unit","catch_weight_unit","item_unit","denominatorUnit","rate","warningClass","classNames","renderNote","note_from_seller","renderDepositDescription","deposit_average","renderDeposit","renderDepositSubtotal","renderSubtotal","renderQuantity","QuantitySelect","minimum","quantity_minimum","maximum","quantity_maximum","initial","renderCatchWeightInput","placeholder","renderUnavailable","is_published","unavailable_until_description","rowClass","src","product_photo","small_url","height","producer_name","effective_unit_price","quantitySelect","addButton","onCreate","onProductUnitSelected","notifyParentOfSubtotalChange","buyer_order_id","current","refocus","calculateSubtotal","focus","ref","renderUnitPrice","price","buttonClass","disabled","ProductUnitSelect","published","seller_id","fetcher","CatalogFetcher","unavailable_type","AddToCart","addToCartBackorder","addToCart","renderQuantityInput","showPricing","cartEnabled","QuantityInput","unitId","dontCare","buyer_order_item_params","addItem","backorder","renderAddToCart","colorClass","addToCartFunction","renderAvailability","renderQtyAndButton","Cart","visible","toggle","seeOrder","path","seller_browsing","buyer_order","removeItem","order_item_id","confirm","removeOrderItem","updateOrderItemQuantity","buyer_order_item_id","renderProducts","CartItem","showProducer","editQuantity","orderTotal","x","itemCount","body","edit","confirmEdit","renderNotAvailable","renderBackordered","renderOriginalSubtotal","original_subtotal","width","DeliveryDatePicker","chooseDate","toggleDatePicker","showDatePicker","formatDate","date_string","isTomorrow","toLocaleDateString","weekday","month","day","renderButtons","available_days","renderActiveButton","renderDisabledButton","monthName","string_date","slice","isToday","active","requested_on","renderDropdown","OrderCatalog","createOrUpdateItem","createOrderAndItem","updateRequestedOn","buyer_id","seller","newUrl","history","replaceState","index","findIndex","removeItemFromBuyerOrder","without","renderCart","accepting_orders","ProductCatalog","page","batch","params","private_catalog_id","producers","categories","collections","requested_on_options","preloaded_products","requestedOn","cart","startTerm","selectedProducerId","Product","expanded","openGallery","showDiscountIndicator","product","discount_price","renderProducerCity","city","renderProducerName","renderProductImage","showImage","imageContainerClassNames","image","note","renderListProduct","ProductUnitPrice","description","renderGridProduct","productContainerClasses","ProductUnitDeposit","Catalog","addItemToCart","changeLayoutToList","changeLayoutToGrid","changeGalleryIndex","closeGallery","requestProductDetail","toggleLocalOnly","setSort","toggleFilters","setProducer","setRequestedOn","toggleIsStocked","changeLayoutToListNoImages","search","fetchProducts","grid","list","listNoImg","isStocked","showGallery","layout","pageCount","currentPage","batchSize","filters","sortBy","collection","subcollection","localOnly","empty","productCount","loadingResults","pagedProducts","initialProductRequest","buildParams","productBatch","requestProductCount","loadProducts","ahoy","modulus","newIndex","productSlug","product_slug","response","otherProducts","searchParams","count","newPageCount","ceil","buyerId","requestProducts","componentDidMount","validSearch","addedProducts","changeSearchTerm","newSearchTerm","previousSearchTerm","trim","term","showFilters","changePage","desiredPage","offsetPosition","getBoundingClientRect","top","pageYOffset","scrollTo","behavior","changeFilters","setCategory","category","setCollection","collectionSlug","setSubcollection","currentTarget","newIsStocked","renderPageTabs","tabs","starting","len","i","language","renderLayoutButtons","changeLayoutGridButtonClass","changeLayoutListButtonClass","changeLayoutListNoImagesButtonClass","role","renderProductList","renderNoResults","loadedPageCount","renderSearchNotifier","category_list","collectionName","slug","current_children","producer_list","terms","concat","today","tomorrow","setDate","getDate","join","start","currentEnd","countMsg","renderWaitSpinner","renderOrderDeadlineText","ordering_message","renderSellerLogo","logoContent","logo_url","renderCategoryToggles","classes","renderCollections","renderCollectionToggles","collectionClasses","children","child_collection","subcollectionClasses","renderIsStocked","placement","renderProducers","producerOptions","producer","city_state","htmlFor","renderRequestFor","values","filter","element","renderDownload","renderLocalOnlyToggle","renderSort","selected","sidebarToggleClass","ProductGallery","SearchBar","handleSwipe","handleKeyPress","componentWillUnmount","removeEventListener","keyCode","next","previous","direction","stopPropagation","renderDisplay","renderIndividualUnitPrice","individual_unit_name","individual_unit_price","renderProductUnits","other_product_units","otherUnits","show_unit","Boolean","rightarrow","leftarrow","city_state_tag","large_url","onSwipe","deposit","showDiscountPrice","renderDiscountUnitPrice","discount_unit_price","renderDiscountPrice","renderCatchWeight","formattedUnitPrice","catch_weight_unit_price","formattedPrice","PublicCatalog","upperLimit","handleChange","newval","parseInt","reset","flatMap","y","subslug","subname","pickCollection","all","fuse","Fuse","includeScore","threshold","weight","parentSlug","renderMatchingCollections","autoComplete","Forecast","renderForecastUpArrow","forecast","arrowClass","in_qty","arrow","renderForecastDownArrow","out_qty","forecastStyling","close_qty","is_sequence","is_replenishment","renderForecast","multiplier","split_multiplier","forecast_columns","forecasts","forecast_day","stocked_qty","openOrder","earliest_draft_po","title","parseFloat","renderHeader","dateOptions","timeZone","headers","formattedDate","replace","OrderInfo","renderStatusIcon","renderDate","order","fulfillment_expected_on","stripZeros","total_quantity","Option","innerProps","option","availableIcon","mutedUnavailable","strikethroughClass","discountPrice","c","Input","SingleValue","searchInput","onInputChange","inputValue","isLoading","products","filterOption","noOptionsMessage","components","isOptionSelected","maxMenuHeightnumber","isClearable","closeOnTab","negativePattern","RegExp","allowDecimal","positivePattern","showMenu","checkNumeric","onlyNegativeQuantity","test","changeTo","closeMenu","select","renderQuantityButtons","mult","which","quantityAsNumber","inputClasses","onKeyDown","BuyerOrderService","static","Promise","reject","HTTP","InventoryForecastService","OrderItemMoveService","sales_order_item_id","move_attributes","order_item_move","SalesOrderEdit","onChangeBuyerOrder","changeOrder","changeSortMethod","toggleForecast","showForecast","open_orders","sortMethod","scrubbed_buyer_order","update","move_type","new_order_id","notes","reason","to_order_id","to_order","buyerOrder","loadingForecast","query","subtotals","overpayment_credit","productUnitCounts","sortedItems","created_at","forecast_product_unit_id","split_product_unit_id","SalesOrderItemEdit","isPurchaseOrder","credit","sales_order_item","showProducerName","updatedSalesOrderItem","String","commonInternalNotes","orderProductUnitCount","deletedSalesOrderItem","renderAfterSubtotalRows","renderOverpaymentRow","payment_id","endsWith","renderButton","contactCount","action","acceptCharset","method","csrf_token","renderForecastButton","forecastActive","renderSortButtons","timeActive","nameActive","renderOrderButtons","orderLinks","SalesOrderItemNew","sales_order","createdSalesOrderItem","onMoveRadioChanged","changeSalesOrderItem","changePriceOverride","changeSubtotalOverride","copyInternalNote","moveRadio","moveType","existingOrderId","errorMessages","errorMessage","internal_seller_note","newMoveRadio","newStateValues","undefined","SalesOrderItemService","new_sales_order_item","calculated_subtotal","renderSticky","lineId","iconLetter","tooltipText","renderNoteInput","internalNote","renderReasonDropdown","renderMove","draftOrderButtons","open_order","renderAdvancedEdit","renderSellerNote","reasonButtons","renderBuyerNote","renderInternalSellerNote","renderSubtotalOverride","subtotal_override","price_override","maxWidth","renderDepositOverride","deposit_override","renderOriginalEffectivePrice","original_effective_price","renderBackorder","renderSrc","unavailable_until","split","productUnitSelect","initialQuantity","showUnavailable","application","Application","debug","Stimulus","Controller","connect","showPopover","hidePopover","fetchPopoverContent","popoverElement","cancelHidePopover","startHidePopover","disconnect","off","clone","targetForm","cloneFrom","clonerCloneFrom","clonedElement","cloneNode","register","ProductUnitActivityPopoverController","SimplePopoverController","ClonerController","fn","DataTable","require","global","Sortable","LocalTime","Chart","ChartDataLabels","font","size","mapboxgl","componentRequireContext","ReactRailsUJS","useContext","handleEvent","handleMount","handleUnmount","sellerId","catalogId","buyer","privateCatalog","categoriesSearch","collectionsSearch","producersSearch","textSearch","isFeatured","encodeURIComponent","success","failure","xhr","XMLHttpRequest","onload","handleResponse","JSON","parse","responseText","send","setRequestHeader","stringify","parseISO","format","numericPrice","toLocaleString","substr","dateString","tomorrowDate","numberString","numericNumber","visitsUrl","eventsUrl","tooltip","selectize","onDropdownOpen","clear","selectOnTab","allowEmptyOption","plugins","$input","get","sort","$order","optionsArray","obj","setValue","ids","selectized","destroy","selectedOption","multiple","datatable","stateSave","api","draw","inputs","querySelectorAll","totalElement","innerHTML","getAttribute","flatpickr","altInput","altFormat","dateFormat","enableTime","inline","selectedDates","dateStr","instance","onDayCreate","dObj","dStr","fp","dayElem","schedule","indexOf","dateObj","toISOString","minDate","_input","hasClass","attr","mapboxElement","accessToken","Map","container","bounds","routeMarkers","forEach","route","markers","marker","createElement","coordinates","Marker","setLngLat","setPopup","Popup","offset","setHTML","addTo","alert","routes","loadImage","addImage","solution_route","stops","n","fetch","json","geometry","sourceName","addSource","properties","addLayer","source","paint","stop","el","numberEl","appendChild","eta","col","checkAll","checkboxes","checkbox","dispatchEvent","Event","editMultipleForm","existingInput","newInput","prepend","contentSection","orderIds","addresses","address","left","center","right","unused","movedDashboard","evt","dashboard","column","to","URLSearchParams","toString","group","animation","emptyInsertThreshold","ghostClass","onEnd","table_id","separator","rows","csv","row","cols","j","innerText","csv_string","filename","link","display","setAttribute","removeChild","download_table_as_csv","timeoutRequestElement","pollPath","request","useTurbo","Turbo","visit","msDelay"],"sourceRoot":""}