Update frontend for new backend

This commit is contained in:
IgorVolochay
2026-09-01 14:31:52 +03:00
parent bdf3d5aec1
commit 008dd1c29e
22 changed files with 1113 additions and 264 deletions
+27 -13
View File
@@ -1,13 +1,13 @@
import React, { useState } from 'react';
import { useApp } from '../../context/AppContext';
import { currentUser } from '../../services/auth';
import { currentUser, hapticImpact, hapticNotification } from '../../services/auth';
import { api } from '../../services/api';
import './CreateCard.css';
const MAX_LENGTH = 150;
export default function CreateCard({ onBack }) {
const { showToast, closeMenu } = useApp();
const { showToast, closeMenu, handleApiResponse } = useApp();
const [choiceA, setChoiceA] = useState('');
const [choiceB, setChoiceB] = useState('');
const [isSending, setIsSending] = useState(false);
@@ -17,47 +17,60 @@ export default function CreateCard({ onBack }) {
async function handleSubmit() {
if (!canSubmit) return;
setIsSending(true);
hapticImpact('light');
try {
const result = await api.addCard(choiceA.trim(), choiceB.trim(), currentUser.id);
handleApiResponse(result);
if (!result.error) {
hapticNotification('success');
showToast('Карточка отправлена на модерацию!');
setTimeout(() => {
closeMenu();
}, 2000);
}, 1800);
} else {
showToast('Ошибка: ' + (result.result || 'неизвестная'));
hapticNotification('error');
showToast(typeof result.result === 'string' ? result.result : 'Ошибка модерации или отправки');
setIsSending(false);
}
} catch (err) {
console.error('Add card error:', err);
hapticNotification('error');
showToast('Ошибка отправки');
setIsSending(false);
}
}
const handleBack = () => {
hapticImpact('light');
onBack();
};
return (
<div className="create-card custom-scroll">
<button className="create-back" onClick={onBack} aria-label="Назад">
<button className="create-back" onClick={handleBack} aria-label="Назад">
Назад
</button>
<h2 className="create-title">Создать карточку</h2>
<p className="create-rules">
При создании карточек запрещается использование мата и ссылок.
Все карточки проходят процесс модерации перед публикацией.
Лимит по длине текста: {MAX_LENGTH} символов.
</p>
<div className="create-rules-box">
<p className="create-rules">
💡 <strong>Правила публикации:</strong> Запрещены нецензурные выражения, оскорбления и спам-ссылки. Все карточки проверяются перед публикацией.
</p>
</div>
<div className="create-fields">
<div className="create-field create-field--a">
<textarea
className="create-textarea"
placeholder="Первый вариант"
placeholder="Вариант А"
value={choiceA}
onChange={(e) => setChoiceA(e.target.value.slice(0, MAX_LENGTH))}
maxLength={MAX_LENGTH}
rows={3}
disabled={isSending}
/>
<span className="create-counter">
{choiceA.length}/{MAX_LENGTH}
@@ -67,11 +80,12 @@ export default function CreateCard({ onBack }) {
<div className="create-field create-field--b">
<textarea
className="create-textarea"
placeholder="Второй вариант"
placeholder="Вариант Б"
value={choiceB}
onChange={(e) => setChoiceB(e.target.value.slice(0, MAX_LENGTH))}
maxLength={MAX_LENGTH}
rows={3}
disabled={isSending}
/>
<span className="create-counter">
{choiceB.length}/{MAX_LENGTH}
@@ -84,7 +98,7 @@ export default function CreateCard({ onBack }) {
onClick={handleSubmit}
disabled={!canSubmit}
>
{isSending ? 'Отправка...' : 'Отправить!'}
{isSending ? 'Отправка на модерацию...' : 'Отправить на модерацию'}
</button>
</div>
);