239 lines
8.3 KiB
TypeScript
239 lines
8.3 KiB
TypeScript
'use client'
|
||
|
||
import React, { useEffect, useState } from 'react'
|
||
import { useSession } from 'next-auth/react'
|
||
import Link from 'next/link'
|
||
import Cookies from 'js-cookie'
|
||
|
||
interface Address {
|
||
id: string
|
||
street: string
|
||
city: string
|
||
postcode: string
|
||
order: number
|
||
}
|
||
|
||
interface Route {
|
||
id: string
|
||
createdAt: string
|
||
status: string
|
||
addresses: Address[]
|
||
}
|
||
|
||
export default function RoutesPage() {
|
||
const { data: session, status } = useSession()
|
||
const [routes, setRoutes] = useState<Route[]>([])
|
||
const [loading, setLoading] = useState(true)
|
||
const [error, setError] = useState<string | null>(null)
|
||
const [isDeleting, setIsDeleting] = useState(false)
|
||
const [messages, setMessages] = useState<any>(null)
|
||
|
||
useEffect(() => {
|
||
const loadMessages = async () => {
|
||
const lang = Cookies.get('NEXT_LOCALE') || 'de'
|
||
const messages = await import(`@/messages/${lang}.json`)
|
||
setMessages(messages.default)
|
||
}
|
||
loadMessages()
|
||
}, [])
|
||
|
||
useEffect(() => {
|
||
fetchRoutes()
|
||
}, [session])
|
||
|
||
const fetchRoutes = async () => {
|
||
try {
|
||
const response = await fetch('/api/routes', {
|
||
credentials: 'include'
|
||
})
|
||
|
||
if (!response.ok) {
|
||
const errorData = await response.json()
|
||
throw new Error(errorData.message || messages?.routes?.error)
|
||
}
|
||
|
||
const data = await response.json()
|
||
setRoutes(data)
|
||
} catch (err) {
|
||
console.error('Rotaları getirme hatası:', err)
|
||
setError(err instanceof Error ? err.message : messages?.routes?.error)
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
const handleDelete = async (routeId: string) => {
|
||
if (!confirm(messages?.routes?.confirmDelete?.message)) {
|
||
return
|
||
}
|
||
|
||
setIsDeleting(true)
|
||
try {
|
||
const response = await fetch(`/api/routes/${routeId}`, {
|
||
method: 'DELETE',
|
||
credentials: 'include'
|
||
})
|
||
|
||
if (!response.ok) {
|
||
throw new Error(messages?.routes?.error)
|
||
}
|
||
|
||
// Rotayı listeden kaldır
|
||
setRoutes(routes.filter(route => route.id !== routeId))
|
||
} catch (err) {
|
||
console.error('Rota silme hatası:', err)
|
||
setError(err instanceof Error ? err.message : messages?.routes?.error)
|
||
} finally {
|
||
setIsDeleting(false)
|
||
}
|
||
}
|
||
|
||
if (!messages || status === 'loading' || loading) {
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center">
|
||
<div className="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-indigo-500"></div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
if (status === 'unauthenticated') {
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center">
|
||
<div className="text-center">
|
||
<h2 className="text-2xl font-bold mb-4">{messages.common.accessDenied}</h2>
|
||
<p className="mb-4">{messages.common.loginRequired}</p>
|
||
<Link
|
||
href="/auth/login"
|
||
className="text-indigo-600 hover:text-indigo-800"
|
||
>
|
||
{messages.common.login}
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
if (error) {
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center">
|
||
<div className="text-center">
|
||
<h2 className="text-2xl font-bold mb-4">{messages.common.error}</h2>
|
||
<p className="text-red-600">{error}</p>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<div className="min-h-screen bg-gray-100 py-6">
|
||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||
<div className="flex justify-between items-center">
|
||
<div className="flex items-center space-x-4">
|
||
<Link
|
||
href="/dashboard"
|
||
className="bg-gray-500 text-white px-4 py-2 rounded-md hover:bg-gray-600"
|
||
>
|
||
{messages?.common?.back}
|
||
</Link>
|
||
<h1 className="text-3xl font-bold text-gray-900">
|
||
{messages?.routes?.title}
|
||
</h1>
|
||
</div>
|
||
<Link
|
||
href="/dashboard/new-route"
|
||
className="bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700"
|
||
>
|
||
{messages?.dashboard?.newRoute?.title}
|
||
</Link>
|
||
</div>
|
||
|
||
<div className="mt-8">
|
||
{routes.length === 0 ? (
|
||
<div className="text-center py-12">
|
||
<p className="text-gray-500">{messages?.routes?.noRoutes}</p>
|
||
<Link
|
||
href="/dashboard/new-route"
|
||
className="text-indigo-600 hover:text-indigo-800 mt-2 inline-block"
|
||
>
|
||
{messages?.routes?.createFirst}
|
||
</Link>
|
||
</div>
|
||
) : (
|
||
<div className="bg-white shadow overflow-hidden sm:rounded-md">
|
||
<ul className="divide-y divide-gray-200">
|
||
{routes.map((route) => (
|
||
<li key={route.id}>
|
||
<div className="px-4 py-4 sm:px-6">
|
||
<div className="flex items-center justify-between">
|
||
<div className="flex flex-col">
|
||
<p className="text-sm font-medium text-indigo-600 truncate">
|
||
{route.addresses.length} {messages?.routes?.addresses}
|
||
</p>
|
||
<p className="mt-1 text-sm text-gray-500">
|
||
{messages?.routes?.createdAt}: {new Date(route.createdAt).toLocaleDateString()}
|
||
</p>
|
||
</div>
|
||
<div className="flex items-center space-x-4">
|
||
<span
|
||
className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${
|
||
route.status === 'COMPLETED'
|
||
? 'bg-green-100 text-green-800'
|
||
: route.status === 'IN_PROGRESS'
|
||
? 'bg-yellow-100 text-yellow-800'
|
||
: 'bg-gray-100 text-gray-800'
|
||
}`}
|
||
>
|
||
{route.status === 'COMPLETED'
|
||
? messages?.routes?.status?.completed
|
||
: route.status === 'IN_PROGRESS'
|
||
? messages?.routes?.status?.active
|
||
: messages?.routes?.status?.active}
|
||
</span>
|
||
<Link
|
||
href={`/dashboard/routes/${route.id}/edit`}
|
||
className="text-yellow-600 hover:text-yellow-900 font-medium"
|
||
>
|
||
{messages?.common?.edit}
|
||
</Link>
|
||
<button
|
||
onClick={() => handleDelete(route.id)}
|
||
disabled={isDeleting}
|
||
className="text-red-600 hover:text-red-900 font-medium disabled:opacity-50"
|
||
>
|
||
{messages?.common?.delete}
|
||
</button>
|
||
<Link
|
||
href={`/dashboard/routes/${route.id}`}
|
||
className="text-indigo-600 hover:text-indigo-900 font-medium"
|
||
>
|
||
{messages?.common?.details}
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
<div className="mt-2">
|
||
<div className="text-sm text-gray-500">
|
||
<ul className="list-disc list-inside">
|
||
{route.addresses
|
||
.slice(0, 3)
|
||
.map((address) => (
|
||
<li key={address.id}>
|
||
{address.street}, {address.city} {address.postcode}
|
||
</li>
|
||
))}
|
||
{route.addresses.length > 3 && (
|
||
<li>{messages?.routeDetails?.moreAddresses.replace('{count}', String(route.addresses.length - 3))}</li>
|
||
)}
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|