chore: move index.astro script to a seperate file
feat: add custom validation for input elements
This commit is contained in:
parent
7cb50bd982
commit
318d1caa9e
|
@ -24,7 +24,6 @@
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"htmx.org": "^1.9.12",
|
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"lucide-react": "^0.309.0",
|
"lucide-react": "^0.309.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
|
4
src/env.d.ts
vendored
4
src/env.d.ts
vendored
|
@ -4,10 +4,6 @@
|
||||||
/// <reference types="@types/leaflet" />
|
/// <reference types="@types/leaflet" />
|
||||||
|
|
||||||
export declare global {
|
export declare global {
|
||||||
interface Window {
|
|
||||||
htmx: any
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace astroHTML.JSX {
|
namespace astroHTML.JSX {
|
||||||
interface HTMLAttributes {
|
interface HTMLAttributes {
|
||||||
_?: any
|
_?: any
|
||||||
|
|
|
@ -38,11 +38,5 @@
|
||||||
<body class='container my-8'>
|
<body class='container my-8'>
|
||||||
<slot />
|
<slot />
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script>
|
|
||||||
import htmx from "htmx.org";
|
|
||||||
|
|
||||||
window.htmx = htmx;
|
|
||||||
</script>
|
|
||||||
</html>
|
</html>
|
||||||
<style is:global></style>
|
<style is:global></style>
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
---
|
---
|
||||||
export const prerender = true;
|
export const prerender = true
|
||||||
|
|
||||||
import "@/styles/globals.css";
|
import "@/styles/globals.css"
|
||||||
import "../styles/locked-page.css";
|
import "../styles/locked-page.css"
|
||||||
|
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro"
|
||||||
|
import { Loader2 } from "lucide-react"
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout>
|
<Layout>
|
||||||
|
@ -126,84 +127,15 @@ import Layout from "../layouts/Layout.astro";
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<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'
|
type='submit'
|
||||||
id='submit-button'>
|
id='submit-button'>
|
||||||
|
<Loader2 id='submit-button-spinner' className='animate-spin hidden' />
|
||||||
Bağlantıyı Oluştur
|
Bağlantıyı Oluştur
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<script src='../scripts/initSelectionMap.js'></script>
|
<script src='../scripts/initSelectionMap.ts'></script>
|
||||||
|
<script src='../scripts/index.ts'></script>
|
||||||
</main>
|
</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>
|
</Layout>
|
||||||
|
|
99
src/scripts/index.ts
Normal file
99
src/scripts/index.ts
Normal 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)
|
|
@ -1,3 +1,7 @@
|
||||||
|
import {
|
||||||
|
currentLocationIcon,
|
||||||
|
targetLocationIcon,
|
||||||
|
} from "@/components/Leaflet/icons"
|
||||||
import { toast } from "@/lib/utils"
|
import { toast } from "@/lib/utils"
|
||||||
import L from "leaflet"
|
import L from "leaflet"
|
||||||
|
|
||||||
|
@ -5,16 +9,6 @@ type TargetLocation = [lat: number, lng: number] | null
|
||||||
|
|
||||||
const mapEl = document.getElementById("map")
|
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 targetLocation = mapEl?.dataset.targetLocation
|
||||||
|
|
||||||
const data = targetLocation ? JSON.parse(targetLocation) : null
|
const data = targetLocation ? JSON.parse(targetLocation) : null
|
||||||
|
@ -108,10 +102,6 @@ function addTargetLocationMarker(target: TargetLocation) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initLocationControls() {
|
|
||||||
targetLocationControl.addTo(map)
|
|
||||||
goToCurrentLocationControl.addTo(map)
|
|
||||||
}
|
|
||||||
|
|
||||||
addTargetLocationMarker(TARGET_LOCATION)
|
addTargetLocationMarker(TARGET_LOCATION)
|
||||||
initLocationControls()
|
targetLocationControl.addTo(map)
|
||||||
|
goToCurrentLocationControl.addTo(map)
|
||||||
|
|
|
@ -54,7 +54,6 @@ const CurrentLocationControl = L.Control.extend({
|
||||||
locationButton.id = "current-location-control"
|
locationButton.id = "current-location-control"
|
||||||
|
|
||||||
locationButton.addEventListener("click", (ev) => {
|
locationButton.addEventListener("click", (ev) => {
|
||||||
console.log(currentLocationMarker)
|
|
||||||
if (currentLocationMarker) {
|
if (currentLocationMarker) {
|
||||||
map.setView(currentLocationMarker.getLatLng(), 12)
|
map.setView(currentLocationMarker.getLatLng(), 12)
|
||||||
} else {
|
} else {
|
||||||
|
@ -116,10 +115,18 @@ map.on("click", (e) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const pos = targetLocationMarker.getLatLng()
|
const pos = targetLocationMarker.getLatLng()
|
||||||
updateText("coordinates", `${pos.lat}. Enlem, ${pos.lng}. Boylam`)
|
|
||||||
updateInputValue("geolocation-input", `${pos.lat},${pos.lng}`)
|
updateInputValue("geolocation-input", `${pos.lat},${pos.lng}`)
|
||||||
|
updateText("coordinates", `${pos.lat}. Enlem, ${pos.lng}. Boylam`)
|
||||||
updateText(
|
updateText(
|
||||||
"location-selected-confirmation",
|
"location-selected-confirmation",
|
||||||
"Konum seçildi, bir sonraki adıma geçebilirsiniz."
|
"Konum seçildi, bir sonraki adıma geçebilirsiniz."
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const geolocationInputEl = document.getElementById(
|
||||||
|
"geolocation-input"
|
||||||
|
) as HTMLInputElement | null
|
||||||
|
|
||||||
|
if (geolocationInputEl?.value) {
|
||||||
|
geolocationInputEl.value = ""
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user