mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
wip - registration client
This commit is contained in:
parent
22aa182250
commit
6f34e083ae
@ -33,23 +33,23 @@ class ContactRegisterController extends Controller
|
||||
}
|
||||
|
||||
$client = factory(Client::class)->create([
|
||||
'user_id' => $user->id, /** @wip */
|
||||
'user_id' => $company->owner()->id,
|
||||
'company_id' => $company->id
|
||||
]);
|
||||
|
||||
ClientContact::create([
|
||||
$client_contact = ClientContact::create([
|
||||
'first_name' => $request->first_name,
|
||||
'last_name' => $request->last_name,
|
||||
'email' => $request->email,
|
||||
'company_id' => $company->id,
|
||||
'password' => Hash::make($request->password),
|
||||
'client_id' => $client->id,
|
||||
'user_id' => $user->id, /** @wip */
|
||||
'is_primary' => true, /** @verify */
|
||||
'user_id' => $company->owner()->id,
|
||||
'is_primary' => true,
|
||||
'contact_key' => \Illuminate\Support\Str::random(40),
|
||||
]);
|
||||
|
||||
Auth::guard('contact')->login($client, true);
|
||||
Auth::guard('contact')->login($client_contact, true);
|
||||
|
||||
return redirect()->route('client.dashboard');
|
||||
}
|
||||
|
@ -37,8 +37,7 @@ class ContactRegister
|
||||
|
||||
$company = Company::where('company_key', $request->company_key)->firstOrFail();
|
||||
|
||||
abort_unless($company->getSetting('enable_client_registration'), 404);
|
||||
// abort_unless(true, 404);
|
||||
abort_unless($company->getSetting('client_can_register'), 404);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ class RegisterRequest extends FormRequest
|
||||
return [
|
||||
'first_name' => ['required', 'string', 'max:255'],
|
||||
'last_name' => ['required', 'string', 'max:255'],
|
||||
'phone' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:client_contacts'],
|
||||
'password' => ['required', 'string', 'min:6', 'confirmed'],
|
||||
];
|
||||
|
@ -84,6 +84,7 @@ class ClientContact extends Authenticatable implements HasLocalePreference
|
||||
'custom_value4',
|
||||
'email',
|
||||
'is_primary',
|
||||
'client_id',
|
||||
];
|
||||
|
||||
public function getEntityType()
|
||||
|
2
public/css/app.css
vendored
2
public/css/app.css
vendored
File diff suppressed because one or more lines are too long
2
public/js/clients/shared/pdf.js
vendored
2
public/js/clients/shared/pdf.js
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"/js/app.js": "/js/app.js?id=baf7fef12d5e65c3d9ff",
|
||||
"/css/app.css": "/css/app.css?id=8520caf5bca7a47876a2",
|
||||
"/css/app.css": "/css/app.css?id=73e166af0c645080c49e",
|
||||
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=0632d6281202800e0921",
|
||||
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=d7e708d66a9c769b4c6e",
|
||||
"/js/clients/payment_methods/authorize-ach.js": "/js/clients/payment_methods/authorize-ach.js?id=9e6495d9ae236b3cb5ad",
|
||||
@ -14,7 +14,7 @@
|
||||
"/js/clients/payments/sofort.js": "/js/clients/payments/sofort.js?id=ff4ad07a93bd9fb327c1",
|
||||
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=2fe0ad3e46ead2edb8c3",
|
||||
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=1c5d76fb5f98bd49f6c8",
|
||||
"/js/clients/shared/pdf.js": "/js/clients/shared/pdf.js?id=b70e8547534a34ea85e2",
|
||||
"/js/clients/shared/pdf.js": "/js/clients/shared/pdf.js?id=ba1182244cda0e0ffbeb",
|
||||
"/js/setup/setup.js": "/js/setup/setup.js?id=87653cfb4084aadea7a2",
|
||||
"/css/card-js.min.css": "/css/card-js.min.css?id=62afeb675235451543ad"
|
||||
}
|
||||
|
@ -2,70 +2,290 @@
|
||||
@section('meta_title', ctrans('texts.register'))
|
||||
|
||||
@section('body')
|
||||
<div class="grid lg:grid-cols-3">
|
||||
<div class="hidden lg:block col-span-1 bg-red-100 h-screen">
|
||||
<img src="https://www.invoiceninja.com/wp-content/uploads/2018/04/bg-home2018b.jpg" class="w-full h-screen object-cover" alt="Background image">
|
||||
</div>
|
||||
<div class="col-span-2 h-screen flex">
|
||||
<div class="m-auto md:w-1/2 lg:w-1/4">
|
||||
<div class="flex flex-col">
|
||||
<h1 class="text-center text-3xl">{{ ctrans('texts.register') }}</h1>
|
||||
<p class="block text-center text-gray-600">{{ ctrans('texts.register_label') }}</p>
|
||||
<form action="{{ route('client.register', request()->route('company_key')) }}" method="post" class="mt-6">
|
||||
@csrf
|
||||
<div class="flex flex-col">
|
||||
<label for="first_name" class="input-label">{{ ctrans('texts.first_name') }}</label>
|
||||
<input type="text" name="first_name" id="first_name" class="input" value="{{ old('first_name') }}" autofocus>
|
||||
<div class="grid lg:grid-cols-12 bg-gray-100 py-8">
|
||||
<div class="col-span-4 col-start-5">
|
||||
<h1 class="text-center text-3xl">{{ ctrans('texts.register') }}</h1>
|
||||
<p class="block text-center text-gray-600">{{ ctrans('texts.register_label') }}</p>
|
||||
|
||||
<form action="{{ route('client.register', request()->route('company_key')) }}" method="post">
|
||||
@csrf
|
||||
|
||||
<!-- Personal info, first name, last name, e-mail address .. -->
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900 mt-8">{{ ctrans('texts.profile') }}</h3>
|
||||
<p class="mt-1 text-sm leading-5 text-gray-500">
|
||||
{{ ctrans('texts.client_information_text') }}
|
||||
</p>
|
||||
<div class="shadow overflow-hidden rounded mt-4">
|
||||
<div class="px-4 py-5 bg-white sm:p-6">
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<section class="flex items-center">
|
||||
<label for="first_name" class="input-label">{{ ctrans('texts.first_name') }}</label>
|
||||
<section class="text-red-400 ml-1 text-sm">*</section>
|
||||
</section>
|
||||
<input id="first_name" class="input w-full" name="first_name" />
|
||||
@error('first_name')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="flex flex-col mt-4">
|
||||
<label for="last_name" class="input-label">{{ ctrans('texts.last_name') }}</label>
|
||||
<input type="text" name="last_name" id="last_name" class="input" value="{{ old('last_name') }}" autofocus>
|
||||
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<section class="flex items-center">
|
||||
<label for="last_name" class="input-label">{{ ctrans('texts.last_name') }}</label>
|
||||
<section class="text-red-400 ml-1 text-sm">*</section>
|
||||
</section>
|
||||
<input id="last_name" class="input w-full" name="last_name" />
|
||||
@error('last_name')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="flex flex-col mt-4">
|
||||
<label for="email" class="input-label">{{ ctrans('texts.email_address') }}</label>
|
||||
<input type="email" name="email" id="email" class="input" value="{{ old('email') }}" autofocus>
|
||||
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<section class="flex items-center">
|
||||
<label for="email_address" class="input-label">{{ ctrans('texts.email_address') }}</label>
|
||||
<section class="text-red-400 ml-1 text-sm">*</section>
|
||||
</section>
|
||||
<input id="email_address" class="input w-full" type="email" name="email" />
|
||||
@error('email')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="flex flex-col mt-4">
|
||||
<label for="password" class="input-label">{{ ctrans('texts.password') }}</label>
|
||||
<input type="password" name="password" id="password" class="input">
|
||||
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<section class="flex items-center">
|
||||
<label for="phone" class="input-label">{{ ctrans('texts.phone') }}</label>
|
||||
<section class="text-red-400 ml-1 text-sm">*</section>
|
||||
</section>
|
||||
<input id="phone" class="input w-full" name="phone" />
|
||||
@error('phone')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-span-6 sm:col-span-6 lg:col-span-3">
|
||||
<section class="flex items-center">
|
||||
<label for="password" class="input-label">{{ ctrans('texts.password') }}</label>
|
||||
<section class="text-red-400 ml-1 text-sm">*</section>
|
||||
</section>
|
||||
<input id="password" class="input w-full" name="password" type="password" />
|
||||
@error('password')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="flex flex-col mt-4">
|
||||
<label for="email" class="input-label">{{ ctrans('texts.password_confirmation') }}</label>
|
||||
<input type="password" name="password_confirmation" id="password_confirmation" class="input">
|
||||
|
||||
<div class="col-span-6 sm:col-span-3 lg:col-span-3">
|
||||
<section class="flex items-center">
|
||||
<label for="password_confirmation" class="input-label">{{ ctrans('texts.confirm_password') }}</label>
|
||||
<section class="text-red-400 ml-1 text-sm">*</section>
|
||||
</section>
|
||||
<input id="state" class="input w-full" name="password_confirmation" type="password" />
|
||||
@error('password_confirmation')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<button id="loginBtn" class="button button-primary button-block">
|
||||
{{ trans('texts.register') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Name, website -->
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900 mt-8">{{ ctrans('texts.website') }}</h3>
|
||||
<p class="mt-1 text-sm leading-5 text-gray-500">
|
||||
{{ ctrans('texts.make_sure_use_full_link') }}
|
||||
</p>
|
||||
<div class="shadow overflow-hidden rounded mt-4">
|
||||
<div class="px-4 py-5 bg-white sm:p-6">
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="street" class="input-label">@lang('texts.name')</label>
|
||||
<input id="name" class="input w-full" name="name" />
|
||||
@error('name')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="website" class="input-label">@lang('texts.website')</label>
|
||||
<input id="website" class="input w-full" name="last_name" />
|
||||
@error('website')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Client personal address -->
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900 mt-8">{{ ctrans('texts.personal_address') }}</h3>
|
||||
<p class="mt-1 text-sm leading-5 text-gray-500">
|
||||
{{ ctrans('texts.enter_your_personal_address') }}
|
||||
</p>
|
||||
<div class="shadow overflow-hidden rounded mt-4">
|
||||
<div class="px-4 py-5 bg-white sm:p-6">
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<label for="address1" class="input-label">@lang('texts.address1')</label>
|
||||
<input id="address1" class="input w-full" name="address1" />
|
||||
@error('address1')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="address2" class="input-label">@lang('texts.address2')</label>
|
||||
<input id="address2" class="input w-full" name="address2" />
|
||||
@error('address2')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="city" class="input-label">@lang('texts.city')</label>
|
||||
<input id="city" class="input w-full" name="city" />
|
||||
@error('city')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-2">
|
||||
<label for="state" class="input-label">@lang('texts.state')</label>
|
||||
<input id="state" class="input w-full" name="state" />
|
||||
@error('state')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-2">
|
||||
<label for="postal_code" class="input-label">@lang('texts.postal_code')</label>
|
||||
<input id="postal_code" class="input w-full" name="postal_code" />
|
||||
@error('postal_code')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-2">
|
||||
<label for="country" class="input-label">@lang('texts.country')</label>
|
||||
<select id="country" class="input w-full form-select" name="country">
|
||||
@foreach(App\Utils\TranslationHelper::getCountries() as $country)
|
||||
<option value="{{ $country->id }}">
|
||||
{{ $country->iso_3166_2 }} ({{ $country->name }})
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('country')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Client shipping address -->
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900 mt-8">{{ ctrans('texts.shipping_address') }}</h3>
|
||||
<p class="mt-1 text-sm leading-5 text-gray-500">
|
||||
{{ ctrans('texts.enter_your_shipping_address') }}
|
||||
</p>
|
||||
<div class="shadow overflow-hidden rounded mt-4">
|
||||
<div class="px-4 py-5 bg-white sm:p-6">
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<label for="shipping_address1" class="input-label">@lang('texts.shipping_address1')</label>
|
||||
<input id="shipping_address1" class="input w-full" name="shipping_address1" />
|
||||
@error('shipping_address1')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="shipping_address2" class="input-label">@lang('texts.shipping_address2')</label>
|
||||
<input id="shipping_address2" class="input w-full" name="shipping_address2" />
|
||||
@error('shipping_address2')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="shipping_city" class="input-label">@lang('texts.shipping_city')</label>
|
||||
<input id="shipping_city" class="input w-full" name="shipping_city" />
|
||||
@error('shipping_city')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-2">
|
||||
<label for="shipping_state" class="input-label">@lang('texts.shipping_state')</label>
|
||||
<input id="shipping_state" class="input w-full" name="shipping_state" />
|
||||
@error('shipping_state')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-2">
|
||||
<label for="shipping_postal_code" class="input-label">@lang('texts.shipping_postal_code')</label>
|
||||
<input id="shipping_postal_code" class="input w-full" name="shipping_postal_code" />
|
||||
@error('shipping_postal_code')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-span-4 sm:col-span-2">
|
||||
<label for="shipping_country" class="input-label">@lang('texts.shipping_country')</label>
|
||||
<select id="shipping_country" class="input w-full form-select" name="shipping_country">
|
||||
@foreach(App\Utils\TranslationHelper::getCountries() as $country)
|
||||
<option {{ $country == isset(auth()->user()->client->shipping_country->id) ? 'selected' : null }} value="{{ $country->id }}">
|
||||
{{ $country->iso_3166_2 }}
|
||||
({{ $country->name }})
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('country')
|
||||
<div class="validation validation-fail">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center mt-8">
|
||||
<span class="inline-flex items-center">
|
||||
<input type="checkbox" name="terms" class="form-checkbox mr-2 cursor-pointer" checked>
|
||||
<span class="text-sm text-gray-800">
|
||||
{{ ctrans('texts.i_agree') }} <a class="button-link" href="https://www.invoiceninja.com/self-hosting-terms-service/">{{ ctrans('texts.terms_of_service') }}</a> and <a class="button-link" href="https://www.invoiceninja.com/self-hosting-privacy-data-control/">{{ ctrans('texts.privacy_policy') }}</a>
|
||||
</span>
|
||||
</span>
|
||||
<button class="button button-primary">
|
||||
@lang('texts.save')
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
1
tailwind.config.js
vendored
1
tailwind.config.js
vendored
@ -5,6 +5,7 @@ module.exports = {
|
||||
'./resources/views/portal/ninja2020/**/*.blade.php',
|
||||
'./resources/views/email/**/*.blade.php',
|
||||
'./resources/views/themes/ninja2020/**/*.blade.php',
|
||||
'./resources/views/auth/**/*.blade.php',
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user