Add contact form submission handling and introduce theme_clicks2cart module with enhanced shop page and product item layouts.
This commit is contained in:
parent
06bc61de9c
commit
048789595c
Binary file not shown.
@ -57,36 +57,36 @@ class ContactController(http.Controller):
|
||||
|
||||
return request.render('dine360_theme_chennora.contact_thank_you')
|
||||
|
||||
class BlogController(http.Controller):
|
||||
@http.route(['/blog'], type='http', auth='public', website=True)
|
||||
def blog_list(self, **post):
|
||||
blog_posts = request.env['chennora.blog.post'].sudo().search([('active', '=', True)])
|
||||
return request.render('dine360_theme_chennora.blog_page', {
|
||||
'blog_posts': blog_posts,
|
||||
})
|
||||
|
||||
@http.route(['/blog/<string:slug>'], type='http', auth='public', website=True)
|
||||
def blog_detail(self, slug, **post):
|
||||
blog_post = request.env['chennora.blog.post'].sudo().search([('slug', '=', slug), ('active', '=', True)], limit=1)
|
||||
if not blog_post:
|
||||
return request.not_found()
|
||||
|
||||
recent_posts = request.env['chennora.blog.post'].sudo().search([('active', '=', True), ('id', '!=', blog_post.id)], limit=3)
|
||||
|
||||
# Get dynamic categories and counts
|
||||
all_posts = request.env['chennora.blog.post'].sudo().search([('active', '=', True)])
|
||||
categories = {}
|
||||
for p in all_posts:
|
||||
if p.category:
|
||||
categories[p.category] = categories.get(p.category, 0) + 1
|
||||
|
||||
return request.render('dine360_theme_chennora.blog_detail_layout', {
|
||||
'blog_title': blog_post.title,
|
||||
'blog_img': blog_post.image,
|
||||
'blog_date': blog_post.date.strftime('%B %d, %Y') if blog_post.date else '',
|
||||
'blog_category': blog_post.category,
|
||||
'blog_content': blog_post.content,
|
||||
'recent_posts': recent_posts,
|
||||
'categories': categories,
|
||||
})
|
||||
# class BlogController(http.Controller):
|
||||
# @http.route(['/blog'], type='http', auth='public', website=True)
|
||||
# def blog_list(self, **post):
|
||||
# blog_posts = request.env['chennora.blog.post'].sudo().search([('active', '=', True)])
|
||||
# return request.render('dine360_theme_chennora.blog_page', {
|
||||
# 'blog_posts': blog_posts,
|
||||
# })
|
||||
#
|
||||
# @http.route(['/blog/<string:slug>'], type='http', auth='public', website=True)
|
||||
# def blog_detail(self, slug, **post):
|
||||
# blog_post = request.env['chennora.blog.post'].sudo().search([('slug', '=', slug), ('active', '=', True)], limit=1)
|
||||
# if not blog_post:
|
||||
# return request.not_found()
|
||||
#
|
||||
# recent_posts = request.env['chennora.blog.post'].sudo().search([('active', '=', True), ('id', '!=', blog_post.id)], limit=3)
|
||||
#
|
||||
# # Get dynamic categories and counts
|
||||
# all_posts = request.env['chennora.blog.post'].sudo().search([('active', '=', True)])
|
||||
# categories = {}
|
||||
# for p in all_posts:
|
||||
# if p.category:
|
||||
# categories[p.category] = categories.get(p.category, 0) + 1
|
||||
#
|
||||
# return request.render('dine360_theme_chennora.blog_detail_layout', {
|
||||
# 'blog_title': blog_post.title,
|
||||
# 'blog_img': blog_post.image,
|
||||
# 'blog_date': blog_post.date.strftime('%B %d, %Y') if blog_post.date else '',
|
||||
# 'blog_category': blog_post.category,
|
||||
# 'blog_content': blog_post.content,
|
||||
# 'recent_posts': recent_posts,
|
||||
# 'categories': categories,
|
||||
# })
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from . import controllers
|
||||
|
||||
@ -5,10 +5,11 @@
|
||||
'category': 'Theme/Website',
|
||||
'version': '1.0',
|
||||
'author': 'Dine360',
|
||||
'depends': ['website', 'website_sale', 'website_crm'],
|
||||
'depends': ['website', 'website_sale', 'website_crm', 'website_blog'],
|
||||
'data': [
|
||||
'views/layout.xml',
|
||||
'views/pages.xml',
|
||||
'views/shop_page.xml',
|
||||
'views/snippets.xml',
|
||||
'data/website_data.xml',
|
||||
],
|
||||
@ -16,6 +17,7 @@
|
||||
'web.assets_frontend': [
|
||||
'theme_clicks2cart/static/src/scss/primary_variables.scss',
|
||||
'theme_clicks2cart/static/src/scss/theme.scss',
|
||||
'theme_clicks2cart/static/src/scss/shop.scss',
|
||||
'theme_clicks2cart/static/src/js/quickview.js',
|
||||
],
|
||||
},
|
||||
|
||||
Binary file not shown.
1
addons/theme_clicks2cart/controllers/__init__.py
Normal file
1
addons/theme_clicks2cart/controllers/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import main
|
||||
Binary file not shown.
Binary file not shown.
15
addons/theme_clicks2cart/controllers/main.py
Normal file
15
addons/theme_clicks2cart/controllers/main.py
Normal file
@ -0,0 +1,15 @@
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
|
||||
class Clicks2CartBlog(http.Controller):
|
||||
@http.route(['/blog'], type='http', auth='public', website=True)
|
||||
def blog_list(self, **post):
|
||||
# Fetch actual blog posts if website_blog is installed
|
||||
# Otherwise, just show the template
|
||||
blog_posts = []
|
||||
if request.env.get('blog.post'):
|
||||
blog_posts = request.env['blog.post'].sudo().search([('website_published', '=', True)], limit=10)
|
||||
|
||||
return request.render('theme_clicks2cart.blog_page', {
|
||||
'blog_posts': blog_posts,
|
||||
})
|
||||
@ -1,7 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- We will exclude website creation from XML for now to prevent module loading issues
|
||||
and focus on getting the module visible first. Website can be created in UI -->
|
||||
<function model="website.page" name="write">
|
||||
<function model="website.page" name="search">
|
||||
<value eval="[('url', '=', '/blog'), ('website_id', '=', 6)]"/>
|
||||
</function>
|
||||
<value eval="{'view_id': ref('theme_clicks2cart.blog_page'), 'is_published': True}"/>
|
||||
</function>
|
||||
|
||||
<record id="blog_page_link" model="website.page">
|
||||
<field name="url">/blog</field>
|
||||
<field name="is_published">True</field>
|
||||
<field name="view_id" ref="theme_clicks2cart.blog_page"/>
|
||||
<field name="name">Blog</field>
|
||||
<field name="website_id" eval="6"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
428
addons/theme_clicks2cart/static/src/scss/shop.scss
Normal file
428
addons/theme_clicks2cart/static/src/scss/shop.scss
Normal file
@ -0,0 +1,428 @@
|
||||
/* Shop Page Decorative Backgrounds */
|
||||
#wrap.oe_structure:has(.oe_website_sale) {
|
||||
background-image:
|
||||
url('https://landing.engotheme.com/html/jenstore/demo/img/who.png'),
|
||||
url('https://landing.engotheme.com/html/jenstore/demo/img/who.png');
|
||||
background-repeat: no-repeat, no-repeat;
|
||||
background-position: left center, right bottom;
|
||||
background-size: 40% auto, 30% auto;
|
||||
background-attachment: fixed, absolute;
|
||||
background-color: #fff;
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
/* Hide Odoo Default Controls & Redundant Bars */
|
||||
.o_wsale_products_searchbar_formres,
|
||||
.o_wsale_products_searchbar_form,
|
||||
.o_wsale_products_searchbar,
|
||||
.o_wsale_apply_layout,
|
||||
.products_pager,
|
||||
.o_website_sale_search,
|
||||
#o_wsale_offcanvas_content {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Sidebar Styles */
|
||||
#products_grid_before {
|
||||
display: block !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
width: 25% !important;
|
||||
padding-right: 40px;
|
||||
flex: 0 0 25% !important;
|
||||
max-width: 25% !important;
|
||||
|
||||
.sidebar_title {
|
||||
font-family: 'Outfit', sans-serif !important;
|
||||
text-transform: uppercase !important;
|
||||
letter-spacing: 2px !important;
|
||||
font-weight: 800 !important;
|
||||
font-size: 1.1rem !important;
|
||||
color: #000 !important;
|
||||
margin-bottom: 25px !important;
|
||||
display: block;
|
||||
border-bottom: 3px solid #000;
|
||||
padding-bottom: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.s_sidebar_card {
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
margin-bottom: 45px;
|
||||
padding: 0;
|
||||
|
||||
/* Category specific tweaks */
|
||||
#wsale_products_categories_collapse {
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.nav-pills {
|
||||
.nav-item {
|
||||
border-bottom: 1px solid #f2f2f2;
|
||||
&:last-child { border-bottom: none; }
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
padding: 12px 0;
|
||||
color: #333;
|
||||
font-size: 0.95rem;
|
||||
font-family: 'Outfit', sans-serif;
|
||||
transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
text-transform: capitalize;
|
||||
letter-spacing: 0.5px;
|
||||
font-weight: 600;
|
||||
background: transparent !important;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&:hover, &.active {
|
||||
color: #e6b3a3 !important;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
span.badge {
|
||||
font-weight: 400;
|
||||
color: #999;
|
||||
font-size: 0.8rem;
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Plus/Minus Icons */
|
||||
&[data-bs-toggle="collapse"]:after {
|
||||
font-family: 'FontAwesome';
|
||||
content: '\f067';
|
||||
font-size: 0.75rem;
|
||||
color: #bbb;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
&[aria-expanded="true"]:after {
|
||||
content: '\f068';
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Attributes Styling (Color circles, Sizes) */
|
||||
.js_attributes {
|
||||
.nav-item {
|
||||
border: none;
|
||||
margin-bottom: 35px;
|
||||
|
||||
/* Attribute headers */
|
||||
h6, strong {
|
||||
@extend .sidebar_title;
|
||||
font-size: 0.95rem !important;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* Color circles */
|
||||
ul.nav-pills {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
margin-top: 15px;
|
||||
border: none !important;
|
||||
|
||||
li.nav-item {
|
||||
margin: 0;
|
||||
border: none !important;
|
||||
|
||||
label.nav-link {
|
||||
border: 1px solid #eee;
|
||||
border-radius: 50% !important;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
|
||||
&.active {
|
||||
box-shadow: 0 0 0 2px #fff, 0 0 0 4px #000;
|
||||
}
|
||||
|
||||
input { display: none; }
|
||||
&:after { content: none !important; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Price Filter Styling */
|
||||
.o_wsale_price_range_selector {
|
||||
padding: 0 10px;
|
||||
margin-top: 15px;
|
||||
|
||||
.ui_slider_handle {
|
||||
background: #000 !important;
|
||||
border: none !important;
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
top: -6px !important;
|
||||
border-radius: 50% !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ui_slider_range {
|
||||
background: #000 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Redirection adjustments for main grid */
|
||||
#products_grid {
|
||||
flex: 0 0 75% !important;
|
||||
max-width: 75% !important;
|
||||
width: 75% !important;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
/* Product Grid Top Bar */
|
||||
.products_header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 25px;
|
||||
background: #f4f4f4;
|
||||
margin-bottom: 50px;
|
||||
font-family: 'Outfit', sans-serif;
|
||||
border-radius: 2px;
|
||||
|
||||
.products_header_left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 25px;
|
||||
|
||||
.btn_sidebar_toggle {
|
||||
background: #fff;
|
||||
border: 1px solid #ddd;
|
||||
color: #000;
|
||||
padding: 7px 18px;
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
font-weight: 800;
|
||||
letter-spacing: 1.5px;
|
||||
}
|
||||
|
||||
.view_mode_icons {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
color: #bbb;
|
||||
font-size: 1.1rem;
|
||||
|
||||
i {
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
&.active { color: #000; }
|
||||
&:hover { color: #000; }
|
||||
}
|
||||
}
|
||||
|
||||
.results_count {
|
||||
color: #666;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.products_header_right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
|
||||
.show_filter, .sort_filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
span { font-size: 0.85rem; color: #888; font-weight: 500; }
|
||||
}
|
||||
|
||||
.form-select, .btn-sm {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
background: transparent;
|
||||
border: 1px solid #eee;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Product Cards */
|
||||
.oe_product {
|
||||
margin-bottom: 60px;
|
||||
|
||||
.oe_product_cart {
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
|
||||
.oe_product_image {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: #f7f7f7;
|
||||
aspect-ratio: 1/1.2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 1s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
}
|
||||
|
||||
.s_product_label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 6px 15px;
|
||||
font-size: 0.65rem;
|
||||
font-weight: 900;
|
||||
letter-spacing: 2.5px;
|
||||
color: #fff;
|
||||
z-index: 10;
|
||||
font-family: 'Outfit', sans-serif;
|
||||
|
||||
&.label-sale { background: #e6b3a3; }
|
||||
&.label-hot { background: #fd8b6b; }
|
||||
}
|
||||
|
||||
.s_product_actions {
|
||||
position: absolute;
|
||||
bottom: -70px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 15px;
|
||||
padding: 20px;
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
z-index: 5;
|
||||
|
||||
.action-btn {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
background: #fff;
|
||||
border: 1px solid #efefef;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #111;
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
text-decoration: none;
|
||||
font-size: 1rem;
|
||||
|
||||
&:hover {
|
||||
background: #000;
|
||||
color: #fff;
|
||||
border-color: #000;
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.oe_product_image {
|
||||
img {
|
||||
transform: scale(1.15);
|
||||
}
|
||||
.s_product_actions {
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 25px 0 10px;
|
||||
text-align: center;
|
||||
|
||||
h6 {
|
||||
font-family: 'Outfit', sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 1.15rem;
|
||||
margin-bottom: 10px;
|
||||
letter-spacing: 0.5px;
|
||||
|
||||
a {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s;
|
||||
&:hover { color: #e6b3a3; }
|
||||
}
|
||||
}
|
||||
|
||||
.o_rating_star_card {
|
||||
color: #ffc107;
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.product_price {
|
||||
font-family: 'Outfit', sans-serif;
|
||||
font-weight: 900;
|
||||
font-size: 1.25rem;
|
||||
color: #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
|
||||
del {
|
||||
font-size: 0.95rem;
|
||||
color: #ccc;
|
||||
font-weight: 500;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Pagination */
|
||||
.o_wsale_products_grid_table_wrapper {
|
||||
.pagination {
|
||||
margin-top: 70px;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
|
||||
.page-item {
|
||||
.page-link {
|
||||
border: 1px solid #eee;
|
||||
background: #fcfcfc;
|
||||
color: #000;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 800;
|
||||
font-size: 0.95rem;
|
||||
border-radius: 4px !important;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: #eee;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
&.active .page-link {
|
||||
background: #000 !important;
|
||||
color: #fff !important;
|
||||
border-color: #000 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1254,6 +1254,56 @@ footer#bottom.o_footer {
|
||||
}
|
||||
}
|
||||
|
||||
.s_holiday_section {
|
||||
position: relative;
|
||||
// padding: 120px 0;
|
||||
overflow: hidden;
|
||||
|
||||
.s_holiday_bg_accent {
|
||||
position: absolute;
|
||||
top: -150px;
|
||||
left: -100px;
|
||||
width: 450px;
|
||||
height: 450px;
|
||||
background-image: url('https://landing.engotheme.com/html/jenstore/demo/img/floral_accent_tl.png');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0.1;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
|
||||
.s_holiday_bg_accent_br {
|
||||
position: absolute;
|
||||
bottom: -100px;
|
||||
right: -80px;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-image: url('https://landing.engotheme.com/html/jenstore/demo/img/decor-flower.png');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0.12;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
transform: scaleX(-1) rotate(30deg);
|
||||
}
|
||||
|
||||
.s_holiday_splash {
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
left: -5%;
|
||||
width: 40vw;
|
||||
height: 60vh;
|
||||
background-image: url('https://landing.engotheme.com/html/jenstore/demo/img/wedding_brush_splash.png');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0.04;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// Product Action Hover Icons (Global)
|
||||
// =========================================
|
||||
|
||||
@ -405,8 +405,10 @@
|
||||
|
||||
<!-- Holiday Section -->
|
||||
<section class="s_holiday_section">
|
||||
<!-- Top accent floral -->
|
||||
<!-- Elementor-style Decorations -->
|
||||
<div class="s_holiday_bg_accent" aria-hidden="true"></div>
|
||||
<div class="s_holiday_bg_accent_br" aria-hidden="true"></div>
|
||||
<div class="s_holiday_splash" aria-hidden="true"></div>
|
||||
|
||||
<div class="container">
|
||||
<!-- Section Header -->
|
||||
@ -839,4 +841,72 @@
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Blog Page Template -->
|
||||
<template id="blog_page" name="Blog Page">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="oe_structure">
|
||||
<section class="s_blog_page_header py-5" style="background: #fafafa; border-bottom: 1px solid #eee;">
|
||||
<div class="container text-center">
|
||||
<h1 class="display-4 fw-bold mb-3" style="font-family: 'Playfair Display', serif; color: #333;">Our Blog</h1>
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb justify-content-center mb-0" style="background: transparent;">
|
||||
<li class="breadcrumb-item"><a href="/" class="text-decoration-none" style="color: #e6b3a3;">Home</a></li>
|
||||
<li class="breadcrumb-item active text-muted" aria-current="page">Blog</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="s_blog_listing py-5" style="background: #fff;">
|
||||
<div class="container">
|
||||
<div class="row g-4">
|
||||
<t t-if="not blog_posts">
|
||||
<!-- Fallback Static Content -->
|
||||
<t t-foreach="[1,2,3,4,5,6]" t-as="i">
|
||||
<div class="col-lg-4 col-md-6">
|
||||
<div class="s_blog_card mb-4" style="transition: transform 0.3s ease;">
|
||||
<div class="s_blog_img_wrap overflow-hidden" style="height: 250px;">
|
||||
<img t-attf-src="/theme_clicks2cart/static/src/img/blog_listing_#{i}.png"
|
||||
onerror="this.src='/theme_clicks2cart/static/src/img/flora_col.png'"
|
||||
class="img-fluid w-100 h-100 object-fit-cover"
|
||||
alt="Blog"/>
|
||||
</div>
|
||||
<div class="s_blog_info p-4 border border-top-0">
|
||||
<div class="s_blog_meta mb-2" style="font-size: 0.8rem; color: #888; font-family: 'Outfit';">
|
||||
<span><i class="fa fa-calendar-o me-1"></i> May 12, 2024</span>
|
||||
<span class="mx-2">|</span>
|
||||
<span><i class="fa fa-user-o me-1"></i> Admin</span>
|
||||
</div>
|
||||
<h4 class="s_blog_name mb-3" style="font-family: 'Playfair Display'; font-weight: 700; color: #222; font-size: 1.25rem;">The Secret of Beautiful Roses</h4>
|
||||
<p class="s_blog_desc mb-3 text-muted" style="font-size: 0.9rem; line-height: 1.6;">Discover how to keep your roses fresh for weeks with our simple yet effective care secrets.</p>
|
||||
<a href="#" class="btn-link text-decoration-none fw-bold" style="color: #e6b3a3; font-size: 0.9rem; letter-spacing: 1px;">READ MORE <i class="fa fa-long-arrow-right ms-1"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
<t t-foreach="blog_posts" t-as="blog">
|
||||
<div class="col-lg-4 col-md-6">
|
||||
<div class="s_blog_card mb-4">
|
||||
<div class="s_blog_img_wrap overflow-hidden" style="height: 250px;">
|
||||
<img t-att-src="website.image_url(blog, 'image_1024')" class="img-fluid w-100 h-100 object-fit-cover" t-att-alt="blog.name"/>
|
||||
</div>
|
||||
<div class="s_blog_info p-4 border border-top-0">
|
||||
<div class="s_blog_meta mb-2" style="font-size: 0.8rem; color: #888; font-family: 'Outfit';">
|
||||
<span t-field="blog.post_date" t-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<h4 class="s_blog_name mb-3" style="font-family: 'Playfair Display'; font-weight: 700; color: #222; font-size: 1.25rem;" t-field="blog.name"/>
|
||||
<p class="s_blog_desc mb-3 text-muted" style="font-size: 0.9rem; line-height: 1.6;" t-field="blog.subtitle"/>
|
||||
<a t-attf-href="/blog/#{blog.id}" class="btn-link text-decoration-none fw-bold" style="color: #e6b3a3; font-size: 0.9rem; letter-spacing: 1px;">READ MORE <i class="fa fa-long-arrow-right ms-1"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
</odoo>
|
||||
|
||||
129
addons/theme_clicks2cart/views/shop_page.xml
Normal file
129
addons/theme_clicks2cart/views/shop_page.xml
Normal file
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Shop Page Banner & Layout Refinement -->
|
||||
<template id="shop_banner_inherit" inherit_id="website_sale.products" name="Shop Banner">
|
||||
<!-- Force Sidebar Visibility and Layout -->
|
||||
<xpath expr="//div[contains(@class, 'o_wsale_products_main_row')]" position="attributes">
|
||||
<attribute name="class" add="d-flex flex-row flex-wrap" separator=" "/>
|
||||
</xpath>
|
||||
<xpath expr="//*[@id='products_grid_before']" position="attributes">
|
||||
<attribute name="class" remove="d-none" separator=" "/>
|
||||
<attribute name="class" add="col-lg-3 d-block pe-4" separator=" "/>
|
||||
</xpath>
|
||||
<xpath expr="//*[@id='products_grid']" position="attributes">
|
||||
<attribute name="class" remove="col-lg-12" separator=" "/>
|
||||
<attribute name="class" add="col-lg-9" separator=" "/>
|
||||
</xpath>
|
||||
|
||||
<!-- Customize Top Bar -->
|
||||
<xpath expr="//div[hasclass('o_wsale_products_main_row')]" position="before">
|
||||
<div class="products_header">
|
||||
<div class="products_header_left">
|
||||
<button class="btn btn_sidebar_toggle d-lg-none" data-bs-toggle="collapse" data-bs-target="#products_grid_before">
|
||||
Show Sidebar
|
||||
</button>
|
||||
<div class="view_mode_icons d-none d-lg-flex">
|
||||
<i class="fa fa-th active"/>
|
||||
<i class="fa fa-list"/>
|
||||
</div>
|
||||
<div class="results_count d-none d-md-block">
|
||||
<span>Showing 1 - 12 of 28 results</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="products_header_right">
|
||||
<div class="show_filter">
|
||||
<span>Show</span>
|
||||
<select class="form-select form-select-sm">
|
||||
<option>12</option>
|
||||
<option>24</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="sort_filter">
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
||||
Default sorting
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#">Price: Low to High</a></li>
|
||||
<li><a class="dropdown-item" href="#">Price: High to Low</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Customize Product Item -->
|
||||
<template id="shop_product_item_inherit" inherit_id="website_sale.products_item" name="Shop Product Item">
|
||||
<xpath expr="//form" position="replace">
|
||||
<t t-set="combination_info" t-value="product._get_combination_info(only_template=True, add_qty=add_qty or 1)"/>
|
||||
<div class="oe_product_cart" t-att-data-publish="product.website_published and 'on' or 'off'" itemscope="itemscope" itemtype="http://schema.org/Product">
|
||||
<div class="oe_product_image position-relative">
|
||||
<!-- Badges -->
|
||||
<t t-if="product.website_id.id % 2 == 0">
|
||||
<span class="s_product_label label-sale">SALE</span>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span class="s_product_label label-hot">HOT</span>
|
||||
</t>
|
||||
|
||||
<a t-att-href="product_href" class="d-block h-100" itemprop="url">
|
||||
<t t-set="image_holder" t-value="product._get_image_holder()"/>
|
||||
<img t-att-src="website.image_url(image_holder, 'image_512')" class="img-fluid d-block mx-auto" t-att-alt="product.name" loading="lazy"/>
|
||||
</a>
|
||||
|
||||
<!-- Hover Actions -->
|
||||
<div class="s_product_actions">
|
||||
<a href="#" class="action-btn quick-view"
|
||||
t-att-data-name="product.name"
|
||||
t-att-data-price="combination_info['price']"
|
||||
t-att-data-img="website.image_url(product, 'image_1024')"
|
||||
t-att-data-desc="product.description_sale or 'Premium floral arrangement for your special occasions.'">
|
||||
<i class="fa fa-eye"></i>
|
||||
</a>
|
||||
<a href="#" class="action-btn add-to-cart"><i class="fa fa-shopping-cart"></i></a>
|
||||
<a href="#" class="action-btn wishlist"><i class="fa fa-heart-o"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section>
|
||||
<div class="o_rating_star_card">
|
||||
<i class="fa fa-star"/>
|
||||
<i class="fa fa-star"/>
|
||||
<i class="fa fa-star"/>
|
||||
<i class="fa fa-star"/>
|
||||
<i class="fa fa-star-o"/>
|
||||
</div>
|
||||
<h6>
|
||||
<a t-att-href="product_href" itemprop="name" t-field="product.name"/>
|
||||
</h6>
|
||||
<div class="product_price" itemprop="offers" itemscope="itemscope" itemtype="http://schema.org/Offer">
|
||||
<span t-if="combination_info['price']" t-esc="combination_info['price']" t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
|
||||
<del t-if="combination_info['has_discounted_price']" t-esc="combination_info['list_price']" t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Upgrade Sidebar UI: Categories -->
|
||||
<template id="shop_sidebar_categories_inherit" inherit_id="website_sale.products_categories" name="Shop Sidebar Categories">
|
||||
<xpath expr="//div[@id='wsale_products_categories_collapse']" position="before">
|
||||
<h6 class="sidebar_title">Categories</h6>
|
||||
</xpath>
|
||||
<xpath expr="//div[@id='wsale_products_categories_collapse']" position="attributes">
|
||||
<attribute name="class" add="s_sidebar_card" separator=" "/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Upgrade Sidebar UI: Attributes/Filters -->
|
||||
<template id="shop_sidebar_attributes_inherit" inherit_id="website_sale.products_attributes" name="Shop Sidebar Attributes">
|
||||
<xpath expr="//form" position="attributes">
|
||||
<attribute name="class" add="s_sidebar_card" separator=" "/>
|
||||
</xpath>
|
||||
<xpath expr="//form//t[1]" position="before">
|
||||
<!-- This will be styled via CSS if needed, or we can add individual headers -->
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
Loading…
x
Reference in New Issue
Block a user