tahamajs/IE / Projects /front /src /components /async /OfflineCollaborationQueue.tsx
tahamajs's picture
download
raw
2.95 kB
// src/components/async/OfflineCollaborationQueue.tsx
import { useOfflineSync } from "@/hooks/useOfflineSync";
import {
CloudUpload,
CloudOff,
Clock,
CheckCircle2,
AlertTriangle,
RefreshCw,
Trash2,
} from "lucide-react";
export function OfflineCollaborationQueue() {
const { status, queue, queueCount, processQueue } = useOfflineSync();
// Don't render anything if queue is empty and we are fully synced
if (queueCount === 0 && status === "synced") return null;
// Status icon and text
const getStatusIcon = () => {
switch (status) {
case "syncing":
return <CloudUpload className="w-4 h-4 text-blue-500 animate-pulse" />;
case "pending":
return <Clock className="w-4 h-4 text-amber-500" />;
default:
return <CloudOff className="w-4 h-4 text-red-500" />;
}
};
const getStatusText = () => {
switch (status) {
case "syncing":
return "Syncing...";
case "pending":
return "Pending Sync";
default:
return `${queueCount} queued`;
}
};
return (
<div className="glass rounded-2xl border border-white/20 dark:border-white/10 p-4 bg-white/80 dark:bg-gray-900/80 backdrop-blur-md shadow-lg">
{/* Header */}
<div className="flex items-center justify-between mb-3">
<h4 className="text-sm font-semibold flex items-center gap-2">
{getStatusIcon()}
<span>{getStatusText()}</span>
</h4>
<button
onClick={processQueue}
disabled={status === "syncing"}
className="btn btn-ghost btn-xs gap-1 flex items-center text-xs px-2 py-1 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 disabled:opacity-50"
>
<RefreshCw className={`w-3 h-3 ${status === "syncing" ? "animate-spin" : ""}`} />
Sync Now
</button>
</div>
{/* Queue items (up to 5) */}
<div className="space-y-0">
{queue.slice(0, 5).map((item) => (
<div
key={item.id}
className="flex items-center gap-2 text-xs py-1.5 border-b border-white/10 dark:border-gray-700 last:border-0"
>
{item.status === "failed" ? (
<AlertTriangle className="w-3.5 h-3.5 text-red-400" />
) : item.status === "processing" ? (
<RefreshCw className="w-3.5 h-3.5 text-blue-400 animate-spin" />
) : (
<Clock className="w-3.5 h-3.5 text-amber-400" />
)}
<span className="flex-1 truncate capitalize">{item.type}</span>
<span className="text-gray-400 text-[10px]">
{new Date(item.createdAt).toLocaleTimeString()}
</span>
</div>
))}
</div>
{/* More items indicator */}
{queue.length > 5 && (
<p className="text-[10px] text-gray-400 text-center mt-2">
+{queue.length - 5} more items
</p>
)}
</div>
);
}

Xet Storage Details

Size:
2.95 kB
·
Xet hash:
ec187b043214a8e4249bee7d1b6aa03c7e3509e7aef87702cee2d20e0ce301cd

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.