chart bug fix
This commit is contained in:
parent
b69b4c8be2
commit
a052266950
|
|
@ -375,7 +375,57 @@ new class extends Component
|
||||||
@else
|
@else
|
||||||
<div
|
<div
|
||||||
wire:ignore
|
wire:ignore
|
||||||
x-data="trendsChart($wire.chartData)"
|
x-data="{
|
||||||
|
chart: null,
|
||||||
|
data: @js($chartData),
|
||||||
|
init() {
|
||||||
|
if (typeof Chart === 'undefined') return;
|
||||||
|
this.chart = new Chart(this.$refs.canvas, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: this.data.labels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: @js(__('admin_metrics.new_clients')),
|
||||||
|
data: this.data.newClients,
|
||||||
|
borderColor: '#D4AF37',
|
||||||
|
backgroundColor: 'rgba(212, 175, 55, 0.1)',
|
||||||
|
tension: 0.3,
|
||||||
|
fill: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: @js(__('admin_metrics.consultations')),
|
||||||
|
data: this.data.consultations,
|
||||||
|
borderColor: '#0A1F44',
|
||||||
|
backgroundColor: 'rgba(10, 31, 68, 0.1)',
|
||||||
|
tension: 0.3,
|
||||||
|
fill: false,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: {
|
||||||
|
tooltip: { enabled: true },
|
||||||
|
legend: {
|
||||||
|
position: 'bottom',
|
||||||
|
rtl: document.dir === 'rtl',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true,
|
||||||
|
ticks: { precision: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
destroy() {
|
||||||
|
if (this.chart) this.chart.destroy();
|
||||||
|
}
|
||||||
|
}"
|
||||||
class="h-64"
|
class="h-64"
|
||||||
>
|
>
|
||||||
<canvas x-ref="canvas"></canvas>
|
<canvas x-ref="canvas"></canvas>
|
||||||
|
|
@ -393,7 +443,50 @@ new class extends Component
|
||||||
@else
|
@else
|
||||||
<div
|
<div
|
||||||
wire:ignore
|
wire:ignore
|
||||||
x-data="breakdownChart($wire.chartData.consultationBreakdown)"
|
x-data="{
|
||||||
|
chart: null,
|
||||||
|
data: @js($chartData['consultationBreakdown']),
|
||||||
|
init() {
|
||||||
|
if (typeof Chart === 'undefined') return;
|
||||||
|
const total = this.data.free + this.data.paid;
|
||||||
|
this.chart = new Chart(this.$refs.canvas, {
|
||||||
|
type: 'doughnut',
|
||||||
|
data: {
|
||||||
|
labels: [
|
||||||
|
@js(__('admin_metrics.free')) + ` (${this.data.free})`,
|
||||||
|
@js(__('admin_metrics.paid')) + ` (${this.data.paid})`
|
||||||
|
],
|
||||||
|
datasets: [{
|
||||||
|
data: [this.data.free, this.data.paid],
|
||||||
|
backgroundColor: ['#D4AF37', '#0A1F44'],
|
||||||
|
borderWidth: 0,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: {
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: function(context) {
|
||||||
|
const value = context.parsed;
|
||||||
|
const percent = total > 0 ? Math.round((value / total) * 100) : 0;
|
||||||
|
return `${context.label}: ${percent}%`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
position: 'bottom',
|
||||||
|
rtl: document.dir === 'rtl',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
destroy() {
|
||||||
|
if (this.chart) this.chart.destroy();
|
||||||
|
}
|
||||||
|
}"
|
||||||
class="h-64"
|
class="h-64"
|
||||||
>
|
>
|
||||||
<canvas x-ref="canvas"></canvas>
|
<canvas x-ref="canvas"></canvas>
|
||||||
|
|
@ -411,7 +504,75 @@ new class extends Component
|
||||||
@else
|
@else
|
||||||
<div
|
<div
|
||||||
wire:ignore
|
wire:ignore
|
||||||
x-data="noShowChart($wire.chartData)"
|
x-data="{
|
||||||
|
chart: null,
|
||||||
|
data: @js($chartData),
|
||||||
|
init() {
|
||||||
|
if (typeof Chart === 'undefined') return;
|
||||||
|
this.chart = new Chart(this.$refs.canvas, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: this.data.labels,
|
||||||
|
datasets: [{
|
||||||
|
label: @js(__('admin_metrics.noshow_rate_percent')),
|
||||||
|
data: this.data.noShowRates,
|
||||||
|
borderColor: '#E74C3C',
|
||||||
|
backgroundColor: 'rgba(231, 76, 60, 0.1)',
|
||||||
|
fill: true,
|
||||||
|
tension: 0.3,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: {
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: function(context) {
|
||||||
|
return context.parsed.y + '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
position: 'bottom',
|
||||||
|
rtl: document.dir === 'rtl',
|
||||||
|
},
|
||||||
|
annotation: {
|
||||||
|
annotations: {
|
||||||
|
threshold: {
|
||||||
|
type: 'line',
|
||||||
|
yMin: 20,
|
||||||
|
yMax: 20,
|
||||||
|
borderColor: 'rgba(231, 76, 60, 0.5)',
|
||||||
|
borderWidth: 2,
|
||||||
|
borderDash: [5, 5],
|
||||||
|
label: {
|
||||||
|
display: true,
|
||||||
|
content: @js(__('admin_metrics.concerning_threshold')),
|
||||||
|
position: 'end'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
ticks: {
|
||||||
|
callback: function(value) {
|
||||||
|
return value + '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
destroy() {
|
||||||
|
if (this.chart) this.chart.destroy();
|
||||||
|
}
|
||||||
|
}"
|
||||||
class="h-64"
|
class="h-64"
|
||||||
>
|
>
|
||||||
<canvas x-ref="canvas"></canvas>
|
<canvas x-ref="canvas"></canvas>
|
||||||
|
|
@ -448,188 +609,4 @@ new class extends Component
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@script
|
|
||||||
<script>
|
|
||||||
// Ensure Chart.js is available
|
|
||||||
if (typeof Chart === 'undefined') {
|
|
||||||
console.error('Chart.js is not loaded');
|
|
||||||
}
|
|
||||||
|
|
||||||
Alpine.data('trendsChart', (data) => ({
|
|
||||||
chart: null,
|
|
||||||
init() {
|
|
||||||
if (typeof Chart === 'undefined') return;
|
|
||||||
|
|
||||||
this.chart = new Chart(this.$refs.canvas, {
|
|
||||||
type: 'line',
|
|
||||||
data: {
|
|
||||||
labels: data.labels,
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: @js(__('admin_metrics.new_clients')),
|
|
||||||
data: data.newClients,
|
|
||||||
borderColor: '#D4AF37',
|
|
||||||
backgroundColor: 'rgba(212, 175, 55, 0.1)',
|
|
||||||
tension: 0.3,
|
|
||||||
fill: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: @js(__('admin_metrics.consultations')),
|
|
||||||
data: data.consultations,
|
|
||||||
borderColor: '#0A1F44',
|
|
||||||
backgroundColor: 'rgba(10, 31, 68, 0.1)',
|
|
||||||
tension: 0.3,
|
|
||||||
fill: false,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
plugins: {
|
|
||||||
tooltip: { enabled: true },
|
|
||||||
legend: {
|
|
||||||
position: 'bottom',
|
|
||||||
rtl: document.dir === 'rtl',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
ticks: { precision: 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
if (this.chart) {
|
|
||||||
this.chart.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
Alpine.data('breakdownChart', (data) => ({
|
|
||||||
chart: null,
|
|
||||||
init() {
|
|
||||||
if (typeof Chart === 'undefined') return;
|
|
||||||
|
|
||||||
const total = data.free + data.paid;
|
|
||||||
const freePercent = total > 0 ? Math.round((data.free / total) * 100) : 0;
|
|
||||||
const paidPercent = total > 0 ? Math.round((data.paid / total) * 100) : 0;
|
|
||||||
|
|
||||||
this.chart = new Chart(this.$refs.canvas, {
|
|
||||||
type: 'doughnut',
|
|
||||||
data: {
|
|
||||||
labels: [
|
|
||||||
@js(__('admin_metrics.free')) + ` (${data.free})`,
|
|
||||||
@js(__('admin_metrics.paid')) + ` (${data.paid})`
|
|
||||||
],
|
|
||||||
datasets: [{
|
|
||||||
data: [data.free, data.paid],
|
|
||||||
backgroundColor: ['#D4AF37', '#0A1F44'],
|
|
||||||
borderWidth: 0,
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
plugins: {
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
label: function(context) {
|
|
||||||
const value = context.parsed;
|
|
||||||
const percent = total > 0 ? Math.round((value / total) * 100) : 0;
|
|
||||||
return `${context.label}: ${percent}%`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
position: 'bottom',
|
|
||||||
rtl: document.dir === 'rtl',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
if (this.chart) {
|
|
||||||
this.chart.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
Alpine.data('noShowChart', (data) => ({
|
|
||||||
chart: null,
|
|
||||||
init() {
|
|
||||||
if (typeof Chart === 'undefined') return;
|
|
||||||
|
|
||||||
this.chart = new Chart(this.$refs.canvas, {
|
|
||||||
type: 'line',
|
|
||||||
data: {
|
|
||||||
labels: data.labels,
|
|
||||||
datasets: [{
|
|
||||||
label: @js(__('admin_metrics.noshow_rate_percent')),
|
|
||||||
data: data.noShowRates,
|
|
||||||
borderColor: '#E74C3C',
|
|
||||||
backgroundColor: 'rgba(231, 76, 60, 0.1)',
|
|
||||||
fill: true,
|
|
||||||
tension: 0.3,
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
plugins: {
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
label: function(context) {
|
|
||||||
return context.parsed.y + '%';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
position: 'bottom',
|
|
||||||
rtl: document.dir === 'rtl',
|
|
||||||
},
|
|
||||||
annotation: {
|
|
||||||
annotations: {
|
|
||||||
threshold: {
|
|
||||||
type: 'line',
|
|
||||||
yMin: 20,
|
|
||||||
yMax: 20,
|
|
||||||
borderColor: 'rgba(231, 76, 60, 0.5)',
|
|
||||||
borderWidth: 2,
|
|
||||||
borderDash: [5, 5],
|
|
||||||
label: {
|
|
||||||
display: true,
|
|
||||||
content: @js(__('admin_metrics.concerning_threshold')),
|
|
||||||
position: 'end'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
min: 0,
|
|
||||||
max: 100,
|
|
||||||
ticks: {
|
|
||||||
callback: function(value) {
|
|
||||||
return value + '%';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
if (this.chart) {
|
|
||||||
this.chart.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
</script>
|
|
||||||
@endscript
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue