233 lines
5.1 KiB
JavaScript

import { defineStore } from "pinia";
export const useModalStore = defineStore("modal", {
state: () => ({
// Dynamic modal registry - can handle any number of modals
modals: {},
// Stack for modal layering (optional)
modalStack: [],
// Component registry for dynamic modals
registeredComponents: {},
// Global modal configuration
globalConfig: {
closeOnEscape: true,
closeOnOutsideClick: true,
preventBodyScroll: true
}
}),
getters: {
// Check if any modal is open
hasOpenModal: (state) => {
return Object.values(state.modals).some(modal => modal.isOpen);
},
// Get modal by ID
getModal: (state) => (modalId) => {
return state.modals[modalId] || null;
},
// Check if specific modal is open
isModalOpen: (state) => (modalId) => {
return state.modals[modalId]?.isOpen || false;
},
// Get modal data
getModalData: (state) => (modalId) => {
return state.modals[modalId]?.data || null;
},
// Get the topmost modal in stack
getTopModal: (state) => {
if (state.modalStack.length === 0) return null;
const topModalId = state.modalStack[state.modalStack.length - 1];
return state.modals[topModalId];
}
},
actions: {
// Register a modal component for dynamic loading
registerModalComponent(modalId, component) {
this.registeredComponents[modalId] = component;
},
// Initialize a modal (register it in the store)
initializeModal(modalId, config = {}) {
if (!this.modals[modalId]) {
this.modals[modalId] = {
id: modalId,
isOpen: false,
data: null,
config: {
...this.globalConfig,
...config
},
history: []
};
}
},
// Open a modal with optional data
openModal(modalId, data = null, config = {}) {
// Initialize modal if it doesn't exist
this.initializeModal(modalId, config);
// Close other modals if exclusive mode (default behavior)
if (config.exclusive !== false) {
this.closeAllModals();
}
// Set modal state
this.modals[modalId].isOpen = true;
this.modals[modalId].data = data;
this.modals[modalId].config = {
...this.modals[modalId].config,
...config
};
// Add to stack
if (!this.modalStack.includes(modalId)) {
this.modalStack.push(modalId);
}
// Track opening in history
this.modals[modalId].history.push({
action: 'opened',
timestamp: new Date(),
data: data
});
},
// Close a specific modal
closeModal(modalId) {
if (this.modals[modalId]) {
this.modals[modalId].isOpen = false;
this.modals[modalId].data = null;
// Remove from stack
const index = this.modalStack.indexOf(modalId);
if (index > -1) {
this.modalStack.splice(index, 1);
}
// Track closing in history
this.modals[modalId].history.push({
action: 'closed',
timestamp: new Date()
});
}
},
// Toggle a modal
toggleModal(modalId, data = null, config = {}) {
if (this.isModalOpen(modalId)) {
this.closeModal(modalId);
} else {
this.openModal(modalId, data, config);
}
},
// Close all modals
closeAllModals() {
Object.keys(this.modals).forEach(modalId => {
if (this.modals[modalId].isOpen) {
this.closeModal(modalId);
}
});
this.modalStack = [];
},
// Close the topmost modal
closeTopModal() {
if (this.modalStack.length > 0) {
const topModalId = this.modalStack[this.modalStack.length - 1];
this.closeModal(topModalId);
}
},
// Update modal data without opening/closing
updateModalData(modalId, data) {
if (this.modals[modalId]) {
this.modals[modalId].data = data;
}
},
// Update modal configuration
updateModalConfig(modalId, config) {
if (this.modals[modalId]) {
this.modals[modalId].config = {
...this.modals[modalId].config,
...config
};
}
},
// Remove a modal from the store (cleanup)
removeModal(modalId) {
if (this.modals[modalId]) {
this.closeModal(modalId);
delete this.modals[modalId];
}
},
// Convenience methods for common modals
// Add your specific modal methods here
// Example: Edit User Modal
openEditUser(userData = null) {
this.openModal('editUser', userData, {
closeOnEscape: true,
closeOnOutsideClick: false
});
},
closeEditUser() {
this.closeModal('editUser');
},
// Example: Confirmation Modal
openConfirmation(message, onConfirm, onCancel = null) {
this.openModal('confirmation', {
message,
onConfirm,
onCancel
}, {
closeOnEscape: false,
closeOnOutsideClick: false
});
},
closeConfirmation() {
this.closeModal('confirmation');
},
// Example: Image Gallery Modal
openImageGallery(images, currentIndex = 0) {
this.openModal('imageGallery', {
images,
currentIndex
}, {
closeOnEscape: true,
exclusive: true
});
},
closeImageGallery() {
this.closeModal('imageGallery');
},
// Create Client Modal
openCreateClient(clientData = null) {
this.openModal('createClient', clientData, {
closeOnEscape: true,
closeOnOutsideClick: true,
exclusive: true
});
},
closeCreateClient() {
this.closeModal('createClient');
}
}
});