/* ===== Подари вторую жизнь — Admin ===== */
function adminReplaceStore(list){ PF.animals.length=0; list.forEach(x=>PF.animals.push(x)); }
function buildAnimal(form){
const ageMonths = Math.max(1, Number(form.ageMonths)||12);
const photos = (form.photos && form.photos.length) ? form.photos : [PF.U(form.species==='cat'?'1518791841217-8f162f1e1131':'1543466835-00a7907e9de1',800)];
const waiting = Math.max(0, Number(form.waiting)||0);
return {
id: form.id || ('pet-'+Date.now().toString(36)),
name: form.name?.trim()||'Без клички', species:form.species, breed:form.breed?.trim()||'Метис',
color:form.color, size:form.size, sex:form.sex, ageMonths,
weight: Math.max(0.1, Number(form.weight)||5),
health: form.health?.trim()||'Привит, обработан от паразитов',
needs: form.needs?.trim() || null,
waiting,
second: waiting >= 12 || PF.ageGroup(ageMonths)==='senior',
loc: form.loc?.trim()||'Передержка, Москва', contact: form.contact?.trim()||'+7 000 000-00-00',
desc: form.desc?.trim()||'Описание появится позже.',
ageText: PF.ageLabel(ageMonths), ageGroup: PF.ageGroup(ageMonths),
photoUrl: photos[0], photoUrlSm: photos[0], galleryUrls: photos, gallery: photos, photo:null,
};
}
function AdminScreen(){
const { go } = useNav();
const [authed, setAuthed] = useState(()=> sessionStorage.getItem('pf_admin')==='1');
const [pass, setPass] = useState(''); const [err, setErr] = useState(false);
const [, force] = useState(0);
const [view, setView] = useState('list'); // list | form
const [editing, setEditing] = useState(null);
const [toast, setToast] = useState(null);
const list = PF.animals;
const login = (e)=>{ e.preventDefault(); if(pass===PF.ADMIN_PASS){ sessionStorage.setItem('pf_admin','1'); setAuthed(true);} else { setErr(true);} };
const logout = ()=>{ sessionStorage.removeItem('pf_admin'); setAuthed(false); setPass(''); };
const notify = (m)=>{ setToast(m); setTimeout(()=>setToast(null),2400); };
const onSave = (form)=>{
const built = buildAnimal(form);
if(form.id){ const i=list.findIndex(x=>x.id===form.id); if(i>=0) list[i]=built; notify('Изменения сохранены'); }
else { list.unshift(built); notify('Питомец добавлен'); }
setView('list'); setEditing(null); force(n=>n+1);
};
const onDelete = (id)=>{
const i=list.findIndex(x=>x.id===id); if(i>=0) list.splice(i,1);
notify('Питомец удалён'); force(n=>n+1);
};
if(!authed){
return (
Вход для кураторов
Раздел доступен по паролю. Подсказка для демо — lapka
);
}
if(view==='form') return {setView('list');setEditing(null);}} toast={toast}/>;
return (
Админ-панель
Управление животными
{list.length} {plural(list.length,'питомец','питомца','питомцев')} в базе
{list.map(a=>(
{a.name}
{PF.speciesOne(a.species)} · {a.breed} · {a.ageText} · {PF.sizeLabel(a.size)}
{a.loc}
))}
{toast &&
}
);
}
function AdminForm({ initial, onSave, onCancel, toast }){
const [form, setForm] = useState(()=> initial ? {
id:initial.id, name:initial.name, species:initial.species, breed:initial.breed, color:initial.color,
size:initial.size, sex:initial.sex, ageMonths:initial.ageMonths, loc:initial.loc, contact:initial.contact,
desc:initial.desc, weight:initial.weight, health:initial.health, needs:initial.needs||'', waiting:initial.waiting,
photos:[...(initial.galleryUrls||[])]
} : {
name:'', species:'cat', breed:'', color:'grey', size:'medium', sex:'male', ageMonths:12,
weight:5, health:'Привит, обработан от паразитов', needs:'', waiting:1,
loc:'', contact:'', desc:'', photos:[]
});
const set = (k,v)=> setForm(f=>({...f,[k]:v}));
const addPhotos = (files)=>{
[...files].forEach(file=>{ if(!file.type.startsWith('image/'))return; const r=new FileReader(); r.onload=e=>setForm(f=>({...f,photos:[...f.photos,e.target.result]})); r.readAsDataURL(file); });
};
const fieldStyle = {width:'100%',padding:'12px 14px',borderRadius:'var(--radius-sm)',border:'1.5px solid var(--line-strong)',fontSize:15,fontFamily:'var(--font-body)',background:'var(--surface)'};
const Lbl = ({children}) => ;
const Seg = ({value,opts,onCh,renderIco}) => (
{opts.map(o=>(
))}
);
return (
{initial?'Редактировать питомца':'Новый питомец'}
Заполните карточку — она появится в каталоге сразу после сохранения.
{/* photos */}
Фотографии
{form.photos.map((p,i)=>(
{i===0 &&
главное}
))}
Вид({id:s.id,label:s.one}))} onCh={v=>set('species',v)} renderIco={o=>}/>
Окрасset('color',v)} renderIco={o=>}/>
Размерset('size',v)}/>
Полset('sex',v)} renderIco={o=>o.id==='male'?:}/>
Здоровьеset('health',e.target.value)} placeholder="Привит, обработан, стерилизован…"/>
Особые потребности (если есть)set('needs',e.target.value)} placeholder="Диета, без маленьких детей, опытный хозяин…"/>
Описание характера
{toast &&
}
);
}
function Toast({ msg }){
return {msg}
;
}
window.AdminScreen = AdminScreen;