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