Next.js ile Aracım Nerede? Uygulaması
Alışveriş merkezlerine gittiğinizde ya da dışarı çıkıp işlerinizi halletmek istediğinizde arabanızı karışık bir sokağa park ettiğinizde bazen aracınızı bulmakta benim gibi zorlananlarınız olmuştur. İşte böyle bir durumda basit ama etkili bir küçük uygulama geliştirmek istedim.
Kendi küçük ama etkisi büyük derler ya, bu uygulama o tanıma girecek cinsten olduğunu düşünüyorum.
Not: Uygulamayı test etmek istiyorsanız https://bul.atailkkan.com adresinden ulaşabilir ve test edebilirsiniz.
Uygulamanın Temel Akışı
- Kullanıcı Konumuzunu Kaydedin düğmesine basar.
- Cihazın gerçek GPS konumu alınır.
- Bu konum, tarayıcıda Localstorage olarak kaydedilir.
- Kullanıcı geri döndüğünde, aracı ile kendi konumu arasındaki mesafe, harita üzerinde gösterilir.
Uygulamada Kullanılacak Paketler
- geolib (Haversine formülü ile de hesaplanır, ama paket kullanımı daha kolay)
- mapbox-gl & react-map-gl (Gösterilecek harita için)
- react-use (Anlık konum ve aracınızın konumunu almak için)
- @remixicon/react (ikonlar için, isteğe göre)
Uygulama Mimarisi
app/
├── (pages)/
│ ├── navigate/
│ │ └── page.js
│ ├── park/
│ │ └── page.js
├── components/
│ ├── DistanceInfo.js
│ ├── Logo.js
│ ├── MapBox.js
│ └── Menu.js
├── globals.css
├── layout.js
└── page.js
.env
MapBox Token
.env
Mapbox kütüphanesini kullanabilmeniz için siteden token almanız .env dosyanıza kaydetmeniz gerekiyor.
NEXT_PUBLIC_MAPBOX_TOKEN = "pk.*****************"
Konum Kaydetme (Park Etme)
park/page.js
Konumunuzu belirledikten sonra Konumuzunu Kaydedin düğmesine basarak, konum bilgileriniz kaydedilir.
"use client"
import { useGeolocation } from "react-use";
export default function ParkPage() {
const geo = useGeolocation({
enableHighAccuracy: true,
maximumAge: 0,
timeout: 15000,
});
const saveParkLocation = () => {
if (geo.loading) {
alert("Konum alınıyor, lütfen bekleyin");
return;
}
if (geo.error) {
alert("Konum izni verilmedi veya hata oluştu");
return;
}
if (!geo.latitude || !geo.longitude) {
alert("Konum henüz alınamadı");
return;
}
localStorage.setItem(
"carLocation",
JSON.stringify({
lat: geo.latitude,
lng: geo.longitude,
time: Date.now(),
})
);
alert("Arabanın konumu kaydedildi");
};
return (
<div>
<h1 className="text-lg font-medium mb-4">Arabayı Park Et</h1>
<p className='mb-4'>Konumunuz hazır duruma geldiği zaman aşağıdaki butona basmanız yeterli.</p>
<div className='font-medium mb-6'>
{geo.loading && <p className='animate-pulse text-sky-600'>Konum alınıyor</p>}
{geo.error && <p className='text-rose-600'>Konum alınamadı</p>}
{geo.latitude && <p className='text-green-600'>Konum hazır</p>}
</div>
<button onClick={saveParkLocation} className='p-3 px-5 bg-black text-white duration-200 hover:bg-black/75 cursor-pointer rounded-md'>Konumunuzu Kaydedin</button>
</div>
);
}
Haritadan Takip
navigate/page.js
Açılan haritada, sizin anlık konumunuz ile aracınızın konumunu canlı olarak takip edebilirsiniz.
"use client"
import { useEffect, useState } from "react";
import { useGeolocation } from "react-use";
import DistanceInfo from "../../components/DistanceInfo";
import dynamic from "next/dynamic";
const MapBox = dynamic(() => import("../../components/MapBox"), { ssr: false });
export default function NavigatePage() {
const geo = useGeolocation({ enableHighAccuracy: true });
const [parked, setParked] = useState(null);
const [route, setRoute] = useState(null);
useEffect(() => {
const data = localStorage.getItem("carLocation");
if (data) setParked(JSON.parse(data));
}, []);
useEffect(() => {
if (!geo.latitude || !parked) return;
fetch(`https://api.mapbox.com/directions/v5/mapbox/walking/` + `${geo.longitude},${geo.latitude};${parked.lng},${parked.lat}` + `?geometries=geojson&access_token=${process.env.NEXT_PUBLIC_MAPBOX_TOKEN}`)
.then(res => res.json())
.then(data => {
setRoute(data.routes[0].geometry);
});
}, [geo, parked]);
if (!geo.latitude || !parked) return null;
const current = { lat: geo.latitude, lng: geo.longitude };
return (
<>
<DistanceInfo current={current} parked={parked} />
<MapBox current={current} parked={parked} route={route} />
</>
);
}
Mesafe Hesaplama
components/DistanceInfo.js
Sizin konumunuz ile aracınızın konumu arasındaki mesafe hesaplanır ve metre cinsinden ekrana bastırılır.
"use client"
import { getDistance } from "geolib";
export default function DistanceInfo({ current, parked }) {
const distance = getDistance(
{ latitude: current.lat, longitude: current.lng },
{ latitude: parked.lat, longitude: parked.lng }
);
return (
<h1 className="text-lg font-medium mb-6">
Kalan mesafe: <strong>{distance} metre</strong>
</h1>
);
}
MapBox Harita
components/MapBox.js
Haritaya gönderilen bilgiler doğrultusunda sizin ve aracınızın konumunu pinler yardımıyla gösterebilirsiniz.
"use client"
import Map, { Marker, Source, Layer } from "react-map-gl";
export default function MapBox({ current, parked, route }) {
return (
<Map
initialViewState={{
latitude: current.lat,
longitude: current.lng,
zoom: 15,
}}
mapboxAccessToken={process.env.NEXT_PUBLIC_MAPBOX_TOKEN}
style={{ width: '100%', height: 400 }}
mapStyle="mapbox://styles/mapbox/streets-v12"
>
<Marker latitude={current.lat} longitude={current.lng} color="blue" />
<Marker latitude={parked.lat} longitude={parked.lng} color="red" />
{
route && (
<Source type="geojson" data={route}>
<Layer
id="route"
type="line"
paint={{ "line-width": 4 }}
/>
</Source>
)
}
</Map>
);
}
Yanılma Payını En Aza İndirmek
enableHighAccuracy: trueolarak ayarlanmalı,maximumAge: 0olarak ayarlanmalı,- Kapalı otoparklarda ve sık ağaçlı alanlarda GPS sapması fazla olacaktır,
- Android → Chrome > Konum = Hassas olarak ayarlanmalı,
- iOS → Safari > Konum = Always Allow olarak ayarlanmalı.