introduce tncsc_deployment addon featuring community dashboard views, controllers, and custom branding assets
Some checks failed
CI / Brand-leak check (push) Has been cancelled
CI / flake8 / pylint-odoo / manifest completeness (push) Has been cancelled
CI / Install all modules with --test-enable (push) Has been cancelled

This commit is contained in:
Alaguraj0361 2026-09-26 15:46:17 +05:30
parent 56dd9f5596
commit 3ad1bc980d
20 changed files with 3320 additions and 138 deletions

View File

@ -46,12 +46,28 @@ that applies to the community_* product modules.
'data/ir_cron.xml', 'data/ir_cron.xml',
'views/website_pages.xml', 'views/website_pages.xml',
'views/event_kanban_views.xml', 'views/event_kanban_views.xml',
'views/community_dashboard_views.xml',
'views/login_templates.xml',
], ],
'demo': [], 'demo': [],
'assets': { 'assets': {
'web._assets_primary_variables': [
'tncsc_deployment/static/src/scss/primary_variables.scss',
],
'web.assets_frontend': [
'tncsc_deployment/static/src/scss/login_theme.scss',
],
'web.assets_backend': [ 'web.assets_backend': [
'tncsc_deployment/static/src/scss/tncsc_backend_theme.scss',
'tncsc_deployment/static/src/scss/event_kanban.scss', 'tncsc_deployment/static/src/scss/event_kanban.scss',
'tncsc_deployment/static/src/scss/community_dashboard.scss',
'tncsc_deployment/static/src/scss/login_theme.scss',
'tncsc_deployment/static/src/js/event_kanban_renderer.js',
'tncsc_deployment/static/src/js/community_dashboard.js',
'tncsc_deployment/static/src/js/global_sidebar.js',
'tncsc_deployment/static/src/xml/kanban_empty_column.xml', 'tncsc_deployment/static/src/xml/kanban_empty_column.xml',
'tncsc_deployment/static/src/xml/community_dashboard.xml',
'tncsc_deployment/static/src/xml/global_sidebar.xml',
], ],
}, },
'application': False, 'application': False,

View File

@ -1 +1,3 @@
# -*- coding: utf-8 -*-
from . import main from . import main
from . import dashboard

View File

