Browse Source

Separa views e controladores dos associados e colaboradores

usuarios_separados
Guilherme Capanema 6 years ago
parent
commit
204d2b87c4
36 changed files with 1055 additions and 82 deletions
  1. +1
    -1
      app/Http/Controllers/Associates/Auth/EmailVerificationController.php
  2. +1
    -1
      app/Http/Controllers/Associates/Auth/LogoutController.php
  3. +2
    -2
      app/Http/Controllers/Associates/Auth/PasswordResetController.php
  4. +34
    -0
      app/Http/Controllers/Collaborators/Auth/EmailVerificationController.php
  5. +18
    -0
      app/Http/Controllers/Collaborators/Auth/LogoutController.php
  6. +15
    -0
      app/Http/Controllers/Collaborators/Auth/PasswordResetController.php
  7. +2
    -2
      app/Http/Livewire/Associates/Auth/Login.php
  8. +2
    -2
      app/Http/Livewire/Associates/Auth/Passwords/Email.php
  9. +2
    -2
      app/Http/Livewire/Associates/Auth/Passwords/Reset.php
  10. +2
    -2
      app/Http/Livewire/Associates/Auth/Register/Individual.php
  11. +40
    -0
      app/Http/Livewire/Collaborators/Auth/Login.php
  12. +47
    -0
      app/Http/Livewire/Collaborators/Auth/Passwords/Email.php
  13. +92
    -0
      app/Http/Livewire/Collaborators/Auth/Passwords/Reset.php
  14. +181
    -0
      app/Http/Livewire/Collaborators/Auth/Register/Individual.php
  15. +1
    -1
      resources/views/associates/auth/login.blade.php
  16. +1
    -1
      resources/views/associates/auth/passwords/email.blade.php
  17. +1
    -1
      resources/views/associates/auth/passwords/reset.blade.php
  18. +1
    -1
      resources/views/associates/auth/register/individual.blade.php
  19. +8
    -0
      resources/views/collaborators/auth/login.blade.php
  20. +8
    -0
      resources/views/collaborators/auth/passwords/email.blade.php
  21. +10
    -0
      resources/views/collaborators/auth/passwords/reset.blade.php
  22. +8
    -0
      resources/views/collaborators/auth/register/individual.blade.php
  23. +0
    -0
      resources/views/livewire/associates/auth/login.blade.php
  24. +0
    -0
      resources/views/livewire/associates/auth/passwords/email.blade.php
  25. +0
    -0
      resources/views/livewire/associates/auth/passwords/reset.blade.php
  26. +0
    -0
      resources/views/livewire/associates/auth/register/individual.blade.php
  27. +74
    -0
      resources/views/livewire/collaborators/auth/login.blade.php
  28. +57
    -0
      resources/views/livewire/collaborators/auth/passwords/email.blade.php
  29. +65
    -0
      resources/views/livewire/collaborators/auth/passwords/reset.blade.php
  30. +302
    -0
      resources/views/livewire/collaborators/auth/register/individual.blade.php
  31. +19
    -5
      routes/web.php
  32. +8
    -8
      tests/Feature/Associates/Auth/LoginTest.php
  33. +1
    -1
      tests/Feature/Associates/Auth/LogoutTest.php
  34. +5
    -5
      tests/Feature/Associates/Auth/Passwords/EmailTest.php
  35. +9
    -9
      tests/Feature/Associates/Auth/Passwords/ResetTest.php
  36. +38
    -38
      tests/Feature/Associates/Auth/Register/IndividualTest.php

app/Http/Controllers/Auth/EmailVerificationController.php → app/Http/Controllers/Associates/Auth/EmailVerificationController.php View File


app/Http/Controllers/Auth/LogoutController.php → app/Http/Controllers/Associates/Auth/LogoutController.php View File


app/Http/Controllers/Auth/PasswordResetController.php → app/Http/Controllers/Associates/Auth/PasswordResetController.php View File


+ 34
- 0
app/Http/Controllers/Collaborators/Auth/EmailVerificationController.php View File

@ -0,0 +1,34 @@
<?php
namespace App\Http\Controllers\Collaborators\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Auth\Events\Verified;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\RedirectResponse;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Access\AuthorizationException;
class EmailVerificationController extends Controller
{
public function __invoke(string $id, string $hash): RedirectResponse
{
if (!hash_equals((string) $id, (string) Auth::user()->getKey())) {
throw new AuthorizationException();
}
if (!hash_equals((string) $hash, sha1(Auth::user()->getEmailForVerification()))) {
throw new AuthorizationException();
}
if (Auth::user()->hasVerifiedEmail()) {
return redirect(route('home'));
}
if (Auth::user()->markEmailAsVerified()) {
event(new Verified(Auth::user()));
}
return redirect(route('home'));
}
}

+ 18
- 0
app/Http/Controllers/Collaborators/Auth/LogoutController.php View File

@ -0,0 +1,18 @@
<?php
namespace App\Http\Controllers\Collaborators\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\RedirectResponse;
class LogoutController extends Controller
{
public function __invoke(): RedirectResponse
{
Auth::logout();
return redirect(route('home'));
}
}

+ 15
- 0
app/Http/Controllers/Collaborators/Auth/PasswordResetController.php View File

