314 lines
8.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import { Address } from '@prisma/client'
// İsviçre posta kodları ve şehirleri (örnek veri)
const SWISS_CITIES = [
{ city: 'Zürich', postcode: '8000' },
{ city: 'Basel', postcode: '4000' },
{ city: 'Bern', postcode: '3000' },
{ city: 'Genf', postcode: '1200' },
{ city: 'Lausanne', postcode: '1000' },
{ city: 'Winterthur', postcode: '8400' },
{ city: 'St. Gallen', postcode: '9000' },
{ city: 'Lugano', postcode: '6900' },
]
// Sokak isimleri için örnek son ekler
const STREET_SUFFIXES = [
'strasse',
'weg',
'platz',
'gasse',
'allee',
'boulevard',
'rue',
'via',
]
interface NominatimResult {
place_id: number
licence: string
osm_type: string
osm_id: number
boundingbox: string[]
lat: string
lon: string
display_name: string
class: string
type: string
importance: number
address?: {
house_number?: string
road?: string
suburb?: string
city?: string
town?: string
village?: string
municipality?: string
state?: string
postcode?: string
country?: string
street?: string
}
}
interface SearchParams {
q: string
type: 'street' | 'number' | 'city'
street?: string
}
async function searchStreets(query: string): Promise<string[]> {
try {
const params = new URLSearchParams({
q: `${query} ${query.toLowerCase().endsWith('strasse') ? '' : 'strasse'} switzerland`,
format: 'json',
addressdetails: '1',
countrycodes: 'ch',
limit: '5',
'accept-language': 'de',
featuretype: 'street'
})
const response = await fetch(
`https://nominatim.openstreetmap.org/search?${params}`,
{
headers: {
'User-Agent': 'PostaciApp/1.0'
}
}
)
if (!response.ok) {
throw new Error('Adres arama servisi şu anda kullanılamıyor')
}
const results: NominatimResult[] = await response.json()
return results
.filter(result => result.address?.road)
.map(result => result.address?.road || '')
.filter((value, index, self) => self.indexOf(value) === index) // Tekrar edenleri kaldır
} catch (error) {
console.error('OpenStreetMap API hatası:', error)
throw error
}
}
async function searchHouseNumbers(street: string): Promise<string[]> {
try {
const params = new URLSearchParams({
q: `${street} switzerland`,
format: 'json',
addressdetails: '1',
countrycodes: 'ch',
limit: '15', // Daha fazla sonuç al
'accept-language': 'de'
})
const response = await fetch(
`https://nominatim.openstreetmap.org/search?${params}`,
{
headers: {
'User-Agent': 'PostaciApp/1.0'
}
}
)
if (!response.ok) {
throw new Error('Adres arama servisi şu anda kullanılamıyor')
}
const results: NominatimResult[] = await response.json()
return results
.filter(result => result.address?.house_number && result.address?.road === street)
.map(result => result.address?.house_number || '')
.filter((value, index, self) => self.indexOf(value) === index) // Tekrar edenleri kaldır
.sort((a, b) => parseInt(a) - parseInt(b)) // Numaraları sırala
} catch (error) {
console.error('OpenStreetMap API hatası:', error)
throw error
}
}
async function searchCities(query: string): Promise<string[]> {
try {
const params = new URLSearchParams({
q: `${query} switzerland`,
format: 'json',
addressdetails: '1',
countrycodes: 'ch',
limit: '5',
'accept-language': 'de',
featuretype: 'city'
})
const response = await fetch(
`https://nominatim.openstreetmap.org/search?${params}`,
{
headers: {
'User-Agent': 'PostaciApp/1.0'
}
}
)
if (!response.ok) {
throw new Error('Adres arama servisi şu anda kullanılamıyor')
}
const results: NominatimResult[] = await response.json()
return results
.filter(result => result.address?.city || result.address?.postcode)
.map(result => {
const city = result.address?.city || ''
const postcode = result.address?.postcode || ''
return `${postcode} ${city}`.trim()
})
.filter((value, index, self) => self.indexOf(value) === index) // Tekrar edenleri kaldır
} catch (error) {
console.error('OpenStreetMap API hatası:', error)
throw error
}
}
// Levenshtein mesafesi hesaplama
function levenshteinDistance(a: string, b: string): number {
if (a.length === 0) return b.length
if (b.length === 0) return a.length
const matrix = []
for (let i = 0; i <= b.length; i++) {
matrix[i] = [i]
}
for (let j = 0; j <= a.length; j++) {
matrix[0][j] = j
}
for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) === a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1]
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1,
matrix[i][j - 1] + 1,
matrix[i - 1][j] + 1
)
}
}
}
return matrix[b.length][a.length]
}
// Benzerlik oranı hesaplama
function calculateSimilarity(input: string, candidate: string): number {
const distance = levenshteinDistance(input.toLowerCase(), candidate.toLowerCase())
const maxLength = Math.max(input.length, candidate.length)
return 1 - distance / maxLength
}
// Yedek adres verileri
const BACKUP_ADDRESSES = [
'Luzernstrasse 27, 4552 Derendingen',
'Luzernstrasse 15, 4552 Derendingen',
'Luzernstrasse 29, 4552 Derendingen',
'Luzernstrasse 25, 4552 Derendingen',
'Luzernstrasse 31, 4552 Derendingen',
'Luzernstrasse 12, 6003 Luzern',
'Luzernstrasse 8, 6003 Luzern',
'Luzernstrasse 16, 6003 Luzern',
'Bahnhofstrasse 10, 3011 Bern',
'Hauptstrasse 1, 8001 Zürich',
'Kirchstrasse 7, 2502 Biel',
'Marktgasse 8, 4051 Basel',
'Oberer Graben 12, 9000 St. Gallen',
'Pilatusstrasse 20, 6003 Luzern',
'Rue de Lausanne 25, 1800 Vevey',
'Rue du Mont-Blanc 15, 1201 Genève',
'Via Nassa 5, 6900 Lugano'
]
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url)
const query = searchParams.get('q')
if (!query || query.length < 2) {
return NextResponse.json({ error: 'Arama terimi çok kısa' }, { status: 400 })
}
// Önce Nominatim API'den ara
try {
const params = new URLSearchParams({
q: `${query} switzerland`,
format: 'json',
addressdetails: '1',
countrycodes: 'ch',
limit: '5',
'accept-language': 'de'
})
const response = await fetch(
`https://nominatim.openstreetmap.org/search?${params}`,
{
headers: {
'User-Agent': 'PostaciApp/1.0'
}
}
)
if (!response.ok) {
throw new Error('Nominatim API yanıt vermedi')
}
const results: NominatimResult[] = await response.json()
const addresses = results
.filter(result => result.address?.road || result.display_name)
.map(result => {
const street = result.address?.road || ''
const houseNumber = result.address?.house_number || ''
const postcode = result.address?.postcode || ''
const city = result.address?.city || result.address?.town || result.address?.village || ''
return `${street} ${houseNumber}, ${postcode} ${city}`.trim().replace(/\s+/g, ' ')
})
.filter(address => address.length > 0)
// Eğer Nominatim'den sonuç geldiyse, döndür
if (addresses.length > 0) {
return NextResponse.json(addresses)
}
} catch (error) {
console.warn('Nominatim API hatası:', error)
// Nominatim hatası durumunda yedek adreslere geç
}
// Yedek adreslerden benzerlik araması yap
const sortedAddresses = BACKUP_ADDRESSES
.map(address => ({
address,
similarity: calculateSimilarity(query, address)
}))
.sort((a, b) => b.similarity - a.similarity)
.filter(item => item.similarity > 0.3)
.map(item => item.address)
.slice(0, 5)
if (sortedAddresses.length === 0) {
return NextResponse.json(
{ error: 'Sonuç bulunamadı' },
{ status: 200 } // 404 yerine 200 dönüyoruz
)
}
return NextResponse.json(sortedAddresses)
} catch (error) {
console.error('Adres arama hatası:', error)
return NextResponse.json(
{ error: 'Adres arama sırasında bir hata oluştu' },
{ status: 200 } // 404 yerine 200 dönüyoruz
)
}
}