Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/api/streetcode/text-content/facts.api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Agent from '@api/agent.api';
import { API_ROUTES } from '@constants/api-routes.constants';
import { Fact } from '@models/streetcode/text-contents.model';
import { Fact, FactCreate } from '@models/streetcode/text-contents.model';

const FactsApi = {
getById: (id: number) => Agent.get<Fact>(`${API_ROUTES.FACTS.GET}/${id}`),
Expand All @@ -11,7 +11,7 @@ const FactsApi = {
`${API_ROUTES.FACTS.GET_BY_STREETCODE_ID}/${streetcodeId}`,
),

create: (fact: Fact) => Agent.post<Fact>(`${API_ROUTES.FACTS.CREATE}`, fact),
create: (fact: FactCreate) => Agent.post<Fact>(`${API_ROUTES.FACTS.CREATE}`, fact),

update: (fact: Fact) => Agent.put<Fact>(`${API_ROUTES.FACTS.UPDATE}`, fact),

Expand Down
Original file line number Diff line number Diff line change
@@ -1,87 +1,235 @@
import './InterestingFactsAdminModal.style.scss';
import './InterestingFactsAdminModal.styles.scss';

import { observer } from 'mobx-react-lite';
import { useState } from 'react';
import { useEffect } from 'react';
import { InboxOutlined } from '@ant-design/icons';
import CancelBtn from '@assets/images/utils/Cancel_btn.svg';
import useMobx from '@stores/root-store';

import { Button, Form, Modal, Upload } from 'antd';
import FormItem from 'antd/es/form/FormItem';
import { UploadFile } from 'antd/lib/upload/interface';

import Image, { ImageCreate } from '@/models/media/image.model';
import { ImageCreate } from '@/models/media/image.model';
import { Fact, FactCreate } from '@/models/streetcode/text-contents.model';

const InterestingFactsModal = () => {
const { modalStore, factsStore, imagesStore: { getImageArray } } = useMobx();
interface InterestingFactsModalProps {
streetcodeId: number;
factToEdit?: Fact | null;
}

const InterestingFactsModal = ({ streetcodeId = 1, factToEdit = null }: InterestingFactsModalProps) => {
const { modalStore, factsStore, imagesStore: { createImage } } = useMobx();
const { setModal, modalsState: { adminFacts } } = modalStore;
const [factContent, setFactContent] = useState('');
const [form] = Form.useForm();

const titleValue = Form.useWatch('title', form) || '';
const mainTextValue = Form.useWatch('mainText', form) || '';
const imageDescriptionValue = Form.useWatch('imageDescription', form) || '';

const titleCount = titleValue.length;
const mainTextCount = mainTextValue.length;
const imageDescCount = imageDescriptionValue.length;

useEffect(() => {
if (adminFacts.isOpen && factToEdit) {
form.setFieldsValue({
title: factToEdit.title,
mainText: factToEdit.factContent,
imageDescription: factToEdit.imageDescription,
});
} else if (adminFacts.isOpen && !factToEdit) {
form.resetFields();
}
}, [adminFacts.isOpen, factToEdit, form]);

const characterCount = factContent.length | 0;
const fileToBase64 = (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const result = reader.result as string;
const base64 = result.split(',')[1];
resolve(base64);
};
reader.onerror = (error) => reject(error);
});
};

const normFile = (e: any) => {
if (Array.isArray(e)) {
return e;
}
return e?.fileList;
};