@ -0,0 +1,15 @@
<?php
namespace App\Http\Controllers\Collaborators\Auth;
use App\Http\Controllers\Controller;
class PasswordResetController extends Controller
{
public function __invoke($token)
{
return view('collaborators.auth.passwords.reset', [
'token' => $token,
]);
}
}

app/Http/Livewire/Auth/Login.php → app/Http/Livewire/Associates/Auth/Login.php View File


app/Http/Livewire/Auth/Passwords/Email.php → app/Http/Livewire/Associates/Auth/Passwords/Email.php View File


app/Http/Livewire/Auth/Passwords/Reset.php → app/Http/Livewire/Associates/Auth/Passwords/Reset.php View File


app/Http/Livewire/Auth/Register/Individual.php → app/Http/Livewire/Associates/Auth/Register/Individual.php View File


+ 40
- 0
app/Http/Livewire/Collaborators/Auth/Login.php View File

@ -0,0 +1,40 @@
<?php
namespace App\Http\Livewire\Collaborators\Auth;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class Login extends Component
{
/** @var string */
public $email = '';
/** @var string */
public $password = '';
/** @var bool */
public $remember = false;
public function authenticate()
{
$credentials = $this->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (!Auth::attempt($credentials, $this->remember)) {
$this->addError('email', trans('auth.failed'));
return;
}
redirect(route('home'));
}
public function render()
{
return view('livewire.collaborators.auth.login');
}
}

+ 47
- 0
app/Http/Livewire/Collaborators/Auth/Passwords/Email.php View File

@ -0,0 +1,47 @@
<?php
namespace App\Http\Livewire\Collaborators\Auth\Passwords;
use Livewire\Component;
use Illuminate\Support\Facades\Password;
class Email extends Component
{
/** @var string */
public $email;
/** @var string|null */
public $emailSentMessage = false;
public function sendResetPasswordLink()
{
$this->validate([
'email' => ['required', 'email'],
]);
$response = $this->broker()->sendResetLink(['email' => $this->email]);
if ($response == Password::RESET_LINK_SENT) {
$this->emailSentMessage = trans($response);
return;
}
$this->addError('email', trans($response));
}
/**
* Get the broker to be used during password reset.
*
* @return \Illuminate\Contracts\Auth\PasswordBroker
*/
public function broker()
{
return Password::broker();
}
public function render()
{
return view('livewire.collaborators.auth.passwords.email');
}
}

+ 92
- 0
app/Http/Livewire/Collaborators/Auth/Passwords/Reset.php View File

