Adds comprehensive customer detail view components
Implements full customer detail page with multiple feature-rich components including overview, economy, statistics, journal, appointments, giftcards, and activity sections Creates reusable ViewComponents for different customer detail aspects with robust data modeling and presentation logic
This commit is contained in:
parent
38e9243bcd
commit
1b25978d9b
26 changed files with 3792 additions and 956 deletions
|
|
@ -4,9 +4,11 @@
|
|||
* Handles:
|
||||
* - Fuzzy search with Fuse.js
|
||||
* - Customer drawer population
|
||||
* - Customer detail economy chart
|
||||
*/
|
||||
|
||||
import Fuse from 'fuse.js';
|
||||
import { createChart } from '@sevenweirdpeople/swp-charting';
|
||||
|
||||
interface CustomerItem {
|
||||
name: string;
|
||||
|
|
@ -233,3 +235,94 @@ export class CustomersController {
|
|||
return tag.charAt(0).toUpperCase() + tag.slice(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Customer Economy Controller
|
||||
*
|
||||
* Handles the economy chart on customer detail page.
|
||||
* Initializes chart lazily when economy tab is shown.
|
||||
*/
|
||||
interface ChartDataPoint {
|
||||
x: string;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface ChartSeries {
|
||||
name: string;
|
||||
color: string;
|
||||
data: ChartDataPoint[];
|
||||
}
|
||||
|
||||
interface CustomerChartData {
|
||||
categories: string[];
|
||||
series: ChartSeries[];
|
||||
}
|
||||
|
||||
class CustomerEconomyController {
|
||||
private chartInitialized = false;
|
||||
private chart: ReturnType<typeof createChart> | null = null;
|
||||
|
||||
constructor() {
|
||||
this.setupTabListener();
|
||||
// Check if economy tab is already active on page load
|
||||
this.checkInitialTab();
|
||||
}
|
||||
|
||||
private setupTabListener(): void {
|
||||
document.addEventListener('click', (e: Event) => {
|
||||
const target = e.target as HTMLElement;
|
||||
const tab = target.closest<HTMLElement>('swp-tab[data-tab="economy"]');
|
||||
|
||||
if (tab) {
|
||||
// Small delay to let tab content become visible
|
||||
setTimeout(() => this.initializeChart(), 50);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private checkInitialTab(): void {
|
||||
const activeTab = document.querySelector('swp-tab[data-tab="economy"].active');
|
||||
if (activeTab) {
|
||||
this.initializeChart();
|
||||
}
|
||||
}
|
||||
|
||||
private initializeChart(): void {
|
||||
if (this.chartInitialized) return;
|
||||
|
||||
const container = document.getElementById('customerRevenueChart');
|
||||
if (!container) return;
|
||||
|
||||
const dataScript = document.getElementById('customerRevenueChartData');
|
||||
if (!dataScript) return;
|
||||
|
||||
try {
|
||||
const data = JSON.parse(dataScript.textContent || '') as CustomerChartData;
|
||||
this.createRevenueChart(container, data);
|
||||
this.chartInitialized = true;
|
||||
} catch (err) {
|
||||
console.error('Failed to parse chart data:', err);
|
||||
}
|
||||
}
|
||||
|
||||
private createRevenueChart(container: HTMLElement, data: CustomerChartData): void {
|
||||
this.chart = createChart(container, {
|
||||
deferRender: true,
|
||||
height: 200,
|
||||
xAxis: {
|
||||
categories: data.categories
|
||||
},
|
||||
series: data.series.map(s => ({
|
||||
name: s.name,
|
||||
color: s.color,
|
||||
data: s.data
|
||||
})),
|
||||
legend: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize economy controller if on customer detail page
|
||||
if (document.getElementById('customerRevenueChart') || document.querySelector('swp-tab[data-tab="economy"]')) {
|
||||
new CustomerEconomyController();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue