327 lines
9.7 KiB
React
327 lines
9.7 KiB
React
import { useEffect, useState, useRef } from 'react';
|
||
import { useParams, useNavigate } from 'react-router-dom';
|
||
import { useSelector } from 'react-redux';
|
||
|
||
import { useGetFilialsQuery, useUpdateFilialMutation, useUploadFilialPictureMutation } from '../api/apiFilial';
|
||
import { selectUtils } from '../store/slice/utilsSlice';
|
||
import { selectRegions } from '../store/slice/regionSlice';
|
||
/**/
|
||
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 { ResponseModals } from '../components/Modals/ResponseModals';
|
||
import { PhoneInput } from '../components/Input/PhoneInput';
|
||
|
||
export const EditFilialPage = () => {
|
||
const { id } = useParams();
|
||
const { data: filialsRaw = [], isLoading, loadingError } = useGetFilialsQuery();
|
||
const PHOTO_PLACEHOLDER = '/src/assets/photo-placeholder.png';
|
||
const photoInputRef = useRef(null);
|
||
|
||
const filials = filialsRaw.length === 0 ? [] : filialsRaw.data;
|
||
const filial = filials.find( ( filial ) => String( filial.fid ) === id );
|
||
|
||
const regions = useSelector( selectRegions );
|
||
const RELOAD_TIMEOUT = useSelector(selectUtils).RELOAD_TIMEOUT;
|
||
|
||
const [ updateFilial ] = useUpdateFilialMutation();
|
||
const [uploadPicture] = useUploadFilialPictureMutation();
|
||
|
||
const navigate = useNavigate();
|
||
const navigateBack = () => navigate( `/filials` );
|
||
|
||
const [ form, setForm ] = useState({
|
||
id: '',
|
||
regionId: '',
|
||
address: '',
|
||
name: '',
|
||
siteId: '',
|
||
company: '',
|
||
phone: '',
|
||
active: '',
|
||
email: '',
|
||
fid: '',
|
||
origin: '',
|
||
picture: null,
|
||
policy: '',
|
||
});
|
||
const updateField = ( key, value ) => {
|
||
const normalized = value === undefined || value === null ? '' : value;
|
||
setForm(prev => ({ ...prev, [key]: normalized }));
|
||
};
|
||
|
||
const [ modal, setModal ] = useState( undefined );
|
||
const [previewFile, setPreviewFile] = useState(null);
|
||
|
||
useEffect(() => {
|
||
if (!filial) return;
|
||
|
||
const filialData = {
|
||
id: filial.id,
|
||
regionId: filial.regionId,
|
||
address: filial.address,
|
||
name: filial.name,
|
||
siteId: filial.siteId,
|
||
company: filial.company,
|
||
phone: filial.phone,
|
||
active: filial.active,
|
||
email: filial.email,
|
||
fid: filial.fid,
|
||
origin: filial.origin,
|
||
picture: `https://api.sovamed.ru${filial.pictureLink}`,
|
||
policy: filial.policy,
|
||
}
|
||
setForm({... filialData})
|
||
}, [ filial ]);
|
||
|
||
const isValidImage = (file) => {
|
||
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
|
||
if (allowedTypes.includes(file.type)) return true;
|
||
|
||
const ext = file.name.split('.').pop().toLowerCase();
|
||
return ['jpg', 'jpeg', 'png'].includes(ext);
|
||
};
|
||
|
||
const handlePhotoUpload = () => {
|
||
const file = photoInputRef.current.files[0]
|
||
if (!file) return window.alert('Файл не выбран')
|
||
if (!isValidImage(file)) {
|
||
return window.alert('Изображения должны быть только формата JPG, JPEG или PNG');
|
||
}
|
||
updateField('picture', window.URL.createObjectURL(file));
|
||
setPreviewFile(file);
|
||
}
|
||
|
||
const handleSave = async () => {
|
||
setModal('loading');
|
||
|
||
const data = {
|
||
id: form.id,
|
||
fid: form.fid,
|
||
active: form.active,
|
||
regionId: Number(form.regionId),
|
||
address: form.address || '',
|
||
name: form.name || '',
|
||
company: form.company || '',
|
||
phone: form.phone ? form.phone.replaceAll(' ', '') : '',
|
||
email: form.email || '',
|
||
policy: form.policy || '',
|
||
origin: form.origin || '',
|
||
};
|
||
|
||
try {
|
||
await updateFilial( { filialId: form.fid, data: form.siteId ? { ...data, siteId: form.siteId } : data } ).unwrap();
|
||
|
||
if (previewFile) {
|
||
await uploadPicture({ id: form.id, file: previewFile }).unwrap();
|
||
console.log('success photo update')
|
||
}
|
||
|
||
setModal('success');
|
||
window.setTimeout(() => { window.location.reload() }, RELOAD_TIMEOUT);
|
||
}
|
||
catch ( error ) {
|
||
setModal('error')
|
||
console.error('Filial update error:', error);
|
||
}
|
||
}
|
||
|
||
if ( isLoading ) return <LoadingComponent />
|
||
if ( loadingError ) return <ErrorComponent />
|
||
if ( !filial ) return (
|
||
<NotFindElement
|
||
message={ `Филиал с ID=${id} не найден.` }
|
||
navigateBack={ navigateBack }
|
||
/>
|
||
)
|
||
|
||
return (
|
||
<EditElementForm
|
||
navigateBack={ navigateBack }
|
||
header={ `Редактировать филиал #${ filial.fid }` }
|
||
handleSave={ handleSave }
|
||
isAddSpecialist={ true }
|
||
>
|
||
|
||
<div style={{ display: 'flex', gap: '1rem' }} className='photo-filial-block'>
|
||
|
||
<div className='align-self-start'>
|
||
<div className="form-group d-flex flex-column" style={{ gap: '0.75rem' }}>
|
||
<img
|
||
src={ form.picture }
|
||
alt="Фото врача"
|
||
style={{ width: '12rem', height: '12rem', objectFit: 'cover', borderRadius: '3%' }}
|
||
className=""
|
||
onError={ e => e.currentTarget.src = PHOTO_PLACEHOLDER }
|
||
/>
|
||
<button
|
||
type="button"
|
||
className="btn btn-outline-secondary"
|
||
style={{ width: '100%' }}
|
||
onClick={ () => photoInputRef.current.click() }
|
||
>
|
||
Загрузить фото
|
||
</button>
|
||
<input
|
||
type="file"
|
||
accept="image/*"
|
||
ref={ photoInputRef }
|
||
style={{ display: 'none' }}
|
||
onChange={handlePhotoUpload}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div style={{ flexGrow: 1 }}>
|
||
|
||
<div style={{ flexGrow: 1 }}>
|
||
|
||
<div className='d-flex filial-input-string' style={{ gap: '1rem' }}>
|
||
<div className="form-group">
|
||
<label htmlFor="regionSelect">
|
||
Город
|
||
</label>
|
||
<select
|
||
id="regionSelect"
|
||
className="form-control w-auto"
|
||
value={ form.regionId }
|
||
onChange={( e ) => updateField( 'regionId', e.target.value )}
|
||
>
|
||
{
|
||
Object.entries( regions ).map(( [ key, label ] ) => (
|
||
<option key={ key } value={ key }>
|
||
{ label }
|
||
</option>
|
||
))
|
||
}
|
||
</select>
|
||
</div>
|
||
<div className="form-group" style={{ flexGrow: 1 }}>
|
||
<label>
|
||
ID филиала
|
||
</label>
|
||
<input
|
||
type="text"
|
||
className="form-control"
|
||
value={ form.fid }
|
||
onChange={( e ) => updateField( 'fid', e.target.value )}
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group" style={{ flexGrow: 1 }}>
|
||
<label>
|
||
Calltouch ID
|
||
</label>
|
||
<input
|
||
type="text"
|
||
className="form-control"
|
||
value={ form.siteId }
|
||
onChange={( e ) => updateField( 'siteId', e.target.value )}
|
||
/>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
|
||
<div className="form-group">
|
||
<label>
|
||
Название
|
||
</label>
|
||
<input
|
||
type="text"
|
||
className="form-control"
|
||
value={ form.name }
|
||
onChange={( e ) => updateField( 'name', e.target.value )}
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>
|
||
Компания
|
||
</label>
|
||
<input
|
||
type="text"
|
||
className="form-control"
|
||
value={ form.company }
|
||
onChange={( e ) => updateField( 'company', e.target.value )}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<div className="form-group">
|
||
<label>
|
||
Адрес
|
||
</label>
|
||
<input
|
||
type="text"
|
||
className="form-control"
|
||
value={ form.address }
|
||
onChange={( e ) => updateField( 'address', e.target.value )}
|
||
/>
|
||
</div>
|
||
|
||
|
||
|
||
<div className="form-group">
|
||
<label>
|
||
Телефон
|
||
</label>
|
||
<PhoneInput
|
||
value={form.phone}
|
||
onChange={(val) => updateField('phone', val)}
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>
|
||
Электронная почта филиала
|
||
</label>
|
||
<input
|
||
type="text"
|
||
className="form-control"
|
||
value={ form.email }
|
||
onChange={( e ) => updateField( 'email', e.target.value )}
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>
|
||
Ссылка на сайт
|
||
</label>
|
||
<input
|
||
type="text"
|
||
className="form-control"
|
||
value={ form.origin }
|
||
onChange={( e ) => updateField( 'origin', e.target.value )}
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>
|
||
Ссылка на политику кониденциальности
|
||
</label>
|
||
<input
|
||
type="text"
|
||
className="form-control"
|
||
value={ form.policy }
|
||
onChange={( e ) => updateField( 'policy', e.target.value )}
|
||
/>
|
||
</div>
|
||
|
||
<ResponseModals
|
||
modal={ modal }
|
||
setModal={ setModal }
|
||
/>
|
||
|
||
</EditElementForm>
|
||
)
|
||
}
|