233 lines
5.1 KiB
JavaScript
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');
|
|
}
|
|
}
|
|
});
|