Files
reactShop/src/components/ArticleRatingForm.js

262 lines
7.4 KiB
JavaScript

import React, { Component } from 'react';
import {
Box,
Typography,
TextField,
Button,
Paper,
Alert,
CircularProgress,
Rating
} from '@mui/material';
import StarIcon from '@mui/icons-material/Star';
import { withI18n } from '../i18n/withTranslation.js';
import PhotoUpload from './PhotoUpload.js';
class ArticleRatingForm extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
rating: 0,
review: '',
photos: [],
loading: false,
success: false,
error: null
};
this.photoUploadRef = React.createRef();
}
handleInputChange = (field) => (event) => {
this.setState({ [field]: event.target.value });
};
handleRatingChange = (event, newValue) => {
this.setState({ rating: newValue });
};
handlePhotosChange = (files) => {
this.setState({ photos: files });
};
convertPhotosToBase64 = (photos) => {
return Promise.all(
photos.map(photo => {
return new Promise((resolve, _reject) => {
const reader = new FileReader();
reader.onload = (e) => {
resolve({
name: photo.name,
type: photo.type,
size: photo.size,
data: e.target.result // base64 string
});
};
reader.readAsDataURL(photo);
});
})
);
};
handleSubmit = async (event) => {
event.preventDefault();
this.setState({ loading: true });
try {
// Convert photos to base64
const photosBase64 = await this.convertPhotosToBase64(this.state.photos);
// Prepare data for API emission
const ratingData = {
type: 'article_rating',
productId: this.props.productId,
productName: this.props.productName,
name: this.state.name,
email: this.state.email,
rating: this.state.rating,
review: this.state.review,
photos: photosBase64,
timestamp: new Date().toISOString()
};
// Emit data via socket
console.log('Article Rating Data to emit:', ratingData);
window.socketManager.emit('article_rating_submit', ratingData);
// Set up response handler
window.socketManager.once('article_rating_response', (response) => {
if (response.success) {
this.setState({
loading: false,
success: true,
name: '',
email: '',
rating: 0,
review: '',
photos: []
});
// Reset the photo upload component
if (this.photoUploadRef.current) {
this.photoUploadRef.current.reset();
}
} else {
this.setState({
loading: false,
error: response.error || 'Ein Fehler ist aufgetreten'
});
}
// Clear messages after 3 seconds
setTimeout(() => {
this.setState({ success: false, error: null });
}, 3000);
});
} catch {
this.setState({
loading: false,
error: 'Fehler beim Verarbeiten der Fotos'
});
}
// Fallback timeout in case backend doesn't respond
setTimeout(() => {
if (this.state.loading) {
this.setState({
loading: false,
success: true,
name: '',
email: '',
rating: 0,
review: '',
photos: []
});
// Reset the photo upload component
if (this.photoUploadRef.current) {
this.photoUploadRef.current.reset();
}
// Clear success message after 3 seconds
setTimeout(() => {
this.setState({ success: false });
}, 3000);
}
}, 5000);
};
render() {
const { name, email, rating, review, loading, success, error } = this.state;
return (
<Paper sx={{ p: 3, mt: 4, borderRadius: 2, boxShadow: "0 2px 8px rgba(0,0,0,0.08)" }}>
<Typography variant="h5" gutterBottom sx={{ fontWeight: 600, color: '#333' }}>
Artikel Bewerten
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
Teilen Sie Ihre Erfahrungen mit diesem Artikel und helfen Sie anderen Kunden bei der Entscheidung.
</Typography>
{success && (
<Alert severity="success" sx={{ mb: 3 }}>
Vielen Dank für Ihre Bewertung! Sie wird nach Prüfung veröffentlicht.
</Alert>
)}
{error && (
<Alert severity="error" sx={{ mb: 3 }}>
{error}
</Alert>
)}
<Box component="form" onSubmit={this.handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<TextField
label="Name"
value={name}
onChange={this.handleInputChange('name')}
required
fullWidth
disabled={loading}
placeholder="Ihr Name"
/>
<TextField
label="E-Mail"
type="email"
value={email}
onChange={this.handleInputChange('email')}
required
fullWidth
disabled={loading}
placeholder="ihre.email@example.com"
helperText="Ihre E-Mail wird nicht veröffentlicht"
/>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography variant="body2" sx={{ fontWeight: 500 }}>
Bewertung *
</Typography>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Rating
name="article-rating"
value={rating}
onChange={this.handleRatingChange}
size="large"
disabled={loading}
emptyIcon={<StarIcon style={{ opacity: 0.55 }} fontSize="inherit" />}
/>
<Typography variant="body2" color="text.secondary">
{rating > 0 ? `${rating} von 5 Sternen` : 'Bitte bewerten'}
</Typography>
</Box>
</Box>
<TextField
label="Ihre Bewertung (optional)"
value={review}
onChange={this.handleInputChange('review')}
fullWidth
multiline
rows={4}
disabled={loading}
placeholder="Beschreiben Sie Ihre Erfahrungen mit diesem Artikel..."
/>
<PhotoUpload
ref={this.photoUploadRef}
onChange={this.handlePhotosChange}
disabled={loading}
maxFiles={5}
label="Fotos zur Bewertung anhängen (optional)"
/>
<Button
type="submit"
variant="contained"
disabled={loading || !name || !email || rating === 0}
sx={{
mt: 2,
py: 1.5,
fontSize: '1rem',
fontWeight: 600
}}
>
{loading ? (
<>
<CircularProgress size={20} sx={{ mr: 1 }} />
Wird gesendet...
</>
) : (
'Bewertung abgeben'
)}
</Button>
</Box>
</Paper>
);
}
}
export default withI18n()(ArticleRatingForm);