feat: modernize admin panel UI and add openinary integration

This commit is contained in:
Mustafa Yildiz
2026-07-12 15:10:50 +03:00
parent 378a1e033a
commit ca1e849e80
20 changed files with 536 additions and 248 deletions
+58 -53
View File
@@ -3,7 +3,7 @@
import { useActionState, useState, useRef } from 'react'
import { saveSettings } from './actions'
import Image from 'next/image'
import { Upload, X, Loader2 } from 'lucide-react'
import { Upload, X, Loader2, Save } from 'lucide-react'
export default function SettingsForm({
defaultRestaurantName,
@@ -49,62 +49,62 @@ export default function SettingsForm({
}
return (
<form action={action} className="space-y-6">
<form action={action} className="space-y-8">
{state?.success && (
<div className="bg-green-50 text-green-700 p-3 rounded-lg text-sm">
<div className="bg-emerald-50 text-emerald-700 px-4 py-3 rounded-xl text-sm font-medium border border-emerald-100/50">
{state.message}
</div>
)}
{state?.error && (
<div className="bg-red-50 text-red-700 p-3 rounded-lg text-sm">
<div className="bg-red-50 text-red-700 px-4 py-3 rounded-xl text-sm font-medium border border-red-100/50">
{state.error}
</div>
)}
{/* Logo Upload */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
<label className="block text-sm font-semibold text-slate-700 mb-3">
Site Logosu
</label>
<div className="flex items-start gap-4">
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-6">
{/* Preview */}
<div className="relative w-40 h-20 rounded-xl overflow-hidden border-2 border-gray-200 bg-stone-900 flex items-center justify-center flex-shrink-0">
<div className="relative w-48 h-24 rounded-2xl overflow-hidden border border-slate-200 bg-slate-900 shadow-inner flex items-center justify-center flex-shrink-0 group">
{logoUrl ? (
<>
<Image
src={logoUrl}
alt="Logo önizleme"
fill
className="object-contain p-2"
className="object-contain p-3"
/>
<button
type="button"
onClick={() => { setLogoUrl(''); if (fileInputRef.current) fileInputRef.current.value = '' }}
className="absolute top-1 right-1 bg-red-500 text-white rounded-full p-0.5 hover:bg-red-600 transition-colors"
className="absolute top-2 right-2 bg-red-500/90 text-white rounded-full p-1 hover:bg-red-600 transition-colors opacity-0 group-hover:opacity-100 backdrop-blur-sm shadow-sm"
>
<X size={12} />
<X size={14} />
</button>
</>
) : (
<span className="text-xs text-gray-400 text-center px-2">Logo yok<br />(varsayılan kullanılır)</span>
<span className="text-xs text-slate-400 text-center px-4 font-medium">Logo yok<br />(varsayılan kullanılır)</span>
)}
</div>
{/* Upload button */}
<div className="flex flex-col gap-2 justify-center h-20">
<div className="flex flex-col gap-2.5 justify-center">
<button
type="button"
onClick={() => fileInputRef.current?.click()}
disabled={uploading}
className="flex items-center gap-2 px-4 py-2 border-2 border-dashed border-gray-300 rounded-lg text-sm text-gray-600 hover:border-blue-400 hover:text-blue-600 transition-colors disabled:opacity-50"
className="flex items-center gap-2 px-5 py-2.5 border-2 border-dashed border-slate-300 rounded-xl text-sm font-medium text-slate-600 hover:border-blue-400 hover:text-blue-600 transition-colors disabled:opacity-50 hover:bg-blue-50/50"
>
{uploading
? <><Loader2 size={16} className="animate-spin" /> Yükleniyor...</>
: <><Upload size={16} /> Logo Yükle</>
? <><Loader2 size={18} className="animate-spin" /> Yükleniyor...</>
: <><Upload size={18} /> Yeni Logo Seç</>
}
</button>
<p className="text-xs text-gray-500">PNG, SVG, WEBP Maks. 5MB</p>
{uploadError && <p className="text-xs text-red-600">{uploadError}</p>}
<p className="text-xs text-slate-400 font-medium ml-1">Önerilen format: Şeffaf arka planlı PNG veya SVG (Maks. 5MB)</p>
{uploadError && <p className="text-xs text-red-600 font-medium ml-1">{uploadError}</p>}
</div>
</div>
@@ -118,39 +118,41 @@ export default function SettingsForm({
<input type="hidden" name="logo_url" value={logoUrl} />
</div>
<hr className="border-gray-100" />
<hr className="border-slate-100" />
{/* Restaurant Name */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Restoran / Mekan Adı
</label>
<input
type="text"
name="restaurant_name"
defaultValue={defaultRestaurantName}
required
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Restaurant Name */}
<div>
<label className="block text-sm font-semibold text-slate-700 mb-1.5">
Restoran / Mekan Adı
</label>
<input
type="text"
name="restaurant_name"
defaultValue={defaultRestaurantName}
required
className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 focus:bg-white outline-none text-sm transition-all"
/>
</div>
{/* Location */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Konum Bilgisi
</label>
<input
type="text"
name="location"
defaultValue={defaultLocation}
required
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
/>
{/* Location */}
<div>
<label className="block text-sm font-semibold text-slate-700 mb-1.5">
Konum Bilgisi
</label>
<input
type="text"
name="location"
defaultValue={defaultLocation}
required
className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 focus:bg-white outline-none text-sm transition-all"
/>
</div>
</div>
{/* Google Review Url */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
<label className="block text-sm font-semibold text-slate-700 mb-1.5">
Google Yorum Linki
</label>
<input
@@ -158,18 +160,21 @@ export default function SettingsForm({
name="google_review_url"
defaultValue={defaultGoogleReviewUrl}
placeholder="https://g.page/r/..."
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 focus:bg-white outline-none text-sm transition-all"
/>
<p className="text-xs text-gray-500 mt-1">Eğer buraya link eklerseniz site açılışında ziyaretçilere yorum yapmaları için popup gösterilir.</p>
<p className="text-xs text-slate-500 mt-2 font-medium ml-1">Eğer buraya link eklerseniz, ziyaretçilere her 30 dakikada bir işletmenizi değerlendirmelerini isteyen bir açılır pencere (popup) gösterilir.</p>
</div>
<button
type="submit"
disabled={isPending || uploading}
className="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg transition-colors disabled:opacity-70"
>
{isPending ? 'Kaydediliyor...' : 'Kaydet'}
</button>
<div className="pt-4 flex justify-end">
<button
type="submit"
disabled={isPending || uploading}
className="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2.5 px-8 rounded-xl transition-all shadow-sm hover:shadow hover:-translate-y-0.5 disabled:opacity-70 disabled:hover:translate-y-0 disabled:shadow-none flex items-center gap-2"
>
<Save size={18} />
{isPending ? 'Kaydediliyor...' : 'Değişiklikleri Kaydet'}
</button>
</div>
</form>
)
}