@ -0,0 +1,92 @@
<?php
namespace App\Http\Livewire\Collaborators\Auth\Passwords;
use App\Providers\RouteServiceProvider;
use Livewire\Component;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Auth\Events\PasswordReset;
class Reset extends Component
{
/** @var string */
public $token;
/** @var string */
public $email;
/** @var string */
public $password;
/** @var string */
public $passwordConfirmation;
public function mount($token)
{
$this->token = $token;
}
public function resetPassword()
{
$this->validate([
'token' => 'required',
'email' => 'required|email',
'password' => 'required|min:8|same:passwordConfirmation',
]);
$response = $this->broker()->reset(
[
'token' => $this->token,
'email' => $this->email,
'password' => $this->password
],
function ($user, $password) {
$user->password = Hash::make($password);
$user->setRememberToken(Str::random(60));
$user->save();
event(new PasswordReset($user));
$this->guard()->login($user);
}
);
if ($response == Password::PASSWORD_RESET) {
session()->flash(trans($response));
return redirect(route('home'));
}
$this->addError('email', trans($response));
}
/**
* Get the broker to be used during password reset.
*
* @return \Illuminate\Contracts\Auth\PasswordBroker
*/
public function broker()
{
return Password::broker();
}
/**
* Get the guard to be used during password reset.
*
* @return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
public function render()
{
return view('livewire.collaborators.auth.passwords.reset');
}
}

+ 181
- 0
app/Http/Livewire/Collaborators/Auth/Register/Individual.php View File

@ -0,0 +1,181 @@
<?php
namespace App\Http\Livewire\Collaborators\Auth\Register;
use App\Providers\RouteServiceProvider;
use App\Associate;
use App\AssociateCategory;
use App\AssociateNature;
use App\AssociateType;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Livewire\Component;
class Individual extends Component
{
/** @var string */
public $name = '';
/** @var string */
public $birthday = '';
/** @var array */
public $document = [
'type' => 'cpf',
'number' => '',
];
/** @var array */
public $address = [
'city' => '',
'complement' => '',
'country' => 'BR',
'neighbourhood' => '',
'number' => '',
'postcode' => '',
'state' => '',
'street' => '',
];
/** @var array */
public $profile = [
'gender' => '',
'occupation' => '',
'scholarity' => '',
'phone' => '',
'secondary_emails' => '',
'website' => '',
'social' => '',
'expectation' => '',
'bike_use' => '',
'org_participation' => '',
'bike_activities' => '',
'comments' => '',
'ucb_comments' => '',
];
/** @var string */
public $email = '';
/** @var string */
public $discussion = '';
/** @var int */
public $contribution = null;
public function updated($field)
{
$this->validateOnly($field, [
'address.city' => ['string'],
'address.complement' => ['string'],
'address.country' => ['string'],
'address.neighbourhood' => ['string'],
'address.number' => ['string'],
'address.postcode' => ['string'],
'address.state' => ['string'],
'address.street' => ['string'],
'birthday' => ['date_format:d/m/Y'],
'contribution' => ['numeric'],
'discussion' => ['string', 'in:all,daily,occasional'],
'document.number' => ['string'],
'document.type' => ['string', 'in:cpf,identity,passport'],
'email' => ['email', 'unique:associates'],
'profile.bike_activities' => ['string'],
'profile.bike_use' => ['string'],
'profile.comments' => ['string'],
'profile.expectation' => ['string'],
'profile.gender' => ['string', 'in:male,female,other'],
'profile.occupation' => ['string'],
'profile.org_participation' => ['string'],
'profile.phone' => ['string'],
'profile.scholarity' => ['string', 'in:primary-school,high-school,bachelor,master,phd'],
'profile.secondary_emails' => ['string'],
'profile.social' => ['string'],
'profile.ucb_comments' => ['string'],
'profile.website' => ['string'],
]);
if ($this->address['country'] === 'BR' && $field === 'address.postcode') {
$postcode = Str::slug($this->address['postcode'], '');
try {
$response = Http::timeout(5)->get("https://viacep.com.br/ws/$postcode/json");
if ($response->ok()) {
$address = $response->json();
$this->address['city'] = $response['localidade'];
$this->address['neighbourhood'] = $response['bairro'];
$this->address['state'] = $response['uf'];
$this->address['street'] = $response['logradouro'];
$this->dispatchBrowserEvent('address-autofilled');
}
} catch (\Illuminate\Http\Client\ConnectionException $exception) {
// TODO: show error to associate
}
}
}
public function register()
{
$this->validate([
'address.city' => ['required', 'string'],
'address.complement' => ['nullable', 'string'],
'address.country' => ['required', 'string'],
'address.neighbourhood' => ['required', 'string'],
'address.number' => ['required', 'string'],
'address.postcode' => ['required', 'string'],
'address.state' => ['required', 'string'],
'address.street' => ['required', 'string'],
'birthday' => ['required', 'date_format:d/m/Y'],
'contribution' => ['required', 'numeric'],
'discussion' => ['required', 'string', 'in:all,daily,occasional'],
'document.number' => ['required', 'string'],
'document.type' => ['required', 'string', 'in:cpf,identity,passport'],
'email' => ['required', 'email', 'unique:associates'],
'name' => ['required'],
'profile.bike_activities' => ['nullable', 'string'],
'profile.bike_use' => ['nullable', 'string'],
'profile.comments' => ['nullable', 'string'],
'profile.expectation' => ['nullable', 'string'],
'profile.gender' => ['required', 'string', 'in:male,female,other'],
'profile.occupation' => ['required', 'string'],
'profile.org_participation' => ['nullable', 'string'],
'profile.phone' => ['required', 'string'],
'profile.scholarity' => ['required', 'string', 'in:primary-school,high-school,bachelor,master,phd'],
'profile.secondary_emails' => ['nullable', 'string'],
'profile.social' => ['nullable', 'string'],
'profile.ucb_comments' => ['nullable', 'string'],
'profile.website' => ['nullable', 'string'],
]);
$associate = new Associate([
'address' => $this->address,
'birthday' => Carbon::createFromFormat('d/m/Y', $this->birthday),
'contribution' => $this->contribution,
'discussion' => $this->discussion,
'document' => $this->document,
'email' => $this->email,
'name' => $this->name,
'profile' => $this->profile,
]);
$associate->associate_category_id = AssociateCategory::where('key', 'individual')->first()->id;
$associate->associate_nature_id = AssociateNature::where('key', 'individual')->first()->id;
$associate->associate_type_id = AssociateType::where('key', 'individual')->first()->id;
$associate->save();
Auth::login($associate, true);
redirect(route('home'));
}
public function render()
{
return view('livewire.collaborators.auth.register.individual');
}
}

resources/views/auth/login.blade.php → resources/views/associates/auth/login.blade.php View File


resources/views/auth/passwords/email.blade.php → resources/views/associates/auth/passwords/email.blade.php View File


resources/views/auth/passwords/reset.blade.php → resources/views/associates/auth/passwords/reset.blade.php View File


resources/views/auth/register/individual.blade.php → resources/views/associates/auth/register/individual.blade.php View File


+ 8
- 0
resources/views/collaborators/auth/login.blade.php View File

@ -0,0 +1,8 @@
@extends('layouts.auth')
@section('title', 'Sign in to your account')
@section('content')
<div>
@livewire('collaborators.auth.login')
</div>
@endsection

+ 8
- 0
resources/views/collaborators/auth/passwords/email.blade.php View File

@ -0,0 +1,8 @@
@extends('layouts.auth')
@section('title', 'Reset password')
@section('content')
<div>
@livewire('collaborators.auth.passwords.email')
</div>
@endsection

+ 10
- 0
resources/views/collaborators/auth/passwords/reset.blade.php View File

@ -0,0 +1,10 @@
@extends('layouts.auth')
@section('title', 'Reset password')
@section('content')
<div>
@livewire('collaborators.auth.passwords.reset', [
'token' => $token
])
</div>
@endsection

