AI_Agent_Final / web /src /components /ProfileEditor.tsx
SarahXia0405's picture
Upload 73 files
0ef5c60 verified
import React, { useState, useRef } from 'react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Textarea } from './ui/textarea';
import { Dialog, DialogContent, DialogTitle } from './ui/dialog';
import type { User as UserType } from '../App';
import { toast } from 'sonner';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from './ui/select';
interface ProfileEditorProps {
user: UserType;
onSave: (user: UserType) => void;
onClose: () => void;
}
export function ProfileEditor({ user, onSave, onClose }: ProfileEditorProps) {
const [name, setName] = useState(user.name);
const [email, setEmail] = useState(user.email);
const [studentId, setStudentId] = useState('S12345678');
const [department, setDepartment] = useState('Computer Science');
const [year, setYear] = useState('3rd Year');
const [major, setMajor] = useState('Artificial Intelligence');
const [bio, setBio] = useState('Passionate about AI and machine learning');
const [photoPreview, setPhotoPreview] = useState<string | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const handleSave = () => {
if (name.trim() && email.trim()) {
onSave({ name: name.trim(), email: email.trim() });
toast.success('Profile updated successfully!');
onClose();
} else {
toast.error('Please fill in all required fields');
}
};
const handlePhotoSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
// Validate file type
if (!file.type.startsWith('image/')) {
toast.error('Please select an image file');
return;
}
// Validate file size (2MB)
if (file.size > 2 * 1024 * 1024) {
toast.error('File size must be less than 2MB');
return;
}
// Create preview
const reader = new FileReader();
reader.onload = (e) => {
setPhotoPreview(e.target?.result as string);
toast.success('Photo updated successfully!');
};
reader.readAsDataURL(file);
}
};
const handleChangePhotoClick = () => {
fileInputRef.current?.click();
};
return (
<Dialog open onOpenChange={(open) => { if (!open) onClose(); }}>
<DialogContent
className="sm:max-w-[800px] p-0 gap-0 max-h-[90vh] overflow-hidden"
style={{ zIndex: 1001, maxWidth: '800px', width: '800px' }}
overlayClassName="!top-16 !left-0 !right-0 !bottom-0 !z-[99]"
overlayStyle={{
top: '64px',
left: 0,
right: 0,
bottom: 0,
zIndex: 99,
position: 'fixed'
}}
>
<div className="flex flex-col max-h-[90vh]">
{/* Header */}
<div className="p-4 flex items-center justify-between flex-shrink-0">
<DialogTitle className="text-xl font-medium">Edit Profile</DialogTitle>
</div>
{/* Content */}
<div className="p-6 space-y-6 overflow-y-auto flex-1">
{/* Profile Picture */}
<div className="flex items-center gap-4">
<div className="w-20 h-20 rounded-full bg-gradient-to-br from-red-500 to-orange-500 flex items-center justify-center text-white text-2xl overflow-hidden">
{photoPreview ? (
<img src={photoPreview} alt="Profile" className="w-full h-full object-cover" />
) : (
name.charAt(0).toUpperCase()
)}
</div>
<div>
<input
ref={fileInputRef}
type="file"
accept="image/jpeg,image/png,image/gif,image/webp"
onChange={handlePhotoSelect}
className="hidden"
/>
<Button
variant="outline"
size="sm"
onClick={handleChangePhotoClick}
>
Change Photo
</Button>
<p className="text-xs text-muted-foreground mt-1">
JPG, PNG or GIF. Max size 2MB
</p>
</div>
</div>
{/* Basic Information */}
<div className="space-y-4">
<h3 className="text-sm font-medium">Basic Information</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="edit-name">Full Name *</Label>
<Input
id="edit-name"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter your full name"
/>
</div>
<div className="space-y-2">
<Label htmlFor="edit-email">Email *</Label>
<Input
id="edit-email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
/>
</div>
<div className="space-y-2">
<Label htmlFor="edit-student-id">Student ID</Label>
<Input
id="edit-student-id"
value={studentId}
onChange={(e) => setStudentId(e.target.value)}
placeholder="Enter your student ID"
/>
</div>
<div className="space-y-2">
<Label htmlFor="edit-department">Department</Label>
<Input
id="edit-department"
value={department}
onChange={(e) => setDepartment(e.target.value)}
placeholder="Enter your department"
/>
</div>
</div>
</div>
{/* Academic Background */}
<div className="space-y-4">
<h3 className="text-sm font-medium">Academic Background</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="edit-year">Year Level</Label>
<Select value={year} onValueChange={setYear}>
<SelectTrigger id="edit-year">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="1st Year">1st Year</SelectItem>
<SelectItem value="2nd Year">2nd Year</SelectItem>
<SelectItem value="3rd Year">3rd Year</SelectItem>
<SelectItem value="4th Year">4th Year</SelectItem>
<SelectItem value="Graduate">Graduate</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="edit-major">Major</Label>
<Input
id="edit-major"
value={major}
onChange={(e) => setMajor(e.target.value)}
placeholder="Enter your major"
/>
</div>
</div>
</div>
{/* Bio */}
<div className="space-y-2">
<Label htmlFor="edit-bio">Bio</Label>
<Textarea
id="edit-bio"
value={bio}
onChange={(e) => setBio(e.target.value)}
placeholder="Tell us about yourself..."
className="min-h-[100px] resize-none"
/>
<p className="text-xs text-muted-foreground">
Brief description for your profile. Max 200 characters.
</p>
</div>
{/* Learning Preferences */}
<div className="space-y-4">
<h3 className="text-sm font-medium">Learning Preferences</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="edit-learning-style">Preferred Learning Style</Label>
<Select defaultValue="visual">
<SelectTrigger id="edit-learning-style">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="visual">Visual</SelectItem>
<SelectItem value="auditory">Auditory</SelectItem>
<SelectItem value="reading">Reading/Writing</SelectItem>
<SelectItem value="kinesthetic">Kinesthetic</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="edit-pace">Learning Pace</Label>
<Select defaultValue="moderate">
<SelectTrigger id="edit-pace">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="slow">Slow & Steady</SelectItem>
<SelectItem value="moderate">Moderate</SelectItem>
<SelectItem value="fast">Fast-paced</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div>
</div>
{/* Footer */}
<div className="border-t border-border p-4 flex justify-end gap-2 flex-shrink-0">
<Button variant="outline" onClick={onClose}>
Cancel
</Button>
<Button onClick={handleSave}>
Save Changes
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}