Refactor: Implement desktop layout modernization

This commit is contained in:
gpt-engineer-app[bot]
2025-10-14 20:16:24 +00:00
parent 2eec20f653
commit b8f2889b1d
6 changed files with 387 additions and 302 deletions

View File

@@ -244,7 +244,7 @@ export function AccountProfileTab() {
const isDeactivated = profile?.deactivated || false;
return (
<div className="space-y-8">
<div className="space-y-6">
{/* Deletion Status Banner */}
{deletionRequest && (
<DeletionStatusBanner
@@ -253,26 +253,93 @@ export function AccountProfileTab() {
/>
)}
{/* Profile Picture */}
<div className="space-y-4">
<h3 className="text-lg font-medium">Profile Picture</h3>
<PhotoUpload
variant="avatar"
maxFiles={1}
maxSizeMB={1}
existingPhotos={avatarUrl ? [avatarUrl] : []}
onUploadComplete={handleAvatarUpload}
currentImageId={avatarImageId}
onError={(error) => {
handleError(new Error(error), { action: 'Upload avatar' });
}}
/>
{/* Profile Picture + Account Info Grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Profile Picture */}
<Card>
<CardHeader>
<CardTitle>Profile Picture</CardTitle>
<CardDescription>Upload your profile picture</CardDescription>
</CardHeader>
<CardContent>
<PhotoUpload
variant="avatar"
maxFiles={1}
maxSizeMB={1}
existingPhotos={avatarUrl ? [avatarUrl] : []}
onUploadComplete={handleAvatarUpload}
currentImageId={avatarImageId}
onError={(error) => {
handleError(new Error(error), { action: 'Upload avatar' });
}}
/>
</CardContent>
</Card>
{/* Account Information */}
<Card>
<CardHeader>
<CardTitle>Account Information</CardTitle>
<CardDescription>View your account details</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{pendingEmail && (
<EmailChangeStatus
currentEmail={user?.email || ''}
pendingEmail={pendingEmail}
onCancel={() => setShowCancelEmailDialog(true)}
/>
)}
<div className="p-4 bg-muted/50 rounded-lg space-y-4">
<div className="flex items-center justify-between">
<div className="flex-1">
<p className="text-sm font-medium">Email Address</p>
<div className="flex items-center gap-2 mt-1">
<p className="text-sm text-muted-foreground">{user?.email}</p>
{pendingEmail ? (
<Badge variant="secondary" className="bg-blue-500/10 text-blue-500 border-blue-500/20 text-xs">
Change Pending
</Badge>
) : user?.email_confirmed_at ? (
<Badge variant="secondary" className="text-xs">Verified</Badge>
) : (
<Badge variant="outline" className="text-xs">Pending Verification</Badge>
)}
</div>
</div>
<Button
variant="outline"
size="sm"
onClick={() => setShowEmailDialog(true)}
disabled={!!pendingEmail}
>
<Mail className="w-4 h-4 mr-2" />
Change
</Button>
</div>
<Separator />
<div>
<p className="text-sm font-medium">Account Created</p>
<p className="text-sm text-muted-foreground mt-1">
{profile?.created_at ? new Date(profile.created_at).toLocaleDateString() : 'N/A'}
</p>
</div>
</div>
</CardContent>
</Card>
</div>
<Separator />
{/* Profile Information */}
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<Card>
<CardHeader>
<CardTitle>Profile Information</CardTitle>
<CardDescription>Update your public profile details</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<h3 className="text-lg font-medium">Profile Information</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
@@ -393,86 +460,57 @@ export function AccountProfileTab() {
)}
</div>
<div className="flex items-center justify-between">
<Button
type="submit"
disabled={
loading ||
isDeactivated ||
isSaving ||
usernameValidation.isChecking ||
usernameValidation.isAvailable === false
}
>
{loading || isSaving ? 'Saving...' : 'Save Changes'}
</Button>
{lastSaved && !loading && !isSaving && (
<span className="text-sm text-muted-foreground">
Last saved {formatDistanceToNow(lastSaved, { addSuffix: true })}
</span>
)}
</div>
{isDeactivated && (
<p className="text-sm text-muted-foreground">
Your account is deactivated. Profile editing is disabled.
</p>
)}
</form>
<Separator />
{/* Account Information */}
<div className="space-y-4">
<h3 className="text-lg font-medium">Account Information</h3>
<div className="space-y-4">
{pendingEmail && (
<EmailChangeStatus
currentEmail={user?.email || ''}
pendingEmail={pendingEmail}
onCancel={() => setShowCancelEmailDialog(true)}
/>
)}
<div className="p-4 bg-muted/50 rounded-lg space-y-4">
<div className="flex items-center justify-between">
<div className="flex-1">
<p className="text-sm font-medium">Email Address</p>
<div className="flex items-center gap-2 mt-1">
<p className="text-sm text-muted-foreground">{user?.email}</p>
{pendingEmail ? (
<Badge variant="secondary" className="bg-blue-500/10 text-blue-500 border-blue-500/20 text-xs">
Change Pending
</Badge>
) : user?.email_confirmed_at ? (
<Badge variant="secondary" className="text-xs">Verified</Badge>
) : (
<Badge variant="outline" className="text-xs">Pending Verification</Badge>
)}
</div>
</div>
<Button
variant="outline"
size="sm"
onClick={() => setShowEmailDialog(true)}
disabled={!!pendingEmail}
type="submit"
disabled={
loading ||
isDeactivated ||
isSaving ||
usernameValidation.isChecking ||
usernameValidation.isAvailable === false
}
>
<Mail className="w-4 h-4 mr-2" />
Change Email
{loading || isSaving ? 'Saving...' : 'Save Changes'}
</Button>
{lastSaved && !loading && !isSaving && (
<span className="text-sm text-muted-foreground">
Last saved {formatDistanceToNow(lastSaved, { addSuffix: true })}
</span>
)}
</div>
<Separator />
<div>
<p className="text-sm font-medium">Account Created</p>
<p className="text-sm text-muted-foreground mt-1">
{profile?.created_at ? new Date(profile.created_at).toLocaleDateString() : 'N/A'}
{isDeactivated && (
<p className="text-sm text-muted-foreground">
Your account is deactivated. Profile editing is disabled.
</p>
</div>
</div>
</div>
</div>
)}
</form>
</CardContent>
</Card>
{/* Danger Zone */}
<Card className="border-destructive/50">
<CardHeader>
<CardTitle className="text-destructive">Danger Zone</CardTitle>
<CardDescription>Irreversible account actions</CardDescription>
</CardHeader>
<CardContent>
<Button
variant="destructive"
onClick={() => setShowDeletionDialog(true)}
disabled={!!deletionRequest}
>
<Trash2 className="w-4 h-4 mr-2" />
Delete Account
</Button>
{deletionRequest && (
<p className="text-sm text-muted-foreground mt-2">
Account deletion already in progress
</p>
)}
</CardContent>
</Card>
{/* Email Change Dialog */}
{user && (
@@ -486,29 +524,6 @@ export function AccountProfileTab() {
{/* Cancel Email Change Dialog */}
<AlertDialog open={showCancelEmailDialog} onOpenChange={setShowCancelEmailDialog}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Cancel Email Change?</AlertDialogTitle>
<AlertDialogDescription>
This will cancel your pending email change to <strong>{pendingEmail}</strong>.
Your email will remain as <strong>{user?.email}</strong>.
You can start a new email change request at any time.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel disabled={cancellingEmail}>Keep Change</AlertDialogCancel>
<AlertDialogAction
onClick={handleCancelEmailChange}
disabled={cancellingEmail}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{cancellingEmail ? 'Cancelling...' : 'Yes, Cancel Change'}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<Separator />
{/* Danger Zone */}
<Card className="border-destructive">
@@ -538,6 +553,28 @@ export function AccountProfileTab() {
</CardContent>
</Card>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Cancel Email Change?</AlertDialogTitle>
<AlertDialogDescription>
This will cancel your pending email change to <strong>{pendingEmail}</strong>.
Your email will remain as <strong>{user?.email}</strong>.
You can start a new email change request at any time.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel disabled={cancellingEmail}>Keep Change</AlertDialogCancel>
<AlertDialogAction
onClick={handleCancelEmailChange}
disabled={cancellingEmail}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{cancellingEmail ? 'Cancelling...' : 'Yes, Cancel Change'}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
{/* Account Deletion Dialog */}
<AccountDeletionDialog
open={showDeletionDialog}