@ -0,0 +1,115 @@
# -*- coding: utf-8 -*-
from odoo import http
from odoo.http import request
class TNCSCCommunityDashboardController(http.Controller):
@http.route('/community/dashboard/stats', type='jsonrpc', auth='user')
def get_dashboard_stats(self):
env = request.env
# 1. Membership Stats
Partner = env['res.partner']
Tier = env['community.membership.tier']
total_members = Partner.search_count([('is_company', '=', False)])
active_members = Partner.search_count([('membership_state', '=', 'active')])
renewal_due = Partner.search_count([('membership_state', '=', 'renewal_due')])
expired_members = Partner.search_count([('membership_state', '=', 'expired')])
tiers_data = []
try:
for tier in Tier.search([], order='sequence asc'):
count = Partner.search_count([('membership_tier_id', '=', tier.id)])
tiers_data.append({
'id': tier.id,
'name': tier.name,
'price': f"${tier.price:,.0f}" if tier.price else "$0",
'period': tier.period,
'count': count,
})
except Exception:
pass
# 2. Events Stats
Event = env['event.event']
total_events = Event.search_count([])
upcoming_events = []
try:
events_records = Event.search([], order='date_begin asc', limit=6)
for ev in events_records:
city = 'Mississauga, ON'
if ev.address_id and ev.address_id.city:
city = f"{ev.address_id.city}, ON"
upcoming_events.append({
'id': ev.id,
'name': ev.name,
'date_begin': ev.date_begin.strftime('%b %d, %Y - %I:%M %p') if ev.date_begin else 'TBD',
'date_short': ev.date_begin.strftime('%d %b') if ev.date_begin else '',
'day': ev.date_begin.strftime('%d') if ev.date_begin else '',
'month_year': ev.date_begin.strftime('%b %Y') if ev.date_begin else '',
'city': city,
'stage': ev.stage_id.name if ev.stage_id else 'New',
'seats_taken': ev.seats_taken,
'seats_max': ev.seats_max,
})
except Exception:
pass
# 3. Tamil School Stats
Student = env.get('community.school.student')
Class = env.get('community.school.class')
Term = env.get('community.school.term')
students_count = Student.search_count([]) if Student else 0
classes_count = Class.search_count([]) if Class else 0
terms_count = Term.search_count([]) if Term else 0
# 4. Classifieds Stats
Classified = env.get('community.classified')
classifieds_count = Classified.search_count([]) if Classified else 0
# 5. Benefits Stats
Benefit = env.get('community.benefit')
PartnerBenefit = env.get('community.benefit.partner')
benefits_count = Benefit.search_count([]) if Benefit else 0
partners_count = PartnerBenefit.search_count([]) if PartnerBenefit else 0
# 6. Interac Transactions Stats
Tx = env.get('payment.transaction')
interac_count = 0
if Tx:
try:
interac_count = Tx.search_count([('provider_id.code', '=', 'interac')])
except Exception:
pass
return {
'membership': {
'total': total_members,
'active': active_members,
'renewal_due': renewal_due,
'expired': expired_members,
'tiers': tiers_data,
},
'events': {
'total': total_events,
'upcoming': upcoming_events,
},
'school': {
'students': students_count,
'classes': classes_count,
'terms': terms_count,
},
'classifieds': {
'total': classifieds_count,
},
'benefits': {
'total': benefits_count,
'partners': partners_count,
},
'interac': {
'total': interac_count,
},
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 KiB

View File

@ -0,0 +1,225 @@
/** @odoo-module **/
import { Component, useState, onWillStart } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
import { rpc } from "@web/core/network/rpc";
export class CommunityDashboard extends Component {
static template = "tncsc_deployment.CommunityDashboard";
setup() {
this.actionService = useService("action");
this.notification = useService("notification");
this.state = useState({
loading: true,
activeTab: "dashboard",
stats: {
membership: {
total: 5,
active: 0,
renewal_due: 0,
expired: 0,
tiers: [
{ name: "Individual", price: "$50", period: "Annual", count: 0, icon: "fa-user" },
{ name: "Family", price: "$80", period: "Annual", count: 0, icon: "fa-users" },
{ name: "Student", price: "$20", period: "Annual", count: 0, icon: "fa-graduation-cap" },
{ name: "Senior", price: "$30", period: "Annual", count: 0, icon: "fa-ribbon" },
{ name: "Life", price: "$500", period: "One_time", count: 0, icon: "fa-crown" },
],
},
events: {
total: 4,
upcoming: [
{
id: 1,
name: "Pongal Celebration",
day: "18",
month_year: "JAN 2026",
city: "Brampton, ON",
date_begin: "Jan 18, 2026 - 04:30 AM",
date_short: "18 Jan",
stage: "Booked",
},
{
id: 2,
name: "Tamil New Year Festival",
day: "14",
month_year: "APR 2026",
city: "Toronto, ON",
date_begin: "Apr 14, 2026 - 10:00 AM",
date_short: "14 Apr",
stage: "Ended",
},
{
id: 3,
name: "TNCSC's Summer Picnic 2026",
day: "11",
month_year: "OCT 2026",
city: "Mississauga, ON",
date_begin: "Oct 11, 2026 - 11:00 AM",
date_short: "11 Oct",
stage: "New",
},
{
id: 4,
name: "Diwali Celebration",
day: "05",
month_year: "NOV 2026",
city: "Scarborough, ON",
date_begin: "Nov 05, 2026 - 06:00 PM",
date_short: "05 Nov",
stage: "Booked",
},
],
},
school: { students: 0, classes: 0, terms: 0 },
classifieds: { total: 0 },
benefits: { total: 0, partners: 0 },
interac: { total: 0 },
},
});
onWillStart(async () => {
await this.loadStats();
});
}
async loadStats() {
this.state.loading = true;
try {
const data = await rpc("/community/dashboard/stats", {});
if (data) {
if (data.membership) {
this.state.stats.membership.total = data.membership.total || 0;
this.state.stats.membership.active = data.membership.active || 0;
this.state.stats.membership.renewal_due = data.membership.renewal_due || 0;
this.state.stats.membership.expired = data.membership.expired || 0;
if (data.membership.tiers && data.membership.tiers.length > 0) {
const iconMap = {
"Individual": "fa-user",
"Family": "fa-users",
"Student": "fa-graduation-cap",
"Senior": "fa-ribbon",
"Life": "fa-crown",
};
this.state.stats.membership.tiers = data.membership.tiers.map((t) => ({
...t,
icon: iconMap[t.name] || "fa-id-badge",
}));
}
}
if (data.events) {
this.state.stats.events.total = data.events.total || 0;
if (data.events.upcoming && data.events.upcoming.length > 0) {
this.state.stats.events.upcoming = data.events.upcoming;
}
}
if (data.school) this.state.stats.school = data.school;
if (data.classifieds) this.state.stats.classifieds = data.classifieds;
if (data.benefits) this.state.stats.benefits = data.benefits;
if (data.interac) this.state.stats.interac = data.interac;
}
} catch (error) {
console.error("Failed to load community dashboard stats", error);
} finally {
this.state.loading = false;
}
}
openMembers() {
this.actionService.doAction("community_membership.action_membership_members");
}
openTiers() {
this.actionService.doAction("community_membership.action_membership_tier");
}
openEvents() {
this.actionService.doAction("event.action_event_view");
}
openEvent(eventId) {
if (!eventId) {
this.openEvents();
return;
}
this.actionService.doAction({
type: "ir.actions.act_window",
res_model: "event.event",
res_id: eventId,
views: [[false, "form"]],
target: "current",
});
}
openSchool() {
this.actionService.doAction("community_school.action_school_student");
}
openSchoolClasses() {
this.actionService.doAction("community_school.action_school_class");
}
openBenefits() {
this.actionService.doAction("community_benefits.action_benefit");
}
openClassifieds() {
this.actionService.doAction("community_classifieds.action_classified_moderation");
}
openMarketplace() {
this.actionService.doAction("community_classifieds.action_classified_moderation");
}
openCulturalPrograms() {
this.actionService.doAction("event.action_event_view");
}
openReports() {
this.actionService.doAction("event.event_registration_action");
}
openSettings() {
this.actionService.doAction("base.action_res_users");
}
openInterac() {
this.actionService.doAction("community_interac.action_payment_transaction_interac_pending");
}
openNewEvent() {
this.actionService.doAction({
type: "ir.actions.act_window",
res_model: "event.event",
views: [[false, "form"]],
target: "current",
});
}
openNewMember() {
this.actionService.doAction({
type: "ir.actions.act_window",
res_model: "res.partner",
views: [[false, "form"]],
context: { default_is_company: false },
target: "current",
});
}
openNewStudent() {
this.actionService.doAction({
type: "ir.actions.act_window",
res_model: "community.school.student",
views: [[false, "form"]],
target: "current",
});
}
async refreshDashboard() {
await this.loadStats();
}
}
registry.category("actions").add("tncsc_community_dashboard", CommunityDashboard);

View File

@ -0,0 +1,112 @@
/** @odoo-module **/
import { KanbanRenderer } from "@web/views/kanban/kanban_renderer";
import { patch } from "@web/core/utils/patch";
patch(KanbanRenderer.prototype, {
setup() {
super.setup(...arguments);
if (this.isTncscEventKanban) {
this.state.tncscActiveStage = "all";
}
},
get isTncscEventKanban() {
return Boolean(this.props.list && this.props.list.resModel === "event.event");
},
get tncscStageCounts() {
const counts = {
all: 0,
new: 0,
booked: 0,
announced: 0,
ended: 0,
};
if (!this.props.list) {
return counts;
}
if (this.props.list.isGrouped && this.props.list.groups) {
for (const group of this.props.list.groups) {
const name = (group.displayName || "").trim().toLowerCase();
const count = group.count || 0;
counts.all += count;
if (name === "new") {
counts.new += count;
} else if (name === "booked") {
counts.booked += count;
} else if (name === "announced") {
counts.announced += count;
} else if (name === "ended") {
counts.ended += count;
}
}
} else if (this.props.list.records) {
counts.all = this.props.list.records.length;
for (const record of this.props.list.records) {
const stageVal = record.data && record.data.stage_id;
const name = (Array.isArray(stageVal) ? stageVal[1] : (stageVal || ""))
.trim()
.toLowerCase();
if (name === "new") {
counts.new += 1;
} else if (name === "booked") {
counts.booked += 1;
} else if (name === "announced") {
counts.announced += 1;
} else if (name === "ended") {
counts.ended += 1;
}
}
}
return counts;
},
setTncscStage(stage) {
if (this.state.tncscActiveStage === stage) {
return;
}
this.state.tncscActiveStage = stage;
},
getGroupsOrRecords() {
const items = super.getGroupsOrRecords();
if (!this.isTncscEventKanban) {
return items;
}
const activeStage = this.state.tncscActiveStage || "all";
if (activeStage === "all") {
return items;
}
if (this.props.list.isGrouped) {
return items.filter((item) => {
if (!item.group) {
return true;
}
const name = (item.group.displayName || "").trim().toLowerCase();
return name === activeStage;
});
} else {
return items.filter((item) => {
if (!item.record) {
return true;
}
const stageVal = item.record.data && item.record.data.stage_id;
const name = (Array.isArray(stageVal) ? stageVal[1] : (stageVal || ""))
.trim()
.toLowerCase();
return name === activeStage;
});
}
},
getGroupClasses(group, isGroupProcessing) {
const classes = super.getGroupClasses(...arguments);
if (this.isTncscEventKanban && this.state.tncscActiveStage && this.state.tncscActiveStage !== "all") {
return `${classes} o_tncsc_single_stage_group`;
}
return classes;
},
});

View File

@ -0,0 +1,152 @@
/** @odoo-module **/
import { Component, useState, onWillStart, onMounted } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { useService, useBus } from "@web/core/utils/hooks";
import { routerBus } from "@web/core/browser/router";
export class TncscGlobalSidebar extends Component {
static template = "tncsc_deployment.GlobalSidebar";
setup() {
this.actionService = useService("action");
this.state = useState({
activeTab: "dashboard",
collapsed: false,
});
useBus(routerBus, "ROUTE_CHANGE", () => {
this.updateActiveTab();
setTimeout(() => this.updateActiveTab(), 80);
});
useBus(this.env.bus, "ACTION_MANAGER:UPDATE", () => {
this.updateActiveTab();
setTimeout(() => this.updateActiveTab(), 80);
});
onMounted(() => {
this.updateActiveTab();
setTimeout(() => this.updateActiveTab(), 80);
});
}
updateActiveTab() {
try {
const currentController = this.actionService.currentController;
const action = currentController?.action;
const resModel = action?.res_model || "";
const actionTag = action?.tag || "";
const actionPath = action?.path || "";
const xmlId = action?.xml_id || "";
const actionName = (action?.name || "").toLowerCase();
const currentUrl = window.location.href;
if (
actionTag === "tncsc_community_dashboard" ||
actionPath === "community-dashboard" ||
currentUrl.includes("/odoo/community-dashboard")
) {
this.state.activeTab = "dashboard";
} else if (
xmlId.includes("membership") ||
actionName.includes("member") ||
resModel.includes("membership") ||
(resModel === "res.partner" && !actionName.includes("school") && !actionName.includes("contact"))
) {
this.state.activeTab = "members";
} else if (
xmlId.includes("event.action_event_view") ||
(resModel === "event.event" && !actionName.includes("registration")) ||
actionName === "events"
) {
this.state.activeTab = "events";
} else if (
xmlId.includes("school") ||
resModel.includes("school") ||
actionName.includes("school") ||
actionName.includes("student")
) {
this.state.activeTab = "school";
} else if (
xmlId.includes("benefit") ||
resModel.includes("benefit") ||
resModel.includes("classified") ||
actionName.includes("benefit") ||
actionName.includes("marketplace") ||
actionName.includes("classified")
) {
this.state.activeTab = "benefits";
} else if (
actionName.includes("cultural")
) {
this.state.activeTab = "cultural";
} else if (
xmlId.includes("registration") ||
resModel.includes("registration") ||
actionName.includes("registration") ||
actionName.includes("report")
) {
this.state.activeTab = "reports";
} else if (
resModel.includes("res.users") ||
resModel.includes("res.config") ||
actionName.includes("setting") ||
actionName.includes("user")
) {
this.state.activeTab = "settings";
}
} catch {
// fallback
}
}
openDashboard() {
this.state.activeTab = "dashboard";
this.actionService.doAction("tncsc_deployment.action_community_dashboard", { clearBreadcrumbs: true });
}
openMembers() {
this.state.activeTab = "members";
this.actionService.doAction("community_membership.action_membership_members", { clearBreadcrumbs: true });
}
openEvents() {
this.state.activeTab = "events";
this.actionService.doAction("event.action_event_view", { clearBreadcrumbs: true });
}
openSchool() {
this.state.activeTab = "school";
this.actionService.doAction("community_school.action_school_student", { clearBreadcrumbs: true });
}
openBenefits() {
this.state.activeTab = "benefits";
this.actionService.doAction("community_benefits.action_benefit", { clearBreadcrumbs: true });
}
openCulturalPrograms() {
this.state.activeTab = "cultural";
this.actionService.doAction("event.action_event_view", { clearBreadcrumbs: true });
}
openReports() {
this.state.activeTab = "reports";
this.actionService.doAction("event.event_registration_action", { clearBreadcrumbs: true });
}
openSettings() {
this.state.activeTab = "settings";
this.actionService.doAction("base.action_res_users", { clearBreadcrumbs: true });
}
toggleCollapse() {
this.state.collapsed = !this.state.collapsed;
document.body.classList.toggle("o_tncsc_sidebar_collapsed", this.state.collapsed);
}
}
registry.category("main_components").add("tncsc_global_sidebar", {
Component: TncscGlobalSidebar,
});

View File

@ -0,0 +1,759 @@
/* ==========================================================================
TNCSC EXECUTIVE COMMUNITY DASHBOARD & GLOBAL SIDEBAR (EXACT THEME MATCH)
========================================================================== */
// ----------------------------------------------------------------------
// 1. PERSISTENT GLOBAL SIDEBAR (PRESENT ON ALL PAGES)
// ----------------------------------------------------------------------
.o_tncsc_global_sidebar {
position: fixed !important;
top: 0 !important;
left: 0 !important;
bottom: 0 !important;
width: 220px !important;
min-width: 220px !important;
max-width: 220px !important;
height: 100vh !important;
background: #080A10 !important;
border-right: 1px solid rgba(216, 156, 67, 0.22) !important;
padding: 24px 14px 18px 14px !important;
box-sizing: border-box !important;
z-index: 1050 !important;
overflow-y: auto !important;
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background: rgba(216, 156, 67, 0.2);
border-radius: 4px;
}
.o_sidebar_brand {
cursor: pointer !important;
.o_sidebar_logo {
width: 44px !important;
height: auto !important;
margin-bottom: 8px !important;
filter: drop-shadow(0 2px 8px rgba(216, 156, 67, 0.4)) !important;
}
.o_brand_text_line1,
.o_brand_text_line2,
.o_brand_text_line3 {
font-family: 'Playfair Display', Georgia, serif !important;
font-size: 10px !important;
font-weight: 700 !important;
letter-spacing: 1px !important;
color: #D89C43 !important;
line-height: 1.3 !important;
}
}
.o_sidebar_nav {
.o_nav_item {
display: flex !important;
align-items: center !important;
gap: 12px !important;
padding: 10px 14px !important;
border-radius: 12px !important;
margin-bottom: 5px !important;
color: #94A3B8 !important;
font-size: 13px !important;
font-weight: 500 !important;
text-decoration: none !important;
cursor: pointer !important;
transition: all 0.2s ease !important;
&:hover {
background: rgba(255, 255, 255, 0.05) !important;
color: #FFFFFF !important;
}
.o_nav_icon {
font-size: 14px !important;
width: 18px !important;
text-align: center !important;
color: #94A3B8 !important;
transition: color 0.2s !important;
}
&.active {
background: #231C14 !important;
border: 1px solid rgba(216, 156, 67, 0.45) !important;
color: #E5A93C !important;
font-weight: 600 !important;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3), inset 0 0 12px rgba(216, 156, 67, 0.12) !important;
.o_nav_icon {
color: #E5A93C !important;
}
}
}
}
.o_sidebar_bottom {
margin-top: auto !important;
padding-top: 16px !important;
.o_chariot_img_wrap {
width: 100% !important;
display: flex !important;
justify-content: center !important;
.o_chariot_img {
width: 135px !important;
height: auto !important;
filter: drop-shadow(0 4px 14px rgba(216, 156, 67, 0.25)) !important;
mix-blend-mode: screen !important;
opacity: 0.85 !important;
}
}
.o_motto_wrap {
font-family: 'Playfair Display', Georgia, serif !important;
font-style: italic !important;
font-size: 12.5px !important;
color: #D89C43 !important;
line-height: 1.25 !important;
margin-top: 6px !important;
opacity: 0.9 !important;
}
}
}
// ----------------------------------------------------------------------
// 2. ROOT LAYOUT SHIFT FOR SIDEBAR ACROSS ENTIRE BACKEND
// ----------------------------------------------------------------------
.o_web_client {
padding-left: 220px !important;
width: 100% !important;
min-height: 100vh !important;
background: #090B12 !important;
box-sizing: border-box !important;
}
.o_main_navbar {
background: #080A10 !important;
border-bottom: 1px solid rgba(216, 156, 67, 0.22) !important;
}
// When on the community dashboard itself:
body:has(.o_tncsc_dashboard_root) {
.o_main_navbar {
display: none !important;
}
.o_action_manager {
height: 100vh !important;
overflow: hidden !important;
padding: 0 !important;
margin: 0 !important;
background: #090B12 !important;
}
.o_content {
padding: 0 !important;
margin: 0 !important;
overflow: hidden !important;
background: #090B12 !important;
height: 100vh !important;
}
.o_control_panel {
display: none !important;
}
}
.o_tncsc_dashboard_root {
width: 100% !important;
height: 100vh !important;
max-height: 100vh !important;
background: #090B12 !important;
color: #F8FAFC !important;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
box-sizing: border-box !important;
overflow: hidden !important;
// ----------------------------------------------------------------------
// 3. MAIN DASHBOARD CONTENT AREA
// ----------------------------------------------------------------------
.o_tncsc_main_content {
background: #090B12 !important;
overflow-y: auto !important;
height: 100% !important;
min-height: 100vh !important;
width: 100% !important;
// Custom scrollbar
&::-webkit-scrollbar {
width: 7px;
}
&::-webkit-scrollbar-track {
background: #090B12;
}
&::-webkit-scrollbar-thumb {
background: rgba(216, 156, 67, 0.3);
border-radius: 4px;
}
// Header with Gopuram Silhouette
.o_dashboard_header {
padding: 24px 32px 20px 32px !important;
background: linear-gradient(90deg, #090B12 0%, #090B12 35%, rgba(9, 11, 18, 0.82) 60%, rgba(9, 11, 18, 0.3) 100%),
url('/tncsc_deployment/static/src/img/dashboard/gopuram_header_bg.jpg') right center / cover no-repeat !important;
border-bottom: 1px solid rgba(216, 156, 67, 0.18) !important;
.o_society_tag {
font-size: 10.5px !important;
font-weight: 700 !important;
letter-spacing: 1.5px !important;
color: #D89C43 !important;
margin-bottom: 4px !important;
text-transform: uppercase !important;
}
.o_dashboard_title {
font-family: 'Playfair Display', Georgia, serif !important;
font-size: 30px !important;
font-weight: 700 !important;
color: #FFFFFF !important;
margin-bottom: 4px !important;
letter-spacing: 0.5px !important;
}
.o_dashboard_tagline {
font-size: 12.5px !important;
color: #C5B495 !important;
letter-spacing: 0.3px !important;
}
.o_btn_gold_gradient {
background: linear-gradient(135deg, #F59E0B 0%, #B45309 100%) !important;
border: none !important;
color: #000000 !important;
font-weight: 700 !important;
font-size: 12.5px !important;
padding: 8px 20px !important;
border-radius: 9999px !important;
box-shadow: 0 4px 14px rgba(245, 158, 11, 0.35) !important;
transition: all 0.2s ease !important;
&:hover {
transform: translateY(-1px) !important;
box-shadow: 0 6px 18px rgba(245, 158, 11, 0.5) !important;
}
}
.o_btn_dark_pill {
background: rgba(255, 255, 255, 0.05) !important;
border: 1px solid rgba(216, 156, 67, 0.38) !important;
color: #FFFFFF !important;
font-size: 12.5px !important;
font-weight: 500 !important;
padding: 7px 18px !important;
border-radius: 9999px !important;
transition: all 0.2s ease !important;
&:hover {
background: rgba(216, 156, 67, 0.12) !important;
border-color: #D89C43 !important;
}
}
.o_btn_circle_icon {
width: 36px !important;
height: 36px !important;
border-radius: 50% !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
background: rgba(255, 255, 255, 0.05) !important;
border: 1px solid rgba(216, 156, 67, 0.35) !important;
color: #D89C43 !important;
font-size: 13px !important;
transition: all 0.2s ease !important;
&:hover {
background: rgba(216, 156, 67, 0.15) !important;
transform: rotate(45deg) !important;
}
}
}
// Body Content
.o_dashboard_body {
padding: 24px 32px 32px 32px !important;
}
// ------------------------------------------------------------------
// ROW 1: 4 KPI CARDS
// ------------------------------------------------------------------
.o_kpi_card {
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.18) !important;
border-radius: 14px !important;
padding: 18px 20px !important;
position: relative !important;
overflow: hidden !important;
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35) !important;
cursor: pointer !important;
transition: all 0.22s ease !important;
&:hover {
transform: translateY(-3px) !important;
border-color: #D89C43 !important;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5), 0 0 15px rgba(216, 156, 67, 0.2) !important;
}
.o_kpi_watermark {
position: absolute !important;
right: 16px !important;
top: 14px !important;
font-size: 58px !important;
color: #FFFFFF !important;
opacity: 0.04 !important;
pointer-events: none !important;
}
.o_kpi_gold_badge {
width: 38px !important;
height: 38px !important;
border-radius: 10px !important;
background: linear-gradient(135deg, #F5A623 0%, #D48817 100%) !important;
color: #FFFFFF !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 16px !important;
box-shadow: 0 3px 10px rgba(245, 166, 35, 0.3) !important;
}
.o_kpi_title {
font-size: 10.5px !important;
font-weight: 700 !important;
letter-spacing: 0.6px !important;
color: #94A3B8 !important;
text-transform: uppercase !important;
}
.o_kpi_number {
font-size: 32px !important;
font-weight: 700 !important;
color: #FFFFFF !important;
line-height: 1.1 !important;
margin: 12px 0 10px 0 !important;
}
.o_pill_badge {
font-size: 11px !important;
font-weight: 600 !important;
padding: 2px 10px !important;
border-radius: 9999px !important;
&.badge_green {
background: rgba(16, 185, 129, 0.18) !important;
color: #34D399 !important;
border: 1px solid rgba(16, 185, 129, 0.35) !important;
}
&.badge_amber {
background: rgba(245, 158, 11, 0.18) !important;
color: #FBBF24 !important;
border: 1px solid rgba(245, 158, 11, 0.35) !important;
}
&.badge_purple {
background: rgba(168, 85, 247, 0.18) !important;
color: #C084FC !important;
border: 1px solid rgba(168, 85, 247, 0.35) !important;
}
&.badge_blue {
background: rgba(59, 130, 246, 0.18) !important;
color: #60A5FA !important;
border: 1px solid rgba(59, 130, 246, 0.35) !important;
}
}
.o_kpi_link {
font-size: 12px !important;
font-weight: 600 !important;
color: #94A3B8 !important;
transition: all 0.2s !important;
&:hover {
color: #D89C43 !important;
transform: translateX(2px) !important;
}
}
}
// ------------------------------------------------------------------
// ROW 2: LEFT IVORY CARD (UPCOMING CULTURAL PROGRAMS)
// ------------------------------------------------------------------
.o_ivory_card {
background: #FFFDF7 !important;
border: 1px solid #EBE4D6 !important;
border-radius: 18px !important;
padding: 22px 24px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35) !important;
.o_ivory_gold_icon {
width: 34px !important;
height: 34px !important;
border-radius: 8px !important;
background: #D89C43 !important;
color: #FFFFFF !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 15px !important;
}
.o_ivory_card_title {
font-family: 'Playfair Display', Georgia, serif !important;
font-size: 19px !important;
font-weight: 700 !important;
color: #181226 !important;
}
.o_ivory_card_subtitle {
font-size: 12px !important;
color: #71717A !important;
}
.o_btn_ivory_pill {
background: #F4EFE6 !important;
border: 1px solid #D4CEBF !important;
color: #27272A !important;
border-radius: 9999px !important;
font-size: 12px !important;
font-weight: 600 !important;
padding: 4px 14px !important;
transition: all 0.2s !important;
&:hover {
background: #ECE5D8 !important;
border-color: #C5B9A5 !important;
}
}
// Featured Pongal Banner
.o_featured_pongal_banner {
background: linear-gradient(90deg, rgba(20, 14, 8, 0.95) 0%, rgba(35, 22, 10, 0.88) 35%, rgba(216, 156, 67, 0.35) 65%, rgba(0, 0, 0, 0.3) 100%),
url('/tncsc_deployment/static/src/img/dashboard/pongal_featured_banner.jpg') center / cover no-repeat !important;
border: 1.5px solid rgba(216, 156, 67, 0.6) !important;
border-radius: 14px !important;
padding: 14px 18px !important;
margin-bottom: 14px !important;
display: flex !important;
align-items: center !important;
justify-content: space-between !important;
box-shadow: 0 4px 14px rgba(216, 156, 67, 0.25) !important;
cursor: pointer !important;
transition: all 0.2s ease !important;
&:hover {
transform: translateY(-2px) !important;
border-color: #D89C43 !important;
box-shadow: 0 6px 20px rgba(216, 156, 67, 0.4) !important;
}
.o_pongal_date_box {
background: rgba(16, 12, 8, 0.9) !important;
border: 1px solid #D89C43 !important;
border-radius: 10px !important;
width: 62px !important;
text-align: center !important;
padding: 6px 4px !important;
.day {
font-size: 22px !important;
font-weight: 700 !important;
color: #FFFFFF !important;
line-height: 1 !important;
}
.month {
font-size: 9px !important;
font-weight: 700 !important;
color: #D89C43 !important;
letter-spacing: 0.5px !important;
margin-top: 3px !important;
}
}
.o_featured_badge {
font-size: 9.5px !important;
font-weight: 700 !important;
letter-spacing: 1.5px !important;
color: #F59E0B !important;
text-transform: uppercase !important;
}
.o_featured_name {
font-family: 'Playfair Display', Georgia, serif !important;
font-size: 20px !important;
font-weight: 700 !important;
color: #FFFFFF !important;
margin: 2px 0 4px 0 !important;
}
.o_featured_meta {
font-size: 12px !important;
color: #F3E8D0 !important;
}
.o_btn_details_pill {
background: #181410 !important;
color: #FFFFFF !important;
border: 1px solid rgba(255, 255, 255, 0.25) !important;
border-radius: 9999px !important;
padding: 6px 16px !important;
font-size: 12px !important;
font-weight: 600 !important;
transition: all 0.2s !important;
&:hover {
background: #251F19 !important;
border-color: #D89C43 !important;
}
}
}
// Events List
.o_ivory_event_row {
background: #FFFDF7 !important;
border: 1px solid #EBE4D6 !important;
border-radius: 10px !important;
padding: 10px 14px !important;
margin-bottom: 8px !important;
display: flex !important;
align-items: center !important;
justify-content: space-between !important;
cursor: pointer !important;
transition: all 0.2s ease !important;
&:hover {
background: #FDF9F0 !important;
border-color: #D89C43 !important;
transform: translateX(2px) !important;
}
.o_event_date_pill {
background: #F4EFE6 !important;
border: 1px solid #D4CEBF !important;
border-radius: 8px !important;
padding: 3px 9px !important;
font-size: 11.5px !important;
font-weight: 700 !important;
color: #27272A !important;
min-width: 58px !important;
text-align: center !important;
}
.o_event_name_text {
font-size: 13.5px !important;
font-weight: 600 !important;
color: #181226 !important;
}
.o_status_pill {
font-size: 11px !important;
font-weight: 600 !important;
padding: 2px 10px !important;
border-radius: 9999px !important;
&.status_ended {
background: #F3E8FF !important;
color: #7E22CE !important;
}
&.status_new {
background: #FEF3C7 !important;
color: #D97706 !important;
}
&.status_booked {
background: #E0F2FE !important;
color: #0284C7 !important;
}
}
.o_chevron_icon {
font-size: 11px !important;
color: #A1A1AA !important;
}
}
}
// ------------------------------------------------------------------
// ROW 2: RIGHT DARK CARD (MEMBERSHIP STRUCTURE)
// ------------------------------------------------------------------
.o_dark_structure_card {
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.2) !important;
border-radius: 18px !important;
padding: 22px 24px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4) !important;
.o_structure_gold_icon {
width: 34px !important;
height: 34px !important;
border-radius: 8px !important;
background: #D89C43 !important;
color: #FFFFFF !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 15px !important;
}
.o_dark_card_title {
font-family: 'Playfair Display', Georgia, serif !important;
font-size: 19px !important;
font-weight: 700 !important;
color: #FFFFFF !important;
}
.o_dark_card_subtitle {
font-size: 12px !important;
color: #8E95A8 !important;
}
.o_btn_dark_pill_sm {
background: rgba(255, 255, 255, 0.05) !important;
border: 1px solid rgba(255, 255, 255, 0.18) !important;
color: #FFFFFF !important;
border-radius: 9999px !important;
font-size: 12px !important;
font-weight: 500 !important;
padding: 4px 14px !important;
transition: all 0.2s !important;
&:hover {
background: rgba(216, 156, 67, 0.15) !important;
border-color: #D89C43 !important;
}
}
.o_tier_table {
width: 100% !important;
border-collapse: separate !important;
border-spacing: 0 !important;
th {
font-size: 10.5px !important;
font-weight: 700 !important;
color: #71788E !important;
letter-spacing: 0.5px !important;
padding: 8px 10px !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important;
}
td {
padding: 10px 10px !important;
font-size: 13px !important;
color: #FFFFFF !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.04) !important;
}
tr:hover td {
background: rgba(255, 255, 255, 0.03) !important;
}
.o_tier_icon {
color: #D89C43 !important;
width: 16px !important;
font-size: 12px !important;
text-align: center !important;
}
.text-gold {
color: #D89C43 !important;
font-weight: 600 !important;
}
.text-muted-dim {
color: #8E95A8 !important;
font-size: 12px !important;
}
}
.o_membership_status_trio {
border-top: 1px solid rgba(255, 255, 255, 0.08) !important;
.o_status_divider {
width: 1px !important;
height: 32px !important;
background: rgba(255, 255, 255, 0.1) !important;
}
.o_status_label {
font-size: 10px !important;
font-weight: 700 !important;
color: #8E95A8 !important;
letter-spacing: 0.5px !important;
margin-top: 3px !important;
}
}
}
// ------------------------------------------------------------------
// ROW 3: COMMUNITY OPERATIONS HUB
// ------------------------------------------------------------------
.o_operations_hub_section {
.o_hub_section_title {
font-family: 'Playfair Display', Georgia, serif !important;
font-size: 20px !important;
font-weight: 700 !important;
color: #E0A948 !important;
}
.o_hub_section_subtitle {
font-size: 12px !important;
color: #8E95A8 !important;
}
.o_hub_pill_card {
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.2) !important;
border-radius: 12px !important;
padding: 14px 20px !important;
display: flex !important;
align-items: center !important;
justify-content: space-between !important;
cursor: pointer !important;
transition: all 0.22s ease !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3) !important;
&:hover {
transform: translateY(-2px) !important;
border-color: #D89C43 !important;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5), 0 0 12px rgba(216, 156, 67, 0.18) !important;
.o_hub_pill_arrow {
transform: translateX(3px) !important;
}
}
.o_hub_pill_icon {
width: 36px !important;
height: 36px !important;
border-radius: 10px !important;
background: linear-gradient(135deg, #F5A623 0%, #D48817 100%) !important;
color: #FFFFFF !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 15px !important;
}
.o_hub_pill_title {
font-size: 14px !important;
font-weight: 600 !important;
color: #FFFFFF !important;
}
.o_hub_pill_arrow {
color: #D89C43 !important;
font-size: 13px !important;
transition: transform 0.2s !important;
}
}
}
}
}

