Skip to content

Commit f571a61

Browse files
Update index.html
1 parent 5e5539c commit f571a61

1 file changed

Lines changed: 193 additions & 38 deletions

File tree

index.html

Lines changed: 193 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ <h1 class="mt-4 text-3xl font-semibold leading-tight sm:text-4xl">
510510
{ type: "Events (incl. Conf + HH)", events: 2, avgInvited: 330, avgAttended: 300, avgOpps: 85, avgOppInvited: "25%", avgOppAttended: "28%", avgClosed: 25, win: "28%" },
511511
{ type: "Partner Events", events: 3, avgInvited: 280, avgAttended: 207, avgOpps: 52, avgOppInvited: "19%", avgOppAttended: "25%", avgClosed: 12, win: "24%" },
512512
]
513-
}
513+
},
514+
filterModalOpen: false,
515+
selectedPartnerTypes: []
514516
};
515517
const PARTNER_TYPES = ["Registered", "Preferred", "Premier", "MSP", "Technology Partner (ISV)", "OEM Partner", "Distributor Partner"];
516518
const TABS = [
@@ -521,6 +523,26 @@ <h1 class="mt-4 text-3xl font-semibold leading-tight sm:text-4xl">
521523
{ id: 'margins', label: 'Margins', icon: 'dollar-sign' },
522524
{ id: 'roe', label: 'Rules of Engagement', icon: 'gavel' }
523525
];
526+
function initFilter() {
527+
STATE.selectedPartnerTypes = PARTNER_TYPES.slice();
528+
if (typeof localStorage !== 'undefined') {
529+
try {
530+
const saved = localStorage.getItem('recastPartnerTypeFilter');
531+
if (saved) {
532+
const parsed = JSON.parse(saved);
533+
STATE.selectedPartnerTypes = parsed.selectedPartnerTypes.filter(t => PARTNER_TYPES.includes(t));
534+
}
535+
} catch (e) {
536+
// fallback to default
537+
}
538+
}
539+
if (STATE.selectedPartnerTypes.length === 0) {
540+
STATE.selectedPartnerTypes = PARTNER_TYPES.slice();
541+
}
542+
if (!STATE.selectedPartnerTypes.includes(STATE.partnerType)) {
543+
STATE.partnerType = STATE.selectedPartnerTypes[0];
544+
}
545+
}
524546
function setDefaultBand(type) {
525547
if (type === 'Registered') return 'band3';
526548
if (type === 'Preferred') return 'band2';
@@ -562,6 +584,9 @@ <h1 class="mt-4 text-3xl font-semibold leading-tight sm:text-4xl">
562584
}
563585
}
564586
function render() {
587+
if (!STATE.selectedPartnerTypes.includes(STATE.partnerType)) {
588+
STATE.partnerType = STATE.selectedPartnerTypes[0] || PARTNER_TYPES[0];
589+
}
565590
const data = getPartnerData(STATE.partnerType);
566591
let html = '<div class="space-y-6">';
567592
html += renderPartnerTypeSelector();
@@ -589,14 +614,16 @@ <h1 class="mt-4 text-3xl font-semibold leading-tight sm:text-4xl">
589614
break;
590615
case 'onboarding':
591616
if (STATE.partnerType !== 'Registered') {
592-
html += renderOnboardingContent();
617+
html += renderOnboardingContent(data);
593618
} else {
594619
html += '<p class="text-center text-gray-700 leading-relaxed">Not applicable for Registered partners.</p>';
595620
}
596621
break;
597622
}
598623
html += '</div>';
599624
html += '</div>';
625+
html += renderFilterTrigger();
626+
if (STATE.filterModalOpen) html += renderFilterModal();
600627
if (STATE.showBusinessPlanModal) {
601628
html += renderBusinessPlanModal();
602629
}
@@ -611,9 +638,51 @@ <h1 class="mt-4 text-3xl font-semibold leading-tight sm:text-4xl">
611638
lucide.createIcons();
612639
addEventListeners();
613640
}
641+
function renderFilterTrigger() {
642+
return `
643+
<div class="fixed bottom-4 left-4 z-50">
644+
<input type="checkbox" id="filterTrigger" class="h-4 w-4 rounded accent-[#2563eb] opacity-50 focus:opacity-100" ${STATE.filterModalOpen ? 'checked' : ''} />
645+
</div>
646+
`;
647+
}
648+
function renderFilterModal() {
649+
let checkboxes = '';
650+
PARTNER_TYPES.forEach(t => {
651+
const display = t === 'Registered' ? 'Registered (LAR/Referral)' : t;
652+
const checked = STATE.selectedPartnerTypes.includes(t) ? 'checked' : '';
653+
checkboxes += `
654+
<label class="flex items-center gap-2">
655+
<input type="checkbox" class="partner-type-checkbox h-4 w-4 rounded accent-[#2563eb]" data-type="${t}" ${checked} />
656+
${display}
657+
</label>
658+
`;
659+
});
660+
const allChecked = STATE.selectedPartnerTypes.length === PARTNER_TYPES.length ? 'checked' : '';
661+
return `
662+
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4" role="dialog" aria-modal="true" id="filterModalBg">
663+
<div class="relative max-w-md w-full bg-white rounded-xl shadow-2xl p-6">
664+
<button class="absolute top-4 right-4 text-gray-600 hover:text-gray-900 focus:outline-none" id="closeFilterModal">
665+
<i data-lucide="x" class="h-5 w-5"></i>
666+
</button>
667+
<h2 class="text-xl font-medium mb-4">Select Partner Types to Show</h2>
668+
<div class="space-y-3">
669+
<label class="flex items-center gap-2 font-medium">
670+
<input type="checkbox" id="selectAll" class="h-4 w-4 rounded accent-[#2563eb]" ${allChecked} />
671+
Select All
672+
</label>
673+
${checkboxes}
674+
</div>
675+
<div class="mt-6 flex justify-end gap-3">
676+
<button id="resetFilter" class="rounded-full border border-gray-300 px-4 py-2 text-sm hover:bg-gray-50 transition-all duration-300">Reset</button>
677+
<button id="saveFilter" class="rounded-full bg-[#2563eb] hover:bg-[#1d4ed8] px-4 py-2 text-sm text-white shadow-sm transition-all duration-300">Save</button>
678+
</div>
679+
</div>
680+
</div>
681+
`;
682+
}
614683
function renderPartnerTypeSelector() {
615684
let options = '';
616-
PARTNER_TYPES.forEach((t) => {
685+
STATE.selectedPartnerTypes.forEach((t) => {
617686
const display = t === "Registered" ? "Registered (LAR/Referral)" : t;
618687
options += `<option value="${t}" ${STATE.partnerType === t ? 'selected' : ''}>${display}</option>`;
619688
});
@@ -829,9 +898,7 @@ <h4 class="font-medium mb-2">${r.band} - ${r.upTo}</h4>
829898
return html;
830899
}
831900
function renderROEContent() {
832-
// MSP already has its own ROE block; keep that path
833901
if (STATE.partnerType === 'MSP') {
834-
// Add partner/internal toggle even for MSP
835902
return renderROEWithToggle(renderSimpleROE(STATE.partnerType), renderInternalROE());
836903
}
837904
return renderROEWithToggle(renderSimpleROE(STATE.partnerType), renderInternalROE());
@@ -1026,7 +1093,7 @@ <h3 class="text-lg font-semibold p-5 border-b border-[#E2E8F0] flex items-center
10261093
function renderSalesMotionContent() {
10271094
let html = '<h2 class="text-xl font-medium mb-6 flex items-center gap-3"><i data-lucide="table" class="h-6 w-6 stroke-[#2563eb]"></i>Sales Motion</h2>';
10281095
html += '<div class="flex flex-col gap-4 md:flex-row md:items-end md:justify-between mb-4">';
1029-
html += '<div><p class="text-base text-gray-700 leading-relaxed mt-1">See who owns each stage, who supports it, and what moves the deal forward.</p></div>';
1096+
html += '<div><p class="text-base text-gray-700 leading-relaxed mt-1">View the sales cycle matrix showing stages, ownership, support, exit criteria, and deliverables based on the selected band.</p></div>';
10301097
if (STATE.partnerType !== 'Registered') {
10311098
html += '<select id="bandSelect" class="w-[280px] rounded-lg border border-[#E2E8F0] bg-white px-4 py-2.5 text-sm focus:border-[#2563eb] focus:ring-2 focus:ring-[#2563eb] focus:ring-opacity-50">';
10321099
['band1', 'band2', 'band3'].forEach(b => {
@@ -1082,30 +1149,24 @@ <h3 class="text-lg font-semibold p-5 border-b border-[#E2E8F0] flex items-center
10821149
html += '</div>';
10831150
return html;
10841151
}
1085-
function renderOnboardingContent() {
1152+
function renderOnboardingContent(data) {
1153+
let html = '<h2 class="text-xl font-medium mb-6 flex items-center gap-3"><i data-lucide="rocket" class="h-6 w-6 stroke-[#2563eb]"></i>Onboarding Requirements</h2>';
1154+
let certHtml = '<div class="rounded-xl bg-amber-100 border border-amber-200 p-4 mb-6">';
1155+
certHtml += '<h3 class="text-lg font-medium mb-2 flex items-center gap-2"><i data-lucide="award" class="h-5 w-5 stroke-[#d97706]"></i>Required Certifications</h3>';
1156+
let certText;
10861157
if (STATE.partnerType === 'MSP') {
1087-
let html = '<h2 class="text-xl font-medium mb-6 flex items-center gap-3"><i data-lucide="rocket" class="h-6 w-6 stroke-[#2563eb]"></i>Onboarding</h2>';
1088-
html += '<h3 class="text-xl font-medium mb-4">Onboarding Steps:</h3>';
1089-
html += '<ol class="space-y-4 list-decimal pl-6">';
1090-
STATE.msp.onboarding.steps.forEach(s => {
1091-
html += `<li class="text-gray-700 leading-relaxed">${s.replace(/\n/g, '<br>')}</li>`;
1092-
});
1093-
html += '</ol>';
1094-
html += '<h3 class="text-xl font-medium mt-8 mb-4">Resources Provided:</h3>';
1095-
html += '<ul class="space-y-4">';
1096-
STATE.msp.onboarding.resources.forEach(r => {
1097-
html += `
1098-
<li class="flex items-start gap-3">
1099-
<div class="flex-shrink-0 mt-1 bg-[#2563eb] rounded-full p-1">
1100-
<i data-lucide="check" class="h-3 w-3 stroke-white"></i>
1101-
</div>
1102-
<span class="text-gray-700 leading-relaxed">${r}</span>
1103-
</li>
1104-
`;
1105-
});
1106-
html += '</ul>';
1107-
return html;
1158+
certText = 'Initial sales and technical certifications for eligible product lines.';
1159+
} else if (STATE.partnerType === 'Preferred') {
1160+
certText = '1 Certified Sales resource and 1 Certified Technical resource.';
1161+
} else if (STATE.partnerType === 'Premier') {
1162+
certText = 'Certified sales and technical resources (minimum 2 each recommended).';
11081163
} else {
1164+
certText = 'Customized onboarding based on GTM motion; must complete GTM certification.';
1165+
}
1166+
certHtml += `<p class="text-gray-700 leading-relaxed">For ${STATE.partnerType} partners: ${certText} These must be completed during the initial onboarding phase before advancing and accessing full partner benefits, resources, and margin eligibility.</p>`;
1167+
certHtml += '</div>';
1168+
html += certHtml;
1169+
if (data.isStandard) {
11091170
const steps = STATE.model.onboarding.steps;
11101171
let buttonsHtml = '<div class="flex flex-wrap gap-3 mb-6">';
11111172
steps.forEach((s, i) => {
@@ -1134,12 +1195,31 @@ <h3 class="text-lg font-semibold p-5 border-b border-[#E2E8F0] flex items-center
11341195
`;
11351196
});
11361197
listHtml += '</ul>';
1137-
return `
1138-
<h2 class="text-xl font-medium mb-6 flex items-center gap-3"><i data-lucide="rocket" class="h-6 w-6 stroke-[#2563eb]"></i>Onboarding Requirements</h2>
1139-
${buttonsHtml}
1140-
${listHtml}
1141-
`;
1198+
html += buttonsHtml + listHtml;
1199+
} else if (STATE.partnerType === 'MSP') {
1200+
html += '<h3 class="text-xl font-medium mb-4">Onboarding Steps:</h3>';
1201+
html += '<ol class="space-y-4 list-decimal pl-6">';
1202+
STATE.msp.onboarding.steps.forEach(s => {
1203+
html += `<li class="text-gray-700 leading-relaxed">${s.replace(/\n/g, '<br>')}</li>`;
1204+
});
1205+
html += '</ol>';
1206+
html += '<h3 class="text-xl font-medium mt-8 mb-4">Resources Provided:</h3>';
1207+
html += '<ul class="space-y-4">';
1208+
STATE.msp.onboarding.resources.forEach(r => {
1209+
html += `
1210+
<li class="flex items-start gap-3">
1211+
<div class="flex-shrink-0 mt-1 bg-[#2563eb] rounded-full p-1">
1212+
<i data-lucide="check" class="h-3 w-3 stroke-white"></i>
1213+
</div>
1214+
<span class="text-gray-700 leading-relaxed">${r}</span>
1215+
</li>
1216+
`;
1217+
});
1218+
html += '</ul>';
1219+
} else {
1220+
// For OEM, ISV, Distributor - already handled in certHtml
11421221
}
1222+
return html;
11431223
}
11441224
function renderBusinessPlanModal() {
11451225
return `
@@ -1523,10 +1603,81 @@ <h2 class="text-xl font-medium mb-4 flex items-center gap-3"><i data-lucide="upl
15231603
URL.revokeObjectURL(url);
15241604
});
15251605
}
1606+
const filterTrigger = document.getElementById('filterTrigger');
1607+
if (filterTrigger) {
1608+
filterTrigger.addEventListener('change', (e) => {
1609+
STATE.filterModalOpen = e.target.checked;
1610+
render();
1611+
});
1612+
}
1613+
const selectAll = document.getElementById('selectAll');
1614+
if (selectAll) {
1615+
selectAll.addEventListener('change', (e) => {
1616+
if (e.target.checked) {
1617+
STATE.selectedPartnerTypes = PARTNER_TYPES.slice();
1618+
} else {
1619+
STATE.selectedPartnerTypes = [];
1620+
}
1621+
render();
1622+
});
1623+
}
1624+
document.querySelectorAll('.partner-type-checkbox').forEach(cb => {
1625+
cb.addEventListener('change', (e) => {
1626+
const type = e.target.dataset.type;
1627+
if (e.target.checked) {
1628+
if (!STATE.selectedPartnerTypes.includes(type)) {
1629+
STATE.selectedPartnerTypes.push(type);
1630+
}
1631+
} else {
1632+
STATE.selectedPartnerTypes = STATE.selectedPartnerTypes.filter(t => t !== type);
1633+
}
1634+
render();
1635+
});
1636+
});
1637+
const saveFilter = document.getElementById('saveFilter');
1638+
if (saveFilter) {
1639+
saveFilter.addEventListener('click', () => {
1640+
if (STATE.selectedPartnerTypes.length === 0) {
1641+
STATE.selectedPartnerTypes = PARTNER_TYPES.slice();
1642+
}
1643+
if (typeof localStorage !== 'undefined') {
1644+
localStorage.setItem('recastPartnerTypeFilter', JSON.stringify({ selectedPartnerTypes: STATE.selectedPartnerTypes }));
1645+
}
1646+
STATE.filterModalOpen = false;
1647+
render();
1648+
});
1649+
}
1650+
const resetFilter = document.getElementById('resetFilter');
1651+
if (resetFilter) {
1652+
resetFilter.addEventListener('click', () => {
1653+
STATE.selectedPartnerTypes = PARTNER_TYPES.slice();
1654+
if (typeof localStorage !== 'undefined') {
1655+
localStorage.setItem('recastPartnerTypeFilter', JSON.stringify({ selectedPartnerTypes: STATE.selectedPartnerTypes }));
1656+
}
1657+
STATE.filterModalOpen = false;
1658+
render();
1659+
});
1660+
}
1661+
const closeFilterModal = document.getElementById('closeFilterModal');
1662+
if (closeFilterModal) {
1663+
closeFilterModal.addEventListener('click', () => {
1664+
STATE.filterModalOpen = false;
1665+
render();
1666+
});
1667+
}
1668+
const filterModalBg = document.getElementById('filterModalBg');
1669+
if (filterModalBg) {
1670+
filterModalBg.addEventListener('click', (e) => {
1671+
if (e.target === filterModalBg) {
1672+
STATE.filterModalOpen = false;
1673+
render();
1674+
}
1675+
});
1676+
}
15261677
const modals = document.querySelectorAll('#businessPlanModal, #partnerEventsModal, #evaluationModal, #csvModal');
1527-
modals.forEach(modal => {
1528-
modal.addEventListener('click', (e) => {
1529-
if (e.target === modal) {
1678+
modals.forEach(m => {
1679+
m.addEventListener('click', (e) => {
1680+
if (e.target === m) {
15301681
STATE.showBusinessPlanModal = false;
15311682
STATE.showPartnerEventsModal = false;
15321683
STATE.showEvaluationModal = false;
@@ -1536,16 +1687,20 @@ <h2 class="text-xl font-medium mb-4 flex items-center gap-3"><i data-lucide="upl
15361687
});
15371688
});
15381689
document.addEventListener('keydown', (e) => {
1539-
if (e.key === 'Escape' && (STATE.showBusinessPlanModal || STATE.showPartnerEventsModal || STATE.showEvaluationModal || STATE.showCsvModal)) {
1690+
if (e.key === 'Escape' && (STATE.showBusinessPlanModal || STATE.showPartnerEventsModal || STATE.showEvaluationModal || STATE.showCsvModal || STATE.filterModalOpen)) {
15401691
STATE.showBusinessPlanModal = false;
15411692
STATE.showPartnerEventsModal = false;
15421693
STATE.showEvaluationModal = false;
15431694
STATE.showCsvModal = false;
1695+
STATE.filterModalOpen = false;
15441696
render();
15451697
}
15461698
});
15471699
}
1548-
document.addEventListener('DOMContentLoaded', render);
1700+
document.addEventListener('DOMContentLoaded', () => {
1701+
initFilter();
1702+
render();
1703+
});
15491704
</script>
15501705
</body>
15511706
</html>

0 commit comments

Comments
 (0)