monacousa-portal/design-mockups/pages/auth/ProfessionalLogin.vue

419 lines
11 KiB
Vue

<template>
<div class="login-page">
<div class="login-container">
<!-- Left Side - Branding -->
<div class="login-branding">
<div class="branding-content">
<div class="logo-container">
<img src="/MONACOUSA-Flags_376x376.png" alt="MonacoUSA" class="logo" />
</div>
<h1 class="brand-title">MonacoUSA Portal</h1>
<p class="brand-tagline">Excellence in Partnership</p>
<div class="feature-list">
<div class="feature-item" v-for="feature in features" :key="feature">
<svg class="feature-icon" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
<span>{{ feature }}</span>
</div>
</div>
</div>
<!-- Background pattern -->
<div class="branding-pattern"></div>
</div>
<!-- Right Side - Login Form -->
<div class="login-form-section">
<NeumorphicCard size="lg" elevation="lg" class="login-card">
<template #header>
<h2 class="login-title">Welcome Back</h2>
<p class="login-subtitle">Sign in to access your account</p>
</template>
<form @submit.prevent="handleLogin" class="login-form">
<div class="form-group">
<label for="email" class="form-label">Email Address</label>
<div class="input-wrapper">
<input
id="email"
v-model="credentials.email"
type="email"
class="form-input"
placeholder="you@example.com"
required
/>
<span class="input-icon">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
</span>
</div>
</div>
<div class="form-group">
<label for="password" class="form-label">Password</label>
<div class="input-wrapper">
<input
id="password"
v-model="credentials.password"
:type="showPassword ? 'text' : 'password'"
class="form-input"
placeholder="Enter your password"
required
/>
<button
type="button"
@click="showPassword = !showPassword"
class="input-icon clickable"
>
<svg v-if="!showPassword" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
</svg>
<svg v-else fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21" />
</svg>
</button>
</div>
</div>
<div class="form-options">
<label class="checkbox-label">
<input v-model="credentials.rememberMe" type="checkbox" class="checkbox-input" />
<span>Remember me</span>
</label>
<button type="button" class="forgot-password-link" @click="showForgotPassword = true">
Forgot password?
</button>
</div>
<ProfessionalButton
type="submit"
variant="primary"
size="lg"
block
:loading="loading"
class="login-button"
>
Sign In
</ProfessionalButton>
</form>
<template #footer>
<div class="login-footer">
<p class="signup-prompt">
Don't have an account?
<a href="/signup" class="signup-link">Create Account</a>
</p>
</div>
</template>
</NeumorphicCard>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import NeumorphicCard from '../../components/core/NeumorphicCard.vue';
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
// Data
const credentials = ref({
email: '',
password: '',
rememberMe: false
});
const showPassword = ref(false);
const loading = ref(false);
const showForgotPassword = ref(false);
const features = [
'Secure Member Access',
'Event Management',
'Document Library',
'Payment Processing'
];
// Methods
const handleLogin = async () => {
loading.value = true;
// Simulate API call
setTimeout(() => {
loading.value = false;
console.log('Login with:', credentials.value);
}, 2000);
};
</script>
<style lang="scss" scoped>
@import '../../styles/neumorphic-system.scss';
.login-page {
min-height: 100vh;
background: linear-gradient(135deg, $neutral-50 0%, $neutral-100 100%);
display: flex;
align-items: center;
justify-content: center;
}
.login-container {
width: 100%;
max-width: 1400px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1fr;
min-height: 100vh;
@media (max-width: $breakpoint-md) {
grid-template-columns: 1fr;
}
}
// Left side - Branding
.login-branding {
position: relative;
background: linear-gradient(135deg, $primary-600, $primary-800);
display: flex;
align-items: center;
justify-content: center;
padding: $space-12;
overflow: hidden;
@media (max-width: $breakpoint-md) {
display: none;
}
.branding-content {
position: relative;
z-index: 2;
text-align: center;
color: white;
}
.logo-container {
width: 120px;
height: 120px;
margin: 0 auto $space-6;
background: white;
border-radius: $radius-2xl;
padding: $space-4;
box-shadow: $shadow-soft-lg;
.logo {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.brand-title {
font-family: $font-heading;
font-size: $text-3xl;
font-weight: $font-bold;
margin-bottom: $space-2;
letter-spacing: -0.025em;
}
.brand-tagline {
font-size: $text-lg;
opacity: 0.9;
margin-bottom: $space-12;
}
.feature-list {
text-align: left;
max-width: 300px;
margin: 0 auto;
}
.feature-item {
display: flex;
align-items: center;
gap: $space-3;
margin-bottom: $space-4;
font-size: $text-base;
.feature-icon {
width: 20px;
height: 20px;
flex-shrink: 0;
color: rgba(white, 0.9);
}
}
.branding-pattern {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.05'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
opacity: 0.5;
}
}
// Right side - Login form
.login-form-section {
display: flex;
align-items: center;
justify-content: center;
padding: $space-8;
.login-card {
width: 100%;
max-width: 480px;
}
.login-title {
font-family: $font-heading;
font-size: $text-2xl;
font-weight: $font-bold;
color: $neutral-800;
margin-bottom: $space-2;
}
.login-subtitle {
font-size: $text-base;
color: $neutral-600;
}
.login-form {
.form-group {
margin-bottom: $space-5;
}
.form-label {
display: block;
font-size: $text-sm;
font-weight: $font-medium;
color: $neutral-700;
margin-bottom: $space-2;
}
.input-wrapper {
position: relative;
}
.form-input {
width: 100%;
padding: $space-3 $space-4;
padding-right: $space-12;
background: $neutral-50;
border: none;
border-radius: $radius-lg;
box-shadow: $shadow-inset-sm;
font-size: $text-base;
color: $neutral-800;
transition: all $transition-base;
&::placeholder {
color: $neutral-400;
}
&:focus {
outline: none;
box-shadow: $shadow-inset-md, 0 0 0 3px rgba($primary-500, 0.1);
}
}
.input-icon {
position: absolute;
right: $space-3;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
color: $neutral-400;
&.clickable {
cursor: pointer;
background: none;
border: none;
padding: 0;
transition: color $transition-base;
&:hover {
color: $neutral-600;
}
}
}
.form-options {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: $space-6;
}
.checkbox-label {
display: flex;
align-items: center;
gap: $space-2;
font-size: $text-sm;
color: $neutral-700;
cursor: pointer;
.checkbox-input {
width: 18px;
height: 18px;
border-radius: $radius-sm;
cursor: pointer;
}
}
.forgot-password-link {
background: none;
border: none;
color: $primary-600;
font-size: $text-sm;
font-weight: $font-medium;
cursor: pointer;
padding: 0;
transition: color $transition-base;
&:hover {
color: $primary-700;
text-decoration: underline;
}
}
.login-button {
margin-top: $space-4;
}
}
.login-footer {
text-align: center;
.signup-prompt {
font-size: $text-sm;
color: $neutral-600;
}
.signup-link {
color: $primary-600;
font-weight: $font-medium;
text-decoration: none;
margin-left: $space-1;
transition: color $transition-base;
&:hover {
color: $primary-700;
text-decoration: underline;
}
}
}
}
// Dark mode support
@include dark-mode {
.login-page {
background: linear-gradient(135deg, $neutral-900 0%, $neutral-800 100%);
}
}
</style>