+ 8
- 0
resources/views/collaborators/auth/register/individual.blade.php View File

@ -0,0 +1,8 @@
@extends('layouts.auth')
@section('title', __('user_categories.individual'))
@section('content')
<div>
@livewire('collaborators.auth.register.individual')
</div>
@endsection

resources/views/livewire/auth/login.blade.php → resources/views/livewire/associates/auth/login.blade.php View File


resources/views/livewire/auth/passwords/email.blade.php → resources/views/livewire/associates/auth/passwords/email.blade.php View File


resources/views/livewire/auth/passwords/reset.blade.php → resources/views/livewire/associates/auth/passwords/reset.blade.php View File


resources/views/livewire/auth/register/individual.blade.php → resources/views/livewire/associates/auth/register/individual.blade.php View File


+ 74
- 0
resources/views/livewire/collaborators/auth/login.blade.php View File

@ -0,0 +1,74 @@
<div>
<div class="sm:mx-auto sm:w-full sm:max-w-md">
<a href="{{ route('home') }}">
<x-logo class="w-auto h-16 mx-auto text-green-600" />
</a>
<h2 class="mt-6 text-3xl font-extrabold text-center text-gray-900 leading-9">
{{ __('auth.login') }}
</h2>
<p class="mt-2 text-sm text-center text-gray-600 leading-5 max-w">
Ou
<a href="{{ route('register') }}" class="font-medium text-green-600 hover:text-green-500 lowercase focus:outline-none focus:underline transition ease-in-out duration-150">
{{ __('auth.register') }}
</a>
</p>
</div>
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div class="px-4 py-8 bg-white shadow sm:rounded-lg sm:px-10">
<form wire:submit.prevent="authenticate">
<div>
<label for="email" class="block text-sm font-medium text-gray-700 leading-5">
{{ __('users.attributes.email') }}
</label>
<div class="mt-1 rounded-md shadow-sm">
<input wire:model.lazy="email" id="email" name="email" type="email" required autofocus class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md placeholder-gray-400 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5 @error('email') border-red-300 text-red-900 placeholder-red-300 focus:border-red-300 focus:shadow-outline-red @enderror" />
</div>
@error('email')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div class="mt-6">
<label for="password" class="block text-sm font-medium text-gray-700 leading-5">
{{ __('users.attributes.password') }}
</label>
<div class="mt-1 rounded-md shadow-sm">
<input wire:model.lazy="password" id="password" type="password" required class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md placeholder-gray-400 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5 @error('password') border-red-300 text-red-900 placeholder-red-300 focus:border-red-300 focus:shadow-outline-red @enderror" />
</div>
@error('password')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div class="flex items-center justify-between mt-6">
<div class="flex items-center">
<input wire:model.lazy="remember" id="remember" type="checkbox" class="form-checkbox w-4 h-4 text-green-600 transition duration-150 ease-in-out" />
<label for="remember" class="block ml-2 text-sm text-gray-900 leading-5">
{{ __('auth.remember') }}
</label>
</div>
<div class="text-sm leading-5">
<a href="{{ route('password.request') }}" class="font-medium text-green-600 hover:text-green-500 focus:outline-none focus:underline transition ease-in-out duration-150">
{{ __('auth.forgot-password') }}
</a>
</div>
</div>
<div class="mt-6">
<span class="block w-full rounded-md shadow-sm">
<button type="submit" class="flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-500 focus:outline-none focus:border-green-700 focus:shadow-outline-green active:bg-green-700 transition duration-150 ease-in-out">
{{ __('auth.sign-in') }}
</button>
</span>
</div>
</form>
</div>
</div>
</div>

+ 57
- 0
resources/views/livewire/collaborators/auth/passwords/email.blade.php View File

@ -0,0 +1,57 @@
<div>
<div class="sm:mx-auto sm:w-full sm:max-w-md">
<a href="{{ route('home') }}">
<x-logo class="w-auto h-16 mx-auto text-green-600" />
</a>
<h2 class="mt-6 text-3xl font-extrabold text-center text-gray-900 leading-9">
Reset password
</h2>
</div>
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div class="px-4 py-8 bg-white shadow sm:rounded-lg sm:px-10">
@if ($emailSentMessage)
<div class="rounded-md bg-green-50 p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-green-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
</svg>
</div>
<div class="ml-3">
<p class="text-sm leading-5 font-medium text-green-800">
{{ $emailSentMessage }}
</p>
</div>
</div>
</div>
@else
<form wire:submit.prevent="sendResetPasswordLink">
<div>
<label for="email" class="block text-sm font-medium text-gray-700 leading-5">
Email address
</label>
<div class="mt-1 rounded-md shadow-sm">
<input wire:model.lazy="email" id="email" name="email" type="email" required autofocus class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md placeholder-gray-400 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5 @error('email') border-red-300 text-red-900 placeholder-red-300 focus:border-red-300 focus:shadow-outline-red @enderror" />
</div>
@error('email')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div class="mt-6">
<span class="block w-full rounded-md shadow-sm">
<button type="submit" class="flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-500 focus:outline-none focus:border-green-700 focus:shadow-outline-green active:bg-green-700 transition duration-150 ease-in-out">
Send password reset link
</button>
</span>
</div>
</form>
@endif
</div>
</div>
</div>

