diff --git a/bun.lockb b/bun.lockb index b363b79..c91bb72 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/src/components/LockedContent.tsx b/src/components/LockedContent.tsx index 4569741..8be41ef 100644 --- a/src/components/LockedContent.tsx +++ b/src/components/LockedContent.tsx @@ -1,136 +1,146 @@ -import { Button } from "@/components/ui/button" -import { Card, CardContent } from "@/components/ui/card" +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; -import { LockClosedIcon, LockOpen1Icon } from "@radix-ui/react-icons" -import { useEffect, useState } from "react" +import { LockClosedIcon, LockOpen1Icon } from "@radix-ui/react-icons"; +import { useEffect, useState } from "react"; -import "../styles/locked-content.css" -import type { Generated } from "kysely" -import { onLocationError } from "@/lib/error" +import "../styles/locked-content.css"; +import type { Generated } from "kysely"; +import { onLocationError } from "@/lib/error"; const incrementCounter = async (id: string | Generated) => - await fetch(`${import.meta.env.PUBLIC_HOME_URL}/api/content/increment?id=${id}`) + await fetch(`http://localhost:3000/api/location/increment/${id}`, { + method: "PATCH", + }); const LocationButton = ({ contentId = "", imageUrl = "#", - location = "" + location = "", }: { - contentId?: string | Generated - imageUrl?: string - location?: string + contentId?: string | Generated; + imageUrl?: string; + location?: string; }) => { - const [atTarget, setAtTarget] = useState(false) - const [contentVisible, setContentVisible] = useState(false) - const [hasPermission, setHasPermission] = useState(false) - const [watchId, setWatchId] = useState() - const [distanceRemain, setDistanceRemain] = useState("") + const [atTarget, setAtTarget] = useState(false); + const [contentVisible, setContentVisible] = useState(false); + const [hasPermission, setHasPermission] = useState(false); + const [watchId, setWatchId] = useState(); + const [distanceRemain, setDistanceRemain] = useState(""); - const targetCoordinates = JSON.parse(location).coordinates + const targetCoordinates = JSON.parse(location); + + console.log("coor", targetCoordinates); const targetPos = { lat: targetCoordinates[0], - lng: targetCoordinates[1] - } + lng: targetCoordinates[1], + }; const startWatchingLocation = () => { - setHasPermission(true) + setHasPermission(true); if (!watchId) { const id = navigator.geolocation.watchPosition( (position: GeolocationPosition) => { const pos = { lat: position.coords.latitude, - lng: position.coords.longitude - } + lng: position.coords.longitude, + }; // @ts-expect-error 3rd party script - const targetLatLng = L.latLng(targetPos) + const targetLatLng = L.latLng(targetPos); // @ts-expect-error 3rd party script - const currentLatLng = L.latLng(pos) + const currentLatLng = L.latLng(pos); - const betweenMeters = currentLatLng.distanceTo(targetLatLng) + const betweenMeters = currentLatLng.distanceTo(targetLatLng); if (betweenMeters > 1000) { - setDistanceRemain(`${(betweenMeters / 1000).toFixed()} KM`) + setDistanceRemain(`${(betweenMeters / 1000).toFixed()} KM`); } else if (betweenMeters > 50) { - setDistanceRemain(`${betweenMeters.toFixed(0)} M`) + setDistanceRemain(`${betweenMeters.toFixed(0)} M`); } else { - setAtTarget(true) + setAtTarget(true); } }, - err => onLocationError(err), + (err) => onLocationError(err), { enableHighAccuracy: true, timeout: 27000, maximumAge: 10000 } - ) + ); - setWatchId(id) + setWatchId(id); } - } + }; const handleUnlock = async () => { - setContentVisible(true) - await incrementCounter(contentId) - } + setContentVisible(true); + await incrementCounter(contentId); + }; useEffect(() => { - navigator.permissions.query({ name: "geolocation" }).then(permissionStatus => { - if (permissionStatus.state === "granted") { - setHasPermission(true) - startWatchingLocation() - } - }) - }, []) + navigator.permissions + .query({ name: "geolocation" }) + .then((permissionStatus) => { + if (permissionStatus.state === "granted") { + setHasPermission(true); + startWatchingLocation(); + } + }); + }, []); if (contentVisible) { return ( -
+
- ) + ); } else { return ( -
+
{atTarget ? ( -
- +
+ -
+
- - İçeriği görmek için butona bas! + + + İçeriği görmek için butona bas! +
) : ( -
- -
- - + {hasPermission ? ( - +

İçeriği görmek için konuma gitmelisin!

{distanceRemain && `Kalan mesafe: ${distanceRemain}`}

) : ( -
- +
+ Ne kadar yaklaştığını görmek için aşağıdaki butona bas.
@@ -140,8 +150,8 @@ const LocationButton = ({
)}
- ) + ); } -} +}; -export default LocationButton +export default LocationButton; diff --git a/src/env.d.ts b/src/env.d.ts index 623fcd7..381873d 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -1,3 +1,4 @@ +/// /// /// /// diff --git a/src/pages/[id].astro b/src/pages/[id].astro index b1d6eab..bce0c68 100644 --- a/src/pages/[id].astro +++ b/src/pages/[id].astro @@ -19,16 +19,18 @@ import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; import utc from 'dayjs/plugin/utc'; -type Content = Omit; +type Content = ContentTable; const { id } = Astro.params; const res = await fetch( - `${import.meta.env.PUBLIC_HOME_URL}/api/content?id=${id}` + `http://localhost:3000/api/location/${id}` ); const data: Content | null = res.status === 200 ? await res.json() : null; +console.log(data) + dayjs.extend(relativeTime); dayjs.extend(utc); @@ -68,8 +70,8 @@ const dateFromNow = dayjs.utc(data?.created_at).from(dayjs.utc()); diff --git a/src/pages/api/content/increment.ts b/src/pages/api/content/increment.ts deleted file mode 100644 index 3b5b7f8..0000000 --- a/src/pages/api/content/increment.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { Database } from "@/lib/db" -import { createKysely } from "@vercel/postgres-kysely" -import type { APIRoute } from "astro" - -export const GET: APIRoute = async ({ request }) => { - const contentId = new URL(request.url).searchParams.get("id") - - if (!contentId) { - return new Response(null, { - status: 400, - statusText: "Content id is required" - }) - } - - const db = createKysely({ connectionString: import.meta.env.POSTGRES_URL }) - - try { - const result = await db - .updateTable("contents") - .set(eb => ({ unlocked_counter: eb("unlocked_counter", "+", 1) })) - .where("id", "=", contentId) - .executeTakeFirst() - - if (result) { - return new Response(JSON.stringify({ counter: Number(result) })) - } else { - return new Response(null, { - status: 404, - statusText: "Could not increment the counter" - }) - } - } catch (error) { - console.error("Error fetching content:", error) - return new Response(null, { - status: 500, - statusText: "Error while fetching content" - }) - } -} diff --git a/src/pages/api/content/index.ts b/src/pages/api/content/index.ts deleted file mode 100644 index dbad08f..0000000 --- a/src/pages/api/content/index.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { createClient } from "@supabase/supabase-js" -import type { APIRoute } from "astro" -import { createKysely } from "@vercel/postgres-kysely" -import { customAlphabet } from "nanoid" -import sharpService from "astro/assets/services/sharp" - -import type { Database } from "@/lib/db" - -export const POST: APIRoute = async ({ request }) => { - const formData = await request.formData() - - const image = formData.get("selected-photo") as File - const author = formData.get("author") - const description = formData.get("description") - const geolocation = formData.get("geolocation") - - if (!image || !geolocation) { - return new Response(null, { - status: 400, - statusText: "Image and geolocation are required fields" - }) - } - - const pos = geolocation.toString().split(",") - - if (pos.length !== 2) { - return new Response(null, { - status: 400, - statusText: "Geolocation not correctly formatted" - }) - } - - const supabaseUrl = import.meta.env.SUPABASE_URL - const supabaseKey = import.meta.env.SUPABASE_KEY - const supabase = createClient(supabaseUrl, supabaseKey) - - const nanoid = customAlphabet("abcdefghijklmnoprstuvyz", 10) - - const randomImageId = nanoid() - - const imageName = `${image.name.replace(/\.[^/.]+$/, "")}${randomImageId}.webp` - - const imageBuf = await image.arrayBuffer() - - const { data, format } = await sharpService.transform( - new Uint8Array(imageBuf), - { src: imageName, format: "webp" }, - { domains: [], remotePatterns: [], service: { entrypoint: "", config: { limitInputPixels: false } } } - ) - - console.log(format) - - const { error } = await supabase.storage.from("images").upload(`public/${imageName}`, data, { - cacheControl: "3600", - upsert: false, - contentType: "image/webp" - }) - - if (error) { - console.error(error.message, imageName, error.cause) - return new Response(null, { - status: 400, - statusText: error.message - }) - } - - const imagePublicUrl = `https://sozfqjbdyppxfwhqktja.supabase.co/storage/v1/object/public/images/public/${imageName}` - - const db = createKysely({ connectionString: import.meta.env.POSTGRES_URL }) - - const newUrl = nanoid() - - const res = await db - .insertInto("contents") - .values({ - url: `${newUrl.slice(0, 3)}-${newUrl.slice(3, 7)}-${newUrl.slice(7)}`, - blob_url: imagePublicUrl, - author: author?.toString() ?? "", - description: description?.toString() ?? "", - loc: `SRID=4326;POINT(${pos[0]} ${pos[1]})` - }) - .returning("url") - .executeTakeFirst() - - if (res?.url) { - return new Response( - JSON.stringify({ - url: res.url - }) - ) - } else { - return new Response(null, { - status: 500, - statusText: "Error while saving data" - }) - } -} - -export const GET: APIRoute = async ({ request }) => { - const contentId = new URL(request.url).searchParams.get("id") - - if (!contentId) { - return new Response(null, { - status: 400, - statusText: "Content id is required" - }) - } - - const db = createKysely({ connectionString: import.meta.env.POSTGRES_URL }) - - try { - const content = await db - .selectFrom("contents") - .select(({ fn }) => [ - "id", - "blob_url", - fn("ST_AsGeoJSON", ["loc"]).as("loc"), - "description", - "author", - "created_at", - "unlocked_counter" - ]) - .where("url", "=", contentId) - .executeTakeFirst() - - if (content) { - return new Response(JSON.stringify(content)) - } else { - return new Response(null, { - status: 404, - statusText: "Content not found" - }) - } - } catch (error) { - console.error("Error fetching content:", error) - return new Response(null, { - status: 500, - statusText: "Error while fetching content" - }) - } -} diff --git a/src/pages/api/debug.ts b/src/pages/api/debug.ts deleted file mode 100644 index 75c9874..0000000 --- a/src/pages/api/debug.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { APIRoute } from "astro" - -export const POST: APIRoute = async ({ request }) => { - const data = await request.json() - - console.log(data) - - return new Response(null, { - status: 200 - }) -} diff --git a/src/pages/index.astro b/src/pages/index.astro index 38c313e..063c8cd 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -195,7 +195,7 @@ import { Label } from '@/components/ui/label'; const formData = new FormData(e.target as HTMLFormElement); - const res = await fetch(`/api/content`, { + const res = await fetch(`http://127.0.0.1:3000/api/location`, { method: 'POST', body: formData, }); diff --git a/src/scripts/initMap.js b/src/scripts/initMap.js index 04dd7ab..b2a7b2e 100644 --- a/src/scripts/initMap.js +++ b/src/scripts/initMap.js @@ -1,6 +1,6 @@ const data = JSON.parse(document.getElementById('map').dataset.targetLocation) -const TARGET_LOCATION = data.coordinates +const TARGET_LOCATION = data function startWatchingLocation() { map.locate({ watch: true })