Skip to content

Commit 272ecb2

Browse files
committed
Companies pages migrate to react
1 parent 30806b6 commit 272ecb2

19 files changed

Lines changed: 2031 additions & 230 deletions

app/Http/Controllers/Companies/AddressesController.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Http\Controllers\Companies;
44

5+
use Illuminate\Http\Request;
56
use App\Models\Companies\CompaniesAddresses;
67
use App\Http\Requests\Companies\StoreAdressRequest;
78
use App\Http\Requests\Companies\UpdateAdressRequest;
@@ -20,6 +21,54 @@ public function store(StoreAdressRequest $request)
2021
return redirect()->route('companies.show', ['id' => $request->companies_id])->with('success', 'Successfully created adress');
2122
}
2223

24+
public function storeJson(StoreAdressRequest $request)
25+
{
26+
$address = CompaniesAddresses::create($request->validated());
27+
$address->default = $request->boolean('default');
28+
$address->save();
29+
30+
if ($address->default) {
31+
CompaniesAddresses::where('companies_id', $address->companies_id)
32+
->where('id', '!=', $address->id)
33+
->update(['default' => 0]);
34+
}
35+
36+
return response()->json($this->formatAddress($address), 201);
37+
}
38+
39+
public function updateJson(UpdateAdressRequest $request, CompaniesAddresses $address)
40+
{
41+
$address->update($request->validated());
42+
$address->default = $request->boolean('default');
43+
$address->save();
44+
45+
if ($address->default) {
46+
CompaniesAddresses::where('companies_id', $address->companies_id)
47+
->where('id', '!=', $address->id)
48+
->update(['default' => 0]);
49+
}
50+
51+
return response()->json($this->formatAddress($address));
52+
}
53+
54+
private function formatAddress(CompaniesAddresses $a): array
55+
{
56+
return [
57+
'id' => $a->id,
58+
'companies_id' => $a->companies_id,
59+
'ordre' => $a->ordre,
60+
'label' => $a->label,
61+
'adress' => $a->adress,
62+
'zipcode' => $a->zipcode,
63+
'city' => $a->city,
64+
'province' => $a->province,
65+
'country' => $a->country,
66+
'number' => $a->number,
67+
'mail' => $a->mail,
68+
'default' => (bool) $a->default,
69+
];
70+
}
71+
2372
/**
2473
* Update the specified address in storage.
2574
*

app/Http/Controllers/Companies/CompaniesController.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use App\Models\Accounting\AccountingDelivery;
2727
use App\Models\Accounting\AccountingPaymentMethod;
2828
use App\Http\Requests\Companies\UpdateCompanieRequest;
29+
use App\Http\Requests\Companies\UpdateCompanieJsonRequest;
2930
use App\Models\Accounting\AccountingPaymentConditions;
3031
use Carbon\Carbon;
3132
use App\Models\Methods\MethodsServices;
@@ -318,6 +319,38 @@ public function show(Companies $id)
318319
'purchasesForEvaluation',));
319320
}
320321

322+
/**
323+
* AJAX update — returns JSON, no redirect.
324+
*/
325+
public function updateJson(UpdateCompanieJsonRequest $request, Companies $company)
326+
{
327+
$vatNumber = $request->input('intra_community_vat');
328+
$vatWarning = null;
329+
330+
if ($vatNumber) {
331+
$countryCode = substr($vatNumber, 0, 2);
332+
$vatCode = substr($vatNumber, 2);
333+
try {
334+
$isValid = $this->companyService->validateVatNumber($countryCode, $vatCode);
335+
if (!$isValid) {
336+
$vatWarning = 'Le numéro de TVA est invalide, mais les autres informations ont été mises à jour.';
337+
}
338+
} catch (\Exception $e) {
339+
$vatWarning = 'Le service de validation de la TVA est indisponible. La fiche a été mise à jour sans validation du numéro de TVA.';
340+
}
341+
}
342+
343+
$company->update($request->validated());
344+
$company->active = $request->boolean('active');
345+
$company->quoted_delivery_note = $request->boolean('quoted_delivery_note');
346+
$company->save();
347+
348+
return response()->json([
349+
'success' => true,
350+
'warning' => $vatWarning,
351+
]);
352+
}
353+
321354
/**
322355
* @param $id
323356
* @return \Illuminate\Http\RedirectResponse

app/Http/Controllers/Companies/ContactsController.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Http\Controllers\Companies;
44

5+
use Illuminate\Http\Request;
56
use App\Models\Companies\CompaniesContacts;
67
use App\Http\Requests\Companies\StoreContactRequest;
78
use App\Http\Requests\Companies\UpdateContactRequest;
@@ -18,6 +19,53 @@ public function store(StoreContactRequest $request)
1819
return redirect()->route('companies.show', ['id' => $request->companies_id])->with('success', 'Successfully created contact');
1920
}
2021

22+
public function storeJson(StoreContactRequest $request)
23+
{
24+
$contact = CompaniesContacts::create($request->validated());
25+
$contact->default = $request->boolean('default');
26+
$contact->save();
27+
28+
if ($contact->default) {
29+
CompaniesContacts::where('companies_id', $contact->companies_id)
30+
->where('id', '!=', $contact->id)
31+
->update(['default' => 0]);
32+
}
33+
34+
return response()->json($this->formatContact($contact), 201);
35+
}
36+
37+
public function updateJson(UpdateContactRequest $request, CompaniesContacts $contact)
38+
{
39+
$contact->update($request->validated());
40+
$contact->default = $request->boolean('default');
41+
$contact->save();
42+
43+
if ($contact->default) {
44+
CompaniesContacts::where('companies_id', $contact->companies_id)
45+
->where('id', '!=', $contact->id)
46+
->update(['default' => 0]);
47+
}
48+
49+
return response()->json($this->formatContact($contact));
50+
}
51+
52+
private function formatContact(CompaniesContacts $c): array
53+
{
54+
return [
55+
'id' => $c->id,
56+
'companies_id' => $c->companies_id,
57+
'ordre' => $c->ordre,
58+
'civility' => $c->civility,
59+
'first_name' => $c->first_name,
60+
'name' => $c->name,
61+
'function' => $c->function,
62+
'number' => $c->number,
63+
'mobile' => $c->mobile,
64+
'mail' => $c->mail,
65+
'default' => (bool) $c->default,
66+
];
67+
}
68+
2169
/**
2270
* @param \Illuminate\Http\Request $request
2371
* @return \Illuminate\Http\RedirectResponse

app/Http/Controllers/Workflow/InvoicesController.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public function listJson(Request $request)
105105
$statuses = array_filter(array_map('intval', (array) $request->get('statuses', [])));
106106
$sortField = $request->get('sort', 'created_at');
107107
$sortAsc = $request->boolean('asc', false);
108+
$companyId = $request->get('company_id');
108109

109110
$allowed = ['code', 'label', 'created_at', 'due_date', 'statu', 'companie', 'contact', 'invoice_lines_count', 'total_amount'];
110111
if (!in_array($sortField, $allowed)) {
@@ -118,7 +119,8 @@ public function listJson(Request $request)
118119
->selectRaw("invoices.*, {$totalSub} as total_amount")
119120
->with(['companie:id,label,code', 'contact:id,first_name,name'])
120121
->when($search, fn ($q) => $q->where('label', 'like', '%'.$search.'%'))
121-
->when($statuses, fn ($q) => $q->whereIn('statu', $statuses));
122+
->when($statuses, fn ($q) => $q->whereIn('statu', $statuses))
123+
->when($companyId, fn ($q) => $q->where('companies_id', $companyId));
122124

123125
match ($sortField) {
124126
'companie' => $query->orderByRaw("(SELECT label FROM companies WHERE companies.id = invoices.companies_id) {$dir}"),
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace App\Http\Requests\Companies;
4+
5+
class UpdateCompanieJsonRequest extends UpdateCompanieRequest
6+
{
7+
/**
8+
* Override rules for JSON endpoint: fields that are required in the Blade
9+
* form can be null here (e.g. a company without an assigned user).
10+
*/
11+
public function rules(): array
12+
{
13+
return array_merge(parent::rules(), [
14+
'user_id' => 'nullable',
15+
'statu_customer' => 'nullable',
16+
'statu_supplier' => 'nullable',
17+
'recept_controle' => 'nullable',
18+
'delivery_constraint' => 'nullable|numeric',
19+
'tolerance_days' => 'nullable|numeric',
20+
]);
21+
}
22+
}

