fix: g+f+p

This commit is contained in:
KofK
2025-02-12 00:57:29 +03:00
parent 0c81c88228
commit a3b9ce9985
6 changed files with 784 additions and 44 deletions

View File

@@ -1,8 +1,20 @@
import { ThemeProvider, createTheme } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import logo from './logo.svg';
import './App.css';
const theme = createTheme({
palette: {
primary: {
main: '#1976d2',
},
},
});
function App() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
@@ -19,6 +31,7 @@ function App() {
</a>
</header>
</div>
</ThemeProvider>
);
}

View File

@@ -37,14 +37,14 @@ function GraphContainer({ vector }) {
const options = {
nodes: {
borderWidth: 2,
color: { border: '#800', background: '#F0E0D6' },
color: { border: '#42A5F5', background: '#F0E0D6' },
font: { size: 14 }
},
edges: {
color: '#800',
color: '#42A5F5',
width: 2,
arrows: 'to',
smooth: { type: 'curvedCW' }
smooth: { type: 'curvedCW' },
arrows: 'none'
},
physics: {
stabilization: true,

View File

@@ -1,60 +1,151 @@
import { useFormik } from 'formik';
import { useState } from 'react';
import {
Box,
Button,
TextField,
CircularProgress,
InputAdornment,
IconButton,
Snackbar,
Alert,
Typography,
Paper
} from '@mui/material';
import { PhotoCamera, Close } from '@mui/icons-material';
import { API_URL } from '../config';
function PostForm({ onPostCreated }) {
const [text, setText] = useState('');
const [image, setImage] = useState(null);
const [preview, setPreview] = useState('');
const [snackbar, setSnackbar] = useState({ open: false, message: '', severity: 'success' });
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData();
if (text) formData.append('text', text);
if (image) formData.append('image', image);
const formik = useFormik({
initialValues: {
text: '',
image: null
},
onSubmit: async (values, { setSubmitting, resetForm }) => {
try {
const formData = new FormData();
if (values.text) formData.append('text', values.text);
if (values.image) formData.append('image', values.image);
const response = await fetch(`${API_URL}/posts/`, {
method: 'POST',
body: formData,
});
if (!response.ok) throw new Error('Ошибка сервера');
try {
const response = await fetch(`${API_URL}/posts/`, {
method: 'POST',
body: formData,
});
if (response.ok) {
const data = await response.json();
onPostCreated(data.vector);
setText('');
setImage(null);
resetForm();
setPreview('');
showSnackbar('Пост успешно создан!', 'success');
} catch (error) {
showSnackbar(error.message || 'Ошибка создания поста', 'error');
} finally {
setSubmitting(false);
}
} catch (error) {
console.error('Post creation error:', error);
}
};
});
const handleImageChange = (e) => {
const file = e.target.files[0];
if (file) {
setImage(file);
const reader = new FileReader();
reader.onload = () => setPreview(reader.result);
reader.readAsDataURL(file);
formik.setFieldValue('image', file);
setPreview(URL.createObjectURL(file));
}
};
const showSnackbar = (message, severity) => {
setSnackbar({ open: true, message, severity });
};
return (
<div className="post-form">
<h2>Новый пост</h2>
<form onSubmit={handleSubmit}>
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
rows="4"
placeholder="Текст поста"
<Paper elevation={3} sx={{ p: 3, mb: 4, maxWidth: 600, mx: 'auto' }}>
<Typography variant="h5" gutterBottom component="div">
Новый пост
</Typography>
<form onSubmit={formik.handleSubmit}>
<TextField
fullWidth
multiline
minRows={4}
name="text"
value={formik.values.text}
onChange={formik.handleChange}
placeholder="Текст поста..."
variant="outlined"
margin="normal"
InputProps={{
endAdornment: (
<InputAdornment position="end">
<input
accept="image/*"
style={{ display: 'none' }}
id="image-upload"
type="file"
onChange={handleImageChange}
/>
<label htmlFor="image-upload">
<IconButton component="span" color="primary">
<PhotoCamera />
</IconButton>
</label>
</InputAdornment>
)
}}
/>
<input type="file" onChange={handleImageChange} accept="image/*" />
{preview && <img src={preview} className="preview-image" alt="Preview" />}
<button type="submit">Отправить</button>
{preview && (
<Box sx={{ mt: 2, position: 'relative' }}>
<img
src={preview}
alt="Preview"
style={{
maxWidth: '100%',
borderRadius: 4,
maxHeight: 200,
objectFit: 'cover'
}}
/>
<IconButton
onClick={() => {
formik.setFieldValue('image', null);
setPreview('');
}}
sx={{ position: 'absolute', right: 8, top: 8, bgcolor: 'background.paper' }}
>
<Close />
</IconButton>
</Box>
)}
<Box sx={{ mt: 3, display: 'flex', justifyContent: 'flex-end' }}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={formik.isSubmitting || (!formik.values.text && !formik.values.image)}
startIcon={formik.isSubmitting && <CircularProgress size={20} />}
>
{formik.isSubmitting ? 'Отправка...' : 'Опубликовать'}
</Button>
</Box>
</form>
</div>
<Snackbar
open={snackbar.open}
autoHideDuration={6000}
onClose={() => setSnackbar(prev => ({ ...prev, open: false }))}
>
<Alert severity={snackbar.severity} sx={{ width: '100%' }}>
{snackbar.message}
</Alert>
</Snackbar>
</Paper>
);
}