264 lines
7.4 KiB
JavaScript
264 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);
|
|
|
|
if (this.props.socket) {
|
|
this.props.socket.emit('article_rating_submit', ratingData);
|
|
|
|
// Set up response handler
|
|
this.props.socket.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);
|