resources/js/app.js

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import ProductsIndex from './components/ProductsIndex.jsx';
1616
import QuoteLinesIndex from './components/QuoteLinesIndex.jsx';
1717
import OrderLinesIndex from './components/OrderLinesIndex.jsx';
1818
import SetupWizard from './components/SetupWizard.jsx';
19+
import CompanyDashboard from './components/CompanyDashboard.jsx';
20+
import CompanyForm from './components/CompanyForm.jsx';
21+
import CompanyAddresses from './components/CompanyAddresses.jsx';
22+
import CompanyContacts from './components/CompanyContacts.jsx';
1923
// livewire-sortable ne doit être chargé que sur les pages qui embarquent Livewire
2024
document.addEventListener('livewire:init', () => {
2125
import('livewire-sortable');
@@ -208,11 +212,12 @@ function mountInvoicesIndex() {
208212

209213
createRoot(element).render(
210214
React.createElement(InvoicesIndex, {
211-
kpi: parse('kpi') ?? {},
212-
chartData: parse('chart') ?? {},
213-
topClients: parse('topClients') ?? [],
214-
endpoints: parse('endpoints') ?? {},
215-
trans: parse('trans') ?? {},
215+
kpi: parse('kpi') ?? {},
216+
chartData: parse('chart') ?? {},
217+
topClients: parse('topClients') ?? [],
218+
endpoints: parse('endpoints') ?? {},
219+
trans: parse('trans') ?? {},
220+
companieId: element.dataset.companieId ? parseInt(element.dataset.companieId, 10) : null,
216221
})
217222
);
218223
}
@@ -253,6 +258,79 @@ function mountCompaniesIndex() {
253258
);
254259
}
255260

261+
function mountCompanyForm() {
262+
const element = document.getElementById('company-form-app');
263+
if (!element) return;
264+
265+
const parse = (attr) => {
266+
try { return JSON.parse(element.dataset[attr] ?? 'null'); } catch { return null; }
267+
};
268+
269+
createRoot(element).render(
270+
React.createElement(CompanyForm, {
271+
company: parse('company') ?? {},
272+
users: parse('users') ?? [],
273+
endpoint: element.dataset.endpoint ?? '',
274+
trans: parse('trans') ?? {},
275+
})
276+
);
277+
}
278+
279+
function mountCompanyDashboard() {
280+
const element = document.getElementById('company-dashboard-app');
281+
if (!element) return;
282+
283+
const parse = (attr) => {
284+
try { return JSON.parse(element.dataset[attr] ?? 'null'); } catch { return null; }
285+
};
286+
287+
createRoot(element).render(
288+
React.createElement(CompanyDashboard, {
289+
kpi: parse('kpi') ?? {},
290+
charts: parse('charts') ?? {},
291+
trans: parse('trans') ?? {},
292+
})
293+
);
294+
}
295+
296+
function mountCompanyAddresses() {
297+
const element = document.getElementById('company-addresses-app');
298+
if (!element) return;
299+
300+
const parse = (attr) => {
301+
try { return JSON.parse(element.dataset[attr] ?? 'null'); } catch { return null; }
302+
};
303+
304+
createRoot(element).render(
305+
React.createElement(CompanyAddresses, {
306+
initialAddresses: parse('addresses') ?? [],
307+
storeUrl: element.dataset.storeUrl ?? '',
308+
updateBaseUrl: element.dataset.updateBaseUrl ?? '',
309+
companieId: element.dataset.companieId ? parseInt(element.dataset.companieId, 10) : null,
310+
trans: parse('trans') ?? {},
311+
})
312+
);
313+
}
314+
315+
function mountCompanyContacts() {
316+
const element = document.getElementById('company-contacts-app');
317+
if (!element) return;
318+
319+
const parse = (attr) => {
320+
try { return JSON.parse(element.dataset[attr] ?? 'null'); } catch { return null; }
321+
};
322+
323+
createRoot(element).render(
324+
React.createElement(CompanyContacts, {
325+
initialContacts: parse('contacts') ?? [],
326+
storeUrl: element.dataset.storeUrl ?? '',
327+
updateBaseUrl: element.dataset.updateBaseUrl ?? '',
328+
companieId: element.dataset.companieId ? parseInt(element.dataset.companieId, 10) : null,
329+
trans: parse('trans') ?? {},
330+
})
331+
);
332+
}
333+
256334
function mountSetupWizard() {
257335
const element = document.getElementById('setup-wizard-app');
258336
if (!element) return;
@@ -270,6 +348,10 @@ function mountSetupWizard() {
270348
}
271349

272350
mountSetupWizard();
351+
mountCompanyDashboard();
352+
mountCompanyForm();
353+
mountCompanyAddresses();
354+
mountCompanyContacts();
273355
mountKanbanBoard();
274356
mountDocumentTable();
275357
mountCompaniesIndex();

0 commit comments

Comments
 (0)