246 lines
5.9 KiB
TypeScript

import { defineStore } from "pinia";
import { ref, computed } from "vue";
import InvoiceService, {
Invoice,
CreateInvoicePayload,
UpdateInvoicePayload,
} from "@/services/invoice";
export const useInvoiceStore = defineStore("invoice", () => {
// State
const invoices = ref<Invoice[]>([]);
const currentInvoice = ref<Invoice | null>(null);
const loading = ref(false);
const error = ref<string | null>(null);
// Pagination state
const pagination = ref({
current_page: 1,
last_page: 1,
per_page: 10,
total: 0,
});
// Getters
const allInvoices = computed(() => invoices.value);
const isLoading = computed(() => loading.value);
const hasError = computed(() => error.value !== null);
const getError = computed(() => error.value);
const getInvoiceById = computed(() => (id: number) =>
invoices.value.find((invoice) => invoice.id === id)
);
const getPagination = computed(() => pagination.value);
// Actions
const setLoading = (isLoading: boolean) => {
loading.value = isLoading;
};
const setError = (err: string | null) => {
error.value = err;
};
const setInvoices = (newInvoices: Invoice[]) => {
invoices.value = newInvoices;
};
const setCurrentInvoice = (invoice: Invoice | null) => {
currentInvoice.value = invoice;
};
const setPagination = (meta: any) => {
if (meta) {
pagination.value = {
current_page: meta.current_page || 1,
last_page: meta.last_page || 1,
per_page: meta.per_page || 10,
total: meta.total || 0,
};
}
};
/**
* Fetch all invoices with optional pagination and filters
*/
const fetchInvoices = async (params?: {
page?: number;
per_page?: number;
search?: string;
status?: string;
client_id?: number;
}) => {
setLoading(true);
setError(null);
try {
const response = await InvoiceService.getAllInvoices(params);
setInvoices(response.data);
if (response.meta) {
setPagination(response.meta);
}
return response;
} catch (err: any) {
const errorMessage =
err.response?.data?.message || err.message || "Failed to fetch invoices";
setError(errorMessage);
throw err;
} finally {
setLoading(false);
}
};
/**
* Fetch a single invoice by ID
*/
const fetchInvoice = async (id: number) => {
setLoading(true);
setError(null);
try {
const response = await InvoiceService.getInvoice(id);
setCurrentInvoice(response.data);
return response.data;
} catch (err: any) {
const errorMessage =
err.response?.data?.message || err.message || "Failed to fetch invoice";
setError(errorMessage);
throw err;
} finally {
setLoading(false);
}
};
/**
* Create a new invoice
*/
const createInvoice = async (payload: CreateInvoicePayload) => {
setLoading(true);
setError(null);
try {
const response = await InvoiceService.createInvoice(payload);
invoices.value.push(response.data);
setCurrentInvoice(response.data);
return response.data;
} catch (err: any) {
const errorMessage =
err.response?.data?.message || err.message || "Failed to create invoice";
setError(errorMessage);
throw err;
} finally {
setLoading(false);
}
};
/**
* Create an invoice from a quote
*/
const createFromQuote = async (quoteId: number) => {
setLoading(true);
setError(null);
try {
const response = await InvoiceService.createFromQuote(quoteId);
invoices.value.push(response.data);
setCurrentInvoice(response.data);
return response.data;
} catch (err: any) {
const errorMessage =
err.response?.data?.message || err.message || "Failed to create invoice from quote";
setError(errorMessage);
throw err;
} finally {
setLoading(false);
}
};
/**
* Update an existing invoice
*/
const updateInvoice = async (payload: UpdateInvoicePayload) => {
setLoading(true);
setError(null);
try {
const response = await InvoiceService.updateInvoice(payload);
const updatedInvoice = response.data;
// Update in the invoices list
const index = invoices.value.findIndex(
(invoice) => invoice.id === updatedInvoice.id
);
if (index !== -1) {
invoices.value[index] = updatedInvoice;
}
// Update current invoice if it's the one being edited
if (currentInvoice.value && currentInvoice.value.id === updatedInvoice.id) {
setCurrentInvoice(updatedInvoice);
}
return updatedInvoice;
} catch (err: any) {
const errorMessage =
err.response?.data?.message || err.message || "Failed to update invoice";
setError(errorMessage);
throw err;
} finally {
setLoading(false);
}
};
/**
* Delete an invoice
*/
const deleteInvoice = async (id: number) => {
setLoading(true);
setError(null);
try {
const response = await InvoiceService.deleteInvoice(id);
// Remove from the invoices list
invoices.value = invoices.value.filter((invoice) => invoice.id !== id);
// Clear current invoice if it's the one being deleted
if (currentInvoice.value && currentInvoice.value.id === id) {
setCurrentInvoice(null);
}
return response;
} catch (err: any) {
const errorMessage =
err.response?.data?.message || err.message || "Failed to delete invoice";
setError(errorMessage);
throw err;
} finally {
setLoading(false);
}
};
return {
// State
invoices,
currentInvoice,
loading,
error,
pagination,
// Getters
allInvoices,
isLoading,
hasError,
getError,
getInvoiceById,
getPagination,
// Actions
fetchInvoices,
fetchInvoice,
createInvoice,
createFromQuote,
updateInvoice,
deleteInvoice,
};
});