Explorar el Código

Create HTML & CSS for Login Page

Eldar Mukhtarov hace 9 meses
padre
commit
8b1390a899

+ 343 - 0
project/frontend-angular/src/app/login/login.css

@@ -0,0 +1,343 @@
+.login-container {
+  max-width: 450px;
+  margin: 40px auto;
+  padding: 20px;
+  animation: fadeIn 0.6s ease-in;
+}
+
+@keyframes fadeIn {
+  from { 
+    opacity: 0; 
+    transform: translateY(30px); 
+  }
+  to { 
+    opacity: 1; 
+    transform: translateY(0); 
+  }
+}
+
+.login-card,
+.logged-in-card {
+  background: linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.02) 100%);
+  border: 1px solid rgba(255, 255, 255, 0.1);
+  border-radius: 16px;
+  padding: 40px;
+  backdrop-filter: blur(10px);
+  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
+  transition: all 0.3s ease;
+}
+
+.login-card:hover,
+.logged-in-card:hover {
+  border-color: rgba(255, 255, 255, 0.15);
+  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
+}
+
+.form-header {
+  text-align: center;
+  margin-bottom: 32px;
+}
+
+.form-title {
+  font-size: 32px;
+  font-weight: 700;
+  letter-spacing: -1px;
+  color: #ffffff;
+  margin-bottom: 8px;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+  background: linear-gradient(135deg, #ffffff 0%, #e0e0e0 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+}
+
+.form-subtitle {
+  font-size: 16px;
+  color: #b0b0b0;
+  font-weight: 400;
+  margin: 0;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+}
+
+.login-form {
+  display: flex;
+  flex-direction: column;
+  gap: 24px;
+}
+
+.form-group {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.form-label {
+  font-size: 14px;
+  font-weight: 500;
+  color: #e0e0e0;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+  margin-bottom: 4px;
+}
+
+.form-input {
+  padding: 14px 16px;
+  background: rgba(255, 255, 255, 0.05);
+  border: 1px solid rgba(255, 255, 255, 0.1);
+  border-radius: 8px;
+  color: #ffffff;
+  font-size: 16px;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+  transition: all 0.3s ease;
+  width: 100%;
+  box-sizing: border-box;
+}
+
+.form-input:focus {
+  outline: none;
+  border-color: rgba(255, 255, 255, 0.3);
+  background: rgba(255, 255, 255, 0.08);
+  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.1);
+  transform: translateY(-1px);
+  z-index: 1;
+  position: relative;
+}
+
+.form-input::placeholder {
+  color: #888;
+  font-style: italic;
+}
+
+.error-messages {
+  margin-top: 4px;
+}
+
+.error-message {
+  font-size: 12px;
+  color: #ff6b6b;
+  font-weight: 500;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+  display: flex;
+  align-items: center;
+  gap: 6px;
+}
+
+.global-error {
+  background: rgba(255, 107, 107, 0.1);
+  border: 1px solid rgba(255, 107, 107, 0.3);
+  border-radius: 8px;
+  padding: 16px;
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  margin-top: 16px;
+  animation: shake 0.5s ease-in-out;
+}
+
+@keyframes shake {
+  0%, 100% { transform: translateX(0); }
+  25% { transform: translateX(-5px); }
+  75% { transform: translateX(5px); }
+}
+
+.error-text {
+  color: #ff6b6b;
+  font-size: 14px;
+  font-weight: 500;
+}
+
+.form-actions {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+  margin-top: 8px;
+}
+
+.submit-button {
+  background: linear-gradient(135deg, #8C231E 0%, #a02b26 100%);
+  border: none;
+  border-radius: 8px;
+  color: #ffffff;
+  padding: 16px 24px;
+  font-size: 16px;
+  font-weight: 600;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+  position: relative;
+  overflow: hidden;
+}
+
+.submit-button:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 8px 20px rgba(140, 35, 30, 0.4);
+  background: linear-gradient(135deg, #a02b26 0%, #b83530 100%);
+}
+
+.submit-button:active {
+  transform: translateY(0);
+}
+
+.submit-button:disabled {
+  opacity: 0.6;
+  cursor: not-allowed;
+  transform: none;
+}
+
+.form-input.ng-invalid.ng-touched {
+  border-color: rgba(255, 107, 107, 0.5);
+  background: rgba(255, 107, 107, 0.05);
+}
+
+.form-input.ng-valid.ng-touched {
+  border-color: rgba(76, 175, 80, 0.5);
+  background: rgba(76, 175, 80, 0.05);
+}
+
+.form-divider {
+  display: flex;
+  align-items: center;
+  margin: 32px 0 24px 0;
+  gap: 16px;
+}
+
+.divider-line {
+  flex: 1;
+  height: 1px;
+  background: rgba(255, 255, 255, 0.1);
+}
+
+.divider-text {
+  color: #b0b0b0;
+  font-size: 14px;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+  font-weight: 400;
+}
+
+.form-footer {
+  text-align: center;
+}
+
+.footer-text {
+  color: #b0b0b0;
+  font-size: 14px;
+  margin: 0;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+}
+
+.footer-link {
+  color: #ffffff;
+  text-decoration: none;
+  font-weight: 500;
+  transition: all 0.3s ease;
+  position: relative;
+}
+
+.footer-link:hover {
+  color: #e0e0e0;
+  text-decoration: underline;
+}
+
+.footer-link::after {
+  content: '';
+  position: absolute;
+  width: 0;
+  height: 2px;
+  bottom: -2px;
+  left: 0;
+  background: linear-gradient(135deg, #8C231E 0%, #a02b26 100%);
+  transition: width 0.3s ease;
+}
+
+.footer-link:hover::after {
+  width: 100%;
+}
+
+.logged-in-content {
+  text-align: center;
+  padding: 20px 0;
+}
+
+.logged-in-title {
+  font-size: 28px;
+  font-weight: 700;
+  color: #ffffff;
+  margin-bottom: 16px;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+  background: linear-gradient(135deg, #ffffff 0%, #e0e0e0 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+}
+
+.logged-in-text {
+  font-size: 16px;
+  color: #b0b0b0;
+  margin: 0;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+}
+
+.user-role {
+  color: #ffffff;
+  font-weight: 600;
+  background: linear-gradient(135deg, #8C231E 0%, #a02b26 100%);
+  padding: 4px 12px;
+  border-radius: 16px;
+  font-size: 14px;
+  display: inline-block;
+  margin-left: 4px;
+}
+
+.submit-button.loading {
+  pointer-events: none;
+}
+
+.submit-button.loading::after {
+  content: "";
+  position: absolute;
+  width: 16px;
+  height: 16px;
+  margin: auto;
+  border: 2px solid transparent;
+  border-top-color: #ffffff;
+  border-radius: 50%;
+  animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
+@media (max-width: 768px) {
+  .login-container {
+    margin: 20px auto;
+    padding: 15px;
+  }
+
+  .login-card,
+  .logged-in-card {
+    padding: 24px;
+  }
+
+  .form-title,
+  .logged-in-title {
+    font-size: 24px;
+  }
+
+  .form-subtitle {
+    font-size: 14px;
+  }
+
+  .form-input {
+    padding: 12px 14px;
+    font-size: 16px;
+  }
+
+  .submit-button {
+    padding: 14px 20px;
+  }
+
+  .form-divider {
+    margin: 24px 0 20px 0;
+  }
+}

+ 53 - 23
project/frontend-angular/src/app/login/login.html

@@ -1,51 +1,81 @@
-<div>
+<div class="login-container">
   @if (isLoggedIn) {
-    <div>
-      Logged in as {{roles}}.
+    <div class="logged-in-card">
+      <div class="logged-in-content">
+        <h2 class="logged-in-title">Welcome Back!</h2>
+        <p class="logged-in-text">Logged in as <span class="user-role">{{roles}}</span></p>
+      </div>
     </div>
   } @else {
     <ng-container *ngTemplateOutlet="loggedOut"></ng-container>
   }
 
   <ng-template #loggedOut>
-    <div>
-      <form name="form" (ngSubmit)="f.form.valid && onSubmit()" #f="ngForm" novalidate>
-        <div>
-          <label for="username" id="username">Username</label>
-          <input type="text" name="username" [(ngModel)]="form.username" #username="ngModel" required>
+    <div class="login-card">
+      <div class="form-header">
+        <h1 class="form-title">Welcome Back</h1>
+        <p class="form-subtitle">Sign in to Better WIKAMP</p>
+      </div>
+      
+      <form class="login-form" name="form" (ngSubmit)="f.form.valid && onSubmit()" #f="ngForm" novalidate>
+        <div class="form-group">
+          <label class="form-label" for="username">Username</label>
+          <input 
+            type="text" 
+            id="username"
+            class="form-input" 
+            name="username" 
+            [(ngModel)]="form.username" 
+            #username="ngModel" 
+            required 
+            placeholder="Enter your username"
+          />
           @if (f.submitted && username.invalid) {
-            <div>
+            <div class="error-messages">
               @if (username.errors?.['required']) {
-                Username is required
+                <div class="error-message">Username is required</div>
               }
             </div>
           }
         </div>
-        <div>
-          <label for="password" id="password">Password</label>
-          <input type="password" name="password" [(ngModel)]="form.password" #password="ngModel"
-                 required minlength="6">
+
+        <div class="form-group">
+          <label class="form-label" for="password">Password</label>
+          <input 
+            type="password" 
+            id="password"
+            class="form-input" 
+            name="password" 
+            [(ngModel)]="form.password" 
+            #password="ngModel" 
+            required 
+            minlength="6" 
+            placeholder="Enter your password"
+          />
           @if (f.submitted && password.invalid) {
-            <div>
+            <div class="error-messages">
               @if (password.errors?.['required']) {
-                Password is required
+                <div class="error-message">Password is required</div>
               }
               @if (password.errors?.['minlength']) {
-                Password must be at least 6 characters
+                <div class="error-message">Password must be at least 6 characters</div>
               }
             </div>
           }
         </div>
-        <div>
-          <button>Login</button>
+
+        <div class="form-actions">
+          <button type="submit" class="submit-button">Sign In</button>
+          
           @if (f.submitted && isLoginFailed) {
-            <div>
-              Login failed. Please try again.
+            <div class="global-error">
+              <div class="error-text">
+                Login failed. Please check your credentials and try again.
+              </div>
             </div>
           }
         </div>
       </form>
-      <hr>
     </div>
   </ng-template>
-</div>
+</div>