fix: Sync avatar to account sidebar
- Fetch avatar settings in AccountLayout on mount - Display custom avatar or gravatar in sidebar - Dispatch woonoow:avatar-updated event on upload/remove - Listen for event in AccountLayout for real-time sync
This commit is contained in:
@@ -90,6 +90,9 @@ export default function AccountDetails() {
|
|||||||
current_avatar: result.avatar_url,
|
current_avatar: result.avatar_url,
|
||||||
} : null);
|
} : null);
|
||||||
|
|
||||||
|
// Dispatch event to sync sidebar avatar
|
||||||
|
window.dispatchEvent(new CustomEvent('woonoow:avatar-updated', { detail: { avatar_url: result.avatar_url } }));
|
||||||
|
|
||||||
toast.success('Avatar uploaded successfully');
|
toast.success('Avatar uploaded successfully');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Upload avatar error:', error);
|
console.error('Upload avatar error:', error);
|
||||||
@@ -115,6 +118,10 @@ export default function AccountDetails() {
|
|||||||
...prev,
|
...prev,
|
||||||
current_avatar: null,
|
current_avatar: null,
|
||||||
} : null);
|
} : null);
|
||||||
|
|
||||||
|
// Dispatch event to sync sidebar avatar (will fall back to gravatar)
|
||||||
|
window.dispatchEvent(new CustomEvent('woonoow:avatar-updated', { detail: { avatar_url: null } }));
|
||||||
|
|
||||||
toast.success('Avatar removed');
|
toast.success('Avatar removed');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Remove avatar error:', error);
|
console.error('Remove avatar error:', error);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import React, { ReactNode, useState } from 'react';
|
import React, { ReactNode, useState, useEffect } from 'react';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
import { LayoutDashboard, ShoppingBag, Download, MapPin, Heart, User, LogOut } from 'lucide-react';
|
import { LayoutDashboard, ShoppingBag, Download, MapPin, Heart, User, LogOut } from 'lucide-react';
|
||||||
import { useModules } from '@/hooks/useModules';
|
import { useModules } from '@/hooks/useModules';
|
||||||
|
import { api } from '@/lib/api/client';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
@@ -24,6 +25,27 @@ export function AccountLayout({ children }: AccountLayoutProps) {
|
|||||||
const { isEnabled } = useModules();
|
const { isEnabled } = useModules();
|
||||||
const wishlistEnabled = (window as any).woonoowCustomer?.settings?.wishlist_enabled !== false;
|
const wishlistEnabled = (window as any).woonoowCustomer?.settings?.wishlist_enabled !== false;
|
||||||
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
||||||
|
const [avatarUrl, setAvatarUrl] = useState<string | null>(null);
|
||||||
|
|
||||||
|
// Fetch avatar settings
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchAvatar = async () => {
|
||||||
|
try {
|
||||||
|
const data = await api.get<{ current_avatar: string | null; gravatar_url: string }>('/account/avatar-settings');
|
||||||
|
setAvatarUrl(data.current_avatar || data.gravatar_url);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch avatar:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchAvatar();
|
||||||
|
|
||||||
|
// Listen for avatar updates
|
||||||
|
const handleAvatarUpdate = (e: CustomEvent) => {
|
||||||
|
setAvatarUrl(e.detail?.avatar_url || null);
|
||||||
|
};
|
||||||
|
window.addEventListener('woonoow:avatar-updated' as any, handleAvatarUpdate);
|
||||||
|
return () => window.removeEventListener('woonoow:avatar-updated' as any, handleAvatarUpdate);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const allMenuItems = [
|
const allMenuItems = [
|
||||||
{ id: 'dashboard', label: 'Dashboard', path: '/my-account', icon: LayoutDashboard },
|
{ id: 'dashboard', label: 'Dashboard', path: '/my-account', icon: LayoutDashboard },
|
||||||
@@ -106,9 +128,17 @@ export function AccountLayout({ children }: AccountLayoutProps) {
|
|||||||
<aside className="bg-white rounded-lg border p-4">
|
<aside className="bg-white rounded-lg border p-4">
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<div className="flex items-center gap-3 pb-4 border-b">
|
<div className="flex items-center gap-3 pb-4 border-b">
|
||||||
<div className="w-12 h-12 rounded-full bg-gray-200 flex items-center justify-center">
|
{avatarUrl ? (
|
||||||
<User className="w-6 h-6 text-gray-600" />
|
<img
|
||||||
</div>
|
src={avatarUrl}
|
||||||
|
alt={user?.display_name || 'User'}
|
||||||
|
className="w-12 h-12 rounded-full object-cover"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="w-12 h-12 rounded-full bg-gray-200 flex items-center justify-center">
|
||||||
|
<User className="w-6 h-6 text-gray-600" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div>
|
<div>
|
||||||
<p className="font-semibold">{user?.display_name || 'User'}</p>
|
<p className="font-semibold">{user?.display_name || 'User'}</p>
|
||||||
<p className="text-sm text-gray-500">{user?.email}</p>
|
<p className="text-sm text-gray-500">{user?.email}</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user