issues/27: admin content CRUD promotions pattern
This commit is contained in:
committed by
Valeriy Petrov
parent
5aab178eb8
commit
dde8ab9ceb
@@ -0,0 +1,103 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useCreateSitePromoMutation } from '/src/api/apiSitePromo';
|
||||
import { selectRegions } from '../store/slice/regionSlice';
|
||||
import { TextEditor } from '../components/Editors/TextEditor';
|
||||
import { LoadingComponent } from '../components/Placeholders/LoadingComponent';
|
||||
import { ErrorComponent } from '../components/Placeholders/ErrorComponent';
|
||||
import { NotFindElement } from '../components/Placeholders/NotFindElement';
|
||||
import { EditElementForm } from '../components/Forms/EditElementForm';
|
||||
import Modal from '../components/Modals/Modal';
|
||||
|
||||
export function AddSitePromoPage() {
|
||||
|
||||
const navigate = useNavigate();
|
||||
const navigateBack = () => navigate(`/site-promo`);
|
||||
const regions = useSelector(selectRegions);
|
||||
const [createSitePromo] = useCreateSitePromoMutation();
|
||||
const [isModalSuccess, setModalSuccess] = useState(false);
|
||||
const [errors, setErrors] = useState({ name: '', alias: '', regionId: '' });
|
||||
const [form, setForm] = useState({
|
||||
name: '',
|
||||
active: false,
|
||||
regionId: '',
|
||||
alias: '',
|
||||
shortName: '',
|
||||
period: '',
|
||||
timer: '',
|
||||
timerBg: '',
|
||||
clinics: '',
|
||||
linkServices: '',
|
||||
linkStaff: '',
|
||||
photos: '',
|
||||
});
|
||||
const [anons, setAnons] = useState('');
|
||||
const [content, setContent] = useState('');
|
||||
|
||||
|
||||
|
||||
const handleChange = (key) => (e) => {
|
||||
const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
|
||||
setForm((f) => ({ ...f, [key]: value }));
|
||||
if (key === 'name' || key === 'alias' || key === 'regionId') setErrors((err) => ({ ...err, [key]: '' }));
|
||||
};
|
||||
|
||||
|
||||
|
||||
const handleSave = async () => {
|
||||
const newErrors = { name: '', alias: '', regionId: '' };
|
||||
let hasError = false;
|
||||
if (!String(form.name ?? '').trim()) { newErrors.name = 'Название не может быть пустым'; hasError = true; }
|
||||
if (!String(form.alias ?? '').trim()) { newErrors.alias = 'Alias не может быть пустым'; hasError = true; }
|
||||
if (form.regionId === '' || form.regionId == null) { newErrors.regionId = 'Укажите регион'; hasError = true; }
|
||||
if (hasError) { setErrors(newErrors); window.alert('Пожалуйста исправьте ошибки в форме.'); return; }
|
||||
const data = { anons, content };
|
||||
try {
|
||||
data.name = form.name === '' ? null : form.name;
|
||||
data.active = Boolean(form.active);
|
||||
data.regionId = form.regionId === '' ? null : Number(form.regionId);
|
||||
data.alias = form.alias === '' ? null : form.alias;
|
||||
data.shortName = form.shortName === '' ? null : form.shortName;
|
||||
data.period = form.period === '' ? null : form.period;
|
||||
data.timer = form.timer === '' ? null : form.timer;
|
||||
data.timerBg = form.timerBg === '' ? null : form.timerBg;
|
||||
data.clinics = !form.clinics || !String(form.clinics).trim() ? null : JSON.parse(form.clinics);
|
||||
data.linkServices = !form.linkServices || !String(form.linkServices).trim() ? null : JSON.parse(form.linkServices);
|
||||
data.linkStaff = !form.linkStaff || !String(form.linkStaff).trim() ? null : JSON.parse(form.linkStaff);
|
||||
data.photos = !form.photos || !String(form.photos).trim() ? null : JSON.parse(form.photos);
|
||||
} catch (e) { window.alert('Пожалуйста исправьте ошибки в форме.'); return; }
|
||||
try {
|
||||
const response = await createSitePromo({ data }).unwrap();
|
||||
setModalSuccess(true);
|
||||
window.setTimeout(() => { navigate(`/site-promo/edit/${response.id}`); window.location.reload(); }, 2000);
|
||||
} catch (err) {
|
||||
console.error('Ошибка сохранения:', err);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<EditElementForm navigateBack={navigateBack} header={`Добавление: промо`} handleSave={handleSave} handleDelete={() => {}} isAddSpecialist={true}>
|
||||
<div className="form-group"><label>Название</label><input type="text" className="form-control" value={form.name} onChange={handleChange('name')} />
|
||||
{errors.name && <small className="text-danger">{errors.name}</small>}</div>
|
||||
<div className="form-group form-check"><input type="checkbox" className="form-check-input" id="active" checked={Boolean(form.active)} onChange={handleChange('active')} /><label className="form-check-label" htmlFor="active">Активно</label></div>
|
||||
<div className="form-group"><label>Регион</label><select className="form-control" value={form.regionId === '' || form.regionId == null ? '' : String(form.regionId)} onChange={handleChange('regionId')}><option value="">—</option>{Object.entries(regions).map(([rid, name]) => (<option key={rid} value={rid}>{name}</option>))}</select>
|
||||
{errors.regionId && <small className="text-danger">{errors.regionId}</small>}</div>
|
||||
<div className="form-group"><label>Alias</label><input type="text" className="form-control" value={form.alias} onChange={handleChange('alias')} />
|
||||
{errors.alias && <small className="text-danger">{errors.alias}</small>}</div>
|
||||
<div className="form-group"><label>Анонс</label><TextEditor content={anons} setContent={setAnons} /></div>
|
||||
<div className="form-group"><label>Контент</label><TextEditor content={content} setContent={setContent} /></div>
|
||||
<div className="form-group"><label>Короткое название</label><input type="text" className="form-control" value={form.shortName} onChange={handleChange('shortName')} /></div>
|
||||
<div className="form-group"><label>Период</label><input type="text" className="form-control" value={form.period} onChange={handleChange('period')} /></div>
|
||||
<div className="form-group"><label>Таймер</label><input type="text" className="form-control" value={form.timer} onChange={handleChange('timer')} /></div>
|
||||
<div className="form-group"><label>Фон таймера</label><input type="text" className="form-control" value={form.timerBg} onChange={handleChange('timerBg')} /></div>
|
||||
<div className="form-group"><label>clinics (JSON)</label><textarea className="form-control font-monospace" rows={4} value={form.clinics} onChange={handleChange('clinics')} /></div>
|
||||
<div className="form-group"><label>linkServices (JSON)</label><textarea className="form-control font-monospace" rows={4} value={form.linkServices} onChange={handleChange('linkServices')} /></div>
|
||||
<div className="form-group"><label>linkStaff (JSON)</label><textarea className="form-control font-monospace" rows={4} value={form.linkStaff} onChange={handleChange('linkStaff')} /></div>
|
||||
<div className="form-group"><label>photos (JSON)</label><textarea className="form-control font-monospace" rows={4} value={form.photos} onChange={handleChange('photos')} /></div>
|
||||
<Modal isOpen={isModalSuccess} title="Изменения внесены" hasButtons={false}><p className="mb-1">Изменения успешно внесены.</p></Modal>
|
||||
</EditElementForm>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user