Signup: require a display name (changeable later), remove skip
Per request, a display name is now mandatory when signing up:
- Removed the "Skip for now" button from the profile step — the only forward
path is Save, which is disabled until a non-empty name is entered.
- Marked the field required (*), added helper copy ("Required — how you'll show
up across SkateSpots. Change it anytime."), and a hint under the button.
- finishSignup guards against an empty/whitespace name (defense-in-depth for
keyboard/Enter), trims the name before publishing kind 0.
- Reworded the step copy: name required, bio + avatar still optional.
Only affects the primary nsec signup dialog (also the endpoint the mnemonic
flow feeds into); the mnemonic dialog has no name step.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
39afc00b6e
commit
3833625bde
1 changed files with 32 additions and 24 deletions
|
|
@ -152,14 +152,26 @@ const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onComplete
|
||||||
};
|
};
|
||||||
|
|
||||||
const finishSignup = async (skipProfile = false) => {
|
const finishSignup = async (skipProfile = false) => {
|
||||||
|
// A display name is mandatory (changeable later). Guard here too so the step
|
||||||
|
// can't be completed without one, even via keyboard/Enter.
|
||||||
|
const trimmedName = profileData.name.trim();
|
||||||
|
if (!skipProfile && !trimmedName) {
|
||||||
|
toast({
|
||||||
|
title: 'Display name required',
|
||||||
|
description: 'Pick a display name so other skaters know who you are. You can change it anytime.',
|
||||||
|
variant: 'destructive',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Mark signup completion time for fallback welcome modal
|
// Mark signup completion time for fallback welcome modal
|
||||||
localStorage.setItem('signup_completed', Date.now().toString());
|
localStorage.setItem('signup_completed', Date.now().toString());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Publish profile if user provided information
|
// Publish profile if user provided information
|
||||||
if (!skipProfile && (profileData.name || profileData.about || profileData.picture)) {
|
if (!skipProfile && (trimmedName || profileData.about || profileData.picture)) {
|
||||||
const metadata: Record<string, string> = {};
|
const metadata: Record<string, string> = {};
|
||||||
if (profileData.name) metadata.name = profileData.name;
|
if (trimmedName) metadata.name = trimmedName;
|
||||||
if (profileData.about) metadata.about = profileData.about;
|
if (profileData.about) metadata.about = profileData.about;
|
||||||
if (profileData.picture) metadata.picture = profileData.picture;
|
if (profileData.picture) metadata.picture = profileData.picture;
|
||||||
|
|
||||||
|
|
@ -365,11 +377,11 @@ const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onComplete
|
||||||
|
|
||||||
<div className='relative z-10 space-y-2'>
|
<div className='relative z-10 space-y-2'>
|
||||||
<p className='text-base font-semibold'>
|
<p className='text-base font-semibold'>
|
||||||
You're in! 🛹 Add a name so skaters know who you are
|
You're in! 🛹 Pick a display name so skaters know who you are
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className='text-sm text-muted-foreground'>
|
<p className='text-sm text-muted-foreground'>
|
||||||
This is optional — you can skip it and fill it in later.
|
You can change it anytime later. Bio and avatar are optional.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -390,16 +402,22 @@ const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onComplete
|
||||||
<div className={`space-y-4 text-left ${isPublishing ? 'opacity-50 pointer-events-none' : ''}`}>
|
<div className={`space-y-4 text-left ${isPublishing ? 'opacity-50 pointer-events-none' : ''}`}>
|
||||||
<div className='space-y-2'>
|
<div className='space-y-2'>
|
||||||
<label htmlFor='profile-name' className='text-sm font-medium'>
|
<label htmlFor='profile-name' className='text-sm font-medium'>
|
||||||
Display Name
|
Display Name <span className='text-red-500'>*</span>
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
id='profile-name'
|
id='profile-name'
|
||||||
value={profileData.name}
|
value={profileData.name}
|
||||||
onChange={(e) => setProfileData(prev => ({ ...prev, name: e.target.value }))}
|
onChange={(e) => setProfileData(prev => ({ ...prev, name: e.target.value }))}
|
||||||
placeholder='Your name'
|
placeholder='e.g. Tony, gnarlyGrind, or your crew name'
|
||||||
className='rounded-lg'
|
className='rounded-lg'
|
||||||
|
maxLength={64}
|
||||||
|
required
|
||||||
|
aria-required='true'
|
||||||
disabled={isPublishing}
|
disabled={isPublishing}
|
||||||
/>
|
/>
|
||||||
|
<p className='text-xs text-muted-foreground'>
|
||||||
|
Required — how you'll show up across SkateSpots. Change it anytime.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='space-y-2'>
|
<div className='space-y-2'>
|
||||||
|
|
@ -456,12 +474,12 @@ const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onComplete
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Action buttons */}
|
{/* Action button — a display name is required to continue. */}
|
||||||
<div className='space-y-3'>
|
<div className='space-y-3'>
|
||||||
<Button
|
<Button
|
||||||
className='w-full rounded-full py-4 text-base font-semibold bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 transform transition-all duration-200 hover:scale-105 shadow-lg disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none'
|
className='w-full rounded-full py-4 text-base font-semibold bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 transform transition-all duration-200 hover:scale-105 shadow-lg disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none disabled:hover:scale-100'
|
||||||
onClick={() => finishSignup(false)}
|
onClick={() => finishSignup(false)}
|
||||||
disabled={isPublishing || isUploading}
|
disabled={isPublishing || isUploading || !profileData.name.trim()}
|
||||||
>
|
>
|
||||||
{isPublishing ? (
|
{isPublishing ? (
|
||||||
<>
|
<>
|
||||||
|
|
@ -476,21 +494,11 @@ const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onComplete
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
{!profileData.name.trim() && !isPublishing && (
|
||||||
variant='outline'
|
<p className='text-center text-xs text-muted-foreground'>
|
||||||
className='w-full rounded-full py-3 disabled:opacity-50 disabled:cursor-not-allowed'
|
Add a display name to continue.
|
||||||
onClick={() => finishSignup(true)}
|
</p>
|
||||||
disabled={isPublishing || isUploading}
|
)}
|
||||||
>
|
|
||||||
{isPublishing ? (
|
|
||||||
<>
|
|
||||||
<div className='w-4 h-4 mr-2 border-2 border-current border-t-transparent rounded-full animate-spin' />
|
|
||||||
Setting up account...
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
'Skip for now'
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue