182 lines
4.4 KiB
Markdown
182 lines
4.4 KiB
Markdown
# ContactTable Component - Complete Redesign
|
|
|
|
## Overview
|
|
The ContactTable has been completely rewritten to match the ClientTable structure with improved features, loading states, and action buttons.
|
|
|
|
## New Features Added
|
|
|
|
### 1. **Loading State with Skeleton Screen**
|
|
- Shows animated skeleton rows while data is loading
|
|
- Loading spinner in top-right corner
|
|
- Smooth pulse animation for better UX
|
|
|
|
### 2. **Complete Data Display**
|
|
Columns now show:
|
|
- **Contact Name** - With avatar and full name
|
|
- **Client** - Shows associated client name (or "-" if none)
|
|
- **Email** - Contact email address
|
|
- **Phone / Mobile** - Both phone numbers with icons
|
|
- **Position** - Job title/position
|
|
- **Status** - Shows star badge if primary contact
|
|
- **Actions** - View, Edit, Delete buttons
|
|
|
|
### 3. **Action Buttons**
|
|
Three action buttons per contact:
|
|
- **View** (Info/Blue) - View contact details
|
|
- **Edit** (Warning/Yellow) - Edit contact information
|
|
- **Delete** (Danger/Red) - Delete contact
|
|
|
|
### 4. **Empty State**
|
|
Shows a friendly message when no contacts exist:
|
|
- Address book icon
|
|
- "Aucun contact trouvé" message
|
|
- Helpful text
|
|
|
|
### 5. **DataTable Integration**
|
|
- Searchable table
|
|
- Pagination (5, 10, 15, 20 per page)
|
|
- Fixed height scrolling
|
|
- Automatic reinitialization on data changes
|
|
|
|
### 6. **Event Emissions**
|
|
The component now emits three events:
|
|
```javascript
|
|
emit("view", contactId) // When view button clicked
|
|
emit("edit", contactId) // When edit button clicked
|
|
emit("delete", contactId) // When delete button clicked
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Basic Usage
|
|
```vue
|
|
<ContactTable
|
|
:data="contacts"
|
|
:loading="isLoading"
|
|
:skeletonRows="5"
|
|
@view="handleViewContact"
|
|
@edit="handleEditContact"
|
|
@delete="handleDeleteContact"
|
|
/>
|
|
```
|
|
|
|
### Props
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `data` | Array | `[]` | Array of contact objects |
|
|
| `loading` | Boolean | `false` | Shows loading skeleton |
|
|
| `skeletonRows` | Number | `5` | Number of skeleton rows to show |
|
|
|
|
### Events
|
|
|
|
| Event | Payload | Description |
|
|
|-------|---------|-------------|
|
|
| `@view` | `contactId` | Emitted when view button is clicked |
|
|
| `@edit` | `contactId` | Emitted when edit button is clicked |
|
|
| `@delete` | `contactId` | Emitted when delete button is clicked |
|
|
|
|
### Expected Data Structure
|
|
|
|
```javascript
|
|
const contacts = [
|
|
{
|
|
id: 1,
|
|
first_name: "John",
|
|
last_name: "Doe",
|
|
full_name: "John Doe", // Computed in backend
|
|
email: "john@example.com",
|
|
phone: "+33 1 23 45 67 89",
|
|
mobile: "+33 6 12 34 56 78",
|
|
position: "Sales Manager",
|
|
is_primary: true,
|
|
client: {
|
|
id: 5,
|
|
name: "Acme Corporation"
|
|
}
|
|
},
|
|
// ...
|
|
]
|
|
```
|
|
|
|
## Parent Component Example
|
|
|
|
```vue
|
|
<script setup>
|
|
import { ref } from 'vue';
|
|
import ContactTable from '@/components/molecules/Tables/ContactTable.vue';
|
|
import { contactApi } from '@/api/contacts';
|
|
|
|
const contacts = ref([]);
|
|
const loading = ref(false);
|
|
|
|
const loadContacts = async () => {
|
|
loading.value = true;
|
|
try {
|
|
const response = await contactApi.getAll();
|
|
contacts.value = response.data;
|
|
} catch (error) {
|
|
console.error('Error loading contacts:', error);
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
const handleViewContact = (contactId) => {
|
|
router.push(`/contacts/${contactId}`);
|
|
};
|
|
|
|
const handleEditContact = (contactId) => {
|
|
router.push(`/contacts/${contactId}/edit`);
|
|
};
|
|
|
|
const handleDeleteContact = async (contactId) => {
|
|
if (confirm('Delete this contact?')) {
|
|
try {
|
|
await contactApi.delete(contactId);
|
|
await loadContacts(); // Reload list
|
|
} catch (error) {
|
|
console.error('Error deleting contact:', error);
|
|
}
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
loadContacts();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<ContactTable
|
|
:data="contacts"
|
|
:loading="loading"
|
|
@view="handleViewContact"
|
|
@edit="handleEditContact"
|
|
@delete="handleDeleteContact"
|
|
/>
|
|
</template>
|
|
```
|
|
|
|
## Styling Features
|
|
|
|
- **Responsive design** - Adapts to mobile screens
|
|
- **Skeleton animations** - Shimmer and pulse effects
|
|
- **Icon badges** - For status indicators
|
|
- **Avatar images** - Random avatars for visual appeal
|
|
- **Consistent spacing** - Matches ClientTable design
|
|
|
|
## Dependencies
|
|
|
|
- `simple-datatables` - For table pagination and search
|
|
- `SoftButton` - Custom button component
|
|
- `SoftAvatar` - Avatar component
|
|
- Font Awesome icons
|
|
|
|
## File Modified
|
|
- `src/components/molecules/Tables/ContactTable.vue`
|
|
|
|
---
|
|
|
|
**Status**: ✅ Complete
|
|
**Date**: October 16, 2025
|