Seed: dashboard template (24 files)
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
import { useState } from "react";
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
Upload, Camera, Save, Trash2, AlertTriangle, Mail, Phone, User, Check
|
||||
} from "lucide-react";
|
||||
import Sidebar from "@/components/Sidebar";
|
||||
import Header from "@/components/Header";
|
||||
|
||||
export default function ProfilePage() {
|
||||
const [name, setName] = useState("Sarah Mitchell");
|
||||
const [email, setEmail] = useState("sarah@metricflow.com");
|
||||
const [phone, setPhone] = useState("+1 (555) 234-5678");
|
||||
const [bio, setBio] = useState("Product lead with a passion for data-driven decisions. Building better analytics tools for modern teams.");
|
||||
const [profileSaved, setProfileSaved] = useState(false);
|
||||
|
||||
const handleProfileSave = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setProfileSaved(true);
|
||||
toast.success("Profile updated!");
|
||||
setTimeout(() => setProfileSaved(false), 3000);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen bg-slate-50">
|
||||
<Sidebar activePath="/profile" />
|
||||
<div className="flex-1 lg:ml-64">
|
||||
<Header />
|
||||
<main className="p-6 space-y-8 max-w-3xl">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-900 animate-fade-up">My Profile</h1>
|
||||
<p className="text-sm text-slate-500 mt-1">Manage your personal information and preferences</p>
|
||||
</div>
|
||||
|
||||
{/* ── Avatar Section ── */}
|
||||
<Card className="border-0 shadow-sm">
|
||||
<CardContent className="p-6">
|
||||
<div className="flex flex-col sm:flex-row items-center gap-6">
|
||||
<div className="relative">
|
||||
<Avatar className="h-24 w-24">
|
||||
<AvatarFallback className="bg-sky-100 text-sky-700 text-2xl font-bold">SM</AvatarFallback>
|
||||
</Avatar>
|
||||
<button className="absolute bottom-0 right-0 h-8 w-8 rounded-full bg-sky-600 text-white flex items-center justify-center shadow-lg hover:bg-sky-700 transition-colors">
|
||||
<Camera className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="text-center sm:text-left">
|
||||
<h2 className="text-lg font-semibold text-slate-900">{name}</h2>
|
||||
<p className="text-sm text-slate-500">{email}</p>
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<Badge className="bg-red-100 text-red-700 border-0">Admin</Badge>
|
||||
<Badge className="bg-emerald-100 text-emerald-700 border-0">Active</Badge>
|
||||
</div>
|
||||
</div>
|
||||
<div className="sm:ml-auto">
|
||||
<Button variant="outline" size="sm" className="active:scale-[0.98]">
|
||||
<Upload className="mr-2 h-4 w-4" /> Upload Photo
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* ── Profile Form ── */}
|
||||
<Card className="border-0 shadow-sm">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Personal Information</CardTitle>
|
||||
<CardDescription>Update your personal details below</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form onSubmit={handleProfileSave} className="space-y-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="name" className="flex items-center gap-2">
|
||||
<User className="h-4 w-4 text-slate-400" /> Full Name
|
||||
</Label>
|
||||
<Input id="name" value={name} onChange={(e) => setName(e.target.value)} className="bg-slate-50" required />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="email" className="flex items-center gap-2">
|
||||
<Mail className="h-4 w-4 text-slate-400" /> Email Address
|
||||
</Label>
|
||||
<Input id="email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} className="bg-slate-50" required />
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="phone" className="flex items-center gap-2">
|
||||
<Phone className="h-4 w-4 text-slate-400" /> Phone Number
|
||||
</Label>
|
||||
<Input id="phone" value={phone} onChange={(e) => setPhone(e.target.value)} className="bg-slate-50" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="bio">Bio</Label>
|
||||
<Textarea
|
||||
id="bio"
|
||||
value={bio}
|
||||
onChange={(e) => setBio(e.target.value)}
|
||||
className="bg-slate-50 min-h-[100px]"
|
||||
placeholder="Tell us a little about yourself..."
|
||||
/>
|
||||
</div>
|
||||
{profileSaved && (
|
||||
<div className="flex items-center gap-2 text-sm font-medium text-emerald-600 bg-emerald-50 px-4 py-2.5 rounded-lg">
|
||||
<Check className="h-4 w-4" /> Profile updated!
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit" className="bg-sky-600 hover:bg-sky-700 text-white active:scale-[0.98] transition-all">
|
||||
<Save className="mr-2 h-4 w-4" /> Save Changes
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* ── Danger Zone ── */}
|
||||
<Card className="border-0 shadow-sm border-red-100">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg text-red-600 flex items-center gap-2">
|
||||
<AlertTriangle className="h-5 w-5" /> Danger Zone
|
||||
</CardTitle>
|
||||
<CardDescription>Irreversible actions that affect your account</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between p-4 rounded-lg bg-red-50 border border-red-100">
|
||||
<div>
|
||||
<p className="font-medium text-red-900">Delete Account</p>
|
||||
<p className="text-sm text-red-600 mt-0.5">Permanently delete your account and all associated data</p>
|
||||
</div>
|
||||
<Button variant="destructive" size="sm" className="mt-3 sm:mt-0 active:scale-[0.98]">
|
||||
<Trash2 className="mr-2 h-4 w-4" /> Delete Account
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user