Add new Radix UI components and associated dependencies in package-lock.json
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
||||
import { Shield, Zap, AlertCircle, Loader2, CheckCircle, Fingerprint, Key } from 'lucide-react';
|
||||
|
||||
interface RegisterProps {
|
||||
onRegisterSuccess: (token: string, masterKey: Uint8Array, communityId: string, username: string) => void;
|
||||
onRegisterSuccess: (token: string, masterKey: Uint8Array, communityId: string, username: string, userId: string, role?: string) => void;
|
||||
onSwitchToLogin: () => void;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,8 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
const data = await res.json();
|
||||
const masterKeyBytes = new TextEncoder().encode(data.masterKey);
|
||||
|
||||
onRegisterSuccess(data.token, masterKeyBytes, data.communityId, data.username);
|
||||
localStorage.setItem('auth_token', data.token);
|
||||
onRegisterSuccess(data.token, masterKeyBytes, data.communityId, data.username, data.userId, data.role);
|
||||
} catch (err) {
|
||||
setError((err as Error).message);
|
||||
} finally {
|
||||
@@ -140,7 +141,8 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
const data = await finishRes.json();
|
||||
const masterKeyBytes = new TextEncoder().encode(data.masterKey || 'this-is-a-32-byte-master-key-xyz');
|
||||
|
||||
onRegisterSuccess(data.token, masterKeyBytes, data.communityId, username);
|
||||
localStorage.setItem('auth_token', data.token);
|
||||
onRegisterSuccess(data.token, masterKeyBytes, data.communityId, username, data.userId ?? 'user-passkey', data.role);
|
||||
} catch (err) {
|
||||
setError((err as Error).message);
|
||||
} finally {
|
||||
@@ -169,21 +171,21 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#0a0b10] flex items-center justify-center p-6 relative overflow-hidden">
|
||||
<div className="min-h-screen bg-background flex items-center justify-center p-6 relative overflow-hidden">
|
||||
{/* Background Effects */}
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
<div className="absolute top-1/4 -left-48 w-96 h-96 bg-indigo-600/10 rounded-full blur-3xl animate-pulse"></div>
|
||||
<div className="absolute bottom-1/4 -right-48 w-96 h-96 bg-purple-600/10 rounded-full blur-3xl animate-pulse" style={{ animationDelay: '1s' }}></div>
|
||||
<div className="absolute top-1/4 -left-48 w-96 h-96 bg-primary/10 rounded-full blur-3xl animate-pulse"></div>
|
||||
<div className="absolute bottom-1/4 -right-48 w-96 h-96 bg-indigo-500/10 rounded-full blur-3xl animate-pulse" style={{ animationDelay: '1s' }}></div>
|
||||
</div>
|
||||
|
||||
<div className="max-w-md w-full relative z-10">
|
||||
{/* Logo */}
|
||||
<div className="text-center mb-10">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 bg-indigo-600 rounded-2xl mb-4 shadow-2xl shadow-indigo-600/50">
|
||||
<Zap className="w-8 h-8 text-white fill-white" />
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 bg-primary rounded-2xl mb-4 shadow-2xl shadow-primary/50">
|
||||
<Zap className="w-8 h-8 text-primary-foreground fill-primary-foreground" />
|
||||
</div>
|
||||
<h1 className="text-3xl font-black text-white tracking-tight mb-2">Create Account</h1>
|
||||
<p className="text-slate-500 text-sm font-medium">Zero-Knowledge Gaming Infrastructure</p>
|
||||
<h1 className="text-3xl font-black text-foreground tracking-tight mb-2 uppercase italic">ArmaCloud</h1>
|
||||
<p className="text-muted-foreground text-sm font-medium uppercase tracking-widest">Create your account</p>
|
||||
</div>
|
||||
|
||||
{/* Auth Method Selector */}
|
||||
@@ -192,8 +194,8 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
onClick={() => setAuthMethod('password')}
|
||||
className={`flex-1 px-4 py-3 rounded-xl font-bold text-sm transition-all ${
|
||||
authMethod === 'password'
|
||||
? 'bg-indigo-600 text-white shadow-lg shadow-indigo-600/20'
|
||||
: 'bg-slate-800 text-slate-400 hover:bg-slate-700'
|
||||
? 'bg-primary text-primary-foreground shadow-lg shadow-primary/20'
|
||||
: 'bg-muted text-muted-foreground hover:bg-accent hover:text-accent-foreground'
|
||||
}`}
|
||||
>
|
||||
<Key className="w-4 h-4 inline mr-2" />
|
||||
@@ -203,8 +205,8 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
onClick={() => setAuthMethod('passkey')}
|
||||
className={`flex-1 px-4 py-3 rounded-xl font-bold text-sm transition-all ${
|
||||
authMethod === 'passkey'
|
||||
? 'bg-indigo-600 text-white shadow-lg shadow-indigo-600/20'
|
||||
: 'bg-slate-800 text-slate-400 hover:bg-slate-700'
|
||||
? 'bg-primary text-primary-foreground shadow-lg shadow-primary/20'
|
||||
: 'bg-muted text-muted-foreground hover:bg-accent hover:text-accent-foreground'
|
||||
}`}
|
||||
>
|
||||
<Fingerprint className="w-4 h-4 inline mr-2" />
|
||||
@@ -213,30 +215,30 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
</div>
|
||||
|
||||
{/* Register Card */}
|
||||
<div className="bg-[#0c0d14] border border-slate-800 rounded-3xl p-8 shadow-2xl">
|
||||
<div className="bg-card/50 backdrop-blur-xl border border-border/50 rounded-3xl p-8 shadow-2xl">
|
||||
<form onSubmit={authMethod === 'password' ? handlePasswordRegister : handlePasskeyRegister} className="space-y-5">
|
||||
{/* Common Fields */}
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-slate-300 mb-2">Username</label>
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] font-black uppercase tracking-widest text-muted-foreground/60">Username</label>
|
||||
<input
|
||||
type="text"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
placeholder="your_username"
|
||||
className="w-full px-4 py-3 bg-slate-900 border border-slate-700 rounded-xl text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all"
|
||||
placeholder="Operator ID"
|
||||
className="w-full px-4 py-3 bg-background border border-border/50 rounded-xl text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
|
||||
required
|
||||
disabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-slate-300 mb-2">Email (Optional)</label>
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] font-black uppercase tracking-widest text-muted-foreground/60">Email (optional)</label>
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="you@example.com"
|
||||
className="w-full px-4 py-3 bg-slate-900 border border-slate-700 rounded-xl text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all"
|
||||
placeholder="operator@backbone.net"
|
||||
className="w-full px-4 py-3 bg-background border border-border/50 rounded-xl text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
|
||||
disabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
@@ -244,8 +246,8 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
{/* Password-specific fields */}
|
||||
{authMethod === 'password' && (
|
||||
<>
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-slate-300 mb-2">Password</label>
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] font-black uppercase tracking-widest text-muted-foreground/60">Password</label>
|
||||
<input
|
||||
type="password"
|
||||
value={password}
|
||||
@@ -253,36 +255,36 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
setPassword(e.target.value);
|
||||
checkPasswordStrength(e.target.value);
|
||||
}}
|
||||
placeholder="Min. 12 characters"
|
||||
className="w-full px-4 py-3 bg-slate-900 border border-slate-700 rounded-xl text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all"
|
||||
placeholder="••••••••••••"
|
||||
className="w-full px-4 py-3 bg-background border border-border/50 rounded-xl text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
|
||||
required
|
||||
disabled={isLoading}
|
||||
/>
|
||||
{passwordStrength && password.length > 0 && (
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<div className="flex-1 h-2 bg-slate-800 rounded-full overflow-hidden">
|
||||
<div className="flex-1 h-1.5 bg-muted rounded-full overflow-hidden">
|
||||
<div
|
||||
className={`h-full transition-all ${
|
||||
passwordStrength.score <= 1 ? 'bg-red-500' :
|
||||
passwordStrength.score === 2 ? 'bg-yellow-500' :
|
||||
passwordStrength.score === 3 ? 'bg-blue-500' : 'bg-green-500'
|
||||
passwordStrength.score <= 1 ? 'bg-destructive' :
|
||||
passwordStrength.score === 2 ? 'bg-amber-500' :
|
||||
passwordStrength.score === 3 ? 'bg-blue-500' : 'bg-emerald-500'
|
||||
}`}
|
||||
style={{ width: `${(passwordStrength.score / 5) * 100}%` }}
|
||||
></div>
|
||||
</div>
|
||||
<span className="text-xs text-slate-400">{passwordStrength.message}</span>
|
||||
<span className="text-[9px] font-black uppercase text-muted-foreground/60">{passwordStrength.message}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-slate-300 mb-2">Confirm Password</label>
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] font-black uppercase tracking-widest text-muted-foreground/60">Confirm Password</label>
|
||||
<input
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
placeholder="Repeat password"
|
||||
className="w-full px-4 py-3 bg-slate-900 border border-slate-700 rounded-xl text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all"
|
||||
placeholder="••••••••••••"
|
||||
className="w-full px-4 py-3 bg-background border border-border/50 rounded-xl text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
|
||||
required
|
||||
disabled={isLoading}
|
||||
/>
|
||||
@@ -290,24 +292,24 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
</>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-slate-300 mb-2">Community Name (Optional)</label>
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] font-black uppercase tracking-widest text-muted-foreground/60">Community Name (optional)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={communityName}
|
||||
onChange={(e) => setCommunityName(e.target.value)}
|
||||
placeholder="e.g., Elite Tactical Gaming"
|
||||
className="w-full px-4 py-3 bg-slate-900 border border-slate-700 rounded-xl text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all"
|
||||
placeholder="e.g., Tactical Command Alpha"
|
||||
className="w-full px-4 py-3 bg-background border border-border/50 rounded-xl text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
|
||||
disabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="p-4 bg-red-500/10 border border-red-500/20 rounded-xl flex items-start space-x-3">
|
||||
<AlertCircle className="w-5 h-5 text-red-400 flex-shrink-0 mt-0.5" />
|
||||
<div className="p-4 bg-destructive/10 border border-destructive/20 rounded-xl flex items-start space-x-3">
|
||||
<AlertCircle className="w-5 h-5 text-destructive flex-shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<h3 className="text-sm font-bold text-red-200">Registration Failed</h3>
|
||||
<p className="text-xs text-red-400/80 mt-1">{error}</p>
|
||||
<h3 className="text-sm font-bold text-destructive">Registration failed</h3>
|
||||
<p className="text-xs text-destructive/80 mt-1">{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -315,35 +317,35 @@ export const Register: React.FC<RegisterProps> = ({ onRegisterSuccess, onSwitchT
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading || !username.trim() || (authMethod === 'password' && (!password || !confirmPassword))}
|
||||
className="w-full bg-indigo-600 hover:bg-indigo-500 disabled:bg-slate-800 disabled:text-slate-600 text-white font-bold py-4 rounded-xl transition-all duration-200 shadow-lg shadow-indigo-600/20 active:scale-95 flex items-center justify-center space-x-2"
|
||||
className="w-full bg-primary hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground text-primary-foreground font-black uppercase tracking-widest py-4 rounded-xl transition-all duration-200 shadow-lg shadow-primary/20 active:scale-95 flex items-center justify-center space-x-2"
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="w-5 h-5 animate-spin" />
|
||||
<span>Creating Account...</span>
|
||||
<span>Processing...</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{authMethod === 'password' ? <Shield className="w-5 h-5" /> : <Fingerprint className="w-5 h-5" />}
|
||||
<span>Create Account with {authMethod === 'password' ? 'Password' : 'Passkey'}</span>
|
||||
<span>Create Account</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Security Info */}
|
||||
<div className="mt-6 pt-6 border-t border-slate-800">
|
||||
<div className="flex items-start space-x-3 text-xs text-slate-500">
|
||||
<CheckCircle className="w-4 h-4 text-green-500 flex-shrink-0 mt-0.5" />
|
||||
<p>Your master encryption key is generated client-side and never leaves your device unencrypted.</p>
|
||||
<div className="mt-6 pt-6 border-t border-border/50">
|
||||
<div className="flex items-start space-x-3 text-[10px] font-medium text-muted-foreground/60">
|
||||
<CheckCircle className="w-4 h-4 text-emerald-500 flex-shrink-0 mt-0.5" />
|
||||
<p>Your data is end-to-end encrypted. Encryption keys never leave your device.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Switch to Login */}
|
||||
<p className="text-center text-sm text-slate-500 mt-6">
|
||||
<p className="text-center text-sm text-muted-foreground mt-6">
|
||||
Already have an account?{' '}
|
||||
<button onClick={onSwitchToLogin} className="text-indigo-400 hover:text-indigo-300 font-bold transition-colors">
|
||||
<button onClick={onSwitchToLogin} className="text-primary hover:text-primary/80 font-black transition-colors uppercase tracking-widest">
|
||||
Sign in
|
||||
</button>
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user