diff --git a/Modules/Company/Http/Controllers/CompanyController.php b/Modules/Company/Http/Controllers/CompanyController.php
index 0880b292..10a583c1 100644
--- a/Modules/Company/Http/Controllers/CompanyController.php
+++ b/Modules/Company/Http/Controllers/CompanyController.php
@@ -18,11 +18,11 @@ class CompanyController extends Controller
{
return view('company::index', [
'companies' => Company::query()
- ->with(['address.country', 'country'])
+ ->with(['address.country'])
->withCount(['users', 'warehouses', 'licenseKeys', 'divisions'])
->latest('id')
->paginate(20),
- 'countries' => $this->countries(),
+ 'countries' => $this->countriesForSelect(),
]);
}
@@ -36,7 +36,7 @@ class CompanyController extends Controller
'status' => 'active',
'timezone' => 'Europe/London',
]),
- 'countries' => $this->countries(),
+ 'countries' => $this->countriesForSelect(),
]);
}
@@ -45,7 +45,10 @@ class CompanyController extends Controller
*/
public function store(Request $request)
{
- $company = Company::create($this->validated($request));
+ $validated = $this->validated($request);
+
+ $company = Company::create($validated['company']);
+ $this->syncAddressCountry($company, $validated['country_id']);
return redirect()
->route('platform.companies.index')
@@ -73,7 +76,7 @@ class CompanyController extends Controller
'recentUsers' => $company->users()->latest('id')->limit(5)->get(),
'recentWarehouses' => $company->warehouses()->latest('id')->limit(5)->get(),
'recentLicenseKeys' => $company->licenseKeys()->latest('id')->limit(5)->get(),
- 'countries' => Country::query()->active()->orderBy('sort_order')->orderBy('name')->get(['id', 'alpha2', 'name', 'display_name', 'common_name']),
+ 'countries' => $this->countriesForSelect(),
'companyUsers' => $company->users()->orderBy('name')->get(['id', 'name', 'email', 'company_id']),
'unassignedWarehouses' => $company->warehouses()->whereNull('division_id')->orderBy('name')->get(),
]);
@@ -85,8 +88,8 @@ class CompanyController extends Controller
public function edit(Company $company)
{
return view('company::edit', [
- 'company' => $company->loadMissing(['address.country', 'country']),
- 'countries' => $this->countries(),
+ 'company' => $company->loadMissing('address.country'),
+ 'countries' => $this->countriesForSelect(),
]);
}
@@ -95,7 +98,10 @@ class CompanyController extends Controller
*/
public function update(Request $request, Company $company)
{
- $company->update($this->validated($request, $company));
+ $validated = $this->validated($request, $company);
+
+ $company->update($validated['company']);
+ $this->syncAddressCountry($company, $validated['country_id']);
return redirect()
->route('platform.companies.show', $company)
@@ -122,20 +128,44 @@ class CompanyController extends Controller
'name' => ['required', 'string', 'max:255'],
'billing_email' => ['nullable', 'email', 'max:255'],
'status' => ['required', Rule::in(['active', 'suspended', 'inactive'])],
- 'country_id' => ['nullable', Rule::exists('countries', 'id')->where('is_active', true)],
+ 'country_id' => ['nullable', 'integer', Rule::exists('countries', 'id')],
]);
- $data['slug'] = Str::slug($data['name']);
- $data['timezone'] = $company?->timezone ?: 'Europe/London';
-
- return $data;
+ return [
+ 'company' => [
+ 'name' => $data['name'],
+ 'billing_email' => $data['billing_email'] ?? null,
+ 'status' => $data['status'],
+ 'slug' => Str::slug($data['name']),
+ 'timezone' => $company?->timezone ?: 'Europe/London',
+ ],
+ 'country_id' => $data['country_id'] ?? null,
+ ];
}
- private function countries()
+ private function countriesForSelect()
{
return Country::query()
->active()
- ->ordered()
- ->get(['id', 'alpha2', 'name', 'display_name', 'common_name', 'sort_order']);
+ ->orderByRaw("LOWER(COALESCE(NULLIF(display_name, ''), NULLIF(common_name, ''), name)) ASC")
+ ->get(['id', 'alpha2', 'name', 'display_name', 'common_name']);
+ }
+
+ private function syncAddressCountry(Company $company, ?int $countryId): void
+ {
+ if ($countryId === null) {
+ $company->address()?->delete();
+
+ return;
+ }
+
+ $company->address()->updateOrCreate(
+ [],
+ [
+ 'country_id' => $countryId,
+ 'label' => 'Registered address',
+ 'is_primary' => true,
+ ]
+ );
}
}
diff --git a/Modules/Company/Resources/views/_form.blade.php b/Modules/Company/Resources/views/_form.blade.php
index 6316cd1b..340639fe 100644
--- a/Modules/Company/Resources/views/_form.blade.php
+++ b/Modules/Company/Resources/views/_form.blade.php
@@ -1,13 +1,13 @@
@csrf
-
+
@error('name')
@@ -23,7 +23,7 @@
name="billing_email"
value="{{ old('billing_email', $company->billing_email) }}"
placeholder="billing@example.com"
- class="mt-2 w-full rounded-xl border-zinc-300 dark:border-zinc-700 dark:bg-zinc-950 dark:text-white"
+ class="mt-2 h-12 w-full rounded-xl border-zinc-300 bg-white px-4 text-sm text-zinc-900 shadow-sm outline-none transition focus:border-blue-500 focus:ring-2 focus:ring-blue-500/30 dark:border-zinc-700 dark:bg-zinc-950 dark:text-white"
>
@error('billing_email')
{{ $message }}
@@ -35,7 +35,7 @@
-
-
@@ -183,4 +212,30 @@
{{ $companies->links() }}
+
+ @push('scripts')
+
+
+
+ @endpush
diff --git a/Modules/Company/changelog.yaml b/Modules/Company/changelog.yaml
index 55cc3e18..5f29b1fe 100644
--- a/Modules/Company/changelog.yaml
+++ b/Modules/Company/changelog.yaml
@@ -1,6 +1,12 @@
-latest: 1.2.0
+latest: 1.2.1
versions:
+ - version: 1.2.1
+ date: 2026-07-07
+ changes:
+ - Replaced company country inputs with a shared Select2-enhanced dropdown populated by the Countries module.
+ - Aligned the company create forms and changed the primary create/save action to green.
+ - Stored the selected country on the company address relationship during create and update.
- version: 1.2.0
date: 2026-07-02
changes:
diff --git a/Modules/Company/module.json b/Modules/Company/module.json
index 1689228d..6c43da16 100644
--- a/Modules/Company/module.json
+++ b/Modules/Company/module.json
@@ -1,7 +1,7 @@
{
"name": "Company",
"alias": "company",
- "version": "1.2.0",
+ "version": "1.2.1",
"description": "",
"keywords": [],
"priority": 0,
diff --git a/Modules/Countries/Http/Controllers/CountriesController.php b/Modules/Countries/Http/Controllers/CountriesController.php
index a6179046..e8ff25e7 100644
--- a/Modules/Countries/Http/Controllers/CountriesController.php
+++ b/Modules/Countries/Http/Controllers/CountriesController.php
@@ -13,10 +13,7 @@ use Modules\Countries\Support\CountryUsageReport;
class CountriesController extends Controller
{
- /**
- * Display ISO 3166 country records.
- */
- public function index(Request $request): View
+ public function __invoke(Request $request): View
{
$search = trim((string) $request->query('search', ''));
$status = (string) $request->query('status', 'all');
@@ -40,80 +37,78 @@ class CountriesController extends Controller
->when($status === 'active', fn ($query) => $query->where('is_active', true))
->when($status === 'inactive', fn ($query) => $query->where('is_active', false))
->when($region !== 'all' && $region !== '', fn ($query) => $query->where('region', $region))
- ->ordered()
+ ->orderByRaw('LOWER(COALESCE(display_name, common_name, name)) ASC')
->paginate(50)
->withQueryString();
$activeCount = Country::query()->where('is_active', true)->count();
$inactiveCount = Country::query()->where('is_active', false)->count();
$totalCount = Country::query()->count();
- $regions = Country::query()->whereNotNull('region')->distinct()->orderBy('region')->pluck('region');
- return view('countries::index', compact('countries', 'activeCount', 'inactiveCount', 'totalCount', 'search', 'status', 'region', 'regions'));
+ $regions = Country::query()
+ ->whereNotNull('region')
+ ->distinct()
+ ->orderBy('region')
+ ->pluck('region');
+
+ return view('countries::index', compact(
+ 'countries',
+ 'activeCount',
+ 'inactiveCount',
+ 'totalCount',
+ 'search',
+ 'status',
+ 'region',
+ 'regions'
+ ));
}
- /**
- * Show the country creation form.
- */
public function create(): View
{
return view('countries::create', ['country' => new Country]);
}
- /**
- * Store a new ISO country record.
- */
public function store(StoreCountryRequest $request): RedirectResponse
{
$country = Country::query()->create($this->payload($request));
- return redirect()->route('countries.show', $country)->with('success', 'Country created.');
+ return redirect()
+ ->route('countries.show', $country)
+ ->with('success', 'Country created.');
}
- /**
- * Show a country record.
- */
public function show(Country $country, CountryUsageReport $usageReport): View
{
$country->load(['subdivisions' => fn ($query) => $query->ordered()->limit(250)]);
+
$usageRows = $usageReport->forCountry($country);
return view('countries::show', compact('country', 'usageRows'));
}
- /**
- * Show the edit form.
- */
public function edit(Country $country): View
{
return view('countries::edit', compact('country'));
}
- /**
- * Update all editable ISO/support fields.
- */
public function update(UpdateCountryRequest $request, Country $country): RedirectResponse
{
$country->update($this->payload($request));
- return redirect()->route('countries.show', $country)->with('success', 'Country updated.');
+ return redirect()
+ ->route('countries.show', $country)
+ ->with('success', 'Country updated.');
}
- /**
- * Soft-delete a custom/retired country record.
- */
public function destroy(Country $country): RedirectResponse
{
$country->delete();
- return redirect()->route('countries.index')->with('success', 'Country archived.');
+ return redirect()
+ ->route('countries.index')
+ ->with('success', 'Country archived.');
}
- /**
- * Build the database payload from validated request data.
- *
- * @return array
- */
private function payload(StoreCountryRequest|UpdateCountryRequest $request): array
{
$data = $request->validated();
@@ -130,7 +125,10 @@ class CountriesController extends Controller
foreach (['languages', 'timezones', 'metadata'] as $jsonField) {
$value = $data[$jsonField] ?? null;
- $data[$jsonField] = blank($value) ? null : json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR);
+
+ $data[$jsonField] = blank($value)
+ ? null
+ : json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR);
}
foreach (['is_active', 'independent', 'un_member'] as $booleanField) {
diff --git a/Modules/Countries/Routes/web.php b/Modules/Countries/Routes/web.php
index 9bf3c4ee..eaa78263 100644
--- a/Modules/Countries/Routes/web.php
+++ b/Modules/Countries/Routes/web.php
@@ -6,7 +6,7 @@ use Modules\Countries\Http\Controllers\CountrySyncController;
use Modules\Countries\Http\Controllers\ReferenceDataController;
Route::prefix('countries')->name('countries.')->middleware(['web', 'auth'])->group(function (): void {
- Route::get('/', [CountriesController::class, 'index'])->name('index');
+ Route::get('/', CountriesController::class)->name('index');
Route::get('/create', [CountriesController::class, 'create'])->name('create');
Route::post('/', [CountriesController::class, 'store'])->name('store');
Route::post('/sync', CountrySyncController::class)->name('sync');
diff --git a/resources/css/app.css b/resources/css/app.css
index f677a995..280713c7 100644
--- a/resources/css/app.css
+++ b/resources/css/app.css
@@ -1410,199 +1410,130 @@ html[data-wms-sidebar="collapsed"] .wms-sidebar {
}
-
-@layer components {
- .wms-select2-field .select2-container {
- width: 100% !important;
- display: block;
- }
-
- .wms-select2-field .select2-container--default .select2-selection--single {
- position: relative;
- min-height: 2.75rem;
- border: 1px solid rgb(212 212 216);
- border-radius: 0.85rem;
- background: linear-gradient(180deg, rgb(255 255 255), rgb(250 250 250));
- box-shadow: 0 1px 2px rgb(15 23 42 / 0.05);
- transition: border-color 140ms ease, box-shadow 140ms ease, background 140ms ease;
- }
-
- .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__rendered {
- min-height: 2.75rem;
- padding-left: 0.95rem;
- padding-right: 3rem;
- color: rgb(24 24 27);
- font-size: 0.875rem;
- font-weight: 650;
- line-height: 2.75rem;
- }
-
- .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__placeholder {
- color: rgb(113 113 122);
- font-weight: 550;
- }
-
- .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__clear {
- position: absolute;
- right: 2.6rem;
- top: 0.62rem;
- z-index: 2;
- width: 1.35rem;
- height: 1.35rem;
- border-radius: 999px;
- color: rgb(113 113 122);
- font-size: 1rem;
- font-weight: 700;
- line-height: 1.25rem;
- text-align: center;
- }
-
- .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__clear:hover {
- background: rgb(244 244 245);
- color: rgb(39 39 42);
- }
-
- .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__arrow {
- top: 0.45rem;
- right: 0.55rem;
- width: 1.85rem;
- height: 1.85rem;
- border-radius: 0.65rem;
- background: rgb(244 244 245);
- border: 1px solid rgb(228 228 231);
- }
-
- .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__arrow b {
- border-color: rgb(82 82 91) transparent transparent transparent;
- border-width: 5px 4px 0 4px;
- margin-left: -4px;
- margin-top: -2px;
- }
-
- .wms-select2-field .select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
- border-color: transparent transparent rgb(82 82 91) transparent;
- border-width: 0 4px 5px 4px;
- }
-
- .wms-select2-field .select2-container--default.select2-container--focus .select2-selection--single,
- .wms-select2-field .select2-container--default.select2-container--open .select2-selection--single {
- border-color: rgb(22 163 74);
- background: white;
- box-shadow: 0 0 0 4px rgb(34 197 94 / 0.14), 0 10px 24px rgb(15 23 42 / 0.08);
- }
-
- .select2-container--default .select2-dropdown {
- overflow: hidden;
- margin-top: 0.35rem;
- border: 1px solid rgb(212 212 216);
- border-radius: 1rem;
- background: white;
- box-shadow: 0 24px 60px rgb(15 23 42 / 0.18);
- }
-
- .select2-container--default .select2-search--dropdown {
- padding: 0.75rem;
- border-bottom: 1px solid rgb(244 244 245);
- }
-
- .select2-container--default .select2-search--dropdown .select2-search__field {
- min-height: 2.5rem;
- border: 1px solid rgb(212 212 216);
- border-radius: 0.75rem;
- padding: 0.55rem 0.8rem;
- background: rgb(250 250 250);
- color: rgb(24 24 27);
- font-size: 0.875rem;
- font-weight: 600;
- outline: none;
- }
-
- .select2-container--default .select2-search--dropdown .select2-search__field:focus {
- border-color: rgb(22 163 74);
- background: white;
- box-shadow: 0 0 0 4px rgb(34 197 94 / 0.14);
- }
-
- .select2-container--default .select2-results > .select2-results__options {
- max-height: 16rem;
- padding: 0.35rem;
- }
-
- .select2-container--default .select2-results__option {
- margin: 0.1rem 0;
- border-radius: 0.65rem;
- padding: 0.65rem 0.8rem;
- color: rgb(39 39 42);
- font-size: 0.875rem;
- font-weight: 650;
- }
-
- .select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
- background: rgb(22 163 74);
- color: white;
- }
-
- .select2-container--default .select2-results__option--selected {
- background: rgb(240 253 244);
- color: rgb(21 128 61);
- }
-
- .dark .wms-select2-field .select2-container--default .select2-selection--single {
- border-color: rgb(63 63 70);
- background: linear-gradient(180deg, rgb(24 24 27), rgb(9 9 11));
- }
-
- .dark .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__rendered {
- color: white;
- }
-
- .dark .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__placeholder {
- color: rgb(161 161 170);
- }
-
- .dark .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__arrow {
- border-color: rgb(63 63 70);
- background: rgb(39 39 42);
- }
-
- .dark .wms-select2-field .select2-container--default .select2-selection--single .select2-selection__arrow b {
- border-color: rgb(212 212 216) transparent transparent transparent;
- }
-
- .dark .wms-select2-field .select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
- border-color: transparent transparent rgb(212 212 216) transparent;
- }
-
- .dark .wms-select2-field .select2-container--default.select2-container--focus .select2-selection--single,
- .dark .wms-select2-field .select2-container--default.select2-container--open .select2-selection--single {
- border-color: rgb(34 197 94);
- background: rgb(9 9 11);
- box-shadow: 0 0 0 4px rgb(34 197 94 / 0.16);
- }
-
- .dark .select2-container--default .select2-dropdown {
- border-color: rgb(63 63 70);
- background: rgb(24 24 27);
- color: rgb(244 244 245);
- box-shadow: 0 24px 60px rgb(0 0 0 / 0.35);
- }
-
- .dark .select2-container--default .select2-search--dropdown {
- border-bottom-color: rgb(39 39 42);
- }
-
- .dark .select2-container--default .select2-search--dropdown .select2-search__field {
- border-color: rgb(63 63 70);
- background: rgb(9 9 11);
- color: white;
- }
-
- .dark .select2-container--default .select2-results__option {
- color: rgb(244 244 245);
- }
-
- .dark .select2-container--default .select2-results__option--selected {
- background: rgb(20 83 45);
- color: rgb(220 252 231);
- }
+/* Company country Select2 */
+.wms-country-select + .select2-container {
+ display: block;
+ width: 100% !important;
+ margin-top: 0.5rem;
+}
+
+.wms-country-select + .select2-container .select2-selection--single {
+ height: 3rem;
+ min-height: 3rem;
+ display: flex;
+ align-items: center;
+ border-radius: 0.75rem;
+ border: 1px solid rgb(212 212 216);
+ background: rgb(255 255 255);
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
+ transition: border-color 150ms ease, box-shadow 150ms ease, background-color 150ms ease;
+}
+
+.dark .wms-country-select + .select2-container .select2-selection--single {
+ border-color: rgb(63 63 70);
+ background: rgb(9 9 11);
+}
+
+.wms-country-select + .select2-container .select2-selection--single .select2-selection__rendered {
+ line-height: 3rem;
+ width: 100%;
+ padding-left: 1rem;
+ padding-right: 2.75rem;
+ color: rgb(24 24 27);
+ font-size: 0.875rem;
+}
+
+.dark .wms-country-select + .select2-container .select2-selection--single .select2-selection__rendered {
+ color: rgb(244 244 245);
+}
+
+.wms-country-select + .select2-container .select2-selection--single .select2-selection__placeholder {
+ color: rgb(113 113 122);
+}
+
+.dark .wms-country-select + .select2-container .select2-selection--single .select2-selection__placeholder {
+ color: rgb(161 161 170);
+}
+
+.wms-country-select + .select2-container .select2-selection--single .select2-selection__arrow {
+ height: 3rem;
+ right: 0.75rem;
+ top: 0;
+}
+
+.wms-country-select + .select2-container .select2-selection--single .select2-selection__arrow b {
+ border-color: rgb(113 113 122) transparent transparent transparent;
+}
+
+.wms-country-select + .select2-container .select2-selection--single .select2-selection__clear {
+ order: 2;
+ margin-right: 0.5rem;
+ color: rgb(113 113 122);
+ font-size: 1.125rem;
+ font-weight: 700;
+}
+
+.wms-country-select + .select2-container.select2-container--focus .select2-selection--single,
+.wms-country-select + .select2-container.select2-container--open .select2-selection--single {
+ border-color: rgb(59 130 246);
+ box-shadow: 0 0 0 3px rgb(59 130 246 / 0.28);
+}
+
+.select2-container--open .select2-dropdown {
+ border: 1px solid rgb(63 63 70);
+ border-radius: 0.875rem;
+ overflow: hidden;
+ background: rgb(255 255 255);
+ box-shadow: 0 20px 35px -15px rgb(0 0 0 / 0.45);
+}
+
+.dark .select2-container--open .select2-dropdown {
+ background: rgb(24 24 27);
+ border-color: rgb(63 63 70);
+}
+
+.select2-container--default .select2-search--dropdown {
+ padding: 0.75rem;
+ border-bottom: 1px solid rgb(228 228 231);
+}
+
+.dark .select2-container--default .select2-search--dropdown {
+ border-bottom-color: rgb(63 63 70);
+}
+
+.select2-container--default .select2-search--dropdown .select2-search__field {
+ min-height: 2.5rem;
+ border-radius: 0.75rem;
+ border: 1px solid rgb(212 212 216);
+ padding: 0.5rem 0.75rem;
+ color: rgb(24 24 27);
+ outline: none;
+}
+
+.dark .select2-container--default .select2-search--dropdown .select2-search__field {
+ border-color: rgb(63 63 70);
+ background: rgb(9 9 11);
+ color: rgb(244 244 245);
+}
+
+.select2-container--default .select2-results__option {
+ padding: 0.7rem 0.9rem;
+ font-size: 0.875rem;
+ color: rgb(39 39 42);
+}
+
+.dark .select2-container--default .select2-results__option {
+ color: rgb(228 228 231);
+}
+
+.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable,
+.select2-container--default .select2-results__option--highlighted[aria-selected] {
+ background: rgb(37 99 235);
+ color: white;
+}
+
+.select2-container--default .select2-results__option--selected,
+.select2-container--default .select2-results__option[aria-selected="true"] {
+ background: rgb(22 101 52);
+ color: white;
}
diff --git a/resources/js/app.js b/resources/js/app.js
index ee6d0713..900aeba2 100644
--- a/resources/js/app.js
+++ b/resources/js/app.js
@@ -167,7 +167,7 @@ function initialiseSelect2() {
return;
}
- $('[data-helpdesk-select2], [data-wms-select2]').each(function () {
+ $('[data-helpdesk-select2], [data-company-country-select2]').each(function () {
const $select = $(this);
if ($select.hasClass('select2-hidden-accessible')) {
@@ -176,15 +176,17 @@ function initialiseSelect2() {
const isMultiple = $select.prop('multiple');
+ const placeholder =
+ $select.data('placeholder') ||
+ $select.find('option[value=""]').first().text() ||
+ (isMultiple ? 'Select options' : 'Select option');
+
$select.select2({
width: '100%',
allowClear: !isMultiple,
closeOnSelect: !isMultiple,
- dropdownAutoWidth: true,
- placeholder:
- $select.data('placeholder') ||
- $select.find('option[value=""]').first().text() ||
- (isMultiple ? 'Select options' : 'Select option'),
+ dropdownAutoWidth: false,
+ placeholder,
});
$select.off('change.select2-livewire');