refactor(frontend): Improve consent and success UX
- Move ConsentCheckboxes below DescriptionInput for better flow - Replace success dialog with inline success display - Add copy-to-clipboard button for group ID - Show detailed next steps and GDPR contact info inline
This commit is contained in:
parent
76aa028686
commit
5bc2b0d222
|
|
@ -12,7 +12,6 @@ import DescriptionInput from '../ComponentUtils/MultiUpload/DescriptionInput';
|
||||||
import UploadProgress from '../ComponentUtils/MultiUpload/UploadProgress';
|
import UploadProgress from '../ComponentUtils/MultiUpload/UploadProgress';
|
||||||
import Loading from '../ComponentUtils/LoadingAnimation/Loading';
|
import Loading from '../ComponentUtils/LoadingAnimation/Loading';
|
||||||
import ConsentCheckboxes from '../ComponentUtils/MultiUpload/ConsentCheckboxes';
|
import ConsentCheckboxes from '../ComponentUtils/MultiUpload/ConsentCheckboxes';
|
||||||
import UploadSuccessDialog from '../ComponentUtils/MultiUpload/UploadSuccessDialog';
|
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { uploadImageBatch } from '../../Utils/batchUpload';
|
import { uploadImageBatch } from '../../Utils/batchUpload';
|
||||||
|
|
@ -42,7 +41,6 @@ function MultiUploadPage() {
|
||||||
const [uploadResult, setUploadResult] = useState(null);
|
const [uploadResult, setUploadResult] = useState(null);
|
||||||
const [isEditMode, setIsEditMode] = useState(false);
|
const [isEditMode, setIsEditMode] = useState(false);
|
||||||
const [imageDescriptions, setImageDescriptions] = useState({});
|
const [imageDescriptions, setImageDescriptions] = useState({});
|
||||||
const [showSuccessDialog, setShowSuccessDialog] = useState(false);
|
|
||||||
|
|
||||||
// Cleanup object URLs when component unmounts
|
// Cleanup object URLs when component unmounts
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -189,11 +187,10 @@ function MultiUploadPage() {
|
||||||
clearInterval(progressInterval);
|
clearInterval(progressInterval);
|
||||||
setUploadProgress(100);
|
setUploadProgress(100);
|
||||||
|
|
||||||
// Show success dialog
|
// Show success content
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setUploadComplete(true);
|
setUploadComplete(true);
|
||||||
setUploadResult(result);
|
setUploadResult(result);
|
||||||
setShowSuccessDialog(true);
|
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -247,17 +244,17 @@ function MultiUploadPage() {
|
||||||
|
|
||||||
{selectedImages.length > 0 && (
|
{selectedImages.length > 0 && (
|
||||||
<>
|
<>
|
||||||
|
<DescriptionInput
|
||||||
|
metadata={metadata}
|
||||||
|
onMetadataChange={setMetadata}
|
||||||
|
/>
|
||||||
|
|
||||||
<ConsentCheckboxes
|
<ConsentCheckboxes
|
||||||
consents={consents}
|
consents={consents}
|
||||||
onConsentChange={setConsents}
|
onConsentChange={setConsents}
|
||||||
disabled={uploading}
|
disabled={uploading}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DescriptionInput
|
|
||||||
metadata={metadata}
|
|
||||||
onMetadataChange={setMetadata}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Box sx={{ display: 'flex', gap: '15px', justifyContent: 'center', mt: '20px', flexWrap: 'wrap' }}>
|
<Box sx={{ display: 'flex', gap: '15px', justifyContent: 'center', mt: '20px', flexWrap: 'wrap' }}>
|
||||||
<Button
|
<Button
|
||||||
sx={{
|
sx={{
|
||||||
|
|
@ -317,31 +314,172 @@ function MultiUploadPage() {
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ textAlign: 'center', padding: '40px 0' }}>
|
<div style={{ textAlign: 'center', padding: '40px 0' }}>
|
||||||
<Loading />
|
{!uploadComplete ? (
|
||||||
<UploadProgress
|
<>
|
||||||
progress={uploadProgress}
|
<Loading />
|
||||||
totalFiles={selectedImages.length}
|
<UploadProgress
|
||||||
isUploading={uploading}
|
progress={uploadProgress}
|
||||||
/>
|
totalFiles={selectedImages.length}
|
||||||
|
isUploading={uploading}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Box sx={{
|
||||||
|
mt: 4,
|
||||||
|
p: 4,
|
||||||
|
borderRadius: '16px',
|
||||||
|
background: 'linear-gradient(135deg, #4CAF50 0%, #45a049 100%)',
|
||||||
|
color: 'white',
|
||||||
|
boxShadow: '0 8px 32px rgba(76, 175, 80, 0.4)',
|
||||||
|
animation: 'slideIn 0.5s ease-out',
|
||||||
|
'@keyframes slideIn': {
|
||||||
|
from: {
|
||||||
|
opacity: 0,
|
||||||
|
transform: 'translateY(-20px)'
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
opacity: 1,
|
||||||
|
transform: 'translateY(0)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
{/* Success Icon & Title */}
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 2, mb: 2 }}>
|
||||||
|
<Box sx={{
|
||||||
|
bgcolor: 'white',
|
||||||
|
borderRadius: '50%',
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
boxShadow: '0 4px 12px rgba(0,0,0,0.2)'
|
||||||
|
}}>
|
||||||
|
<Typography sx={{ fontSize: '32px' }}>✅</Typography>
|
||||||
|
</Box>
|
||||||
|
<Typography sx={{ fontSize: '32px', fontWeight: 'bold' }}>
|
||||||
|
Upload erfolgreich!
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Upload Count */}
|
||||||
|
<Typography sx={{ fontSize: '18px', mb: 3 }}>
|
||||||
|
<strong>{uploadResult?.imageCount || 0}</strong> {uploadResult?.imageCount === 1 ? 'Bild wurde' : 'Bilder wurden'} erfolgreich hochgeladen
|
||||||
|
und {uploadResult?.imageCount === 1 ? 'wird' : 'werden'} nach der Prüfung durch das Hobbyhimmel-Team angezeigt.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{/* Group ID Box */}
|
||||||
|
<Box sx={{
|
||||||
|
bgcolor: 'rgba(255,255,255,0.2)',
|
||||||
|
borderRadius: '12px',
|
||||||
|
p: 3,
|
||||||
|
mb: 3,
|
||||||
|
border: '2px solid rgba(255,255,255,0.3)'
|
||||||
|
}}>
|
||||||
|
<Typography sx={{ fontSize: '14px', mb: 1, opacity: 0.9 }}>
|
||||||
|
Ihre Referenz-Nummer:
|
||||||
|
</Typography>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 2 }}>
|
||||||
|
<Typography sx={{
|
||||||
|
fontSize: '24px',
|
||||||
|
fontFamily: 'monospace',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
letterSpacing: '2px'
|
||||||
|
}}>
|
||||||
|
{uploadResult?.groupId}
|
||||||
|
</Typography>
|
||||||
|
<Button
|
||||||
|
sx={{
|
||||||
|
bgcolor: 'white',
|
||||||
|
color: '#4CAF50',
|
||||||
|
minWidth: 'auto',
|
||||||
|
px: 2,
|
||||||
|
py: 1,
|
||||||
|
'&:hover': {
|
||||||
|
bgcolor: '#f0f0f0'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(uploadResult?.groupId || '');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
📋 Kopieren
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Typography sx={{ fontSize: '12px', mt: 1, opacity: 0.8 }}>
|
||||||
|
Notieren Sie sich diese Nummer für spätere Anfragen
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Next Steps */}
|
||||||
|
<Box sx={{
|
||||||
|
bgcolor: 'rgba(255,255,255,0.15)',
|
||||||
|
borderRadius: '8px',
|
||||||
|
p: 2,
|
||||||
|
mb: 3,
|
||||||
|
textAlign: 'left'
|
||||||
|
}}>
|
||||||
|
<Typography sx={{ fontSize: '16px', fontWeight: 600, mb: 1.5 }}>
|
||||||
|
Was passiert jetzt?
|
||||||
|
</Typography>
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
|
||||||
|
<Box sx={{ display: 'flex', gap: 1 }}>
|
||||||
|
<Typography sx={{ fontSize: '14px' }}>•</Typography>
|
||||||
|
<Typography sx={{ fontSize: '14px' }}>
|
||||||
|
Ihre Bilder werden vom Team geprüft
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ display: 'flex', gap: 1 }}>
|
||||||
|
<Typography sx={{ fontSize: '14px' }}>•</Typography>
|
||||||
|
<Typography sx={{ fontSize: '14px' }}>
|
||||||
|
Nach Freigabe erscheinen sie auf dem Werkstatt-Monitor
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ display: 'flex', gap: 1 }}>
|
||||||
|
<Typography sx={{ fontSize: '14px' }}>•</Typography>
|
||||||
|
<Typography sx={{ fontSize: '14px' }}>
|
||||||
|
Bei gewählter Social Media Einwilligung werden sie entsprechend veröffentlicht
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* GDPR Contact */}
|
||||||
|
<Typography sx={{ fontSize: '12px', opacity: 0.9, mb: 3 }}>
|
||||||
|
<strong>Fragen oder Widerruf?</strong> Kontaktieren Sie uns mit Ihrer Referenz-Nummer unter: <strong>it@hobbyhimmel.de</strong>
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{/* Action Button */}
|
||||||
|
<Button
|
||||||
|
sx={{
|
||||||
|
bgcolor: 'white',
|
||||||
|
color: '#4CAF50',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: '16px',
|
||||||
|
px: 5,
|
||||||
|
py: 1.5,
|
||||||
|
borderRadius: '25px',
|
||||||
|
textTransform: 'none',
|
||||||
|
boxShadow: '0 4px 12px rgba(0,0,0,0.2)',
|
||||||
|
'&:hover': {
|
||||||
|
bgcolor: '#f0f0f0',
|
||||||
|
transform: 'scale(1.05)',
|
||||||
|
boxShadow: '0 6px 16px rgba(0,0,0,0.3)'
|
||||||
|
},
|
||||||
|
transition: 'all 0.3s ease'
|
||||||
|
}}
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
>
|
||||||
|
👍 Weitere Bilder hochladen
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
{/* Success Dialog */}
|
|
||||||
{showSuccessDialog && uploadResult && (
|
|
||||||
<UploadSuccessDialog
|
|
||||||
open={showSuccessDialog}
|
|
||||||
onClose={() => {
|
|
||||||
setShowSuccessDialog(false);
|
|
||||||
window.location.reload();
|
|
||||||
}}
|
|
||||||
groupId={uploadResult.groupId}
|
|
||||||
uploadCount={uploadResult.imageCount}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="footerContainer">
|
<div className="footerContainer">
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user