chore: move index.astro script to a seperate file

feat: add custom validation for input elements
This commit is contained in:
log101 2024-07-28 17:00:10 +03:00
parent 7cb50bd982
commit 318d1caa9e
8 changed files with 123 additions and 106 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -24,7 +24,6 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"dayjs": "^1.11.11",
"htmx.org": "^1.9.12",
"leaflet": "^1.9.4",
"lucide-react": "^0.309.0",
"react": "^18.3.1",

4
src/env.d.ts vendored
View File

@ -4,10 +4,6 @@
/// <reference types="@types/leaflet" />
export declare global {
interface Window {
htmx: any
}
namespace astroHTML.JSX {
interface HTMLAttributes {
_?: any

View File

@ -38,11 +38,5 @@
<body class='container my-8'>
<slot />
</body>
<script>
import htmx from "htmx.org";
window.htmx = htmx;
</script>
</html>
<style is:global></style>

View File

@ -1,10 +1,11 @@
---
export const prerender = true;
export const prerender = true
import "@/styles/globals.css";
import "../styles/locked-page.css";
import "@/styles/globals.css"
import "../styles/locked-page.css"
import Layout from "../layouts/Layout.astro";
import Layout from "../layouts/Layout.astro"
import { Loader2 } from "lucide-react"
---
<Layout>
@ -126,84 +127,15 @@ import Layout from "../layouts/Layout.astro";
</div>
<button
class='w-full text-lg bg-slate-900 text-white p-2 rounded-lg'
class='w-full text-lg bg-slate-900 text-white p-2 rounded-lg inline-flex justify-center items-center gap-2'
type='submit'
id='submit-button'>
<Loader2 id='submit-button-spinner' className='animate-spin hidden' />
Bağlantıyı Oluştur
</button>
</div>
</form>
<script src='../scripts/initSelectionMap.js'></script>
<script src='../scripts/initSelectionMap.ts'></script>
<script src='../scripts/index.ts'></script>
</main>
<script>
import { toast } from "@/lib/utils";
const handleSubmit = async (e: SubmitEvent) => {
e.preventDefault();
const locationSelected = document.getElementById(
"location-selected-confirmation"
)?.innerText;
if (!locationSelected) {
const coordinatesText = document.getElementById("coordinates");
const mapDiv = document.getElementById("map");
mapDiv?.classList.add("border-slate-700");
coordinatesText?.classList.add("drop-shadow-xl");
setTimeout(() => {
mapDiv?.classList.remove("border-slate-700");
coordinatesText?.classList.remove("drop-shadow-xl");
}, 500);
return;
}
const inputEl = document.getElementById(
"photo-selector"
) as HTMLInputElement | null;
if (!inputEl) return;
const files = inputEl.files;
if (!files) return;
if (files.length > 0) {
if (files[0].size > 4 * 1024 * 1024) {
inputEl.setCustomValidity("Dosya boyutu 4 MB'den küçük olmalıdır.");
inputEl.reportValidity();
return;
}
}
const submitButton = document.getElementById(
"submit-button"
) as HTMLButtonElement;
submitButton.disabled = true;
const formData = new FormData(e.target as HTMLFormElement);
const res = await fetch(`http://127.0.0.1:3000/api/location`, {
method: "POST",
body: formData,
});
submitButton.disabled = false;
if (res.status === 200) {
const data = await res.json();
if (data.url) location.assign("/" + data.url);
} else {
toast("Konulu konum oluşturulamadı, lütfen tekrar deneyin.");
}
};
document.getElementById("sample-form")!.onsubmit = handleSubmit;
</script>
</Layout>

99
src/scripts/index.ts Normal file
View File

@ -0,0 +1,99 @@
import { addClasses, removeClasses } from "@/components/LockedContent/domUtils"
import { toast } from "@/lib/utils"
export function toggleMap() {
const coordinatesText = document.getElementById("coordinates")
const mapDiv = document.getElementById("map")
mapDiv?.classList.add("border-slate-900")
coordinatesText?.classList.add("drop-shadow-2xl")
setTimeout(() => {
mapDiv?.classList.remove("border-slate-900")
coordinatesText?.classList.remove("drop-shadow-2xl")
}, 800)
}
export function validateFileInput(el: HTMLInputElement) {
const files = el.files
if (!files) return
if (files.length > 0) {
if (files[0].size > 4 * 1024 * 1024) {
el.setCustomValidity("Dosya boyutu 4 MB'den küçük olmalıdır.")
el.reportValidity()
} else {
el.setCustomValidity("")
}
}
}
function toggleButton(elemId: string, spinnerId: string) {
const elem = document.getElementById(elemId) as HTMLButtonElement | null
const spinner = document.getElementById(spinnerId)
if (!elem) {
throw new Error("Element could not be found!")
} else if (elem.disabled) {
spinner?.classList.add("hidden")
removeClasses(elemId, "bg-slate-500")
addClasses(elemId, "bg-slate-900")
elem.disabled = false
} else {
spinner?.classList.remove("hidden")
removeClasses(elemId, "bg-slate-900")
addClasses(elemId, "bg-slate-500")
elem.disabled = true
setTimeout(() => toggleButton(elemId, spinnerId), 1000)
}
}
const handleSubmit = async (e: SubmitEvent) => {
e.preventDefault()
toggleButton("submit-button", "submit-button-spinner")
const locationSelected = document.getElementById(
"geolocation-input"
) as HTMLInputElement | null
if (!locationSelected) {
throw new Error("Element could not be found!")
}
if (!locationSelected.value) {
const map = document.getElementById("map")
map?.scrollIntoView({ behavior: "smooth", block: "center" })
return toggleMap()
}
const inputEl = document.getElementById(
"photo-selector"
) as HTMLInputElement | null
if (!inputEl) {
throw new Error("Element could not be found!")
}
validateFileInput(inputEl)
const formData = new FormData(e.target as HTMLFormElement)
const res = await fetch(`http://127.0.0.1:3000/api/location`, {
method: "POST",
body: formData,
})
if (res.status === 200) {
const data = await res.json()
if (data.url) location.assign("/" + data.url)
} else {
toast("Konulu konum oluşturulamadı, lütfen tekrar deneyin.")
}
}
document.getElementById("sample-form")!.onsubmit = handleSubmit
document.getElementById("photo-selector")!.oninput = (ev) =>
validateFileInput(ev.target as HTMLInputElement)

View File

@ -1,3 +1,7 @@
import {
currentLocationIcon,
targetLocationIcon,
} from "@/components/Leaflet/icons"
import { toast } from "@/lib/utils"
import L from "leaflet"
@ -5,16 +9,6 @@ type TargetLocation = [lat: number, lng: number] | null
const mapEl = document.getElementById("map")
var targetLocationIcon = L.icon({
iconUrl: "goal.svg",
iconSize: [32, 32],
})
var currentLocationIcon = L.icon({
iconUrl: "blue-dot.png",
iconSize: [32, 32],
})
const targetLocation = mapEl?.dataset.targetLocation
const data = targetLocation ? JSON.parse(targetLocation) : null
@ -108,10 +102,6 @@ function addTargetLocationMarker(target: TargetLocation) {
}
}
function initLocationControls() {
addTargetLocationMarker(TARGET_LOCATION)
targetLocationControl.addTo(map)
goToCurrentLocationControl.addTo(map)
}
addTargetLocationMarker(TARGET_LOCATION)
initLocationControls()

View File

@ -54,7 +54,6 @@ const CurrentLocationControl = L.Control.extend({
locationButton.id = "current-location-control"
locationButton.addEventListener("click", (ev) => {
console.log(currentLocationMarker)
if (currentLocationMarker) {
map.setView(currentLocationMarker.getLatLng(), 12)
} else {
@ -116,10 +115,18 @@ map.on("click", (e) => {
}
const pos = targetLocationMarker.getLatLng()
updateText("coordinates", `${pos.lat}. Enlem, ${pos.lng}. Boylam`)
updateInputValue("geolocation-input", `${pos.lat},${pos.lng}`)
updateText("coordinates", `${pos.lat}. Enlem, ${pos.lng}. Boylam`)
updateText(
"location-selected-confirmation",
"Konum seçildi, bir sonraki adıma geçebilirsiniz."
)
})
const geolocationInputEl = document.getElementById(
"geolocation-input"
) as HTMLInputElement | null
if (geolocationInputEl?.value) {
geolocationInputEl.value = ""
}