create form and modal components, update datatable persistant filtering
This commit is contained in:
parent
b70e08026d
commit
8d9bb81fe2
23 changed files with 3502 additions and 74 deletions
90
frontend/src/stores/filters.js
Normal file
90
frontend/src/stores/filters.js
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { FilterMatchMode } from "@primevue/core";
|
||||
|
||||
export const useFiltersStore = defineStore("filters", {
|
||||
state: () => ({
|
||||
// Store filters by table/component name
|
||||
tableFilters: {
|
||||
clients: {
|
||||
fullName: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
},
|
||||
jobs: {
|
||||
customer: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
jobId: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
},
|
||||
timesheets: {
|
||||
employee: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
customer: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
},
|
||||
warranties: {
|
||||
customer: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
warrantyId: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
address: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
assignedTechnician: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
},
|
||||
routes: {
|
||||
technician: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
routeId: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
}
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
// Generic method to get filters for a specific table
|
||||
getTableFilters(tableName) {
|
||||
return this.tableFilters[tableName] || {};
|
||||
},
|
||||
|
||||
// Generic method to update a specific filter
|
||||
updateTableFilter(tableName, fieldName, value, matchMode = null) {
|
||||
if (!this.tableFilters[tableName]) {
|
||||
this.tableFilters[tableName] = {};
|
||||
}
|
||||
if (!this.tableFilters[tableName][fieldName]) {
|
||||
this.tableFilters[tableName][fieldName] = {
|
||||
value: null,
|
||||
matchMode: FilterMatchMode.CONTAINS
|
||||
};
|
||||
}
|
||||
this.tableFilters[tableName][fieldName].value = value;
|
||||
// Update match mode if provided
|
||||
if (matchMode) {
|
||||
this.tableFilters[tableName][fieldName].matchMode = matchMode;
|
||||
}
|
||||
},
|
||||
|
||||
// Method to clear all filters for a table
|
||||
clearTableFilters(tableName) {
|
||||
if (this.tableFilters[tableName]) {
|
||||
Object.keys(this.tableFilters[tableName]).forEach(key => {
|
||||
this.tableFilters[tableName][key].value = null;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Method to initialize filters for a table if they don't exist
|
||||
initializeTableFilters(tableName, columns) {
|
||||
if (!this.tableFilters[tableName]) {
|
||||
this.tableFilters[tableName] = {};
|
||||
}
|
||||
|
||||
columns.forEach(column => {
|
||||
if (column.filterable && !this.tableFilters[tableName][column.fieldName]) {
|
||||
this.tableFilters[tableName][column.fieldName] = {
|
||||
value: null,
|
||||
matchMode: FilterMatchMode.CONTAINS
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Legacy method for backward compatibility
|
||||
setClientNameFilter(filterValue) {
|
||||
this.updateTableFilter('clients', 'fullName', filterValue);
|
||||
},
|
||||
|
||||
// Getter for legacy compatibility
|
||||
get clientNameFilter() {
|
||||
return this.tableFilters?.clients?.fullName?.value || "";
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
@ -1,36 +1,232 @@
|
|||
import { defineStore } from "pinia";
|
||||
|
||||
export const useModalsStore = defineStore("modals", {
|
||||
export const useModalStore = defineStore("modal", {
|
||||
state: () => ({
|
||||
isCreateClientOpen: false,
|
||||
isCreateInvoiceOpen: false,
|
||||
isCreateJobOpen: false,
|
||||
isCreateEstimateOpen: false,
|
||||
// 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
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
openCreateClient() {
|
||||
this.isCreateClientOpen = true;
|
||||
|
||||
getters: {
|
||||
// Check if any modal is open
|
||||
hasOpenModal: (state) => {
|
||||
return Object.values(state.modals).some(modal => modal.isOpen);
|
||||
},
|
||||
closeCreateClient() {
|
||||
this.isCreateClientOpen = false;
|
||||
|
||||
// Get modal by ID
|
||||
getModal: (state) => (modalId) => {
|
||||
return state.modals[modalId] || null;
|
||||
},
|
||||
openCreateInvoice() {
|
||||
this.isCreateInvoiceOpen = true;
|
||||
|
||||
// Check if specific modal is open
|
||||
isModalOpen: (state) => (modalId) => {
|
||||
return state.modals[modalId]?.isOpen || false;
|
||||
},
|
||||
closeCreateInvoice() {
|
||||
this.isCreateInvoiceOpen = false;
|
||||
},
|
||||
openCreateJob() {
|
||||
this.isCreateJobOpen = true;
|
||||
},
|
||||
closeCreateJob() {
|
||||
this.isCreateJobOpen = false;
|
||||
},
|
||||
openCreateEstimate() {
|
||||
this.isCreateEstimateOpen = true;
|
||||
},
|
||||
closeCreateEstimate() {
|
||||
this.isCreateEstimateOpen = 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');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
import { defineStore } from "pinia";
|
||||
|
||||
export const useUserStore = defineStore("user", {
|
||||
state: () => ({
|
||||
username: "",
|
||||
roles: [],
|
||||
}),
|
||||
actions: {
|
||||
check_permission(role) {
|
||||
if (this.roles.includes(role)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue