diff --git a/thanasoft-back/database/seeders/ClientSeeder.php b/thanasoft-back/database/seeders/ClientSeeder.php new file mode 100644 index 0000000..b1fb1a6 --- /dev/null +++ b/thanasoft-back/database/seeders/ClientSeeder.php @@ -0,0 +1,48 @@ +toArray(); + + for ($i = 0; $i < 20; $i++) { + Client::create([ + 'name' => $faker->company, + 'vat_number' => 'FR' . $faker->numberBetween(10000000000, 99999999999), + 'siret' => $faker->numberBetween(10000000000000, 99999999999999), + 'email' => $faker->unique()->companyEmail, + 'phone' => $faker->phoneNumber, + + 'billing_address_line1' => $faker->streetAddress, + 'billing_address_line2' => $faker->optional()->secondaryAddress, + 'billing_postal_code' => $faker->postcode, + 'billing_city' => $faker->city, + 'billing_country_code' => 'FR', + + 'group_id' => null, // ou random si tu veux + 'notes' => $faker->optional()->sentence, + + 'is_active' => $faker->boolean(90), + 'is_parent' => false, + 'parent_id' => null, + + 'client_category_id' => $faker->numberBetween(1, 5), + + 'user_id' => 1, + + 'avatar' => null, + ]); + } + } +} \ No newline at end of file diff --git a/thanasoft-back/database/seeders/DatabaseSeeder.php b/thanasoft-back/database/seeders/DatabaseSeeder.php index 136cf75..0d7a314 100644 --- a/thanasoft-back/database/seeders/DatabaseSeeder.php +++ b/thanasoft-back/database/seeders/DatabaseSeeder.php @@ -24,5 +24,6 @@ class DatabaseSeeder extends Seeder $this->call(ProductCategorySeeder::class); $this->call(EmployeeSeeder::class); $this->call(ThanatopractitionerSeeder::class); + $this->call(ClientSeeder::class); } } diff --git a/thanasoft-front/src/components/Organism/CRM/ClientPresentation.vue b/thanasoft-front/src/components/Organism/CRM/ClientPresentation.vue index 9c1d0ff..ed68965 100644 --- a/thanasoft-front/src/components/Organism/CRM/ClientPresentation.vue +++ b/thanasoft-front/src/components/Organism/CRM/ClientPresentation.vue @@ -36,12 +36,7 @@ import { storeToRefs } from "pinia"; const router = useRouter(); const clientStore = useClientStore(); -// Use storeToRefs to keep reactivity for pagination if it was passed as a prop, -// but since we are using the store directly for actions, we can also extract it here if needed. -// However, the common pattern is that the parent view passes the data. -// Let's check where clientData comes from. It comes from props. - -const emit = defineEmits(["pushDetails"]); +const emit = defineEmits(["pushDetails", "deleteClient"]); const props = defineProps({ clientData: { @@ -74,7 +69,10 @@ const deleteClient = (client) => { }; const onPageChange = (page) => { - clientStore.fetchClients({ page: page, per_page: props.pagination.per_page }); + clientStore.fetchClients({ + page, + per_page: props.pagination.per_page, + }); }; const onPerPageChange = (perPage) => { @@ -84,7 +82,6 @@ const onPerPageChange = (perPage) => { const onSearch = (query) => { clientStore.fetchClients({ page: 1, - per_page: props.pagination.per_page, search: query, }); }; diff --git a/thanasoft-front/src/components/molecules/Tables/CRM/ClientTable.vue b/thanasoft-front/src/components/molecules/Tables/CRM/ClientTable.vue index 904cc71..7d48535 100644 --- a/thanasoft-front/src/components/molecules/Tables/CRM/ClientTable.vue +++ b/thanasoft-front/src/components/molecules/Tables/CRM/ClientTable.vue @@ -1,101 +1,54 @@ - - diff --git a/thanasoft-front/src/components/molecules/client/ClientInfoTab.vue b/thanasoft-front/src/components/molecules/client/ClientInfoTab.vue index 96b47cc..c19cf35 100644 --- a/thanasoft-front/src/components/molecules/client/ClientInfoTab.vue +++ b/thanasoft-front/src/components/molecules/client/ClientInfoTab.vue @@ -244,7 +244,7 @@ maxlength="255" />

- {{ client.billing_address_line1 || "-" }} + {{ client.billing_address?.line1 || "-" }}

- {{ client.billing_address_line2 || "-" }} + {{ client.billing_address?.line2 || "-" }}

- {{ client.billing_postal_code || "-" }} + {{ client.billing_address?.postal_code || "-" }}

- {{ client.billing_city || "-" }} + {{ client.billing_address?.city || "-" }}

{{ errors.billing_city }} @@ -325,7 +325,7 @@ maxlength="2" />

- {{ client.billing_country_code || "-" }} + {{ client.billing_address?.country_code || "-" }}

{ + const billingAddress = props.client.billing_address || {}; + isEditing.value = true; Object.assign(formData, { name: props.client.name || "", @@ -419,11 +421,11 @@ const startEdit = () => { siret: props.client.siret || "", email: props.client.email || "", phone: props.client.phone || "", - billing_address_line1: props.client.billing_address_line1 || "", - billing_address_line2: props.client.billing_address_line2 || "", - billing_postal_code: props.client.billing_postal_code || "", - billing_city: props.client.billing_city || "", - billing_country_code: props.client.billing_country_code || "FR", // Valeur par défaut + billing_address_line1: billingAddress.line1 || "", + billing_address_line2: billingAddress.line2 || "", + billing_postal_code: billingAddress.postal_code || "", + billing_city: billingAddress.city || "", + billing_country_code: billingAddress.country_code || "FR", group_id: props.client.group_id || null, notes: props.client.notes || "", is_active: @@ -606,7 +608,7 @@ const saveChanges = async () => { try { isEditing.value = false; - emit("client-updated", formData); + emit("client-updated", prepareFormData()); } catch (error) { console.error("Erreur lors de la mise à jour:", error); if (error.response && error.response.data && error.response.data.errors) { diff --git a/thanasoft-front/src/stores/clientStore.ts b/thanasoft-front/src/stores/clientStore.ts index 3bfed09..1292974 100644 --- a/thanasoft-front/src/stores/clientStore.ts +++ b/thanasoft-front/src/stores/clientStore.ts @@ -6,7 +6,6 @@ import type { Client, CreateClientPayload, UpdateClientPayload, - ClientListResponse, } from "@/services/client"; import { Contact } from "@/services/contact"; @@ -18,6 +17,16 @@ export const useClientStore = defineStore("client", () => { const error = ref(null); const searchResults = ref([]); const contacts_client = ref([]); + const filters = ref<{ + page: number; + per_page: number; + search?: string; + is_active?: boolean; + group_id?: number; + }>({ + page: 1, + per_page: 10, + }); // Pagination state const pagination = ref({ @@ -25,6 +34,8 @@ export const useClientStore = defineStore("client", () => { last_page: 1, per_page: 10, total: 0, + from: 0, + to: 0, }); // Getters @@ -80,10 +91,33 @@ export const useClientStore = defineStore("client", () => { last_page: Number(getValue(meta.last_page)) || 1, per_page: Number(getValue(meta.per_page)) || 10, total: Number(getValue(meta.total)) || 0, + from: Number(getValue(meta.from)) || 0, + to: Number(getValue(meta.to)) || 0, + }; + + filters.value = { + ...filters.value, + page: pagination.value.current_page, + per_page: pagination.value.per_page, }; } }; + const setFilters = (params?: { + page?: number; + per_page?: number; + search?: string; + is_active?: boolean; + group_id?: number; + }) => { + filters.value = { + ...filters.value, + ...params, + page: params?.page ?? filters.value.page ?? 1, + per_page: params?.per_page ?? filters.value.per_page ?? 10, + }; + }; + /** * Fetch all clients with optional pagination and filters */ @@ -98,7 +132,21 @@ export const useClientStore = defineStore("client", () => { setError(null); try { - const response = await ClientService.getAllClients(params); + setFilters(params); + + const requestParams = Object.fromEntries( + Object.entries(filters.value).filter( + ([, value]) => value !== undefined && value !== null && value !== "" + ) + ) as { + page?: number; + per_page?: number; + search?: string; + is_active?: boolean; + group_id?: number; + }; + + const response = await ClientService.getAllClients(requestParams); setClients(response.data); if (response.meta) { setPagination(response.meta); @@ -166,7 +214,6 @@ export const useClientStore = defineStore("client", () => { setError(null); try { - const response = await ClientService.updateClient(payload); const updatedClient = response.data; @@ -227,7 +274,6 @@ export const useClientStore = defineStore("client", () => { * Search clients */ const searchClients = async (query: string, exactMatch: boolean = false) => { - setLoading(true); error.value = null; @@ -375,6 +421,12 @@ export const useClientStore = defineStore("client", () => { last_page: 1, per_page: 10, total: 0, + from: 0, + to: 0, + }; + filters.value = { + page: 1, + per_page: 10, }; }; @@ -394,6 +446,7 @@ export const useClientStore = defineStore("client", () => { getError, getClientById, getPagination, + filters, // Actions fetchClients, diff --git a/thanasoft-front/src/views/pages/CRM/Clients.vue b/thanasoft-front/src/views/pages/CRM/Clients.vue index 319a6ba..24c24c6 100644 --- a/thanasoft-front/src/views/pages/CRM/Clients.vue +++ b/thanasoft-front/src/views/pages/CRM/Clients.vue @@ -4,16 +4,19 @@ :loading-data="clientStore.loading" :pagination="clientStore.getPagination" @push-details="goDetails" + @delete-client="handleDeleteClient" />