Files
mkd/components/settings/CompanySettingsModal.tsx
2026-02-04 00:17:04 +05:00

262 lines
10 KiB
TypeScript
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useEffect, useState } from 'react';
import { X, Building2, Loader2 } from 'lucide-react';
import { apiClient } from '../../services/apiClient';
interface CompanySettings {
id?: number;
name: string;
fullName?: string | null;
address?: string | null;
phone?: string | null;
email?: string | null;
website?: string | null;
licenseNumber?: string | null;
licenseValidUntil?: string | null;
logoUrl?: string | null;
}
interface CompanySettingsModalProps {
onClose: () => void;
}
export const CompanySettingsModal: React.FC<CompanySettingsModalProps> = ({ onClose }) => {
const [form, setForm] = useState<CompanySettings>({
name: '',
fullName: '',
address: '',
phone: '',
email: '',
website: '',
licenseNumber: '',
licenseValidUntil: '',
logoUrl: '',
});
const [isLoading, setIsLoading] = useState(false);
const [isSaving, setIsSaving] = useState(false);
useEffect(() => {
const load = async () => {
try {
setIsLoading(true);
const data = await apiClient.get<CompanySettings>('/settings/company');
setForm({
name: data.name || '',
fullName: data.fullName || '',
address: data.address || '',
phone: data.phone || '',
email: data.email || '',
website: data.website || '',
licenseNumber: data.licenseNumber || '',
licenseValidUntil: data.licenseValidUntil
? String(data.licenseValidUntil).substring(0, 10)
: '',
logoUrl: data.logoUrl || '',
});
} catch (err: any) {
console.error('Error loading company settings:', err);
alert(`Не удалось загрузить данные компании: ${err.message || 'Неизвестная ошибка'}`);
} finally {
setIsLoading(false);
}
};
load();
}, []);
const handleChange = (field: keyof CompanySettings, value: string) => {
setForm(prev => ({ ...prev, [field]: value }));
};
const handleSave = async () => {
try {
setIsSaving(true);
await apiClient.put('/settings/company', {
name: form.name,
fullName: form.fullName || null,
address: form.address || null,
phone: form.phone || null,
email: form.email || null,
website: form.website || null,
licenseNumber: form.licenseNumber || null,
licenseValidUntil: form.licenseValidUntil || null,
logoUrl: form.logoUrl || null,
});
alert('Данные управляющей компании сохранены');
onClose();
} catch (err: any) {
console.error('Error saving company settings:', err);
alert(`Не удалось сохранить данные компании: ${err.message || 'Неизвестная ошибка'}`);
} finally {
setIsSaving(false);
}
};
return (
<div className="fixed inset-0 z-[70] bg-black/50 flex items-center justify-center p-4">
<div className="bg-white rounded-3xl shadow-2xl max-w-2xl w-full p-6">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3">
<div className="p-2 rounded-xl bg-primary-50 text-primary-600">
<Building2 className="w-5 h-5" />
</div>
<div>
<h2 className="text-lg font-black text-slate-800">Управляющая компания</h2>
<p className="text-xs text-slate-500">
Эти данные используются в отчетах жителям и PR-отчетах
</p>
</div>
</div>
<button
type="button"
onClick={onClose}
className="p-2 rounded-xl hover:bg-slate-100 text-slate-400"
>
<X className="w-4 h-4" />
</button>
</div>
{isLoading ? (
<div className="py-10 flex items-center justify-center">
<Loader2 className="w-6 h-6 animate-spin text-primary-600" />
</div>
) : (
<div className="space-y-4 max-h-[70vh] overflow-y-auto pr-1">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-xs font-black text-slate-500 uppercase mb-1">
Краткое наименование
</label>
<input
type="text"
value={form.name}
onChange={e => handleChange('name', e.target.value)}
className="w-full px-3 py-2 rounded-xl border border-slate-200 text-sm"
placeholder='Например: УК "Дружба"'
/>
</div>
<div>
<label className="block text-xs font-black text-slate-500 uppercase mb-1">
Полное наименование
</label>
<input
type="text"
value={form.fullName || ''}
onChange={e => handleChange('fullName', e.target.value)}
className="w-full px-3 py-2 rounded-xl border border-slate-200 text-sm"
placeholder='Например: ООО "Управляющая компания Дружба"'
/>
</div>
<div className="md:col-span-2">
<label className="block text-xs font-black text-slate-500 uppercase mb-1">
Адрес
</label>
<input
type="text"
value={form.address || ''}
onChange={e => handleChange('address', e.target.value)}
className="w-full px-3 py-2 rounded-xl border border-slate-200 text-sm"
placeholder="Юридический / фактический адрес"
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-xs font-black text-slate-500 uppercase mb-1">
Телефон
</label>
<input
type="text"
value={form.phone || ''}
onChange={e => handleChange('phone', e.target.value)}
className="w-full px-3 py-2 rounded-xl border border-slate-200 text-sm"
placeholder="+7 (___) ___-__-__"
/>
</div>
<div>
<label className="block text-xs font-black text-slate-500 uppercase mb-1">
Email
</label>
<input
type="email"
value={form.email || ''}
onChange={e => handleChange('email', e.target.value)}
className="w-full px-3 py-2 rounded-xl border border-slate-200 text-sm"
placeholder="info@company.ru"
/>
</div>
<div>
<label className="block text-xs font-black text-slate-500 uppercase mb-1">
Сайт
</label>
<input
type="text"
value={form.website || ''}
onChange={e => handleChange('website', e.target.value)}
className="w-full px-3 py-2 rounded-xl border border-slate-200 text-sm"
placeholder="https://..."
/>
</div>
<div>
<label className="block text-xs font-black text-slate-500 uppercase mb-1">
Номер лицензии
</label>
<input
type="text"
value={form.licenseNumber || ''}
onChange={e => handleChange('licenseNumber', e.target.value)}
className="w-full px-3 py-2 rounded-xl border border-slate-200 text-sm"
placeholder="Лицензия №..."
/>
</div>
<div>
<label className="block text-xs font-black text-slate-500 uppercase mb-1">
Лицензия действительна до
</label>
<input
type="date"
value={form.licenseValidUntil || ''}
onChange={e => handleChange('licenseValidUntil', e.target.value)}
className="w-full px-3 py-2 rounded-xl border border-slate-200 text-sm"
/>
</div>
<div>
<label className="block text-xs font-black text-slate-500 uppercase mb-1">
Логотип (URL)
</label>
<input
type="text"
value={form.logoUrl || ''}
onChange={e => handleChange('logoUrl', e.target.value)}
className="w-full px-3 py-2 rounded-xl border border-slate-200 text-sm"
placeholder="https://.../logo.png"
/>
</div>
</div>
</div>
)}
<div className="flex justify-end gap-3 mt-6">
<button
type="button"
onClick={onClose}
className="px-4 py-2 rounded-xl text-xs font-black uppercase tracking-wider bg-slate-100 text-slate-600 hover:bg-slate-200"
>
Отмена
</button>
<button
type="button"
onClick={handleSave}
disabled={isSaving || isLoading || !form.name}
className="px-5 py-2 rounded-xl text-xs font-black uppercase tracking-wider bg-primary-600 text-white hover:bg-primary-700 disabled:opacity-60 disabled:cursor-not-allowed flex items-center gap-2"
>
{isSaving && <Loader2 className="w-4 h-4 animate-spin" />}
Сохранить
</button>
</div>
</div>
</div>
);
};