164 lines
6.0 KiB
JavaScript
164 lines
6.0 KiB
JavaScript
/**
|
|
* state.js - Centralized state management for the dashboard
|
|
*
|
|
* This module maintains the application state and provides getters/setters
|
|
* to allow other modules to interact with the state in a controlled manner.
|
|
*/
|
|
|
|
import { formatDateForAPI } from './dateUtils.js'; // Import from dateUtils
|
|
|
|
// State container - private to this module
|
|
const state = {
|
|
// Current view/period
|
|
currentPeriod: 'daily', // 'daily', 'weekly', 'monthly'
|
|
selectedDate: formatDateForAPI(new Date()), // Current date in YYYY-MM-DD format
|
|
currentDate: new Date(), // Date object for the selected date
|
|
selectedWeekDay: null, // Selected day within weekly view
|
|
|
|
// Table data and filtering
|
|
reportData: [], // Currently displayed report data
|
|
currentStateFilter: 'all', // 'all', 'working', 'not_working'
|
|
userFilterText: '', // Text entered in the user filter input
|
|
|
|
// Sorting
|
|
currentSortColumn: 'duration', // Which column is being sorted - default to duration (real work hours)
|
|
currentSortDirection: 'desc', // 'asc' or 'desc' - default to descending
|
|
|
|
// User states
|
|
userStates: {}, // Cache of user states {username: state}
|
|
userStatesLastUpdate: 0, // Timestamp of last update
|
|
STATE_CACHE_DURATION: 5000, // 5 seconds
|
|
|
|
// Auto-refresh
|
|
autoRefreshEnabled: true, // Auto-refresh enabled by default
|
|
autoRefreshInterval: 60000, // Default refresh interval (60 seconds). Aligns with client-side 1-minute reporting.
|
|
autoRefreshTimer: null, // Holds the timer reference
|
|
lastRefreshTime: Date.now(), // Last time data was refreshed
|
|
countdownTimer: null, // Timer for updating countdown display
|
|
};
|
|
|
|
// Exported getters and setters
|
|
export default {
|
|
// Period/view getters and setters
|
|
getCurrentPeriod: () => state.currentPeriod,
|
|
setCurrentPeriod: (period) => {
|
|
state.currentPeriod = period;
|
|
return state.currentPeriod;
|
|
},
|
|
|
|
getSelectedDate: () => state.selectedDate,
|
|
setSelectedDate: (dateStr) => {
|
|
state.selectedDate = dateStr;
|
|
// Parse YYYY-MM-DD as local date to avoid timezone interpretation issues
|
|
if (dateStr && typeof dateStr === 'string' && dateStr.includes('-')) {
|
|
const parts = dateStr.split('-');
|
|
if (parts.length === 3) {
|
|
const year = parseInt(parts[0], 10);
|
|
const month = parseInt(parts[1], 10) - 1; // JavaScript months are 0-indexed
|
|
const day = parseInt(parts[2], 10);
|
|
// Check if parts are valid numbers before creating date
|
|
if (!isNaN(year) && !isNaN(month) && !isNaN(day)) {
|
|
state.currentDate = new Date(year, month, day);
|
|
} else {
|
|
console.warn(`Invalid date parts in setSelectedDate: ${dateStr}`);
|
|
state.currentDate = new Date(); // Fallback or handle error appropriately
|
|
}
|
|
} else {
|
|
console.warn(`Invalid date string format in setSelectedDate: ${dateStr}`);
|
|
state.currentDate = new Date(); // Fallback
|
|
}
|
|
} else {
|
|
console.warn(`Invalid dateStr input to setSelectedDate: ${dateStr}`);
|
|
state.currentDate = new Date(); // Fallback for null or non-string input
|
|
}
|
|
return state.selectedDate;
|
|
},
|
|
|
|
getCurrentDate: () => state.currentDate,
|
|
setCurrentDate: (date) => {
|
|
state.currentDate = date;
|
|
state.selectedDate = formatDateForAPI(date);
|
|
return state.currentDate;
|
|
},
|
|
|
|
getSelectedWeekDay: () => state.selectedWeekDay,
|
|
setSelectedWeekDay: (day) => {
|
|
state.selectedWeekDay = day;
|
|
return state.selectedWeekDay;
|
|
},
|
|
|
|
// Report data getters and setters
|
|
getReportData: () => state.reportData,
|
|
setReportData: (data) => {
|
|
state.reportData = [...data];
|
|
return state.reportData;
|
|
},
|
|
|
|
// Filter getters and setters
|
|
getCurrentStateFilter: () => state.currentStateFilter,
|
|
setCurrentStateFilter: (filter) => {
|
|
state.currentStateFilter = filter;
|
|
return state.currentStateFilter;
|
|
},
|
|
|
|
getUserFilterText: () => state.userFilterText,
|
|
setUserFilterText: (text) => {
|
|
state.userFilterText = text;
|
|
return state.userFilterText;
|
|
},
|
|
|
|
// Sort getters and setters
|
|
getCurrentSortColumn: () => state.currentSortColumn,
|
|
setCurrentSortColumn: (column) => {
|
|
state.currentSortColumn = column;
|
|
return state.currentSortColumn;
|
|
},
|
|
|
|
getCurrentSortDirection: () => state.currentSortDirection,
|
|
setCurrentSortDirection: (direction) => {
|
|
state.currentSortDirection = direction;
|
|
return state.currentSortDirection;
|
|
},
|
|
|
|
// User states getters and setters
|
|
getUserStates: () => state.userStates,
|
|
setUserStates: (states) => {
|
|
state.userStates = {...states};
|
|
state.userStatesLastUpdate = Date.now();
|
|
return state.userStates;
|
|
},
|
|
|
|
getUserStatesLastUpdate: () => state.userStatesLastUpdate,
|
|
getStateCacheDuration: () => state.STATE_CACHE_DURATION,
|
|
|
|
// Auto-refresh getters and setters
|
|
isAutoRefreshEnabled: () => state.autoRefreshEnabled,
|
|
setAutoRefreshEnabled: (enabled) => {
|
|
state.autoRefreshEnabled = enabled;
|
|
return state.autoRefreshEnabled;
|
|
},
|
|
|
|
getAutoRefreshInterval: () => state.autoRefreshInterval,
|
|
setAutoRefreshInterval: (interval) => {
|
|
state.autoRefreshInterval = interval;
|
|
return state.autoRefreshInterval;
|
|
},
|
|
|
|
getAutoRefreshTimer: () => state.autoRefreshTimer,
|
|
setAutoRefreshTimer: (timer) => {
|
|
state.autoRefreshTimer = timer;
|
|
return state.autoRefreshTimer;
|
|
},
|
|
|
|
getLastRefreshTime: () => state.lastRefreshTime,
|
|
setLastRefreshTime: (time) => {
|
|
state.lastRefreshTime = time;
|
|
return state.lastRefreshTime;
|
|
},
|
|
|
|
getCountdownTimer: () => state.countdownTimer,
|
|
setCountdownTimer: (timer) => {
|
|
state.countdownTimer = timer;
|
|
return state.countdownTimer;
|
|
}
|
|
};
|