chore: initial import for test contour
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import { apiUrl } from '@/config/api';
|
||||
import { CertEditor } from '../Editors/CertEditor'
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
export function CertificatesForm({ initCertificates, onChange }) {
|
||||
const [initialCertificates, setInitialCertificates] = useState([]);
|
||||
const [certificates, setCertificates] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const certificatesWithPictureUrl = initCertificates.map((init) => ({ ...init, picture: apiUrl(`/uploads/${init.picture}`)}))
|
||||
setInitialCertificates([...certificatesWithPictureUrl])
|
||||
setCertificates([...certificatesWithPictureUrl])
|
||||
}, [initCertificates])
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof onChange === 'function') {
|
||||
onChange(certificates);
|
||||
}
|
||||
}, [certificates, onChange]);
|
||||
|
||||
const updateField = (idx, field, value) => {
|
||||
setCertificates(prev =>
|
||||
prev.map((cert, i) =>
|
||||
i === idx
|
||||
? { ...cert, [field]: value }
|
||||
: cert
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const replaceImage = (e, idx) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
if (!isValidImage(file)) {
|
||||
return window.alert('Изображения должны быть только формата JPG, JPEG или PNG');
|
||||
}
|
||||
const url = window.URL.createObjectURL(file);
|
||||
setCertificates(prev =>
|
||||
prev.map((cert, i) =>
|
||||
i === idx
|
||||
? { ...cert, picture: url, _file: file }
|
||||
: cert
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const addCertificate = () => {
|
||||
setCertificates(prev => [
|
||||
...prev,
|
||||
{ name: '', description: '', picture: '', type: 'certificate', active: false, }
|
||||
]);
|
||||
};
|
||||
|
||||
const deleteCertificate = idx => {
|
||||
setCertificates(prev => prev.filter((_, i) => i !== idx));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{certificates.map((cert, idx) => (
|
||||
<div className="card mb-3 p-3" key={idx}>
|
||||
<div className="form-group">
|
||||
<label>Название</label>
|
||||
<input
|
||||
className="form-control"
|
||||
value={cert.name}
|
||||
onChange={e => updateField(idx, 'name', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='d-flex' style={{gap: '2rem'}}>
|
||||
<div className="form-group flex-grow-1">
|
||||
<label>Описание</label>
|
||||
<CertEditor
|
||||
content={cert.description}
|
||||
setContent={newVal => updateField(idx, 'description', newVal)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="form-check mb-3">
|
||||
<input
|
||||
id={`active-cert${idx}`}
|
||||
type="checkbox"
|
||||
className="form-check-input"
|
||||
checked={ cert.active }
|
||||
onChange={e => updateField(idx, 'active', e.target.checked)}
|
||||
/>
|
||||
<label htmlFor={`active-cert${idx}`} className="form-check-label">
|
||||
Отображать на сайте
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-group d-flex flex-column align-items-center" style={{ gap: '1rem' }}>
|
||||
<label
|
||||
htmlFor={`file-${idx}`}
|
||||
className="btn btn-outline-primary"
|
||||
style={{ cursor: 'pointer', height: '2.5rem', width: '13rem' }}
|
||||
>
|
||||
Загрузить сертификат
|
||||
</label>
|
||||
<input
|
||||
id={`file-${idx}`}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
style={{ display: 'none' }}
|
||||
onChange={e => replaceImage(e, idx)}
|
||||
/>
|
||||
{cert.picture && (
|
||||
<img
|
||||
src={cert.picture}
|
||||
alt="Сертификат"
|
||||
style={{ width: '10rem', height: '10rem', objectFit: 'cover', borderRadius: '4px' }}
|
||||
onError={e => e.currentTarget.src = '/placeholder.png'}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='d-flex justify-content-start'>
|
||||
<button
|
||||
className="btn btn-danger"
|
||||
onClick={() => deleteCertificate(idx)}
|
||||
>
|
||||
Удалить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<button
|
||||
className="btn btn-outline-primary mb-3"
|
||||
onClick={addCertificate}
|
||||
>
|
||||
Добавить сертификат
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user