fix: add error handling and loading state to tariff save
This commit is contained in:
@@ -151,13 +151,15 @@ const EMPTY_TARIFF: Omit<Tariff, 'id'> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function TariffModal({
|
function TariffModal({
|
||||||
tariff, onSave, onClose, mealPlans, allInclusions,
|
tariff, onSave, onClose, mealPlans, allInclusions, saving, error,
|
||||||
}: {
|
}: {
|
||||||
tariff?: Tariff
|
tariff?: Tariff
|
||||||
onSave: (t: Omit<Tariff, 'id'>) => void
|
onSave: (t: Omit<Tariff, 'id'>) => void
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
mealPlans: Array<{ id: string; label: string; description: string; inclusions: string[] }>
|
mealPlans: Array<{ id: string; label: string; description: string; inclusions: string[] }>
|
||||||
allInclusions: Array<{ id: string; label: string; icon: React.ElementType }>
|
allInclusions: Array<{ id: string; label: string; icon: React.ElementType }>
|
||||||
|
saving?: boolean
|
||||||
|
error?: string
|
||||||
}) {
|
}) {
|
||||||
const [form, setForm] = useState<Omit<Tariff, 'id'>>(
|
const [form, setForm] = useState<Omit<Tariff, 'id'>>(
|
||||||
tariff ? { ...tariff } : { ...EMPTY_TARIFF }
|
tariff ? { ...tariff } : { ...EMPTY_TARIFF }
|
||||||
@@ -214,16 +216,18 @@ function TariffModal({
|
|||||||
size="2xl"
|
size="2xl"
|
||||||
footer={
|
footer={
|
||||||
<>
|
<>
|
||||||
<button onClick={onClose} className="btn-secondary">Отмена</button>
|
{error && <p className="text-sm text-red-600 dark:text-red-400 mr-auto">{error}</p>}
|
||||||
|
<button onClick={onClose} className="btn-secondary" disabled={saving}>Отмена</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!form.name) return
|
if (!form.name || saving) return
|
||||||
const code = form.code || autoCode(form.name) || `T${Date.now().toString(36).toUpperCase().slice(-4)}`
|
const code = form.code || autoCode(form.name) || `T${Date.now().toString(36).toUpperCase().slice(-4)}`
|
||||||
onSave({ ...form, code })
|
onSave({ ...form, code })
|
||||||
}}
|
}}
|
||||||
className="btn-primary"
|
className="btn-primary gap-1.5 disabled:opacity-50"
|
||||||
disabled={!form.name}
|
disabled={!form.name || saving}
|
||||||
>
|
>
|
||||||
|
{saving && <Loader2 size={14} className="animate-spin" />}
|
||||||
{tariff ? 'Сохранить' : 'Создать тариф'}
|
{tariff ? 'Сохранить' : 'Создать тариф'}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
@@ -412,6 +416,8 @@ export function TariffsPage() {
|
|||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [modal, setModal] = useState<'create' | Tariff | null>(null)
|
const [modal, setModal] = useState<'create' | Tariff | null>(null)
|
||||||
const [deleteTarget, setDeleteTarget] = useState<Tariff | null>(null)
|
const [deleteTarget, setDeleteTarget] = useState<Tariff | null>(null)
|
||||||
|
const [saveError, setSaveError] = useState('')
|
||||||
|
const [saving, setSaving] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!slug) return
|
if (!slug) return
|
||||||
@@ -442,6 +448,9 @@ export function TariffsPage() {
|
|||||||
|
|
||||||
const save = async (data: Omit<Tariff, 'id'>) => {
|
const save = async (data: Omit<Tariff, 'id'>) => {
|
||||||
if (!slug) return
|
if (!slug) return
|
||||||
|
setSaving(true)
|
||||||
|
setSaveError('')
|
||||||
|
try {
|
||||||
const payload = {
|
const payload = {
|
||||||
name: data.name, code: data.code, meal_plan: data.mealPlan,
|
name: data.name, code: data.code, meal_plan: data.mealPlan,
|
||||||
inclusions: data.inclusions, modifier_type: data.modifierType,
|
inclusions: data.inclusions, modifier_type: data.modifierType,
|
||||||
@@ -451,14 +460,19 @@ export function TariffsPage() {
|
|||||||
}
|
}
|
||||||
const isEdit = typeof modal === 'object' && modal !== null
|
const isEdit = typeof modal === 'object' && modal !== null
|
||||||
const saved = isEdit
|
const saved = isEdit
|
||||||
? await api.tariffs.update(slug, modal.id, payload)
|
? await api.tariffs.update(slug, (modal as Tariff).id, payload)
|
||||||
: await api.tariffs.create(slug, payload)
|
: await api.tariffs.create(slug, payload)
|
||||||
const converted = fromApi(saved)
|
const converted = fromApi(saved)
|
||||||
setTariffs(prev => isEdit
|
setTariffs(prev => isEdit
|
||||||
? prev.map(t => t.id === modal.id ? converted : t)
|
? prev.map(t => t.id === (modal as Tariff).id ? converted : t)
|
||||||
: [...prev, converted],
|
: [...prev, converted],
|
||||||
)
|
)
|
||||||
setModal(null)
|
setModal(null)
|
||||||
|
} catch (err) {
|
||||||
|
setSaveError(err instanceof Error ? err.message : 'Ошибка сохранения')
|
||||||
|
} finally {
|
||||||
|
setSaving(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleActive = async (id: string) => {
|
const toggleActive = async (id: string) => {
|
||||||
@@ -740,9 +754,11 @@ export function TariffsPage() {
|
|||||||
<TariffModal
|
<TariffModal
|
||||||
tariff={typeof modal === 'object' ? modal : undefined}
|
tariff={typeof modal === 'object' ? modal : undefined}
|
||||||
onSave={save}
|
onSave={save}
|
||||||
onClose={() => setModal(null)}
|
onClose={() => { setModal(null); setSaveError('') }}
|
||||||
mealPlans={mealPlans}
|
mealPlans={mealPlans}
|
||||||
allInclusions={allInclusions}
|
allInclusions={allInclusions}
|
||||||
|
saving={saving}
|
||||||
|
error={saveError}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user