+ 65
- 0
resources/views/livewire/collaborators/auth/passwords/reset.blade.php View File

@ -0,0 +1,65 @@
<div>
<div class="sm:mx-auto sm:w-full sm:max-w-md">
<a href="{{ route('home') }}">
<x-logo class="w-auto h-16 mx-auto text-green-600" />
</a>
<h2 class="mt-6 text-3xl font-extrabold text-center text-gray-900 leading-9">
Reset password
</h2>
</div>
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div class="px-4 py-8 bg-white shadow sm:rounded-lg sm:px-10">
<form wire:submit.prevent="resetPassword">
<input wire:model="token" type="hidden">
<div>
<label for="email" class="block text-sm font-medium text-gray-700 leading-5">
Email address
</label>
<div class="mt-1 rounded-md shadow-sm">
<input wire:model.lazy="email" id="email" type="email" required autofocus class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md placeholder-gray-400 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5 @error('email') border-red-300 text-red-900 placeholder-red-300 focus:border-red-300 focus:shadow-outline-red @enderror" />
</div>
@error('email')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div class="mt-6">
<label for="password" class="block text-sm font-medium text-gray-700 leading-5">
Password
</label>
<div class="mt-1 rounded-md shadow-sm">
<input wire:model.lazy="password" id="password" type="password" required class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md placeholder-gray-400 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5 @error('password') border-red-300 text-red-900 placeholder-red-300 focus:border-red-300 focus:shadow-outline-red @enderror" />
</div>
@error('password')
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div class="mt-6">
<label for="password_confirmation" class="block text-sm font-medium text-gray-700 leading-5">
Confirm Password
</label>
<div class="mt-1 rounded-md shadow-sm">
<input wire:model.lazy="passwordConfirmation" id="password_confirmation" type="password" required class="block w-full px-3 py-2 placeholder-gray-400 border border-gray-300 appearance-none rounded-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5" />
</div>
</div>
<div class="mt-6">
<span class="block w-full rounded-md shadow-sm">
<button type="submit" class="flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-500 focus:outline-none focus:border-green-700 focus:shadow-outline-green active:bg-green-700 transition duration-150 ease-in-out">
Reset password
</button>
</span>
</div>
</form>
</div>
</div>
</div>

+ 302
- 0
resources/views/livewire/collaborators/auth/register/individual.blade.php View File