View File

@ -1,28 +1,27 @@
// ============================================================================ // ============================================================================
// TNCSC Tamil Luxury Brand Palette & Dark Theme Tokens // TNCSC Tamil Luxury Brand Palette & Theme Tokens (Royal Obsidian Dark Mode)
// ============================================================================ // ============================================================================
$tncsc-bg-midnight: #0A051B; $tncsc-bg-page: #090B12; // Royal obsidian canvas background
$tncsc-bg-header: #0D0722; $tncsc-card-bg: #111420; // Dark luxury card background
$tncsc-bg-card-top: #170C3D; $tncsc-navy-dark: #080A10; // Deepest obsidian
$tncsc-bg-card-bot: #0A041B; $tncsc-gold: #D89C43; // Signature TNCSC Gold
$tncsc-gold: #D4A359; $tncsc-gold-bright: #F59E0B; // Bright amber
$tncsc-gold-bright: #E5A93C; $tncsc-gold-hover: #FBBF24;
$tncsc-gold-border: rgba(200, 147, 58, 0.38); $tncsc-gold-border: rgba(216, 156, 67, 0.25);
$tncsc-text-white: #FFFFFF; $tncsc-text-white: #FFFFFF;
$tncsc-text-muted: #9CA3AF; $tncsc-text-muted: #94A3B8;
$tncsc-text-lavender: #C4BEEA;
$tncsc-font-serif: 'Playfair Display', Georgia, 'Times New Roman', serif; $tncsc-font-serif: 'Playfair Display', Georgia, 'Times New Roman', serif;
// ============================================================================ // ============================================================================
// 1. Overall Dark Background & Hide Unwanted Panels // 1. Overall Dark Mode Page Background & Layout
// ============================================================================ // ============================================================================
body:has(.o_event_kanban_view), body:has(.o_event_kanban_view),
.o_action_manager:has(.o_event_kanban_view), .o_action_manager:has(.o_event_kanban_view),
.o_content:has(.o_event_kanban_view) { .o_content:has(.o_event_kanban_view) {
background-color: $tncsc-bg-midnight !important; background-color: $tncsc-bg-page !important;
} }
// Sleek dark scrollbar // Sleek light scrollbar
body:has(.o_event_kanban_view) { body:has(.o_event_kanban_view) {
&::-webkit-scrollbar, &::-webkit-scrollbar,
*::-webkit-scrollbar { *::-webkit-scrollbar {
@ -31,16 +30,16 @@ body:has(.o_event_kanban_view) {
} }
&::-webkit-scrollbar-track, &::-webkit-scrollbar-track,
*::-webkit-scrollbar-track { *::-webkit-scrollbar-track {
background: #0A051B !important; background: #F1F5F9 !important;
} }
&::-webkit-scrollbar-thumb, &::-webkit-scrollbar-thumb,
*::-webkit-scrollbar-thumb { *::-webkit-scrollbar-thumb {
background: rgba(200, 147, 58, 0.35) !important; background: rgba(216, 156, 67, 0.35) !important;
border-radius: 4px !important; border-radius: 4px !important;
} }
&::-webkit-scrollbar-thumb:hover, &::-webkit-scrollbar-thumb:hover,
*::-webkit-scrollbar-thumb:hover { *::-webkit-scrollbar-thumb:hover {
background: rgba(200, 147, 58, 0.65) !important; background: rgba(216, 156, 67, 0.65) !important;
} }
} }
@ -67,11 +66,11 @@ body:has(.o_event_kanban_view) {
} }
// ============================================================================ // ============================================================================
// 2. Top Main Navbar (Deep Dark Midnight with Gold Accents) // 2. Top Main Navbar (Deep Navy with Gold Accents matching Website Header)
// ============================================================================ // ============================================================================
.o_main_navbar { .o_main_navbar {
background-color: #070314 !important; background-color: #080A10 !important;
border-bottom: 1px solid rgba(200, 147, 58, 0.2) !important; border-bottom: 1px solid rgba(216, 156, 67, 0.25) !important;
color: #FFFFFF !important; color: #FFFFFF !important;
.o_menu_brand { .o_menu_brand {
@ -83,7 +82,7 @@ body:has(.o_event_kanban_view) {
.o_nav_entry, .o_nav_entry,
.o_menu_sections > a, .o_menu_sections > a,
.o_menu_sections .dropdown-toggle { .o_menu_sections .dropdown-toggle {
color: $tncsc-text-lavender !important; color: #B8B2E6 !important;
font-weight: 500 !important; font-weight: 500 !important;
padding-top: 10px !important; padding-top: 10px !important;
padding-bottom: 10px !important; padding-bottom: 10px !important;
@ -104,7 +103,7 @@ body:has(.o_event_kanban_view) {
} }
.o_navbar_apps_menu .dropdown-toggle { .o_navbar_apps_menu .dropdown-toggle {
color: $tncsc-text-lavender !important; color: #B8B2E6 !important;
&:hover { color: #FFFFFF !important; } &:hover { color: #FFFFFF !important; }
} }
@ -114,20 +113,20 @@ body:has(.o_event_kanban_view) {
} }
.o_notification_counter { .o_notification_counter {
background-color: $tncsc-gold-bright !important; background-color: $tncsc-gold !important;
color: #0A051B !important; color: #120735 !important;
font-weight: 800 !important; font-weight: 800 !important;
} }
} }
// ============================================================================ // ============================================================================
// 3. Control Panel Header (Golden Lotus + Tamil Overline + Centered Pill Search) // 3. Control Panel Header (Royal Obsidian Dark & Gold)
// ============================================================================ // ============================================================================
.o_view_controller:has(.o_event_kanban_view), .o_view_controller:has(.o_event_kanban_view),
body:has(.o_event_kanban_view) { body:has(.o_event_kanban_view) {
.o_control_panel { .o_control_panel {
background-color: $tncsc-bg-header !important; background-color: #0B0E17 !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.06) !important; border-bottom: 1px solid rgba(216, 156, 67, 0.22) !important;
padding: 16px 36px 14px 36px !important; padding: 16px 36px 14px 36px !important;
display: flex !important; display: flex !important;
flex-direction: row !important; flex-direction: row !important;
@ -136,6 +135,7 @@ body:has(.o_event_kanban_view) {
flex-wrap: nowrap !important; flex-wrap: nowrap !important;
width: 100% !important; width: 100% !important;
gap: 20px !important; gap: 20px !important;
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.4) !important;
.o_control_panel_main { .o_control_panel_main {
display: flex !important; display: flex !important;
@ -221,7 +221,7 @@ body:has(.o_event_kanban_view) {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
font-size: 12.5px !important; font-size: 12.5px !important;
font-weight: 400 !important; font-weight: 400 !important;
color: $tncsc-text-muted !important; color: #94A3B8 !important;
margin-top: 4px !important; margin-top: 4px !important;
letter-spacing: 0 !important; letter-spacing: 0 !important;
white-space: nowrap !important; white-space: nowrap !important;
@ -233,7 +233,7 @@ body:has(.o_event_kanban_view) {
display: none !important; display: none !important;
} }
// 2. Centered Unified Dark Pill Search Bar // 2. Centered Unified Light Pill Search Bar
.o_control_panel_actions, .o_control_panel_actions,
.o_cp_searchview { .o_cp_searchview {
order: 2 !important; order: 2 !important;
@ -244,9 +244,9 @@ body:has(.o_event_kanban_view) {
.o_searchview { .o_searchview {
border-top-left-radius: 9999px !important; border-top-left-radius: 9999px !important;
border-bottom-left-radius: 9999px !important; border-bottom-left-radius: 9999px !important;
border: 1px solid rgba(255, 255, 255, 0.15) !important; border: 1px solid rgba(216, 156, 67, 0.35) !important;
border-right: none !important; border-right: none !important;
background: rgba(255, 255, 255, 0.05) !important; background: #111420 !important;
padding: 6px 18px !important; padding: 6px 18px !important;
box-shadow: none !important; box-shadow: none !important;
display: flex !important; display: flex !important;
@ -261,7 +261,7 @@ body:has(.o_event_kanban_view) {
height: 15px !important; height: 15px !important;
min-width: 15px !important; min-width: 15px !important;
margin-right: 10px !important; margin-right: 10px !important;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23D4A359' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E") no-repeat center / contain !important; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23D89C43' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E") no-repeat center / contain !important;
} }
// Custom placeholder: "Search events..." // Custom placeholder: "Search events..."
@ -269,7 +269,7 @@ body:has(.o_event_kanban_view) {
content: 'Search events...'; content: 'Search events...';
position: absolute; position: absolute;
left: 44px; left: 44px;
color: rgba(255, 255, 255, 0.45); color: #94A3B8;
font-size: 13.5px; font-size: 13.5px;
pointer-events: none; pointer-events: none;
} }
@ -294,27 +294,42 @@ body:has(.o_event_kanban_view) {
.o_searchview_icon { .o_searchview_icon {
display: none !important; display: none !important;
} }
.o_searchview_facet {
background: #1E2333 !important;
border: 1px solid rgba(216, 156, 67, 0.5) !important;
border-radius: 9999px !important;
color: #F8FAFC !important;
.o_searchview_facet_label {
background: rgba(216, 156, 67, 0.25) !important;
color: $tncsc-gold !important;
border-top-left-radius: 9999px !important;
border-bottom-left-radius: 9999px !important;
}
}
} }
.o_searchview_dropdown_toggler { .o_searchview_dropdown_toggler {
border-top-right-radius: 9999px !important; border-top-right-radius: 9999px !important;
border-bottom-right-radius: 9999px !important; border-bottom-right-radius: 9999px !important;
border: 1px solid rgba(255, 255, 255, 0.15) !important; border: 1px solid rgba(216, 156, 67, 0.35) !important;
border-left: none !important; border-left: none !important;
background: rgba(255, 255, 255, 0.05) !important; background: #111420 !important;
color: $tncsc-text-muted !important; color: $tncsc-gold !important;
padding-right: 16px !important; padding-right: 16px !important;
} }
&:focus-within { &:focus-within {
.o_searchview, .o_searchview,
.o_searchview_dropdown_toggler { .o_searchview_dropdown_toggler {
border-color: $tncsc-gold !important; border-color: #D89C43 !important;
background: #161926 !important;
} }
} }
} }
// 3. Right: + New Pill Button (Warm Gold / Amber) // 3. Right: + New Pill Button (Website Gold)
.o_control_panel_main_buttons, .o_control_panel_main_buttons,
.o_cp_buttons { .o_cp_buttons {
order: 3 !important; order: 3 !important;
@ -323,14 +338,14 @@ body:has(.o_event_kanban_view) {
button, button,
button.o-kanban-button-new, button.o-kanban-button-new,
button.btn-primary { button.btn-primary {
background: $tncsc-gold-bright !important; background: $tncsc-gold !important;
color: #0A051B !important; color: #FFFFFF !important;
border-radius: 9999px !important; border-radius: 9999px !important;
border: none !important; border: none !important;
padding: 8px 24px !important; padding: 8px 24px !important;
font-weight: 700 !important; font-weight: 700 !important;
font-size: 14px !important; font-size: 14px !important;
box-shadow: 0 4px 14px rgba(229, 169, 60, 0.35) !important; box-shadow: 0 4px 14px rgba(216, 156, 67, 0.3) !important;
display: inline-flex !important; display: inline-flex !important;
align-items: center !important; align-items: center !important;
gap: 6px !important; gap: 6px !important;
@ -339,16 +354,16 @@ body:has(.o_event_kanban_view) {
&::before { &::before {
content: '+'; content: '+';
color: #0A051B; color: #FFFFFF;
font-weight: 800; font-weight: 800;
font-size: 18px; font-size: 18px;
line-height: 1; line-height: 1;
} }
&:hover { &:hover {
background: lighten($tncsc-gold-bright, 5%) !important; background: $tncsc-gold-hover !important;
transform: translateY(-1px); transform: translateY(-1px);
box-shadow: 0 6px 18px rgba(229, 169, 60, 0.5) !important; box-shadow: 0 6px 18px rgba(216, 156, 67, 0.45) !important;
} }
} }
} }
@ -369,28 +384,28 @@ body:has(.o_event_kanban_view) {
.o_cp_switch_buttons { .o_cp_switch_buttons {
border-radius: 8px !important; border-radius: 8px !important;
border: 1px solid rgba(255, 255, 255, 0.12) !important; border: 1px solid rgba(216, 156, 67, 0.25) !important;
padding: 3px !important; padding: 3px !important;
background: rgba(255, 255, 255, 0.06) !important; background: #111420 !important;
display: inline-flex !important; display: inline-flex !important;
gap: 3px !important; gap: 3px !important;
button { button {
border-radius: 6px !important; border-radius: 6px !important;
border: none !important; border: none !important;
color: $tncsc-text-muted !important; color: #94A3B8 !important;
padding: 6px 10px !important; padding: 6px 10px !important;
background: transparent !important; background: transparent !important;
transition: all 0.15s ease !important; transition: all 0.15s ease !important;
&.active, &.active,
&.o_kanban.active { &.o_kanban.active {
background-color: $tncsc-gold-bright !important; background: linear-gradient(135deg, #F59E0B, #B45309) !important;
color: #0A051B !important; color: #000000 !important;
} }
&:hover:not(.active) { &:hover:not(.active) {
background-color: rgba(255, 255, 255, 0.1) !important; background-color: rgba(216, 156, 67, 0.12) !important;
color: #FFFFFF !important; color: #FFFFFF !important;
} }
} }
@ -400,16 +415,13 @@ body:has(.o_event_kanban_view) {
} }
// ============================================================================ // ============================================================================
// 4. Kanban View Canvas & Top-Right Mandala Watermark // 4. Kanban View Canvas (Royal Obsidian Dark Mode)
// ============================================================================ // ============================================================================
.o_kanban_view.o_event_kanban_view, .o_kanban_view.o_event_kanban_view,
.o_event_kanban_view .o_kanban_renderer { .o_event_kanban_view .o_kanban_renderer {
background-color: $tncsc-bg-midnight !important; background-color: #090B12 !important;
background-image: url('/tncsc_deployment/static/src/img/gold_mandala_top.png') !important; background-image: none !important;
background-repeat: no-repeat !important; padding: 24px 36px 40px 36px !important;
background-position: top 0 right 0 !important;
background-size: 190px auto !important;
padding: 20px 36px 40px 36px !important;
width: 100% !important; width: 100% !important;
display: flex !important; display: flex !important;
flex-direction: row !important; flex-direction: row !important;
@ -436,7 +448,7 @@ body:has(.o_event_kanban_view) {
display: none !important; display: none !important;
} }
// Transparent 4 Stage Columns side-by-side // Side-by-side 4 Stage Columns
.o_kanban_group { .o_kanban_group {
background: transparent !important; background: transparent !important;
border: none !important; border: none !important;
@ -447,6 +459,64 @@ body:has(.o_event_kanban_view) {
flex: 1 1 calc(25% - 20px) !important; flex: 1 1 calc(25% - 20px) !important;
min-width: 270px !important; min-width: 270px !important;
max-width: calc(25% - 15px) !important; max-width: calc(25% - 15px) !important;
// When a single stage tab is active, expand group to 100% width and display cards in flex row
&.o_tncsc_single_stage_group {
flex: 1 1 100% !important;
max-width: 100% !important;
width: 100% !important;
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
gap: 20px !important;
align-items: stretch !important;
.o_kanban_record {
flex: 1 1 calc(25% - 20px) !important;
min-width: 270px !important;
max-width: calc(25% - 15px) !important;
margin: 0 !important;
}
.o_kanban_load_more {
flex-basis: 100% !important;
}
}
}
// Empty Stage Box
.o_tncsc_empty_stage_box {
flex: 1 1 100% !important;
width: 100% !important;
background: #111420 !important;
border: 1.5px dashed rgba(216, 156, 67, 0.3) !important;
border-radius: 16px !important;
padding: 48px 24px !important;
text-align: center !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3) !important;
.o_tncsc_empty_icon {
opacity: 0.9;
}
.o_tncsc_empty_title {
font-family: $tncsc-font-serif !important;
letter-spacing: 0.5px;
color: #FFFFFF !important;
}
.o_tncsc_empty_sub {
color: #94A3B8 !important;
}
}
.o_tncsc_empty_column_placeholder {
background: #111420 !important;
border: 1.5px dashed rgba(216, 156, 67, 0.25) !important;
border-radius: 12px !important;
margin-top: 10px !important;
padding: 24px 16px !important;
color: #94A3B8 !important;
} }
} }
@ -461,7 +531,7 @@ body:has(.o_event_kanban_view) {
} }
// ============================================================================ // ============================================================================
// 5. Filter Pills Bar (All, New, Booked, Announced, Ended) // 5. Filter Pills Bar (White Mode: All, New, Booked, Announced, Ended)
// ============================================================================ // ============================================================================
.o_tncsc_filter_pills_bar { .o_tncsc_filter_pills_bar {
width: 100% !important; width: 100% !important;
@ -477,51 +547,56 @@ body:has(.o_event_kanban_view) {
font-weight: 500 !important; font-weight: 500 !important;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
background: rgba(255, 255, 255, 0.05); background: #111420;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(216, 156, 67, 0.25);
color: #FFFFFF; color: #CBD5E1;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
.o_dot { .o_dot {
font-size: 11px; font-size: 11px;
margin-right: 2px; margin-right: 2px;
color: #94A3B8;
} }
.o_count { .o_count {
color: $tncsc-text-muted; color: #94A3B8;
font-size: 12.5px; font-size: 12.5px;
margin-left: 14px; margin-left: 14px;
font-weight: 600;
} }
&.active { &.active {
background: $tncsc-gold !important; background: linear-gradient(135deg, #F59E0B, #B45309) !important;
color: #0A051B !important; color: #000000 !important;
border-color: $tncsc-gold !important; border-color: transparent !important;
font-weight: 700 !important; font-weight: 700 !important;
box-shadow: 0 4px 14px rgba(245, 158, 11, 0.4) !important;
.o_dot { color: #0A051B !important; } .o_dot { color: #000000 !important; }
.o_count { color: #0A051B !important; font-weight: 700; } .o_count { color: #000000 !important; font-weight: 700; }
} }
&.pill-new .dot-gold { color: $tncsc-gold-bright; } &.pill-new .dot-gold { color: $tncsc-gold; }
&.pill-booked .dot-cyan { color: #38BDF8; } &.pill-booked .dot-cyan { color: #0284C7; }
&.pill-announced .dot-green { color: #4ADE80; } &.pill-announced .dot-green { color: #16A34A; }
&.pill-ended .dot-purple { color: #C084FC; } &.pill-ended .dot-purple { color: #9333EA; }
&:hover:not(.active) { &:hover:not(.active) {
background: rgba(255, 255, 255, 0.1) !important; background: rgba(216, 156, 67, 0.12) !important;
border-color: rgba(255, 255, 255, 0.22) !important; border-color: $tncsc-gold !important;
color: #FFFFFF !important;
} }
} }
} }
// ============================================================================ // ============================================================================
// 6. Tamil Luxury Dark Event Card // 6. Tamil Cultural Royal Obsidian Event Card
// ============================================================================ // ============================================================================
.o_event_kanban_view .o_kanban_record { .o_event_kanban_view .o_kanban_record {
background: radial-gradient(circle at 50% 0%, #170C3D 0%, #0A041B 100%) !important; background: #111420 !important;
border: 1px solid $tncsc-gold-border !important; border: 1px solid rgba(216, 156, 67, 0.2) !important;
border-radius: 16px !important; border-radius: 16px !important;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5) !important; box-shadow: 0 4px 18px rgba(0, 0, 0, 0.4) !important;
overflow: hidden !important; overflow: hidden !important;
padding: 18px 20px 22px 20px !important; padding: 18px 20px 22px 20px !important;
display: flex !important; display: flex !important;
@ -529,25 +604,18 @@ body:has(.o_event_kanban_view) {
min-height: 520px !important; min-height: 520px !important;
width: 100% !important; width: 100% !important;
position: relative !important; position: relative !important;
color: #FFFFFF !important;
transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease !important; transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease !important;
&:hover { &:hover {
transform: translateY(-4px) !important; transform: translateY(-4px) !important;
border-color: $tncsc-gold !important; border-color: $tncsc-gold !important;
box-shadow: 0 14px 38px rgba(0, 0, 0, 0.65), 0 0 20px rgba(212, 163, 89, 0.25) !important; box-shadow: 0 12px 28px rgba(0, 0, 0, 0.6), 0 0 16px rgba(216, 156, 67, 0.2) !important;
} }
// Bottom-Right Golden Mandala Corner Artwork // Bottom-Right Corner Artwork (Hidden in White Mode to avoid dark image box)
.o_tncsc_mandala_corner { .o_tncsc_mandala_corner {
position: absolute !important; display: none !important;
bottom: 0 !important;
right: 0 !important;
width: 85px !important;
height: 85px !important;
background: url('/tncsc_deployment/static/src/img/gold_mandala_corner.png') no-repeat bottom right / contain !important;
pointer-events: none !important;
opacity: 0.8 !important;
z-index: 1 !important;
} }
// Top Header: Stage Pill Badge + Three Dots Button // Top Header: Stage Pill Badge + Three Dots Button
@ -571,59 +639,65 @@ body:has(.o_event_kanban_view) {
} }
&.pill-new { &.pill-new {
background: $tncsc-gold-bright !important; background: #FEF3C7 !important;
color: #0A051B !important; border: 1px solid #FDE68A !important;
color: #92400E !important;
font-weight: 700 !important; font-weight: 700 !important;
.o_dot { display: none !important; } .o_dot { color: $tncsc-gold !important; }
} }
&.pill-booked { &.pill-booked {
background: rgba(56, 189, 248, 0.15) !important; background: #E0F2FE !important;
border: 1px solid rgba(56, 189, 248, 0.35) !important; border: 1px solid #BAE6FD !important;
color: #FFFFFF !important; color: #0369A1 !important;
.o_dot { color: #38BDF8; } .o_dot { color: #0284C7; }
} }
&.pill-announced { &.pill-announced {
background: rgba(74, 222, 128, 0.15) !important; background: #DCFCE7 !important;
border: 1px solid rgba(74, 222, 128, 0.35) !important; border: 1px solid #BBF7D0 !important;
color: #FFFFFF !important; color: #15803D !important;
.o_dot { color: #4ADE80; } .o_dot { color: #16A34A; }
} }
&.pill-ended { &.pill-ended {
background: rgba(192, 132, 252, 0.15) !important; background: #F3E8FF !important;
border: 1px solid rgba(192, 132, 252, 0.35) !important; border: 1px solid #E9D5FF !important;
color: #FFFFFF !important; color: #7E22CE !important;
.o_dot { color: #C084FC; } .o_dot { color: #9333EA; }
} }
} }
.o_tncsc_card_dots { .o_tncsc_card_dots {
background: rgba(255, 255, 255, 0.05) !important; background: #F8FAFC !important;
border: 1px solid rgba(255, 255, 255, 0.15) !important; border: 1px solid #E2E8F0 !important;
border-radius: 9999px !important; border-radius: 9999px !important;
padding: 2px 10px !important; padding: 2px 10px !important;
color: $tncsc-text-muted !important; color: #64748B !important;
font-size: 13px !important; font-size: 13px !important;
letter-spacing: 1.5px !important; letter-spacing: 1.5px !important;
cursor: pointer !important; cursor: pointer !important;
line-height: 1 !important; line-height: 1 !important;
&:hover {
background: #EDF2F7 !important;
color: #120735 !important;
}
} }
} }
// Date Box Row (Card 1 / New stage) // Date Box Row (for New stage)
.o_tncsc_card_date_box_row { .o_tncsc_card_date_box_row {
margin-bottom: 12px !important; margin-bottom: 12px !important;
position: relative !important; position: relative !important;
z-index: 2 !important; z-index: 2 !important;
.o_tncsc_card_date_box { .o_tncsc_card_date_box {
border: 1px solid rgba(200, 147, 58, 0.45) !important; border: 1px solid #D89C43 !important;
border-radius: 8px !important; border-radius: 8px !important;
padding: 6px 14px !important; padding: 6px 14px !important;
text-align: center !important; text-align: center !important;
background: rgba(255, 255, 255, 0.02) !important; background: rgba(16, 12, 8, 0.9) !important;
min-width: 68px !important; min-width: 68px !important;
.o_day { .o_day {
@ -645,7 +719,7 @@ body:has(.o_event_kanban_view) {
} }
.o_tncsc_card_time_col { .o_tncsc_card_time_col {
color: $tncsc-text-lavender !important; color: #CBD5E1 !important;
font-size: 12px !important; font-size: 12px !important;
font-weight: 500 !important; font-weight: 500 !important;
line-height: 1.4 !important; line-height: 1.4 !important;
@ -663,7 +737,8 @@ body:has(.o_event_kanban_view) {
align-items: center !important; align-items: center !important;
justify-content: center !important; justify-content: center !important;
margin: 16px auto 16px auto !important; margin: 16px auto 16px auto !important;
background: rgba(212, 163, 89, 0.05) !important; background: #1C1814 !important;
color: $tncsc-gold !important;
position: relative !important; position: relative !important;
z-index: 2 !important; z-index: 2 !important;
} }
@ -683,7 +758,7 @@ body:has(.o_event_kanban_view) {
// Subtitle / Tagline // Subtitle / Tagline
.o_tncsc_card_subtitle { .o_tncsc_card_subtitle {
font-size: 12.5px !important; font-size: 12.5px !important;
color: $tncsc-text-muted !important; color: #94A3B8 !important;
margin-bottom: 12px !important; margin-bottom: 12px !important;
line-height: 1.4 !important; line-height: 1.4 !important;
position: relative !important; position: relative !important;
@ -693,7 +768,7 @@ body:has(.o_event_kanban_view) {
// Location // Location
.o_tncsc_card_location { .o_tncsc_card_location {
font-size: 12.5px !important; font-size: 12.5px !important;
color: $tncsc-text-lavender !important; color: #475569 !important;
font-weight: 500 !important; font-weight: 500 !important;
margin-bottom: 8px !important; margin-bottom: 8px !important;
position: relative !important; position: relative !important;
@ -703,7 +778,7 @@ body:has(.o_event_kanban_view) {
// Date & Time (for Cards 2, 3, 4) // Date & Time (for Cards 2, 3, 4)
.o_tncsc_card_datetime { .o_tncsc_card_datetime {
font-size: 12.5px !important; font-size: 12.5px !important;
color: $tncsc-text-lavender !important; color: #475569 !important;
font-weight: 500 !important; font-weight: 500 !important;
margin-bottom: 16px !important; margin-bottom: 16px !important;
position: relative !important; position: relative !important;
@ -728,29 +803,28 @@ body:has(.o_event_kanban_view) {
transition: all 0.2s ease !important; transition: all 0.2s ease !important;
&.btn-primary-gold { &.btn-primary-gold {
background: $tncsc-gold-bright !important; background: linear-gradient(135deg, #F59E0B, #B45309) !important;
color: #0A051B !important; color: #000000 !important;
font-weight: 700 !important; font-weight: 700 !important;
border: none !important; border: none !important;
box-shadow: 0 4px 14px rgba(229, 169, 60, 0.3) !important; box-shadow: 0 4px 14px rgba(245, 158, 11, 0.35) !important;
&:hover { &:hover {
background: lighten($tncsc-gold-bright, 5%) !important;
transform: translateY(-1px); transform: translateY(-1px);
box-shadow: 0 6px 18px rgba(229, 169, 60, 0.45) !important; box-shadow: 0 6px 18px rgba(245, 158, 11, 0.5) !important;
} }
} }
&.btn-outline-gold { &.btn-outline-gold {
background: rgba(255, 255, 255, 0.02) !important; background: rgba(255, 255, 255, 0.05) !important;
border: 1.5px solid $tncsc-gold !important; border: 1.5px solid $tncsc-gold !important;
color: $tncsc-gold !important; color: #FFFFFF !important;
font-weight: 600 !important; font-weight: 600 !important;
&:hover { &:hover {
background: rgba(212, 163, 89, 0.12) !important; background: rgba(216, 156, 67, 0.15) !important;
border-color: $tncsc-gold-bright !important; border-color: $tncsc-gold-hover !important;
color: $tncsc-gold-bright !important; color: $tncsc-gold-hover !important;
transform: translateY(-1px); transform: translateY(-1px);
} }
} }

View File

@ -0,0 +1,393 @@
// ============================================================================
// TNCSC Community OS Suite - Executive Login Page Theme
// Matching the Community Dashboard Royal Obsidian & Gold Aesthetic
// ============================================================================
$tncsc-obsidian-dark: #090B12;
$tncsc-obsidian-subtle: #080A10;
$tncsc-card-bg: #111420;
$tncsc-gold: #D89C43;
$tncsc-gold-bright: #F59E0B;
$tncsc-gold-hover: #FBBF24;
$tncsc-gold-gradient: linear-gradient(135deg, #F59E0B 0%, #B45309 100%);
$tncsc-font-serif: 'Playfair Display', Georgia, 'Times New Roman', serif;
// ----------------------------------------------------------------------------
// 1. Hide Header & Footer on Login Page
// ----------------------------------------------------------------------------
body:has(.oe_login_form),
body:has(.oe_website_login_container),
body:has(.o_database_list),
body:has(.o_login_auth) {
header,
#top,
.o_header_standard,
.o_main_header,
nav.navbar,
#oe_main_menu_navbar,
footer,
#bottom,
#footer,
.o_footer,
.s_social_media,
div.border-top:has(a[href*="odoo.com"]) {
display: none !important;
visibility: hidden !important;
height: 0 !important;
min-height: 0 !important;
max-height: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
opacity: 0 !important;
pointer-events: none !important;
}
}
// ----------------------------------------------------------------------------
// 2. Full-Screen Royal Obsidian Canvas with Gopuram Aura
// ----------------------------------------------------------------------------
body:has(.oe_login_form),
body:has(.oe_website_login_container),
body:has(.o_database_list) {
min-height: 100vh !important;
width: 100vw !important;
margin: 0 !important;
padding: 0 !important;
background-color: #090B12 !important;
background-image:
radial-gradient(ellipse at 50% 15%, rgba(216, 156, 67, 0.18) 0%, transparent 65%),
radial-gradient(ellipse at 50% 85%, rgba(180, 83, 9, 0.12) 0%, transparent 65%),
url('/tncsc_deployment/static/src/img/dashboard/gopuram_header_bg.jpg') !important;
background-size: cover, cover, cover !important;
background-position: center, center, center 20% !important;
background-repeat: no-repeat !important;
background-blend-mode: screen, normal, luminosity !important;
color: #F8FAFC !important;
display: flex !important;
flex-direction: column !important;
justify-content: center !important;
align-items: center !important;
position: relative !important;
box-sizing: border-box !important;
&::before {
content: '';
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(9, 11, 18, 0.84);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
z-index: 0;
pointer-events: none;
}
#wrapwrap {
background: transparent !important;
display: flex !important;
flex-direction: column !important;
justify-content: center !important;
align-items: center !important;
min-height: 100vh !important;
width: 100% !important;
position: relative !important;
z-index: 1 !important;
padding: 40px 16px !important;
box-sizing: border-box !important;
}
main {
width: 100% !important;
display: flex !important;
flex-direction: column !important;
justify-content: center !important;
align-items: center !important;
padding: 0 !important;
margin: 0 !important;
}
}
// ----------------------------------------------------------------------------
// 3. Login Executive Card (Luxury Community Dashboard Style)
// ----------------------------------------------------------------------------
.oe_website_login_container,
.card.o_database_list,
body:has(.oe_login_form) .card {
width: 100% !important;
max-width: 440px !important;
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.32) !important;
border-top: 3.5px solid #D89C43 !important;
border-radius: 24px !important;
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.85), 0 0 35px rgba(216, 156, 67, 0.15) !important;
padding: 36px 36px 30px 36px !important;
margin: 30px auto !important;
backdrop-filter: blur(16px) !important;
-webkit-backdrop-filter: blur(16px) !important;
color: #F8FAFC !important;
box-sizing: border-box !important;
position: relative !important;
z-index: 2 !important;
.card-body {
padding: 0 !important;
background: transparent !important;
}
// Brand Header
.o_tncsc_login_brand_header,
.text-center.pb-3.border-bottom {
border-bottom: 1px solid rgba(216, 156, 67, 0.22) !important;
margin-bottom: 24px !important;
padding-bottom: 20px !important;
text-align: center !important;
.o_tncsc_login_logo,
img {
max-height: 56px !important;
width: auto !important;
filter: drop-shadow(0 4px 14px rgba(216, 156, 67, 0.55)) !important;
margin-bottom: 12px !important;
}
.o_tncsc_login_brand_title {
font-family: $tncsc-font-serif !important;
font-size: 13.5px !important;
font-weight: 700 !important;
letter-spacing: 1.5px !important;
color: #D89C43 !important;
text-transform: uppercase !important;
line-height: 1.3 !important;
}
.o_tncsc_login_brand_country {
font-family: $tncsc-font-serif !important;
font-size: 12px !important;
font-weight: 700 !important;
letter-spacing: 2px !important;
color: #D89C43 !important;
text-transform: uppercase !important;
margin-top: 2px !important;
}
.o_tncsc_login_tagline {
font-size: 11px !important;
color: #94A3B8 !important;
letter-spacing: 0.3px !important;
margin-top: 6px !important;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
}
}
// Form Labels
.form-label,
.col-form-label,
label {
font-size: 11px !important;
font-weight: 700 !important;
letter-spacing: 1px !important;
text-transform: uppercase !important;
color: #D89C43 !important;
margin-bottom: 6px !important;
display: flex !important;
justify-content: space-between !important;
align-items: center !important;
}
// Helper Links in Labels ("Choose a user", "Reset Password")
.o_user_switch_btn,
a.btn-link,
a.btn-sm.btn-link,
.form-label a,
.form-label button {
background: transparent !important;
border: none !important;
color: #D89C43 !important;
font-size: 11.5px !important;
font-weight: 500 !important;
letter-spacing: 0 !important;
text-transform: none !important;
text-decoration: none !important;
padding: 0 !important;
box-shadow: none !important;
cursor: pointer !important;
&:hover {
color: #FBBF24 !important;
text-decoration: underline !important;
background: transparent !important;
}
}
// Input Fields
.form-control,
input[type="text"],
input[type="password"],
input[type="email"] {
background-color: #0A0C14 !important;
border: 1px solid rgba(216, 156, 67, 0.3) !important;
border-radius: 12px !important;
color: #FFFFFF !important;
padding: 11px 16px !important;
font-size: 14px !important;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.5) !important;
transition: all 0.2s ease !important;
&::placeholder {
color: #64748B !important;
}
&:focus {
background-color: #0E111C !important;
border-color: #D89C43 !important;
box-shadow: 0 0 0 3px rgba(216, 156, 67, 0.3), inset 0 2px 4px rgba(0, 0, 0, 0.5) !important;
color: #FFFFFF !important;
}
// WebKit Autocomplete Dark Override
&:-webkit-autofill,
&:-webkit-autofill:hover,
&:-webkit-autofill:focus,
&:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 1000px #0A0C14 inset !important;
-webkit-text-fill-color: #FFFFFF !important;
caret-color: #FFFFFF !important;
transition: background-color 5000s ease-in-out 0s !important;
border-color: rgba(216, 156, 67, 0.35) !important;
}
}
// Input Groups (Database selector, Password eye button)
.input-group {
.form-control {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
.btn {
background-color: #0A0C14 !important;
border: 1px solid rgba(216, 156, 67, 0.3) !important;
border-left: none !important;
border-top-right-radius: 12px !important;
border-bottom-right-radius: 12px !important;
color: #D89C43 !important;
padding: 0 16px !important;
display: flex !important;
align-items: center !important;
transition: all 0.2s ease !important;
&:hover {
background-color: rgba(216, 156, 67, 0.15) !important;
color: #FBBF24 !important;
}
i {
color: #D89C43 !important;
}
}
}
// Primary "Log in" Button (Grand Gold Gradient)
.btn-primary,
button[type="submit"] {
background: linear-gradient(135deg, #F59E0B 0%, #B45309 100%) !important;
color: #000000 !important;
font-weight: 700 !important;
font-size: 15px !important;
letter-spacing: 0.5px !important;
padding: 12px 28px !important;
border-radius: 9999px !important;
border: none !important;
box-shadow: 0 4px 20px rgba(245, 158, 11, 0.45) !important;
transition: all 0.22s ease !important;
margin-top: 14px !important;
width: 100% !important;
&:hover {
transform: translateY(-2px) !important;
box-shadow: 0 6px 26px rgba(245, 158, 11, 0.65) !important;
color: #000000 !important;
}
&:active {
transform: translateY(0) !important;
}
}
// Divider (- or -)
.text-center.small,
.o_login_auth_divider {
color: #71788E !important;
font-size: 12px !important;
margin: 14px 0 !important;
position: relative !important;
}
// Passkey Button (Luxury Dark Pill)
.passkey_login_link,
.list-group-item.passkey_login_link,
.list-group-item {
background: #0E111B !important;
border: 1px solid rgba(216, 156, 67, 0.32) !important;
color: #F8FAFC !important;
border-radius: 9999px !important;
padding: 10px 22px !important;
font-size: 13.5px !important;
font-weight: 500 !important;
text-align: center !important;
justify-content: center !important;
transition: all 0.2s ease !important;
text-decoration: none !important;
display: flex !important;
align-items: center !important;
gap: 8px !important;
&:hover {
background: rgba(216, 156, 67, 0.16) !important;
border-color: #D89C43 !important;
color: #FBBF24 !important;
transform: translateY(-1px) !important;
}
img, i, svg {
filter: drop-shadow(0 0 4px rgba(216, 156, 67, 0.4));
}
}
// Alerts
.alert-danger {
background: rgba(239, 68, 68, 0.15) !important;
border: 1px solid rgba(239, 68, 68, 0.4) !important;
color: #FCA5A5 !important;
border-radius: 12px !important;
font-size: 13px !important;
padding: 10px 14px !important;
}
.alert-success {
background: rgba(34, 197, 94, 0.15) !important;
border: 1px solid rgba(34, 197, 94, 0.4) !important;
color: #86EFAC !important;
border-radius: 12px !important;
font-size: 13px !important;
padding: 10px 14px !important;
}
}
// ----------------------------------------------------------------------------
// 4. Subtle Bottom Chariot Art Badge Underneath Login Card
// ----------------------------------------------------------------------------
.oe_website_login_container::after,
.container:has(.oe_login_form)::after,
.container:has(.o_database_list)::after {
content: '✦ OUR CULTURE • OUR PRIDE ✦';
display: block;
margin-top: 26px;
font-family: $tncsc-font-serif;
font-size: 11.5px;
letter-spacing: 3px;
color: rgba(216, 156, 67, 0.7);
text-align: center;
text-transform: uppercase;
font-weight: 600;
}

View File

@ -0,0 +1,24 @@
// ============================================================================
// TNCSC Primary SCSS Variables Override
// Overrides default Odoo Community & Enterprise purple (#71639e / #714B67)
// with TNCSC Signature Royal Gold (#D89C43) and Obsidian (#090B12 / #080A10)
// ============================================================================
$o-community-color: #D89C43 !default;
$o-enterprise-color: #D89C43 !default;
$o-enterprise-action-color: #D89C43 !default;
$o-brand-odoo: #D89C43 !default;
$o-brand-primary: #D89C43 !default;
$o-action: #D89C43 !default;
$o-navbar-background: #080A10 !default;
$o-navbar-border-bottom: 1px solid rgba(216, 156, 67, 0.25) !default;
$o-navbar-entry-color: #94A3B8 !default;
$o-navbar-entry-color--hover: #FFFFFF !default;
$o-navbar-entry-color--active: #D89C43 !default;
$o-navbar-entry-bg--hover: rgba(216, 156, 67, 0.12) !default;
$o-navbar-entry-bg--active: #231C14 !default;
$o-navbar-brand-color: #FFFFFF !default;
$o-navbar-badge-bg: #F59E0B !default;
$o-navbar-badge-color: #000000 !default;

View File

@ -0,0 +1,868 @@
// ============================================================================
// TNCSC Community OS Suite - Royal Obsidian & Gold Luxury Theme
// Applied across ALL Community Modules (Membership, School, Classifieds,
// Benefits, Events, Contacts, Invoicing, Settings, Discuss, Reports, etc.)
// Matching the Executive Community Dashboard Design Language
// ============================================================================
$tncsc-obsidian-dark: #090B12; // Deepest obsidian canvas background
$tncsc-obsidian-subtle: #0D101A; // Subtle dark container / navbar
$tncsc-card-bg: #111420; // High-end glassmorphic card background
$tncsc-card-border: rgba(216, 156, 67, 0.2); // Signature gold hairline border
$tncsc-gold: #D89C43; // Signature TNCSC Royal Gold
$tncsc-gold-bright: #F59E0B; // Bright amber accent
$tncsc-gold-hover: #FBBF24;
$tncsc-gold-gradient: linear-gradient(135deg, #F59E0B 0%, #B45309 100%);
$tncsc-text-white: #FFFFFF;
$tncsc-text-muted: #94A3B8;
$tncsc-text-dim: #71788E;
$tncsc-font-serif: 'Playfair Display', Georgia, 'Times New Roman', serif;
// ============================================================================
// Global Theme Tokens & Anti-Purple Overrides (Applied Across ALL Locations)
// ============================================================================
:root,
body,
.o_web_client {
--o-brand-odoo: #D89C43 !important;
--o-brand-primary: #D89C43 !important;
--o-community-color: #D89C43 !important;
--o-enterprise-color: #D89C43 !important;
--primary: #D89C43 !important;
--bs-primary: #D89C43 !important;
--bs-primary-rgb: 216, 156, 67 !important;
--bs-link-color: #F59E0B !important;
--bs-link-hover-color: #FBBF24 !important;
--o-action: #D89C43 !important;
--o-navbar-background: #080A10 !important;
--NavBar-backgroundColor: #080A10 !important;
--NavBar-entry-backgroundColor: transparent !important;
--NavBar-entry-backgroundColor--hover: rgba(216, 156, 67, 0.12) !important;
--NavBar-entry-backgroundColor--focus: rgba(216, 156, 67, 0.12) !important;
--NavBar-entry-backgroundColor--active: #231C14 !important;
--NavBar-entry-color: #94A3B8 !important;
--NavBar-entry-color--hover: #FFFFFF !important;
--NavBar-entry-color--active: #D89C43 !important;
--NavBar-brand-color: #FFFFFF !important;
--NavBar-badge-bg: #F59E0B !important;
--NavBar-badge-color: #000000 !important;
}
// ============================================================================
// 1. Overall Page Canvas & Dark Luxury Scrollbars
// ============================================================================
body,
.o_web_client,
.o_action_manager,
.o_content,
.o_view_controller {
background-color: $tncsc-obsidian-dark !important;
color: #F8FAFC !important;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
}
::-webkit-scrollbar {
width: 7px !important;
height: 7px !important;
}
::-webkit-scrollbar-track {
background: #090B12 !important;
}
::-webkit-scrollbar-thumb {
background: rgba(216, 156, 67, 0.3) !important;
border-radius: 4px !important;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(216, 156, 67, 0.6) !important;
}
// ============================================================================
// 2. Top Main Navbar (Deep Obsidian & Gold Accents - NO PURPLE ANYWHERE)
// ============================================================================
.o_main_navbar {
--o-navbar-background: #080A10 !important;
--NavBar-backgroundColor: #080A10 !important;
--NavBar-entry-backgroundColor: transparent !important;
--NavBar-entry-backgroundColor--hover: rgba(216, 156, 67, 0.12) !important;
--NavBar-entry-backgroundColor--focus: rgba(216, 156, 67, 0.12) !important;
--NavBar-entry-backgroundColor--active: #231C14 !important;
--NavBar-entry-color: #94A3B8 !important;
--NavBar-entry-color--hover: #FFFFFF !important;
--NavBar-entry-color--active: #D89C43 !important;
--NavBar-brand-color: #FFFFFF !important;
background-color: #080A10 !important;
border-bottom: 1px solid rgba(216, 156, 67, 0.25) !important;
color: #FFFFFF !important;
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.5) !important;
// 9-dots waffle apps launcher icon (replaces default purple waffle)
.o_navbar_apps_menu {
button,
.dropdown-toggle {
background: transparent !important;
color: #D89C43 !important;
border: none !important;
padding: 8px 12px !important;
border-radius: 8px !important;
transition: all 0.2s ease !important;
i, .oi, .oi-apps {
color: #D89C43 !important;
filter: drop-shadow(0 0 5px rgba(216, 156, 67, 0.5)) !important;
}
&:hover {
color: #FBBF24 !important;
background: rgba(216, 156, 67, 0.15) !important;
i, .oi, .oi-apps {
color: #FBBF24 !important;
}
}
}
}
// App brand title ("Settings", "Events", etc.)
.o_menu_brand {
color: #FFFFFF !important;
font-family: $tncsc-font-serif !important;
font-weight: 700 !important;
letter-spacing: 0.5px !important;
font-size: 16px !important;
background: transparent !important;
}
// Menu Sections (replaces the purple block behind General Settings, Users & Companies, etc.)
.o_menu_sections {
background: transparent !important;
.o_nav_entry,
.dropdown-toggle,
> a,
button,
.dropdown {
background: transparent !important;
color: #94A3B8 !important;
font-weight: 500 !important;
padding: 10px 14px !important;
border: none !important;
border-bottom: 2.5px solid transparent !important;
transition: all 0.2s ease !important;
&:hover,
&:focus {
color: #D89C43 !important;
background: rgba(216, 156, 67, 0.08) !important;
}
&.active,
&.show,
&:active {
color: #FFFFFF !important;
background: #231C14 !important;
border-bottom: 2.5px solid $tncsc-gold !important;
}
}
}
.o_user_avatar {
border-radius: 50% !important;
border: 2px solid $tncsc-gold !important;
}
.o_notification_counter {
background: linear-gradient(135deg, #F59E0B, #B45309) !important;
color: #000000 !important;
font-weight: 800 !important;
box-shadow: 0 0 8px rgba(245, 158, 11, 0.6) !important;
}
}
// ----------------------------------------------------------------------------
// Global Loading Indicator (Gold Gradient instead of Purple)
// ----------------------------------------------------------------------------
.o_loading_indicator {
background: linear-gradient(135deg, #F59E0B 0%, #B45309 100%) !important;
color: #000000 !important;
font-weight: 700 !important;
box-shadow: 0 2px 14px rgba(245, 158, 11, 0.6) !important;
border-radius: 0 0 8px 8px !important;
}
// ----------------------------------------------------------------------------
// 2B. Grand Apps Launcher Dropdown (Dark Obsidian & Gold)
// ----------------------------------------------------------------------------
.o-dropdown--menu:has(.o_app),
.dropdown-menu:has(.o_app),
div:has(> .o_app.dropdown-item),
.o_navbar_apps_menu .dropdown-menu {
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.35) !important;
border-radius: 18px !important;
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.7), 0 0 20px rgba(216, 156, 67, 0.15) !important;
padding: 14px !important;
min-width: 300px !important;
max-height: 82vh !important;
overflow-y: auto !important;
&::before {
content: '✦ TNCSC COMMUNITY OS SUITE' !important;
display: block !important;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
font-size: 11px !important;
font-weight: 800 !important;
letter-spacing: 2px !important;
color: $tncsc-gold !important;
text-transform: uppercase !important;
padding: 6px 14px 12px 14px !important;
border-bottom: 1.5px solid rgba(255, 255, 255, 0.08) !important;
margin-bottom: 10px !important;
}
.dropdown-item,
.o_app {
border-radius: 12px !important;
padding: 10px 18px !important;
font-size: 14px !important;
font-weight: 600 !important;
color: #F8FAFC !important;
border-left: 3.5px solid transparent !important;
transition: all 0.18s ease !important;
margin-bottom: 3px !important;
display: flex !important;
align-items: center !important;
gap: 10px !important;
&:hover,
&:focus {
background: rgba(216, 156, 67, 0.15) !important;
color: $tncsc-gold !important;
border-left-color: $tncsc-gold !important;
transform: translateX(4px) !important;
}
&.active,
&.focus {
background: #231C14 !important;
color: #E5A93C !important;
font-weight: 700 !important;
border-left-color: $tncsc-gold !important;
}
}
}
// ----------------------------------------------------------------------------
// 2C. Dropdown Menus
// ----------------------------------------------------------------------------
.o_menu_sections .dropdown-menu,
.o_menu_systray .dropdown-menu,
.o-dropdown--menu.dropdown-menu,
.dropdown-menu {
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.25) !important;
border-radius: 14px !important;
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.6) !important;
padding: 8px !important;
color: #F8FAFC !important;
.dropdown-header {
font-size: 11px !important;
font-weight: 700 !important;
text-transform: uppercase !important;
letter-spacing: 1.5px !important;
color: $tncsc-gold !important;
padding: 6px 14px 8px 14px !important;
}
.dropdown-item {
border-radius: 8px !important;
padding: 8px 14px !important;
font-size: 13.5px !important;
font-weight: 500 !important;
color: #CBD5E1 !important;
transition: all 0.15s ease !important;
&:hover,
&:focus {
background: rgba(216, 156, 67, 0.15) !important;
color: #FFFFFF !important;
}
&.active {
background: #231C14 !important;
color: #E5A93C !important;
font-weight: 600 !important;
}
}
}
// ============================================================================
// 3. Control Panel Across ALL Pages (Obsidian Dark & Gold)
// ============================================================================
.o_control_panel {
background-color: #0B0E17 !important;
border-bottom: 1px solid rgba(216, 156, 67, 0.2) !important;
padding: 16px 32px 14px 32px !important;
display: flex !important;
flex-direction: row !important;
align-items: center !important;
justify-content: space-between !important;
width: 100% !important;
gap: 20px !important;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3) !important;
.breadcrumb-item {
font-family: $tncsc-font-serif !important;
font-size: 18px !important;
font-weight: 700 !important;
color: #FFFFFF !important;
&.active {
color: $tncsc-gold !important;
}
a {
color: #94A3B8 !important;
text-decoration: none !important;
&:hover {
color: $tncsc-gold !important;
}
}
}
}
// Search View Box
.o_searchview {
background-color: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.25) !important;
border-radius: 9999px !important;
color: #FFFFFF !important;
padding: 3px 14px !important;
&:focus-within {
border-color: $tncsc-gold !important;
box-shadow: 0 0 0 2px rgba(216, 156, 67, 0.3) !important;
}
.o_searchview_input {
background: transparent !important;
color: #FFFFFF !important;
}
.o_searchview_facet {
background: #1E2333 !important;
border: 1px solid rgba(216, 156, 67, 0.5) !important;
color: #F8FAFC !important;
border-radius: 9999px !important;
.o_searchview_facet_label {
background: rgba(216, 156, 67, 0.2) !important;
color: $tncsc-gold !important;
border-top-left-radius: 9999px !important;
border-bottom-left-radius: 9999px !important;
}
}
}
// ============================================================================
// 4. Action Buttons Across ALL Pages (Gold Gradient Primary, Dark Pill Secondary)
// ============================================================================
.btn-primary,
.o_form_button_save,
.o-kanban-button-new,
.btn.btn-primary {
background: linear-gradient(135deg, #F59E0B 0%, #B45309 100%) !important;
border: none !important;
color: #000000 !important;
font-weight: 700 !important;
font-size: 13px !important;
padding: 7px 18px !important;
border-radius: 9999px !important;
box-shadow: 0 4px 14px rgba(245, 158, 11, 0.35) !important;
transition: all 0.2s ease !important;
&:hover {
transform: translateY(-1px) !important;
box-shadow: 0 6px 18px rgba(245, 158, 11, 0.5) !important;
color: #000000 !important;
}
}
.btn-secondary,
.btn-outline-secondary,
.o_form_button_cancel,
.btn.btn-secondary {
background: rgba(255, 255, 255, 0.05) !important;
border: 1px solid rgba(216, 156, 67, 0.35) !important;
color: #FFFFFF !important;
font-size: 13px !important;
font-weight: 500 !important;
padding: 6px 16px !important;
border-radius: 9999px !important;
transition: all 0.2s ease !important;
&:hover {
background: rgba(216, 156, 67, 0.15) !important;
border-color: $tncsc-gold !important;
color: #FFFFFF !important;
}
}
// View Switcher Buttons
.o_cp_switch_buttons .btn {
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.25) !important;
color: #94A3B8 !important;
&:hover {
color: $tncsc-gold !important;
background: rgba(216, 156, 67, 0.1) !important;
}
&.active {
background: linear-gradient(135deg, #F59E0B, #B45309) !important;
color: #000000 !important;
border-color: transparent !important;
}
}
// ============================================================================
// 5. Data Grids / List Views Across ALL Pages (Matching Dashboard Table)
// ============================================================================
.o_list_renderer {
background: transparent !important;
padding: 16px 24px !important;
}
.o_list_table,
.o_list_view .o_list_table,
.table.o_list_table {
--bs-table-bg: #111420 !important;
--bs-table-color: #F8FAFC !important;
--bs-table-striped-bg: #131622 !important;
--bs-table-striped-color: #F8FAFC !important;
--bs-table-hover-bg: rgba(216, 156, 67, 0.12) !important;
--bs-table-hover-color: #FFFFFF !important;
--bs-table-border-color: rgba(255, 255, 255, 0.08) !important;
background-color: #111420 !important;
color: #F8FAFC !important;
border: 1px solid rgba(216, 156, 67, 0.22) !important;
border-radius: 16px !important;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.45) !important;
border-collapse: separate !important;
border-spacing: 0 !important;
overflow: hidden !important;
width: 100% !important;
thead, thead tr, thead th {
background-color: #0D101A !important;
color: #D89C43 !important;
font-size: 11.5px !important;
font-weight: 700 !important;
letter-spacing: 0.8px !important;
text-transform: uppercase !important;
border-bottom: 1px solid rgba(216, 156, 67, 0.2) !important;
padding: 13px 16px !important;
vertical-align: middle !important;
* {
color: #D89C43 !important;
}
}
tbody, tbody tr {
background-color: #111420 !important;
}
tbody tr > td,
tbody tr > th,
.o_data_row > td,
.o_data_cell {
background-color: #111420 !important;
color: #F8FAFC !important;
padding: 12px 16px !important;
font-size: 13.5px !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.04) !important;
}
tbody tr:nth-of-type(even) > td,
tbody tr:nth-of-type(even) > th {
background-color: #131622 !important;
}
tbody tr:hover > td,
tbody tr:hover > th,
.o_data_row:hover > td {
background-color: rgba(216, 156, 67, 0.12) !important;
color: #FFFFFF !important;
}
&.o_data_row_selected,
.o_data_row_selected > td {
background-color: rgba(216, 156, 67, 0.18) !important;
}
tbody td,
tbody td *,
.o_data_cell,
.o_data_cell * {
color: #F8FAFC !important;
}
tbody td a,
.o_data_cell a {
color: #F59E0B !important;
font-weight: 600 !important;
text-decoration: none !important;
&:hover {
color: #FBBF24 !important;
text-decoration: underline !important;
}
}
.text-muted {
color: #94A3B8 !important;
}
input[type="checkbox"] {
accent-color: $tncsc-gold !important;
width: 15px !important;
height: 15px !important;
cursor: pointer !important;
}
}
// Empty View / Nocontent helper state
.o_view_nocontent {
background: transparent !important;
color: #94A3B8 !important;
.o_nocontent_help,
p {
color: #94A3B8 !important;
font-size: 14px !important;
}
h4, b, strong {
color: #FFFFFF !important;
font-family: $tncsc-font-serif !important;
}
.o_view_nocontent_smiling_face {
filter: brightness(0.85) sepia(1) hue-rotate(5deg) saturate(3) !important;
}
}
// ============================================================================
// 6. Kanban Views Across ALL Pages (Matching Dashboard Cards)
// ============================================================================
.o_kanban_view {
background: transparent !important;
padding: 16px 24px !important;
.o_kanban_group {
background: #0B0E17 !important;
border: 1px solid rgba(255, 255, 255, 0.05) !important;
border-radius: 16px !important;
padding: 12px !important;
.o_kanban_header_title {
color: $tncsc-gold !important;
font-weight: 700 !important;
font-size: 14px !important;
}
}
.o_kanban_record {
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.2) !important;
border-radius: 14px !important;
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35) !important;
color: #FFFFFF !important;
margin-bottom: 12px !important;
padding: 16px !important;
transition: all 0.22s ease !important;
&:hover {
transform: translateY(-3px) !important;
border-color: $tncsc-gold !important;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5), 0 0 15px rgba(216, 156, 67, 0.2) !important;
}
strong, .o_kanban_record_title {
font-family: $tncsc-font-serif !important;
color: #FFFFFF !important;
font-size: 15.5px !important;
font-weight: 700 !important;
}
}
}
// ============================================================================
// 7. Form Views (Obsidian Sheet & Gold Pipelines)
// ============================================================================
.o_form_sheet_bg {
background: #090B12 !important;
padding: 24px !important;
}
.o_form_sheet {
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.25) !important;
border-top: 3px solid $tncsc-gold !important;
border-radius: 18px !important;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5) !important;
color: #FFFFFF !important;
max-width: 1200px !important;
padding: 28px 32px !important;
h1, .oe_title h1 {
font-family: $tncsc-font-serif !important;
color: #FFFFFF !important;
font-weight: 700 !important;
}
}
// Form Statusbar
.o_form_statusbar {
background: #0D101A !important;
border: 1px solid rgba(216, 156, 67, 0.2) !important;
border-radius: 12px !important;
padding: 6px 14px !important;
margin-bottom: 20px !important;
.o_statusbar_status .o_arrow_button.o_arrow_button_current {
background: linear-gradient(135deg, #F59E0B, #B45309) !important;
color: #000000 !important;
font-weight: 700 !important;
border-radius: 9999px !important;
}
}
// Smart Buttons
.oe_button_box .btn {
background: #0D101A !important;
border: 1px solid rgba(216, 156, 67, 0.2) !important;
color: #FFFFFF !important;
border-radius: 10px !important;
margin-right: 6px !important;
.o_stat_value {
color: $tncsc-gold !important;
font-weight: 700 !important;
font-size: 16px !important;
}
.o_stat_text {
color: #94A3B8 !important;
font-size: 11px !important;
}
&:hover {
border-color: $tncsc-gold !important;
background: rgba(216, 156, 67, 0.1) !important;
}
}
// Form Labels & Inputs
.o_inner_group {
.o_form_label {
color: #94A3B8 !important;
font-weight: 600 !important;
font-size: 12.5px !important;
}
}
.o_field_widget input,
.o_field_widget select,
.o_field_widget textarea {
background: #0A0C14 !important;
border: 1px solid rgba(216, 156, 67, 0.25) !important;
color: #FFFFFF !important;
border-radius: 8px !important;
padding: 6px 12px !important;
&:focus {
border-color: $tncsc-gold !important;
box-shadow: 0 0 0 2px rgba(216, 156, 67, 0.3) !important;
}
}
// Notebook Tabs
.nav-tabs {
border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
.nav-link {
color: #94A3B8 !important;
font-weight: 500 !important;
border: none !important;
border-bottom: 2.5px solid transparent !important;
&:hover {
color: $tncsc-gold !important;
}
&.active {
color: $tncsc-gold !important;
background: transparent !important;
border-bottom: 2.5px solid $tncsc-gold !important;
font-weight: 700 !important;
}
}
}
// ============================================================================
// 8. Chatter Container (Obsidian Dark Feed)
// ============================================================================
.o_ChatterContainer,
.o-mail-Chatter {
background: #090B12 !important;
border-left: 1px solid rgba(216, 156, 67, 0.18) !important;
.o-mail-Message {
background: #111420 !important;
border: 1px solid rgba(255, 255, 255, 0.06) !important;
border-radius: 12px !important;
color: #F1F5F9 !important;
margin-bottom: 12px !important;
padding: 14px !important;
}
.o-mail-Composer {
background: #0D101A !important;
border: 1px solid rgba(216, 156, 67, 0.25) !important;
border-radius: 12px !important;
}
}
// ============================================================================
// 9. Modals & Dialogs
// ============================================================================
.modal-content {
background: #111420 !important;
border: 1px solid rgba(216, 156, 67, 0.35) !important;
border-radius: 18px !important;
color: #FFFFFF !important;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7) !important;
.modal-header {
border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important;
font-family: $tncsc-font-serif !important;
color: $tncsc-gold !important;
}
.modal-footer {
border-top: 1px solid rgba(255, 255, 255, 0.08) !important;
}
}
// ============================================================================
// 10. Universal Anti-Purple & Gold Theme Color Polish (All Locations)
// ============================================================================
// Links across the application
a:not(.btn):not(.o_nav_item):not(.dropdown-item) {
color: #F59E0B;
&:hover {
color: #FBBF24;
}
}
// Form view URL links
.o_form_uri {
color: #F59E0B !important;
&:hover {
color: #FBBF24 !important;
}
}
// Primary outline buttons
.btn-outline-primary {
border-color: $tncsc-gold !important;
color: $tncsc-gold !important;
background: transparent !important;
&:hover,
&:active,
&.active {
background: linear-gradient(135deg, #F59E0B, #B45309) !important;
border-color: transparent !important;
color: #000000 !important;
}
}
// Badges & Tag Pills
.badge.bg-primary,
.badge.text-bg-primary,
.badge-primary,
.o_tag.badge-primary,
.o_tag_color_0 {
background: linear-gradient(135deg, #F59E0B, #B45309) !important;
color: #000000 !important;
font-weight: 700 !important;
}
// Form switches & toggles
.form-check-input:checked {
background-color: $tncsc-gold !important;
border-color: $tncsc-gold !important;
}
// Progress bars
.progress-bar,
.o_progressbar .o_progress {
background-color: $tncsc-gold !important;
background-image: linear-gradient(135deg, #F59E0B 0%, #B45309 100%) !important;
}
// Datepicker / DateTime Picker
.o_datetime_picker .o_selected,
.datepicker td.active,
.datepicker td.active:hover {
background: linear-gradient(135deg, #F59E0B, #B45309) !important;
color: #000000 !important;
font-weight: 700 !important;
}
// Many2one and Many2many field pills
.o_field_many2many_tags .badge,
.o_field_tags .badge {
background: rgba(216, 156, 67, 0.2) !important;
border: 1px solid rgba(216, 156, 67, 0.45) !important;
color: #F8FAFC !important;
border-radius: 9999px !important;
.o_delete {
color: $tncsc-gold !important;
&:hover {
color: #FFFFFF !important;
}
}
}
// Required input left border highlight
.o_required_modifier.o_input,
.o_required_modifier input {
border-left: 3px solid $tncsc-gold !important;
}
// Dropdown item focus & active states
.dropdown-item.active,
.dropdown-item:active,
.ui-autocomplete .ui-menu-item.ui-state-focus,
.ui-autocomplete .ui-menu-item > a.ui-state-active {
background-color: #231C14 !important;
color: #E5A93C !important;
font-weight: 600 !important;
}
// Notification counters & systray
.o_menu_systray {
.dropdown-toggle {
color: #94A3B8 !important;
&:hover {
color: #FFFFFF !important;
}
}
}

View File

@ -0,0 +1,311 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="tncsc_deployment.CommunityDashboard">
<div class="o_tncsc_dashboard_root d-flex">
<!-- MAIN CONTENT AREA -->
<main class="o_tncsc_main_content flex-grow-1">
<!-- HEADER WITH GOPURAM SILHOUETTE BANNER -->
<header class="o_dashboard_header d-flex align-items-center justify-content-between">
<div class="o_header_left">
<div class="o_society_tag">✦ TAMIL NADU CULTURAL SOCIETY OF CANADA</div>
<h1 class="o_dashboard_title">Community Dashboard</h1>
<div class="o_dashboard_tagline">Connecting our roots • Celebrating our culture • Building our community</div>
</div>
<div class="o_header_right d-flex align-items-center gap-2">
<button class="btn o_btn_gold_gradient" t-on-click="openNewEvent">
+ New Event
</button>
<button class="btn o_btn_dark_pill" t-on-click="openNewMember">
+ Add Member
</button>
<button class="btn o_btn_dark_pill" t-on-click="openNewStudent">
+ Enroll Student
</button>
<button class="btn o_btn_circle_icon" t-on-click="refreshDashboard" title="Refresh">
<i class="fa fa-refresh"/>
</button>
</div>
</header>
<div class="o_dashboard_body">
<!-- ROW 1: 4 EXECUTIVE KPI CARDS -->
<div class="row g-3 mb-3">
<!-- KPI 1: Members -->
<div class="col-12 col-sm-6 col-xl-3">
<div class="o_kpi_card" t-on-click="openMembers">
<i class="fa fa-users o_kpi_watermark"/>
<div class="d-flex align-items-center gap-2 mb-2">
<div class="o_kpi_gold_badge">
<i class="fa fa-users"/>
</div>
<span class="o_kpi_title">COMMUNITY MEMBERS</span>
</div>
<div class="o_kpi_number"><t t-esc="state.stats.membership.total"/></div>
<div class="d-flex align-items-center justify-content-between mt-2">
<span class="o_pill_badge badge_green"><t t-esc="state.stats.membership.active"/> Active</span>
<span class="o_kpi_link">Manage Members →</span>
</div>
</div>
</div>
<!-- KPI 2: Events -->
<div class="col-12 col-sm-6 col-xl-3">
<div class="o_kpi_card" t-on-click="openEvents">
<i class="fa fa-calendar o_kpi_watermark"/>
<div class="d-flex align-items-center gap-2 mb-2">
<div class="o_kpi_gold_badge">
<i class="fa fa-calendar"/>
</div>
<span class="o_kpi_title">EVENTS &amp; FESTIVALS</span>
</div>
<div class="o_kpi_number"><t t-esc="state.stats.events.total"/></div>
<div class="d-flex align-items-center justify-content-between mt-2">
<span class="o_pill_badge badge_amber"><t t-esc="state.stats.events.upcoming.length"/> Scheduled</span>
<span class="o_kpi_link">View Events →</span>
</div>
</div>
</div>
<!-- KPI 3: School -->
<div class="col-12 col-sm-6 col-xl-3">
<div class="o_kpi_card" t-on-click="openSchool">
<i class="fa fa-graduation-cap o_kpi_watermark"/>
<div class="d-flex align-items-center gap-2 mb-2">
<div class="o_kpi_gold_badge">
<i class="fa fa-graduation-cap"/>
</div>
<span class="o_kpi_title">TAMIL SCHOOL (தமிழ்ப் பள்ளி)</span>
</div>
<div class="o_kpi_number"><t t-esc="state.stats.school.students"/></div>
<div class="d-flex align-items-center justify-content-between mt-2">
<span class="o_pill_badge badge_purple"><t t-esc="state.stats.school.classes"/> Classes Active</span>
<span class="o_kpi_link">School Portal →</span>
</div>
</div>
</div>
<!-- KPI 4: Benefits & Marketplace -->
<div class="col-12 col-sm-6 col-xl-3">
<div class="o_kpi_card" t-on-click="openBenefits">
<i class="fa fa-shopping-bag o_kpi_watermark"/>
<div class="d-flex align-items-center gap-2 mb-2">
<div class="o_kpi_gold_badge">
<i class="fa fa-shopping-cart"/>
</div>
<span class="o_kpi_title">BENEFITS &amp; MARKETPLACE</span>
</div>
<div class="o_kpi_number"><t t-esc="state.stats.classifieds.total"/></div>
<div class="d-flex align-items-center justify-content-between mt-2">
<span class="o_pill_badge badge_blue"><t t-esc="state.stats.classifieds.total"/> Classifieds</span>
<span class="o_kpi_link">Explore Hub →</span>
</div>
</div>
</div>
</div>
<!-- ROW 2: MIDDLE 2 COLUMNS -->
<div class="row g-3 mb-3">
<!-- Left: Upcoming Cultural Programs (Warm Ivory Card) -->
<div class="col-12 col-lg-7">
<div class="o_ivory_card h-100">
<div class="d-flex align-items-center justify-content-between mb-3">
<div class="d-flex align-items-center gap-2">
<div class="o_ivory_gold_icon">
<i class="fa fa-calendar-check-o"/>
</div>
<div>
<h3 class="o_ivory_card_title mb-0">Upcoming Cultural Programs</h3>
<div class="o_ivory_card_subtitle">Events organized by Tamil Nadu Cultural Society of Canada</div>
</div>
</div>
<button class="btn o_btn_ivory_pill" t-on-click="openEvents">
View All Events
</button>
</div>
<!-- Featured Program Banner (Pongal) -->
<div class="o_featured_pongal_banner" t-on-click="() => this.openEvent(state.stats.events.upcoming[0]?.id)">
<div class="d-flex align-items-center gap-3">
<div class="o_pongal_date_box">
<div class="day"><t t-esc="state.stats.events.upcoming[0]?.day || '18'"/></div>
<div class="month"><t t-esc="state.stats.events.upcoming[0]?.month_year || 'JAN 2026'"/></div>
</div>
<div class="o_pongal_info">
<div class="o_featured_badge">FEATURED PROGRAM</div>
<h4 class="o_featured_name"><t t-esc="state.stats.events.upcoming[0]?.name || 'Pongal Celebration'"/></h4>
<div class="o_featured_meta">
<i class="fa fa-map-marker me-1"/> <t t-esc="state.stats.events.upcoming[0]?.city || 'Brampton, ON'"/> • <i class="fa fa-clock-o ms-2 me-1"/> <t t-esc="state.stats.events.upcoming[0]?.date_begin || 'Jan 18, 2026 - 04:30 AM'"/>
</div>
</div>
</div>
<button class="btn o_btn_details_pill">
Open Details →
</button>
</div>
<!-- Mini Events List -->
<div class="o_ivory_events_list">
<t t-foreach="state.stats.events.upcoming.slice(1, 4)" t-as="ev" t-key="ev.id">
<div class="o_ivory_event_row" t-on-click="() => this.openEvent(ev.id)">
<div class="d-flex align-items-center gap-3">
<span class="o_event_date_pill"><t t-esc="ev.date_short"/></span>
<span class="o_event_name_text"><t t-esc="ev.name"/></span>
</div>
<div class="d-flex align-items-center gap-2">
<span t-attf-class="o_status_pill #{ev.stage == 'Ended' ? 'status_ended' : ev.stage == 'New' ? 'status_new' : 'status_booked'}">
<t t-esc="ev.stage"/>
</span>
<i class="fa fa-chevron-right o_chevron_icon"/>
</div>
</div>
</t>
</div>
</div>
</div>
<!-- Right: Membership Structure (Dark Card) -->
<div class="col-12 col-lg-5">
<div class="o_dark_structure_card h-100 d-flex flex-column justify-content-between">
<div>
<div class="d-flex align-items-center justify-content-between mb-3">
<div class="d-flex align-items-center gap-2">
<div class="o_structure_gold_icon">
<i class="fa fa-id-card-o"/>
</div>
<div>
<h3 class="o_dark_card_title mb-0">Membership Structure</h3>
<div class="o_dark_card_subtitle">Tier pricing and member enrollment</div>
</div>
</div>
<button class="btn o_btn_dark_pill_sm" t-on-click="openTiers">
View Tiers
</button>
</div>
<!-- Tier Table -->
<div class="o_tier_table_wrapper">
<table class="o_tier_table">
<thead>
<tr>
<th class="ps-2">TIER</th>
<th class="text-center">PRICE (CAD)</th>
<th class="text-center">TERM</th>
<th class="text-end pe-2">ENROLLED</th>
</tr>
</thead>
<tbody>
<t t-foreach="state.stats.membership.tiers" t-as="tier" t-key="tier.name">
<tr t-on-click="openMembers">
<td class="ps-2 d-flex align-items-center gap-2">
<i t-attf-class="fa #{tier.icon} o_tier_icon"/>
<span><t t-esc="tier.name"/></span>
</td>
<td class="text-center text-gold"><t t-esc="tier.price"/></td>
<td class="text-center text-muted-dim"><t t-esc="tier.period"/></td>
<td class="text-end pe-2 text-white font-monospace"><t t-esc="tier.count"/></td>
</tr>
</t>
</tbody>
</table>
</div>
</div>
<!-- Bottom 3 Counter Row -->
<div class="o_membership_status_trio d-flex align-items-center justify-content-around pt-3 mt-3">
<div class="text-center">
<div class="d-flex align-items-center justify-content-center gap-2">
<i class="fa fa-users text-success fs-5"/>
<span class="fs-4 fw-bold text-white"><t t-esc="state.stats.membership.active"/></span>
</div>
<div class="o_status_label">ACTIVE</div>
</div>
<div class="o_status_divider"/>
<div class="text-center">
<div class="d-flex align-items-center justify-content-center gap-2">
<i class="fa fa-refresh text-warning fs-5"/>
<span class="fs-4 fw-bold text-white"><t t-esc="state.stats.membership.renewal_due"/></span>
</div>
<div class="o_status_label">RENEWAL DUE</div>
</div>
<div class="o_status_divider"/>
<div class="text-center">
<div class="d-flex align-items-center justify-content-center gap-2">
<i class="fa fa-clock-o text-secondary fs-5"/>
<span class="fs-4 fw-bold text-white"><t t-esc="state.stats.membership.expired"/></span>
</div>
<div class="o_status_label">EXPIRED</div>
</div>
</div>
</div>
</div>
</div>
<!-- ROW 3: OPERATIONS HUB -->
<div class="o_operations_hub_section mt-4 mb-2">
<div class="mb-3">
<h3 class="o_hub_section_title mb-0">Community Operations Hub</h3>
<div class="o_hub_section_subtitle">Fast access to manage modules in the Community OS Suite</div>
</div>
<div class="row g-3">
<div class="col-12 col-sm-6 col-xl-3">
<div class="o_hub_pill_card" t-on-click="openMembers">
<div class="d-flex align-items-center gap-3">
<div class="o_hub_pill_icon">
<i class="fa fa-users"/>
</div>
<span class="o_hub_pill_title">Members</span>
</div>
<i class="fa fa-arrow-right o_hub_pill_arrow"/>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="o_hub_pill_card" t-on-click="openEvents">
<div class="d-flex align-items-center gap-3">
<div class="o_hub_pill_icon">
<i class="fa fa-calendar"/>
</div>
<span class="o_hub_pill_title">Events</span>
</div>
<i class="fa fa-arrow-right o_hub_pill_arrow"/>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="o_hub_pill_card" t-on-click="openSchool">
<div class="d-flex align-items-center gap-3">
<div class="o_hub_pill_icon">
<i class="fa fa-graduation-cap"/>
</div>
<span class="o_hub_pill_title">Tamil School</span>
</div>
<i class="fa fa-arrow-right o_hub_pill_arrow"/>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="o_hub_pill_card" t-on-click="openMarketplace">
<div class="d-flex align-items-center gap-3">
<div class="o_hub_pill_icon">
<i class="fa fa-shopping-cart"/>
</div>
<span class="o_hub_pill_title">Marketplace</span>
</div>
<i class="fa fa-arrow-right o_hub_pill_arrow"/>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</t>
</templates>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="tncsc_deployment.GlobalSidebar">
<aside class="o_tncsc_global_sidebar d-flex flex-column justify-content-between" t-att-class="{'collapsed': state.collapsed}">
<div class="o_sidebar_top">
<!-- Brand Header -->
<div class="o_sidebar_brand text-center" t-on-click="openDashboard">
<img class="o_sidebar_logo" src="/tncsc_deployment/static/src/img/gold_lotus_logo.png" alt="TNCSC Logo"/>
<div class="o_brand_text_line1">TAMIL NADU</div>
<div class="o_brand_text_line2">CULTURAL SOCIETY</div>
<div class="o_brand_text_line3">OF CANADA</div>
</div>
<!-- Navigation Links -->
<nav class="o_sidebar_nav mt-4">
<a t-attf-class="o_nav_item #{state.activeTab == 'dashboard' ? 'active' : ''}" t-on-click="openDashboard">
<i class="fa fa-home o_nav_icon"/>
<span class="o_nav_label">Dashboard</span>
</a>
<a t-attf-class="o_nav_item #{state.activeTab == 'members' ? 'active' : ''}" t-on-click="openMembers">
<i class="fa fa-users o_nav_icon"/>
<span class="o_nav_label">Members</span>
</a>
<a t-attf-class="o_nav_item #{state.activeTab == 'events' ? 'active' : ''}" t-on-click="openEvents">
<i class="fa fa-calendar o_nav_icon"/>
<span class="o_nav_label">Events</span>
</a>
<a t-attf-class="o_nav_item #{state.activeTab == 'school' ? 'active' : ''}" t-on-click="openSchool">
<i class="fa fa-graduation-cap o_nav_icon"/>
<span class="o_nav_label">Tamil School</span>
</a>
<a t-attf-class="o_nav_item #{state.activeTab == 'benefits' ? 'active' : ''}" t-on-click="openBenefits">
<i class="fa fa-tags o_nav_icon"/>
<span class="o_nav_label">Benefits &amp; Marketplace</span>
</a>
<a t-attf-class="o_nav_item #{state.activeTab == 'cultural' ? 'active' : ''}" t-on-click="openCulturalPrograms">
<i class="fa fa-university o_nav_icon"/>
<span class="o_nav_label">Cultural Programs</span>
</a>
<a t-attf-class="o_nav_item #{state.activeTab == 'reports' ? 'active' : ''}" t-on-click="openReports">
<i class="fa fa-file-text-o o_nav_icon"/>
<span class="o_nav_label">Reports</span>
</a>
<a t-attf-class="o_nav_item #{state.activeTab == 'settings' ? 'active' : ''}" t-on-click="openSettings">
<i class="fa fa-cog o_nav_icon"/>
<span class="o_nav_label">Settings</span>
</a>
</nav>
</div>
<!-- Sidebar Bottom: Chariot Art & Motto -->
<div class="o_sidebar_bottom text-center">
<div class="o_chariot_img_wrap">
<img src="/tncsc_deployment/static/src/img/dashboard/gold_chariot_art.jpg" alt="Tamil Chariot" class="o_chariot_img"/>
</div>
<div class="o_motto_wrap">
<div class="o_motto_line">Our Culture</div>
<div class="o_motto_line">Our Pride</div>
</div>
</div>
</aside>
</t>
</templates>

View File

@ -3,45 +3,75 @@
<!-- Filter Pills Bar above Kanban Groups --> <!-- Filter Pills Bar above Kanban Groups -->
<t t-inherit="web.KanbanRenderer" t-inherit-mode="extension"> <t t-inherit="web.KanbanRenderer" t-inherit-mode="extension">
<xpath expr="//t[@t-foreach='getGroupsOrRecords()']" position="before"> <xpath expr="//t[@t-foreach='getGroupsOrRecords()']" position="before">
<t t-if="props.list and props.list.resModel === 'event.event'"> <t t-if="isTncscEventKanban">
<div class="o_tncsc_filter_pills_bar d-flex align-items-center gap-3 w-100 flex-wrap"> <div class="o_tncsc_filter_pills_bar d-flex align-items-center gap-3 w-100 flex-wrap">
<div class="o_tncsc_filter_pill active d-flex align-items-center justify-content-between"> <div t-attf-class="o_tncsc_filter_pill d-flex align-items-center justify-content-between {{ (state.tncscActiveStage || 'all') === 'all' ? 'active' : '' }}"
t-on-click="() => this.setTncscStage('all')">
<span class="d-flex align-items-center gap-2"> <span class="d-flex align-items-center gap-2">
<span class="o_dot">&#9679;</span> <span class="o_dot">&#9679;</span>
<span class="o_label">All</span> <span class="o_label">All</span>
</span> </span>
<span class="o_count ms-3">4</span> <span class="o_count ms-3" t-esc="tncscStageCounts.all"/>
</div> </div>
<div class="o_tncsc_filter_pill pill-new d-flex align-items-center justify-content-between"> <div t-attf-class="o_tncsc_filter_pill pill-new d-flex align-items-center justify-content-between {{ state.tncscActiveStage === 'new' ? 'active' : '' }}"
t-on-click="() => this.setTncscStage('new')">
<span class="d-flex align-items-center gap-2"> <span class="d-flex align-items-center gap-2">
<span class="o_dot dot-gold">&#9679;</span> <span class="o_dot dot-gold">&#9679;</span>
<span class="o_label">New</span> <span class="o_label">New</span>
</span> </span>
<span class="o_count ms-3">1</span> <span class="o_count ms-3" t-esc="tncscStageCounts.new"/>
</div> </div>
<div class="o_tncsc_filter_pill pill-booked d-flex align-items-center justify-content-between"> <div t-attf-class="o_tncsc_filter_pill pill-booked d-flex align-items-center justify-content-between {{ state.tncscActiveStage === 'booked' ? 'active' : '' }}"
t-on-click="() => this.setTncscStage('booked')">
<span class="d-flex align-items-center gap-2"> <span class="d-flex align-items-center gap-2">
<span class="o_dot dot-cyan">&#9679;</span> <span class="o_dot dot-cyan">&#9679;</span>
<span class="o_label">Booked</span> <span class="o_label">Booked</span>
</span> </span>
<span class="o_count ms-3">0</span> <span class="o_count ms-3" t-esc="tncscStageCounts.booked"/>
</div> </div>
<div class="o_tncsc_filter_pill pill-announced d-flex align-items-center justify-content-between"> <div t-attf-class="o_tncsc_filter_pill pill-announced d-flex align-items-center justify-content-between {{ state.tncscActiveStage === 'announced' ? 'active' : '' }}"
t-on-click="() => this.setTncscStage('announced')">
<span class="d-flex align-items-center gap-2"> <span class="d-flex align-items-center gap-2">
<span class="o_dot dot-green">&#9679;</span> <span class="o_dot dot-green">&#9679;</span>
<span class="o_label">Anounced</span> <span class="o_label">Announced</span>
</span> </span>
<span class="o_count ms-3">0</span> <span class="o_count ms-3" t-esc="tncscStageCounts.announced"/>
</div> </div>
<div class="o_tncsc_filter_pill pill-ended d-flex align-items-center justify-content-between"> <div t-attf-class="o_tncsc_filter_pill pill-ended d-flex align-items-center justify-content-between {{ state.tncscActiveStage === 'ended' ? 'active' : '' }}"
t-on-click="() => this.setTncscStage('ended')">
<span class="d-flex align-items-center gap-2"> <span class="d-flex align-items-center gap-2">
<span class="o_dot dot-purple">&#9679;</span> <span class="o_dot dot-purple">&#9679;</span>
<span class="o_label">Ended</span> <span class="o_label">Ended</span>
</span> </span>
<span class="o_count ms-3">0</span> <span class="o_count ms-3" t-esc="tncscStageCounts.ended"/>
</div> </div>
</div> </div>
</t> </t>
</xpath> </xpath>
<!-- Empty state inside grouped column when 0 records -->
<xpath expr="//t[@t-foreach='group.list.records']" position="after">
<t t-if="isTncscEventKanban and group.list.records.length === 0">
<t t-if="state.tncscActiveStage and state.tncscActiveStage !== 'all'">
<div class="o_tncsc_empty_stage_box d-flex flex-column align-items-center justify-content-center w-100 py-5 my-3">
<div class="o_tncsc_empty_icon mb-3">
<svg viewBox="0 0 24 24" width="44" height="44" stroke="#D4A359" stroke-width="1.6" fill="none" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
<line x1="16" y1="2" x2="16" y2="6"/>
<line x1="8" y1="2" x2="8" y2="6"/>
<line x1="3" y1="10" x2="21" y2="10"/>
</svg>
</div>
<div class="o_tncsc_empty_title fs-5 fw-bold mb-1">No Events Found</div>
<div class="o_tncsc_empty_sub small">There are currently no events in <t t-esc="group.displayName"/> stage.</div>
</div>
</t>
<t t-else="">
<div class="o_tncsc_empty_column_placeholder text-center p-4 w-100">
<span class="text-muted small fst-italic">No <t t-esc="group.displayName"/> events</span>
</div>
</t>
</t>
</xpath>
</t> </t>
</templates> </templates>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Community Dashboard Client Action -->
<record id="action_community_dashboard" model="ir.actions.client">
<field name="name">Community Dashboard</field>
<field name="tag">tncsc_community_dashboard</field>
<field name="path">community-dashboard</field>
</record>
<!-- Top-Level Root Menu in Apps Launcher -->
<menuitem id="menu_community_dashboard_root"
name="Community Dashboard"
action="action_community_dashboard"
sequence="1"
web_icon="tncsc_deployment,static/src/img/gold_lotus_logo.png"/>
</odoo>

View File

@ -22,7 +22,7 @@
<!-- Replace standard main content with Tamil Luxury Dark Theme Card while keeping <main> tag --> <!-- Replace standard main content with Tamil Luxury Dark Theme Card while keeping <main> tag -->
<xpath expr="//main" position="replace"> <xpath expr="//main" position="replace">
<main class="p-0 o_tncsc_dark_card w-100"> <main class="p-0 o_tncsc_card w-100">
<!-- Bottom-right subtle mandala corner artwork --> <!-- Bottom-right subtle mandala corner artwork -->
<div class="o_tncsc_mandala_corner"/> <div class="o_tncsc_mandala_corner"/>
@ -144,7 +144,7 @@
<!-- Ensure default group by stage for the main Events action and clear upcoming filter --> <!-- Ensure default group by stage for the main Events action and clear upcoming filter -->
<record id="event.action_event_view" model="ir.actions.act_window"> <record id="event.action_event_view" model="ir.actions.act_window">
<field name="context">{'default_group_by': 'stage_id', 'search_default_stage_id': 1, 'search_default_upcoming': 0}</field> <field name="context">{'default_group_by': 'stage_id', 'search_default_upcoming': 0}</field>
</record> </record>
<!-- Load Google Fonts Playfair Display cleanly in web.layout --> <!-- Load Google Fonts Playfair Display cleanly in web.layout -->

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Brand Header inside the Login Form / Card -->
<template id="tncsc_login_card_branding" inherit_id="web.login" name="TNCSC Login Card Branding" priority="50">
<xpath expr="//form" position="before">
<div class="text-center pb-3 border-bottom mb-4 o_tncsc_login_brand_header">
<img src="/tncsc_deployment/static/src/img/gold_lotus_logo.png" alt="TNCSC Golden Lotus" class="o_tncsc_login_logo" style="max-height: 58px; width: auto;"/>
<div class="o_tncsc_login_brand_title" style="font-family: 'Playfair Display', Georgia, serif; font-size: 13.5px; font-weight: 700; letter-spacing: 1.5px; color: #D89C43; text-transform: uppercase; margin-top: 10px; line-height: 1.3;">
TAMIL NADU CULTURAL SOCIETY
</div>
<div class="o_tncsc_login_brand_country" style="font-family: 'Playfair Display', Georgia, serif; font-size: 12px; font-weight: 700; letter-spacing: 2px; color: #D89C43; text-transform: uppercase; margin-top: 2px;">
OF CANADA
</div>
<div class="o_tncsc_login_tagline" style="font-size: 11px; color: #94A3B8; letter-spacing: 0.3px; margin-top: 6px;">
Connecting our roots • Celebrating our culture
</div>
</div>
</xpath>
</template>
</odoo>