Remove multiple login and signup templates from expert_theme, consolidating to a more streamlined design approach.

This commit is contained in:
Altahir Hassan 2026-01-05 15:58:18 +04:00
parent 01b9498193
commit 575bb504ee
15 changed files with 737 additions and 2473 deletions

View File

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
{ {
'name': 'Expert Theme', 'name': 'Expert Theme',
'version': '18.0.1.0.0', 'version': '1.0.0',
'category': 'Theme/Backend', 'category': 'Themes',
'summary': 'Custom backend theme with installed modules home page', 'summary': 'Custom backend theme with installed modules home page',
'description': """ 'description': """
Expert Theme Expert Theme
@ -14,8 +14,8 @@
- Easy navigation to installed applications - Easy navigation to installed applications
""", """,
'author': 'Expert', 'author': 'Expert',
'website': '', 'website': 'https://www.exp-sa.com',
'depends': ['base', 'web'], 'depends': ['base', 'web','website'],
'data': [ 'data': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'data/expert_login_template_data.xml', 'data/expert_login_template_data.xml',
@ -26,21 +26,21 @@
'views/expert_menu_views.xml', 'views/expert_menu_views.xml',
], ],
'assets': { 'assets': {
'web.assets_frontend': [
'expert_theme/static/src/scss/login_modern.scss',
'expert_theme/static/src/scss/expert_login.scss',
'expert_theme/static/src/scss/login_minimal.scss',
'expert_theme/static/src/js/expert_login_template.js',
],
'web.assets_backend': [ 'web.assets_backend': [
'expert_theme/static/src/css/expert_theme_config.css', 'expert_theme/static/src/scss/expert_theme_config.scss',
'expert_theme/static/src/css/expert_theme.css', 'expert_theme/static/src/scss/expert_theme.scss',
'expert_theme/static/src/js/expert_theme_dynamic.js', 'expert_theme/static/src/js/expert_theme_dynamic.js',
'expert_theme/static/src/js/expert_theme_config.js', 'expert_theme/static/src/js/expert_theme_config.js',
'expert_theme/static/src/js/expert_home.js', 'expert_theme/static/src/js/expert_home.js',
'expert_theme/static/src/js/expert_login_template_list.js', 'expert_theme/static/src/js/expert_login_template_list.js',
'expert_theme/static/src/xml/expert_home.xml', 'expert_theme/static/src/xml/expert_home.xml',
], ]
'web.assets_frontend': [
'expert_theme/static/src/css/expert_login.css',
'expert_theme/static/src/css/login_modern.css',
'expert_theme/static/src/css/login_minimal.css',
'expert_theme/static/src/js/expert_login_template.js',
],
}, },
'installable': True, 'installable': True,
'auto_install': False, 'auto_install': False,

View File

@ -55,46 +55,6 @@ class ExpertController(http.Controller):
'error': str(e) 'error': str(e)
}) })
@http.route('/web/login', type='http', auth='none', methods=['GET', 'POST'], csrf=False)
def web_login(self, redirect=None, **kw):
"""Override Odoo login to use expert login templates when configured.
- POST: delegate to standard Odoo login logic (authentication, redirects, etc.).
- GET: render the active expert login template if not 'default', otherwise use standard login.
"""
# Import Home from its new location in Odoo 18
from odoo.addons.web.controllers.home import Home
# Handle login submission via standard controller
if request.httprequest.method == 'POST':
home = Home()
return home.web_login(redirect=redirect, **kw)
# GET: decide which template to render
try:
login_template = request.env['expert.login.template'].sudo().get_active_template()
template_name = login_template.get_template_name()
except Exception as e:
_logger.error("Error getting active login template: %s", e)
template_name = 'web.login'
# For default template, just call the standard login
if template_name == 'web.login':
home = Home()
return home.web_login(redirect=redirect, **kw)
# Try to render the selected expert template; fall back to default on error
try:
return request.render(template_name, {
'redirect': redirect or '',
'login': kw.get('login', ''),
'login_template': login_template,
})
except Exception as e:
_logger.error("Error rendering login template '%s': %s", template_name, e)
home = Home()
return home.web_login(redirect=redirect, **kw)
@http.route('/expert_theme/get_login_template_styles', type='http', auth='public', methods=['GET']) @http.route('/expert_theme/get_login_template_styles', type='http', auth='public', methods=['GET'])
def get_login_template_styles(self): def get_login_template_styles(self):
"""Get CSS styles for the active login template (public access for login page)""" """Get CSS styles for the active login template (public access for login page)"""
@ -181,106 +141,4 @@ class ExpertController(http.Controller):
'error': str(e) 'error': str(e)
}) })
@http.route('/web/signup', type='http', auth='public', methods=['GET', 'POST'], website=True, csrf=False)
def web_auth_signup(self, redirect=None, **kw):
"""Override Odoo signup to use expert signup templates when modern template is active.
- POST: delegate to standard Odoo signup logic (authentication, redirects, etc.).
- GET: render the active expert signup template if modern template is active, otherwise use standard signup.
"""
# Import AuthSignupHome from auth_signup module
try:
from odoo.addons.auth_signup.controllers.main import AuthSignupHome
except ImportError:
# If auth_signup is not installed, return 404
from werkzeug.exceptions import NotFound
raise NotFound()
# Handle signup submission via standard controller
if request.httprequest.method == 'POST':
auth_signup_home = AuthSignupHome()
return auth_signup_home.web_auth_signup(redirect=redirect, **kw)
# GET: decide which template to render
try:
login_template = request.env['expert.login.template'].sudo().get_active_template()
template_name = login_template.get_signup_template_name()
except Exception as e:
_logger.error("Error getting active signup template: %s", e)
template_name = 'auth_signup.signup'
# For default template, just call the standard signup
if template_name == 'auth_signup.signup':
auth_signup_home = AuthSignupHome()
return auth_signup_home.web_auth_signup(redirect=redirect, **kw)
# Try to render the selected expert template; fall back to default on error
try:
# Get signup context from auth_signup
auth_signup_home = AuthSignupHome()
qcontext = auth_signup_home.get_auth_signup_qcontext()
qcontext.update({
'redirect': redirect or '',
'login': kw.get('login', ''),
'login_template': login_template,
})
response = request.render(template_name, qcontext)
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
response.headers['Content-Security-Policy'] = "frame-ancestors 'self'"
return response
except Exception as e:
_logger.error("Error rendering signup template '%s': %s", template_name, e)
auth_signup_home = AuthSignupHome()
return auth_signup_home.web_auth_signup(redirect=redirect, **kw)
@http.route('/web/reset_password', type='http', auth='public', methods=['GET', 'POST'], website=True, csrf=False)
def web_auth_reset_password(self, redirect=None, **kw):
"""Override Odoo reset password to use expert reset password templates when modern template is active.
- POST: delegate to standard Odoo reset password logic (authentication, redirects, etc.).
- GET: render the active expert reset password template if modern template is active, otherwise use standard reset password.
"""
# Import AuthSignupHome from auth_signup module
try:
from odoo.addons.auth_signup.controllers.main import AuthSignupHome
except ImportError:
# If auth_signup is not installed, return 404
from werkzeug.exceptions import NotFound
raise NotFound()
# Handle reset password submission via standard controller
if request.httprequest.method == 'POST':
auth_signup_home = AuthSignupHome()
return auth_signup_home.web_auth_reset_password(redirect=redirect, **kw)
# GET: decide which template to render
try:
login_template = request.env['expert.login.template'].sudo().get_active_template()
template_name = login_template.get_reset_password_template_name()
except Exception as e:
_logger.error("Error getting active reset password template: %s", e)
template_name = 'auth_signup.reset_password'
# For default template, just call the standard reset password
if template_name == 'auth_signup.reset_password':
auth_signup_home = AuthSignupHome()
return auth_signup_home.web_auth_reset_password(redirect=redirect, **kw)
# Try to render the selected expert template; fall back to default on error
try:
# Get reset password context from auth_signup
auth_signup_home = AuthSignupHome()
qcontext = auth_signup_home.get_auth_signup_qcontext()
qcontext.update({
'redirect': redirect or '',
'login': kw.get('login', ''),
'login_template': login_template,
})
response = request.render(template_name, qcontext)
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
response.headers['Content-Security-Policy'] = "frame-ancestors 'self'"
return response
except Exception as e:
_logger.error("Error rendering reset password template '%s': %s", template_name, e)
auth_signup_home = AuthSignupHome()
return auth_signup_home.web_auth_reset_password(redirect=redirect, **kw)

View File

