First commit - backup RDOC
This commit is contained in:
315
src/stores/useAppStateStore.ts
Normal file
315
src/stores/useAppStateStore.ts
Normal file
@@ -0,0 +1,315 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
|
||||
// Tipos para notificações
|
||||
export interface Notification {
|
||||
id: string;
|
||||
type: 'success' | 'error' | 'warning' | 'info';
|
||||
title: string;
|
||||
message: string;
|
||||
timestamp: string;
|
||||
read: boolean;
|
||||
autoClose?: boolean;
|
||||
duration?: number;
|
||||
}
|
||||
|
||||
// Tipos para configurações
|
||||
export interface AppSettings {
|
||||
theme: 'light' | 'dark' | 'system';
|
||||
language: 'pt-BR' | 'en-US';
|
||||
autoSync: boolean;
|
||||
syncInterval: number; // em minutos
|
||||
offlineMode: boolean;
|
||||
notifications: {
|
||||
push: boolean;
|
||||
email: boolean;
|
||||
sound: boolean;
|
||||
};
|
||||
display: {
|
||||
density: 'compact' | 'comfortable' | 'spacious';
|
||||
animations: boolean;
|
||||
reducedMotion: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
// Estado da aplicação focado em UI e configurações
|
||||
interface AppState {
|
||||
// Estado de conectividade e sincronização
|
||||
isOnline: boolean;
|
||||
isSyncing: boolean;
|
||||
lastSync: string | null;
|
||||
syncError: string | null;
|
||||
|
||||
// Estado de UI
|
||||
isLoading: boolean;
|
||||
sidebarCollapsed: boolean;
|
||||
currentView: string;
|
||||
|
||||
// Notificações
|
||||
notifications: Notification[];
|
||||
|
||||
// Configurações
|
||||
settings: AppSettings;
|
||||
|
||||
// Filtros e estado de navegação
|
||||
filters: {
|
||||
users: Record<string, any>;
|
||||
obras: Record<string, any>;
|
||||
tasks: Record<string, any>;
|
||||
rdos: Record<string, any>;
|
||||
};
|
||||
|
||||
// Ações para conectividade
|
||||
setOnline: (online: boolean) => void;
|
||||
setConnectivity: (online: boolean) => void;
|
||||
setSyncing: (syncing: boolean) => void;
|
||||
setLastSync: (timestamp: string) => void;
|
||||
setSyncError: (error: string | null) => void;
|
||||
|
||||
// Ações para UI
|
||||
setLoading: (loading: boolean) => void;
|
||||
setSidebarCollapsed: (collapsed: boolean) => void;
|
||||
setCurrentView: (view: string) => void;
|
||||
|
||||
// Ações para notificações
|
||||
addNotification: (notification: Omit<Notification, 'id' | 'timestamp' | 'read'>) => void;
|
||||
removeNotification: (id: string) => void;
|
||||
markNotificationAsRead: (id: string) => void;
|
||||
clearNotifications: () => void;
|
||||
|
||||
// Ações para configurações
|
||||
updateSettings: (settings: Partial<AppSettings>) => void;
|
||||
resetSettings: () => void;
|
||||
|
||||
// Ações para filtros
|
||||
setFilter: (entity: keyof AppState['filters'], filters: Record<string, any>) => void;
|
||||
clearFilters: (entity?: keyof AppState['filters']) => void;
|
||||
|
||||
// Utilitários
|
||||
initializeApp: () => void;
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
const defaultSettings: AppSettings = {
|
||||
theme: 'system',
|
||||
language: 'pt-BR',
|
||||
autoSync: true,
|
||||
syncInterval: 5,
|
||||
offlineMode: false,
|
||||
notifications: {
|
||||
push: true,
|
||||
email: false,
|
||||
sound: true,
|
||||
},
|
||||
display: {
|
||||
density: 'comfortable',
|
||||
animations: true,
|
||||
reducedMotion: false,
|
||||
},
|
||||
};
|
||||
|
||||
const initialState = {
|
||||
isOnline: navigator.onLine,
|
||||
isSyncing: false,
|
||||
lastSync: null,
|
||||
syncError: null,
|
||||
isLoading: false,
|
||||
sidebarCollapsed: false,
|
||||
currentView: 'dashboard',
|
||||
notifications: [],
|
||||
settings: defaultSettings,
|
||||
filters: {
|
||||
users: {},
|
||||
obras: {},
|
||||
tasks: {},
|
||||
rdos: {},
|
||||
},
|
||||
};
|
||||
|
||||
export const useAppStateStore = create<AppState>()(
|
||||
devtools(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
...initialState,
|
||||
|
||||
// Ações para conectividade
|
||||
setOnline: (online) => set({ isOnline: online }, false, 'setOnline'),
|
||||
|
||||
setConnectivity: (online) => set({ isOnline: online }, false, 'setConnectivity'),
|
||||
|
||||
setSyncing: (syncing) => set({ isSyncing: syncing }, false, 'setSyncing'),
|
||||
|
||||
setLastSync: (timestamp) => set({ lastSync: timestamp }, false, 'setLastSync'),
|
||||
|
||||
setSyncError: (error) => set({ syncError: error }, false, 'setSyncError'),
|
||||
|
||||
// Ações para UI
|
||||
setLoading: (loading) => set({ isLoading: loading }, false, 'setLoading'),
|
||||
|
||||
setSidebarCollapsed: (collapsed) => set({ sidebarCollapsed: collapsed }, false, 'setSidebarCollapsed'),
|
||||
|
||||
setCurrentView: (view) => set({ currentView: view }, false, 'setCurrentView'),
|
||||
|
||||
// Ações para notificações
|
||||
addNotification: (notification) => {
|
||||
const newNotification: Notification = {
|
||||
...notification,
|
||||
id: crypto.randomUUID(),
|
||||
timestamp: new Date().toISOString(),
|
||||
read: false,
|
||||
};
|
||||
|
||||
set(
|
||||
(state) => ({
|
||||
notifications: [newNotification, ...state.notifications].slice(0, 50), // Manter apenas 50 notificações
|
||||
}),
|
||||
false,
|
||||
'addNotification'
|
||||
);
|
||||
},
|
||||
|
||||
removeNotification: (id) => {
|
||||
set(
|
||||
(state) => ({
|
||||
notifications: state.notifications.filter(n => n.id !== id),
|
||||
}),
|
||||
false,
|
||||
'removeNotification'
|
||||
);
|
||||
},
|
||||
|
||||
markNotificationAsRead: (id) => {
|
||||
set(
|
||||
(state) => ({
|
||||
notifications: state.notifications.map(n =>
|
||||
n.id === id ? { ...n, read: true } : n
|
||||
),
|
||||
}),
|
||||
false,
|
||||
'markNotificationAsRead'
|
||||
);
|
||||
},
|
||||
|
||||
clearNotifications: () => set({ notifications: [] }, false, 'clearNotifications'),
|
||||
|
||||
// Ações para configurações
|
||||
updateSettings: (newSettings) => {
|
||||
set(
|
||||
(state) => ({
|
||||
settings: { ...state.settings, ...newSettings },
|
||||
}),
|
||||
false,
|
||||
'updateSettings'
|
||||
);
|
||||
},
|
||||
|
||||
resetSettings: () => set({ settings: defaultSettings }, false, 'resetSettings'),
|
||||
|
||||
// Ações para filtros
|
||||
setFilter: (entity, filters) => {
|
||||
set(
|
||||
(state) => ({
|
||||
filters: {
|
||||
...state.filters,
|
||||
[entity]: filters,
|
||||
},
|
||||
}),
|
||||
false,
|
||||
'setFilter'
|
||||
);
|
||||
},
|
||||
|
||||
clearFilters: (entity) => {
|
||||
if (entity) {
|
||||
set(
|
||||
(state) => ({
|
||||
filters: {
|
||||
...state.filters,
|
||||
[entity]: {},
|
||||
},
|
||||
}),
|
||||
false,
|
||||
'clearFilter'
|
||||
);
|
||||
} else {
|
||||
set(
|
||||
{
|
||||
filters: {
|
||||
users: {},
|
||||
obras: {},
|
||||
tasks: {},
|
||||
rdos: {},
|
||||
},
|
||||
},
|
||||
false,
|
||||
'clearAllFilters'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// Utilitários
|
||||
initializeApp: () => {
|
||||
// Inicializar estado da aplicação
|
||||
set({
|
||||
isOnline: navigator.onLine,
|
||||
isLoading: false,
|
||||
lastSync: null,
|
||||
syncError: null
|
||||
}, false, 'initializeApp');
|
||||
},
|
||||
|
||||
reset: () => set(initialState, false, 'reset'),
|
||||
}),
|
||||
{
|
||||
name: 'app-state-store',
|
||||
partialize: (state) => ({
|
||||
settings: state.settings,
|
||||
sidebarCollapsed: state.sidebarCollapsed,
|
||||
filters: state.filters,
|
||||
}),
|
||||
}
|
||||
),
|
||||
{
|
||||
name: 'app-state-store',
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Seletores otimizados
|
||||
export const useIsOnline = () => useAppStateStore((state) => state.isOnline);
|
||||
export const useIsSyncing = () => useAppStateStore((state) => state.isSyncing);
|
||||
export const useIsLoading = () => useAppStateStore((state) => state.isLoading);
|
||||
export const useTheme = () => useAppStateStore((state) => state.settings.theme);
|
||||
export const useLanguage = () => useAppStateStore((state) => state.settings.language);
|
||||
export const useNotifications = () => useAppStateStore((state) => state.notifications);
|
||||
export const useUnreadNotifications = () => useAppStateStore((state) =>
|
||||
state.notifications.filter(n => !n.read)
|
||||
);
|
||||
export const useSettings = () => useAppStateStore((state) => state.settings);
|
||||
export const useSidebarCollapsed = () => useAppStateStore((state) => state.sidebarCollapsed);
|
||||
export const useCurrentView = () => useAppStateStore((state) => state.currentView);
|
||||
export const useFilters = (entity: keyof AppState['filters']) =>
|
||||
useAppStateStore((state) => state.filters[entity]);
|
||||
|
||||
// Configurar listeners para eventos do sistema
|
||||
if (typeof window !== 'undefined') {
|
||||
// Listener para mudanças de conectividade
|
||||
window.addEventListener('online', () => {
|
||||
useAppStateStore.getState().setOnline(true);
|
||||
});
|
||||
|
||||
window.addEventListener('offline', () => {
|
||||
useAppStateStore.getState().setOnline(false);
|
||||
});
|
||||
|
||||
// Listener para mudanças de tema do sistema
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
mediaQuery.addEventListener('change', () => {
|
||||
// Trigger re-render se o tema for 'system'
|
||||
const { settings } = useAppStateStore.getState();
|
||||
if (settings.theme === 'system') {
|
||||
// Force update para aplicar o novo tema
|
||||
useAppStateStore.getState().updateSettings({ theme: 'system' });
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user