144 lines
4.3 KiB
JavaScript
144 lines
4.3 KiB
JavaScript
import { useCallback } from 'react';
|
||
import { useDropzone } from 'react-dropzone';
|
||
import {
|
||
Box,
|
||
Button,
|
||
Card,
|
||
CardActionArea,
|
||
CardContent,
|
||
CardMedia,
|
||
Grid,
|
||
Stack,
|
||
Typography,
|
||
} from '@mui/material';
|
||
import { useNavigate } from 'react-router-dom';
|
||
import { useAppStore } from '../store/useAppStore';
|
||
|
||
const dropzoneStyle = {
|
||
border: '2px dashed rgba(108, 155, 207, 0.7)',
|
||
borderRadius: 12,
|
||
padding: '32px',
|
||
textAlign: 'center',
|
||
backgroundColor: 'rgba(108, 155, 207, 0.08)',
|
||
cursor: 'pointer',
|
||
};
|
||
|
||
const UploadStep = () => {
|
||
const navigate = useNavigate();
|
||
const uploadedImages = useAppStore((state) => state.uploadedImages);
|
||
const setUploadedImages = useAppStore((state) => state.setUploadedImages);
|
||
const resetFromStep = useAppStore((state) => state.resetFromStep);
|
||
const coverImageId = useAppStore((state) => state.coverImageId);
|
||
const setCoverImageId = useAppStore((state) => state.setCoverImageId);
|
||
|
||
const onDrop = useCallback(
|
||
(acceptedFiles) => {
|
||
if (!acceptedFiles.length) return;
|
||
resetFromStep('upload');
|
||
const mapped = acceptedFiles.map((file, index) => ({
|
||
id: crypto.randomUUID(),
|
||
file,
|
||
previewUrl: URL.createObjectURL(file),
|
||
order: uploadedImages.length + index,
|
||
filename: file.name,
|
||
}));
|
||
setUploadedImages([...uploadedImages, ...mapped]);
|
||
},
|
||
[uploadedImages, resetFromStep, setUploadedImages],
|
||
);
|
||
|
||
const handleCoverToggle = (imageId) => {
|
||
const nextId = coverImageId === imageId ? null : imageId;
|
||
setCoverImageId(nextId);
|
||
};
|
||
|
||
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
||
onDrop,
|
||
accept: {
|
||
'image/png': ['.png'],
|
||
'image/jpeg': ['.jpg', '.jpeg'],
|
||
},
|
||
multiple: true,
|
||
});
|
||
|
||
return (
|
||
<Stack spacing={4}>
|
||
<Box {...getRootProps()} sx={dropzoneStyle}>
|
||
<input {...getInputProps()} />
|
||
<Typography variant="h5" gutterBottom>
|
||
Görselleri sürükleyip bırak veya tıkla
|
||
</Typography>
|
||
<Typography color="text.secondary" gutterBottom>
|
||
.png, .jpg, .jpeg formatlarında çoklu dosya yükleyebilirsin.
|
||
</Typography>
|
||
<Button variant="contained" color="primary">
|
||
Dosya seç
|
||
</Button>
|
||
{isDragActive && (
|
||
<Typography mt={2} fontWeight={600}>
|
||
Bırak ve yükleyelim!
|
||
</Typography>
|
||
)}
|
||
</Box>
|
||
|
||
<Box>
|
||
<Typography variant="h6" gutterBottom>
|
||
Yüklenen görseller ({uploadedImages.length})
|
||
</Typography>
|
||
{uploadedImages.length === 0 ? (
|
||
<Typography color="text.secondary">
|
||
Henüz görsel yüklenmedi.
|
||
</Typography>
|
||
) : (
|
||
<Grid container spacing={2}>
|
||
{uploadedImages.map((image) => (
|
||
<Grid item xs={12} sm={6} md={4} lg={3} key={image.id}>
|
||
<Card>
|
||
<CardActionArea>
|
||
<CardMedia
|
||
component="img"
|
||
height="160"
|
||
image={image.previewUrl}
|
||
alt={image.filename}
|
||
/>
|
||
<CardContent>
|
||
<Typography variant="body2" noWrap>
|
||
{image.filename}
|
||
</Typography>
|
||
<Button
|
||
variant={image.id === coverImageId ? 'contained' : 'outlined'}
|
||
size="small"
|
||
fullWidth
|
||
sx={{ mt: 1 }}
|
||
onClick={(event) => {
|
||
event.stopPropagation();
|
||
handleCoverToggle(image.id);
|
||
}}
|
||
>
|
||
{image.id === coverImageId ? 'Kapak seçildi' : 'Kapak olarak işaretle'}
|
||
</Button>
|
||
</CardContent>
|
||
</CardActionArea>
|
||
</Card>
|
||
</Grid>
|
||
))}
|
||
</Grid>
|
||
)}
|
||
</Box>
|
||
|
||
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} justifyContent="flex-end">
|
||
<Button
|
||
variant="contained"
|
||
color="primary"
|
||
disabled={!uploadedImages.length}
|
||
onClick={() => navigate('/crop')}
|
||
>
|
||
Devam et
|
||
</Button>
|
||
</Stack>
|
||
</Stack>
|
||
);
|
||
};
|
||
|
||
export default UploadStep;
|