@ -9,7 +9,7 @@ class ExpertLoginTemplate(models.Model):
_rec_name = 'name' _rec_name = 'name'
_order = 'sequence, name' _order = 'sequence, name'
name = fields.Char(string='Template Name', required=True, help='Name of the login page template') name = fields.Char(string='Template Name', required=True, translate=True, help='Name of the login page template')
active = fields.Boolean(string='Active', default=False, help='Only one template can be active at a time. Activate this template to use it on the login page.') active = fields.Boolean(string='Active', default=False, help='Only one template can be active at a time. Activate this template to use it on the login page.')
sequence = fields.Integer(string='Sequence', default=10, help='Order of display') sequence = fields.Integer(string='Sequence', default=10, help='Order of display')
@ -37,47 +37,47 @@ class ExpertLoginTemplate(models.Model):
corporate_template_logo = fields.Binary(string='Corporate Template Logo', help='Company logo to display on Corporate login, signup, and reset password pages') corporate_template_logo = fields.Binary(string='Corporate Template Logo', help='Company logo to display on Corporate login, signup, and reset password pages')
# Modern Template Text Fields # Modern Template Text Fields
modern_login_title = fields.Char(string='Login Title', default='Welcome to Expert 👋', help='Title text for Modern template login page') modern_login_title = fields.Char(string='Login Title', default='Welcome to Expert 👋', translate=True, help='Title text for Modern template login page')
modern_login_subtitle = fields.Char(string='Login Subtitle', default='Kindly fill in your details below to sign in to your account', help='Subtitle text for Modern template login page') modern_login_subtitle = fields.Char(string='Login Subtitle', default='Kindly fill in your details below to sign in to your account', translate=True, help='Subtitle text for Modern template login page')
modern_login_button_text = fields.Char(string='Login Button Text', default='Sign In', help='Button text for Modern template login page') modern_login_button_text = fields.Char(string='Login Button Text', default='Sign In', translate=True, help='Button text for Modern template login page')
modern_login_button_bg_color = fields.Char(string='Login Button Background', default='#007bff', help='Background color for login button') modern_login_button_bg_color = fields.Char(string='Login Button Background', default='#007bff', help='Background color for login button')
modern_login_button_text_color = fields.Char(string='Login Button Text Color', default='#FFFFFF', help='Text color for login button') modern_login_button_text_color = fields.Char(string='Login Button Text Color', default='#FFFFFF', help='Text color for login button')
modern_login_button_bg_hover = fields.Char(string='Login Button BG Hover', default='#0056b3', help='Background color for login button on hover') modern_login_button_bg_hover = fields.Char(string='Login Button BG Hover', default='#0056b3', help='Background color for login button on hover')
modern_login_button_text_hover = fields.Char(string='Login Button Text Hover', default='#FFFFFF', help='Text color for login button on hover') modern_login_button_text_hover = fields.Char(string='Login Button Text Hover', default='#FFFFFF', help='Text color for login button on hover')
modern_signup_title = fields.Char(string='Signup Title', default='Create an account', help='Title text for Modern template signup page') modern_signup_title = fields.Char(string='Signup Title', default='Create an account', translate=True, help='Title text for Modern template signup page')
modern_signup_subtitle = fields.Char(string='Signup Subtitle', default='Join us today and get started', help='Subtitle text for Modern template signup page') modern_signup_subtitle = fields.Char(string='Signup Subtitle', default='Join us today and get started', translate=True, help='Subtitle text for Modern template signup page')
modern_signup_button_text = fields.Char(string='Signup Button Text', default='Create an account', help='Button text for Modern template signup page') modern_signup_button_text = fields.Char(string='Signup Button Text', default='Create an account', translate=True, help='Button text for Modern template signup page')
modern_signup_button_bg_color = fields.Char(string='Signup Button Background', default='#28a745', help='Background color for signup button') modern_signup_button_bg_color = fields.Char(string='Signup Button Background', default='#28a745', help='Background color for signup button')
modern_signup_button_text_color = fields.Char(string='Signup Button Text Color', default='#FFFFFF', help='Text color for signup button') modern_signup_button_text_color = fields.Char(string='Signup Button Text Color', default='#FFFFFF', help='Text color for signup button')
modern_signup_button_bg_hover = fields.Char(string='Signup Button BG Hover', default='#218838', help='Background color for signup button on hover') modern_signup_button_bg_hover = fields.Char(string='Signup Button BG Hover', default='#218838', help='Background color for signup button on hover')
modern_signup_button_text_hover = fields.Char(string='Signup Button Text Hover', default='#FFFFFF', help='Text color for signup button on hover') modern_signup_button_text_hover = fields.Char(string='Signup Button Text Hover', default='#FFFFFF', help='Text color for signup button on hover')
modern_reset_title = fields.Char(string='Reset Password Title', default='Reset your password', help='Title text for Modern template reset password page') modern_reset_title = fields.Char(string='Reset Password Title', default='Reset your password', translate=True, help='Title text for Modern template reset password page')
modern_reset_subtitle = fields.Char(string='Reset Password Subtitle', default='Enter your email to receive reset instructions', help='Subtitle text for Modern template reset password page') modern_reset_subtitle = fields.Char(string='Reset Password Subtitle', default='Enter your email to receive reset instructions', translate=True, help='Subtitle text for Modern template reset password page')
# Minimal Template Text Fields # Minimal Template Text Fields
minimal_login_title = fields.Char(string='Login Title', default='Welcome to Expert 👋', help='Title text for Minimal template login page') minimal_login_title = fields.Char(string='Login Title', default='Welcome to Expert 👋', translate=True, help='Title text for Minimal template login page')
minimal_login_subtitle = fields.Char(string='Login Subtitle', default='Kindly fill in your details below to sign in to your account', help='Subtitle text for Minimal template login page') minimal_login_subtitle = fields.Char(string='Login Subtitle', default='Kindly fill in your details below to sign in to your account', translate=True, help='Subtitle text for Minimal template login page')
minimal_login_button_text = fields.Char(string='Login Button Text', default='Sign In', help='Button text for Minimal template login page') minimal_login_button_text = fields.Char(string='Login Button Text', default='Sign In', translate=True, help='Button text for Minimal template login page')
minimal_login_button_bg_color = fields.Char(string='Login Button Background', default='#E5E5E5', help='Background color for login button') minimal_login_button_bg_color = fields.Char(string='Login Button Background', default='#E5E5E5', help='Background color for login button')
minimal_login_button_text_color = fields.Char(string='Login Button Text Color', default='#000000', help='Text color for login button') minimal_login_button_text_color = fields.Char(string='Login Button Text Color', default='#000000', help='Text color for login button')
minimal_login_button_bg_hover = fields.Char(string='Login Button BG Hover', default='#D0D0D0', help='Background color for login button on hover') minimal_login_button_bg_hover = fields.Char(string='Login Button BG Hover', default='#D0D0D0', help='Background color for login button on hover')
minimal_login_button_text_hover = fields.Char(string='Login Button Text Hover', default='#000000', help='Text color for login button on hover') minimal_login_button_text_hover = fields.Char(string='Login Button Text Hover', default='#000000', help='Text color for login button on hover')
minimal_signup_title = fields.Char(string='Signup Title', default='Create an account', help='Title text for Minimal template signup page') minimal_signup_title = fields.Char(string='Signup Title', default='Create an account', translate=True, help='Title text for Minimal template signup page')
minimal_signup_subtitle = fields.Char(string='Signup Subtitle', default='Join us today and get started', help='Subtitle text for Minimal template signup page') minimal_signup_subtitle = fields.Char(string='Signup Subtitle', default='Join us today and get started', translate=True, help='Subtitle text for Minimal template signup page')
minimal_signup_button_text = fields.Char(string='Signup Button Text', default='Create an account', help='Button text for Minimal template signup page') minimal_signup_button_text = fields.Char(string='Signup Button Text', default='Create an account', translate=True, help='Button text for Minimal template signup page')
minimal_signup_button_bg_color = fields.Char(string='Signup Button Background', default='#000000', help='Background color for signup button') minimal_signup_button_bg_color = fields.Char(string='Signup Button Background', default='#000000', help='Background color for signup button')
minimal_signup_button_text_color = fields.Char(string='Signup Button Text Color', default='#FFFFFF', help='Text color for signup button') minimal_signup_button_text_color = fields.Char(string='Signup Button Text Color', default='#FFFFFF', help='Text color for signup button')
minimal_signup_button_bg_hover = fields.Char(string='Signup Button BG Hover', default='#333333', help='Background color for signup button on hover') minimal_signup_button_bg_hover = fields.Char(string='Signup Button BG Hover', default='#333333', help='Background color for signup button on hover')
minimal_signup_button_text_hover = fields.Char(string='Signup Button Text Hover', default='#FFFFFF', help='Text color for signup button on hover') minimal_signup_button_text_hover = fields.Char(string='Signup Button Text Hover', default='#FFFFFF', help='Text color for signup button on hover')
minimal_reset_title = fields.Char(string='Reset Password Title', default='Reset your password', help='Title text for Minimal template reset password page') minimal_reset_title = fields.Char(string='Reset Password Title', default='Reset your password', translate=True, help='Title text for Minimal template reset password page')
minimal_reset_subtitle = fields.Char(string='Reset Password Subtitle', default='Enter your email to receive reset instructions', help='Subtitle text for Minimal template reset password page') minimal_reset_subtitle = fields.Char(string='Reset Password Subtitle', default='Enter your email to receive reset instructions', translate=True, help='Subtitle text for Minimal template reset password page')
# Description # Description
description = fields.Text(string='Description', help='Description of this template') description = fields.Text(string='Description', translate=True, help='Description of this template')
@api.model @api.model
def get_active_template(self): def get_active_template(self):
@ -111,13 +111,14 @@ class ExpertLoginTemplate(models.Model):
def create(self, vals): def create(self, vals):
"""Ensure only one template is active at a time""" """Ensure only one template is active at a time"""
# If no active value is set, default to False (don't auto-activate new templates) # If no active value is set, default to False (don't auto-activate new templates)
if 'active' not in vals: if 'active' not in vals[0]:
vals['active'] = False vals[0]['active'] = False
# Only deactivate others if this one is being set to active # Only deactivate others if this one is being set to active
if vals.get('active'): print(vals[0])
if vals[0].get('active'):
# Deactivate all other templates (excluding the one being created) # Deactivate all other templates (excluding the one being created)
self.search([('active', '=', True)]).write({'active': False}) self.search([('active', '=', True)]).write({'active': False})
return super(ExpertLoginTemplate, self).create(vals) return super(ExpertLoginTemplate, self).create(vals[0])
def write(self, vals): def write(self, vals):
"""Ensure only one template is active at a time""" """Ensure only one template is active at a time"""
@ -133,6 +134,7 @@ class ExpertLoginTemplate(models.Model):
super(ExpertLoginTemplate, other_templates).write({'active': False}) super(ExpertLoginTemplate, other_templates).write({'active': False})
need_reload = True need_reload = True
view = self.env.ref('custom_auth_theme.view_custom_login_inherit', raise_if_not_found=False)
result = super(ExpertLoginTemplate, self).write(vals) result = super(ExpertLoginTemplate, self).write(vals)
# Update template views if active state changed # Update template views if active state changed

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -1,269 +0,0 @@
/* Expert Theme - Minimal Login Template Styles */
.expert-login-minimal {
background: #FFFFFF;
min-height: 100vh;
padding: 20px;
}
.expert-login-minimal .container-fluid {
height: calc(100vh - 40px);
}
.expert-login-minimal .row {
height: 100%;
margin: 0;
}
/* Left Column: Login Form */
.expert-login-minimal .expert-login-left {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 40px;
text-align: center;
}
/* Logo Section */
.expert-login-minimal .expert-login-logo {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 40px;
width: 100%;
}
.expert-login-minimal .expert-login-logo .expert-logo-icon {
width: 40px;
height: 40px;
background: #000000;
border-radius: 8px;
margin-right: 12px;
display: flex;
align-items: center;
justify-content: center;
}
.expert-login-minimal .expert-login-logo .expert-logo-icon span {
color: white;
font-weight: bold;
font-size: 20px;
}
.expert-login-minimal .expert-login-logo .expert-logo-text {
color: #000000;
font-size: 20px;
font-weight: 600;
}
/* Welcome Section */
.expert-login-minimal .expert-login-welcome {
width: 100%;
text-align: center;
margin-bottom: 40px;
}
.expert-login-minimal .expert-login-welcome h1 {
color: #000000;
font-size: 32px;
font-weight: 700;
margin-bottom: 12px;
line-height: 1.2;
text-align: center;
}
.expert-login-minimal .expert-login-welcome h1 .welcome-emoji {
font-size: 32px;
}
.expert-login-minimal .expert-login-welcome p {
color: rgba(0, 0, 0, 0.7);
font-size: 16px;
margin-bottom: 0;
text-align: center;
}
/* Form Section */
.expert-login-minimal .expert-login-form {
max-width: 450px;
width: 100%;
margin: 0 auto;
background-color: transparent !important;
}
.expert-login-minimal .expert-login-form .form-group {
margin-bottom: 24px;
}
.expert-login-minimal .expert-login-form .form-group label {
font-weight: 500;
color: #000000;
display: block;
margin-bottom: 8px;
font-size: 14px;
text-align: start;
}
.expert-login-minimal .expert-login-form .form-group input[type="text"],
.expert-login-minimal .expert-login-form .form-group input[type="password"] {
background: #FFFFFF !important;
border: 1px solid #000000 !important;
border-radius: 8px;
padding: 12px 16px;
width: 100%;
box-sizing: border-box;
color: #000000 !important;
font-size: 14px;
}
.expert-login-minimal .expert-login-form .form-group input[type="text"]::placeholder,
.expert-login-minimal .expert-login-form .form-group input[type="password"]::placeholder {
color: rgba(0, 0, 0, 0.5) !important;
}
.expert-login-minimal .expert-login-form .form-group input[type="text"]:focus,
.expert-login-minimal .expert-login-form .form-group input[type="password"]:focus {
background: #FFFFFF !important;
border-color: #000000 !important;
outline: none;
color: #000000 !important;
}
.expert-login-minimal .expert-login-form .form-check {
margin-bottom: 32px;
}
.expert-login-minimal .expert-login-form .form-check label {
color: #000000;
display: flex;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
gap: 5px;
font-size: 14px;
cursor: pointer;
}
.expert-login-minimal .expert-login-form .form-check label input[type="checkbox"] {
margin-right: 8px;
width: 18px;
height: 18px;
cursor: pointer;
accent-color: #000000;
}
.expert-login-minimal .expert-login-form button[type="submit"] {
width: 100%;
background: #E5E5E5;
border: none;
border-radius: 8px;
padding: 14px;
font-weight: 600;
color: #000000;
font-size: 16px;
cursor: pointer;
transition: background 0.2s;
}
.expert-login-minimal .expert-login-form button[type="submit"]:hover {
background: #D5D5D5;
}
.expert-login-minimal .expert-login-form button[type="submit"]:active {
background: #CCCCCC;
}
/* Login Link Section */
.expert-login-minimal .expert-login-link {
margin-top: 24px;
max-width: 450px;
width: 100%;
text-align: center;
}
.expert-login-minimal .expert-login-link p {
color: rgba(0, 0, 0, 0.7);
font-size: 14px;
margin: 0;
}
.expert-login-minimal .expert-login-link p a {
color: #000000;
text-decoration: underline;
font-weight: 500;
}
.expert-login-minimal .expert-login-link p a:hover {
text-decoration: none;
}
/* Right Column: Image Section */
.expert-login-minimal .expert-login-right {
padding: 0;
height: 100%;
overflow: hidden;
border-radius: 0;
}
.expert-login-minimal .expert-login-right .expert-login-image {
width: 100%;
height: 100%;
background: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.expert-login-minimal .expert-login-right .expert-login-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.expert-login-minimal .expert-minimal-illustration {
width: 600px !important;
height: 600px !important;
object-fit: contain;
}
/* Alert Messages */
.expert-login-minimal .alert {
border-radius: 8px;
padding: 12px 16px;
margin-bottom: 20px;
text-align: start;
}
.expert-login-minimal .alert-danger {
background-color: #F8D7DA;
border: 1px solid #F5C6CB;
color: #721C24;
}
.expert-login-minimal .alert-success {
background-color: #D4EDDA;
border: 1px solid #C3E6CB;
color: #155724;
}
/* Responsive adjustments */
@media (max-width: 991.98px) {
.expert-login-minimal .expert-login-left {
padding: 30px 20px;
}
.expert-login-minimal .expert-login-welcome h1 {
font-size: 28px;
}
.expert-login-minimal .expert-login-welcome h1 .welcome-emoji {
font-size: 28px;
}
.expert-login-minimal .expert-login-welcome p {
font-size: 14px;
}
}

View File

@ -1,234 +0,0 @@
/* Expert Theme - Modern Login Template Styles */
.expert-login-modern {
background: #19181F !important;
min-height: 100vh;
padding: 20px;
}
.expert-login-modern .container-fluid {
height: calc(100vh - 40px);
}
.expert-login-modern .row {
height: 100%;
margin: 0;
}
/* Left Column: Login Form */
.expert-login-modern .expert-login-left {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 40px;
text-align: center;
}
/* Logo Section */
.expert-login-modern .expert-login-logo {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 40px;
width: 100%;
}
.expert-login-modern .expert-login-logo .expert-logo-icon {
width: 40px;
height: 40px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 8px;
margin-right: 12px;
display: flex;
align-items: center;
justify-content: center;
}
.expert-login-modern .expert-login-logo .expert-logo-icon span {
color: white;
font-weight: bold;
font-size: 20px;
}
.expert-login-modern .expert-login-logo .expert-logo-text {
color: white;
font-size: 20px;
font-weight: 600;
}
/* Welcome Section */
.expert-login-modern .expert-login-welcome {
width: 100%;
text-align: center;
}
.expert-login-modern .expert-login-welcome h1 {
color: white;
font-size: 36px;
font-weight: 700;
margin-bottom: 12px;
line-height: 1.2;
text-align: center;
}
.expert-login-modern .expert-login-welcome h1 .welcome-emoji {
font-size: 36px;
}
.expert-login-modern .expert-login-welcome p {
color: rgba(255, 255, 255, 0.7);
font-size: 16px;
margin-bottom: 40px;
text-align: center;
}
/* Form Section */
.expert-login-modern .expert-login-form {
max-width: 450px;
width: 100%;
margin: 0 auto;
background-color: transparent !important;
}
.expert-login-modern .expert-login-form .form-group {
margin-bottom: 24px;
}
.expert-login-modern .expert-login-form .form-group label {
font-weight: 500;
color: rgba(255, 255, 255, 0.9);
display: block;
margin-bottom: 8px;
font-size: 14px;
text-align: start;
}
.expert-login-modern .expert-login-form .form-group input[type="text"],
.expert-login-modern .expert-login-form .form-group input[type="password"] {
background: rgba(255, 255, 255, 0.1) !important;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
border-radius: 8px;
padding: 12px 16px;
width: 100%;
box-sizing: border-box;
color: white !important;
font-size: 14px;
}
.expert-login-modern .expert-login-form .form-group input[type="text"]::placeholder,
.expert-login-modern .expert-login-form .form-group input[type="password"]::placeholder {
color: rgba(255, 255, 255, 0.5) !important;
}
.expert-login-modern .expert-login-form .form-group input[type="text"]:focus,
.expert-login-modern .expert-login-form .form-group input[type="password"]:focus {
background: rgba(255, 255, 255, 0.15) !important;
border-color: rgba(255, 255, 255, 0.4) !important;
outline: none;
color: white !important;
}
.expert-login-modern .expert-login-form .form-check {
margin-bottom: 32px;
}
.expert-login-modern .expert-login-form .form-check label {
color: rgba(255, 255, 255, 0.8);
display: flex;
align-items: center;
justify-content: flex-start;
font-size: 14px;
cursor: pointer;
}
.expert-login-modern .expert-login-form .form-check label input[type="checkbox"] {
margin-right: 8px;
width: 18px;
height: 18px;
cursor: pointer;
accent-color: #667eea;
}
.expert-login-modern .expert-login-form button[type="submit"] {
width: 100%;
background: #764ba2;
border: none !important;
border-radius: 8px;
padding: 14px;
font-weight: 600;
color: white;
font-size: 16px;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.expert-login-modern .expert-login-form button[type="submit"]:hover {
transform: translateY(-2px);
}
/* Login Link Section */
.expert-login-modern .expert-login-link {
margin-top: 24px;
max-width: 450px;
width: 100%;
text-align: center;
}
.expert-login-modern .expert-login-link p {
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
margin: 0;
}
.expert-login-modern .expert-login-link p a {
color: #667eea;
text-decoration: none;
font-weight: 500;
}
.expert-login-modern .expert-login-link p a:hover {
text-decoration: underline;
}
/* Right Column: Image Section */
.expert-login-modern .expert-login-right {
padding: 0;
height: 100%;
overflow: hidden;
border-radius: 20px;
}
.expert-login-modern .expert-login-right .expert-login-image {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.expert-login-modern .expert-login-right .expert-login-image img {
width: 100% !important;
height: 100% !important;
object-fit: cover !important;
}
/* Responsive adjustments */
@media (max-width: 991.98px) {
.expert-login-modern .expert-login-left {
padding: 30px 20px;
}
.expert-login-modern .expert-login-welcome h1 {
font-size: 28px;
}
.expert-login-modern .expert-login-welcome h1 .welcome-emoji {
font-size: 28px;
}
.expert-login-modern .expert-login-welcome p {
font-size: 14px;
}
}

View File

@ -47,9 +47,9 @@
body { body {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important;
background: linear-gradient(135deg, var(--expert-bg-gradient-start, #f5f7fa) 0%, var(--expert-bg-gradient-end, #c3cfe2) 100%) !important; background: linear-gradient(135deg, var(--expert-bg-gradient-start, #f5f7fa) 0%, var(--expert-bg-gradient-end, #c3cfe2) 100%) !important;
min-height: 100vh !important; // min-height: 100vh !important;
margin: 0 !important; // margin: 0 !important;
padding: 0 !important; // padding: 0 !important;
} }
/* Ensure the gradient shows on the main content area */ /* Ensure the gradient shows on the main content area */
@ -58,7 +58,7 @@ body {
.o_action_manager .o_view_controller .o_content { .o_action_manager .o_view_controller .o_content {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important;
background: linear-gradient(135deg, var(--expert-bg-gradient-start, #f5f7fa) 0%, var(--expert-bg-gradient-end, #c3cfe2) 100%) !important; background: linear-gradient(135deg, var(--expert-bg-gradient-start, #f5f7fa) 0%, var(--expert-bg-gradient-end, #c3cfe2) 100%) !important;
min-height: 100vh !important; // min-height: 100vh !important;
} }
/* Override any Odoo background colors that might interfere */ /* Override any Odoo background colors that might interfere */

View File

@ -0,0 +1,280 @@
/* Expert Theme - Minimal Login Template Styles */
.expert-login-minimal {
background: #FFFFFF;
min-height: 100vh;
.expert-login-left {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
min-height: 100vh;
.expert-login-form-container {
max-width: 450px;
.expert-login-logo {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 40px;
width: 100%;
.expert-logo-icon {
width: 40px;
height: 40px;
background: #000000;
border-radius: 8px;
margin-right: 12px;
display: flex;
align-items: center;
justify-content: center;
span {
color: white;
font-weight: bold;
font-size: 20px;
}
}
.expert-logo-text {
color: #000000;
font-size: 20px;
font-weight: 600;
}
}
.expert-login-welcome {
width: 100%;
text-align: center;
margin-bottom: 40px;
h1 {
color: #000000;
font-size: 32px;
font-weight: 700;
margin-bottom: 12px;
line-height: 1.2;
text-align: center;
.welcome-emoji {
font-size: 32px;
}
}
p {
color: rgba(0, 0, 0, 0.7);
font-size: 16px;
margin-bottom: 0;
text-align: center;
}
}
.expert-login-form {
max-width: 450px;
width: 100%;
margin: 0 auto;
background-color: transparent !important;
.oe_login_form,
.oe_signup_form,
.oe_reset_password_form {
max-width: 450px;
background-color: transparent !important;
label {
font-weight: 500;
color: #000000;
display: block;
margin-bottom: 8px;
font-size: 14px;
text-align: start;
}
input {
&[type="text"],
&[type="password"] {
background: #FFFFFF !important;
border: 1px solid #000000 !important;
border-radius: 8px;
padding: 12px 16px;
width: 100%;
box-sizing: border-box;
color: #000000 !important;
font-size: 14px;
}
&[type="text"]::placeholder,
&[type="password"]::placeholder {
color: rgba(0, 0, 0, 0.5) !important;
}
&[type="text"]:focus,
&[type="password"]:focus {
background: #FFFFFF !important;
border-color: #000000 !important;
outline: none;
color: #000000 !important;
}
}
}
.form-check {
margin-bottom: 32px;
label {
color: #000000;
display: flex;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
gap: 5px;
font-size: 14px;
cursor: pointer;
input[type="checkbox"] {
margin-right: 8px;
width: 18px;
height: 18px;
cursor: pointer;
accent-color: #000000;
}
}
}
.btn-link {
color: #5a5a5a;
}
.btn-primary {
width: 100%;
background: #E5E5E5;
border: none;
border-radius: 8px;
padding: 14px;
font-weight: 600;
color: #000000;
font-size: 16px;
cursor: pointer;
transition: background 0.2s;
margin-bottom: 10px;
&:hover {
background: #D5D5D5;
}
&:active {
background: #CCCCCC;
}
}
}
.expert-login-link {
margin-top: 24px;
max-width: 450px;
width: 100%;
text-align: center;
p {
color: rgba(0, 0, 0, 0.7);
font-size: 14px;
margin: 0;
a {
color: #000000;
text-decoration: underline;
font-weight: 500;
&:hover {
text-decoration: none;
}
}
}
}
}
}
.expert-login-right {
padding: 0;
height: 100%;
overflow: hidden;
min-height: 100vh;
.expert-login-image {
width: 100%;
min-height: 100vh;
background: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
}
}
.expert-minimal-illustration {
width: 600px !important;
height: 600px !important;
object-fit: contain;
}
.alert {
border-radius: 8px;
padding: 12px 16px;
margin-bottom: 20px;
text-align: start;
}
.alert-danger {
background-color: #F8D7DA;
border: 1px solid #F5C6CB;
color: #721C24;
}
.alert-success {
background-color: #D4EDDA;
border: 1px solid #C3E6CB;
color: #155724;
}
}
/* Left Column: Login Form */
/* Logo Section */
/* Welcome Section */
/* Form Section */
/* Login Link Section */
/* Right Column: Image Section */
/* Alert Messages */
/* Responsive adjustments */
@media (max-width: 991.98px) {
.expert-login-minimal {
.expert-login-left {
padding: 30px 20px;
}
.expert-login-welcome {
h1 {
font-size: 28px;
.welcome-emoji {
font-size: 28px;
}
}
p {
font-size: 14px;
}
}
}
}

View File

@ -1,26 +1,18 @@
/* Expert Theme - Modern Login Template Styles */ /* Expert Theme - Modern Login Template Styles */
.expert-login-modern { .expert-login-modern {
background: #19181F; background: #19181F;
min-height: 100vh; min-height: 100vh;
padding: 20px; padding: 20px;
.container-fluid {
height: calc(100vh - 40px);
}
.row {
height: 100%;
margin: 0;
}
// Left Column: Login Form // Left Column: Login Form
.expert-login-left { .expert-login-left {
display: flex; display: flex;
flex-direction: column;
justify-content: center; justify-content: center;
padding: 40px; align-items: center;
} min-height: 100vh;
.expert-login-form-container {
max-width: 450px;
// Logo Section // Logo Section
.expert-login-logo { .expert-login-logo {
@ -51,6 +43,7 @@
font-weight: 600; font-weight: 600;
} }
} }
}
// Welcome Section // Welcome Section
.expert-login-welcome { .expert-login-welcome {
@ -75,11 +68,14 @@
// Form Section // Form Section
.expert-login-form { .expert-login-form {
.oe_login_form,
.oe_signup_form,
.oe_reset_password_form {
max-width: 450px; max-width: 450px;
background-color: transparent !important;
.form-group { .form-label,
margin-bottom: 24px;
label { label {
font-weight: 500; font-weight: 500;
color: rgba(255, 255, 255, 0.9); color: rgba(255, 255, 255, 0.9);
@ -88,8 +84,7 @@
font-size: 14px; font-size: 14px;
} }
input[type="text"], .form-control {
input[type="password"] {
background: rgba(255, 255, 255, 0.1); background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2); border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 8px; border-radius: 8px;
@ -110,7 +105,6 @@
color: white; color: white;
} }
} }
}
.form-check { .form-check {
margin-bottom: 32px; margin-bottom: 32px;
@ -132,7 +126,11 @@
} }
} }
button[type="submit"] { .btn-link {
color: #939393;
}
.btn-primary {
width: 100%; width: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none; border: none;
@ -143,6 +141,7 @@
font-size: 16px; font-size: 16px;
cursor: pointer; cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s; transition: transform 0.2s, box-shadow 0.2s;
margin-bottom: 10px;
&:hover { &:hover {
transform: translateY(-2px); transform: translateY(-2px);
@ -155,6 +154,9 @@
} }
} }
}
// Login Link Section // Login Link Section
.expert-login-link { .expert-login-link {
margin-top: 24px; margin-top: 24px;
@ -176,6 +178,7 @@
} }
} }
} }
}
// Right Column: Image Section // Right Column: Image Section
.expert-login-right { .expert-login-right {
@ -183,15 +186,27 @@
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
border-radius: 20px 0 0 20px; border-radius: 20px 0 0 20px;
min-height: 100vh;
.expert-login-image { .expert-login-image {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 25%, #667eea 75%, #764ba2 100%); // background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 25%, #667eea 75%, #764ba2 100%);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
position: relative; position: relative;
padding: 20px;
.expert-login-image-cover {
height: 100%;
width: 100%;
background-color: #667eea;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
border-radius: 16px;
}
.expert-spiral-decoration { .expert-spiral-decoration {
width: 400px; width: 400px;
@ -255,4 +270,3 @@
} }
} }
} }

View File

@ -14,7 +14,6 @@
<p>Your installed modules are listed below</p> <p>Your installed modules are listed below</p>
</div> </div>
<div class="expert-modules-grid" id="expert-modules-container"> <div class="expert-modules-grid" id="expert-modules-container">
<!-- Modules will be loaded here via JavaScript -->
</div> </div>
</div> </div>
</t> </t>

View File

@ -3,31 +3,33 @@
<data> <data>
<!-- Create a new top-level menu for Expert Home --> <!-- Create a new top-level menu for Expert Home -->
<menuitem id="menu_expert_root" <menuitem id="menu_expert_root"
name="Expert Home" name="Odex Theme"
sequence="1"/> web_icon="expert_theme,static/description/icon.png"
sequence="1000" />
<menuitem id="menu_expert_home" <!-- <menuitem id="menu_expert_home"
name="Dashboard" name="Dashboard"
parent="menu_expert_root" parent="menu_expert_root"
action="action_expert_home" action="action_expert_home"
sequence="1"/> sequence="1" /> -->
<menuitem id="menu_expert_login_templates"
name="Login Page Templates"
parent="menu_expert_root"
action="action_expert_login_template"
sequence="2"/>
<menuitem id="menu_expert_theme_colors" <menuitem id="menu_expert_theme_colors"
name="Theme Colors" name="Theme Colors"
parent="menu_expert_root" parent="menu_expert_root"
action="action_expert_theme_config" action="action_expert_theme_config"
sequence="3"/> sequence="1" />
<menuitem id="menu_expert_login_templates"
name="Login Page Templates"
parent="menu_expert_root"
action="action_expert_login_template"
sequence="2" />
<!-- Also add Theme Colors to the main menu for easier access --> <!-- Also add Theme Colors to the main menu for easier access -->
<menuitem id="menu_theme_colors_main" <!-- <menuitem id="menu_theme_colors_main"
name="Theme Colors" name="Theme Colors"
action="action_expert_theme_config" action="action_expert_theme_config"
sequence="100"/> sequence="100" /> -->
</data> </data>
</odoo> </odoo>

View File

@ -7,29 +7,35 @@
--> -->
<!-- Template 1: Modern Card Design --> <!-- Template 1: Modern Card Design -->
<template id="login_template_modern_page" name="Modern Login Template">
<t t-call="web.layout"> <template id="login_template_modern_page" name="Modern Login Template"
<t t-set="head"> inherit_id="website.login_layout" active="False">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/> <xpath expr="//div[contains(@class, 'oe_website_login_container')]" position="replace">
<style> <t t-set="login_template"
body.bg-100 { t-value="request.env['expert.login.template'].sudo().search([('active', '=', True)], limit=1)" />
background-color: <t t-if="login_template and login_template.background_color"><t t-esc="login_template.background_color"/></t><t t-else="">#19181F</t> !important; <style> body.bg-100 { background-color: <t
} t-if="login_template and login_template.background_color">
</style> <t t-esc="login_template.background_color" />
</t> </t><t t-else="">
<t t-set="body_classname" t-value="'bg-100'"/> #19181F</t> !important; } </style>
<div class="oe_login_form expert-login-modern"> <t t-set="body_classname" t-value="'bg-100'" />
<div class="container-fluid p-0"> <t t-set="no_header" t-value="True" />
<t t-set="no_footer" t-value="True" />
<div class="expert-login-modern">
<div class="container-fluid">
<div class="row"> <div class="row">
<!-- Left Column: Login Form (6 columns) --> <!-- Left Column: Login Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left"> <div class="col-lg-6 col-md-12 expert-login-left">
<div class="expert-login-form-container">
<!-- Logo and Text --> <!-- Logo and Text -->
<div class="expert-login-logo"> <div class="expert-login-logo">
<t t-if="login_template and login_template.modern_template_logo"> <t t-if="login_template and login_template.modern_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.modern_template_logo.decode('utf-8')" <img
t-att-src="'data:image/png;base64,%s' % login_template.modern_template_logo.decode('utf-8')"
alt="Company Logo" alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/> style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;" />
<span class="expert-logo-text">Expert</span> <span class="expert-logo-text">Expert</span>
</t> </t>
<t t-else=""> <t t-else="">
@ -43,406 +49,102 @@
<!-- Welcome Text --> <!-- Welcome Text -->
<div class="expert-login-welcome"> <div class="expert-login-welcome">
<h1> <h1>
<t t-if="login_template and login_template.modern_login_title"> <t
<t t-esc="login_template.modern_login_title"/> t-if="login_template and login_template.modern_login_title">
<t t-esc="login_template.modern_login_title" />
</t> </t>
<t t-else=""> <t t-else=""> Welcome to Expert <span class="welcome-emoji">
Welcome to Expert <span class="welcome-emoji">👋</span> 👋</span>
</t> </t>
</h1> </h1>
<p> <p>
<t t-if="login_template and login_template.modern_login_subtitle"> <t
<t t-esc="login_template.modern_login_subtitle"/> t-if="login_template and login_template.modern_login_subtitle">
<t t-esc="login_template.modern_login_subtitle" />
</t> </t>
<t t-else=""> <t t-else="">
Kindly fill in your details below to sign in to your account Kindly fill in your details below to sign in to your
account
</t> </t>
</p> </p>
</div> </div>
<!-- Login Form --> <!-- Login Form -->
<form class="oe_login_form expert-login-form" role="form" method="post" t-att-action="request.httprequest.path"> <div class="expert-login-form">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> <t t-out="0" />
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<div class="form-group">
<label>Email or Username</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email or username"
t-att-value="login"/>
</div> </div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control"
placeholder="Enter your password"/>
</div>
<div class="form-check">
<label>
<input type="checkbox" name="remember"/>
Remember me
</label>
</div>
<button type="submit" class="btn btn-primary expert-modern-login-btn">
<t t-if="login_template and login_template.modern_login_button_text">
<t t-esc="login_template.modern_login_button_text"/>
</t>
<t t-else="">
Sign In
</t>
</button>
</form>
<!-- Button Styles --> <!-- Button Styles -->
<style> <style> .expert-modern-login-btn { background-color: <t
.expert-modern-login-btn { t-if="login_template and login_template.modern_login_button_bg_color">
background-color: <t t-if="login_template and login_template.modern_login_button_bg_color"><t t-esc="login_template.modern_login_button_bg_color"/></t><t t-else="">#007bff</t> !important; <t t-esc="login_template.modern_login_button_bg_color" />
color: <t t-if="login_template and login_template.modern_login_button_text_color"><t t-esc="login_template.modern_login_button_text_color"/></t><t t-else="">#FFFFFF</t> !important; </t><t
border: none !important; t-else="">#007bff</t> !important; color: <t
} t-if="login_template and login_template.modern_login_button_text_color">
.expert-modern-login-btn:hover { <t t-esc="login_template.modern_login_button_text_color" />
background-color: <t t-if="login_template and login_template.modern_login_button_bg_hover"><t t-esc="login_template.modern_login_button_bg_hover"/></t><t t-else="">#0056b3</t> !important; </t><t
color: <t t-if="login_template and login_template.modern_login_button_text_hover"><t t-esc="login_template.modern_login_button_text_hover"/></t><t t-else="">#FFFFFF</t> !important; t-else="">#FFFFFF</t> !important; border: none !important; }
} .expert-modern-login-btn:hover { background-color: <t
</style> t-if="login_template and login_template.modern_login_button_bg_hover">
<t t-esc="login_template.modern_login_button_bg_hover" />
</t><t
t-else="">#0056b3</t> !important; color: <t
t-if="login_template and login_template.modern_login_button_text_hover">
<t t-esc="login_template.modern_login_button_text_hover" />
</t><t
t-else="">#FFFFFF</t> !important; } </style>
<!-- Signup Link --> <!-- Signup Link -->
<div class="expert-login-link"> <!-- <div class="expert-login-link">
<p> <p> Don't have an account? <a
Don't have an account? t-attf-href="/web/signup?{{ keep_query() }}">Sign Up</a>
<a t-attf-href="/web/signup?{{ keep_query() }}">Sign Up</a>
</p> </p>
</div> -->
</div> </div>
</div> </div>
<!-- Right Column: Image (6 columns) --> <!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right"> <div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image"> <div class="expert-login-image">
<img t-if="login_template and login_template.modern_template_image" <div class="expert-login-image-cover"
t-att-src="'data:image/png;base64,%s' % login_template.modern_template_image.decode('utf-8')" t-if="login_template.modern_template_image"
alt="Login Image" class="img-fluid"/> t-attf-style="background-image: url('#{'/web/image/expert.login.template/'+str(login_template.id)+'/modern_template_image' if login_template else '/expert_theme/static/src/img/modern-template-bg.png' }');" />
<img t-else=""
src="/expert_theme/static/src/img/modern-template-bg.png"
alt="Login Image" class="img-fluid"/>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</t> </xpath>
</template>
<!-- Modern Signup Template -->
<template id="signup_template_modern_page" name="Modern Signup Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
<style>
body.bg-100 {
background-color: <t t-if="login_template and login_template.background_color"><t t-esc="login_template.background_color"/></t><t t-else="">#19181F</t> !important;
}
</style>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-modern">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Signup Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.modern_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.modern_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.modern_signup_title">
<t t-esc="login_template.modern_signup_title"/>
</t>
<t t-else="">
Create an account
</t>
</h1>
<p>
<t t-if="login_template and login_template.modern_signup_subtitle">
<t t-esc="login_template.modern_signup_subtitle"/>
</t>
<t t-else="">
Join us today and get started
</t>
</p>
</div>
<!-- Signup Form -->
<form class="oe_signup_form expert-login-form" role="form" method="post" t-if="not message">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<input type="hidden" name="token" t-att-value="token or ''"/>
<div class="form-group">
<label>Your Email</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email"
t-att-value="login"
t-att-readonly="'readonly' if (token and not invalid_token) else None"
autofocus="autofocus"
autocapitalize="off"
required="required"/>
</div>
<div class="form-group" t-if="not (token and not invalid_token)">
<label>Your Name</label>
<input type="text" name="name" class="form-control"
placeholder="e.g. John Doe"
t-att-value="name"
required="required"/>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" id="password" class="form-control"
placeholder="Enter your password"
required="required"
t-att-autofocus="'autofocus' if (token and not invalid_token) else None"/>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" id="confirm_password" class="form-control"
placeholder="Confirm your password"
required="required"/>
</div>
<p class="alert alert-danger" t-if="error" role="alert">
<t t-esc="error"/>
</p>
<button type="submit" class="btn btn-primary expert-modern-signup-btn">
<t t-if="login_template and login_template.modern_signup_button_text">
<t t-esc="login_template.modern_signup_button_text"/>
</t>
<t t-else="">
Sign Up
</t>
</button>
</form>
<!-- Button Styles -->
<style>
.expert-modern-signup-btn {
background-color: <t t-if="login_template and login_template.modern_signup_button_bg_color"><t t-esc="login_template.modern_signup_button_bg_color"/></t><t t-else="">#28a745</t> !important;
color: <t t-if="login_template and login_template.modern_signup_button_text_color"><t t-esc="login_template.modern_signup_button_text_color"/></t><t t-else="">#FFFFFF</t> !important;
border: none !important;
}
.expert-modern-signup-btn:hover {
background-color: <t t-if="login_template and login_template.modern_signup_button_bg_hover"><t t-esc="login_template.modern_signup_button_bg_hover"/></t><t t-else="">#218838</t> !important;
color: <t t-if="login_template and login_template.modern_signup_button_text_hover"><t t-esc="login_template.modern_signup_button_text_hover"/></t><t t-else="">#FFFFFF</t> !important;
}
</style>
<!-- Signup Link -->
<div class="expert-login-link">
<p>
Already have an account?
<a t-attf-href="/web/login?{{ keep_query() }}">Log In</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.modern_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.modern_template_image.decode('utf-8')"
alt="Signup Image" class="img-fluid"/>
<img t-else=""
src="/expert_theme/static/src/img/modern-template-bg.png"
alt="Signup Image" class="img-fluid"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Modern Reset Password Template -->
<template id="reset_password_template_modern_page" name="Modern Reset Password Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
<style>
body.bg-100 {
background-color: <t t-if="login_template and login_template.background_color"><t t-esc="login_template.background_color"/></t><t t-else="">#19181F</t> !important;
}
</style>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-modern">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Reset Password Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.modern_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.modern_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.modern_reset_title">
<t t-esc="login_template.modern_reset_title"/>
</t>
<t t-else="">
Reset Password <span class="welcome-emoji">🔐</span>
</t>
</h1>
<p t-if="not token">
<t t-if="login_template and login_template.modern_reset_subtitle">
<t t-esc="login_template.modern_reset_subtitle"/>
</t>
<t t-else="">
Enter your email address and we'll send you instructions to reset your password
</t>
</p>
<p t-if="token and not invalid_token">
Enter your new password below
</p>
</div>
<!-- Success Message -->
<div t-if="message" class="expert-login-form">
<p class="alert alert-success" role="status">
<t t-esc="message"/>
</p>
<a href="/web/login" class="btn btn-link" style="color: #667eea;">Back to Login</a>
</div>
<!-- Reset Password Form -->
<form class="oe_reset_password_form expert-login-form" role="form" method="post" t-if="not message">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<input type="hidden" name="token" t-att-value="token or ''"/>
<!-- Token-based reset (set new password) -->
<t t-if="token and not invalid_token">
<div class="form-group">
<label>New Password</label>
<input type="password" name="password" id="password" class="form-control"
placeholder="Enter your new password"
required="required"
autofocus="autofocus"/>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" id="confirm_password" class="form-control"
placeholder="Confirm your new password"
required="required"/>
</div>
</t>
<!-- Email-based reset (request reset) -->
<t t-if="not token">
<div class="form-group">
<label>Your Email</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email"
t-att-value="login"
autofocus="autofocus"
required="required"
autocapitalize="off"/>
</div>
</t>
<p class="alert alert-danger" t-if="error" role="alert">
<t t-esc="error"/>
</p>
<button type="submit" class="btn btn-primary">
<t t-if="token and not invalid_token">Reset Password</t>
<t t-if="not token">Send Reset Instructions</t>
</button>
</form>
<!-- Reset Password Link -->
<div class="expert-login-link" t-if="not message">
<p>
<a t-if="not token" t-attf-href="/web/login?{{ keep_query() }}" style="color: #667eea;">Back to Login</a>
<a t-if="invalid_token" href="/web/login" style="color: #667eea;">Back to Login</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.modern_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.modern_template_image.decode('utf-8')"
alt="Reset Password Image" class="img-fluid"/>
<img t-else=""
src="/expert_theme/static/src/img/modern-template-bg.png"
alt="Reset Password Image" class="img-fluid"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template> </template>
<!-- Template 2: Minimal Design --> <!-- Template 2: Minimal Design -->
<template id="login_template_minimal_page" name="Minimal Login Template"> <template id="login_template_minimal_page" name="Minimal Login Template"
<t t-call="web.layout"> inherit_id="website.login_layout" active="False">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/> <xpath expr="//div[contains(@class, 'oe_website_login_container')]" position="replace">
<t t-call-assets="web.assets_frontend" t-js="false"/> <t t-set="login_template"
<style> t-value="request.env['expert.login.template'].sudo().search([('active', '=', True)], limit=1)" />
body.bg-100 { <style> body.bg-100 { background-color: <t
background-color: <t t-if="login_template and login_template.background_color"><t t-esc="login_template.background_color"/></t><t t-else="">#FFFFFF</t> !important; t-if="login_template and login_template.background_color">
} <t t-esc="login_template.background_color" />
</style> </t><t t-else="">
</t> #19181F</t> !important; } </style>
<t t-set="body_classname" t-value="'bg-100'"/> <t t-set="body_classname" t-value="'bg-100'" />
<div class="oe_login_form expert-login-minimal">
<div class="container-fluid p-0"> <div class="expert-login-minimal">
<div class="container-fluid">
<div class="row"> <div class="row">
<!-- Left Column: Login Form (6 columns) --> <!-- Left Column: Login Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left"> <div class="col-lg-6 col-md-12 expert-login-left">
<div class="expert-login-form-container">
<!-- Logo and Text --> <!-- Logo and Text -->
<div class="expert-login-logo"> <div class="expert-login-logo">
<t t-if="login_template and login_template.minimal_template_logo"> <t t-if="login_template and login_template.minimal_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_logo.decode('utf-8')" <img
t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_logo.decode('utf-8')"
alt="Company Logo" alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/> style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;" />
<span class="expert-logo-text">Expert</span> <span class="expert-logo-text">Expert</span>
</t> </t>
<t t-else=""> <t t-else="">
@ -457,15 +159,15 @@
<div class="expert-login-welcome"> <div class="expert-login-welcome">
<h1> <h1>
<t t-if="login_template and login_template.minimal_login_title"> <t t-if="login_template and login_template.minimal_login_title">
<t t-esc="login_template.minimal_login_title"/> <t t-esc="login_template.minimal_login_title" />
</t> </t>
<t t-else=""> <t t-else=""> Welcome to Expert <span class="welcome-emoji">👋</span>
Welcome to Expert <span class="welcome-emoji">👋</span>
</t> </t>
</h1> </h1>
<p> <p>
<t t-if="login_template and login_template.minimal_login_subtitle"> <t
<t t-esc="login_template.minimal_login_subtitle"/> t-if="login_template and login_template.minimal_login_subtitle">
<t t-esc="login_template.minimal_login_subtitle" />
</t> </t>
<t t-else=""> <t t-else="">
Kindly fill in your details below to sign in to your account Kindly fill in your details below to sign in to your account
@ -474,59 +176,36 @@
</div> </div>
<!-- Login Form --> <!-- Login Form -->
<form class="oe_login_form expert-login-form" role="form" method="post" t-att-action="request.httprequest.path"> <div class="expert-login-form">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> <t t-out="0" />
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<div class="form-group">
<label>Email or Username</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email or username"
t-att-value="login"/>
</div> </div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control"
placeholder="Enter your password"/>
</div>
<div class="form-check">
<label>
<input type="checkbox" name="remember"/>
Remember me
</label>
</div>
<button type="submit" class="btn btn-primary expert-minimal-login-btn">
<t t-if="login_template and login_template.minimal_login_button_text">
<t t-esc="login_template.minimal_login_button_text"/>
</t>
<t t-else="">
Sign In
</t>
</button>
</form>
<!-- Button Styles --> <!-- Button Styles -->
<style> <style> .expert-minimal-login-btn { background-color: <t
.expert-minimal-login-btn { t-if="login_template and login_template.minimal_login_button_bg_color">
background-color: <t t-if="login_template and login_template.minimal_login_button_bg_color"><t t-esc="login_template.minimal_login_button_bg_color"/></t><t t-else="">#E5E5E5</t> !important; <t t-esc="login_template.minimal_login_button_bg_color" />
color: <t t-if="login_template and login_template.minimal_login_button_text_color"><t t-esc="login_template.minimal_login_button_text_color"/></t><t t-else="">#000000</t> !important; </t><t
border: none !important; t-else="">#E5E5E5</t> !important; color: <t
} t-if="login_template and login_template.minimal_login_button_text_color">
.expert-minimal-login-btn:hover { <t t-esc="login_template.minimal_login_button_text_color" />
background-color: <t t-if="login_template and login_template.minimal_login_button_bg_hover"><t t-esc="login_template.minimal_login_button_bg_hover"/></t><t t-else="">#D0D0D0</t> !important; </t><t
color: <t t-if="login_template and login_template.minimal_login_button_text_hover"><t t-esc="login_template.minimal_login_button_text_hover"/></t><t t-else="">#000000</t> !important; t-else="">#000000</t> !important; border: none !important; }
} .expert-minimal-login-btn:hover { background-color: <t
</style> t-if="login_template and login_template.minimal_login_button_bg_hover">
<t t-esc="login_template.minimal_login_button_bg_hover" />
</t><t
t-else="">#D0D0D0</t> !important; color: <t
t-if="login_template and login_template.minimal_login_button_text_hover">
<t t-esc="login_template.minimal_login_button_text_hover" />
</t><t
t-else="">#000000</t> !important; } </style>
<!-- Signup Link --> <!-- Signup Link -->
<div class="expert-login-link"> <!-- <div class="expert-login-link">
<p> <p> Don't have an account? <a
Don't have an account? t-attf-href="/web/signup?{{ keep_query() }}">Sign Up</a>
<a t-attf-href="/web/signup?{{ keep_query() }}">Sign Up</a>
</p> </p>
</div> -->
</div> </div>
</div> </div>
@ -534,345 +213,63 @@
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right"> <div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image"> <div class="expert-login-image">
<img t-if="login_template and login_template.minimal_template_image" <img t-if="login_template and login_template.minimal_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_image.decode('utf-8')" t-att-src="'/web/image/expert.login.template/%s/minimal_template_image' % login_template.id"
alt="Login Illustration" class="img-fluid expert-minimal-illustration"/> alt="Signup Illustration"
class="img-fluid expert-minimal-illustration" />
<img t-else="" <img t-else=""
src="/expert_theme/static/src/img/minimal-login-img.png" src="/expert_theme/static/src/img/minimal-login-img.png"
alt="Login Illustration" class="img-fluid expert-minimal-illustration"/> alt="Signup Illustration"
class="img-fluid expert-minimal-illustration" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</t> </xpath>
</template>
<!-- Minimal Signup Template -->
<template id="signup_template_minimal_page" name="Minimal Signup Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
<style>
body.bg-100 {
background-color: <t t-if="login_template and login_template.background_color"><t t-esc="login_template.background_color"/></t><t t-else="">#FFFFFF</t> !important;
}
</style>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-minimal">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Signup Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.minimal_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.minimal_signup_title">
<t t-esc="login_template.minimal_signup_title"/>
</t>
<t t-else="">
Create an account
</t>
</h1>
<p>
<t t-if="login_template and login_template.minimal_signup_subtitle">
<t t-esc="login_template.minimal_signup_subtitle"/>
</t>
<t t-else="">
<a t-attf-href="/web/login?{{ keep_query() }}" style="color: #000; text-decoration: underline;">log in instead</a>
</t>
</p>
</div>
<!-- Signup Form -->
<form class="oe_signup_form expert-login-form" role="form" method="post" t-if="not message">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<input type="hidden" name="token" t-att-value="token or ''"/>
<div class="form-group" t-if="not (token and not invalid_token)">
<label>Your Name</label>
<input type="text" name="name" class="form-control"
placeholder="e.g. John Doe"
t-att-value="name"
required="required"
t-att-autofocus="'autofocus' if login and not (token and not invalid_token) else None"/>
</div>
<div class="form-group">
<label>Your Email</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email"
t-att-value="login"
t-att-readonly="'readonly' if (token and not invalid_token) else None"
autofocus="autofocus"
autocapitalize="off"
required="required"/>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" id="password" class="form-control"
placeholder="Enter your password"
required="required"
t-att-autofocus="'autofocus' if (token and not invalid_token) else None"/>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" id="confirm_password" class="form-control"
placeholder="Confirm your password"
required="required"/>
</div>
<div class="form-check">
<label>
<input type="checkbox" name="terms" required="required"/>
By creating an account, I agree to our <a href="#" style="color: #000; text-decoration: underline;">Terms of use</a> and <a href="#" style="color: #000; text-decoration: underline;">Privacy Policy</a>
</label>
</div>
<p class="alert alert-danger" t-if="error" role="alert">
<t t-esc="error"/>
</p>
<button type="submit" class="btn btn-primary expert-minimal-signup-btn">
<t t-if="login_template and login_template.minimal_signup_button_text">
<t t-esc="login_template.minimal_signup_button_text"/>
</t>
<t t-else="">
Create an account
</t>
</button>
</form>
<!-- Button Styles -->
<style>
.expert-minimal-signup-btn {
background-color: <t t-if="login_template and login_template.minimal_signup_button_bg_color"><t t-esc="login_template.minimal_signup_button_bg_color"/></t><t t-else="">#000000</t> !important;
color: <t t-if="login_template and login_template.minimal_signup_button_text_color"><t t-esc="login_template.minimal_signup_button_text_color"/></t><t t-else="">#FFFFFF</t> !important;
border: none !important;
}
.expert-minimal-signup-btn:hover {
background-color: <t t-if="login_template and login_template.minimal_signup_button_bg_hover"><t t-esc="login_template.minimal_signup_button_bg_hover"/></t><t t-else="">#333333</t> !important;
color: <t t-if="login_template and login_template.minimal_signup_button_text_hover"><t t-esc="login_template.minimal_signup_button_text_hover"/></t><t t-else="">#FFFFFF</t> !important;
}
</style>
<!-- Login Link -->
<div class="expert-login-link">
<p>
Already have an account?
<a t-attf-href="/web/login?{{ keep_query() }}" style="color: #000; text-decoration: underline;">Log In</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.minimal_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_image.decode('utf-8')"
alt="Signup Illustration" class="img-fluid expert-minimal-illustration"/>
<img t-else=""
src="/expert_theme/static/src/img/minimal-login-img.png"
alt="Signup Illustration" class="img-fluid expert-minimal-illustration"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Minimal Reset Password Template -->
<template id="reset_password_template_minimal_page" name="Minimal Reset Password Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
<style>
body.bg-100 {
background-color: <t t-if="login_template and login_template.background_color"><t t-esc="login_template.background_color"/></t><t t-else="">#FFFFFF</t> !important;
}
</style>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-minimal">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Reset Password Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.minimal_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.minimal_reset_title">
<t t-esc="login_template.minimal_reset_title"/>
</t>
<t t-else="">
Reset Password <span class="welcome-emoji">🔐</span>
</t>
</h1>
<p t-if="not token">
<t t-if="login_template and login_template.minimal_reset_subtitle">
<t t-esc="login_template.minimal_reset_subtitle"/>
</t>
<t t-else="">
Enter your email address and we'll send you instructions to reset your password
</t>
</p>
<p t-if="token and not invalid_token">
Enter your new password below
</p>
</div>
<!-- Success Message -->
<div t-if="message" class="expert-login-form">
<p class="alert alert-success" role="status">
<t t-esc="message"/>
</p>
<a href="/web/login" class="btn btn-link" style="color: #000; text-decoration: underline;">Back to Login</a>
</div>
<!-- Reset Password Form -->
<form class="oe_reset_password_form expert-login-form" role="form" method="post" t-if="not message">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<input type="hidden" name="token" t-att-value="token or ''"/>
<!-- Token-based reset (set new password) -->
<t t-if="token and not invalid_token">
<div class="form-group">
<label>New Password</label>
<input type="password" name="password" id="password" class="form-control"
placeholder="Enter your new password"
required="required"
autofocus="autofocus"/>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" id="confirm_password" class="form-control"
placeholder="Confirm your new password"
required="required"/>
</div>
</t>
<!-- Email-based reset (request reset) -->
<t t-if="not token">
<div class="form-group">
<label>Email</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email"
t-att-value="login"
autofocus="autofocus"
required="required"
autocapitalize="off"/>
</div>
</t>
<p class="alert alert-danger" t-if="error" role="alert">
<t t-esc="error"/>
</p>
<button type="submit" class="btn btn-primary">
<t t-if="token and not invalid_token">Reset Password</t>
<t t-if="not token">Send Reset Instructions</t>
</button>
</form>
<!-- Reset Password Link -->
<div class="expert-login-link" t-if="not message">
<p>
<a t-if="not token" t-attf-href="/web/login?{{ keep_query() }}" style="color: #000; text-decoration: underline;">Back to Login</a>
<a t-if="invalid_token" href="/web/login" style="color: #000; text-decoration: underline;">Back to Login</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.minimal_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_image.decode('utf-8')"
alt="Reset Password Illustration" class="img-fluid expert-minimal-illustration"/>
<img t-else=""
src="/expert_theme/static/src/img/minimal-login-img.png"
alt="Reset Password Illustration" class="img-fluid expert-minimal-illustration"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template> </template>
<!-- Template 3: Corporate Design --> <!-- Template 3: Corporate Design -->
<template id="login_template_corporate_page" name="Corporate Login Template"> <template id="login_template_corporate_page" name="Corporate Login Template">
<t t-call="web.layout"> <t t-call="web.layout">
<t t-set="head"> <t t-set="head">
<style> <style> body.bg-100 { background-color: <t
body.bg-100 { t-if="login_template and login_template.background_color">
background-color: <t t-if="login_template and login_template.background_color"><t t-esc="login_template.background_color"/></t><t t-else="">#1a1a1a</t> !important; <t t-esc="login_template.background_color" />
} </t><t
</style> t-else="">#1a1a1a</t> !important; } </style>
</t> </t>
<div class="oe_login_form" t-attf-style="background: {{login_template.background_color if login_template and login_template.background_color else '#1a1a1a'}}; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 20px;"> <div class="oe_login_form"
<div style="width: 100%; max-width: 500px; background: #2d2d2d; padding: 60px 50px; border-radius: 8px; border: 1px solid #404040;"> t-attf-style="background: {{login_template.background_color if login_template and login_template.background_color else '#1a1a1a'}}; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 20px;">
<div
style="width: 100%; max-width: 500px; background: #2d2d2d; padding: 60px 50px; border-radius: 8px; border: 1px solid #404040;">
<div class="text-center mb-5"> <div class="text-center mb-5">
<h2 style="color: #fff; font-size: 32px; font-weight: 600; margin-bottom: 10px;">Company Portal</h2> <h2
style="color: #fff; font-size: 32px; font-weight: 600; margin-bottom: 10px;">Company
Portal</h2>
<p style="color: #999; font-size: 14px; margin: 0;">Secure Login Access</p> <p style="color: #999; font-size: 14px; margin: 0;">Secure Login Access</p>
</div> </div>
<form class="oe_login_form" role="form" method="post" t-att-action="request.httprequest.path"> <form class="oe_login_form" role="form" method="post"
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> t-att-action="request.httprequest.path">
<input type="hidden" name="redirect" t-att-value="redirect or ''"/> <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<input type="hidden" name="redirect" t-att-value="redirect or ''" />
<div style="margin-bottom: 25px;"> <div style="margin-bottom: 25px;">
<label style="color: #ccc; font-size: 13px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; display: block;">Username</label> <label
style="color: #ccc; font-size: 13px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; display: block;">
Username</label>
<input type="text" name="login" class="form-control" <input type="text" name="login" class="form-control"
placeholder="Enter your username" placeholder="Enter your username"
t-att-value="login" t-att-value="login"
style="background: #1a1a1a; border: 1px solid #404040; color: #fff; padding: 12px 15px; border-radius: 4px; width: 100%; box-sizing: border-box;"/> style="background: #1a1a1a; border: 1px solid #404040; color: #fff; padding: 12px 15px; border-radius: 4px; width: 100%; box-sizing: border-box;" />
</div> </div>
<div style="margin-bottom: 35px;"> <div style="margin-bottom: 35px;">
<label style="color: #ccc; font-size: 13px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; display: block;">Password</label> <label
style="color: #ccc; font-size: 13px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; display: block;">
Password</label>
<input type="password" name="password" class="form-control" <input type="password" name="password" class="form-control"
placeholder="Enter your password" placeholder="Enter your password"
style="background: #1a1a1a; border: 1px solid #404040; color: #fff; padding: 12px 15px; border-radius: 4px; width: 100%; box-sizing: border-box;"/> style="background: #1a1a1a; border: 1px solid #404040; color: #fff; padding: 12px 15px; border-radius: 4px; width: 100%; box-sizing: border-box;" />
</div> </div>
<button type="submit" class="btn btn-block" <button type="submit" class="btn btn-block"

View File

@ -1,785 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--
Multiple Login Page Templates with Different HTML Structures
Standalone templates rendered by the /web/login override.
Each template calls web.layout and defines its own login form.
-->
<!-- Template 1: Modern Card Design -->
<template id="login_template_modern_page" name="Modern Login Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-modern">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Login Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.modern_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.modern_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.modern_login_title">
<t t-esc="login_template.modern_login_title"/>
</t>
<t t-else="">
Welcome to Expert <span class="welcome-emoji">👋</span>
</t>
</h1>
<p>
<t t-if="login_template and login_template.modern_login_subtitle">
<t t-esc="login_template.modern_login_subtitle"/>
</t>
<t t-else="">
Kindly fill in your details below to sign in to your account
</t>
</p>
</div>
<!-- Login Form -->
<form class="oe_login_form expert-login-form" role="form" method="post" t-att-action="request.httprequest.path">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<div class="form-group">
<label>Email or Username</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email or username"
t-att-value="login"/>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control"
placeholder="Enter your password"/>
</div>
<div class="form-check">
<label>
<input type="checkbox" name="remember"/>
Remember me
</label>
</div>
<button type="submit" class="btn btn-primary">
<t t-if="login_template and login_template.modern_login_button_text"><t t-esc="login_template.modern_login_button_text"/></t><t t-else="">Sign In</t>
</button>
</form>
<!-- Signup Link -->
<div class="expert-login-link">
<p>
Don't have an account?
<a t-attf-href="/web/signup?{{ keep_query() }}">Sign Up</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.modern_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.modern_template_image.decode('utf-8')"
alt="Login Image" class="img-fluid"/>
<img t-else=""
src="/expert_theme/static/src/img/modern-template-bg.png"
alt="Login Image" class="img-fluid"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Modern Signup Template -->
<template id="signup_template_modern_page" name="Modern Signup Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-modern">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Signup Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.modern_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.modern_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.modern_signup_title">
<t t-esc="login_template.modern_signup_title"/>
</t>
<t t-else="">
Create an account
</t>
</h1>
<p>
<t t-if="login_template and login_template.modern_signup_subtitle">
<t t-esc="login_template.modern_signup_subtitle"/>
</t>
<t t-else="">
Join us today and get started
</t>
</p>
</div>
<!-- Signup Form -->
<form class="oe_signup_form expert-login-form" role="form" method="post" t-if="not message">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<input type="hidden" name="token" t-att-value="token or ''"/>
<div class="form-group">
<label>Your Email</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email"
t-att-value="login"
t-att-readonly="'readonly' if (token and not invalid_token) else None"
autofocus="autofocus"
autocapitalize="off"
required="required"/>
</div>
<div class="form-group" t-if="not (token and not invalid_token)">
<label>Your Name</label>
<input type="text" name="name" class="form-control"
placeholder="e.g. John Doe"
t-att-value="name"
required="required"/>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" id="password" class="form-control"
placeholder="Enter your password"
required="required"
t-att-autofocus="'autofocus' if (token and not invalid_token) else None"/>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" id="confirm_password" class="form-control"
placeholder="Confirm your password"
required="required"/>
</div>
<p class="alert alert-danger" t-if="error" role="alert">
<t t-esc="error"/>
</p>
<button type="submit" class="btn btn-primary">
<t t-if="login_template and login_template.modern_signup_button_text">
<t t-esc="login_template.modern_signup_button_text"/>
</t>
<t t-else="">
Sign Up
</t>
</button>
</form>
<!-- Signup Link -->
<div class="expert-login-link">
<p>
Already have an account?
<a t-attf-href="/web/login?{{ keep_query() }}">Log In</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.modern_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.modern_template_image.decode('utf-8')"
alt="Signup Image" class="img-fluid"/>
<img t-else=""
src="/expert_theme/static/src/img/modern-template-bg.png"
alt="Signup Image" class="img-fluid"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Modern Reset Password Template -->
<template id="reset_password_template_modern_page" name="Modern Reset Password Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-modern">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Reset Password Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.modern_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.modern_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.modern_reset_title">
<t t-esc="login_template.modern_reset_title"/>
</t>
<t t-else="">
Reset Password <span class="welcome-emoji">🔐</span>
</t>
</h1>
<p t-if="not token">
<t t-if="login_template and login_template.modern_reset_subtitle">
<t t-esc="login_template.modern_reset_subtitle"/>
</t>
<t t-else="">
Enter your email address and we'll send you instructions to reset your password
</t>
</p>
<p t-if="token and not invalid_token">
Enter your new password below
</p>
</div>
<!-- Success Message -->
<div t-if="message" class="expert-login-form">
<p class="alert alert-success" role="status">
<t t-esc="message"/>
</p>
<a href="/web/login" class="btn btn-link" style="color: #667eea;">Back to Login</a>
</div>
<!-- Reset Password Form -->
<form class="oe_reset_password_form expert-login-form" role="form" method="post" t-if="not message">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<input type="hidden" name="token" t-att-value="token or ''"/>
<!-- Token-based reset (set new password) -->
<t t-if="token and not invalid_token">
<div class="form-group">
<label>New Password</label>
<input type="password" name="password" id="password" class="form-control"
placeholder="Enter your new password"
required="required"
autofocus="autofocus"/>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" id="confirm_password" class="form-control"
placeholder="Confirm your new password"
required="required"/>
</div>
</t>
<!-- Email-based reset (request reset) -->
<t t-if="not token">
<div class="form-group">
<label>Your Email</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email"
t-att-value="login"
autofocus="autofocus"
required="required"
autocapitalize="off"/>
</div>
</t>
<p class="alert alert-danger" t-if="error" role="alert">
<t t-esc="error"/>
</p>
<button type="submit" class="btn btn-primary">
<t t-if="token and not invalid_token">Reset Password</t>
<t t-if="not token">Send Reset Instructions</t>
</button>
</form>
<!-- Reset Password Link -->
<div class="expert-login-link" t-if="not message">
<p>
<a t-if="not token" t-attf-href="/web/login?{{ keep_query() }}" style="color: #667eea;">Back to Login</a>
<a t-if="invalid_token" href="/web/login" style="color: #667eea;">Back to Login</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.modern_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.modern_template_image.decode('utf-8')"
alt="Reset Password Image" class="img-fluid"/>
<img t-else=""
src="/expert_theme/static/src/img/modern-template-bg.png"
alt="Reset Password Image" class="img-fluid"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Template 2: Minimal Design -->
<template id="login_template_minimal_page" name="Minimal Login Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-minimal">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Login Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.minimal_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.minimal_login_title">
<t t-esc="login_template.minimal_login_title"/>
</t>
<t t-else="">
Welcome to Expert <span class="welcome-emoji">👋</span>
</t>
</h1>
<p>
<t t-if="login_template and login_template.minimal_login_subtitle">
<t t-esc="login_template.minimal_login_subtitle"/>
</t>
<t t-else="">
Kindly fill in your details below to sign in to your account
</t>
</p>
</div>
<!-- Login Form -->
<form class="oe_login_form expert-login-form" role="form" method="post" t-att-action="request.httprequest.path">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<div class="form-group">
<label>Email or Username</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email or username"
t-att-value="login"/>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control"
placeholder="Enter your password"/>
</div>
<div class="form-check">
<label>
<input type="checkbox" name="remember"/>
Remember me
</label>
</div>
<button type="submit" class="btn btn-primary">
<t t-if="login_template and login_template.modern_login_button_text"><t t-esc="login_template.modern_login_button_text"/></t><t t-else="">Sign In</t>
</button>
</form>
<!-- Signup Link -->
<div class="expert-login-link">
<p>
Don't have an account?
<a t-attf-href="/web/signup?{{ keep_query() }}">Sign Up</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.minimal_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_image.decode('utf-8')"
alt="Login Illustration" class="img-fluid expert-minimal-illustration"/>
<img t-else=""
src="/expert_theme/static/src/img/minimal-login-img.png"
alt="Login Illustration" class="img-fluid expert-minimal-illustration"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Minimal Signup Template -->
<template id="signup_template_minimal_page" name="Minimal Signup Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-minimal">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Signup Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.minimal_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.minimal_signup_title">
<t t-esc="login_template.minimal_signup_title"/>
</t>
<t t-else="">
Create an account
</t>
</h1>
<p>
<t t-if="login_template and login_template.minimal_signup_subtitle">
<t t-esc="login_template.minimal_signup_subtitle"/>
</t>
<t t-else="">
<a t-attf-href="/web/login?{{ keep_query() }}" style="color: #000; text-decoration: underline;">log in instead</a>
</t>
</p>
</div>
<!-- Signup Form -->
<form class="oe_signup_form expert-login-form" role="form" method="post" t-if="not message">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<input type="hidden" name="token" t-att-value="token or ''"/>
<div class="form-group" t-if="not (token and not invalid_token)">
<label>Your Name</label>
<input type="text" name="name" class="form-control"
placeholder="e.g. John Doe"
t-att-value="name"
required="required"
t-att-autofocus="'autofocus' if login and not (token and not invalid_token) else None"/>
</div>
<div class="form-group">
<label>Your Email</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email"
t-att-value="login"
t-att-readonly="'readonly' if (token and not invalid_token) else None"
autofocus="autofocus"
autocapitalize="off"
required="required"/>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" id="password" class="form-control"
placeholder="Enter your password"
required="required"
t-att-autofocus="'autofocus' if (token and not invalid_token) else None"/>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" id="confirm_password" class="form-control"
placeholder="Confirm your password"
required="required"/>
</div>
<div class="form-check">
<label>
<input type="checkbox" name="terms" required="required"/>
By creating an account, I agree to our <a href="#" style="color: #000; text-decoration: underline;">Terms of use</a> and <a href="#" style="color: #000; text-decoration: underline;">Privacy Policy</a>
</label>
</div>
<p class="alert alert-danger" t-if="error" role="alert">
<t t-esc="error"/>
</p>
<button type="submit" class="btn btn-primary">
Create an account
</button>
</form>
<!-- Login Link -->
<div class="expert-login-link">
<p>
Already have an account?
<a t-attf-href="/web/login?{{ keep_query() }}" style="color: #000; text-decoration: underline;">Log In</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.minimal_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_image.decode('utf-8')"
alt="Signup Illustration" class="img-fluid expert-minimal-illustration"/>
<img t-else=""
src="/expert_theme/static/src/img/minimal-login-img.png"
alt="Signup Illustration" class="img-fluid expert-minimal-illustration"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Minimal Reset Password Template -->
<template id="reset_password_template_minimal_page" name="Minimal Reset Password Template">
<t t-call="web.layout">
<t t-set="head">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<div class="oe_login_form expert-login-minimal">
<div class="container-fluid p-0">
<div class="row">
<!-- Left Column: Reset Password Form (6 columns) -->
<div class="col-lg-6 col-md-12 expert-login-left">
<!-- Logo and Text -->
<div class="expert-login-logo">
<t t-if="login_template and login_template.minimal_template_logo">
<img t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_logo.decode('utf-8')"
alt="Company Logo"
style="width: 40px; height: 40px; object-fit: contain; margin-right: 12px;"/>
<span class="expert-logo-text">Expert</span>
</t>
<t t-else="">
<div class="expert-logo-icon">
<span>E</span>
</div>
<span class="expert-logo-text">Expert</span>
</t>
</div>
<!-- Welcome Text -->
<div class="expert-login-welcome">
<h1>
<t t-if="login_template and login_template.minimal_reset_title">
<t t-esc="login_template.minimal_reset_title"/>
</t>
<t t-else="">
Reset Password <span class="welcome-emoji">🔐</span>
</t>
</h1>
<p t-if="not token">
<t t-if="login_template and login_template.minimal_reset_subtitle">
<t t-esc="login_template.minimal_reset_subtitle"/>
</t>
<t t-else="">
Enter your email address and we'll send you instructions to reset your password
</t>
</p>
<p t-if="token and not invalid_token">
Enter your new password below
</p>
</div>
<!-- Success Message -->
<div t-if="message" class="expert-login-form">
<p class="alert alert-success" role="status">
<t t-esc="message"/>
</p>
<a href="/web/login" class="btn btn-link" style="color: #000; text-decoration: underline;">Back to Login</a>
</div>
<!-- Reset Password Form -->
<form class="oe_reset_password_form expert-login-form" role="form" method="post" t-if="not message">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<input type="hidden" name="token" t-att-value="token or ''"/>
<!-- Token-based reset (set new password) -->
<t t-if="token and not invalid_token">
<div class="form-group">
<label>New Password</label>
<input type="password" name="password" id="password" class="form-control"
placeholder="Enter your new password"
required="required"
autofocus="autofocus"/>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" id="confirm_password" class="form-control"
placeholder="Confirm your new password"
required="required"/>
</div>
</t>
<!-- Email-based reset (request reset) -->
<t t-if="not token">
<div class="form-group">
<label>Email</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your email"
t-att-value="login"
autofocus="autofocus"
required="required"
autocapitalize="off"/>
</div>
</t>
<p class="alert alert-danger" t-if="error" role="alert">
<t t-esc="error"/>
</p>
<button type="submit" class="btn btn-primary">
<t t-if="token and not invalid_token">Reset Password</t>
<t t-if="not token">Send Reset Instructions</t>
</button>
</form>
<!-- Reset Password Link -->
<div class="expert-login-link" t-if="not message">
<p>
<a t-if="not token" t-attf-href="/web/login?{{ keep_query() }}" style="color: #000; text-decoration: underline;">Back to Login</a>
<a t-if="invalid_token" href="/web/login" style="color: #000; text-decoration: underline;">Back to Login</a>
</p>
</div>
</div>
<!-- Right Column: Image (6 columns) -->
<div class="col-lg-6 col-md-12 d-none d-lg-block expert-login-right">
<div class="expert-login-image">
<img t-if="login_template and login_template.minimal_template_image"
t-att-src="'data:image/png;base64,%s' % login_template.minimal_template_image.decode('utf-8')"
alt="Reset Password Illustration" class="img-fluid expert-minimal-illustration"/>
<img t-else=""
src="/expert_theme/static/src/img/minimal-login-img.png"
alt="Reset Password Illustration" class="img-fluid expert-minimal-illustration"/>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Template 3: Corporate Design -->
<template id="login_template_corporate_page" name="Corporate Login Template">
<t t-call="web.layout">
<div class="oe_login_form" style="background: #1a1a1a; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 20px;">
<div style="width: 100%; max-width: 500px; background: #2d2d2d; padding: 60px 50px; border-radius: 8px; border: 1px solid #404040;">
<div class="text-center mb-5">
<h2 style="color: #fff; font-size: 32px; font-weight: 600; margin-bottom: 10px;">Company Portal</h2>
<p style="color: #999; font-size: 14px; margin: 0;">Secure Login Access</p>
</div>
<form class="oe_login_form" role="form" method="post" t-att-action="request.httprequest.path">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="redirect" t-att-value="redirect or ''"/>
<div style="margin-bottom: 25px;">
<label style="color: #ccc; font-size: 13px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; display: block;">Username</label>
<input type="text" name="login" class="form-control"
placeholder="Enter your username"
t-att-value="login"
style="background: #1a1a1a; border: 1px solid #404040; color: #fff; padding: 12px 15px; border-radius: 4px; width: 100%; box-sizing: border-box;"/>
</div>
<div style="margin-bottom: 35px;">
<label style="color: #ccc; font-size: 13px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; display: block;">Password</label>
<input type="password" name="password" class="form-control"
placeholder="Enter your password"
style="background: #1a1a1a; border: 1px solid #404040; color: #fff; padding: 12px 15px; border-radius: 4px; width: 100%; box-sizing: border-box;"/>
</div>
<button type="submit" class="btn btn-block"
style="width: 100%; background: #007bff; color: white; border: none; padding: 14px; font-size: 15px; font-weight: 600; border-radius: 4px; text-transform: uppercase; letter-spacing: 0.5px;">
Access Portal
</button>
</form>
</div>
</div>
</t>
</template>
</odoo>