import { defineStore } from "pinia"; import { ref } from "vue"; import { apiService } from "../services/api"; export const useDashboardStore = defineStore("dashboard", () => { // State existent const summary = ref(null); const trends = ref(null); const isLoading = ref(false); const error = ref(null); // State nou pentru carduri const performanceData = ref({}); const cashflowData = ref({}); const maturityData = ref({}); const currentPeriod = ref(null); // State pentru detailed data pagination const detailedDataTotal = ref(0); // Cache pentru date const dataCache = new Map(); const loadDashboardSummary = async (companyId) => { isLoading.value = true; error.value = null; try { const response = await apiService.get("/dashboard/summary", { params: { company: companyId }, }); summary.value = response.data; return { success: true }; } catch (err) { error.value = err.response?.data?.detail || "Failed to load dashboard"; console.error("Failed to load dashboard:", err); return { success: false, error: error.value }; } finally { isLoading.value = false; } }; const loadTrendData = async ( companyId, period = "12m", chartType = "line", ) => { isLoading.value = true; error.value = null; try { console.log( `Loading trend data for company ${companyId}, period: ${period}`, ); const response = await apiService.get("/dashboard/trends", { params: { company: companyId, period: period, }, }); // Validate response structure if (!response.data) { throw new Error("Empty response from trends API"); } console.log("Raw trends response:", response.data); // Transform backend response to Chart.js format const backendData = response.data; const transformedData = transformTrendsData(backendData); if (!transformedData) { throw new Error("Failed to transform trends data - invalid format"); } trends.value = transformedData; console.log("Transformed trends data:", transformedData); return { success: true, data: transformedData }; } catch (err) { const errorMessage = err.response?.data?.detail || err.message || "Failed to load trend data"; error.value = errorMessage; console.error("Failed to load trend data:", err); console.error("Error details:", { status: err.response?.status, statusText: err.response?.statusText, data: err.response?.data, }); // Clear trends data and return error - no more mock data trends.value = null; return { success: false, error: error.value }; } finally { isLoading.value = false; } }; // Transform backend trends data to Chart.js format AND preserve raw data const transformTrendsData = (backendData) => { if ( !backendData || !backendData.periods || !Array.isArray(backendData.periods) || backendData.periods.length === 0 ) { console.warn("Invalid trends data received:", backendData); return null; } // Validate that we have all required data const requiredFields = [ "trezorerie_sold", "clienti_sold", "furnizori_sold", "clienti_incasat", "furnizori_achitat", ]; for (const field of requiredFields) { if (!backendData[field] || !Array.isArray(backendData[field])) { console.warn(`Missing ${field} data`); return null; } } // Data is already in ASC order from backend const periods = [...backendData.periods]; // Format labels for monthly data (YYYY-MM -> MM/YYYY) const formattedPeriods = periods.map((period) => { const [year, month] = period.split("-"); const date = new Date(year, month - 1); return date.toLocaleDateString("ro-RO", { month: "2-digit", year: "numeric", }); }); // Preserve all raw data from backend for card calculations return { labels: formattedPeriods, raw: { // Current period data periods: backendData.periods, clienti_facturat: backendData.clienti_facturat || [], clienti_incasat: backendData.clienti_incasat || [], clienti_sold: backendData.clienti_sold || [], furnizori_facturat: backendData.furnizori_facturat || [], furnizori_achitat: backendData.furnizori_achitat || [], furnizori_sold: backendData.furnizori_sold || [], trezorerie_sold: backendData.trezorerie_sold || [], // Previous period data (year-over-year comparison) previous_periods: backendData.previous_periods || [], clienti_facturat_prev: backendData.clienti_facturat_prev || [], clienti_incasat_prev: backendData.clienti_incasat_prev || [], clienti_sold_prev: backendData.clienti_sold_prev || [], furnizori_facturat_prev: backendData.furnizori_facturat_prev || [], furnizori_achitat_prev: backendData.furnizori_achitat_prev || [], furnizori_sold_prev: backendData.furnizori_sold_prev || [], trezorerie_sold_prev: backendData.trezorerie_sold_prev || [], }, datasets: [ { label: "Trezorerie - Sold Net", data: [...backendData.trezorerie_sold].map((val) => Number(val) || 0), borderColor: "rgb(59, 130, 246)", backgroundColor: "rgba(59, 130, 246, 0.1)", tension: 0.4, fill: false, pointBackgroundColor: "rgb(59, 130, 246)", pointBorderColor: "#ffffff", pointBorderWidth: 2, pointRadius: 4, pointHoverRadius: 6, }, ], }; }; const loadDetailedData = async ( dataType, companyId, page = 1, pageSize = 25, search = "", ) => { isLoading.value = true; error.value = null; try { const response = await apiService.get("/dashboard/detailed-data", { params: { company: companyId, data_type: dataType, page: page, page_size: pageSize, search: search, }, }); // Store total for pagination detailedDataTotal.value = response.data.total || 0; return { success: true, data: response.data.data || [], // Backend returns 'data' not 'items' total: response.data.total || 0, page: response.data.page || 1, }; } catch (err) { error.value = err.response?.data?.detail || "Failed to load detailed data"; console.error("Failed to load detailed data:", err); // Return mock data structure for testing const mockData = generateMockDetailedData(dataType); detailedDataTotal.value = mockData.length; return { success: false, error: error.value, data: mockData, total: mockData.length, page: 1, }; } finally { isLoading.value = false; } }; // Generate mock data for testing until backend endpoint is implemented const generateMockDetailedData = (dataType) => { switch (dataType) { case "clients": return [ { id: 1, client: "SC ALPHA SRL", facturat: 15000, incasat: 12000, sold: 3000, status: "Activ", }, { id: 2, client: "SC BETA SRL", facturat: 8500, incasat: 8500, sold: 0, status: "Activ", }, { id: 3, client: "SC GAMMA SRL", facturat: 22000, incasat: 15000, sold: 7000, status: "Activ", }, { id: 4, client: "SC DELTA SRL", facturat: 5500, incasat: 2000, sold: 3500, status: "Întârziere", }, { id: 5, client: "SC EPSILON SRL", facturat: 18000, incasat: 18000, sold: 0, status: "Activ", }, ]; case "suppliers": return [ { id: 1, furnizor: "SC SUPPLIER A SRL", facturat: 12000, achitat: 10000, sold: 2000, status: "Activ", }, { id: 2, furnizor: "SC SUPPLIER B SRL", facturat: 7500, achitat: 7500, sold: 0, status: "Activ", }, { id: 3, furnizor: "SC SUPPLIER C SRL", facturat: 19000, achitat: 12000, sold: 7000, status: "Pendente", }, { id: 4, furnizor: "SC SUPPLIER D SRL", facturat: 4200, achitat: 4200, sold: 0, status: "Activ", }, { id: 5, furnizor: "SC SUPPLIER E SRL", facturat: 16800, achitat: 8000, sold: 8800, status: "Pendente", }, ]; case "treasury": return [ { id: 1, cont: "5121", nume_cont: "Cont curent BCR", sold: 45000, valuta: "RON", tip: "Bancă", }, { id: 2, cont: "5311", nume_cont: "Casa RON", sold: 2500, valuta: "RON", tip: "Numerar", }, { id: 3, cont: "5124", nume_cont: "Cont curent BRD EUR", sold: 8500, valuta: "EUR", tip: "Bancă", }, { id: 4, cont: "5125", nume_cont: "Cont economii ING", sold: 125000, valuta: "RON", tip: "Economii", }, { id: 5, cont: "5312", nume_cont: "Casa valută", sold: 500, valuta: "EUR", tip: "Numerar", }, ]; default: return []; } }; // Funcții noi pentru carduri const loadPerformanceData = async (companyId, period = "7d") => { const cacheKey = `performance-${companyId}-${period}`; // Check cache if (dataCache.has(cacheKey)) { performanceData.value[period] = dataCache.get(cacheKey); return { success: true, data: dataCache.get(cacheKey) }; } try { const response = await apiService.get("/dashboard/performance", { params: { company: companyId, period }, }); performanceData.value[period] = response.data; dataCache.set(cacheKey, response.data); return { success: true, data: response.data }; } catch (err) { console.error("Failed to load performance data:", err); return { success: false, error: err.message }; } }; const loadCashFlowData = async (companyId, period = "7d") => { const cacheKey = `cashflow-${companyId}-${period}`; if (dataCache.has(cacheKey)) { cashflowData.value[period] = dataCache.get(cacheKey); return { success: true, data: dataCache.get(cacheKey) }; } try { const response = await apiService.get("/dashboard/cashflow", { params: { company: companyId, period }, }); cashflowData.value[period] = response.data; dataCache.set(cacheKey, response.data); return { success: true, data: response.data }; } catch (err) { console.error("Failed to load cashflow data:", err); return { success: false, error: err.message }; } }; const loadMaturityData = async (companyId, period = "7d") => { const cacheKey = `maturity-${companyId}-${period}`; if (dataCache.has(cacheKey)) { maturityData.value[period] = dataCache.get(cacheKey); return { success: true, data: dataCache.get(cacheKey) }; } try { const response = await apiService.get("/dashboard/maturity", { params: { company: companyId, period }, }); maturityData.value[period] = response.data; dataCache.set(cacheKey, response.data); return { success: true, data: response.data }; } catch (err) { console.error("Failed to load maturity data:", err); return { success: false, error: err.message }; } }; const loadCurrentPeriod = async (companyId) => { try { const response = await apiService.get("/dashboard/current-period", { params: { company: companyId }, }); currentPeriod.value = response.data; return { success: true, data: response.data }; } catch (err) { console.error("Failed to load current period:", err); // Fallback to current date if API fails const now = new Date(); const fallbackPeriod = { year: now.getFullYear(), month: now.getMonth() + 1, period: `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`, }; currentPeriod.value = fallbackPeriod; return { success: false, error: err.message, data: fallbackPeriod }; } }; // Clear cache const clearCache = () => { dataCache.clear(); }; const reset = () => { summary.value = null; trends.value = null; isLoading.value = false; error.value = null; // Clear new data as well performanceData.value = {}; cashflowData.value = {}; maturityData.value = {}; currentPeriod.value = null; clearCache(); }; return { // Existing summary, trends, isLoading, error, loadDashboardSummary, loadTrendData, loadDetailedData, reset, // New performanceData, cashflowData, maturityData, currentPeriod, loadPerformanceData, loadCashFlowData, loadMaturityData, loadCurrentPeriod, clearCache, // Detailed data pagination detailedDataTotal, }; });