Convert backends to Firebase and combine projects
This commit is contained in:
142
RIT-EVENT-MANAGEMENT--main/components/CreateDomainView.tsx
Normal file
142
RIT-EVENT-MANAGEMENT--main/components/CreateDomainView.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
import React, { useState } from 'react';
|
||||
import { supabase, uploadImageToSupabase } from '../supabase';
|
||||
|
||||
interface CreateDomainViewProps {
|
||||
onShowToast: (msg: string, type: 'success' | 'delete') => void;
|
||||
onBack: () => void;
|
||||
}
|
||||
|
||||
const CreateDomainView: React.FC<CreateDomainViewProps> = ({ onShowToast, onBack }) => {
|
||||
const [formData, setFormData] = useState({
|
||||
name: '',
|
||||
description: '',
|
||||
category: 'TECHNICAL',
|
||||
});
|
||||
const [imageFile, setImageFile] = useState<File | null>(null);
|
||||
const [imagePreview, setImagePreview] = useState<string | null>(null);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (file) {
|
||||
if (file.size > 2 * 1024 * 1024) {
|
||||
alert("Image must be less than 2MB");
|
||||
return;
|
||||
}
|
||||
setImageFile(file);
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
setImagePreview(reader.result as string);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!imagePreview) {
|
||||
alert("Please upload a cover image for the domain.");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsSubmitting(true);
|
||||
try {
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
if (!user) throw new Error("Authentication required");
|
||||
|
||||
const imagePath = `domain_covers/${Date.now()}_${formData.name.replace(/\s+/g, '_')}`;
|
||||
const imageUrl = await uploadImageToSupabase(imagePreview, imagePath, 'domains');
|
||||
|
||||
const { error } = await supabase.from('domains').insert({
|
||||
name: formData.name,
|
||||
description: formData.description,
|
||||
category: formData.category,
|
||||
image: imageUrl,
|
||||
status: formData.category === 'CENTRE-ACTIVITY' ? 'APPROVED' : 'PENDING',
|
||||
created_by: user.id
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
onShowToast("Domain verification requested successfully!", "success");
|
||||
onBack();
|
||||
} catch (error: any) {
|
||||
console.error("Domain Request Error:", error);
|
||||
alert(`Request failed: ${error.message}`);
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-4xl mx-auto bg-white rounded-[3rem] p-8 md:p-12 shadow-[0_20px_50px_rgba(0,0,0,0.05)] border border-slate-100">
|
||||
<div className="flex items-center justify-between mb-10">
|
||||
<div>
|
||||
<h2 className="text-4xl font-black text-slate-900 uppercase tracking-tighter">Propose Domain</h2>
|
||||
<p className="text-slate-400 font-bold uppercase tracking-widest text-[10px] mt-1">Submit a new domain for verification</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onBack}
|
||||
className="w-12 h-12 bg-slate-50 text-slate-400 rounded-full flex items-center justify-center hover:bg-slate-100 hover:text-slate-600 transition-all border border-slate-200"
|
||||
>
|
||||
<i className="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest mb-3 ml-2">Domain Name *</label>
|
||||
<input required name="name" placeholder="e.g. Artificial Intelligence" className="w-full bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.name} onChange={handleInputChange} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest mb-3 ml-2">Category *</label>
|
||||
<select required name="category" className="w-full bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.category} onChange={handleInputChange}>
|
||||
<option value="TECHNICAL">Technical</option>
|
||||
<option value="NON-TECHNICAL">Non-Technical</option>
|
||||
<option value="WORKSHOP">Workshop</option>
|
||||
<option value="CENTRE-ACTIVITY">Centre Activity</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest mb-3 ml-2">Description</label>
|
||||
<textarea name="description" placeholder="Brief description of the domain..." rows={4} className="w-full bg-slate-50 border-none rounded-3xl px-6 py-5 text-xs font-medium outline-none focus:ring-2 focus:ring-[#004a99] transition-all resize-none" value={formData.description} onChange={handleInputChange}></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest mb-3 ml-2">Cover Image *</label>
|
||||
<div className="relative w-full h-64 bg-slate-50 border-2 border-dashed border-slate-200 rounded-[2rem] overflow-hidden group hover:border-[#004a99] transition-colors cursor-pointer flex flex-col items-center justify-center">
|
||||
<input type="file" accept="image/*" onChange={handleImageChange} className="absolute inset-0 w-full h-full opacity-0 cursor-pointer z-10" required />
|
||||
{imagePreview ? (
|
||||
<img src={imagePreview} alt="Preview" className="w-full h-full object-cover" />
|
||||
) : (
|
||||
<div className="text-center p-6">
|
||||
<div className="w-16 h-16 bg-white rounded-full flex items-center justify-center mx-auto mb-4 shadow-sm text-slate-300 group-hover:text-[#004a99] transition-colors">
|
||||
<i className="fas fa-image text-xl"></i>
|
||||
</div>
|
||||
<span className="block text-xs font-black text-slate-500 uppercase tracking-widest">Upload Cover</span>
|
||||
<span className="block text-[10px] font-medium text-slate-400 mt-2">Max. 2MB (16:9 Recommended)</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" disabled={isSubmitting} className="w-full py-5 bg-orange-500 text-white rounded-2xl font-black uppercase text-xs tracking-[0.2em] hover:bg-orange-600 transition-all shadow-xl shadow-orange-500/20 active:scale-95 disabled:opacity-70 disabled:cursor-not-allowed">
|
||||
{isSubmitting ? 'Submitting Request...' : 'Submit Domain for Verification'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateDomainView;
|
||||
Reference in New Issue
Block a user