{"version":3,"file":"js/application-9175d5587d7523ca579f.js","mappings":"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","sources":["webpack://app/./app/javascript/controllers/ sync _controller\\.js$","webpack://app/./app/javascript/controllers/bulk_activities_controller.js","webpack://app/./app/javascript/helpers/index.js","webpack://app/./app/javascript/controllers/dropzone_controller.js","webpack://app/./app/javascript/controllers/index.js","webpack://app/./app/javascript/application.js"],"sourcesContent":["var map = {\n\t\"./bulk_activities_controller.js\": 258,\n\t\"./dropzone_controller.js\": 364,\n\t\"controllers/bulk_activities_controller.js\": 258,\n\t\"controllers/dropzone_controller.js\": 364\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 124;","// app/javascript/controllers/bulk_activities_controller.js\nimport { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [\"form\", \"activitiesContainer\", \"activityTemplate\", \"submitButton\", \"errorContainer\"]\n\n connect() {\n this.activityCounter = 0\n\n // Check if there are submitted activities from a previous submission\n if (document.querySelector('[data-submitted-activities]')) {\n const submittedActivities = JSON.parse(document.querySelector('[data-submitted-activities]').dataset.submittedActivities)\n if (submittedActivities && submittedActivities.length > 0) {\n // Add each submitted activity\n submittedActivities.forEach(activity => {\n this.addActivityWithValues(activity)\n })\n } else {\n // If no submitted activities, add a blank one\n this.addActivity()\n }\n } else {\n // No submitted activities, add a blank one\n this.addActivity()\n }\n\n // Check if there are validation errors passed from the server\n if (this.hasErrorContainerTarget && this.errorContainerTarget.dataset.errors) {\n const errors = JSON.parse(this.errorContainerTarget.dataset.errors)\n this.displayErrors(errors)\n }\n }\n\n // New method to add an activity with pre-filled values\n addActivityWithValues(activityData) {\n const id = this.activityCounter++\n const template = this.activityTemplateTarget.innerHTML\n .replace(/\\${id}/g, id)\n\n this.activitiesContainerTarget.insertAdjacentHTML('beforeend', template)\n\n // Initialize select2 for the newly added activity selector\n this.initializeSelect2ForActivity(id)\n\n // Set the values\n const row = this.element.querySelector(`.activity-row[data-activity-id=\"${id}\"]`)\n if (row) {\n const activitySelect = row.querySelector('.activity-selector')\n const amountInput = row.querySelector('.amount-input')\n const dateInput = row.querySelector('input[type=\"date\"]')\n\n if (activitySelect && activityData.activity_id) {\n activitySelect.value = activityData.activity_id\n $(activitySelect).trigger('change') // Trigger select2 update\n }\n\n if (amountInput && activityData.amount) {\n amountInput.value = activityData.amount\n }\n\n if (dateInput && activityData.completed_at) {\n dateInput.value = activityData.completed_at\n }\n\n // Calculate miles\n this.calculateMiles({ currentTarget: { dataset: { activityId: id } } })\n }\n }\n\n addActivity() {\n const id = this.activityCounter++\n const template = this.activityTemplateTarget.innerHTML\n .replace(/\\${id}/g, id)\n\n this.activitiesContainerTarget.insertAdjacentHTML('beforeend', template)\n\n // Initialize select2 for the newly added activity selector\n this.initializeSelect2ForActivity(id)\n }\n\n initializeSelect2ForActivity(id) {\n const controller = this\n const selector = $(`.activity-selector[data-activity-id=\"${id}\"]`)\n\n selector.select2({\n placeholder: 'Select an activity',\n width: '100%',\n containerCssClass: 'form-control select2-container-height',\n dropdownCssClass: 'activity-dropdown'\n })\n\n selector.on(\"select2:close\", function (evt) {\n var context = $(evt.target);\n\n $(document).on(\"keydown.select2\", function (e) {\n if (e.which === 9) {\n var highlighted = context\n .data(\"select2\")\n .$dropdown.find(\".select2-results__option--highlighted\");\n\n if (highlighted && highlighted.length === 1) {\n $.fn.select2.amd.require([\"select2/utils\"], function (Utils) {\n var data = Utils.__cache[highlighted.data().select2Id].data;\n var $select2 = context.data('select2');\n $select2.trigger(\"select\", { data: data });\n });\n }\n }\n });\n\n setTimeout(function () {\n $(document).off(\"keydown.select2\");\n }, 1);\n })\n\n // Handle the select2:select event to update units and calculate miles\n selector.on('select2:select', function (e) {\n const activityId = $(this).data('activity-id')\n const selectedOption = this.options[this.selectedIndex]\n const units = selectedOption.dataset.units || 'minutes'\n\n const unitsLabel = controller.element.querySelector(`.units-label[data-activity-id=\"${activityId}\"]`)\n if (unitsLabel) {\n unitsLabel.textContent = units\n }\n\n // Create a synthetic event to pass to calculateMiles\n const syntheticEvent = { currentTarget: { dataset: { activityId } } }\n controller.calculateMiles(syntheticEvent)\n\n // Clear error when a value is selected\n const formGroup = $(this).closest('.form-group')[0]\n if (formGroup && formGroup.classList.contains('has-error')) {\n formGroup.classList.remove('has-error')\n const errorMessage = formGroup.querySelector('.help-block')\n if (errorMessage) {\n errorMessage.remove()\n }\n\n // Reset select2 border\n const select2Container = formGroup.querySelector('.select2-container')\n if (select2Container) {\n select2Container.style.borderColor = ''\n }\n }\n })\n }\n\n removeActivity(event) {\n const activityId = event.currentTarget.dataset.activityId\n const activityRow = this.element.querySelector(`.activity-row[data-activity-id=\"${activityId}\"]`)\n\n if (activityRow) {\n // Destroy select2 instance before removing the element\n $(`.activity-selector[data-activity-id=\"${activityId}\"]`).select2('destroy')\n activityRow.remove()\n }\n\n // Add a new activity if none remain\n if (this.activitiesContainerTarget.children.length === 0) {\n this.addActivity()\n }\n }\n\n updateUnits(event) {\n // This method is still needed for non-select2 events\n const activityId = event.currentTarget.dataset.activityId\n const selectedOption = event.currentTarget.selectedOptions[0]\n const units = selectedOption.dataset.units || 'minutes'\n\n const unitsLabel = this.element.querySelector(`.units-label[data-activity-id=\"${activityId}\"]`)\n if (unitsLabel) {\n unitsLabel.textContent = units\n }\n\n this.calculateMiles(event)\n\n // Clear error when a value is selected\n const formGroup = event.currentTarget.closest('.form-group')\n if (formGroup && formGroup.classList.contains('has-error')) {\n formGroup.classList.remove('has-error')\n const errorMessage = formGroup.querySelector('.help-block')\n if (errorMessage) {\n errorMessage.remove()\n }\n }\n }\n\n calculateMiles(event) {\n const activityId = event.currentTarget.dataset.activityId\n const activityRow = this.element.querySelector(`.activity-row[data-activity-id=\"${activityId}\"]`)\n\n const activitySelect = activityRow.querySelector('.activity-selector')\n const amountInput = activityRow.querySelector('.amount-input')\n const milesDisplay = activityRow.querySelector('.calculated-miles')\n\n if (activitySelect.value && amountInput.value) {\n const selectedOption = activitySelect.selectedOptions[0]\n const conversionFactor = parseFloat(selectedOption.dataset.conversionFactor) || 0\n const amount = parseFloat(amountInput.value) || 0\n\n const miles = (amount * conversionFactor).toFixed(2)\n milesDisplay.textContent = miles\n } else {\n milesDisplay.textContent = '0'\n }\n }\n\n validateForm() {\n let isValid = true\n const errors = {}\n\n // Get all activity rows\n const activityRows = this.element.querySelectorAll('.activity-row')\n\n activityRows.forEach((row, index) => {\n const activityId = row.dataset.activityId\n const activitySelect = row.querySelector('.activity-selector')\n const amountInput = row.querySelector('.amount-input')\n const dateInput = row.querySelector('input[type=\"date\"]')\n\n const rowErrors = {}\n\n // Validate activity selection\n if (!activitySelect.value) {\n rowErrors.activity = \"Activity can't be blank\"\n isValid = false\n this.highlightError(activitySelect)\n }\n\n // Validate amount\n if (!amountInput.value) {\n rowErrors.amount = \"Amount can't be blank\"\n isValid = false\n this.highlightError(amountInput)\n } else if (parseFloat(amountInput.value) <= 0) {\n rowErrors.amount = \"Amount must be greater than 0\"\n isValid = false\n this.highlightError(amountInput)\n }\n\n // Validate date\n if (!dateInput.value) {\n rowErrors.date = \"Date can't be blank\"\n isValid = false\n this.highlightError(dateInput)\n }\n\n if (Object.keys(rowErrors).length > 0) {\n errors[index] = rowErrors\n }\n })\n\n if (!isValid) {\n this.displayErrors(errors)\n }\n\n return isValid\n }\n\n displayErrors(errors) {\n // Clear existing error messages\n this.element.querySelectorAll('.help-block').forEach(el => el.remove())\n\n // Remove existing has-error classes\n this.element.querySelectorAll('.has-error').forEach(el => {\n el.classList.remove('has-error')\n })\n\n // Reset all select2 borders\n this.element.querySelectorAll('.select2-container').forEach(el => {\n el.style.borderColor = ''\n })\n\n // Display new error messages\n Object.entries(errors).forEach(([index, rowErrors]) => {\n const row = this.element.querySelectorAll('.activity-row')[parseInt(index)]\n if (row) {\n Object.entries(rowErrors).forEach(([field, message]) => {\n let formGroup\n\n switch (field) {\n case 'activity':\n case 'activity_id':\n formGroup = row.querySelector('.activity-form-group')\n // Special handling for select2\n if (formGroup) {\n const select2Container = formGroup.querySelector('.select2-container')\n if (select2Container) {\n select2Container.style.borderColor = '#e74c3c'\n }\n }\n break\n case 'amount':\n formGroup = row.querySelector('.amount-form-group')\n break\n case 'date':\n case 'completed_at':\n formGroup = row.querySelector('.date-form-group')\n break\n }\n\n if (formGroup) {\n formGroup.classList.add('has-error')\n const errorSpan = document.createElement('span')\n errorSpan.className = 'help-block'\n errorSpan.textContent = message\n formGroup.appendChild(errorSpan)\n }\n })\n }\n })\n }\n\n highlightError(element) {\n // Find the parent form-group\n let formGroup = element.closest('.form-group')\n if (!formGroup) {\n // If not directly in a form-group, try to find the custom form group\n if (element.classList.contains('activity-selector')) {\n formGroup = element.closest('.activity-form-group')\n } else if (element.classList.contains('amount-input')) {\n formGroup = element.closest('.amount-form-group')\n } else {\n formGroup = element.closest('.date-form-group')\n }\n }\n\n if (formGroup) {\n formGroup.classList.add('has-error')\n\n // Special handling for select2\n if (element.classList.contains('activity-selector')) {\n const select2Container = formGroup.querySelector('.select2-container')\n if (select2Container) {\n select2Container.style.borderColor = '#e74c3c'\n }\n }\n\n // Add event listener to clear error on input\n if (!element.classList.contains('activity-selector')) {\n // For regular inputs\n element.addEventListener('input', () => {\n formGroup.classList.remove('has-error')\n const errorMessage = formGroup.querySelector('.help-block')\n if (errorMessage) {\n errorMessage.remove()\n }\n }, { once: true })\n }\n // For select2, the event is handled in the select2:select event\n }\n }\n\n submitForm(event) {\n if (!this.validateForm()) {\n event.preventDefault()\n }\n }\n\n cloneActivity(event) {\n const activityId = event.currentTarget.dataset.activityId\n const activityRow = this.element.querySelector(`.activity-row[data-activity-id=\"${activityId}\"]`)\n\n if (activityRow) {\n // Get values from the current row\n const activitySelect = activityRow.querySelector('.activity-selector')\n const amountInput = activityRow.querySelector('.amount-input')\n const dateInput = activityRow.querySelector('input[type=\"date\"]')\n\n // Create a new activity with these values\n this.addActivityWithValues({\n activity_id: activitySelect.value,\n amount: amountInput.value,\n completed_at: dateInput.value\n })\n }\n }\n}\n","export function getMetaValue(name) {\n const element = findElement(document.head, `meta[name=\"${name}\"]`)\n if (element) {\n return element.getAttribute(\"content\")\n }\n}\n\nexport function findElement(root, selector) {\n if (typeof root == \"string\") {\n selector = root\n root = document\n }\n return root.querySelector(selector)\n}\n\nexport function removeElement(el) {\n if (el && el.parentNode) {\n el.parentNode.removeChild(el);\n }\n}\n\nexport function insertAfter(el, referenceNode) {\n return referenceNode.parentNode.insertBefore(el, referenceNode.nextSibling);\n}","import { Controller } from \"@hotwired/stimulus\"\nimport { DirectUpload } from \"@rails/activestorage\"\nimport Dropzone from \"dropzone\"\nimport { getMetaValue, findElement, removeElement, insertAfter } from \"helpers\"\n\nDropzone.autoDiscover = false\n\nexport default class extends Controller {\n static targets = [\"input\"]\n\n connect() {\n this.dropZone = createDropZone(this)\n this.hideFileInput()\n this.bindEvents()\n }\n\n // Private\n hideFileInput() {\n this.inputTarget.disabled = true\n this.inputTarget.style.display = \"none\"\n }\n\n bindEvents() {\n this.dropZone.on(\"addedfile\", (file) => {\n setTimeout(() => { file.accepted && createDirectUploadController(this, file).start() }, 500)\n })\n\n this.dropZone.on(\"removedfile\", (file) => {\n file.controller && removeElement(file.controller.hiddenInput)\n })\n\n this.dropZone.on(\"canceled\", (file) => {\n file.controller && file.controller.xhr.abort()\n })\n\n this.dropZone.on(\"processing\", (file) => {\n this.submitButton.disabled = true\n })\n\n this.dropZone.on(\"queuecomplete\", (file) => {\n this.submitButton.disabled = false\n })\n }\n\n get headers() { return { \"X-CSRF-Token\": getMetaValue(\"csrf-token\") } }\n\n get url() { return this.inputTarget.getAttribute(\"data-direct-upload-url\") }\n\n get maxFiles() { return this.data.get(\"maxFiles\") || 1 }\n\n get maxFileSize() { return this.data.get(\"maxFileSize\") || 256 }\n\n get acceptedFiles() { return this.data.get(\"acceptedFiles\") }\n\n get addRemoveLinks() { return this.data.get(\"addRemoveLinks\") || true }\n\n get form() { return this.element.closest(\"form\") }\n\n get submitButton() { return findElement(this.form, \"input[type=submit], button[type=submit]\") }\n\n}\n\nclass DirectUploadController {\n constructor(source, file) {\n this.directUpload = createDirectUpload(file, source.url, this)\n this.source = source\n this.file = file\n }\n\n start() {\n this.file.controller = this\n this.hiddenInput = this.createHiddenInput()\n this.directUpload.create((error, attributes) => {\n if (error) {\n removeElement(this.hiddenInput)\n this.emitDropzoneError(error)\n } else {\n this.hiddenInput.value = attributes.signed_id\n this.emitDropzoneSuccess()\n }\n })\n }\n\n // Private\n createHiddenInput() {\n const input = document.createElement(\"input\")\n input.type = \"hidden\"\n input.name = this.source.inputTarget.name\n insertAfter(input, this.source.inputTarget)\n return input\n }\n\n directUploadWillStoreFileWithXHR(xhr) {\n this.bindProgressEvent(xhr)\n this.emitDropzoneUploading()\n }\n\n bindProgressEvent(xhr) {\n this.xhr = xhr\n this.xhr.upload.addEventListener(\"progress\", event => this.uploadRequestDidProgress(event))\n }\n\n uploadRequestDidProgress(event) {\n const element = this.source.element\n const progress = event.loaded / event.total * 100\n findElement(this.file.previewTemplate, \".dz-upload\").style.width = `${progress}%`\n }\n\n emitDropzoneUploading() {\n this.file.status = Dropzone.UPLOADING\n this.source.dropZone.emit(\"processing\", this.file)\n }\n\n emitDropzoneError(error) {\n this.file.status = Dropzone.ERROR\n this.source.dropZone.emit(\"error\", this.file, error)\n this.source.dropZone.emit(\"complete\", this.file)\n }\n\n emitDropzoneSuccess() {\n this.file.status = Dropzone.SUCCESS\n this.source.dropZone.emit(\"success\", this.file)\n this.source.dropZone.emit(\"complete\", this.file)\n }\n}\n\n// Top level...\nfunction createDirectUploadController(source, file) {\n return new DirectUploadController(source, file)\n}\n\nfunction createDirectUpload(file, url, controller) {\n return new DirectUpload(file, url, controller)\n}\n\nfunction createDropZone(controller) {\n return new Dropzone(controller.element, {\n url: controller.url,\n headers: controller.headers,\n maxFiles: controller.maxFiles,\n maxFilesize: controller.maxFileSize,\n acceptedFiles: controller.acceptedFiles,\n addRemoveLinks: controller.addRemoveLinks,\n thumbnailMethod: 'contain',\n autoQueue: false\n })\n}\n","// Load all the controllers within this directory and all subdirectories. \n// Controller files must be named *_controller.js.\n\nimport { Application } from \"@hotwired/stimulus\"\nimport { definitionsFromContext } from \"@hotwired/stimulus-webpack-helpers\"\n\nconst application = Application.start()\nconst context = require.context(\"controllers\", true, /_controller\\.js$/)\napplication.load(definitionsFromContext(context))\n\nimport Clipboard from \"@stimulus-components/clipboard\"\napplication.register(\"clipboard\", Clipboard)\n","/* eslint no-console:0 */\n// This file is automatically compiled by Webpack, along with any other files\n// present in this directory. You're encouraged to place your actual application logic in\n// a relevant structure within app/javascript and only use these pack files to reference\n// that code so it'll be compiled.\n//\n// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate\n// layout file, like app/views/layouts/application.html.erb\n\n\n// Uncomment to copy all static images under ../images to the output folder and reference\n// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)\n// or the `imagePath` JavaScript helper below.\n//\n// const images = require.context('../images', true)\n// const imagePath = (name) => images(name, true)\n\nimport * as ActiveStorage from \"@rails/activestorage\"\nActiveStorage.start()\n\nimport \"stylesheets/application\" \nimport \"controllers\"\n"],"names":["map","webpackContext","req","id","webpackContextResolve","__webpack_require__","o","e","Error","code","keys","Object","resolve","module","exports","Controller","static","connect","this","activityCounter","document","querySelector","submittedActivities","JSON","parse","dataset","length","forEach","activity","addActivityWithValues","addActivity","hasErrorContainerTarget","errorContainerTarget","errors","displayErrors","activityData","template","activityTemplateTarget","innerHTML","replace","activitiesContainerTarget","insertAdjacentHTML","initializeSelect2ForActivity","row","element","activitySelect","amountInput","dateInput","activity_id","value","$","trigger","amount","completed_at","calculateMiles","currentTarget","activityId","controller","selector","select2","placeholder","width","containerCssClass","dropdownCssClass","on","evt","context","target","which","highlighted","data","$dropdown","find","fn","amd","require","Utils","__cache","select2Id","setTimeout","off","units","options","selectedIndex","unitsLabel","textContent","syntheticEvent","formGroup","closest","classList","contains","remove","errorMessage","select2Container","style","borderColor","removeActivity","event","activityRow","children","updateUnits","selectedOptions","milesDisplay","selectedOption","conversionFactor","parseFloat","miles","toFixed","validateForm","isValid","querySelectorAll","index","rowErrors","highlightError","date","el","entries","parseInt","field","message","add","errorSpan","createElement","className","appendChild","addEventListener","once","submitForm","preventDefault","cloneActivity","getMetaValue","name","findElement","head","getAttribute","root","removeElement","parentNode","removeChild","Dropzone","autoDiscover","dropZone","url","headers","maxFiles","maxFilesize","maxFileSize","acceptedFiles","addRemoveLinks","thumbnailMethod","autoQueue","hideFileInput","bindEvents","inputTarget","disabled","display","file","accepted","source","DirectUploadController","createDirectUploadController","start","hiddenInput","xhr","abort","submitButton","get","form","constructor","directUpload","DirectUpload","createDirectUpload","createHiddenInput","create","error","attributes","emitDropzoneError","signed_id","emitDropzoneSuccess","input","referenceNode","type","insertBefore","nextSibling","directUploadWillStoreFileWithXHR","bindProgressEvent","emitDropzoneUploading","upload","uploadRequestDidProgress","progress","loaded","total","previewTemplate","status","UPLOADING","emit","ERROR","SUCCESS","application","Application","load","definitionsFromContext","register","Clipboard","ActiveStorage"],"sourceRoot":""}