'use client'; import { useState, useEffect } from 'react'; import Header from '@/components/Header'; import dynamic from 'next/dynamic'; import { motion, AnimatePresence } from 'framer-motion'; import { ScanLine, Plus, Search, Trash2, Edit2, Layers, MapPin, X, AlertCircle, XCircle, Box } from 'lucide-react'; const Scanner = dynamic(() => import('@yudiel/react-qr-scanner').then(mod => mod.Scanner), { ssr: false }); export default function AdminLocations() { const [locations, setLocations] = useState([]); const [warehouses, setWarehouses] = useState([]); const [selectedWarehouse, setSelectedWarehouse] = useState(''); const [newCode, setNewCode] = useState(''); const [loading, setLoading] = useState(false); const [cameraEnabled, setCameraEnabled] = useState(false); const [camError, setCamError] = useState(''); const [activeFilter, setActiveFilter] = useState('all'); const [editingId, setEditingId] = useState(null); const [editCode, setEditCode] = useState(''); const [toast, setToast] = useState({ show: false, message: '', isError: false }); const showToast = (message, isError = false) => { setToast({ show: true, message, isError }); setTimeout(() => setToast({ show: false, message: '', isError: false }), 3000); }; useEffect(() => { fetchLocations(); fetchSettings(); }, []); const fetchSettings = async () => { try { const res = await fetch('/api/settings'); if (res.ok) { const data = await res.json(); setWarehouses(data.warehouses || []); if (data.warehouses?.length > 0) { setSelectedWarehouse(data.warehouses[0].id); } } } catch (e) { console.error(e); } }; const fetchLocations = async () => { try { const res = await fetch('/api/locations'); if (res.ok) { setLocations(await res.json()); } } catch (e) { console.error(e); } }; const handleAddOrEdit = async (codeValue) => { const targetCode = editingId ? editCode : (codeValue || newCode); if (!targetCode) return; if (!selectedWarehouse) { showToast('لطفاً ابتدا انبار را انتخاب کنید', true); return; } setLoading(true); try { const method = editingId ? 'PUT' : 'POST'; const url = editingId ? `/api/locations/${editingId}` : '/api/locations'; const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code: targetCode, warehouse: selectedWarehouse }) }); const data = await res.json(); if (res.ok) { showToast(editingId ? 'قفسه با موفقیت ویرایش شد' : 'قفسه با موفقیت ثبت شد!'); setNewCode(''); setEditingId(null); setEditCode(''); fetchLocations(); } else { showToast(data.error || 'خطا در ثبت قفسه', true); } } catch (e) { showToast('خطای شبکه', true); } finally { setLoading(false); setCameraEnabled(false); } }; const handleDelete = async (id) => { if (!confirm('آیا از حذف این قفسه اطمینان دارید؟')) return; try { const res = await fetch(`/api/locations/${id}`, { method: 'DELETE' }); const data = await res.json(); if (res.ok) { showToast('قفسه حذف شد'); fetchLocations(); } else { showToast(data.error || 'خطا در حذف', true); } } catch (e) { showToast('خطای شبکه', true); } }; const handleScan = (detectedCodes) => { if (detectedCodes && detectedCodes.length > 0) { const scannedValue = detectedCodes[0].rawValue; handleAddOrEdit(scannedValue); } }; const handleError = (error) => { const msg = error?.message || error?.name || ''; if (msg.includes('Requested device not found')) { setCamError('دوربینی یافت نشد.'); } else { setCamError(msg || 'خطا در دسترسی به دوربین.'); } }; const floors = [...new Set(locations.map(loc => loc.floor))].sort(); const filteredLocations = activeFilter === 'all' ? locations : locations.filter(loc => loc.floor === activeFilter); return (
{/* Header Title */}

تنظیمات قفسه‌ها

ثبت، ویرایش و مدیریت قفسه‌های انبار

{/* Action Box */}
{editingId ? 'ویرایش قفسه' : 'ثبت قفسه جدید'} {editingId && ( )}
editingId ? setEditCode(e.target.value) : setNewCode(e.target.value)} placeholder="مثال: C2F2" className="flex-1 bg-gray-50 border border-gray-200 rounded-[16px] px-4 py-3 text-center uppercase font-black text-gray-800 tracking-widest focus:outline-none focus:border-indigo-500 focus:bg-white transition-colors placeholder-gray-300" /> handleAddOrEdit()} disabled={loading} className="w-14 bg-gray-900 text-white rounded-[16px] flex items-center justify-center transition-opacity disabled:opacity-50 shrink-0" > {loading ?
: (editingId ? : )}
{cameraEnabled && ( {camError ? (
{camError}
) : (
)}
)}
{!cameraEnabled && !editingId && ( setCameraEnabled(true)} className="w-full py-3.5 bg-indigo-50 text-indigo-600 text-sm font-extrabold rounded-[16px] transition-colors flex items-center justify-center gap-2" > اسکن بارکد قفسه )}
{/* List Section */}

لیست قفسه‌ها ({filteredLocations.length})

{/* Tag Filters */} {floors.length > 0 && (
{floors.map(floor => ( ))}
)} {/* Cards */}
{filteredLocations.map((loc) => { const hasData = loc._count?.countings > 0; return (
{loc.code} {loc.warehouse ? `انبار: ${loc.warehouse} • ` : ''}طبقه {loc.floor} • منطقه {loc.region} • قطاع {loc.sector}
{!hasData ? ( <> ) : (
{loc._count.countings} کالا
)}
); })} {filteredLocations.length === 0 && (
هیچ قفسه‌ای یافت نشد با فرم بالا یک قفسه جدید ثبت کنید
)}
{/* Minimal Toast Notification */} {toast.show && ( {toast.isError ? : } {toast.message} )}
); }