@ -0,0 +1,302 @@
<div>
<div class="sm:mx-auto sm:w-full sm:max-w-md">
<a href="{{ route('home') }}">
<x-logo class="w-32 h-auto mx-auto text-green-600" />
</a>
<h2 class="mt-6 text-3xl font-extrabold text-center text-gray-900 leading-9">
{{ __('user_categories.individual') }}
</h2>
<p class="mt-2 text-sm text-center text-gray-600 leading-5 max-w">
Ou
<a href="{{ route('login') }}" class="font-medium text-green-600 hover:text-green-500 lowercase focus:outline-none focus:underline transition ease-in-out duration-150">
{{ __('auth.login') }}
</a>
</p>
</div>
<form wire:submit.prevent="register" class="max-w-7xl mx-auto">
<div class="flex flex-wrap pt-8 border-t border-gray-200 mt-8">
<div class="lg:pr-6 w-full lg:w-1/3">
<h2 class="text-2xl font-medium">
Informações pessoais
</h2>
<p class="text-gray-400 mt-2">
Conte-nos um pouco sobre você.
</p>
</div>
<div class="lg:pl-6 w-full lg:w-2/3">
<div class="px-4 py-8 bg-white shadow sm:rounded-lg sm:px-10 space-y-6">
<x-input.group label="{{ __('users.attributes.name') }}" for="name" :error="$errors->first('name')">
<x-input.text wire:model.lazy="name" id="name" :state="$errors->has('name') ? false : null" required autofocus />
</x-input.group>
<x-input.group label="{{ __('users.attributes.birthday') }}" for="birthday" :error="$errors->first('birthday')">
<x-input.text wire:model.lazy="birthday" id="birthday" mask="date" placeholder="dd/mm/yyyy" :state="$errors->has('birthday') ? false : null" required />
</x-input.group>
<x-input.radio-group label="{{ __('users.attributes.profile.gender') }}" :inline="true" :error="$errors->first('profile.gender')">
<x-input.radio wire:model.lazy="profile.gender" name="profile-gender" label="Homem" value="male" :state="$errors->has('profile.gender') ? false : null" required />
<x-input.radio wire:model.lazy="profile.gender" name="profile-gender" label="Mulher" value="female" :state="$errors->has('profile.gender') ? false : null" required />
<x-input.radio wire:model.lazy="profile.gender" name="profile-gender" label="Outro" value="other" :state="$errors->has('profile.gender') ? false : null" required />
</x-input-radio-group>
<div class="flex flex-wrap -mx-2">
<x-input.group class="px-2 w-full lg:w-1/2 mt-6 lg:mt-0" label="{{ __('users.attributes.document.type') }}" for="document-type" :error="$errors->first('document.type')">
<x-input.select wire:model.lazy="document.type" id="document-type">
<option value="cpf">CPF</option>
<option value="identity">Carteira de Identidade</option>
<option value="passport">Passaporte</option>
</x-input.select>
</x-input.group>
<x-input.group class="px-2 w-full lg:w-1/2 mt-6 lg:mt-0" label="{{ __('users.attributes.document.number') }}" for="document-number" :error="$errors->first('document.number')">
<x-input.text wire:model.lazy="document.number" id="document-number" :state="$errors->has('document.number') ? false : null" required />
</x-input.group>
</div>
<x-input.group label="{{ __('users.attributes.profile.occupation') }}" for="profile-occupation" :error="$errors->first('profile.occupation')">
<x-input.text wire:model.lazy="profile.occupation" id="profile-occupation" placeholder="Profissão ou ocupação principal" :state="$errors->has('profile.occupation') ? false : null" required />
</x-input.group>
<x-input.radio-group label="{{ __('users.attributes.profile.scholarity') }}" :error="$errors->first('profile.scholarity')">
<x-input.radio wire:model.lazy="profile.scholarity" name="profile-scholarity" label="Ensino fundamental" value="primary-school" :state="$errors->has('profile.scholarity') ? false : null" required />
<x-input.radio wire:model.lazy="profile.scholarity" name="profile-scholarity" label="Ensino médio" value="high-school" :state="$errors->has('profile.scholarity') ? false : null" required />
<x-input.radio wire:model.lazy="profile.scholarity" name="profile-scholarity" label="Graduação" value="bachelor" :state="$errors->has('profile.scholarity') ? false : null" required />
<x-input.radio wire:model.lazy="profile.scholarity" name="profile-scholarity" label="Mestrado" value="master" :state="$errors->has('profile.scholarity') ? false : null" required />
<x-input.radio wire:model.lazy="profile.scholarity" name="profile-scholarity" label="Doutorado" value="phd" :state="$errors->has('profile.scholarity') ? false : null" required />
</x-input.radio-group>
</div>
</div>
</div>
<div class="flex flex-wrap pt-8 border-t border-gray-200 mt-8">
<div class="lg:pr-6 w-full lg:w-1/3">
<h2 class="text-2xl font-medium">
Dados de contato
</h2>
<p class="text-gray-400 mt-2">
Endereço e meios de comunicação digitais.
</p>
</div>
<div class="lg:pl-6 w-full lg:w-2/3">
<div class="px-4 py-8 bg-white shadow sm:rounded-lg sm:px-10 space-y-6">
<div x-data="{}" class="flex flex-wrap -mx-2">
<x-input.group class="px-2 w-full lg:w-1/2" label="{{ __('users.attributes.address.country') }}" for="address-country" :error="$errors->first('address.country')">
<x-input.select wire:model="address.country" @input="document.getElementById('address-postcode').dispatchEvent(new Event('refreshMask', {detail: {mask: null}}))" id="address-country" :state="$errors->has('address.country') ? false : null" required>
@foreach (\App\Country::all() as $country)
<option value="{{ $country->code }}">{{ __('countries.' . $country->code) }}</option>
@endforeach
</x-input.select>
</x-input.group>
@if ($address['country'] === 'BR')
<x-input.group class="px-2 w-full lg:w-1/2" label="{{ __('users.attributes.address.postcode') }}" for="address-postcode-masked" :error="$errors->first('address.postcode')">
<x-input.text wire:model.lazy="address.postcode" id="address-postcode-masked" mask="postcode" :state="$errors->has('address.postcode') ? false : null" required />
</x-input.group>
@else
<x-input.group class="px-2 w-full lg:w-1/2" label="{{ __('users.attributes.address.postcode') }}" for="address-postcode" :error="$errors->first('address.postcode')">
<x-input.text wire:model.lazy="address.postcode" id="address-postcode" :state="$errors->has('address.postcode') ? false : null" required />
</x-input.group>
@endif
</div>
<x-input.group label="{{ __('users.attributes.address.street') }}" for="address-street" :error="$errors->first('address.street')">
<x-input.text wire:model.lazy="address.street" wire:target="address.postcode" wire:loading.attr="disabled" id="address-street" :state="$errors->has('address.street') ? false : null" required />
</x-input.group>
<div class="flex flex-wrap -mx-2">
<x-input.group x-data="{}" class="px-2 w-full lg:w-1/4 mt-6 lg:mt-0" label="{{ __('users.attributes.address.number') }}" for="address-number" :error="$errors->first('address.number')">
<x-input.text wire:model.lazy="address.number" @address-autofilled.window="$refs.addressNumber.focus()" x-ref="addressNumber" id="address-number" :state="$errors->has('address.number') ? false : null" required />
</x-input.group>
<x-input.group class="px-2 w-full lg:w-1/4" label="{{ __('users.attributes.address.complement') }}" for="address-complement" :error="$errors->first('address.complement')">
<x-input.text wire:model.lazy="address.complement" id="address-complement" :state="$errors->has('address.complement') ? false : null" />
</x-input.group>
<x-input.group class="px-2 w-full lg:w-1/2 mt-6 lg:mt-0" label="{{ __('users.attributes.address.neighbourhood') }}" for="address-neighbourhood" :error="$errors->first('address.neighbourhood')">
<x-input.text wire:model.lazy="address.neighbourhood" wire:target="address.postcode" wire:loading.attr="disabled" id="address-neighbourhood" :state="$errors->has('address.neighbourhood') ? false : null" required />
</x-input.group>
</div>
<div class="flex flex-wrap -mx-2">
<x-input.group class="px-2 w-full lg:w-1/2" label="{{ __('users.attributes.address.city') }}" for="address-city" :error="$errors->first('address.city')">
<x-input.text wire:model.lazy="address.city" wire:target="address.postcode" wire:loading.attr="disabled" id="address-city" :state="$errors->has('address.city') ? false : null" required />
</x-input.group>
<x-input.group class="px-2 w-full lg:w-1/2 mt-6 lg:mt-0" label="{{ __('users.attributes.address.state') }}" for="address-state" :error="$errors->first('address.state')">
<x-input.text wire:model.lazy="address.state" wire:target="address.postcode" wire:loading.attr="disabled" id="address-state" :state="$errors->has('address.state') ? false : null" required />
</x-input.group>
</div>
<x-input.group label="{{ __('users.attributes.profile.phone') }}" for="profile-phone" :error="$errors->first('profile.phone')">
<x-input.text wire:model.lazy="profile.phone" id="profile-phone" mask="phone" :state="$errors->has('profile.phone') ? false : null" required />
</x-input.group>
<x-input.group label="{{ __('users.attributes.email') }}" for="email" :error="$errors->first('email')">
<x-input.email wire:model.lazy="email" id="email" :state="$errors->has('email') ? false : null" required />
</x-input.group>
<x-input.group label="{{ __('users.attributes.profile.secondary_emails') }}" for="profile-secondary_emails" :error="$errors->first('profile.secondary_emails')">
<x-input.textarea wire:model.lazy="profile.secondary_emails" id="profile-secondary_emails" :state="$errors->has('profile.secondary_emails') ? false : null" />
</x-input.group>
<x-input.group label="{{ __('users.attributes.profile.website') }}" for="profile-website" :error="$errors->first('profile.website')">
<x-input.text wire:model.lazy="profile.website" id="profile-website" :state="$errors->has('profile.website') ? false : null" />
</x-input.group>
<x-input.group label="{{ __('users.attributes.profile.social') }}" for="profile-social" :error="$errors->first('profile.social')">
<x-input.text wire:model.lazy="profile.social" id="profile-social" :state="$errors->has('profile.social') ? false : null" />
</x-input.group>
</div>
</div>
</div>
<div class="flex flex-wrap pt-8 border-t border-gray-200 mt-8">
<div class="lg:pr-6 w-full lg:w-1/3">
<h2 class="text-2xl font-medium">
Dados de contato
</h2>
<p class="text-gray-400 mt-2">
Endereço e meios de comunicação digitais.
</p>
</div>
<div class="lg:pl-6 w-full lg:w-2/3">
<div class="px-4 py-8 bg-white shadow sm:rounded-lg sm:px-10 space-y-6">
<x-input.radio-group label="{{ __('users.attributes.discussion') }}" :error="$errors->first('discussion')">
<x-input.radio wire:model.lazy="discussion" name="discussion" label="Participar da discussão (todos os e-mails)" value="all" :state="$errors->has('discussion') ? false : null" required />
<x-input.radio wire:model.lazy="discussion" name="discussion" label="Compilação da discussão (1 e-mail por dia)" value="daily" :state="$errors->has('discussion') ? false : null" required />
<x-input.radio wire:model.lazy="discussion" name="discussion" label="Notificações ocasionais da diretoria" value="occasional" :state="$errors->has('discussion') ? false : null" required />
</x-input.radio-group>
<x-input.group label="{{ __('users.attributes.profile.expectation') }}" for="profile-expectation" :error="$errors->first('profile.expectation')">
<x-input.textarea wire:model.lazy="profile.expectation" id="profile-expectation" placeholder="O que você espera que UCB consiga ou faça: atuação, conquistas, pautas (descreva brevemente)?" :state="$errors->has('profile.expectation') ? false : null" />
</x-input.group>
<x-input.group label="{{ __('users.attributes.profile.bike_use') }}" for="profile-bike_use" :error="$errors->first('profile.bike_use')">
<x-input.textarea wire:model.lazy="profile.bike_use" id="profile-bike_use" placeholder="Por quê e para quê usa a bicicleta? Descreva brevemente" :state="$errors->has('profile.bike_use') ? false : null" />
</x-input.group>
<x-input.group label="{{ __('users.attributes.profile.org_participation') }}" for="profile-org_participation" :error="$errors->first('profile.org_participation')">
<x-input.textarea wire:model.lazy="profile.bike_use" id="profile-bike_use" placeholder="Você participa em associações ou coletivos de ciclistas que promovem a bicicleta? Quais? " :state="$errors->has('profile.bike_use') ? false : null" />
</x-input.group>
<x-input.group label="{{ __('users.attributes.profile.bike_activities') }}" for="profile-bike_activities" :error="$errors->first('profile.bike_activities')">
<x-input.textarea wire:model.lazy="profile.bike_use" id="profile-bike_use" placeholder="Realiza atividades ou participa para promover a bicicleta (descreva brevemente)?" :state="$errors->has('profile.bike_use') ? false : null" />
</x-input.group>
<x-input.radio-group
x-data="{ custom_contribution: false }"
@click="custom_contribution = false"
label="{{ __('users.attributes.contribution') }}"
for="contribution"
:error="$errors->first('contribution')"
>
<x-input.radio wire:model.lazy="contribution" name="contribution" label="Não desejo contribuir" value="0" :state="$errors->has('contribution') ? false : null" required />
<x-input.radio wire:model.lazy="contribution" name="contribution" label="R$ 15,00" value="15" :state="$errors->has('contribution') ? false : null" required />
<x-input.radio wire:model.lazy="contribution" name="contribution" label="R$ 30,00" value="30" :state="$errors->has('contribution') ? false : null" required />
<x-input.radio wire:model.lazy="contribution" name="contribution" label="R$ 60,00" value="60" :state="$errors->has('contribution') ? false : null" required />
<x-input.radio wire:model.lazy="contribution" name="contribution" label="R$ 120,00" value="120" :state="$errors->has('contribution') ? false : null" required />
<x-input.radio
name="contribution"
@click="
$event.stopPropagation();
custom_contribution = true;
$nextTick(() => { $refs.customContributionInput.focus() });
"
:state="$errors->has('contribution') ? false : null"
required
>
<span class="text-sm">Outro</span>
<x-input.text
wire:model.lazy="contribution"
x-ref="customContributionInput"
@click="$event.stopPropagation();"
x-show="custom_contribution"
id="contribution-other"
mask="currency"
:state="$errors->has('contribution') ? false : null"
/>
</x-input.radio>
</x-input.radio-group>
</div>
</div>
</div>
<div class="flex flex-wrap pt-8 border-t border-gray-200 mt-8">
<div class="lg:pr-6 w-full lg:w-1/3">
<h2 class="text-2xl font-medium">
Declaração de consentimento
</h2>
</div>
<div class="lg:pl-6 w-full lg:w-2/3">
<p>
Declaro que:
</p>
<ol class="list-decimal list-outside leading-relaxed pl-4 mt-3 space-y-2">
<li>Apoio e concordo com as Finalidades, Princípios, Objetivos e demais termos do Estatuto da UCB (http://www.uniaodeciclistas.org.br/sobre-a-ucb/estatuto/);</li>
<li>Confirmarei e/ou atualizará estes dados cadastrais uma vez por ano;</li>
<li>Caso solicitado, prestarei informações adicionais e/ou enviará documentos para a Diretoria da UCB.</li>
</ol>
</div>
</div>
<div class="flex justify-center pt-12">
<span class="block w-full lg:w-auto rounded-md shadow-sm">
<button type="submit" class="flex justify-center w-full px-16 py-2 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-500 focus:outline-none focus:border-green-700 focus:shadow-outline-green active:bg-green-700 transition duration-150 ease-in-out">
{{ __('auth.sign-up') }}
</button>
</span>
</div>
</form>
</div>

+ 19
- 5
routes/web.php View File

@ -15,15 +15,29 @@ use Illuminate\Support\Facades\Route;
Route::middleware('guest')->group(function () {
Route::view('login', 'auth.login')->name('login');
Route::view('login', 'associates.auth.login')->name('login');
Route::redirect('register', 'register/individual')->name('register');
Route::view('register/individual', 'auth.register.individual')->name('register.individual');
Route::view('register/individual', 'associates.auth.register.individual')->name('register.individual');
});
Route::view('password/reset', 'auth.passwords.email')->name('password.request');
Route::get('password/reset/{token}', 'Auth\PasswordResetController')->name('password.reset');
Route::view('password/reset', 'associates.auth.passwords.email')->name('password.request');
Route::get('password/reset/{token}', 'Associates\Auth\PasswordResetController')->name('password.reset');
Route::middleware('auth')->group(function () {
Route::view('/', 'welcome')->name('home');
Route::post('logout', 'Auth\LogoutController')->name('logout');
Route::post('logout', 'Associates\Auth\LogoutController')->name('logout');
});
Route::prefix('admin')->name('collaborators.')->group(function () {
Route::middleware('guest')->group(function () {
Route::view('login', 'collaborators.auth.login')->name('login');
});
Route::view('password/reset', 'collaborators.auth.passwords.email')->name('password.request');
Route::get('password/reset/{token}', 'Collaborators\Auth\PasswordResetController')->name('password.reset');
Route::middleware('auth:collaborators')->group(function () {
Route::view('/', 'welcome')->name('home');
Route::post('logout', 'Collaborators\Auth\LogoutController')->name('logout');
});
});

tests/Feature/Auth/LoginTest.php → tests/Feature/Associates/Auth/LoginTest.php View File


tests/Feature/Auth/LogoutTest.php → tests/Feature/Associates/Auth/LogoutTest.php View File


tests/Feature/Auth/Passwords/EmailTest.php → tests/Feature/Associates/Auth/Passwords/EmailTest.php View File


tests/Feature/Auth/Passwords/ResetTest.php → tests/Feature/Associates/Auth/Passwords/ResetTest.php View File


tests/Feature/Auth/Register/IndividualTest.php → tests/Feature/Associates/Auth/Register/IndividualTest.php View File