Untitled
unknown
plain_text
8 months ago
4.5 kB
6
Indexable
// components/download-all.tsx
import { useState } from "react";
import { Download } from "lucide-react";
import { motion } from "framer-motion";
import { useParams } from "next/navigation";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
export function DownloadAll() {
const [isDownloading, setIsDownloading] = useState(false);
const [progress, setProgress] = useState(0);
const [startTime, setStartTime] = useState<number | null>(null);
const params = useParams();
const clientId = params.clientId as string;
const formatTimeRemaining = (seconds: number) => {
if (seconds < 60) return `${Math.round(seconds)} Sekunden`;
const minutes = Math.ceil(seconds / 60);
return `${minutes} ${minutes === 1 ? 'Minute' : 'Minuten'}`;
};
const handleDownloadAll = async () => {
try {
setIsDownloading(true);
setProgress(0);
setStartTime(Date.now());
toast.info("Download wird vorbereitet", {
description: "Die Bilder werden zusammengefasst. Dies kann einige Minuten dauern."
});
const progressInterval = setInterval(() => {
setProgress(prev => {
const newProgress = prev + 0.5;
return newProgress < 90 ? newProgress : prev;
});
}, 1000);
const response = await fetch(`/api/download/${clientId}`, {
method: 'GET',
cache: 'no-store'
});
if (!response.ok) {
throw new Error(`Download fehlgeschlagen (${response.status})`);
}
if (!response.body) {
throw new Error('Keine Daten erhalten');
}
clearInterval(progressInterval);
setProgress(95);
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = `${clientId}-fotos.zip`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
setProgress(100);
toast.success("Download erfolgreich", {
description: "Die Datei wird jetzt heruntergeladen."
});
setTimeout(() => {
setIsDownloading(false);
setProgress(0);
setStartTime(null);
}, 3000);
} catch (error) {
console.error("Download failed:", error);
setIsDownloading(false);
setProgress(0);
setStartTime(null);
toast.error("Download fehlgeschlagen", {
description: error.message || "Bitte versuchen Sie es später erneut."
});
}
};
const getStatusMessage = () => {
if (!startTime) return "Wird vorbereitet...";
const elapsedSeconds = (Date.now() - startTime) / 1000;
const estimatedTotalSeconds = (elapsedSeconds / progress) * 100;
const remainingSeconds = Math.max(0, estimatedTotalSeconds - elapsedSeconds);
if (progress >= 100) return "Download abgeschlossen!";
if (progress >= 95) return "Fast fertig...";
return `Datei wird vorbereitet... (ca. ${formatTimeRemaining(remainingSeconds)} verbleibend)`;
};
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="mb-12 rounded-lg border bg-card p-4 text-card-foreground shadow-sm"
>
<div className="flex flex-col items-center gap-4 text-center sm:flex-row sm:justify-between sm:text-left">
<div>
<h2 className="text-lg font-semibold">Alle Fotos herunterladen</h2>
<p className="text-sm text-muted-foreground">
Erhalten Sie alle Fotos in Originalqualität in einer einzigen Datei
</p>
</div>
<div className="flex flex-col gap-2 min-w-[200px]">
{isDownloading ? (
<>
<Progress value={progress} className="w-full" />
<p className="text-sm text-muted-foreground text-center">
{getStatusMessage()}
</p>
</>
) : (
<Button size="lg" onClick={handleDownloadAll}>
<Download className="mr-2 h-4 w-4" />
Alle herunterladen
</Button>
)}
</div>
</div>
</motion.div>
);
}
export default DownloadAll;Editor is loading...
Leave a Comment