diff --git a/packages/admin/config/admin.php b/packages/admin/config/admin.php index 28a0acc63..c1df49811 100755 --- a/packages/admin/config/admin.php +++ b/packages/admin/config/admin.php @@ -96,20 +96,13 @@ /* |-------------------------------------------------------------------------- - | Shopper Controllers config + | Shopper Inventory Limit |-------------------------------------------------------------------------- | - | If you want extends your shopper admin panel with great features, - | Here you can specify custom Controller Namespace and Shopper - | RouteServiceProvider will load all your controllers. | */ - 'controllers' => [ - - 'namespace' => 'App\\Http\\Controllers\\Shopper', - - ], + 'inventory-limit' => 4, /* |-------------------------------------------------------------------------- diff --git a/packages/admin/config/components/customer.php b/packages/admin/config/components/customer.php index dcae1f9d6..a0b4046c9 100644 --- a/packages/admin/config/components/customer.php +++ b/packages/admin/config/components/customer.php @@ -13,7 +13,11 @@ |-------------------------------------------------------------------------- */ - 'pages' => [], + 'pages' => [ + 'customer-index' => Livewire\Pages\Customers\Index::class, + 'customer-create' => Livewire\Pages\Customers\Create::class, + 'customer-show' => Livewire\Pages\Customers\Show::class, + ], /* |-------------------------------------------------------------------------- @@ -23,11 +27,8 @@ 'components' => [ 'customers.addresses' => Components\Customers\Addresses::class, - 'customers.browse' => Components\Customers\Browse::class, - 'customers.create' => Components\Customers\Create::class, 'customers.orders' => Components\Customers\Orders::class, 'customers.profile' => Components\Customers\Profile::class, - 'customers.show' => Components\Customers\Show::class, 'modals.delete-customer' => Livewire\Modals\DeleteCustomer::class, ], diff --git a/packages/admin/public/shopper.css b/packages/admin/public/shopper.css index e69764c16..8e81dacf0 100755 --- a/packages/admin/public/shopper.css +++ b/packages/admin/public/shopper.css @@ -3828,6 +3828,11 @@ html { margin-bottom: 1rem; } +.my-6 { + margin-top: 1.5rem; + margin-bottom: 1.5rem; +} + .my-8 { margin-top: 2rem; margin-bottom: 2rem; @@ -3961,6 +3966,10 @@ html { margin-left: 1.25rem; } +.ml-6 { + margin-left: 1.5rem; +} + .ml-auto { margin-left: auto; } @@ -4045,10 +4054,6 @@ html { margin-top: auto; } -.ml-6 { - margin-left: 1.5rem; -} - .line-clamp-\[--line-clamp\] { overflow: hidden; display: -webkit-box; @@ -4385,6 +4390,10 @@ html { width: 100vw; } +.w-0\.5 { + width: 0.125rem; +} + .min-w-0 { min-width: 0px; } @@ -5099,6 +5108,12 @@ html { margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); } +.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.375rem * var(--tw-space-y-reverse)); +} + .space-y-10 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(2.5rem * calc(1 - var(--tw-space-y-reverse))); @@ -5159,12 +5174,6 @@ html { margin-bottom: calc(2rem * var(--tw-space-y-reverse)); } -.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0.375rem * var(--tw-space-y-reverse)); -} - .divide-x > :not([hidden]) ~ :not([hidden]) { --tw-divide-x-reverse: 0; border-right-width: calc(1px * var(--tw-divide-x-reverse)); @@ -5889,6 +5898,14 @@ html { fill: rgba(var(--gray-50), 1); } +.fill-gray-400 { + fill: rgba(var(--gray-400), 1); +} + +.fill-gray-300 { + fill: rgba(var(--gray-300), 1); +} + .stroke-gray-200 { stroke: rgba(var(--gray-200), 1); } @@ -6675,6 +6692,16 @@ html { color: rgba(var(--gray-500), var(--tw-placeholder-opacity)); } +.placeholder-gray-400::-moz-placeholder { + --tw-placeholder-opacity: 1; + color: rgba(var(--gray-400), var(--tw-placeholder-opacity)); +} + +.placeholder-gray-400::placeholder { + --tw-placeholder-opacity: 1; + color: rgba(var(--gray-400), var(--tw-placeholder-opacity)); +} + .opacity-0 { opacity: 0; } @@ -6799,6 +6826,11 @@ html { --tw-ring-color: rgb(220 38 38 / var(--tw-ring-opacity)); } +.ring-gray-100 { + --tw-ring-opacity: 1; + --tw-ring-color: rgba(var(--gray-100), var(--tw-ring-opacity)); +} + .ring-gray-200 { --tw-ring-opacity: 1; --tw-ring-color: rgba(var(--gray-200), var(--tw-ring-opacity)); @@ -8879,11 +8911,6 @@ input[type='number'] { color: rgb(37 99 235 / var(--tw-text-opacity)); } -.hover\:text-primary-700:hover { - --tw-text-opacity: 1; - color: rgb(29 78 216 / var(--tw-text-opacity)); -} - .hover\:text-primary-800:hover { --tw-text-opacity: 1; color: rgb(30 64 175 / var(--tw-text-opacity)); @@ -9530,6 +9557,14 @@ input[type='number'] { fill: rgba(var(--gray-900), 1); } +:is(.dark .dark\:fill-gray-700) { + fill: rgba(var(--gray-700), 1); +} + +:is(.dark .dark\:fill-gray-500) { + fill: rgba(var(--gray-500), 1); +} + :is(.dark .dark\:stroke-gray-900) { stroke: rgba(var(--gray-900), 1); } @@ -9592,10 +9627,6 @@ input[type='number'] { color: rgb(74 222 128 / var(--tw-text-opacity)); } -:is(.dark .dark\:text-green-500\/50) { - color: rgb(34 197 94 / 0.5); -} - :is(.dark .dark\:text-primary-400) { --tw-text-opacity: 1; color: rgb(96 165 250 / var(--tw-text-opacity)); @@ -10312,6 +10343,12 @@ input[type='number'] { margin-bottom: calc(0px * var(--tw-space-y-reverse)); } + .sm\:space-x-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); + margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); + } + .sm\:truncate { overflow: hidden; text-overflow: ellipsis; @@ -10523,10 +10560,6 @@ input[type='number'] { display: block; } - .md\:flex { - display: flex; - } - .md\:table-cell { display: table-cell; } @@ -10589,10 +10622,6 @@ input[type='number'] { grid-template-columns: repeat(3, minmax(0, 1fr)); } - .md\:grid-cols-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - .md\:grid-cols-\[--cols-md\] { grid-template-columns: var(--cols-md); } @@ -10617,10 +10646,6 @@ input[type='number'] { justify-content: flex-end; } - .md\:justify-between { - justify-content: space-between; - } - .md\:gap-1 { gap: 0.25rem; } @@ -10638,18 +10663,6 @@ input[type='number'] { row-gap: 1.5rem; } - .md\:space-x-4 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(1rem * var(--tw-space-x-reverse)); - margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); - } - - .md\:space-y-0 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0px * var(--tw-space-y-reverse)); - } - .md\:divide-y-0 > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 0; border-top-width: calc(0px * calc(1 - var(--tw-divide-y-reverse))); diff --git a/packages/admin/resources/lang/en/layout.php b/packages/admin/resources/lang/en/layout.php index b6d9b1223..01215b944 100755 --- a/packages/admin/resources/lang/en/layout.php +++ b/packages/admin/resources/lang/en/layout.php @@ -160,6 +160,7 @@ 'disabled' => 'Disabled', 'disable' => 'Disable', 'edit' => 'Edit', + 'view' => 'View', 'enable' => 'Enable', 'enabled' => 'Enabled', 'export' => 'Export', diff --git a/packages/admin/resources/lang/fr/layout.php b/packages/admin/resources/lang/fr/layout.php index 0c27ed007..d15e42ea6 100755 --- a/packages/admin/resources/lang/fr/layout.php +++ b/packages/admin/resources/lang/fr/layout.php @@ -160,6 +160,7 @@ 'disable' => 'Désactiver', 'disabled' => 'Désactivé', 'edit' => 'Éditer', + 'view' => 'Voir', 'enable' => 'Activer', 'enabled' => 'Activé', 'export' => 'Exportez', diff --git a/packages/admin/resources/views/components/badge.blade.php b/packages/admin/resources/views/components/badge.blade.php index bdc75f188..a51292940 100755 --- a/packages/admin/resources/views/components/badge.blade.php +++ b/packages/admin/resources/views/components/badge.blade.php @@ -10,6 +10,6 @@ }; @endphp - + {{ $value }} diff --git a/packages/admin/resources/views/components/buttons/primary.blade.php b/packages/admin/resources/views/components/buttons/primary.blade.php index 59722f295..1e7707494 100755 --- a/packages/admin/resources/views/components/buttons/primary.blade.php +++ b/packages/admin/resources/views/components/buttons/primary.blade.php @@ -1,11 +1,10 @@ @isset($link) - twMerge(['class' => 'inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-lg shadow-sm text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-900 focus:ring-primary-500']) }} > {{ $slot }} - + @else diff --git a/packages/admin/resources/views/livewire/customers/addresses.blade.php b/packages/admin/resources/views/livewire/components/customers/addresses.blade.php similarity index 91% rename from packages/admin/resources/views/livewire/customers/addresses.blade.php rename to packages/admin/resources/views/livewire/components/customers/addresses.blade.php index 445832887..d75349dbc 100755 --- a/packages/admin/resources/views/livewire/customers/addresses.blade.php +++ b/packages/admin/resources/views/livewire/components/customers/addresses.blade.php @@ -7,7 +7,9 @@
- {{ $address->type === 'shipping' ? __('shopper::pages/customers.addresses.shipping') : __('shopper::pages/customers.addresses.billing') }} + {{ $address->type === \Shopper\Core\Enum\AddressType::SHIPPING + ? __('shopper::pages/customers.addresses.shipping') + : __('shopper::pages/customers.addresses.billing') }} @if($address->is_default) diff --git a/packages/admin/resources/views/livewire/customers/orders.blade.php b/packages/admin/resources/views/livewire/components/customers/orders.blade.php similarity index 100% rename from packages/admin/resources/views/livewire/customers/orders.blade.php rename to packages/admin/resources/views/livewire/components/customers/orders.blade.php diff --git a/packages/admin/resources/views/livewire/components/customers/profile.blade.php b/packages/admin/resources/views/livewire/components/customers/profile.blade.php new file mode 100755 index 000000000..650e8aadf --- /dev/null +++ b/packages/admin/resources/views/livewire/components/customers/profile.blade.php @@ -0,0 +1,119 @@ + +
+
+

+ {{ __('shopper::pages/customers.profile.title') }} +

+

+ {{ __('shopper::pages/customers.profile.description') }} +

+
+
+
+
+
+ {{ __('shopper::layout.forms.label.first_name') }} +
+
+
+ {{ $customer->first_name }} +
+
+
+
+
+ {{ __('shopper::layout.forms.label.last_name') }} +
+
+
+ {{ $customer->last_name }} +
+
+
+
+
+ {{ __('shopper::layout.forms.label.photo') }} +
+
+ + + +
+
+
+
+ {{ __('shopper::layout.forms.label.email') }} +
+
+
+ {{ $customer->email }} +
+
+
+
+
+ {{ __('shopper::layout.forms.label.birth_date') }} +
+
+
+

+

+
+
+
+
+
+ {{ __('shopper::layout.forms.label.gender') }} +
+
+
+ {{ $customer->gender }} +
+
+
+
+
+
+
+
+

+ {{ __('shopper::pages/customers.profile.account') }} +

+

+ {{ __('shopper::pages/customers.profile.account_description') }} +

+
+
+
+
+
+ {{ __('shopper::pages/customers.profile.marketing') }} +
+
+ +
+
+
+
+ {{ __('shopper::pages/customers.profile.two_factor') }} +
+
+ +
+
+
+
+
+
diff --git a/packages/admin/resources/views/livewire/components/settings/inventories/browse.blade.php b/packages/admin/resources/views/livewire/components/settings/inventories/browse.blade.php deleted file mode 100755 index 82d7bb89e..000000000 --- a/packages/admin/resources/views/livewire/components/settings/inventories/browse.blade.php +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - {{ __('shopper::words.locations') }} - - - - @can('add_inventories') - @if($inventories->count() < 5) -
- - - {{ __('shopper::words.actions_label.add_new', ['name' => strtolower(__('shopper::words.location'))]) }} - - -
- @endif - @endcan -
-
- - - - -
diff --git a/packages/admin/resources/views/livewire/customers/create.blade.php b/packages/admin/resources/views/livewire/customers/create.blade.php deleted file mode 100755 index ba7282553..000000000 --- a/packages/admin/resources/views/livewire/customers/create.blade.php +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - - - - {{ __('shopper::words.actions_label.add_new', ['name' => __('shopper::words.customer')]) }} - - - -
-
-
-

- {{ __('shopper::pages/customers.overview') }} -

-

- {{ __('shopper::pages/customers.overview_description') }} -

-
-
-
-
- - - - - - - - - - - - -
-
- - - {{ __('shopper::layout.forms.label.optional') }} - -
-
- -
-
-
-
-
- - - -
-
-
-
-

- {{ __('shopper::pages/customers.security_title') }} -

-

- {{ __('shopper::pages/customers.security_description') }} -

-
-
-
-
-
-
- -
- - -
-
-
- - @error('password') -
- -
- @enderror -
- @error('password') -

{{ $message }}

- @enderror -
- - - - -
-
-
-
- - - -
-
-
-
-

- {{ __('shopper::pages/customers.address_title') }} -

-

- {{ __('shopper::pages/customers.address_description') }} -

-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
- -
-
-
-
-
-
- - - -
-
-
-
-

- {{ __('shopper::pages/customers.notification_title') }} -

-

- {{ __('shopper::pages/customers.notification_description') }} -

-
-
-
-
-
-
- -
-
- -

- {{ __('shopper::pages/customers.marketing_description') }} -

-
-
- -
-
- -
-
- -

- {{ __('shopper::pages/customers.credential_description') }} -

-
-
-
-
-
-
- -
-
- - - {{ __('shopper::layout.forms.actions.save') }} - -
-
- -
- diff --git a/packages/admin/resources/views/livewire/customers/profile.blade.php b/packages/admin/resources/views/livewire/customers/profile.blade.php deleted file mode 100755 index 8b5c47e39..000000000 --- a/packages/admin/resources/views/livewire/customers/profile.blade.php +++ /dev/null @@ -1,247 +0,0 @@ - -
-
-

- {{ __('shopper::pages/customers.profile.title') }} -

-

- {{ __('shopper::pages/customers.profile.description') }} -

-
-
-
-
-
- {{ __('shopper::layout.forms.label.first_name') }} -
-
-
- {{ $firstName }} -
-
- - - -
-
-
-
- - - - -
-
-
-
-
- {{ __('shopper::layout.forms.label.last_name') }} -
-
-
- {{ $lastName }} -
-
- - - -
-
-
-
- - - - -
-
-
-
-
- {{ __('shopper::layout.forms.label.photo') }} -
-
- - - -
-
-
-
- {{ __('shopper::layout.forms.label.email') }} -
-
-
- {{ $email }} -
-
- - - -
-
-
-
- - - - -
-
-
-
-
- {{ __('shopper::layout.forms.label.birth_date') }} -
-
-
-

- - {{ $birthDateFormatted }} -

-
-
- -
-
-
-
- - - - -
-
-
-
-
- {{ __('shopper::layout.forms.label.gender') }} -
-
-
- {{ $gender }} -
-
- - - - -
-
-
-
- - - - -
-
-
-
-
-
-
-
-

- {{ __('shopper::pages/customers.profile.account') }} -

-

- {{ __('shopper::pages/customers.profile.account_description') }} -

-
-
-
-
-
- {{ __('shopper::pages/customers.profile.marketing') }} -
-
- - - -
-
-
-
- {{ __('shopper::pages/customers.profile.two_factor') }} -
-
- - {{ $hasEnabledTwoFactor ? __('shopper::layout.forms.actions.enabled') : __('shopper::layout.forms.actions.disabled') }} - -
-
-
-
-
-
diff --git a/packages/admin/resources/views/livewire/modals/delete-customer.blade.php b/packages/admin/resources/views/livewire/modals/delete-customer.blade.php deleted file mode 100755 index 1feea36d3..000000000 --- a/packages/admin/resources/views/livewire/modals/delete-customer.blade.php +++ /dev/null @@ -1,33 +0,0 @@ - - -
-
- -
-
- -
-

- {{ __('shopper::pages/customers.modal.description') }} -

-
-
-
-
- - - - - - {{ __('shopper::layout.forms.actions.confirm') }} - - - - - {{ __('shopper::layout.forms.actions.cancel') }} - - - -
diff --git a/packages/admin/resources/views/livewire/pages/auth/login.blade.php b/packages/admin/resources/views/livewire/pages/auth/login.blade.php index 2171f96eb..5d1219fdc 100755 --- a/packages/admin/resources/views/livewire/pages/auth/login.blade.php +++ b/packages/admin/resources/views/livewire/pages/auth/login.blade.php @@ -17,7 +17,7 @@
-
+
@@ -37,7 +37,7 @@ class="relative block w-full px-3 py-2 border rounded-none appearance-none borde name="password" type="password" wire:model="password" - class="relative block w-full px-3 py-2 border rounded-none appearance-none border-gray-300 dark:border-gray-700 dark:bg-gray-800 placeholder-gray-500 text-gray-900 dark:text-gray-300 rounded-b-md focus:outline-none focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-offset-gray-900 focus:z-10 sm:text-sm" + class="relative block w-full px-3 py-1.5 border-0 rounded-b-lg ring-1 ring-inset ring-gray-300 dark:bg-white/5 placeholder-gray-400 text-gray-900 dark:text-gray-300 dark:ring-white/10 focus:outline-none focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-500 focus:z-10 dark:focus:ring-offset-gray-900 sm:text-sm" placeholder="{{ __('shopper::layout.forms.label.password') }}" required /> diff --git a/packages/admin/resources/views/livewire/pages/brand/index.blade.php b/packages/admin/resources/views/livewire/pages/brand/index.blade.php index fb56e733a..e01940cd5 100755 --- a/packages/admin/resources/views/livewire/pages/brand/index.blade.php +++ b/packages/admin/resources/views/livewire/pages/brand/index.blade.php @@ -133,7 +133,7 @@
@else -
+
{{ $this->table }}
@endif diff --git a/packages/admin/resources/views/livewire/pages/category/index.blade.php b/packages/admin/resources/views/livewire/pages/category/index.blade.php index 0a800af0f..5614155ce 100644 --- a/packages/admin/resources/views/livewire/pages/category/index.blade.php +++ b/packages/admin/resources/views/livewire/pages/category/index.blade.php @@ -114,7 +114,7 @@
@else -
+
{{ $this->table }}
@endif diff --git a/packages/admin/resources/views/livewire/pages/customers/create.blade.php b/packages/admin/resources/views/livewire/pages/customers/create.blade.php new file mode 100755 index 000000000..a8fb8b6b4 --- /dev/null +++ b/packages/admin/resources/views/livewire/pages/customers/create.blade.php @@ -0,0 +1,26 @@ + + + + + + + + + {{ __('shopper::words.actions_label.add_new', ['name' => __('shopper::words.customer')]) }} + + + + + {{ $this->form }} + +
+
+ + + {{ __('shopper::layout.forms.actions.save') }} + +
+
+ + +
diff --git a/packages/admin/resources/views/livewire/customers/browse.blade.php b/packages/admin/resources/views/livewire/pages/customers/index.blade.php similarity index 99% rename from packages/admin/resources/views/livewire/customers/browse.blade.php rename to packages/admin/resources/views/livewire/pages/customers/index.blade.php index 61999a132..8ee2da811 100755 --- a/packages/admin/resources/views/livewire/customers/browse.blade.php +++ b/packages/admin/resources/views/livewire/pages/customers/index.blade.php @@ -23,7 +23,7 @@ @@ -172,8 +172,8 @@
@else -
- +
+ {{ $this->table }}
@endif diff --git a/packages/admin/resources/views/livewire/customers/show.blade.php b/packages/admin/resources/views/livewire/pages/customers/show.blade.php similarity index 65% rename from packages/admin/resources/views/livewire/customers/show.blade.php rename to packages/admin/resources/views/livewire/pages/customers/show.blade.php index b210f58fe..f9b7a9a1b 100755 --- a/packages/admin/resources/views/livewire/customers/show.blade.php +++ b/packages/admin/resources/views/livewire/pages/customers/show.blade.php @@ -19,28 +19,39 @@ -
+
-
- {{ $customer->full_name }} -
+ {{ $customer->full_name }}
-

+

{{ $customer->full_name }}

-
-
+
+
@if($customer->email_verified_at) - +
-

+ +

@@ -48,37 +59,25 @@
-
+
@@ -124,7 +123,7 @@ class="px-1 pb-4 text-sm font-medium leading-5 whitespace-no-wrap border-b-2 foc
-
+
@@ -136,5 +135,4 @@ class="px-1 pb-4 text-sm font-medium leading-5 whitespace-no-wrap border-b-2 foc
-
diff --git a/packages/admin/resources/views/livewire/pages/settings/analytics.blade.php b/packages/admin/resources/views/livewire/pages/settings/analytics.blade.php index 6085bde4b..1aaf25eed 100755 --- a/packages/admin/resources/views/livewire/pages/settings/analytics.blade.php +++ b/packages/admin/resources/views/livewire/pages/settings/analytics.blade.php @@ -4,13 +4,13 @@ - + {{ __('shopper::words.analytics') }} -
+
diff --git a/packages/admin/resources/views/livewire/pages/settings/general.blade.php b/packages/admin/resources/views/livewire/pages/settings/general.blade.php index a13f09cdb..c3acfb240 100755 --- a/packages/admin/resources/views/livewire/pages/settings/general.blade.php +++ b/packages/admin/resources/views/livewire/pages/settings/general.blade.php @@ -4,7 +4,7 @@ - + {{ __('shopper::pages/settings.settings.title') }} diff --git a/packages/admin/resources/views/livewire/pages/settings/inventories/browse.blade.php b/packages/admin/resources/views/livewire/pages/settings/inventories/browse.blade.php new file mode 100755 index 000000000..eb4f96b56 --- /dev/null +++ b/packages/admin/resources/views/livewire/pages/settings/inventories/browse.blade.php @@ -0,0 +1,105 @@ + + + + + + + + + {{ __('shopper::words.locations') }} + + + + @can('add_inventories') + @if($inventories->count() < ((int) config('shopper.admin.inventory-limit') + 1)) +
+ + {{ __('shopper::words.actions_label.add_new', ['name' => mb_strtolower(__('shopper::words.location'))]) }} + +
+ @endif + @endcan +
+
+ +
+
+
+

+ {{ __('shopper::words.locations') }} +

+

+ {{ __('shopper::pages/settings.location.description') }} +

+

+ {{ __('shopper::pages/settings.location.count', ['count' => $inventories->count()]) }} +

+
+
+
+ +
    + @foreach($inventories as $inventory) +
  • + +
    +
    + +
    +
    +
    + {{ $inventory->name }} +
    + @if($inventory->is_default) +
    + + {{ __('shopper::words.default') }} + +
    + @endif +
    +
    +
    +
    + {{ isoToEmoji($inventory->country->cca2) }} + {{ $inventory->country->name }} +
    +
    +
    +
    +
    +
    +
    + + + {{ __('shopper::words.added_on') }} + + +
    +
    +
    +
    +
    +
    +
  • + @endforeach +
+
+
+
+ + +
diff --git a/packages/admin/resources/views/livewire/components/settings/inventories/create.blade.php b/packages/admin/resources/views/livewire/pages/settings/inventories/create.blade.php similarity index 89% rename from packages/admin/resources/views/livewire/components/settings/inventories/create.blade.php rename to packages/admin/resources/views/livewire/pages/settings/inventories/create.blade.php index 8cd1f419b..bc3ebdeaa 100755 --- a/packages/admin/resources/views/livewire/components/settings/inventories/create.blade.php +++ b/packages/admin/resources/views/livewire/pages/settings/inventories/create.blade.php @@ -4,11 +4,11 @@ - + {{ __('shopper::pages/settings.location.add') }} - + diff --git a/packages/admin/resources/views/livewire/components/settings/inventories/edit.blade.php b/packages/admin/resources/views/livewire/pages/settings/inventories/edit.blade.php similarity index 93% rename from packages/admin/resources/views/livewire/components/settings/inventories/edit.blade.php rename to packages/admin/resources/views/livewire/pages/settings/inventories/edit.blade.php index bf433acec..07d5cf7e6 100755 --- a/packages/admin/resources/views/livewire/components/settings/inventories/edit.blade.php +++ b/packages/admin/resources/views/livewire/pages/settings/inventories/edit.blade.php @@ -4,7 +4,7 @@ - + {{ $inventory->name }} diff --git a/packages/admin/resources/views/livewire/pages/settings/legal.blade.php b/packages/admin/resources/views/livewire/pages/settings/legal.blade.php index 58c9ff780..581279c3d 100755 --- a/packages/admin/resources/views/livewire/pages/settings/legal.blade.php +++ b/packages/admin/resources/views/livewire/pages/settings/legal.blade.php @@ -18,7 +18,7 @@ - + {{ __('shopper::pages/settings.legal.title') }} diff --git a/packages/admin/resources/views/livewire/pages/settings/payment.blade.php b/packages/admin/resources/views/livewire/pages/settings/payment.blade.php index c31b45d6f..e26c7e5f6 100755 --- a/packages/admin/resources/views/livewire/pages/settings/payment.blade.php +++ b/packages/admin/resources/views/livewire/pages/settings/payment.blade.php @@ -13,7 +13,7 @@ - + {{ __('shopper::pages/settings.payment.title') }} diff --git a/packages/admin/resources/views/livewire/pages/settings/team/index.blade.php b/packages/admin/resources/views/livewire/pages/settings/team/index.blade.php index 02e8068cc..89b62549d 100755 --- a/packages/admin/resources/views/livewire/pages/settings/team/index.blade.php +++ b/packages/admin/resources/views/livewire/pages/settings/team/index.blade.php @@ -4,13 +4,13 @@ - + {{ __('shopper::pages/settings.roles_permissions.header_title') }} -
+

diff --git a/packages/admin/resources/views/livewire/pages/settings/team/role.blade.php b/packages/admin/resources/views/livewire/pages/settings/team/role.blade.php index 0b61cbb83..bbea7042f 100755 --- a/packages/admin/resources/views/livewire/pages/settings/team/role.blade.php +++ b/packages/admin/resources/views/livewire/pages/settings/team/role.blade.php @@ -19,10 +19,11 @@ class="pb-10" - + {{ $role->display_name }} +
@if($role->can_be_removed) diff --git a/packages/admin/resources/views/livewire/tables/cells/customers/email.blade.php b/packages/admin/resources/views/livewire/tables/cells/customers/email.blade.php new file mode 100755 index 000000000..3c4f14a05 --- /dev/null +++ b/packages/admin/resources/views/livewire/tables/cells/customers/email.blade.php @@ -0,0 +1,10 @@ +
+ @if($getRecord()->email_verified_at) +
diff --git a/packages/admin/resources/views/livewire/tables/cells/customers/name.blade.php b/packages/admin/resources/views/livewire/tables/cells/customers/name.blade.php index 77aebebe3..8008b8c89 100755 --- a/packages/admin/resources/views/livewire/tables/cells/customers/name.blade.php +++ b/packages/admin/resources/views/livewire/tables/cells/customers/name.blade.php @@ -1,18 +1,14 @@ -
-
- {{ $row->full_name }} - -
- {{ $row->full_name }} -
-
- @if($row->email_verified_at) - - @else - - @endif - {{ $row->email }} -
-
+
+
+ {{ $getRecord()->full_name }} + + + {{ $getRecord()->full_name }} + +
diff --git a/packages/admin/resources/views/livewire/tables/cells/customers/opt-in.blade.php b/packages/admin/resources/views/livewire/tables/cells/customers/opt-in.blade.php deleted file mode 100755 index 4b5664090..000000000 --- a/packages/admin/resources/views/livewire/tables/cells/customers/opt-in.blade.php +++ /dev/null @@ -1,7 +0,0 @@ - $row->opt_in, - 'bg-gray-100 text-gray-800 dark:bg-gray-600 dark:text-gray-300' => ! $row->opt_in, -])> - {{ $row->opt_in ? __('shopper::layout.forms.label.subscribed') : __('shopper::layout.forms.label.not_subscribed') }} - diff --git a/packages/admin/resources/views/pages/categories/create.blade.php b/packages/admin/resources/views/pages/categories/create.blade.php deleted file mode 100755 index d534cc43e..000000000 --- a/packages/admin/resources/views/pages/categories/create.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/admin/resources/views/pages/categories/edit.blade.php b/packages/admin/resources/views/pages/categories/edit.blade.php deleted file mode 100755 index 80b3bd3e1..000000000 --- a/packages/admin/resources/views/pages/categories/edit.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/admin/resources/views/pages/customers/create.blade.php b/packages/admin/resources/views/pages/customers/create.blade.php deleted file mode 100755 index 13ff861f4..000000000 --- a/packages/admin/resources/views/pages/customers/create.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/admin/resources/views/pages/customers/index.blade.php b/packages/admin/resources/views/pages/customers/index.blade.php deleted file mode 100755 index ad363c078..000000000 --- a/packages/admin/resources/views/pages/customers/index.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/admin/resources/views/pages/customers/show.blade.php b/packages/admin/resources/views/pages/customers/show.blade.php deleted file mode 100755 index 851d0a6fb..000000000 --- a/packages/admin/resources/views/pages/customers/show.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/admin/routes/admin/customer.php b/packages/admin/routes/admin/customer.php index 2c083b4e9..2528672bb 100644 --- a/packages/admin/routes/admin/customer.php +++ b/packages/admin/routes/admin/customer.php @@ -4,4 +4,6 @@ use Illuminate\Support\Facades\Route; -Route::get('/', config('shopper.components.customer.pages.index'))->name('index'); +Route::get('/', config('shopper.components.customer.pages.customer-index'))->name('index'); +Route::get('/create', config('shopper.components.customer.pages.customer-create'))->name('create'); +Route::get('/{user}/show', config('shopper.components.customer.pages.customer-show'))->name('show'); diff --git a/packages/admin/routes/web.php b/packages/admin/routes/web.php index 216b4c4aa..dbe0ef4d3 100755 --- a/packages/admin/routes/web.php +++ b/packages/admin/routes/web.php @@ -68,8 +68,7 @@ }); if (config('shopper.routes.custom_file')) { - Route::namespace(config('shopper.admin.controllers.namespace')) - ->group(config('shopper.routes.custom_file')); + Route::as('shopper.')->group(config('shopper.routes.custom_file')); } }); }); diff --git a/packages/admin/src/Components/Form/AddressField.php b/packages/admin/src/Components/Form/AddressField.php new file mode 100644 index 000000000..2557e453b --- /dev/null +++ b/packages/admin/src/Components/Form/AddressField.php @@ -0,0 +1,50 @@ +label(__('shopper::layout.forms.label.street_address')) + ->placeholder('Akwa Avenue 34...') + ->columnSpan('full') + ->required(), + Components\TextInput::make(self::getPrefix($prefix) . 'street_address_plus') + ->label(__('shopper::layout.forms.label.street_address_plus')) + ->columnSpan('full'), + Components\TextInput::make(self::getPrefix($prefix) . 'city') + ->label(__('shopper::layout.forms.label.city')) + ->required(), + Components\TextInput::make(self::getPrefix($prefix) . 'zipcode') + ->label(__('shopper::layout.forms.label.postal_code')) + ->required(), + Components\Select::make(self::getPrefix($prefix) . 'country_id') + ->label(__('shopper::layout.forms.label.country')) + ->options(Country::query()->pluck('name', 'id')) + ->searchable() + ->required() + ->columnSpan('full'), + Components\TextInput::make(self::getPrefix($prefix) . 'phone_number') + ->label(__('shopper::layout.forms.label.phone_number')) + ->tel() + ->columnSpan('full'), + ]; + } +} diff --git a/packages/admin/src/Components/Form/GenderField.php b/packages/admin/src/Components/Form/GenderField.php new file mode 100644 index 000000000..dd8ee9fc9 --- /dev/null +++ b/packages/admin/src/Components/Form/GenderField.php @@ -0,0 +1,23 @@ +label(__('shopper::layout.forms.label.gender')) + ->options([ + 'male' => __('shopper::words.male'), + 'female' => __('shopper::words.female'), + ]) + ->default('male') + ->native(false); + } +} diff --git a/packages/admin/src/Events/CustomerSidebar.php b/packages/admin/src/Events/CustomerSidebar.php index 839c1b32e..0219433fd 100755 --- a/packages/admin/src/Events/CustomerSidebar.php +++ b/packages/admin/src/Events/CustomerSidebar.php @@ -28,6 +28,7 @@ public function extendWith(Menu $menu): Menu $item->setActiveClass('text-primary-600 bg-gray-100 dark:bg-gray-700/50'); $item->setInactiveClass('text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-900'); $item->route('shopper.customers.index'); + $item->useSpa(); $item->setIcon( icon: 'untitledui-users-02', iconClass: 'mr-3 h-5 w-5 ' . ($item->isActive() ? 'text-primary-600' : 'text-gray-400'), @@ -46,6 +47,7 @@ public function extendWith(Menu $menu): Menu $item->setActiveClass('text-primary-600 bg-gray-100 dark:bg-gray-700/50'); $item->setInactiveClass('text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-900'); $item->route('shopper.reviews.index'); + $item->useSpa(); $item->setIcon( icon: 'untitledui-message-heart-square', iconClass: 'mr-3 h-5 w-5 ' . ($item->isActive() ? 'text-primary-600' : 'text-gray-400'), diff --git a/packages/admin/src/Http/Controllers/Ecommerce/CustomerController.php b/packages/admin/src/Http/Controllers/Ecommerce/CustomerController.php deleted file mode 100755 index f3424e87c..000000000 --- a/packages/admin/src/Http/Controllers/Ecommerce/CustomerController.php +++ /dev/null @@ -1,35 +0,0 @@ -authorize('browse_customers'); - - return view('shopper::pages.customers.index'); - } - - public function create(): View - { - $this->authorize('add_customers'); - - return view('shopper::pages.customers.create'); - } - - public function show(int $id): View - { - $this->authorize('read_customers'); - - return view('shopper::pages.customers.show', [ - 'customer' => (new UserRepository())->with(['addresses', 'orders'])->getById($id), - ]); - } -} diff --git a/packages/admin/src/Livewire/Components/Customers/Addresses.php b/packages/admin/src/Livewire/Components/Customers/Addresses.php index 9432e636e..3b8dd38e7 100755 --- a/packages/admin/src/Livewire/Components/Customers/Addresses.php +++ b/packages/admin/src/Livewire/Components/Customers/Addresses.php @@ -6,7 +6,6 @@ use Illuminate\Contracts\View\View; use Illuminate\Database\Eloquent\Collection; -use Illuminate\Support\Facades\Cache; use Livewire\Component; class Addresses extends Component @@ -20,12 +19,6 @@ public function mount($adresses): void public function render(): View { - return view('shopper::livewire.customers.addresses', [ - 'addresses' => Cache::remember( - key: 'customer-addresses', - ttl: 60 * 60 * 24, - callback: fn () => $this->addresses - ), - ]); + return view('shopper::livewire.components.customers.addresses'); } } diff --git a/packages/admin/src/Livewire/Components/Customers/Browse.php b/packages/admin/src/Livewire/Components/Customers/Browse.php deleted file mode 100755 index b565cf630..000000000 --- a/packages/admin/src/Livewire/Components/Customers/Browse.php +++ /dev/null @@ -1,25 +0,0 @@ - (new UserRepository()) - ->makeModel() - ->whereHas('roles', function (Builder $query): void { - $query->where('name', config('shopper.core.users.default_role')); - }) - ->count(), - ]); - } -} diff --git a/packages/admin/src/Livewire/Components/Customers/Create.php b/packages/admin/src/Livewire/Components/Customers/Create.php deleted file mode 100755 index e23ec291d..000000000 --- a/packages/admin/src/Livewire/Components/Customers/Create.php +++ /dev/null @@ -1,105 +0,0 @@ -validate($this->rules()); - - /** @var User $customer */ - $customer = (new UserRepository())->create([ - 'last_name' => $this->last_name, - 'first_name' => $this->first_name, - 'email' => $this->email, - 'password' => Hash::make($this->password), - 'phone_number' => $this->phone_number, - 'email_verified_at' => now()->toDateTimeString(), - 'opt_in' => $this->opt_in, - ]); - - $customer->assignRole(config('shopper.core.users.default_role')); - - $customer->addresses()->create([ - 'first_name' => $this->address_first_name, - 'last_name' => $this->address_last_name, - 'company_name' => $this->company_name, - 'country_id' => $this->country_id, - 'city' => $this->city, - 'zipcode' => $this->zipcode, - 'street_address' => $this->street_address, - 'street_address_plus' => $this->street_address_plus, - 'is_default' => true, - 'type' => Address::TYPE_SHIPPING, - ]); - - if ($this->send_mail) { - $customer->notify(new CustomerSendCredentials($this->password)); - } - - session()->flash('success', __('shopper::notifications.actions.create', ['item' => __('shopper::words.customer')])); - - $this->redirectRoute('shopper.customers.show', $customer); - } - - public function generate(): void - { - $this->password = mb_substr(mb_strtoupper(uniqid(str_random(10))), 0, 10); - } - - public function rules(): array - { - return array_merge($this->addressRules(), [ - 'email' => 'required|max:150|unique:' . shopper_table('users'), - 'first_name' => 'required', - 'last_name' => 'required', - 'country_id' => 'required', - 'street_address' => 'required', - 'password' => 'required|confirmed|min:8', - 'phone_number' => ['nullable', new Phone()], - ]); - } - - public function render(): View - { - return view('shopper::livewire.customers.create', [ - 'countries' => Cache::get( - key: 'countries-settings', - default: fn () => Country::query()->orderBy('name')->get() - ), - ]); - } -} diff --git a/packages/admin/src/Livewire/Components/Customers/Orders.php b/packages/admin/src/Livewire/Components/Customers/Orders.php index fc68c73ea..361c02cb2 100755 --- a/packages/admin/src/Livewire/Components/Customers/Orders.php +++ b/packages/admin/src/Livewire/Components/Customers/Orders.php @@ -26,9 +26,9 @@ public function paginationSimpleView(): string public function render(): View { - return view('shopper::livewire.customers.orders', [ + return view('shopper::livewire.components.customers.orders', [ 'orders' => $this->customer->orders() - ->with(['customer', 'items', 'shippingAddress', 'paymentMethod']) + ->with(['items', 'shippingAddress', 'paymentMethod']) ->simplePaginate(3), ]); } diff --git a/packages/admin/src/Livewire/Components/Customers/Profile.php b/packages/admin/src/Livewire/Components/Customers/Profile.php index faa6bfffb..9305396a8 100755 --- a/packages/admin/src/Livewire/Components/Customers/Profile.php +++ b/packages/admin/src/Livewire/Components/Customers/Profile.php @@ -4,132 +4,16 @@ namespace Shopper\Livewire\Components\Customers; -use Filament\Notifications\Notification; use Illuminate\Contracts\View\View; -use Illuminate\Validation\Rule; +use Illuminate\Database\Eloquent\Model; use Livewire\Component; class Profile extends Component { - public $customer; - - public int $customer_id; - - public string $firstName; - - public string $lastName; - - public string $email; - - public ?string $birthDate = null; - - public string $birthDateFormatted = ''; - - public string $gender; - - public bool $firstNameUpdate = false; - - public bool $lastNameUpdate = false; - - public bool $emailUpdate = false; - - public bool $genderUpdate = false; - - public bool $birthDateUpdate = false; - - public bool $optIn; - - public bool $hasEnabledTwoFactor; - - public function mount($customer): void - { - $this->customer = $customer; - $this->customer_id = $customer->id; - $this->firstName = $customer->first_name; - $this->lastName = $customer->last_name; - $this->email = $customer->email; - $this->gender = $customer->gender; - $this->birthDate = $customer->birth_date; - $this->birthDateFormatted = $customer->birth_date_formatted; - $this->optIn = (bool) $customer->opt_in; - $this->hasEnabledTwoFactor = (bool) $customer->two_factor_secret; - } - - public function saveFirstName(): void - { - $this->validate(['firstName' => 'sometimes|required']); - - $this->updateValue(field: 'first_name', value: $this->firstName); - - $this->firstNameUpdate = false; - $this->emit('profileUpdate'); - } - - public function saveLastName(): void - { - $this->validate(['lastName' => 'sometimes|required']); - - $this->updateValue(field: 'last_name', value: $this->lastName); - - $this->lastNameUpdate = false; - $this->emit('profileUpdate'); - } - - public function saveEmail(): void - { - $this->validate([ - 'email' => [ - 'sometimes', - 'required', - 'email', - Rule::unique(shopper_table('users'), 'email')->ignore($this->customer_id), - ], - ]); - - $this->updateValue(field: 'email', value: $this->email); - - $this->emailUpdate = false; - $this->emit('profileUpdate'); - } - - public function cancelEmail(): void - { - $this->emailUpdate = false; - $this->email = $this->customer->email; - } - - public function saveBirthDate(): void - { - $this->updateValue(field: 'birth_date', value: $this->birthDate); - - $this->birthDateUpdate = false; - $this->birthDateFormatted = $this->customer->birth_date_formatted; - } - - public function saveGender(): void - { - $this->updateValue(field: 'gender', value: $this->gender); - - $this->genderUpdate = false; - } - - public function updatedOptIn(): void - { - $this->updateValue(field: 'opt_in', value: $this->optIn); - } + public Model $customer; public function render(): View { - return view('shopper::livewire.customers.profile'); - } - - private function updateValue(string $field, mixed $value): void - { - $this->customer->update([$field => $value]); - - Notification::make() - ->body(__('shopper::notifications.actions.update', ['item' => __('shopper::words.customer')])) - ->success() - ->send(); + return view('shopper::livewire.components.customers.profile'); } } diff --git a/packages/admin/src/Livewire/Components/Customers/Show.php b/packages/admin/src/Livewire/Components/Customers/Show.php deleted file mode 100755 index 8012a978a..000000000 --- a/packages/admin/src/Livewire/Components/Customers/Show.php +++ /dev/null @@ -1,78 +0,0 @@ -customer = $customer->load('addresses'); - $this->user_id = $customer->id; - $this->email = $customer->email; - $this->last_name = $customer->last_name; - $this->first_name = $customer->first_name; - $this->picture = $customer->picture; - } - - public function profileUpdate(): void - { - $this->email = $this->customer->email; - $this->last_name = $this->customer->last_name; - $this->first_name = $this->customer->first_name; - $this->picture = $this->customer->picture; - } - - public function store(): void - { - $this->validate($this->rules()); - - (new UserRepository())->getById($this->customer->id)->update([ - 'email' => $this->email, - 'last_name' => $this->last_name, - 'first_name' => $this->first_name, - ]); - - session()->flash('success', __('shopper::notifications.actions.update', ['item' => __('shopper::words.customer')])); - - $this->redirectRoute('shopper.customers.index'); - } - - public function rules(): array - { - return [ - 'email' => [ - 'required', - 'max:150', - Rule::unique(shopper_table('users'), 'email')->ignore($this->user_id), - ], - 'last_name' => 'sometimes|required', - 'first_name' => 'sometimes|required', - ]; - } - - public function render(): View - { - return view('shopper::livewire.customers.show'); - } -} diff --git a/packages/admin/src/Livewire/Components/Settings/Inventories/InventoryForm.php b/packages/admin/src/Livewire/Components/Settings/Inventories/InventoryForm.php index 69db63e60..bfa78875b 100644 --- a/packages/admin/src/Livewire/Components/Settings/Inventories/InventoryForm.php +++ b/packages/admin/src/Livewire/Components/Settings/Inventories/InventoryForm.php @@ -12,9 +12,9 @@ use Illuminate\Contracts\View\View; use Illuminate\Support\Str; use Livewire\Component; +use Shopper\Components\Form\AddressField; use Shopper\Components\Section; use Shopper\Components\Separator; -use Shopper\Core\Models\Country; use Shopper\Core\Models\Inventory; class InventoryForm extends Component implements HasForms @@ -69,31 +69,7 @@ public function form(Form $form): Form ->description(__('shopper::pages/settings.location.address_summary')) ->aside() ->compact() - ->schema([ - Forms\Components\TextInput::make('street_address') - ->label(__('shopper::layout.forms.label.street_address')) - ->placeholder('Akwa Avenue 34...') - ->columnSpan('full') - ->required(), - Forms\Components\TextInput::make('street_address_plus') - ->label(__('shopper::layout.forms.label.street_address_plus')) - ->columnSpan('full'), - Forms\Components\TextInput::make('city') - ->label(__('shopper::layout.forms.label.city')) - ->required(), - Forms\Components\TextInput::make('zipcode') - ->label(__('shopper::layout.forms.label.postal_code')) - ->required(), - Forms\Components\Select::make('country_id') - ->label(__('shopper::layout.forms.label.country')) - ->options(Country::query()->pluck('name', 'id')) - ->searchable() - ->required() - ->columnSpan('full'), - Forms\Components\TextInput::make('phone_number') - ->label(__('shopper::layout.forms.label.phone_number')) - ->columnSpan('full'), - ]) + ->schema(AddressField::make()) ->columns(), ]) ->statePath('data') diff --git a/packages/admin/src/Livewire/Components/Settings/Legal/PolicyForm.php b/packages/admin/src/Livewire/Components/Settings/Legal/PolicyForm.php index 7019e968a..7675269b8 100644 --- a/packages/admin/src/Livewire/Components/Settings/Legal/PolicyForm.php +++ b/packages/admin/src/Livewire/Components/Settings/Legal/PolicyForm.php @@ -33,7 +33,8 @@ public function form(Form $form): Form ->schema([ Components\Hidden::make('title'), Components\Toggle::make('is_enabled') - ->label(__('shopper::layout.forms.actions.enabled')), + ->label(__('shopper::layout.forms.actions.enabled')) + ->onColor('success'), Components\RichEditor::make('content') ->label(__('shopper::layout.forms.label.content')) ->required(), diff --git a/packages/admin/src/Livewire/Modals/DeleteCustomer.php b/packages/admin/src/Livewire/Modals/DeleteCustomer.php deleted file mode 100755 index f33ef2d5d..000000000 --- a/packages/admin/src/Livewire/Modals/DeleteCustomer.php +++ /dev/null @@ -1,38 +0,0 @@ -customerId = $customerId; - } - - public function delete(): void - { - (new UserRepository())->getById($this->customerId)->delete(); - - session()->flash('success', __('shopper::pages/customers.modal.success_message')); - - $this->redirectRoute('shopper.customers.index'); - } - - public static function modalMaxWidth(): string - { - return 'xl'; - } - - public function render(): View - { - return view('shopper::livewire.modals.delete-customer'); - } -} diff --git a/packages/admin/src/Livewire/Pages/Customers/Create.php b/packages/admin/src/Livewire/Pages/Customers/Create.php new file mode 100755 index 000000000..a4b52dffc --- /dev/null +++ b/packages/admin/src/Livewire/Pages/Customers/Create.php @@ -0,0 +1,174 @@ +authorize('add_customers'); + $this->form->fill(); + } + + public function form(Form $form): Form + { + return $form + ->schema([ + Section::make(__('shopper::pages/customers.overview')) + ->description(__('shopper::pages/customers.overview_description')) + ->compact() + ->aside() + ->columns() + ->schema([ + Components\TextInput::make('first_name') + ->label(__('shopper::layout.forms.label.first_name')) + ->required(), + Components\TextInput::make('last_name') + ->label(__('shopper::layout.forms.label.last_name')) + ->required(), + Components\TextInput::make('email') + ->label(__('shopper::layout.forms.label.email')) + ->prefixIcon('untitledui-mail') + ->autocomplete('email-address') + ->email() + ->unique() + ->required(), + Components\TextInput::make('phone_number') + ->label(__('shopper::layout.forms.label.phone_number')) + ->hint(__('shopper::layout.forms.label.optional')) + ->tel(), + GenderField::make(), + ]), + Separator::make(), + Section::make(__('shopper::pages/customers.security_title')) + ->description(__('shopper::pages/customers.security_description')) + ->compact() + ->aside() + ->schema([ + Components\TextInput::make('password') + ->label(__('shopper::layout.forms.label.password')) + ->password() + ->revealable() + ->required() + ->hintAction( + Components\Actions\Action::make(__('shopper::words.generate')) + ->color('info') + ->action(function (Set $set): void { + $set('password', Str::password(12)); + }), + ) + ->confirmed() + ->dehydrateStateUsing(fn (string $state): string => Hash::make($state)), + Components\TextInput::make('password_confirmation') + ->label(__('shopper::layout.forms.label.confirm_password')) + ->password() + ->revealable() + ->required(), + Components\Hidden::make('_password'), + ]), + Separator::make(), + Section::make(__('shopper::pages/customers.address_title')) + ->description(__('shopper::pages/customers.address_description')) + ->compact() + ->aside() + ->columns() + ->schema(AddressField::make('address')), + Separator::make(), + Section::make(__('shopper::pages/customers.notification_title')) + ->description(__('shopper::pages/customers.notification_description')) + ->compact() + ->aside() + ->schema([ + Components\Checkbox::make('opt_in') + ->label(__('shopper::pages/customers.marketing_email')) + ->helperText(__('shopper::pages/customers.marketing_description')), + Components\Checkbox::make('send_mail') + ->label(__('shopper::pages/customers.send_credentials')) + ->helperText(__('shopper::pages/customers.credential_description')), + ]), + ]) + ->statePath('data') + ->model(config('auth.providers.users.model', User::class)); + } + + protected function onValidationError(ValidationException $exception): void + { + Notification::make() + ->title($exception->getMessage()) + ->danger() + ->send(); + } + + public function store(): void + { + $data = $this->form->getState(); + $customerData = Arr::except($data, ['address', 'send_mail', 'password_confirmation']); + $address = array_merge(Arr::only($data, ['address'])['address'], [ + 'first_name' => $data['first_name'], + 'last_name' => $data['last_name'], + 'is_default' => true, + 'type' => AddressType::SHIPPING, + ]); + + /** @var User $customer */ + $customer = (new UserRepository())->create(array_merge( + $customerData, + ['email_verified_at' => now()->toDateTimeString()], + )); + + $customer->assignRole(config('shopper.core.users.default_role')); + + $customer->addresses()->create($address); + + if ($data['send_mail']) { + $customer->notify(new CustomerSendCredentials($data['password_confirmation'])); + } + + Notification::make() + ->title(__('shopper::notifications.actions.create', ['item' => __('shopper::words.customer')])) + ->success() + ->send(); + + $this->redirectRoute(name: 'shopper.customers.index', navigate: true); + } + + public function render(): View + { + return view('shopper::livewire.pages.customers.create', [ + 'countries' => Cache::get( + key: 'countries-settings', + default: fn () => Country::query()->orderBy('name')->get() + ), + ]) + ->title(__('shopper::words.actions_label.add_new', ['name' => __('shopper::words.customer')])); + } +} diff --git a/packages/admin/src/Livewire/Pages/Customers/Index.php b/packages/admin/src/Livewire/Pages/Customers/Index.php new file mode 100755 index 000000000..cb62830f1 --- /dev/null +++ b/packages/admin/src/Livewire/Pages/Customers/Index.php @@ -0,0 +1,110 @@ +authorize('browse_customers'); + } + + public function table(Table $table): Table + { + return $table + ->query( + (new UserRepository()) + ->with('roles') + ->makeModel() + ->scopes('customers') + ->newQuery() + ) + ->columns([ + Tables\Columns\ViewColumn::make('first_name') + ->label(__('shopper::layout.forms.label.full_name')) + ->view('shopper::livewire.tables.cells.customers.name') + ->searchable() + ->sortable(), + Tables\Columns\ViewColumn::make('email') + ->label(__('shopper::layout.forms.label.email')) + ->view('shopper::livewire.tables.cells.customers.email') + ->searchable() + ->sortable(), + Tables\Columns\TextColumn::make('country') + ->label(__('shopper::layout.forms.label.country')) + ->getStateUsing( + fn ($record): ?string => Country::find($record->addresses->first()?->country_id)?->name ?? null + ) + ->sortable(), + Tables\Columns\TextColumn::make('orders_count') + ->counts([ + 'orders' => fn (Builder $query) => $query->where('status', OrderStatus::PAID->value), + ]) + ->label(__('shopper::pages/customers.orders.placed')), + Tables\Columns\TextColumn::make('created_at') + ->label(__('shopper::layout.forms.label.registered_at')) + ->date() + ->sortable(), + ]) + ->filters([ + Tables\Filters\TernaryFilter::make('email_verified_at') + ->label(__('shopper::layout.forms.label.email_verified')) + ->nullable(), + Tables\Filters\Filter::make('created_at') + ->form([ + DatePicker::make('created_from') + ->native(false), + DatePicker::make('created_until') + ->native(false), + ]) + ->query(function (Builder $query, array $data): Builder { + return $query + ->when( + $data['created_from'], + fn (Builder $query, $date): Builder => $query->whereDate('created_at', '>=', $date), + ) + ->when( + $data['created_until'], + fn (Builder $query, $date): Builder => $query->whereDate('created_at', '<=', $date), + ); + }), + ]) + ->persistFiltersInSession() + ->actions([ + Tables\Actions\Action::make('view') + ->label(__('shopper::layout.forms.actions.view')) + ->color('info') + ->url(fn ($record): string => route('shopper.customers.show', $record)), + ]); + } + + public function render(): View + { + return view('shopper::livewire.pages.customers.index', [ + 'total' => (new UserRepository()) + ->makeModel() + ->scopes('customers') + ->count(), + ]) + ->title(__('shopper::layout.sidebar.customers')); + } +} diff --git a/packages/admin/src/Livewire/Pages/Customers/Show.php b/packages/admin/src/Livewire/Pages/Customers/Show.php new file mode 100755 index 000000000..7d5b83c0f --- /dev/null +++ b/packages/admin/src/Livewire/Pages/Customers/Show.php @@ -0,0 +1,56 @@ +label(__('shopper::layout.forms.actions.delete')) + ->requiresConfirmation() + ->icon('untitledui-trash') + ->color('danger') + ->action(function (): void { + $this->customer->delete(); + + Notification::make() + ->title(__('shopper::components.tables.messages.delete', ['name' => __('shopper::words.customer')])) + ->success() + ->send(); + + $this->redirectRoute(name: 'shopper.customers.index', navigate: true); + }); + } + + public function mount(int $user): void + { + $this->authorize('read_customers'); + + $this->customer = (new UserRepository())->with(['addresses', 'orders'])->getById($user); + } + + public function render(): View + { + return view('shopper::livewire.pages.customers.show') + ->title(__('shopper::words.actions_label.show', ['name' => $this->customer->full_name])); + } +} diff --git a/packages/admin/src/Livewire/Pages/Settings/Inventories/Browse.php b/packages/admin/src/Livewire/Pages/Settings/Inventories/Browse.php index 3b86dcd61..43de21f68 100755 --- a/packages/admin/src/Livewire/Pages/Settings/Inventories/Browse.php +++ b/packages/admin/src/Livewire/Pages/Settings/Inventories/Browse.php @@ -19,11 +19,11 @@ public function mount(): void public function render(): View { - return view('shopper::livewire.components.settings.inventories.browse', [ + return view('shopper::livewire.pages.settings.inventories.browse', [ 'inventories' => Inventory::query() ->with('country') ->get() - ->take(4), + ->take(config('shopper.admin.inventory-limit')), ])->title(__('shopper::words.locations')); } } diff --git a/packages/admin/src/Livewire/Pages/Settings/Inventories/Create.php b/packages/admin/src/Livewire/Pages/Settings/Inventories/Create.php index f87bab1ff..f88bd232f 100755 --- a/packages/admin/src/Livewire/Pages/Settings/Inventories/Create.php +++ b/packages/admin/src/Livewire/Pages/Settings/Inventories/Create.php @@ -18,7 +18,7 @@ public function mount(): void public function render(): View { - return view('shopper::livewire.components.settings.inventories.create') + return view('shopper::livewire.pages.settings.inventories.create') ->title(__('shopper::pages/settings.location.add')); } } diff --git a/packages/admin/src/Livewire/Pages/Settings/Inventories/Edit.php b/packages/admin/src/Livewire/Pages/Settings/Inventories/Edit.php index a4d999a7e..de5a439d1 100755 --- a/packages/admin/src/Livewire/Pages/Settings/Inventories/Edit.php +++ b/packages/admin/src/Livewire/Pages/Settings/Inventories/Edit.php @@ -23,7 +23,7 @@ public function mount(Inventory $inventory): void public function render(): View { - return view('shopper::livewire.components.settings.inventories.edit') + return view('shopper::livewire.pages.settings.inventories.edit') ->title(__('shopper::words.locations') . ' ~ ' . $this->inventory->name); } } diff --git a/packages/admin/src/Livewire/Pages/Settings/Team/Index.php b/packages/admin/src/Livewire/Pages/Settings/Team/Index.php index 849c9ebc3..24acd243e 100755 --- a/packages/admin/src/Livewire/Pages/Settings/Team/Index.php +++ b/packages/admin/src/Livewire/Pages/Settings/Team/Index.php @@ -6,7 +6,6 @@ use Filament\Notifications\Notification; use Illuminate\Contracts\View\View; -use Illuminate\Database\Eloquent\Builder; use Livewire\Attributes\Layout; use Livewire\Attributes\On; use Livewire\Component; @@ -41,9 +40,7 @@ public function render(): View 'users' => (new UserRepository()) ->with('roles') ->makeModel() - ->whereHas('roles', function (Builder $query): void { - $query->whereIn('name', [config('shopper.core.users.admin_role'), 'manager']); - }) + ->scopes('administrators') ->orderBy('created_at', 'desc') ->paginate(3), ]) diff --git a/packages/admin/src/Livewire/SlideOvers/CreateTeamMember.php b/packages/admin/src/Livewire/SlideOvers/CreateTeamMember.php index a6642b66a..017f94a9b 100644 --- a/packages/admin/src/Livewire/SlideOvers/CreateTeamMember.php +++ b/packages/admin/src/Livewire/SlideOvers/CreateTeamMember.php @@ -13,6 +13,7 @@ use Illuminate\Contracts\View\View; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; +use Shopper\Components\Form\GenderField; use Shopper\Components\Section; use Shopper\Core\Models\Role; use Shopper\Core\Models\User; @@ -49,6 +50,7 @@ public function form(Form $form): Form ->required() ->hintAction( Components\Actions\Action::make(__('shopper::words.generate')) + ->color('info') ->action(function (Set $set): void { $set('password', Str::password(16)); }), @@ -66,14 +68,7 @@ public function form(Form $form): Form Components\TextInput::make('last_name') ->label(__('shopper::layout.forms.label.last_name')) ->required(), - Components\Select::make('gender') - ->label(__('shopper::layout.forms.label.gender')) - ->options([ - 'male' => __('shopper::words.male'), - 'female' => __('shopper::words.female'), - ]) - ->default('male') - ->native(false), + GenderField::make(), Components\TextInput::make('phone_number') ->label(__('shopper::layout.forms.label.phone_number')) ->tel(), diff --git a/packages/admin/src/Providers/FeatureServiceProvider.php b/packages/admin/src/Providers/FeatureServiceProvider.php index 27a7091e2..d75dd98bf 100644 --- a/packages/admin/src/Providers/FeatureServiceProvider.php +++ b/packages/admin/src/Providers/FeatureServiceProvider.php @@ -15,6 +15,7 @@ final class FeatureServiceProvider extends ServiceProvider protected array $componentsConfig = [ 'brand', 'category', + 'customer', ]; protected string $root = __DIR__ . '/../..'; diff --git a/packages/admin/src/ShopperServiceProvider.php b/packages/admin/src/ShopperServiceProvider.php index c86c54558..983ee0e11 100755 --- a/packages/admin/src/ShopperServiceProvider.php +++ b/packages/admin/src/ShopperServiceProvider.php @@ -135,7 +135,6 @@ protected function getLivewireComponents(): array 'initialize-store-information' => Components\Initialization\Steps\StoreInformation::class, 'initialize-store-address' => Components\Initialization\Steps\StoreAddress::class, 'initialize-store-social-link' => Components\Initialization\Steps\StoreSocialLink::class, - 'forms.trix' => Components\Forms\Trix::class, 'forms.icon-picker' => Components\Forms\IconPicker::class, 'forms.uploads.multiple' => Components\Forms\Uploads\Multiple::class, 'forms.uploads.single' => Components\Forms\Uploads\Single::class, diff --git a/packages/core/config/core.php b/packages/core/config/core.php index 5eb25b3d8..2797dc89b 100755 --- a/packages/core/config/core.php +++ b/packages/core/config/core.php @@ -17,6 +17,7 @@ 'users' => [ 'admin_role' => 'administrator', + 'manager_role' => 'manager', 'default_role' => 'user', ], diff --git a/packages/core/database/migrations/2020_00_01_000000_create_user_addresses_table.php.php b/packages/core/database/migrations/2020_00_01_000000_create_user_addresses_table.php.php index eb56d1ca0..8ed612ca3 100755 --- a/packages/core/database/migrations/2020_00_01_000000_create_user_addresses_table.php.php +++ b/packages/core/database/migrations/2020_00_01_000000_create_user_addresses_table.php.php @@ -22,7 +22,7 @@ public function up(): void $table->string('city'); $table->string('phone_number')->nullable(); $table->boolean('is_default')->default(false); - $table->enum('type', ['billing', 'shipping']); + $table->enum('type', \Shopper\Core\Enum\AddressType::cases()); $this->addForeignKey($table, 'country_id', $this->getTableName('system_countries')); $this->addForeignKey($table, 'user_id', $this->getTableName('users'), false); diff --git a/packages/core/database/seeders/Auth/RolesTableSeeder.php b/packages/core/database/seeders/Auth/RolesTableSeeder.php index d2d08ef24..51090b6d6 100755 --- a/packages/core/database/seeders/Auth/RolesTableSeeder.php +++ b/packages/core/database/seeders/Auth/RolesTableSeeder.php @@ -16,22 +16,22 @@ public function run(): void Role::create([ 'name' => config('shopper.core.users.admin_role'), - 'display_name' => 'Administrator', - 'description' => 'Site administrator with access to shop admin panel and developer tools.', + 'display_name' => __('Administrator'), + 'description' => __('Site administrator with access to shop admin panel and developer tools.'), 'can_be_removed' => false, ]); Role::create([ 'name' => 'manager', - 'display_name' => 'Manager', - 'description' => 'Site manager with access to shop admin panel and publishing menus.', + 'display_name' => __('Manager'), + 'description' => __('Site manager with access to shop admin panel and publishing menus.'), 'can_be_removed' => false, ]); Role::create([ 'name' => config('shopper.core.users.default_role'), - 'display_name' => 'User', - 'description' => 'Site customer role with access on front site.', + 'display_name' => __('User'), + 'description' => __('Site customer role with access on front site.'), 'can_be_removed' => false, ]); diff --git a/packages/core/src/Enum/AddressType.php b/packages/core/src/Enum/AddressType.php new file mode 100644 index 000000000..15139f1a3 --- /dev/null +++ b/packages/core/src/Enum/AddressType.php @@ -0,0 +1,12 @@ + 'bg-yellow-100 text-yellow-800', self::REGISTER => 'bg-primary-100 text-primary-800', - self::PAID => 'bg-green-100 text-green-800', + self::PAID => 'bg-teal-100 text-teal-800', self::CANCELLED => 'bg-pink-100 text-pink-800', - self::COMPLETED => 'bg-purple-100 text-purple-800', + self::COMPLETED => 'bg-success-100 text-success-800', }; } diff --git a/packages/core/src/Models/Address.php b/packages/core/src/Models/Address.php index c719db895..fa1f92268 100755 --- a/packages/core/src/Models/Address.php +++ b/packages/core/src/Models/Address.php @@ -8,21 +8,24 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Shopper\Core\Enum\AddressType; /** * @property-read int $id * @property string $last_name - * @property string|null $first_name + * @property string | null $first_name + * @property string | null $company_name + * @property string | null $street_address + * @property string | null $street_address_plus + * @property string $zipcode + * @property string $city + * @property string | null $phone_number * @property bool $is_default */ class Address extends Model { use HasFactory; - public const TYPE_BILLING = 'billing'; - - public const TYPE_SHIPPING = 'shipping'; - protected $fillable = [ 'last_name', 'first_name', @@ -44,6 +47,7 @@ class Address extends Model protected $casts = [ 'is_default' => 'boolean', + 'type' => AddressType::class, ]; protected static function boot(): void diff --git a/packages/core/src/Models/User.php b/packages/core/src/Models/User.php index 7f115ed53..238566b1e 100755 --- a/packages/core/src/Models/User.php +++ b/packages/core/src/Models/User.php @@ -123,6 +123,23 @@ public function scopeResearch(Builder $query, $term): Builder ); } + public function scopeCustomers(Builder $query): Builder + { + return $query->whereHas('roles', function (Builder $query): void { + $query->where('name', config('shopper.core.users.default_role')); + }); + } + + public function scopeAdministrators(Builder $query): Builder + { + return $query->whereHas('roles', function (Builder $query): void { + $query->whereIn('name', [ + config('shopper.core.users.admin_role'), + config('shopper.core.users.manager_role'), + ]); + }); + } + public function addresses(): HasMany { return $this->hasMany(Address::class); diff --git a/packages/core/src/Rules/Phone.php b/packages/core/src/Rules/Phone.php deleted file mode 100755 index 9cbac8c26..000000000 --- a/packages/core/src/Rules/Phone.php +++ /dev/null @@ -1,59 +0,0 @@ -isPhone($value); - } - - public function message(): string - { - return __('Incorrect phone format for :attribute.'); - } - - protected function isPhone(string $value): bool - { - return $this->isE123($value) || $this->isE164($value) || $this->isNANP($value) || $this->isDigits($value); - } - - protected function isDigits(string $value): bool - { - $conditions = []; - $conditions[] = mb_strlen($value) >= 10; - $conditions[] = mb_strlen($value) <= 16; - $conditions[] = preg_match('/[^\\d]/i', $value) === 0; - - return (bool) array_product($conditions); - } - - protected function isE123(string $value): bool - { - return preg_match('/^(?:\((\+?\d+)?\)|\+?\d+) ?\d*(-?\d{2,3} ?){0,4}$/', $value) === 1; - } - - protected function isE164(string $value): bool - { - $conditions = []; - $conditions[] = mb_strpos($value, '+') === 0; - $conditions[] = mb_strlen($value) >= 9; - $conditions[] = mb_strlen($value) <= 16; - $conditions[] = preg_match('/[^\\d+]/i', $value) === 0; - - return (bool) array_product($conditions); - } - - protected function isNANP(string $value): bool - { - $conditions = []; - $conditions[] = preg_match('/^(?:\\+1|1)?\\s?-?\\(?\\d{3}\\)?(\\s|-)?\\d{3}-\\d{4}$/i', $value) > 0; - - return (bool) array_product($conditions); - } -}