feat: Frontend CSS refactoring and test improvements

Frontend:
- Refactored CSS architecture with new utility classes
- Updated dashboard components styling
- Improved responsive grid system
- Enhanced typography and variables
- Updated E2E and integration tests

Added:
- Claude Code slash commands for validation
- SSH tunnel and start test scripts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-21 21:08:47 +02:00
parent 05fc705fe5
commit 12ac2b671e
58 changed files with 7783 additions and 3539 deletions

View File

@@ -24,7 +24,7 @@ export const useAuthStore = defineStore("auth", () => {
username: credentials.username,
password: credentials.password,
};
const response = await apiService.post("/auth/login", loginData);
const { access_token, refresh_token, user: userData } = response.data;
@@ -36,7 +36,8 @@ export const useAuthStore = defineStore("auth", () => {
localStorage.setItem("refresh_token", refresh_token);
localStorage.setItem("user", JSON.stringify(userData));
apiService.defaults.headers.common["Authorization"] = `Bearer ${access_token}`;
apiService.defaults.headers.common["Authorization"] =
`Bearer ${access_token}`;
return { success: true };
} catch (err) {
@@ -77,7 +78,8 @@ export const useAuthStore = defineStore("auth", () => {
accessToken.value = access_token;
localStorage.setItem("access_token", access_token);
apiService.defaults.headers.common["Authorization"] = `Bearer ${access_token}`;
apiService.defaults.headers.common["Authorization"] =
`Bearer ${access_token}`;
return true;
} catch (err) {
@@ -89,7 +91,8 @@ export const useAuthStore = defineStore("auth", () => {
const initializeAuth = () => {
if (accessToken.value) {
apiService.defaults.headers.common["Authorization"] = `Bearer ${accessToken.value}`;
apiService.defaults.headers.common["Authorization"] =
`Bearer ${accessToken.value}`;
}
};
@@ -113,4 +116,4 @@ export const useAuthStore = defineStore("auth", () => {
initializeAuth,
clearError,
};
});
});

View File

@@ -1,14 +1,14 @@
/**
* Pinia Store pentru Cache Management
*/
import { defineStore } from 'pinia'
import { apiService } from '../services/api'
import { defineStore } from "pinia";
import { apiService } from "../services/api";
export const useCacheStore = defineStore('cache', {
export const useCacheStore = defineStore("cache", {
state: () => ({
stats: null,
loading: false,
error: null
error: null,
}),
getters: {
@@ -16,9 +16,10 @@ export const useCacheStore = defineStore('cache', {
hasError: (state) => state.error !== null,
cacheEnabled: (state) => state.stats?.enabled ?? false,
hitRate: (state) => state.stats?.hit_rate ?? 0,
queriesSaved: (state) => state.stats?.queries_saved ?? { today: 0, week: 0, total: 0 },
queriesSaved: (state) =>
state.stats?.queries_saved ?? { today: 0, week: 0, total: 0 },
responseTimes: (state) => state.stats?.response_times ?? {},
cacheSize: (state) => state.stats?.cache_size ?? { memory: 0, sqlite: 0 }
cacheSize: (state) => state.stats?.cache_size ?? { memory: 0, sqlite: 0 },
},
actions: {
@@ -26,18 +27,18 @@ export const useCacheStore = defineStore('cache', {
* Get cache statistics
*/
async getStats() {
this.loading = true
this.error = null
this.loading = true;
this.error = null;
try {
const response = await apiService.get('/cache/stats')
this.stats = response.data
return response.data
const response = await apiService.get("/cache/stats");
this.stats = response.data;
return response.data;
} catch (error) {
this.error = error.response?.data?.detail || error.message
throw error
this.error = error.response?.data?.detail || error.message;
throw error;
} finally {
this.loading = false
this.loading = false;
}
},
@@ -47,21 +48,21 @@ export const useCacheStore = defineStore('cache', {
* @param {string|null} cacheType - Optional cache type to invalidate
*/
async invalidateCache(companyId = null, cacheType = null) {
this.loading = true
this.error = null
this.loading = true;
this.error = null;
try {
const response = await apiService.post('/cache/invalidate', {
const response = await apiService.post("/cache/invalidate", {
company_id: companyId,
cache_type: cacheType
})
cache_type: cacheType,
});
return response.data
return response.data;
} catch (error) {
this.error = error.response?.data?.detail || error.message
throw error
this.error = error.response?.data?.detail || error.message;
throw error;
} finally {
this.loading = false
this.loading = false;
}
},
@@ -70,23 +71,25 @@ export const useCacheStore = defineStore('cache', {
* @param {boolean} enabled - Enable or disable cache for current user
*/
async toggleUserCache(enabled) {
this.loading = true
this.error = null
this.loading = true;
this.error = null;
try {
const response = await apiService.post('/cache/toggle-user', { enabled })
const response = await apiService.post("/cache/toggle-user", {
enabled,
});
// Update local stats
if (this.stats) {
this.stats.user_enabled = enabled
this.stats.user_enabled = enabled;
}
return response.data
return response.data;
} catch (error) {
this.error = error.response?.data?.detail || error.message
throw error
this.error = error.response?.data?.detail || error.message;
throw error;
} finally {
this.loading = false
this.loading = false;
}
},
@@ -95,24 +98,26 @@ export const useCacheStore = defineStore('cache', {
* @param {boolean} enabled - Enable or disable cache globally
*/
async toggleGlobalCache(enabled) {
this.loading = true
this.error = null
this.loading = true;
this.error = null;
try {
const response = await apiService.post('/cache/toggle-global', { enabled })
const response = await apiService.post("/cache/toggle-global", {
enabled,
});
// Update local stats
if (this.stats) {
this.stats.global_enabled = enabled
this.stats.enabled = enabled
this.stats.global_enabled = enabled;
this.stats.enabled = enabled;
}
return response.data
return response.data;
} catch (error) {
this.error = error.response?.data?.detail || error.message
throw error
this.error = error.response?.data?.detail || error.message;
throw error;
} finally {
this.loading = false
this.loading = false;
}
},
@@ -121,23 +126,26 @@ export const useCacheStore = defineStore('cache', {
* @param {boolean} enabled - Enable or disable auto-invalidation
*/
async toggleAutoInvalidate(enabled) {
this.loading = true
this.error = null
this.loading = true;
this.error = null;
try {
const response = await apiService.post('/cache/toggle-auto-invalidate', { enabled })
const response = await apiService.post(
"/cache/toggle-auto-invalidate",
{ enabled },
);
// Update local stats
if (this.stats) {
this.stats.auto_invalidate = enabled
this.stats.auto_invalidate = enabled;
}
return response.data
return response.data;
} catch (error) {
this.error = error.response?.data?.detail || error.message
throw error
this.error = error.response?.data?.detail || error.message;
throw error;
} finally {
this.loading = false
this.loading = false;
}
},
@@ -145,7 +153,7 @@ export const useCacheStore = defineStore('cache', {
* Clear error state
*/
clearError() {
this.error = null
}
}
})
this.error = null;
},
},
});

View File

@@ -11,7 +11,7 @@ export const useCompanyStore = defineStore("companies", () => {
const username = authStore.user?.username;
if (!username) {
console.log('[Companies] No username available for initialization');
console.log("[Companies] No username available for initialization");
return null;
}
@@ -20,10 +20,13 @@ export const useCompanyStore = defineStore("companies", () => {
if (saved) {
try {
const company = JSON.parse(saved);
console.log(`[Companies] Loaded saved company for user ${username}:`, company.name);
console.log(
`[Companies] Loaded saved company for user ${username}:`,
company.name,
);
return company;
} catch (e) {
console.error('Failed to parse saved company', e);
console.error("Failed to parse saved company", e);
localStorage.removeItem(key);
}
}
@@ -42,15 +45,20 @@ export const useCompanyStore = defineStore("companies", () => {
() => authStore.user,
(newUser) => {
if (newUser && newUser.username && !selectedCompany.value) {
console.log('[Companies] User became available, attempting to restore selected company');
console.log(
"[Companies] User became available, attempting to restore selected company",
);
const restoredCompany = initializeSelectedCompany();
if (restoredCompany) {
selectedCompany.value = restoredCompany;
console.log('[Companies] Successfully restored selected company:', restoredCompany.name);
console.log(
"[Companies] Successfully restored selected company:",
restoredCompany.name,
);
}
}
},
{ immediate: true }
{ immediate: true },
);
// Getters
@@ -59,14 +67,14 @@ export const useCompanyStore = defineStore("companies", () => {
const selectedCompanyId = computed(
() => selectedCompany.value?.id_firma || null,
);
// Computed property for formatted company list display
const companyListFormatted = computed(() => {
return companies.value.map(company => ({
return companies.value.map((company) => ({
...company,
displayName: company.fiscal_code
displayName: company.fiscal_code
? `${company.name} (${company.fiscal_code})`
: company.name
: company.name,
}));
});
@@ -76,22 +84,26 @@ export const useCompanyStore = defineStore("companies", () => {
error.value = null;
try {
console.log('[COMPANY STORE DEBUG] Loading companies...');
console.log("[COMPANY STORE DEBUG] Loading companies...");
const response = await apiService.get("/companies");
console.log('[COMPANY STORE DEBUG] API Response:', response.data);
console.log("[COMPANY STORE DEBUG] API Response:", response.data);
companies.value = response.data.companies || [];
console.log('[COMPANY STORE DEBUG] Companies array:', companies.value);
console.log("[COMPANY STORE DEBUG] Companies array:", companies.value);
// Security validation: Check if saved company is accessible to current user
if (selectedCompany.value) {
const exists = companies.value.find(
c => c.id_firma === selectedCompany.value.id_firma
(c) => c.id_firma === selectedCompany.value.id_firma,
);
if (!exists) {
console.warn('[Companies][Security] Saved company not accessible to current user, clearing');
console.warn(
"[Companies][Security] Saved company not accessible to current user, clearing",
);
clearSelectedCompany();
} else {
console.log('[Companies][Security] Saved company validated successfully');
console.log(
"[Companies][Security] Saved company validated successfully",
);
}
}
@@ -113,14 +125,17 @@ export const useCompanyStore = defineStore("companies", () => {
const username = authStore.user?.username;
if (!username) {
console.warn('[Companies] Cannot save company - no username available');
console.warn("[Companies] Cannot save company - no username available");
return;
}
const key = `selected_company_${username}`;
if (company) {
localStorage.setItem(key, JSON.stringify(company));
console.log(`[Companies] Saved company for user ${username}:`, company.name);
console.log(
`[Companies] Saved company for user ${username}:`,
company.name,
);
} else {
localStorage.removeItem(key);
console.log(`[Companies] Cleared company for user ${username}`);
@@ -142,7 +157,9 @@ export const useCompanyStore = defineStore("companies", () => {
};
const getCompanyById = (id_firma) => {
return companies.value.find((company) => company.id_firma === parseInt(id_firma));
return companies.value.find(
(company) => company.id_firma === parseInt(id_firma),
);
};
const clearError = () => {

View File

@@ -26,8 +26,8 @@ export const useDashboardStore = defineStore("dashboard", () => {
error.value = null;
try {
const response = await apiService.get('/dashboard/summary', {
params: { company: companyId }
const response = await apiService.get("/dashboard/summary", {
params: { company: companyId },
});
summary.value = response.data;
return { success: true };
@@ -40,49 +40,58 @@ export const useDashboardStore = defineStore("dashboard", () => {
}
};
const loadTrendData = async (companyId, period = '12m', chartType = 'line') => {
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
}
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');
throw new Error("Empty response from trends API");
}
console.log('Raw trends response:', response.data);
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');
throw new Error("Failed to transform trends data - invalid format");
}
trends.value = transformedData;
console.log('Transformed trends data:', 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";
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
data: err.response?.data,
});
// Clear trends data and return error - no more mock data
trends.value = null;
return { success: false, error: error.value };
@@ -93,13 +102,24 @@ export const useDashboardStore = defineStore("dashboard", () => {
// 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);
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'];
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`);
@@ -111,10 +131,13 @@ export const useDashboardStore = defineStore("dashboard", () => {
const periods = [...backendData.periods];
// Format labels for monthly data (YYYY-MM -> MM/YYYY)
const formattedPeriods = periods.map(period => {
const [year, month] = period.split('-');
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' });
return date.toLocaleDateString("ro-RO", {
month: "2-digit",
year: "numeric",
});
});
// Preserve all raw data from backend for card calculations
@@ -143,35 +166,41 @@ export const useDashboardStore = defineStore("dashboard", () => {
},
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)',
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',
pointBackgroundColor: "rgb(59, 130, 246)",
pointBorderColor: "#ffffff",
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6
}
]
pointHoverRadius: 6,
},
],
};
};
const loadDetailedData = async (dataType, companyId, page = 1, pageSize = 25, search = '') => {
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', {
const response = await apiService.get("/dashboard/detailed-data", {
params: {
company: companyId,
data_type: dataType,
page: page,
page_size: pageSize,
search: search
}
search: search,
},
});
// Store total for pagination
@@ -179,12 +208,13 @@ export const useDashboardStore = defineStore("dashboard", () => {
return {
success: true,
data: response.data.data || [], // Backend returns 'data' not 'items'
data: response.data.data || [], // Backend returns 'data' not 'items'
total: response.data.total || 0,
page: response.data.page || 1
page: response.data.page || 1,
};
} catch (err) {
error.value = err.response?.data?.detail || "Failed to load detailed data";
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
@@ -195,7 +225,7 @@ export const useDashboardStore = defineStore("dashboard", () => {
error: error.value,
data: mockData,
total: mockData.length,
page: 1
page: 1,
};
} finally {
isLoading.value = false;
@@ -204,30 +234,135 @@ export const useDashboardStore = defineStore("dashboard", () => {
// Generate mock data for testing until backend endpoint is implemented
const generateMockDetailedData = (dataType) => {
switch(dataType) {
case 'clients':
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' }
{
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':
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' }
{
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':
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' }
{
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 [];
@@ -235,92 +370,92 @@ export const useDashboardStore = defineStore("dashboard", () => {
};
// Funcții noi pentru carduri
const loadPerformanceData = async (companyId, period = '7d') => {
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 }
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);
console.error("Failed to load performance data:", err);
return { success: false, error: err.message };
}
};
const loadCashFlowData = async (companyId, period = '7d') => {
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 }
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);
console.error("Failed to load cashflow data:", err);
return { success: false, error: err.message };
}
};
const loadMaturityData = async (companyId, period = '7d') => {
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 }
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);
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 }
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);
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')}`
period: `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`,
};
currentPeriod.value = fallbackPeriod;
return { success: false, error: err.message, data: fallbackPeriod };
@@ -368,6 +503,6 @@ export const useDashboardStore = defineStore("dashboard", () => {
clearCache,
// Detailed data pagination
detailedDataTotal
detailedDataTotal,
};
});
});