|
1 | 1 | import { useState, useEffect, useRef } from 'react' |
2 | | -import { FolderPlus, Loader2, HardDrive, WifiOff, LogIn, Check, Database, Link, User, Truck, Mail, Phone, ArrowLeft, Eye, EyeOff, RotateCw, X } from 'lucide-react' |
| 2 | +import { FolderPlus, Loader2, HardDrive, WifiOff, LogIn, Check, Database, Link, User, Truck, Mail, Phone, ArrowLeft, Eye, EyeOff, RotateCw, X, AlertTriangle, LogOut } from 'lucide-react' |
3 | 3 | import { usePDMStore, ConnectedVault } from '../stores/pdmStore' |
4 | 4 | import { signInWithGoogle, signInWithEmail, signUpWithEmail, signInWithPhone, verifyPhoneOTP, isSupabaseConfigured, supabase, getAccessibleVaults } from '../lib/supabase' |
5 | 5 | import { getInitials } from '../types/pdm' |
@@ -1395,6 +1395,115 @@ export function WelcomeScreen({ onOpenRecentVault }: WelcomeScreenProps) { |
1395 | 1395 | ) |
1396 | 1396 | } |
1397 | 1397 |
|
| 1398 | + // ============================================ |
| 1399 | + // NO ORGANIZATION SCREEN (signed in but not linked to any org) |
| 1400 | + // ============================================ |
| 1401 | + if (user && !organization && !isOfflineMode) { |
| 1402 | + const handleSignOutAndRetry = async () => { |
| 1403 | + uiLog('info', 'User signing out to retry with different account') |
| 1404 | + const { signOut: supabaseSignOut } = await import('../lib/supabase') |
| 1405 | + await supabaseSignOut() |
| 1406 | + } |
| 1407 | + |
| 1408 | + return ( |
| 1409 | + <div className="flex-1 flex items-center justify-center bg-plm-bg overflow-auto"> |
| 1410 | + <div className="max-w-md w-full p-8"> |
| 1411 | + {/* Logo and Title */} |
| 1412 | + <div className="text-center mb-8"> |
| 1413 | + <div className="flex justify-center items-center gap-3 mb-4"> |
| 1414 | + <svg width="48" height="48" viewBox="0 0 24 24" fill="none" className="text-plm-warning"> |
| 1415 | + <path |
| 1416 | + d="M12 2L2 7L12 12L22 7L12 2Z" |
| 1417 | + stroke="currentColor" |
| 1418 | + strokeWidth="2" |
| 1419 | + strokeLinecap="round" |
| 1420 | + strokeLinejoin="round" |
| 1421 | + /> |
| 1422 | + <path |
| 1423 | + d="M2 17L12 22L22 17" |
| 1424 | + stroke="currentColor" |
| 1425 | + strokeWidth="2" |
| 1426 | + strokeLinecap="round" |
| 1427 | + strokeLinejoin="round" |
| 1428 | + /> |
| 1429 | + <path |
| 1430 | + d="M2 12L12 17L22 12" |
| 1431 | + stroke="currentColor" |
| 1432 | + strokeWidth="2" |
| 1433 | + strokeLinecap="round" |
| 1434 | + strokeLinejoin="round" |
| 1435 | + /> |
| 1436 | + </svg> |
| 1437 | + <h1 className="text-2xl font-bold text-plm-fg">{t('welcome.title')}</h1> |
| 1438 | + </div> |
| 1439 | + </div> |
| 1440 | + |
| 1441 | + {/* User Info */} |
| 1442 | + <div className="text-center mb-6"> |
| 1443 | + <div className="inline-flex items-center gap-2 px-4 py-2 bg-plm-bg-light border border-plm-border rounded-full mb-4"> |
| 1444 | + {user.avatar_url ? ( |
| 1445 | + <img src={user.avatar_url} alt="" className="w-5 h-5 rounded-full" /> |
| 1446 | + ) : ( |
| 1447 | + <div className="w-5 h-5 rounded-full bg-plm-accent flex items-center justify-center text-[10px] text-white font-semibold"> |
| 1448 | + {getInitials(user.full_name || user.email)} |
| 1449 | + </div> |
| 1450 | + )} |
| 1451 | + <span className="text-sm text-plm-fg-dim"> |
| 1452 | + {user.full_name || user.email} |
| 1453 | + </span> |
| 1454 | + </div> |
| 1455 | + </div> |
| 1456 | + |
| 1457 | + {/* Warning Card */} |
| 1458 | + <div className="bg-plm-warning/10 border border-plm-warning/30 rounded-xl p-6 mb-6"> |
| 1459 | + <div className="flex gap-4"> |
| 1460 | + <div className="flex-shrink-0"> |
| 1461 | + <AlertTriangle className="w-6 h-6 text-plm-warning" /> |
| 1462 | + </div> |
| 1463 | + <div> |
| 1464 | + <h3 className="text-plm-fg font-semibold mb-2">{t('welcome.noOrgTitle', 'No Organization Found')}</h3> |
| 1465 | + <p className="text-sm text-plm-fg-muted"> |
| 1466 | + {t('welcome.noOrgDesc', 'Your account isn\'t linked to any organization. This can happen if:')} |
| 1467 | + </p> |
| 1468 | + <ul className="text-sm text-plm-fg-muted mt-2 space-y-1 list-disc list-inside"> |
| 1469 | + <li>{t('welcome.noOrgReason1', 'You haven\'t been invited yet')}</li> |
| 1470 | + <li>{t('welcome.noOrgReason2', 'You signed in with a different email than the invite')}</li> |
| 1471 | + <li>{t('welcome.noOrgReason3', 'The invite hasn\'t been processed yet')}</li> |
| 1472 | + </ul> |
| 1473 | + </div> |
| 1474 | + </div> |
| 1475 | + </div> |
| 1476 | + |
| 1477 | + {/* Actions */} |
| 1478 | + <div className="space-y-3"> |
| 1479 | + <button |
| 1480 | + onClick={handleSignOutAndRetry} |
| 1481 | + className="w-full py-3 bg-plm-accent hover:bg-plm-accent-hover text-white font-medium rounded-lg transition-colors flex items-center justify-center gap-2" |
| 1482 | + > |
| 1483 | + <LogOut size={18} /> |
| 1484 | + {t('welcome.signOutAndRetry', 'Sign Out & Try Different Account')} |
| 1485 | + </button> |
| 1486 | + |
| 1487 | + <button |
| 1488 | + onClick={handleOfflineMode} |
| 1489 | + className="w-full py-3 bg-plm-bg-light border border-plm-border hover:bg-plm-bg-light/80 text-plm-fg font-medium rounded-lg transition-colors flex items-center justify-center gap-2" |
| 1490 | + > |
| 1491 | + <WifiOff size={18} /> |
| 1492 | + {t('welcome.workOffline')} |
| 1493 | + </button> |
| 1494 | + </div> |
| 1495 | + |
| 1496 | + {/* Help Text */} |
| 1497 | + <div className="mt-6 p-4 bg-plm-bg-light border border-plm-border rounded-lg"> |
| 1498 | + <p className="text-xs text-plm-fg-muted text-center"> |
| 1499 | + {t('welcome.noOrgHelp', 'If you were invited, please check your email for the invite link and make sure to sign in with the same email address that received the invitation. Contact your administrator if you need help.')} |
| 1500 | + </p> |
| 1501 | + </div> |
| 1502 | + </div> |
| 1503 | + </div> |
| 1504 | + ) |
| 1505 | + } |
| 1506 | + |
1398 | 1507 | // ============================================ |
1399 | 1508 | // VAULT CONNECTION SCREEN (shown when authenticated or offline) |
1400 | 1509 | // ============================================ |
|
0 commit comments