monacousa-portal/pages/auth/login-mockup.vue

466 lines
8.9 KiB
Vue
Raw Normal View History

<template>
<div class="auth-page">
<div class="auth-container">
<!-- Left Panel - Form -->
<div
v-motion
:initial="{ opacity: 0, x: -50 }"
:enter="{ opacity: 1, x: 0 }"
class="auth-panel auth-panel--form"
>
<div class="auth-logo">
<img src="/logo.svg" alt="MonacoUSA" />
<h1>MonacoUSA Portal</h1>
</div>
<div class="auth-header">
<h2>Welcome Back</h2>
<p>Sign in to access your Monaco community</p>
</div>
<form class="auth-form" @submit.prevent="handleLogin">
<FloatingInput
v-model="form.email"
label="Email Address"
type="email"
variant="glass"
leftIcon="mail"
:error="errors.email"
required
/>
<FloatingInput
v-model="form.password"
label="Password"
type="password"
variant="glass"
leftIcon="lock"
:error="errors.password"
required
/>
<div class="auth-options">
<label class="checkbox-label">
<input type="checkbox" v-model="form.remember" />
<span>Remember me</span>
</label>
<a href="/auth/forgot-password" class="link">Forgot password?</a>
</div>
<MonacoButton
type="submit"
variant="primary"
size="lg"
block
:loading="loading"
>
Sign In
</MonacoButton>
<div class="auth-divider">
<span>or continue with</span>
</div>
<div class="social-buttons">
<button type="button" class="social-button">
<Icon name="globe" />
<span>Google</span>
</button>
<button type="button" class="social-button">
<Icon name="briefcase" />
<span>LinkedIn</span>
</button>
</div>
</form>
<div class="auth-footer">
<p>Don't have an account? <a href="/auth/signup" class="link">Sign up</a></p>
</div>
</div>
<!-- Right Panel - Visual -->
<div
v-motion
:initial="{ opacity: 0, x: 50 }"
:enter="{ opacity: 1, x: 0, transition: { delay: 200 } }"
class="auth-panel auth-panel--visual"
>
<div class="visual-content">
<div class="visual-gradient"></div>
<div class="visual-pattern"></div>
<div class="visual-text">
<h3>Connect with Monaco's Elite Business Community</h3>
<p>Join exclusive events, network with leaders, and grow your business in the heart of luxury and innovation.</p>
<div class="stats">
<div class="stat">
<span class="stat__value">500+</span>
<span class="stat__label">Members</span>
</div>
<div class="stat">
<span class="stat__value">50+</span>
<span class="stat__label">Events/Year</span>
</div>
<div class="stat">
<span class="stat__value">25+</span>
<span class="stat__label">Countries</span>
</div>
</div>
</div>
<div class="visual-decoration">
<div class="decoration-circle decoration-circle--1"></div>
<div class="decoration-circle decoration-circle--2"></div>
<div class="decoration-circle decoration-circle--3"></div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import FloatingInput from '~/components/ui/FloatingInput.vue'
import MonacoButton from '~/components/ui/MonacoButton.vue'
import Icon from '~/components/ui/Icon.vue'
const form = ref({
email: '',
password: '',
remember: false
})
const errors = ref({
email: '',
password: ''
})
const loading = ref(false)
const handleLogin = async () => {
loading.value = true
errors.value = { email: '', password: '' }
// Simulate API call
setTimeout(() => {
loading.value = false
console.log('Login with:', form.value)
}, 2000)
}
</script>
<style scoped lang="scss">
.auth-page {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #fef2f2 0%, #ffffff 100%);
padding: 2rem;
}
.auth-container {
display: grid;
grid-template-columns: 1fr 1fr;
max-width: 1200px;
width: 100%;
min-height: 700px;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(20px);
border-radius: 24px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.auth-panel {
padding: 3rem;
display: flex;
flex-direction: column;
&--form {
justify-content: center;
}
&--visual {
background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
position: relative;
overflow: hidden;
}
}
.auth-logo {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 3rem;
img {
width: 48px;
height: 48px;
}
h1 {
margin: 0;
font-size: 1.5rem;
font-weight: 700;
color: #dc2626;
}
}
.auth-header {
margin-bottom: 2rem;
h2 {
margin: 0 0 0.5rem;
font-size: 2rem;
font-weight: 700;
color: #27272a;
}
p {
margin: 0;
color: #6b7280;
}
}
.auth-form {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.auth-options {
display: flex;
justify-content: space-between;
align-items: center;
}
.checkbox-label {
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
input[type="checkbox"] {
width: 1.25rem;
height: 1.25rem;
accent-color: #dc2626;
cursor: pointer;
}
span {
font-size: 0.875rem;
color: #6b7280;
}
}
.link {
color: #dc2626;
text-decoration: none;
font-size: 0.875rem;
font-weight: 500;
transition: opacity 0.2s;
&:hover {
opacity: 0.8;
text-decoration: underline;
}
}
.auth-divider {
position: relative;
text-align: center;
margin: 1rem 0;
span {
position: relative;
padding: 0 1rem;
background: white;
color: #a3a3a3;
font-size: 0.875rem;
}
&::before {
content: '';
position: absolute;
left: 0;
right: 0;
top: 50%;
height: 1px;
background: #e5e5e5;
}
}
.social-buttons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.social-button {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.75rem;
background: white;
border: 2px solid #e5e5e5;
border-radius: 12px;
font-size: 0.875rem;
font-weight: 500;
color: #27272a;
cursor: pointer;
transition: all 0.2s;
&:hover {
background: #f5f5f5;
border-color: #dc2626;
transform: translateY(-2px);
}
}
.auth-footer {
margin-top: 2rem;
text-align: center;
p {
margin: 0;
font-size: 0.875rem;
color: #6b7280;
}
}
.visual-content {
position: relative;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
color: white;
z-index: 1;
}
.visual-gradient {
position: absolute;
inset: 0;
background: linear-gradient(
135deg,
rgba(255, 255, 255, 0.1) 0%,
transparent 100%
);
z-index: 1;
}
.visual-pattern {
position: absolute;
inset: 0;
opacity: 0.1;
background-image: repeating-linear-gradient(
45deg,
transparent,
transparent 35px,
rgba(255, 255, 255, 0.1) 35px,
rgba(255, 255, 255, 0.1) 70px
);
z-index: 0;
}
.visual-text {
position: relative;
z-index: 2;
h3 {
margin: 0 0 1rem;
font-size: 2rem;
font-weight: 700;
}
p {
margin: 0 0 3rem;
font-size: 1.125rem;
opacity: 0.95;
line-height: 1.6;
}
}
.stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
.stat {
display: flex;
flex-direction: column;
&__value {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 0.25rem;
}
&__label {
font-size: 0.875rem;
opacity: 0.9;
}
}
.visual-decoration {
position: absolute;
inset: 0;
z-index: 0;
overflow: hidden;
}
.decoration-circle {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.05);
&--1 {
width: 300px;
height: 300px;
top: -150px;
right: -150px;
}
&--2 {
width: 200px;
height: 200px;
bottom: -100px;
left: -100px;
}
&--3 {
width: 150px;
height: 150px;
top: 50%;
right: 10%;
transform: translateY(-50%);
}
}
// Responsive
@media (max-width: 1024px) {
.auth-container {
grid-template-columns: 1fr;
max-width: 500px;
}
.auth-panel--visual {
display: none;
}
}
@media (max-width: 640px) {
.auth-panel {
padding: 2rem;
}
.social-buttons {
grid-template-columns: 1fr;
}
}
</style>