tahamajs/IE / Projects /front /src /components /collections /CreateCollectionModal.tsx
tahamajs's picture
download
raw
5.05 kB
import { useState } from "react";
import { X, Loader2 } from "lucide-react";
import api from "@/lib/api";
import { toast } from "react-toastify";
interface Props {
isOpen: boolean;
onClose: () => void;
onSuccess?: () => void;
}
export function CreateCollectionModal({ isOpen, onClose, onSuccess }: Props) {
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [isPublic, setIsPublic] = useState(false);
const [loading, setLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!name.trim()) {
toast.warning("Please enter a collection name");
return;
}
setLoading(true);
try {
const response = await api.post("/collections", {
name: name.trim(),
description: description.trim() || undefined,
isPublic: isPublic
});
if (response.data) {
toast.success("Collection created successfully!");
setName("");
setDescription("");
setIsPublic(false);
onSuccess?.();
onClose();
}
} catch (err: any) {
console.error("Create collection error:", err);
const errorMsg = err.response?.data?.error || "Failed to create collection";
toast.error(errorMsg);
} finally {
setLoading(false);
}
};
if (!isOpen) return null;
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4">
<div className="relative w-full max-w-md rounded-2xl bg-white dark:bg-gray-800 shadow-2xl">
{/* Header */}
<div className="flex items-center justify-between border-b border-gray-200 dark:border-gray-700 p-5">
<h2 className="text-xl font-bold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">
Create New Collection
</h2>
<button
onClick={onClose}
className="p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition"
>
<X className="w-5 h-5 text-gray-500" />
</button>
</div>
{/* Form */}
<form onSubmit={handleSubmit} className="p-5 space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Collection Name *
</label>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="e.g., Machine Learning Papers"
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary dark:bg-gray-700 transition"
required
disabled={loading}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Description
</label>
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="Brief description of this collection"
rows={3}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary dark:bg-gray-700 transition resize-none"
disabled={loading}
/>
</div>
<div className="flex items-center gap-2">
<input
type="checkbox"
id="isPublic"
checked={isPublic}
onChange={(e) => setIsPublic(e.target.checked)}
className="w-4 h-4 text-primary rounded border-gray-300 focus:ring-primary"
disabled={loading}
/>
<label htmlFor="isPublic" className="text-sm text-gray-700 dark:text-gray-300">
Make this collection public
</label>
</div>
{/* Buttons */}
<div className="flex gap-3 pt-2">
<button
type="button"
onClick={onClose}
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 transition"
disabled={loading}
>
Cancel
</button>
<button
type="submit"
disabled={loading}
className="flex-1 px-4 py-2 bg-gradient-to-r from-primary to-secondary text-white rounded-lg font-medium hover:shadow-lg transition disabled:opacity-50 flex items-center justify-center gap-2"
>
{loading ? (
<>
<Loader2 className="w-4 h-4 animate-spin" />
Creating...
</>
) : (
"Create Collection"
)}
</button>
</div>
</form>
</div>
</div>
);
}

Xet Storage Details

Size:
5.05 kB
·
Xet hash:
0fde1c376b77616be76c7c658520264bca4401c795c1dcc993f21e90b46c2882

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