{"version":3,"file":"improve_area_selection.js","mappings":"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","sources":["webpack://trace_taiwan/./app/javascript/packs/inline_edit.js","webpack://trace_taiwan/./app/javascript/packs/improve_area_selection.js"],"sourcesContent":["// Shared helpers for the on-page \"suggest an edit\" flows (trace details and river\n// details). Each caller owns its DOM swapping; this module owns the textarea\n// behaviour and the /edits/create request so the two stay in sync.\nexport const SUBMITTED_MESSAGE =\n \"Thank you for your contribution. Your update is being reviewed. It may take some \" +\n \"time before it is live. Please be patient and avoid resubmitting.\";\nexport const DUPLICATE_MESSAGE =\n \"You have already submitted an improvement for this information. Please give us time \" +\n \"to review it before creating another.\";\nexport const LOGIN_MESSAGE =\n 'Only logged in users can edit information. ' +\n 'Click to Login/Sign Up';\n\n// Grow a textarea to fit its content as the user types.\nexport function autoGrow(textarea) {\n const fit = () => {\n textarea.style.height = \"auto\";\n textarea.style.height = `${textarea.scrollHeight}px`;\n };\n textarea.addEventListener(\"input\", fit);\n fit();\n}\n\n// A status banner element; pass the literal color classes so Tailwind keeps them.\nexport function statusBanner(colorClasses, html) {\n const banner = document.createElement(\"div\");\n banner.className = `rounded-lg py-3 px-4 mt-2 text-sm font-semibold ${colorClasses}`;\n banner.innerHTML = html;\n return banner;\n}\n\n// Submit a suggested edit; resolves to 'success', 'duplicate', 'login', or 'error'.\nexport async function submitEdit(edit) {\n const params = new URLSearchParams();\n Object.entries(edit).forEach(([key, value]) => params.set(`edit[${key}]`, value ?? \"\"));\n const response = await fetch(`/edits/create?${params.toString()}`, {\n headers: { Accept: \"application/json\" }\n });\n const body = await response.json().catch(() => null);\n if (!body) return \"success\";\n if (body.message === \"login\") return \"login\";\n if (body.message === \"duplicate edit\") return \"duplicate\";\n return \"error\";\n}\n","// Trace show page: suggest an edit to the region/city/river of a trace. Clicking\n// \"improve\" swaps the location pills for the dependent dropdowns; submitting sends\n// the chosen ids to /edits/create for review.\nimport { statusBanner, submitEdit, LOGIN_MESSAGE } from \"./inline_edit\";\n\n// Region pill colors — keep in sync with RegionsHelper (literal so Tailwind keeps them).\nconst REGION_PILLS = {\n North: { region: \"bg-blue-100 text-blue-800\", city: \"bg-blue-50 text-blue-700\" },\n East: { region: \"bg-green-100 text-green-800\", city: \"bg-green-50 text-green-700\" },\n Central: { region: \"bg-purple-100 text-purple-800\", city: \"bg-purple-50 text-purple-700\" },\n South: { region: \"bg-yellow-100 text-yellow-800\", city: \"bg-yellow-50 text-yellow-700\" }\n};\nconst FALLBACK_PILLS = { region: \"bg-gray-100 text-gray-800\", city: \"bg-gray-50 text-gray-700\" };\n\nconst SUBMITTED_MESSAGE = \"Thank you for your contribution. Your update is being reviewed.\";\nconst DUPLICATE_MESSAGE = \"You have already submitted an improvement for this information. Please wait for review.\";\n\nconst BUTTON_CLASSES =\n \"inline-flex justify-center py-1.5 mt-2 px-4 border border-transparent cursor-pointer \" +\n \"text-sm font-semibold rounded-lg text-white focus:outline-none transition duration-150 \" +\n \"ease-in-out edit-button\";\n\nconst improveButton = document.querySelector(\".improve-selection\");\nconst dropdownArea = document.getElementById(\"dropdown-info\");\nconst traceDetails = document.getElementById(\"trace-details\");\n\nfunction button(label, colorClasses) {\n const el = document.createElement(\"button\");\n el.type = \"button\";\n el.className = `${BUTTON_CLASSES} ${colorClasses}`;\n el.textContent = label;\n return el;\n}\n\nfunction select(id) {\n return document.getElementById(id);\n}\n\nfunction selectedText(el) {\n const option = el.options[el.selectedIndex];\n return option ? option.text : \"\";\n}\n\nfunction cityOption(city) {\n const option = document.createElement(\"option\");\n option.value = city.id;\n option.textContent = city.name;\n return option;\n}\n\nasync function loadCities(keepCityLabel) {\n const regionName = selectedText(select(\"post_region_id\"));\n if (regionName === \"Unknown\") return;\n const response = await fetch(`/regions/${encodeURIComponent(regionName)}/cities`, {\n headers: { Accept: \"application/json\" }\n });\n const cities = await response.json();\n const citySelect = select(\"post_city_id\");\n citySelect.replaceChildren(...cities.map(cityOption));\n const match = Array.from(citySelect.options).find((o) => o.text === keepCityLabel);\n if (match) match.selected = true;\n}\n\nfunction locationPills() {\n const regionText = selectedText(select(\"post_region_id\"));\n const cityText = selectedText(select(\"post_city_id\"));\n const riverText = selectedText(select(\"post_river_id\"));\n const palette = REGION_PILLS[regionText] || FALLBACK_PILLS;\n return `\n ${riverText}\n ${cityText}\n ${regionText}`;\n}\n\nfunction startEditing() {\n const originalHTML = dropdownArea.innerHTML;\n const update = button(\"Update\", \"mr-3 bg-green-500 hover:bg-green-600\");\n const cancel = button(\"Cancel\", \"bg-red-500 hover:bg-red-600\");\n\n dropdownArea.innerHTML = document.getElementById(\"hidden-dropdowns\").innerHTML;\n improveButton.style.display = \"none\";\n dropdownArea.after(update, cancel);\n\n const cancelEditing = () => {\n dropdownArea.innerHTML = originalHTML;\n update.remove();\n cancel.remove();\n improveButton.style.display = \"\";\n };\n\n select(\"post_region_id\").addEventListener(\"change\", () => {\n loadCities(selectedText(select(\"post_city_id\")) || \"Unknown\").catch(() => {});\n });\n cancel.addEventListener(\"click\", cancelEditing);\n\n update.addEventListener(\"click\", async () => {\n const result = await submitEdit({\n region: select(\"post_region_id\").value,\n city: select(\"post_city_id\").value,\n river: select(\"post_river_id\").value,\n post_id: traceDetails.dataset.id,\n attribute_updated: \"location-dropdowns\"\n });\n\n if (result === \"success\") {\n dropdownArea.innerHTML = locationPills();\n update.remove();\n cancel.replaceWith(statusBanner(\"bg-green-100 text-green-800\", SUBMITTED_MESSAGE));\n } else {\n cancelEditing();\n const message = result === \"login\" ? LOGIN_MESSAGE : DUPLICATE_MESSAGE;\n improveButton.replaceWith(statusBanner(\"bg-yellow-100 text-yellow-800\", message));\n }\n });\n\n select(\"post_region_id\").dispatchEvent(new Event(\"change\"));\n}\n\nif (improveButton && dropdownArea) {\n improveButton.addEventListener(\"click\", startEditing);\n}\n"],"names":["statusBanner","colorClasses","html","banner","document","createElement","className","innerHTML","REGION_PILLS","North","region","city","East","Central","South","FALLBACK_PILLS","improveButton","querySelector","dropdownArea","getElementById","traceDetails","label","el","type","textContent","id","selectedText","option","options","selectedIndex","text","cityOption","value","name","addEventListener","originalHTML","update","cancel","style","display","after","cancelEditing","remove","async","keepCityLabel","regionName","response","fetch","encodeURIComponent","headers","Accept","cities","json","citySelect","replaceChildren","map","match","Array","from","find","o","selected","loadCities","catch","result","edit","params","URLSearchParams","Object","entries","forEach","key","set","toString","body","message","submitEdit","river","post_id","dataset","attribute_updated","regionText","cityText","riverText","palette","toLowerCase","locationPills","replaceWith","dispatchEvent","Event"],"ignoreList":[],"sourceRoot":""}