5.8 KiB
5.8 KiB
New Client Detail Page - Modern Design
Overview
A completely redesigned client detail page with modern UI/UX, inspired by the Settings page structure with tabs, client avatar/logo, and better ergonomics.
Features
🎨 Modern Layout
- Left Sidebar: Sticky client card with navigation
- Right Content Area: Tabbed content with clean organization
👤 Client Profile Card
- Avatar/Logo:
- Shows client initials if no image
- Click edit button to upload logo
- Large, prominent display
- Quick Stats:
- Number of contacts
- Active/Inactive status
- Client Info: Name and type
📑 5 Tab Sections
1. Aperçu (Overview)
Default view with key information:
- Contact info card (email, phone)
- Business info card (SIRET, VAT)
- Address card
- Recent contacts (first 3)
- Edit button to modify client
2. Informations (Information)
Complete client details:
- Name, type
- SIRET, VAT number
- Email, phone
- Commercial
3. Contacts
Full contact list with:
- Contact table with avatars
- Email, phone, position
- Primary contact badge
- "Add Contact" button
- Empty state if no contacts
4. Adresse (Address)
Billing address details:
- Address line 1 & 2
- Postal code, city, country
5. Notes
Client notes section
File Location
src/views/pages/CRM/ClientDetailNew.vue
Usage
Update Router
Add the new route in your router configuration:
// router/index.js
{
path: '/clients/:id/detail',
name: 'ClientDetailNew',
component: () => import('@/views/pages/CRM/ClientDetailNew.vue')
}
Replace Old ClientDetail
To use this as the main client detail page:
// Change existing route
{
path: '/clients/:id',
name: 'ClientDetail',
component: () => import('@/views/pages/CRM/ClientDetailNew.vue') // Changed from ClientDetails.vue
}
Component Structure
Template Sections
- Header - Back button to clients list
- Loading State - Spinner while fetching data
- Error State - Alert for errors
- Main Content
- Left: Client card + navigation
- Right: Tab content
Script Features
// Reactive data
const activeTab = ref('overview') // Current tab
const clientAvatar = ref(null) // Client logo/avatar
const contacts_client = ref([]) // Client contacts
// Methods
getInitials(name) // Generate initials from name
formatAddress(client) // Format full address string
triggerFileInput() // Open file selector
handleAvatarUpload() // Handle logo upload
Styling Features
- Sticky sidebar - Stays visible when scrolling
- Active tab highlighting - Gradient background
- Smooth transitions - Hover effects
- Responsive design - Works on mobile
- Clean cards - Soft shadows and borders
Design Principles
Color Scheme
- Primary Actions: Gradient purple-pink (
#7928cato#ff0080) - Success: Green for active status and badges
- Info: Blue for contact info
- Warning: Yellow for business info
- Danger: Red for inactive status
Typography
- Headers: Bold, clear hierarchy
- Body:
text-smfor readability - Labels: Uppercase with spacing
Icons
Using Font Awesome:
- 📊
fa-eye- Overview - ℹ️
fa-info-circle- Information - 👥
fa-users- Contacts - 📍
fa-map-marker-alt- Address - 📝
fa-sticky-note- Notes
Avatar/Logo Upload
Current Implementation
handleAvatarUpload(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
clientAvatar.value = e.target.result;
// TODO: Upload to server
};
reader.readAsDataURL(file);
}
}
TODO: Connect to Backend
To implement server upload:
const handleAvatarUpload = async (event) => {
const file = event.target.files[0];
if (!file) return;
const formData = new FormData();
formData.append('avatar', file);
formData.append('client_id', clientStore.currentClient.id);
try {
const response = await api.post('/clients/upload-avatar', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
clientAvatar.value = response.data.avatar_url;
// Update store
await clientStore.fetchClient(client_id);
} catch (error) {
console.error('Upload failed:', error);
}
};
Comparison: Old vs New
Old Design
- Single page layout
- All info visible at once
- No image/avatar support
- Basic styling
- No tab organization
New Design ✨
- Modern tabbed interface
- Client avatar/logo with upload
- Sticky sidebar navigation
- Card-based organization
- Better mobile responsive
- Visual hierarchy
- Quick stats
- Empty states
- Badge indicators
Customization
Change Tab Order
<!-- Reorder nav items in the sidebar -->
<ul class="nav nav-pills flex-column">
<li class="nav-item">
<a @click="activeTab = 'your-tab'">...</a>
</li>
</ul>
Add New Tab
- Add nav item in sidebar
- Add content section with
v-show - Update
activeTabref
<!-- Nav item -->
<li class="nav-item pt-2">
<a
class="nav-link"
:class="{ active: activeTab === 'documents' }"
@click="activeTab = 'documents'"
>
<i class="fas fa-file me-2"></i>
<span class="text-sm">Documents</span>
</a>
</li>
<!-- Content -->
<div v-show="activeTab === 'documents'" class="card">
<div class="card-header pb-0">
<h6 class="mb-0">Documents</h6>
</div>
<div class="card-body">
<!-- Your content -->
</div>
</div>
Dependencies
- Vue 3 Composition API
- Vue Router
- Pinia stores (clientStore, contactStore)
- Font Awesome icons
- Bootstrap 5 classes
Browser Support
- Chrome, Firefox, Safari (latest)
- Edge (latest)
- Mobile browsers
Status: ✅ Ready to use
Created: October 20, 2025
File: src/views/pages/CRM/ClientDetailNew.vue