Compare commits
	
		
			2 commits
		
	
	
		
			6422189f6c
			...
			03d3d272df
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 03d3d272df | |||
| 
							 | 
						aa8dad9809 | 
					 7 changed files with 924 additions and 73 deletions
				
			
		| 
						 | 
					@ -1,4 +1,3 @@
 | 
				
			||||||
/* login.css */
 | 
					 | 
				
			||||||
* {
 | 
					* {
 | 
				
			||||||
  margin: 0;
 | 
					  margin: 0;
 | 
				
			||||||
  padding: 0;
 | 
					  padding: 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										517
									
								
								src/assets/css/components/signup.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										517
									
								
								src/assets/css/components/signup.css
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,517 @@
 | 
				
			||||||
 | 
					* {
 | 
				
			||||||
 | 
					  margin: 0;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-page {
 | 
				
			||||||
 | 
					  min-height: 100vh;
 | 
				
			||||||
 | 
					  background: linear-gradient(135deg, #0c0c0c 0%, #1a1a2e 50%, #16213e 100%);
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-bg {
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  background: radial-gradient(circle at 20% 80%, rgba(0, 212, 255, 0.05) 0%, transparent 50%),
 | 
				
			||||||
 | 
					              radial-gradient(circle at 80% 20%, rgba(124, 58, 237, 0.05) 0%, transparent 50%);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.floating-elements {
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  pointer-events: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.floating-element {
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  width: 3px;
 | 
				
			||||||
 | 
					  height: 3px;
 | 
				
			||||||
 | 
					  background: linear-gradient(45deg, #00d4ff, #7c3aed);
 | 
				
			||||||
 | 
					  border-radius: 50%;
 | 
				
			||||||
 | 
					  animation: float 8s ease-in-out infinite;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@keyframes float {
 | 
				
			||||||
 | 
					  0%, 100% { 
 | 
				
			||||||
 | 
					    transform: translateY(0px) rotate(0deg); 
 | 
				
			||||||
 | 
					    opacity: 0.3; 
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  50% { 
 | 
				
			||||||
 | 
					    transform: translateY(-30px) rotate(180deg); 
 | 
				
			||||||
 | 
					    opacity: 0.8; 
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-container {
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  z-index: 2;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  max-width: 480px;
 | 
				
			||||||
 | 
					  padding: 2rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-card {
 | 
				
			||||||
 | 
					  background: rgba(255, 255, 255, 0.08);
 | 
				
			||||||
 | 
					  backdrop-filter: blur(20px);
 | 
				
			||||||
 | 
					  border: 1px solid rgba(255, 255, 255, 0.1);
 | 
				
			||||||
 | 
					  border-radius: 24px;
 | 
				
			||||||
 | 
					  padding: 3rem;
 | 
				
			||||||
 | 
					  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
 | 
				
			||||||
 | 
					  animation: slideInUp 0.8s ease-out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@keyframes slideInUp {
 | 
				
			||||||
 | 
					  from {
 | 
				
			||||||
 | 
					    opacity: 0;
 | 
				
			||||||
 | 
					    transform: translateY(50px);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  to {
 | 
				
			||||||
 | 
					    opacity: 1;
 | 
				
			||||||
 | 
					    transform: translateY(0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-header {
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					  margin-bottom: 2.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.logo {
 | 
				
			||||||
 | 
					  font-size: 2rem;
 | 
				
			||||||
 | 
					  font-weight: 800;
 | 
				
			||||||
 | 
					  color: #ffffff;
 | 
				
			||||||
 | 
					  margin-bottom: 1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.logo-accent {
 | 
				
			||||||
 | 
					  background: linear-gradient(45deg, #00d4ff, #7c3aed);
 | 
				
			||||||
 | 
					  background-clip: text;
 | 
				
			||||||
 | 
					  -webkit-background-clip: text;
 | 
				
			||||||
 | 
					  color: transparent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-title {
 | 
				
			||||||
 | 
					  font-size: 1.75rem;
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					  color: #ffffff;
 | 
				
			||||||
 | 
					  margin-bottom: 0.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-subtitle {
 | 
				
			||||||
 | 
					  color: #a0a0a0;
 | 
				
			||||||
 | 
					  font-size: 0.95rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-form {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  gap: 1.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-row {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  gap: 1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-group {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  gap: 0.5rem;
 | 
				
			||||||
 | 
					  margin-bottom: 1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-group.half-width {
 | 
				
			||||||
 | 
					  flex: 1;
 | 
				
			||||||
 | 
					  margin-bottom: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-label {
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					  color: #ffffff;
 | 
				
			||||||
 | 
					  font-size: 0.9rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.input-wrapper {
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.input-icon {
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  left: 1rem;
 | 
				
			||||||
 | 
					  top: 50%;
 | 
				
			||||||
 | 
					  transform: translateY(-50%);
 | 
				
			||||||
 | 
					  color: #888;
 | 
				
			||||||
 | 
					  font-size: 0.9rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-input {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  padding: 1rem 1rem 1rem 2.75rem;
 | 
				
			||||||
 | 
					  background: rgba(255, 255, 255, 0.05);
 | 
				
			||||||
 | 
					  border: 2px solid rgba(255, 255, 255, 0.1);
 | 
				
			||||||
 | 
					  border-radius: 12px;
 | 
				
			||||||
 | 
					  color: #ffffff;
 | 
				
			||||||
 | 
					  font-size: 1rem;
 | 
				
			||||||
 | 
					  transition: all 0.3s ease;
 | 
				
			||||||
 | 
					  backdrop-filter: blur(10px);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-input:focus {
 | 
				
			||||||
 | 
					  outline: none;
 | 
				
			||||||
 | 
					  border-color: #00d4ff;
 | 
				
			||||||
 | 
					  box-shadow: 0 0 20px rgba(0, 212, 255, 0.2);
 | 
				
			||||||
 | 
					  background: rgba(255, 255, 255, 0.08);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-input.error {
 | 
				
			||||||
 | 
					  border-color: #ff4757;
 | 
				
			||||||
 | 
					  box-shadow: 0 0 20px rgba(255, 71, 87, 0.2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-input::placeholder {
 | 
				
			||||||
 | 
					  color: #666;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.password-toggle {
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  right: 1rem;
 | 
				
			||||||
 | 
					  top: 50%;
 | 
				
			||||||
 | 
					  transform: translateY(-50%);
 | 
				
			||||||
 | 
					  background: none;
 | 
				
			||||||
 | 
					  border: none;
 | 
				
			||||||
 | 
					  color: #888;
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  padding: 0.25rem;
 | 
				
			||||||
 | 
					  transition: color 0.3s ease;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.password-toggle:hover {
 | 
				
			||||||
 | 
					  color: #00d4ff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.password-strength {
 | 
				
			||||||
 | 
					  margin-top: 0.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-bar {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  height: 4px;
 | 
				
			||||||
 | 
					  background-color: rgba(255, 255, 255, 0.1);
 | 
				
			||||||
 | 
					  border-radius: 2px;
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					  margin-bottom: 0.25rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-fill {
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  transition: width 0.3s ease, background-color 0.3s ease;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-fill.weak {
 | 
				
			||||||
 | 
					  background: linear-gradient(45deg, #ff4757, #ff6b7a);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-fill.fair {
 | 
				
			||||||
 | 
					  background: linear-gradient(45deg, #ffa502, #ffb347);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-fill.good {
 | 
				
			||||||
 | 
					  background: linear-gradient(45deg, #2ed573, #7bed9f);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-fill.strong {
 | 
				
			||||||
 | 
					  background: linear-gradient(45deg, #00d4ff, #7c3aed);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-text {
 | 
				
			||||||
 | 
					  font-size: 0.75rem;
 | 
				
			||||||
 | 
					  font-weight: 500;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-text.weak {
 | 
				
			||||||
 | 
					  color: #ff4757;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-text.fair {
 | 
				
			||||||
 | 
					  color: #ffa502;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-text.good {
 | 
				
			||||||
 | 
					  color: #2ed573;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.strength-text.strong {
 | 
				
			||||||
 | 
					  background: linear-gradient(45deg, #00d4ff, #7c3aed);
 | 
				
			||||||
 | 
					  background-clip: text;
 | 
				
			||||||
 | 
					  -webkit-background-clip: text;
 | 
				
			||||||
 | 
					  color: transparent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.password-mismatch {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  gap: 0.5rem;
 | 
				
			||||||
 | 
					  margin-top: 0.5rem;
 | 
				
			||||||
 | 
					  font-size: 0.75rem;
 | 
				
			||||||
 | 
					  color: #ff4757;
 | 
				
			||||||
 | 
					  animation: shake 0.5s ease-in-out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-options {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  gap: 1rem;
 | 
				
			||||||
 | 
					  margin-bottom: 0.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.checkbox-wrapper {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: flex-start;
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  gap: 0.75rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.checkbox-input {
 | 
				
			||||||
 | 
					  display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.checkbox-custom {
 | 
				
			||||||
 | 
					  width: 18px;
 | 
				
			||||||
 | 
					  height: 18px;
 | 
				
			||||||
 | 
					  border: 2px solid rgba(255, 255, 255, 0.3);
 | 
				
			||||||
 | 
					  border-radius: 4px;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  transition: all 0.3s ease;
 | 
				
			||||||
 | 
					  flex-shrink: 0;
 | 
				
			||||||
 | 
					  margin-top: 1px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.checkbox-input:checked + .checkbox-custom {
 | 
				
			||||||
 | 
					  background: linear-gradient(45deg, #00d4ff, #7c3aed);
 | 
				
			||||||
 | 
					  border-color: transparent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.checkbox-input:checked + .checkbox-custom::after {
 | 
				
			||||||
 | 
					  content: '✓';
 | 
				
			||||||
 | 
					  color: white;
 | 
				
			||||||
 | 
					  font-size: 12px;
 | 
				
			||||||
 | 
					  font-weight: bold;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.checkbox-label {
 | 
				
			||||||
 | 
					  color: #a0a0a0;
 | 
				
			||||||
 | 
					  font-size: 0.9rem;
 | 
				
			||||||
 | 
					  line-height: 1.4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.link {
 | 
				
			||||||
 | 
					  color: #00d4ff;
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					  transition: color 0.3s ease;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.link:hover {
 | 
				
			||||||
 | 
					  color: #7c3aed;
 | 
				
			||||||
 | 
					  text-decoration: underline;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-button {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  padding: 1rem;
 | 
				
			||||||
 | 
					  background: linear-gradient(45deg, #00d4ff, #7c3aed);
 | 
				
			||||||
 | 
					  color: white;
 | 
				
			||||||
 | 
					  border: none;
 | 
				
			||||||
 | 
					  border-radius: 12px;
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					  font-size: 1.1rem;
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  transition: all 0.3s ease;
 | 
				
			||||||
 | 
					  margin-top: 0.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-button:hover:not(:disabled) {
 | 
				
			||||||
 | 
					  transform: translateY(-2px);
 | 
				
			||||||
 | 
					  box-shadow: 0 15px 40px rgba(0, 212, 255, 0.4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.signup-button:disabled {
 | 
				
			||||||
 | 
					  opacity: 0.5;
 | 
				
			||||||
 | 
					  cursor: not-allowed;
 | 
				
			||||||
 | 
					  transform: none;
 | 
				
			||||||
 | 
					  background: rgba(255, 255, 255, 0.1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.loading-text {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  gap: 0.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.divider {
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					  margin: 1.5rem 0;
 | 
				
			||||||
 | 
					  color: #666;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.divider::before {
 | 
				
			||||||
 | 
					  content: '';
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  top: 50%;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					  right: 0;
 | 
				
			||||||
 | 
					  height: 1px;
 | 
				
			||||||
 | 
					  background: rgba(255, 255, 255, 0.1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.divider span {
 | 
				
			||||||
 | 
					  background: rgba(255, 255, 255, 0.08);
 | 
				
			||||||
 | 
					  padding: 0 1rem;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  z-index: 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.social-signup {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  padding: 0.875rem;
 | 
				
			||||||
 | 
					  background: rgba(255, 255, 255, 0.05);
 | 
				
			||||||
 | 
					  border: 2px solid rgba(255, 255, 255, 0.1);
 | 
				
			||||||
 | 
					  border-radius: 12px;
 | 
				
			||||||
 | 
					  color: #ffffff;
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  transition: all 0.3s ease;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  gap: 0.75rem;
 | 
				
			||||||
 | 
					  margin-bottom: 0.75rem;
 | 
				
			||||||
 | 
					  backdrop-filter: blur(10px);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.social-signup:hover {
 | 
				
			||||||
 | 
					  background: rgba(255, 255, 255, 0.08);
 | 
				
			||||||
 | 
					  border-color: rgba(255, 255, 255, 0.2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.social-signup.google:hover {
 | 
				
			||||||
 | 
					  border-color: rgba(219, 68, 55, 0.5);
 | 
				
			||||||
 | 
					  box-shadow: 0 0 20px rgba(219, 68, 55, 0.1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.social-signup.github:hover {
 | 
				
			||||||
 | 
					  border-color: rgba(255, 255, 255, 0.5);
 | 
				
			||||||
 | 
					  box-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.error-message {
 | 
				
			||||||
 | 
					  background: rgba(255, 71, 87, 0.1);
 | 
				
			||||||
 | 
					  border: 1px solid rgba(255, 71, 87, 0.3);
 | 
				
			||||||
 | 
					  border-radius: 12px;
 | 
				
			||||||
 | 
					  padding: 1rem;
 | 
				
			||||||
 | 
					  color: #ff4757;
 | 
				
			||||||
 | 
					  font-size: 0.9rem;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  gap: 0.5rem;
 | 
				
			||||||
 | 
					  margin-top: 1rem;
 | 
				
			||||||
 | 
					  animation: shake 0.5s ease-in-out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.success-message {
 | 
				
			||||||
 | 
					  background: rgba(46, 213, 115, 0.1);
 | 
				
			||||||
 | 
					  border: 1px solid rgba(46, 213, 115, 0.3);
 | 
				
			||||||
 | 
					  border-radius: 12px;
 | 
				
			||||||
 | 
					  padding: 1rem;
 | 
				
			||||||
 | 
					  color: #2ed573;
 | 
				
			||||||
 | 
					  font-size: 0.9rem;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  gap: 0.5rem;
 | 
				
			||||||
 | 
					  margin-top: 1rem;
 | 
				
			||||||
 | 
					  animation: slideInUp 0.5s ease-out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@keyframes shake {
 | 
				
			||||||
 | 
					  0%, 100% { transform: translateX(0); }
 | 
				
			||||||
 | 
					  25% { transform: translateX(-5px); }
 | 
				
			||||||
 | 
					  75% { transform: translateX(5px); }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.login-prompt {
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					  margin-top: 2rem;
 | 
				
			||||||
 | 
					  padding-top: 2rem;
 | 
				
			||||||
 | 
					  border-top: 1px solid rgba(255, 255, 255, 0.1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.login-prompt p {
 | 
				
			||||||
 | 
					  color: #a0a0a0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.login-link {
 | 
				
			||||||
 | 
					  color: #00d4ff;
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					  transition: color 0.3s ease;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.login-link:hover {
 | 
				
			||||||
 | 
					  color: #7c3aed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Responsive */
 | 
				
			||||||
 | 
					@media (max-width: 640px) {
 | 
				
			||||||
 | 
					  .signup-container {
 | 
				
			||||||
 | 
					    padding: 1rem;
 | 
				
			||||||
 | 
					    max-width: 100%;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .signup-card {
 | 
				
			||||||
 | 
					    padding: 2rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .form-row {
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    gap: 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .form-group.half-width {
 | 
				
			||||||
 | 
					    margin-bottom: 1rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .checkbox-wrapper {
 | 
				
			||||||
 | 
					    align-items: flex-start;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .checkbox-label {
 | 
				
			||||||
 | 
					    font-size: 0.85rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media (max-width: 480px) {
 | 
				
			||||||
 | 
					  .signup-card {
 | 
				
			||||||
 | 
					    padding: 1.5rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .signup-title {
 | 
				
			||||||
 | 
					    font-size: 1.5rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .logo {
 | 
				
			||||||
 | 
					    font-size: 1.75rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,24 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="homepage">
 | 
					  <div class="homepage">
 | 
				
			||||||
    <!-- Navigation -->
 | 
					 | 
				
			||||||
    <nav class="navbar">
 | 
					    <nav class="navbar">
 | 
				
			||||||
      <div class="nav-content">
 | 
					      <div class="nav-content">
 | 
				
			||||||
        <div class="logo" @click="scrollTo('hero')">
 | 
					        <div class="logo" @click="scrollTo('hero')">
 | 
				
			||||||
          Ride<span class="logo-accent">Aware</span>
 | 
					          Ride<span class="logo-accent">Aware</span>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <ul class="nav-links">
 | 
					        <ul class="nav-links">
 | 
				
			||||||
          <li><a href="#" @click.prevent="scrollTo('features')">Features</a></li>
 | 
					          <li>
 | 
				
			||||||
          <li><a href="/newsletters" @click.prevent="goToNewsletters">Newsletters</a></li>
 | 
					            <a href="#" @click.prevent="scrollTo('features')">Features</a>
 | 
				
			||||||
 | 
					          </li>
 | 
				
			||||||
 | 
					          <li>
 | 
				
			||||||
 | 
					            <router-link to="/login" class="login-link">Login</router-link>
 | 
				
			||||||
 | 
					          </li>
 | 
				
			||||||
 | 
					          <li>
 | 
				
			||||||
 | 
					            <router-link to="/signup" class="signup-btn">Sign Up</router-link>
 | 
				
			||||||
 | 
					          </li>
 | 
				
			||||||
        </ul>
 | 
					        </ul>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </nav>
 | 
					    </nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- Hero Section -->
 | 
					 | 
				
			||||||
    <section id="hero" class="hero">
 | 
					    <section id="hero" class="hero">
 | 
				
			||||||
      <div class="hero-bg"></div>
 | 
					      <div class="hero-bg"></div>
 | 
				
			||||||
      <div class="floating-elements">
 | 
					      <div class="floating-elements">
 | 
				
			||||||
| 
						 | 
					@ -72,7 +77,6 @@
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- Features Section -->
 | 
					 | 
				
			||||||
    <section id="features" class="features">
 | 
					    <section id="features" class="features">
 | 
				
			||||||
      <div class="section-header">
 | 
					      <div class="section-header">
 | 
				
			||||||
        <h2 class="section-title">{{ featuresTitle }}</h2>
 | 
					        <h2 class="section-title">{{ featuresTitle }}</h2>
 | 
				
			||||||
| 
						 | 
					@ -101,7 +105,6 @@
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- Stats Section -->
 | 
					 | 
				
			||||||
    <section class="stats">
 | 
					    <section class="stats">
 | 
				
			||||||
      <div class="container">
 | 
					      <div class="container">
 | 
				
			||||||
        <div class="stats-grid">
 | 
					        <div class="stats-grid">
 | 
				
			||||||
| 
						 | 
					@ -113,7 +116,6 @@
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- Footer -->
 | 
					 | 
				
			||||||
    <footer class="footer">
 | 
					    <footer class="footer">
 | 
				
			||||||
      <div class="container">
 | 
					      <div class="container">
 | 
				
			||||||
        <div class="footer-content">
 | 
					        <div class="footer-content">
 | 
				
			||||||
| 
						 | 
					@ -225,7 +227,6 @@ export default {
 | 
				
			||||||
    const animatedStats = reactive({})
 | 
					    const animatedStats = reactive({})
 | 
				
			||||||
    const floatingElements = reactive([])
 | 
					    const floatingElements = reactive([])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Generate floating elements
 | 
					 | 
				
			||||||
    const generateFloatingElements = () => {
 | 
					    const generateFloatingElements = () => {
 | 
				
			||||||
      for (let i = 0; i < 15; i++) {
 | 
					      for (let i = 0; i < 15; i++) {
 | 
				
			||||||
        floatingElements.push({
 | 
					        floatingElements.push({
 | 
				
			||||||
| 
						 | 
					@ -239,7 +240,6 @@ export default {
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Animate stats on scroll
 | 
					 | 
				
			||||||
    const animateStats = () => {
 | 
					    const animateStats = () => {
 | 
				
			||||||
      platformStats.forEach(stat => {
 | 
					      platformStats.forEach(stat => {
 | 
				
			||||||
        let current = 0
 | 
					        let current = 0
 | 
				
			||||||
| 
						 | 
					@ -264,14 +264,11 @@ export default {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const goToNewsletters = () => {
 | 
					    const goToNewsletters = () => {
 | 
				
			||||||
      // Handle navigation to newsletters page
 | 
					 | 
				
			||||||
      // This could be a router push in a real Vue app
 | 
					 | 
				
			||||||
      window.location.href = '/newsletters'
 | 
					      window.location.href = '/newsletters'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const handleNotifyMe = () => {
 | 
					    const handleNotifyMe = () => {
 | 
				
			||||||
      if (isValidEmail.value) {
 | 
					      if (isValidEmail.value) {
 | 
				
			||||||
        // Here you would typically send the email to your backend
 | 
					 | 
				
			||||||
        alert(`Thanks! We'll notify you at ${emailInput.value} when RideAware launches.`)
 | 
					        alert(`Thanks! We'll notify you at ${emailInput.value} when RideAware launches.`)
 | 
				
			||||||
        emailInput.value = ''
 | 
					        emailInput.value = ''
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
| 
						 | 
					@ -293,7 +290,6 @@ export default {
 | 
				
			||||||
    onMounted(() => {
 | 
					    onMounted(() => {
 | 
				
			||||||
      generateFloatingElements()
 | 
					      generateFloatingElements()
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Intersection Observer for stats animation
 | 
					 | 
				
			||||||
      const observer = new IntersectionObserver((entries) => {
 | 
					      const observer = new IntersectionObserver((entries) => {
 | 
				
			||||||
        entries.forEach(entry => {
 | 
					        entries.forEach(entry => {
 | 
				
			||||||
          if (entry.isIntersecting) {
 | 
					          if (entry.isIntersecting) {
 | 
				
			||||||
| 
						 | 
					@ -308,7 +304,6 @@ export default {
 | 
				
			||||||
        observer.observe(statsSection)
 | 
					        observer.observe(statsSection)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Parallax effect for hero background
 | 
					 | 
				
			||||||
      window.addEventListener('scroll', () => {
 | 
					      window.addEventListener('scroll', () => {
 | 
				
			||||||
        const scrolled = window.pageYOffset
 | 
					        const scrolled = window.pageYOffset
 | 
				
			||||||
        const parallax = document.querySelector('.hero-bg')
 | 
					        const parallax = document.querySelector('.hero-bg')
 | 
				
			||||||
| 
						 | 
					@ -318,7 +313,6 @@ export default {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Animate mockup stats
 | 
					 | 
				
			||||||
      let statIndex = 0
 | 
					      let statIndex = 0
 | 
				
			||||||
      setInterval(() => {
 | 
					      setInterval(() => {
 | 
				
			||||||
        activeStat.value = mockupStats[statIndex].id
 | 
					        activeStat.value = mockupStats[statIndex].id
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,19 +0,0 @@
 | 
				
			||||||
<template>
 | 
					 | 
				
			||||||
    <div class="logged-in">
 | 
					 | 
				
			||||||
      <h2>You have successfully logged in!</h2>
 | 
					 | 
				
			||||||
      <p>Welcome back to RideAware!</p>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </template>
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  <script>
 | 
					 | 
				
			||||||
  export default {
 | 
					 | 
				
			||||||
    name: 'LoggedInPage',
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  </script>
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  <style scoped>
 | 
					 | 
				
			||||||
  .logged-in {
 | 
					 | 
				
			||||||
    text-align: center;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  </style>
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="login-page">
 | 
					  <div class="login-page">
 | 
				
			||||||
    <!-- Background Elements -->
 | 
					 | 
				
			||||||
    <div class="login-bg">
 | 
					    <div class="login-bg">
 | 
				
			||||||
      <div class="floating-elements">
 | 
					      <div class="floating-elements">
 | 
				
			||||||
        <div 
 | 
					        <div 
 | 
				
			||||||
| 
						 | 
					@ -12,10 +11,8 @@
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- Login Container -->
 | 
					 | 
				
			||||||
    <div class="login-container">
 | 
					    <div class="login-container">
 | 
				
			||||||
      <div class="login-card">
 | 
					      <div class="login-card">
 | 
				
			||||||
        <!-- Logo/Header -->
 | 
					 | 
				
			||||||
        <div class="login-header">
 | 
					        <div class="login-header">
 | 
				
			||||||
          <div class="logo">
 | 
					          <div class="logo">
 | 
				
			||||||
            Ride<span class="logo-accent">Aware</span>
 | 
					            Ride<span class="logo-accent">Aware</span>
 | 
				
			||||||
| 
						 | 
					@ -24,7 +21,6 @@
 | 
				
			||||||
          <p class="login-subtitle">Sign in to continue your cycling journey</p>
 | 
					          <p class="login-subtitle">Sign in to continue your cycling journey</p>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- Login Form -->
 | 
					 | 
				
			||||||
        <form @submit.prevent="login" class="login-form">
 | 
					        <form @submit.prevent="login" class="login-form">
 | 
				
			||||||
          <div class="form-group">
 | 
					          <div class="form-group">
 | 
				
			||||||
            <label for="username" class="form-label">Username</label>
 | 
					            <label for="username" class="form-label">Username</label>
 | 
				
			||||||
| 
						 | 
					@ -77,14 +73,18 @@
 | 
				
			||||||
          <button 
 | 
					          <button 
 | 
				
			||||||
            type="submit" 
 | 
					            type="submit" 
 | 
				
			||||||
            class="login-button"
 | 
					            class="login-button"
 | 
				
			||||||
            :class="{ 'loading': isLoading }"
 | 
					            :class="{ 'loading': isLoading, 'success': loginSuccess }"
 | 
				
			||||||
            :disabled="isLoading"
 | 
					            :disabled="isLoading"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            <span v-if="!isLoading">Sign In</span>
 | 
					            <span v-if="!isLoading && !loginSuccess">Sign In</span>
 | 
				
			||||||
            <span v-else class="loading-text">
 | 
					            <span v-else-if="isLoading" class="loading-text">
 | 
				
			||||||
              <i class="fas fa-spinner fa-spin"></i>
 | 
					              <i class="fas fa-spinner fa-spin"></i>
 | 
				
			||||||
              Signing In...
 | 
					              Signing In...
 | 
				
			||||||
            </span>
 | 
					            </span>
 | 
				
			||||||
 | 
					            <span v-else-if="loginSuccess" class="success-text">
 | 
				
			||||||
 | 
					              <i class="fas fa-check"></i>
 | 
				
			||||||
 | 
					              Success! Redirecting...
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <div class="divider">
 | 
					          <div class="divider">
 | 
				
			||||||
| 
						 | 
					@ -102,13 +102,16 @@
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
        </form>
 | 
					        </form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- Error Message -->
 | 
					 | 
				
			||||||
        <div v-if="error" class="error-message">
 | 
					        <div v-if="error" class="error-message">
 | 
				
			||||||
          <i class="fas fa-exclamation-triangle"></i>
 | 
					          <i class="fas fa-exclamation-triangle"></i>
 | 
				
			||||||
          {{ error }}
 | 
					          {{ error }}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- Sign Up Link -->
 | 
					        <div v-if="loginSuccess" class="success-message">
 | 
				
			||||||
 | 
					          <i class="fas fa-check-circle"></i>
 | 
				
			||||||
 | 
					          Login successful! Redirecting to homepage...
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div class="signup-prompt">
 | 
					        <div class="signup-prompt">
 | 
				
			||||||
          <p>Don't have an account? <a href="/signup" class="signup-link">Sign up</a></p>
 | 
					          <p>Don't have an account? <a href="/signup" class="signup-link">Sign up</a></p>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
| 
						 | 
					@ -129,6 +132,7 @@ export default {
 | 
				
			||||||
      password: '',
 | 
					      password: '',
 | 
				
			||||||
      error: null,
 | 
					      error: null,
 | 
				
			||||||
      isLoading: false,
 | 
					      isLoading: false,
 | 
				
			||||||
 | 
					      loginSuccess: false,
 | 
				
			||||||
      showPassword: false,
 | 
					      showPassword: false,
 | 
				
			||||||
      rememberMe: false,
 | 
					      rememberMe: false,
 | 
				
			||||||
      floatingElements: []
 | 
					      floatingElements: []
 | 
				
			||||||
| 
						 | 
					@ -146,26 +150,35 @@ export default {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      this.isLoading = true;
 | 
					      this.isLoading = true;
 | 
				
			||||||
      this.error = null;
 | 
					      this.error = null;
 | 
				
			||||||
 | 
					      this.loginSuccess = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        const response = await axios.post('http://127.0.0.1:5000/login', {
 | 
					        const response = await axios.post('http://localhost:5000/auth/login', {
 | 
				
			||||||
          username: this.username,
 | 
					          username: this.username,
 | 
				
			||||||
          password: this.password,
 | 
					          password: this.password,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        console.log('Login successful:', response.data);
 | 
					        console.log('Login successful:', response.data);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Store user data if remember me is checked
 | 
					        const userData = {
 | 
				
			||||||
 | 
					          user_id: response.data.user_id,
 | 
				
			||||||
 | 
					          username: this.username,
 | 
				
			||||||
 | 
					          loginTime: new Date().toISOString()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.rememberMe) {
 | 
					        if (this.rememberMe) {
 | 
				
			||||||
          localStorage.setItem('user', JSON.stringify(response.data));
 | 
					          localStorage.setItem('user', JSON.stringify(userData));
 | 
				
			||||||
 | 
					          localStorage.setItem('authToken', 'authenticated');
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          sessionStorage.setItem('user', JSON.stringify(response.data));
 | 
					          sessionStorage.setItem('user', JSON.stringify(userData));
 | 
				
			||||||
 | 
					          sessionStorage.setItem('authToken', 'authenticated');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Add success animation before redirect
 | 
					        this.loginSuccess = true;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        setTimeout(() => {
 | 
					        setTimeout(() => {
 | 
				
			||||||
          this.$router.push('/logged-in');
 | 
					          this.$router.push('/');
 | 
				
			||||||
        }, 500);
 | 
					        }, 1500);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
      } catch (error) {
 | 
					      } catch (error) {
 | 
				
			||||||
        console.error('Login failed:', error.response?.data);
 | 
					        console.error('Login failed:', error.response?.data);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										344
									
								
								src/components/UserSignup.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								src/components/UserSignup.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,344 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <div class="signup-page">
 | 
				
			||||||
 | 
					    <div class="signup-bg">
 | 
				
			||||||
 | 
					      <div class="floating-elements">
 | 
				
			||||||
 | 
					        <div 
 | 
				
			||||||
 | 
					          v-for="(element, index) in floatingElements" 
 | 
				
			||||||
 | 
					          :key="index"
 | 
				
			||||||
 | 
					          class="floating-element"
 | 
				
			||||||
 | 
					          :style="element.style">
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="signup-container">
 | 
				
			||||||
 | 
					      <div class="signup-card">
 | 
				
			||||||
 | 
					        <div class="signup-header">
 | 
				
			||||||
 | 
					          <div class="logo">
 | 
				
			||||||
 | 
					            Ride<span class="logo-accent">Aware</span>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <h2 class="signup-title">Join RideAware</h2>
 | 
				
			||||||
 | 
					          <p class="signup-subtitle">Create your account to start tracking your cycling journey</p>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <form @submit.prevent="signup" class="signup-form">
 | 
				
			||||||
 | 
					          <div class="form-row">
 | 
				
			||||||
 | 
					            <div class="form-group half-width">
 | 
				
			||||||
 | 
					              <label for="firstName" class="form-label">First Name</label>
 | 
				
			||||||
 | 
					              <div class="input-wrapper">
 | 
				
			||||||
 | 
					                <i class="fas fa-user input-icon"></i>
 | 
				
			||||||
 | 
					                <input 
 | 
				
			||||||
 | 
					                  type="text" 
 | 
				
			||||||
 | 
					                  id="firstName" 
 | 
				
			||||||
 | 
					                  v-model="firstName" 
 | 
				
			||||||
 | 
					                  class="form-input"
 | 
				
			||||||
 | 
					                  :class="{ 'error': error && !firstName }"
 | 
				
			||||||
 | 
					                  placeholder="First name"
 | 
				
			||||||
 | 
					                  required 
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="form-group half-width">
 | 
				
			||||||
 | 
					              <label for="lastName" class="form-label">Last Name</label>
 | 
				
			||||||
 | 
					              <div class="input-wrapper">
 | 
				
			||||||
 | 
					                <i class="fas fa-user input-icon"></i>
 | 
				
			||||||
 | 
					                <input 
 | 
				
			||||||
 | 
					                  type="text" 
 | 
				
			||||||
 | 
					                  id="lastName" 
 | 
				
			||||||
 | 
					                  v-model="lastName" 
 | 
				
			||||||
 | 
					                  class="form-input"
 | 
				
			||||||
 | 
					                  :class="{ 'error': error && !lastName }"
 | 
				
			||||||
 | 
					                  placeholder="Last name"
 | 
				
			||||||
 | 
					                  required 
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div class="form-group">
 | 
				
			||||||
 | 
					            <label for="username" class="form-label">Username</label>
 | 
				
			||||||
 | 
					            <div class="input-wrapper">
 | 
				
			||||||
 | 
					              <i class="fas fa-at input-icon"></i>
 | 
				
			||||||
 | 
					              <input 
 | 
				
			||||||
 | 
					                type="text" 
 | 
				
			||||||
 | 
					                id="username" 
 | 
				
			||||||
 | 
					                v-model="username" 
 | 
				
			||||||
 | 
					                class="form-input"
 | 
				
			||||||
 | 
					                :class="{ 'error': error && !username }"
 | 
				
			||||||
 | 
					                placeholder="Choose a username"
 | 
				
			||||||
 | 
					                required 
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div class="form-group">
 | 
				
			||||||
 | 
					            <label for="email" class="form-label">Email</label>
 | 
				
			||||||
 | 
					            <div class="input-wrapper">
 | 
				
			||||||
 | 
					              <i class="fas fa-envelope input-icon"></i>
 | 
				
			||||||
 | 
					              <input 
 | 
				
			||||||
 | 
					                type="email" 
 | 
				
			||||||
 | 
					                id="email" 
 | 
				
			||||||
 | 
					                v-model="email" 
 | 
				
			||||||
 | 
					                class="form-input"
 | 
				
			||||||
 | 
					                :class="{ 'error': error && !email }"
 | 
				
			||||||
 | 
					                placeholder="Enter your email"
 | 
				
			||||||
 | 
					                required 
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div class="form-group">
 | 
				
			||||||
 | 
					            <label for="password" class="form-label">Password</label>
 | 
				
			||||||
 | 
					            <div class="input-wrapper">
 | 
				
			||||||
 | 
					              <i class="fas fa-lock input-icon"></i>
 | 
				
			||||||
 | 
					              <input 
 | 
				
			||||||
 | 
					                :type="showPassword ? 'text' : 'password'" 
 | 
				
			||||||
 | 
					                id="password" 
 | 
				
			||||||
 | 
					                v-model="password" 
 | 
				
			||||||
 | 
					                class="form-input"
 | 
				
			||||||
 | 
					                :class="{ 'error': error && !password }"
 | 
				
			||||||
 | 
					                placeholder="Create a password"
 | 
				
			||||||
 | 
					                required 
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              <button 
 | 
				
			||||||
 | 
					                type="button" 
 | 
				
			||||||
 | 
					                class="password-toggle"
 | 
				
			||||||
 | 
					                @click="showPassword = !showPassword"
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                <i :class="showPassword ? 'fas fa-eye-slash' : 'fas fa-eye'"></i>
 | 
				
			||||||
 | 
					              </button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="password-strength" v-if="password">
 | 
				
			||||||
 | 
					              <div class="strength-bar">
 | 
				
			||||||
 | 
					                <div 
 | 
				
			||||||
 | 
					                  class="strength-fill" 
 | 
				
			||||||
 | 
					                  :class="passwordStrength.class"
 | 
				
			||||||
 | 
					                  :style="{ width: passwordStrength.width }"
 | 
				
			||||||
 | 
					                ></div>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <span class="strength-text" :class="passwordStrength.class">
 | 
				
			||||||
 | 
					                {{ passwordStrength.text }}
 | 
				
			||||||
 | 
					              </span>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div class="form-group">
 | 
				
			||||||
 | 
					            <label for="confirmPassword" class="form-label">Confirm Password</label>
 | 
				
			||||||
 | 
					            <div class="input-wrapper">
 | 
				
			||||||
 | 
					              <i class="fas fa-lock input-icon"></i>
 | 
				
			||||||
 | 
					              <input 
 | 
				
			||||||
 | 
					                :type="showConfirmPassword ? 'text' : 'password'" 
 | 
				
			||||||
 | 
					                id="confirmPassword" 
 | 
				
			||||||
 | 
					                v-model="confirmPassword" 
 | 
				
			||||||
 | 
					                class="form-input"
 | 
				
			||||||
 | 
					                :class="{ 'error': error && !confirmPassword || passwordMismatch }"
 | 
				
			||||||
 | 
					                placeholder="Confirm your password"
 | 
				
			||||||
 | 
					                required 
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              <button 
 | 
				
			||||||
 | 
					                type="button" 
 | 
				
			||||||
 | 
					                class="password-toggle"
 | 
				
			||||||
 | 
					                @click="showConfirmPassword = !showConfirmPassword"
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                <i :class="showConfirmPassword ? 'fas fa-eye-slash' : 'fas fa-eye'"></i>
 | 
				
			||||||
 | 
					              </button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div v-if="passwordMismatch" class="password-mismatch">
 | 
				
			||||||
 | 
					              <i class="fas fa-exclamation-triangle"></i>
 | 
				
			||||||
 | 
					              Passwords do not match
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div class="form-options">
 | 
				
			||||||
 | 
					            <label class="checkbox-wrapper">
 | 
				
			||||||
 | 
					              <input type="checkbox" v-model="agreeToTerms" class="checkbox-input" required>
 | 
				
			||||||
 | 
					              <span class="checkbox-custom"></span>
 | 
				
			||||||
 | 
					              <span class="checkbox-label">
 | 
				
			||||||
 | 
					                I agree to the <a href="/terms" class="link">Terms of Service</a> 
 | 
				
			||||||
 | 
					                and <a href="/privacy" class="link">Privacy Policy</a>
 | 
				
			||||||
 | 
					              </span>
 | 
				
			||||||
 | 
					            </label>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div class="form-options">
 | 
				
			||||||
 | 
					            <label class="checkbox-wrapper">
 | 
				
			||||||
 | 
					              <input type="checkbox" v-model="subscribeNewsletter" class="checkbox-input">
 | 
				
			||||||
 | 
					              <span class="checkbox-custom"></span>
 | 
				
			||||||
 | 
					              <span class="checkbox-label">
 | 
				
			||||||
 | 
					                Subscribe to newsletter for cycling tips and updates
 | 
				
			||||||
 | 
					              </span>
 | 
				
			||||||
 | 
					            </label>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <button 
 | 
				
			||||||
 | 
					            type="submit" 
 | 
				
			||||||
 | 
					            class="signup-button"
 | 
				
			||||||
 | 
					            :class="{ 'loading': isLoading }"
 | 
				
			||||||
 | 
					            :disabled="isLoading || !isFormValid"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <span v-if="!isLoading">Create Account</span>
 | 
				
			||||||
 | 
					            <span v-else class="loading-text">
 | 
				
			||||||
 | 
					              <i class="fas fa-spinner fa-spin"></i>
 | 
				
			||||||
 | 
					              Creating Account...
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div class="divider">
 | 
				
			||||||
 | 
					            <span>or</span>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <button type="button" class="social-signup google">
 | 
				
			||||||
 | 
					            <i class="fab fa-google"></i>
 | 
				
			||||||
 | 
					            Sign up with Google
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <button type="button" class="social-signup github">
 | 
				
			||||||
 | 
					            <i class="fab fa-github"></i>
 | 
				
			||||||
 | 
					            Sign up with GitHub
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div v-if="error" class="error-message">
 | 
				
			||||||
 | 
					          <i class="fas fa-exclamation-triangle"></i>
 | 
				
			||||||
 | 
					          {{ error }}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div v-if="successMessage" class="success-message">
 | 
				
			||||||
 | 
					          <i class="fas fa-check-circle"></i>
 | 
				
			||||||
 | 
					          {{ successMessage }}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="login-prompt">
 | 
				
			||||||
 | 
					          <p>Already have an account? <a href="/login" class="login-link">Sign in</a></p>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					import axios from 'axios';
 | 
				
			||||||
 | 
					import '@/assets/css/components/signup.css';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  name: 'UserSignup',
 | 
				
			||||||
 | 
					  data() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      firstName: '',
 | 
				
			||||||
 | 
					      lastName: '',
 | 
				
			||||||
 | 
					      username: '',
 | 
				
			||||||
 | 
					      email: '',
 | 
				
			||||||
 | 
					      password: '',
 | 
				
			||||||
 | 
					      confirmPassword: '',
 | 
				
			||||||
 | 
					      error: null,
 | 
				
			||||||
 | 
					      successMessage: null,
 | 
				
			||||||
 | 
					      isLoading: false,
 | 
				
			||||||
 | 
					      showPassword: false,
 | 
				
			||||||
 | 
					      showConfirmPassword: false,
 | 
				
			||||||
 | 
					      agreeToTerms: false,
 | 
				
			||||||
 | 
					      subscribeNewsletter: false,
 | 
				
			||||||
 | 
					      floatingElements: []
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  computed: {
 | 
				
			||||||
 | 
					    passwordMismatch() {
 | 
				
			||||||
 | 
					      return this.confirmPassword && this.password !== this.confirmPassword;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    passwordStrength() {
 | 
				
			||||||
 | 
					      if (!this.password) return { width: '0%', class: '', text: '' };
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      let score = 0;
 | 
				
			||||||
 | 
					      let feedback = [];
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (this.password.length >= 8) score += 1;
 | 
				
			||||||
 | 
					      else feedback.push('at least 8 characters');
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (/[A-Z]/.test(this.password)) score += 1;
 | 
				
			||||||
 | 
					      else feedback.push('uppercase letter');
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (/[a-z]/.test(this.password)) score += 1;
 | 
				
			||||||
 | 
					      else feedback.push('lowercase letter');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (/\d/.test(this.password)) score += 1;
 | 
				
			||||||
 | 
					      else feedback.push('number');
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (/[!@#$%^&*(),.?":{}|<>]/.test(this.password)) score += 1;
 | 
				
			||||||
 | 
					      else feedback.push('special character');
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (score < 2) {
 | 
				
			||||||
 | 
					        return { width: '25%', class: 'weak', text: 'Weak' };
 | 
				
			||||||
 | 
					      } else if (score < 4) {
 | 
				
			||||||
 | 
					        return { width: '50%', class: 'fair', text: 'Fair' };
 | 
				
			||||||
 | 
					      } else if (score < 5) {
 | 
				
			||||||
 | 
					        return { width: '75%', class: 'good', text: 'Good' };
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        return { width: '100%', class: 'strong', text: 'Strong' };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    isFormValid() {
 | 
				
			||||||
 | 
					      return this.firstName && 
 | 
				
			||||||
 | 
					             this.lastName && 
 | 
				
			||||||
 | 
					             this.username && 
 | 
				
			||||||
 | 
					             this.email && 
 | 
				
			||||||
 | 
					             this.password && 
 | 
				
			||||||
 | 
					             this.confirmPassword && 
 | 
				
			||||||
 | 
					             !this.passwordMismatch && 
 | 
				
			||||||
 | 
					             this.agreeToTerms;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  mounted() {
 | 
				
			||||||
 | 
					    this.generateFloatingElements();
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  methods: {
 | 
				
			||||||
 | 
					    async signup() {
 | 
				
			||||||
 | 
					      if (!this.isFormValid) {
 | 
				
			||||||
 | 
					        this.error = 'Please fill in all required fields correctly';
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.isLoading = true;
 | 
				
			||||||
 | 
					      this.error = null;
 | 
				
			||||||
 | 
					      this.successMessage = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        const response = await axios.post('http://localhost:5000/auth/signup', {
 | 
				
			||||||
 | 
					          firstName: this.firstName,
 | 
				
			||||||
 | 
					          lastName: this.lastName,
 | 
				
			||||||
 | 
					          username: this.username,
 | 
				
			||||||
 | 
					          email: this.email,
 | 
				
			||||||
 | 
					          password: this.password,
 | 
				
			||||||
 | 
					          subscribeNewsletter: this.subscribeNewsletter
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        console.log('Signup successful:', response.data);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        this.successMessage = 'Account created successfully! Please check your email to verify your account.';
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        setTimeout(() => {
 | 
				
			||||||
 | 
					          this.$router.push('/login');
 | 
				
			||||||
 | 
					        }, 2000);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					      } catch (error) {
 | 
				
			||||||
 | 
					        console.error('Signup failed:', error.response?.data);
 | 
				
			||||||
 | 
					        this.error = error.response?.data?.error || 'Account creation failed. Please try again.';
 | 
				
			||||||
 | 
					      } finally {
 | 
				
			||||||
 | 
					        this.isLoading = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    generateFloatingElements() {
 | 
				
			||||||
 | 
					      for (let i = 0; i < 12; i++) {
 | 
				
			||||||
 | 
					        this.floatingElements.push({
 | 
				
			||||||
 | 
					          style: {
 | 
				
			||||||
 | 
					            left: Math.random() * 100 + '%',
 | 
				
			||||||
 | 
					            top: Math.random() * 100 + '%',
 | 
				
			||||||
 | 
					            animationDelay: Math.random() * 8 + 's',
 | 
				
			||||||
 | 
					            animationDuration: (6 + Math.random() * 4) + 's'
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -1,43 +1,46 @@
 | 
				
			||||||
import { createRouter, createWebHistory } from 'vue-router';
 | 
					import { createRouter, createWebHistory } from 'vue-router'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Lazy load components for better performance
 | 
					 | 
				
			||||||
const routes = [
 | 
					const routes = [
 | 
				
			||||||
  { 
 | 
					  { 
 | 
				
			||||||
    path: '/', 
 | 
					    path: '/', 
 | 
				
			||||||
    name: 'Home',
 | 
					    name: 'Home',
 | 
				
			||||||
    component: () => import('../components/Home.vue') 
 | 
					    component: () => import('../components/Home.vue'),
 | 
				
			||||||
 | 
					    meta: { title: 'RideAware – Home' } 
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  { 
 | 
					  { 
 | 
				
			||||||
    path: '/login', 
 | 
					    path: '/login', 
 | 
				
			||||||
    name: 'Login',
 | 
					    name: 'Login',
 | 
				
			||||||
    component: () => import('../components/UserLogin.vue') 
 | 
					    component: () => import('../components/UserLogin.vue'),
 | 
				
			||||||
 | 
					    meta: { title: 'RideAware – Sign In' } 
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    path: '/logged-in', 
 | 
					    path: '/signup',
 | 
				
			||||||
    name: 'LoggedIn',
 | 
					    name: 'SignUp',
 | 
				
			||||||
    component: () => import('../components/LoggedinPage.vue'),
 | 
					    component: () => import('../components/UserSignup.vue'),
 | 
				
			||||||
    // Optional: Add route guard to check if user is actually logged in
 | 
					    meta: { title: 'RideAware – Sign Up' }
 | 
				
			||||||
    meta: { requiresAuth: true }
 | 
					  },
 | 
				
			||||||
  }
 | 
					  
 | 
				
			||||||
];
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const router = createRouter({
 | 
					const router = createRouter({
 | 
				
			||||||
  history: createWebHistory(),
 | 
					  history: createWebHistory(),
 | 
				
			||||||
  routes,
 | 
					  routes,
 | 
				
			||||||
});
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Optional: Navigation guard example
 | 
					 | 
				
			||||||
router.beforeEach((to, from, next) => {
 | 
					router.beforeEach((to, from, next) => {
 | 
				
			||||||
  // Check if route requires authentication
 | 
					 | 
				
			||||||
  if (to.meta.requiresAuth) {
 | 
					  if (to.meta.requiresAuth) {
 | 
				
			||||||
    // Check if user is logged in (implement your auth logic)
 | 
					    const isLoggedIn = !!(localStorage.getItem('user') || sessionStorage.getItem('user'))
 | 
				
			||||||
    const isLoggedIn = localStorage.getItem('user') || sessionStorage.getItem('user');
 | 
					 | 
				
			||||||
    if (!isLoggedIn) {
 | 
					    if (!isLoggedIn) {
 | 
				
			||||||
      next('/login');
 | 
					      next({ name: 'Login' })
 | 
				
			||||||
      return;
 | 
					      return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  next();
 | 
					  next()
 | 
				
			||||||
});
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default router;
 | 
					router.afterEach((to) => {
 | 
				
			||||||
 | 
					  const defaultTitle = 'RideAware'
 | 
				
			||||||
 | 
					  document.title = to.meta.title || defaultTitle
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default router
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue