Browse Source

Implementa todos os campos do cadastro de indivíduos

usuarios_separados
Guilherme Capanema 6 years ago
parent
commit
218c014e41
9 changed files with 424 additions and 33 deletions
  1. +97
    -1
      app/Http/Livewire/Auth/Register/Individual.php
  2. +3
    -1
      app/User.php
  3. +3
    -3
      database/migrations/2014_10_12_000000_create_users_table.php
  4. +31
    -0
      resources/lang/pt-BR/users.php
  5. +1
    -1
      resources/views/components/input/group.blade.php
  6. +25
    -0
      resources/views/components/input/radio.blade.php
  7. +12
    -3
      resources/views/components/input/text.blade.php
  8. +12
    -0
      resources/views/components/input/textarea.blade.php
  9. +240
    -24
      resources/views/livewire/auth/register/individual.blade.php

+ 97
- 1
app/Http/Livewire/Auth/Register/Individual.php View File

@ -19,14 +19,80 @@ class Individual extends Component
/** @var string */
public $birthday = '';
/** @var array */
public $document = [
'type' => '',
'number' => '',
];
/** @var array */
public $address = [
'street' => '',
'number' => '',
'complement' => '',
'neighbourhood' => '',
'city' => '',
'state' => '',
'postcode' => '',
'country' => '',
];
/** @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, [
'email' => ['email', 'unique:users'],
'birthday' => ['date_format:d/m/Y'],
'address.street' => ['string'],
'address.number' => ['string'],
'address.complement' => ['string'],
'address.neighbourhood' => ['string'],
'address.city' => ['string'],
'address.state' => ['string'],
'address.postcode' => ['string'],
'address.country' => ['string'],
'profile.gender' => ['string', 'in:male,female,other'],
'profile.occupation' => ['string'],
'profile.scholarity' => ['string', 'in:primary-school,high-school,bachelor,master,phd'],
'profile.phone' => ['string'],
'profile.secondary_emails' => ['string'],
'profile.website' => ['string'],
'profile.social' => ['string'],
'profile.expectation' => ['string'],
'profile.bike_use' => ['string'],
'profile.org_participation' => ['string'],
'profile.bike_activities' => ['string'],
'profile.comments' => ['string'],
'profile.ucb_comments' => ['string'],
'document.type' => ['string', 'in:cpf,identity,passport'],
'document.number' => ['string'],
'discussion' => ['string', 'in:all,daily,occasional'],
'contribution' => ['numeric'],
]);
}
@ -36,12 +102,42 @@ class Individual extends Component
'name' => ['required'],
'birthday' => ['required', 'date_format:d/m/Y'],
'email' => ['required', 'email', 'unique:users'],
'address.street' => ['required', 'string'],
'address.number' => ['required', 'string'],
'address.complement' => ['required', 'string'],
'address.neighbourhood' => ['required', 'string'],
'address.city' => ['required', 'string'],
'address.state' => ['required', 'string'],
'address.postcode' => ['required', 'string'],
'address.country' => ['required', 'string'],
'profile.gender' => ['required', 'string', 'in:male,female,other'],
'profile.occupation' => ['required', 'string'],
'profile.scholarity' => ['required', 'string', 'in:primary-school,high-school,bachelor,master,phd'],
'profile.phone' => ['required', 'string'],
'profile.secondary_emails' => ['required', 'string'],
'profile.website' => ['nullable', 'string'],
'profile.social' => ['nullable', 'string'],
'profile.expectation' => ['nullable', 'string'],
'profile.bike_use' => ['nullable', 'string'],
'profile.org_participation' => ['nullable', 'string'],
'profile.bike_activities' => ['nullable', 'string'],
'profile.comments' => ['nullable', 'string'],
'profile.ucb_comments' => ['nullable', 'string'],
'document.type' => ['required', 'string', 'in:cpf,identity,passport'],
'document.number' => ['required', 'string'],
'discussion' => ['required', 'string', 'in:all,daily,occasional'],
'contribution' => ['required', 'numeric'],
]);
$user = new User([
'name' => $this->name,
'email' => $this->email,
'birthday' => Carbon::createFromFormat('d/m/Y', $this->birthday),
'address' => $this->address,
'profile' => $this->profile,
'document' => $this->document,
'discussion' => $this->discussion,
'contribution' => $this->contribution,
'email' => $this->email,
]);
$user->user_category_id = UserCategory::where('key', 'individual')->first()->id;


+ 3
- 1
app/User.php View File

@ -16,7 +16,7 @@ class User extends Authenticatable
* @var array
*/
protected $fillable = [
'name', 'email', 'password', 'birthday'
'name', 'email', 'password', 'birthday', 'document'
];
/**
@ -35,6 +35,8 @@ class User extends Authenticatable
*/
protected $casts = [
'birthday' => 'date',
'document' => 'array',
'profile' => 'array',
];
/**


+ 3
- 3
database/migrations/2014_10_12_000000_create_users_table.php View File

@ -25,12 +25,12 @@ class CreateUsersTable extends Migration
$table->foreignId('user_type_id');
// $table->string('avatar')->nullable();
$table->date('birthday');
// $table->json('document')->nullable();
$table->json('document')->nullable();
// $table->json('address');
// $table->string('phone');
// $table->string('discussion');
$table->string('discussion');
// $table->integer('donation')->nullable();
// $table->json('profile');
$table->json('profile');
$table->rememberToken();
$table->timestamps();


+ 31
- 0
resources/lang/pt-BR/users.php View File

@ -4,6 +4,37 @@ return [
'attributes' => [
'name' => 'Nome completo',
'birthday' => 'Data de nascimento',
'document' => [
'type' => 'Tipo de documento',
'number' => 'Nº do documento',
],
'address' => [
'street' => 'Rua',
'number' => 'Número',
'complement' => 'Complemento',
'neighbourhood' => 'Bairro',
'city' => 'Cidade',
'state' => 'Estado (UF)',
'postcode' => 'CEP',
'country' => 'País',
],
'profile' => [
'gender' => 'Você se identifica como',
'occupation' => 'Ramo de atuação',
'scholarity' => 'Escolaridade',
'phone' => 'Telefone',
'secondary_emails' => 'E-mails secundários',
'website' => 'Sítio eletrônico',
'social' => 'Rede social',
'expectation' => 'Expectativa em relação à UCB',
'bike_use' => 'Uso da bicicleta',
'org_participation' => 'Participação em organização de ciclistas',
'bike_activities' => 'Atividades pró-ciclomobilidade',
'comments' => 'Observações',
'ucb_comments' => 'Observações UCB',
],
'email' => 'E-mail principal',
'discussion' => 'Participação no grupo de comunicação',
'contribution' => 'Contribuição financeira',
],
];

+ 1
- 1
resources/views/components/input/group.blade.php View File

@ -4,7 +4,7 @@
'error' => false,
])
<div>
<div {{ $attributes }}>
<label for="{{ $for }}" class="block text-sm font-medium text-gray-700 leading-5">
{{ $label }}


+ 25
- 0
resources/views/components/input/radio.blade.php View File

@ -0,0 +1,25 @@
@props([
'label' => null,
'state' => null,
])
<div>
<label class="inline-flex items-center space-x-2 @if ($state === false) text-red-900 @endif">
<input
{{ $attributes }}
type="radio"
class="form-radio
@if ($state === false) border-red-300 focus:border-red-300 focus:shadow-outline-red @endif"
/>
@if ($label)
<span class="text-sm">
{{ $label }}
</span>
@else
{{ $slot }}
@endif
</label>
</div>

+ 12
- 3
resources/views/components/input/text.blade.php View File

@ -12,12 +12,21 @@
/>
</div>
@if ($mask === 'date')
@if ($mask)
@push('scripts')
<script>
new Cleave('#{{ $attributes->get('id') }}', {
date: true,
datePattern: ['d', 'm', 'Y']
@if ($mask === 'date')
date: true,
datePattern: ['d', 'm', 'Y']
@elseif ($mask === 'postcode')
delimiter: '-',
blocks: [5, 3],
numericOnly: true,
@elseif ($mask === 'phone')
phone: true,
phoneRegionCode: 'BR'
@endif
});
</script>
@endpush


+ 12
- 0
resources/views/components/input/textarea.blade.php View File

@ -0,0 +1,12 @@
@props([
'state' => null,
])
<div class="mt-1 rounded-md shadow-sm">
<textarea
{{ $attributes }}
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
@if ($state === false) border-red-300 text-red-900 placeholder-red-300 focus:border-red-300 focus:shadow-outline-red @endif"
>
</textarea>
</div>

+ 240
- 24
resources/views/livewire/auth/register/individual.blade.php View File

@ -16,31 +16,247 @@
</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="register" class="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.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>
<div>
<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.register') }}
</button>
</span>
<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.group label="{{ __('users.attributes.profile.gender') }}" for="profile-gender" :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-group>
<x-input.group label="{{ __('users.attributes.document.type') }}" for="document-type" :error="$errors->first('document.type')">
<x-input.radio wire:model.lazy="document.type" name="document-type" label="CPF" value="cpf" :state="$errors->has('document.type') ? false : null" required />
<x-input.radio wire:model.lazy="document.type" name="document-type" label="Carteira de Identidade" value="identity" :state="$errors->has('document.type') ? false : null" required />
<x-input.radio wire:model.lazy="document.type" name="document-type" label="Passaporte" value="passport" :state="$errors->has('document.type') ? false : null" required />
</x-input-group>
<x-input.group 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>
<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.group label="{{ __('users.attributes.profile.scholarity') }}" for="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-group>
</div>
</div>
</form>
</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.group label="{{ __('users.attributes.address.street') }}" for="address-street" :error="$errors->first('address.street')">
<x-input.text wire:model.lazy="address.street" id="address-street" :state="$errors->has('address.street') ? false : null" required />
</x-input-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.address.number') }}" for="address-number" :error="$errors->first('address.number')">
<x-input.text wire:model.lazy="address.number" 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/2" 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" required />
</x-input-group>
</div>
<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.address.neighbourhood') }}" for="address-neighbourhood" :error="$errors->first('address.neighbourhood')">
<x-input.text wire:model.lazy="address.neighbourhood" id="address-neighbourhood" :state="$errors->has('address.neighbourhood') ? false : null" required />
</x-input-group>
<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" id="address-city" :state="$errors->has('address.city') ? 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 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" id="address-state" :state="$errors->has('address.state') ? false : null" required />
</x-input-group>
<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" mask="postcode" :state="$errors->has('address.postcode') ? false : null" required />
</x-input-group>
</div>
<x-input.group label="{{ __('users.attributes.address.country') }}" for="address-country" :error="$errors->first('address.country')">
<x-input.text wire:model.lazy="address.country" id="address-country" mask="country" :state="$errors->has('address.country') ? false : null" required />
</x-input-group>
<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.group label="{{ __('users.attributes.discussion') }}" for="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-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.group 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" :state="$errors->has('contribution') ? false : null" required>
<span class="text-sm">
Outro:
</span>
<x-input.text wire:model.lazy="contribution" :state="$errors->has('contribution') ? false : null" />
</x-input.radio>
</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">
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.register') }}
</button>
</span>
</div>
</form>
</div>