const RadiusTransferModal = { name: 'RadiusTransferModal', props: { show: Boolean, username: String }, template: `

Bitte geben Sie eine gültige E-Mail-Adresse ein.

`, data: () => ({ window: window, transferInitialLoading: false, transferMonthlyLoading: false, transferYear: new Date().getFullYear(), transferMonth: new Date().getMonth() + 1, transferYearlyData: null, transferMonthlyData: null, transferChartInstance: null, showYearDropdown: false, // Email Logic showEmailModal: false, isSendingEmail: false, recipientEmail: '' }), computed: { availableYears() { const c = new Date().getFullYear(), s = 2021; if (s > c) return [c]; return Array.from({length: c - s + 1}, (_, i) => c - i); }, allMonths() { return Array.from({length: 12}, (_, i) => ({ month: i + 1, name: new Date(2000, i, 1).toLocaleString('de-DE', {month: 'short'}) })); }, isValidEmail() { if (!this.recipientEmail) return false; return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.recipientEmail); } }, watch: { show(val) { if (val && this.username) { this.transferYear = new Date().getFullYear(); this.transferMonth = new Date().getMonth() + 1; this.fetchTransferYearData(); } else { // Cleanup this.close(); } } }, methods: { close() { this.$emit('close'); this.transferYearlyData = null; this.transferMonthlyData = null; this.showYearDropdown = false; this.showEmailModal = false; this.recipientEmail = ''; this.isSendingEmail = false; if (this.transferChartInstance) { this.transferChartInstance.destroy(); this.transferChartInstance = null; } }, async fetchTransferYearData() { this.transferInitialLoading = true; this.transferYearlyData = null; try { const { data } = await axios.get(`${window.TT_CONFIG.BASE_PATH}/Radius/proxyUnsecureHTTPRequestToRadius`, { params: { action2: 'transferStatistic', username: this.username, year: this.transferYear, month: 0 } }); if (data && data.monthlySummary) { this.transferYearlyData = data; const last = [...data.monthlySummary].reverse().find(m => m.grandTotalBytes > 0); this.transferMonth = last ? last.month : new Date().getMonth() + 1; await this.fetchTransferMonthData(); } else { this.transferYearlyData = null; } } catch (e) { console.error(e); this.transferYearlyData = null; } this.transferInitialLoading = false; }, async fetchTransferMonthData() { this.transferMonthlyLoading = true; this.transferMonthlyData = null; if (this.transferChartInstance) this.transferChartInstance.destroy(); try { const { data } = await axios.get(`${window.TT_CONFIG.BASE_PATH}/Radius/proxyUnsecureHTTPRequestToRadius`, { params: { action2: 'transferStatistic', username: this.username, year: this.transferYear, month: this.transferMonth } }); this.transferMonthlyData = data || null; } catch (e) { console.error(e); this.transferMonthlyData = null; } this.transferMonthlyLoading = false; this.$nextTick(() => { if (this.show) this.renderTransferChart(); }); }, isMonthDisabled(month) { if (this.transferInitialLoading || this.transferMonthlyLoading) return true; if (!this.transferYearlyData?.monthlySummary) return true; const m = this.transferYearlyData.monthlySummary.find(m => m.month === month); return !m || m.grandTotalBytes === 0; }, selectYear(year) { this.showYearDropdown = false; if (this.transferYear !== year) this.changeTransferYear(year); }, async changeTransferYear(year) { this.transferYear = year; await this.fetchTransferYearData(); }, async changeTransferMonth(month) { this.transferMonth = month; await this.fetchTransferMonthData(); }, prepareEmailModal() { if (this.transferInitialLoading || !this.transferYearlyData || !this.transferYearlyData.yearlySummary || this.transferYearlyData.yearlySummary.grandTotalBytes === 0) return; this.recipientEmail = ''; this.showEmailModal = true; }, async sendTransferEmail() { if (!this.transferMonthlyData || !this.transferChartInstance || !this.isValidEmail) return; this.isSendingEmail = true; try { const chartImageBase64 = this.transferChartInstance.toBase64Image(); const payload = { username: this.username, year: this.transferYear, month: this.transferMonth, monthlySummary: this.transferMonthlyData.summary, monthlyDetails: this.transferMonthlyData.details, chartImage: chartImageBase64, recipient: this.recipientEmail }; await axios.post(`${window.TT_CONFIG.BASE_PATH}/Radius/sendCustomerEmail`, payload); window.notify('success', 'E-Mail wurde erfolgreich versendet.'); this.showEmailModal = false; } catch (e) { console.error("Failed to send transfer email:", e); window.notify('error', 'Fehler beim Senden der E-Mail.'); } finally { this.isSendingEmail = false; } }, processChartData(details) { if (!details || !details.length) return {labels: [], datasets: []}; const daily = details.reduce((a, s) => { const d = s.startTime.split(' ')[0]; if (!a[d]) a[d] = {downloadBytes: 0, uploadBytes: 0}; a[d].downloadBytes += Number(s.downloadBytes) || 0; a[d].uploadBytes += Number(s.uploadBytes) || 0; return a; }, {}); const dates = Object.keys(daily).sort((a, b) => new Date(a) - new Date(b)); return { labels: dates, datasets: [{ label: 'Download', data: dates.map(d => daily[d].downloadBytes), borderColor: 'rgba(15, 157, 88, 0.8)', backgroundColor: 'rgba(15, 157, 88, 0.1)', fill: true, tension: 0.3, pointRadius: 2, borderWidth: 1.5 }, { label: 'Upload', data: dates.map(d => daily[d].uploadBytes), borderColor: 'rgba(0, 83, 132, 0.8)', backgroundColor: 'rgba(0, 83, 132, 0.1)', fill: true, tension: 0.3, pointRadius: 2, borderWidth: 1.5 }] }; }, renderTransferChart() { if (this.transferChartInstance) this.transferChartInstance.destroy(); if (!this.$refs.transferChartCanvas || !this.transferMonthlyData?.details?.length || !window.Chart) return; const d = this.processChartData(this.transferMonthlyData.details); if (!d.labels.length) return; const chartBackgroundColorPlugin = { id: 'customCanvasBackgroundColor', beforeDraw: (chart) => { const {ctx} = chart; ctx.save(); ctx.globalCompositeOperation = 'destination-over'; ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, chart.width, chart.height); ctx.restore(); } }; this.transferChartInstance = new Chart(this.$refs.transferChartCanvas.getContext('2d'), { type: 'line', data: d, options: { responsive: true, maintainAspectRatio: false, scales: { x: { type: 'time', time: {unit: 'day', tooltipFormat: 'DD.MM.YYYY', displayFormats: {day: 'DD.MM'}}, grid: {display: false}, ticks: {maxRotation: 0, autoSkip: true, maxTicksLimit: 15} }, y: { beginAtZero: true, ticks: {callback: (v) => window.TT_CORE.formatBytes(v, 0)}, grid: {color: 'rgba(0,0,0,0.05)'} } }, plugins: { tooltip: {callbacks: {label: (c) => `${c.dataset.label || ''}: ${window.TT_CORE.formatBytes(c.parsed.y)}`}}, legend: {position: 'bottom', labels: {usePointStyle: true, boxWidth: 8, padding: 20}} }, interaction: {mode: 'index', intersect: false} }, plugins: [chartBackgroundColorPlugin] }); } } }; if (window.VueApp) { window.VueApp.component('radius-transfer-modal', RadiusTransferModal); }