mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 06:11:11 -05:00
Refactor: Implement desktop layout modernization
This commit is contained in:
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user