fix feat req
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600&family=Inter:wght@400;600&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600&family=Inter:wght@400;600&display=swap"
|
||||||
rel="stylesheet">
|
rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" />
|
||||||
<link rel="stylesheet" href="/chat/styles.css">
|
<link rel="stylesheet" href="/chat/styles.css">
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
@@ -452,6 +453,68 @@
|
|||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-menu-container {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu-popup {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 8px);
|
||||||
|
right: 0;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 1000;
|
||||||
|
min-width: 180px;
|
||||||
|
display: none;
|
||||||
|
padding: 6px;
|
||||||
|
animation: menuFadeIn 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes menuFadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu-popup.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #495057;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu-item:hover {
|
||||||
|
background: #f8f9fa;
|
||||||
|
color: var(--shopify-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu-item svg {
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu-item:hover svg {
|
||||||
|
color: var(--shopify-green);
|
||||||
|
}
|
||||||
|
|
||||||
.user-chip-avatar {
|
.user-chip-avatar {
|
||||||
width: 34px;
|
width: 34px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
@@ -466,6 +529,56 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-chip-status {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #6c757d;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-chip-email {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1a1a1a;
|
||||||
|
max-width: 160px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px 18px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--border, #e6e9ee);
|
||||||
|
background: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
color: #1e293b;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
background: #f8fafc;
|
||||||
|
border-color: #cbd5e1;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.ghost {
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.ghost:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.04);
|
||||||
|
border-color: rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -521,10 +634,56 @@
|
|||||||
<span class="brand-text">Plugin Compass</span>
|
<span class="brand-text">Plugin Compass</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
<a href="/apps" class="nav-link">My Apps</a>
|
<a class="btn ghost" href="/apps" style="margin-right: 12px;"><i class="fa-solid fa-grid-2"></i>Apps</a>
|
||||||
<a href="/settings" class="nav-link">Settings</a>
|
<div class="user-menu-container" id="user-menu-container">
|
||||||
<div id="nav-auth-section">
|
<div class="user-chip" id="fr-user-chip" title="Account & settings">
|
||||||
<!-- This will be populated by JavaScript based on auth state -->
|
<div class="user-chip-avatar" id="fr-user-avatar">?</div>
|
||||||
|
<div style="display:flex; flex-direction:column; gap:2px; min-width:0;">
|
||||||
|
<span class="user-chip-status">Signed in</span>
|
||||||
|
<span class="user-chip-email" id="fr-user-email">Checking account…</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-menu-popup" id="user-menu-popup">
|
||||||
|
<a href="/apps" class="user-menu-item">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<rect x="3" y="3" width="7" height="7"></rect>
|
||||||
|
<rect x="14" y="3" width="7" height="7"></rect>
|
||||||
|
<rect x="14" y="14" width="7" height="7"></rect>
|
||||||
|
<rect x="3" y="14" width="7" height="7"></rect>
|
||||||
|
</svg>
|
||||||
|
My Apps
|
||||||
|
</a>
|
||||||
|
<a href="/feature-requests" class="user-menu-item">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
|
||||||
|
</svg>
|
||||||
|
Feature Requests
|
||||||
|
</a>
|
||||||
|
<a href="/topup" class="user-menu-item">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="10"></circle>
|
||||||
|
<path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"></path>
|
||||||
|
<path d="M12 18V6"></path>
|
||||||
|
</svg>
|
||||||
|
Tokens Top-up
|
||||||
|
</a>
|
||||||
|
<div style="margin: 4px 0; border-top: 1px solid #f1f3f5;"></div>
|
||||||
|
<a href="#" class="user-menu-item" id="logout-link">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
|
||||||
|
<polyline points="16 17 21 12 16 7"></polyline>
|
||||||
|
<line x1="21" y1="12" x2="9" y2="12"></line>
|
||||||
|
</svg>
|
||||||
|
Logout
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="nav-auth-section" style="display: none;">
|
||||||
|
<!-- This will be populated by JavaScript for unauthenticated users -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -685,17 +844,17 @@
|
|||||||
|
|
||||||
function updateNavigation() {
|
function updateNavigation() {
|
||||||
const navAuthSection = document.getElementById('nav-auth-section');
|
const navAuthSection = document.getElementById('nav-auth-section');
|
||||||
|
const userMenuContainer = document.getElementById('user-menu-container');
|
||||||
|
|
||||||
if (!state.userId) {
|
if (!state.userId) {
|
||||||
// Unauthenticated state - show sign in link
|
// Unauthenticated state - show sign in link, hide user menu
|
||||||
|
userMenuContainer.style.display = 'none';
|
||||||
|
navAuthSection.style.display = 'block';
|
||||||
navAuthSection.innerHTML = '<a href="/login?next=%2Ffeature-requests" class="nav-link" style="background: var(--shopify-green); color: white; padding: 8px 16px; border-radius: 8px; text-decoration: none;">Sign In</a>';
|
navAuthSection.innerHTML = '<a href="/login?next=%2Ffeature-requests" class="nav-link" style="background: var(--shopify-green); color: white; padding: 8px 16px; border-radius: 8px; text-decoration: none;">Sign In</a>';
|
||||||
} else {
|
} else {
|
||||||
// Authenticated state - show user chip
|
// Authenticated state - show user menu, hide sign in
|
||||||
navAuthSection.innerHTML = `
|
userMenuContainer.style.display = 'inline-block';
|
||||||
<div class="user-chip" id="fr-user-chip" title="Account & settings">
|
navAuthSection.style.display = 'none';
|
||||||
<div class="user-chip-avatar" id="fr-user-avatar">${getUserInitials()}</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -958,6 +1117,62 @@
|
|||||||
|
|
||||||
// Initial load
|
// Initial load
|
||||||
loadFeatureRequests();
|
loadFeatureRequests();
|
||||||
|
|
||||||
|
// User menu functionality
|
||||||
|
const userChip = document.getElementById('fr-user-chip');
|
||||||
|
const userChipEmail = document.getElementById('fr-user-email');
|
||||||
|
const userChipAvatar = document.getElementById('fr-user-avatar');
|
||||||
|
const userMenuPopup = document.getElementById('user-menu-popup');
|
||||||
|
const logoutLink = document.getElementById('logout-link');
|
||||||
|
|
||||||
|
if (userChip && userMenuPopup) {
|
||||||
|
userChip.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
userMenuPopup.classList.toggle('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (!userMenuPopup.contains(e.target) && !userChip.contains(e.target)) {
|
||||||
|
userMenuPopup.classList.remove('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logoutLink) {
|
||||||
|
logoutLink.addEventListener('click', async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/logout', { method: 'POST' });
|
||||||
|
if (response.ok) {
|
||||||
|
localStorage.removeItem('shopify_ai_user');
|
||||||
|
localStorage.removeItem('wordpress_plugin_ai_user');
|
||||||
|
localStorage.removeItem('plugin_compass_onboarding_completed');
|
||||||
|
window.location.href = '/login';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Logout failed:', err);
|
||||||
|
window.location.href = '/login';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load user data for the header
|
||||||
|
async function loadFeatureRequestsUserChip() {
|
||||||
|
try {
|
||||||
|
const resp = await fetch('/api/account', { credentials: 'same-origin' });
|
||||||
|
if (resp.ok) {
|
||||||
|
const data = await resp.json().catch(() => ({}));
|
||||||
|
const email = data?.account?.email || '';
|
||||||
|
if (userChipEmail) userChipEmail.textContent = email || 'Guest';
|
||||||
|
if (userChipAvatar) userChipAvatar.textContent = email ? email.charAt(0).toUpperCase() : '?';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to load user data:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize user data
|
||||||
|
loadFeatureRequestsUserChip();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user