const onFinish = (values: any) => {
const uploadedFile = values.picture.file as UploadFile<any>;
const onFinish = async (values: any) => {
let imgId = factToEdit?.imageId;

const image: ImageCreate = {
blobName: uploadedFile.name ?? '',
mimeType: uploadedFile.type ?? '',
};
if (values.picture && values.picture.length > 0) {
const uploadedFile = values.picture[0];
const file = uploadedFile.originFileObj as File;

if (!file) {
Modal.error({ title: 'Помилка', content: 'Не вдалося отримати файл' });
return;
}

const fileName = uploadedFile.name ?? '';
const extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
const base64 = await fileToBase64(file);

const imageToCreate: ImageCreate = {
title: values.title || fileName,
baseFormat: base64,
mimeType: file.type ?? 'image/jpeg',
extension: extension,
};

const createdImage = await createImage(imageToCreate);
if (!createdImage) {
Modal.error({ title: 'Помилка', content: 'Не вдалося створити зображення' });
return;
}
imgId = createdImage.id;
}

const fact: FactCreate = {
title: values.title,
factContent,
image,
};
if (!imgId && !factToEdit) {
Modal.error({ title: 'Помилка', content: 'Зображення є обовʼязковим' });
return;
}

factsStore.addFactToCreate(fact);
try {
if (factToEdit) {
const fact: Fact = {
id: factToEdit.id,
title: values.title,
factContent: values.mainText,
imageId: imgId!,
order: factToEdit.order,
imageDescription: values.imageDescription,
};
await factsStore.updateFact(fact);
} else {
const fact: FactCreate = {
title: values.title,
factContent: values.mainText,
imageId: imgId!,
imageDescription: values.imageDescription,
streetcodeId: streetcodeId,
};
await factsStore.createFact(fact);
}

form.resetFields();
setModal('adminFacts', undefined, false);
} catch (error) {
console.log("Error: Fact has not been saved!");
Modal.error({
title: 'Помилка',
content: 'Не вдалося зберегти факт'
});
Comment thread
VolodymyrShapoval marked this conversation as resolved.
}
};

return (
<Modal
className="interestingFactsAdminModal"
open={adminFacts.isOpen}
onCancel={() => setModal('adminFacts')}
onCancel={() => {
form.resetFields();
setModal('adminFacts', undefined, false);
}}
footer={null}
maskClosable
centered
closeIcon={<CancelBtn />}
>
<Form className="factForm" onFinish={onFinish}>
<Form
form={form}
className="factForm"
onFinish={onFinish}
>
<h2>Wow-Факт</h2>
<p>Заголовок</p>

<div className="inputBlock">
<Form.Item name="title">
<input />
</Form.Item>
<p>Заголовок</p>
<div className="inputWithCounter">
<Form.Item
name="title"
rules={[
{ required: true, message: 'Поле обовʼязкове' },
{ max: 68, message: 'Максимум 68 символів' }
]}
>
<input maxLength={68} />
</Form.Item>
<span className="inputCounter">{titleCount}/68</span>
</div>
</div>

<div className="textareaBlock">
<p>Основний текст</p>
<textarea value={factContent} maxLength={600} onChange={(e) => setFactContent(e.target.value)} />
<Form.Item
name="mainText"
rules={[
{ required: true, message: 'Поле обовʼязкове' },
{ max: 600, message: 'Максимум 600 символів' }
]}
>
<textarea maxLength={600} />
</Form.Item>
<p className="characterCounter">
{characterCount}
/600
{mainTextCount}/600
</p>
</div>
<p>Зображення:</p>
<FormItem
name="picture"
className=""
>
<Upload
multiple={false}
accept=".jpeg,.png,.jpg"
listType="picture-card"
maxCount={1}

<div className="uploadBlock">
<p>Зображення:</p>
<FormItem
name="picture"
valuePropName="fileList"
getValueFromEvent={normFile}
rules={[
{ required: !factToEdit, message: 'Зображення обовʼязкове' }
]}
>
<div className="upload">
<InboxOutlined />
<p>Виберіть чи перетягніть файл</p>
</div>
</Upload>
</FormItem>
<Button className="saveButton" htmlType="submit">Зберегти</Button>
<Upload
multiple={false}
accept=".jpeg,.png,.jpg,.webp"
listType="picture-card"
maxCount={1}
beforeUpload={() => false}
>
<div className="upload">
<InboxOutlined />
<p>Виберіть чи перетягніть файл</p>
</div>
</Upload>
</FormItem>
</div>

<div className="imageDescriptionBlock">
<p>Підпис до фото</p>
<div className="inputWithCounter">
<Form.Item
name="imageDescription"
rules={[
{ required: true, message: 'Поле обовʼязкове' },
{ max: 200, message: 'Максимум 200 символів' }
]}
>
<input maxLength={200} />
</Form.Item>
<span className="inputCounter">{imageDescCount}/200</span>
</div>
</div>

<Button className="saveButton" htmlType="submit">
{factToEdit ? 'Оновити' : 'Зберегти'}
</Button>
</Form>
</Modal>
);
};

export default observer(InterestingFactsModal);
export default observer(InterestingFactsModal);
Loading