import { useState, useEffect, useCallback, useRef } from 'react'
import { useAlert } from '../context/AlertContext'
import { useAuth } from '../context/AuthContext'
import { motion, AnimatePresence } from 'framer-motion'
import ConfirmModal from '../components/ConfirmModal'
import FormField from '../components/FormField'
import Forbidden from '../components/Forbidden'
import useModalLock from '../hooks/useModalLock'
import apiFetch from '../utils/api'
const API_BASE = '/api/admin'
const DEFAULT_CUSTOMER_FIELD_ORDER = ['street', 'city_postal', 'country', 'company_id', 'vat_id']
const CUSTOMER_FIELD_LABELS = {
street: 'Ulice',
city_postal: 'Město + PSČ',
country: 'Země',
company_id: 'IČO',
vat_id: 'DIČ',
}
export default function OffersCustomers() {
const alert = useAlert()
const { hasPermission } = useAuth()
const [loading, setLoading] = useState(true)
const [customers, setCustomers] = useState([])
const [search, setSearch] = useState('')
const [showModal, setShowModal] = useState(false)
const [editingCustomer, setEditingCustomer] = useState(null)
const [saving, setSaving] = useState(false)
const [form, setForm] = useState({
name: '',
street: '',
city: '',
postal_code: '',
country: '',
company_id: '',
vat_id: '',
})
const [customFields, setCustomFields] = useState([])
const customFieldKeyCounter = useRef(0)
const [fieldOrder, setFieldOrder] = useState([...DEFAULT_CUSTOMER_FIELD_ORDER])
const [deleteConfirm, setDeleteConfirm] = useState({ show: false, customer: null })
const [deleting, setDeleting] = useState(false)
useModalLock(showModal)
// Build the full field order list including custom fields
const getFullFieldOrder = useCallback(() => {
const allBuiltIn = [...DEFAULT_CUSTOMER_FIELD_ORDER]
const order = [...fieldOrder].filter(k => k !== 'name')
for (const f of allBuiltIn) {
if (!order.includes(f)) order.push(f)
}
for (let i = 0; i < customFields.length; i++) {
const key = `custom_${i}`
if (!order.includes(key)) order.push(key)
}
return order.filter(key => {
if (key.startsWith('custom_')) {
const idx = parseInt(key.split('_')[1])
return idx < customFields.length
}
return true
})
}, [fieldOrder, customFields])
const moveField = (index, direction) => {
const order = getFullFieldOrder()
const newIndex = index + direction
if (newIndex < 0 || newIndex >= order.length) return
const updated = [...order]
;[updated[index], updated[newIndex]] = [updated[newIndex], updated[index]]
setFieldOrder(updated)
}
const getFieldDisplayName = (key) => {
if (CUSTOMER_FIELD_LABELS[key]) return CUSTOMER_FIELD_LABELS[key]
if (key.startsWith('custom_')) {
const idx = parseInt(key.split('_')[1])
const cf = customFields[idx]
if (cf) return cf.name ? `${cf.name}: ${cf.value || '...'}` : cf.value || `Vlastní pole ${idx + 1}`
}
return key
}
const fetchData = useCallback(async () => {
try {
const response = await apiFetch(`${API_BASE}/customers.php`)
if (response.status === 401) return
const result = await response.json()
if (result.success) {
setCustomers(result.data.customers)
} else {
alert.error(result.error || 'Nepodařilo se načíst zákazníky')
}
} catch {
alert.error('Chyba připojení')
} finally {
setLoading(false)
}
}, [alert])
useEffect(() => {
fetchData()
}, [fetchData])
const openCreateModal = () => {
setEditingCustomer(null)
setForm({
name: '', street: '', city: '', postal_code: '', country: '',
company_id: '', vat_id: ''
})
setCustomFields([])
setFieldOrder([...DEFAULT_CUSTOMER_FIELD_ORDER])
setShowModal(true)
}
const openEditModal = (customer) => {
setEditingCustomer(customer)
setForm({
name: customer.name || '',
street: customer.street || '',
city: customer.city || '',
postal_code: customer.postal_code || '',
country: customer.country || '',
company_id: customer.company_id || '',
vat_id: customer.vat_id || '',
})
// Load custom fields
const cf = Array.isArray(customer.custom_fields) && customer.custom_fields.length > 0
? customer.custom_fields.map(f => ({ ...f, _key: `cf-${++customFieldKeyCounter.current}` }))
: []
setCustomFields(cf)
// Load field order
if (Array.isArray(customer.customer_field_order) && customer.customer_field_order.length > 0) {
setFieldOrder(customer.customer_field_order)
} else {
setFieldOrder([...DEFAULT_CUSTOMER_FIELD_ORDER])
}
setShowModal(true)
}
const closeModal = () => {
setShowModal(false)
setEditingCustomer(null)
}
const handleSubmit = async () => {
if (!form.name.trim()) {
alert.error('Název zákazníka je povinný')
return
}
setSaving(true)
try {
const url = editingCustomer
? `${API_BASE}/customers.php?id=${editingCustomer.id}`
: `${API_BASE}/customers.php`
const payload = {
...form,
custom_fields: customFields.filter(f => f.name.trim() || f.value.trim()),
customer_field_order: getFullFieldOrder(),
}
const response = await apiFetch(url, {
method: editingCustomer ? 'PUT' : 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
})
const result = await response.json()
if (result.success) {
closeModal()
await new Promise(resolve => setTimeout(resolve, 300))
alert.success(result.message || (editingCustomer ? 'Zákazník byl aktualizován' : 'Zákazník byl vytvořen'))
fetchData()
} else {
alert.error(result.error || 'Nepodařilo se uložit zákazníka')
}
} catch {
alert.error('Chyba připojení')
} finally {
setSaving(false)
}
}
const handleDelete = async () => {
if (!deleteConfirm.customer) return
setDeleting(true)
try {
const response = await apiFetch(`${API_BASE}/customers.php?id=${deleteConfirm.customer.id}`, {
method: 'DELETE'
})
const result = await response.json()
if (result.success) {
setDeleteConfirm({ show: false, customer: null })
alert.success(result.message || 'Zákazník byl smazán')
fetchData()
} else {
alert.error(result.error || 'Nepodařilo se smazat zákazníka')
}
} catch {
alert.error('Chyba připojení')
} finally {
setDeleting(false)
}
}
if (!hasPermission('offers.view')) return
Správa zákazníků pro nabídky
{search ? 'Žádní zákazníci odpovídající hledání.' : 'Zatím nejsou žádní zákazníci.'}
{!search && hasPermission('offers.create') && ( )}| Název | Město | IČO | DIČ | Nabídky | Akce |
|---|---|---|---|---|---|
|
{customer.name}
{customer.street && (
{customer.street}
)}
|
{customer.city || '—'} | {customer.company_id || '—'} | {customer.vat_id || '—'} | {customer.quotation_count || 0} |
{hasPermission('offers.edit') && (
)}
{hasPermission('offers.delete') && (
)}
|