Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rafaelblum/livewire-v3-crud-uploading
Este é um projeto de desenvolvimento de CRUD, Uploading de imagens, bibliotecas front-end e backend, afim de desenvolver mais a nova versão do Livewire 3.0.
https://github.com/rafaelblum/livewire-v3-crud-uploading
chartjs crud flowbite graficos laravel layouts livewire tailwindcss upload-images
Last synced: 4 days ago
JSON representation
Este é um projeto de desenvolvimento de CRUD, Uploading de imagens, bibliotecas front-end e backend, afim de desenvolver mais a nova versão do Livewire 3.0.
- Host: GitHub
- URL: https://github.com/rafaelblum/livewire-v3-crud-uploading
- Owner: RafaelBlum
- Created: 2023-09-16T16:17:29.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2023-10-29T01:16:31.000Z (about 1 year ago)
- Last Synced: 2023-10-29T23:29:03.320Z (about 1 year ago)
- Topics: chartjs, crud, flowbite, graficos, laravel, layouts, livewire, tailwindcss, upload-images
- Language: Blade
- Homepage:
- Size: 8.69 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# 🚀 [Livewire 3.0 - CRUD and uploading image](#)
### Objetivo do projeto
Demonstrar o poder do `livewire` na `versão 3.0` com a criação de `CRUD` de `produto`, `estudante` e `users`, juntamente com o `uploading de imagens`.
E inclui um `sorteio ramdomico` de estudantes, `graficos com chartJS`, e `adaptação de layout administrativo` para o projeto trabalhando as views
com partials, layouts e `skeletons de loadings`.### Tecnologias (serviços externos, libs, frameworks, hospedagem etc.) e instalações.
- 🧩 Php `8.2`
- 🧩 Laravel `10.10` [Projeto laravel] composer create-project laravel/laravel name-project
- 🧩 Livewire `3.0` [Livewire] composer require livewire/livewire
- 🧩 laravel debugbar `3.8` [Debugbar] composer require barryvdh/laravel-debugbar --dev
- 🧩 Remixicon `2.5.0` [Docs](https://remixicon.com/)
- 🧩 Tailwindcss `3.3.3` [Install](https://tailwindcss.com/docs/guides/laravel) npm install -D tailwindcss postcss autoprefixer
- 🧩 Flowbite `1.8.1` [cdn Install](https://cdnjs.cloudflare.com/ajax/libs/flowbite/1.8.1/flowbite.min.css)
- 🧩 ChartJS `4.4.0` [cdn Install](https://cdn.jsdelivr.net/npm/chart.js)## :construction: Desenvolvimento das camadas de componentes
- `php artisan livewire:make gallery.create ` [Component's gallery Product]
- `php artisan livewire:make gallery.edit `
- `php artisan livewire:make gallery.index `
- `php artisan livewire:make student.create ` [Component's student Student]
- `php artisan livewire:make student.edit `
- `php artisan livewire:make student.index `
- `php artisan livewire:make users.create ` [Component's users Users]
- `php artisan livewire:make users.index `
- `php artisan livewire:make raffle.sortition ` [Component's raffle Sortition]
- `php artisan livewire:make adm.painel-button ` [Component's adm Painel-button]## Descritivo dos modulos `components` e front-end
- :zap: Foi criada todas migrates, factories e seeders para popular o banco de dados.
- :zap: Criado um CRUD completo de produtos e upload de images de cada produto registrado, juntamente com as devidas validações de imagens, propriedades e front-end.
- :zap: Estudantes seguiu o mesmo desenvolvimento de CRUD e upload de produto.
- :zap: Foi personalizado a paginação de todos componentes.
- :zap: Foi criado um componente ADM para ser responsável pelos botões rapidos do painel ADM.
- :zap: Criado a listagem simples de usuários e formulário de criação de usuários.
- :zap: O frontend foi todo personalizado apartir de um `template ADM` usando o `Tailwind e Flowbite`.
- :zap: Criado uma página de sorteio aleatório de estudantes importando a biblioteca `JSConfetti`.~~~~~~
import JSConfetti from 'js-confetti'
const jsConfetti = new JSConfetti();
window.confetti = ()=> jsConfetti.addConfetti(
{
emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🌸', '👾', '🌞', '💯'],
}
);
~~~~~~> Abaixo coloquei alguns exemplos simplificados sobre o projeto.
## :label: Exemplo de algumas `atividades` no desenvolvimento.
- :ok_hand: Implement Dependent Dropdown [Documentação](https://livewire.laravel.com/docs/lifecycle-hooks#update)
- updating é renderizado com todas propriedade que após forem atualizadas/selecionada, mas Updated atualização da `propriedade especifica`, no caso a `class_id`
~~~~~~method updated#[Rule('required', message: 'Precisa selecionar uma disciplina.')]
public $class_id;public $sections = [];
public function updatedClassId($value)
{
$this->sections = Section::where('class_id', $value)->get();
}
~~~~~~> Na view
~~~~~~foreach sections
Selecione a turma
@foreach ($sections as $section)
{{ $section->name }} - {{ $section->class->name }}
@endforeach
~~~~~~
- :ok_hand: `STORAGE::` Exemplos com a classe Storage
~~~~~~
if(storage_path('app/public/'.$this->student->image)){
1.create a new folder
Storage::makeDirectory('testeImage');2.store file in directory
Storage::putFile('testeImage', $this->image);3.file generated name hash name
$generatedName = $this->image->hashName();
dd($generatedName);4.store file in directory and rename
Storage::putFileAs('testeImage', $this->image, "student-".$this->student->id.".".$this->image->extension());5.copy file to another directory
Storage::copy('testeImage/student-1.jpg', 'public/imageCopy.png');6.cut file to another directory
Storage::move('public/imageCopy.png', 'public/testeImage/cutImage.png');7.list files or sub files inside folder
$array[] = Storage::files('public/students');
$array[] = Storage::allFiles('public');
dd($array);8.show files
$file = Storage::get('public/default.jpg');
//get file diretory and create to another diretory
dd(Storage::put('students/student-1.jpg', $file));9.download file
return Storage::download('public/default.jpg');10.delete file(s)
if(Storage::exists('students/student-1.jpg')){
dd(Storage::delete('students/student-1.jpg'));
}if(Storage::directoryExists('students')){
dd("DIRETÓRIO EXCLUIDO!", Storage::deleteDirectory('students'));
}dd('sem arquivo e diretório');
dd(Storage::disk('public'));
}
~~~~~~- :ok_hand: DATA BIND
> Passando ID student via rota controller laravel. Poderiamos passar direto pelo component, direto na view sem layout
~~~~~~
~~~~~~- :ok_hand: Como criar uma TAG com um valor inicial
> Na propria chamada do componente criamos um propriedade e definimos seu valor e na view a TAG já terá seu valor.~~~~~~
{{-- IN VIEW COMPONENT --}}
~~~~~~- :ok_hand: Como passar um valor de uma variável para view de um componente
> Exemplo criando uma variável, mas poderia receber de uma variável de um component.~~~~~~
~~~~~~
> No controller temos que inicializar no metodo construtor do component `mount`~~~~~~
public $git;public function mount($git = null)
{
$this->git = $git;
}
~~~~~~- :ok_hand: Actions
> Ações de botões e formulários que reagem com click de botão, form's chamado algum metodo.
~~~~~~
...
...
~~~~~~- :ok_hand: Atualizar algum component modificado
> Exemplo que atualiza a tabela de usuários. Basta incluir na `div` do componente para o _liveiwre_ fazer a **poll** - `wire:poll.visible`~~~~~~
...
~~~~~~
- :ok_hand: Data Binding
> É a forma que vamos interagir e definir valores as propriedades do nosso componente livewire. `wire:model="propertyName"` ou
> na nova versão 3.0 `wire:model.live="propertyName"`.~~~~~~view component
~~~~~~~~~~~~class component
class Create extends Component
{
public $name;public function save(){
User::create([
'name' => $this->name,
]);
}
}
~~~~~~- :ok_hand: Validation
> Na versão 2.0 do livewire seria assim a validação no metodo save.~~~~~~
public function save(){
$this->validate(
[
'name' => 'required|min:3|max:200',
'email' => 'required|email|unique:users',
'password' => 'required|min:8'
],
[
'name.required' => 'Nome é obrigatório!',
'name.min' => 'O minimo para seu nome é 3 caracteres.',
'name.max' => 'O maximo para seu nome é de 200 caracteres',
'email.required' => 'Email é obrigatório!',
'email.unique' => 'Este e-mail já foi registrado!',
'password.required' => 'A senha é obrigatória!',
'password.min' => 'A senha deve ter no minimo 8 caracteres.',
]
);
}
~~~~~~> Na versão 3.0 já ficou mais limpo e claro com as anotações.
~~~~~~Exemple
use Livewire\Attributes\Rule;#[Rule(['name'=>'required|min:3'], message: ['required' => 'O :attribute é necessário.'], attribute: ['name' => 'nome'])]
public $name;public function save(){
$this->validate()
...
}
~~~~~~- :ok_hand: Flash Messages
> Passando messagem de retorno para front-end. Utilizando o `helper` `request() e session()` com flush que passamos `2 argumentos`.
> E também podemos **_redirecionar_ para outra rota**, juntamente com uma messagem with.~~~~~~
request()->session()->flush('success', 'Usuário criado com sucesso!!');
return redirect(router('/...'))->with('success', 'Usuário criado com sucesso!');
~~~~~~- :ok_hand: Paginação
> A paginação é bem parecida com a do laravel, só precisamos chamar na classe o `WithPagination`.~~~~~~
use WithPagination;
public function render()
{
return view('livewire.users.users',
[
'users' => User::paginate(2)
]);
}
~~~~~~> Na view
~~~~~~
{{$users->links()}}
~~~~~~
- :ok_hand: Loading files|states [Documents loading](https://livewire.laravel.com/docs/uploads)
> Para trabalhar com loading de arquivos, primeiro add na classe `WithFileUploads` e com metodo de armazenar os arquivos `store`.
~~~~~~Class component
use WithFileUploads;
/**
*@var TemporaryUploadedFile|mixed $image
*/
#[Rule('required|max:1024', message: 'Image obrigatória ou o tamanho é maior que 1024MB.')]
public $image;
public function save()
{
$this->image->store('image');
}
~~~~~~
> Configuração completa na view. `Visualização temporaria`, `carregamento de progresso`.
~~~~~~View component
{{-- IMAGE --}}
Image
{{-- INPUT IMAGE --}}
@if($image)
@endif
baixando image...
@error('image') {{ $message }} @enderror
~~~~~~
- :ok_hand: Eventos [Documents events](https://livewire.laravel.com/docs/events)
> O metodo `dispatch()` é responsável por fazer a comunicação entre as classes doscomponentes e fazer a atualização `update`.
> O processo é realizado chamando o `dispatch` gerando um nome e passar dados adicionais com o evento passando os dados como segundo parâmetro
~~~~~~Classe User
$user = User::create([// ... ]);
$this->dispatch('user-created', $user);
~~~~~~
~~~~~~Classe List users
use Livewire\Attributes\On;
#[On('user-created')]
public function updateList($user = null){ //.. }
~~~~~~
- :ok_hand: Polling [Documents Polling](https://livewire.laravel.com/docs/wire-poll)
> Uma alternativa para não criar este evento é trabalhar com `wire:poll`
> Desta forma, qualquer atualização no componente será feito o refresh | `
~~~~~~
@foreach($users as $user)
// ...
@endforeach
~~~~~~
- :ok_hand: Lazy Loading [Documents Loading](https://livewire.laravel.com/docs/lazy) e animação de Loading Skeletons [Skeletons](https://delba.dev/blog/animated-loading-skeletons-with-tailwind)
> O componente esqueleto pode ser usado como um indicador de `carregamento alternativo` ao controle giratório, `imitando` o conteúdo que será carregado.
~~~~~~
public function mount()
{
sleep(2);
}
/**
* https://livewire.laravel.com/docs/lazy
*/
public function placeholder()
{
return <<<'HTML'
lazy loading Carregando...
HTML;
}
~~~~~~
~~~~~~
~~~~~~
- :ok_hand: Propriedades Computadas [Property computer](https://livewire.laravel.com/docs/computed-properties)
> As propriedades computadas permitem acessar valores e armazená-los em cache para acesso futuro durante a solicitação
~~~~~~Class
use Livewire\Attributes\Computed;
#[Computed()]
public function users()
{
return User::paginate(2);
}
~~~~~~
~~~~~~View
@foreach($this->users as $user)
//..
@endforeach
~~~~~~
- :ok_hand: Criar Layout [Layout](https://livewire.laravel.com/docs/quickstart#create-a-template-layout)
- [Tutorial](https://www.youtube.com/watch?v=SKxIXm-MOE4&list=PLqDySLfPKRn543NM_fTrJRdhjBgsogzSC&index=16&ab_channel=YeloCode)
> o Livewire procurará automaticamente um arquivo de layout.
~~~~~~
php artisan livewire:layout
~~~~~~
~~~~~~
{{ $title ?? 'Page Title' }}
{{ $slot }}
~~~~~~
- :ok_hand: [Form Objects | ](https://livewire.laravel.com/docs/forms)
> Os objetos de formulário permitem reutilizar a lógica do formulário entre os componentes e fornecem uma ótima maneira
>de manter a classe do componente mais limpa, agrupando todo o código relacionado ao formulário em uma classe separada.
~~~~~~
php artisan livewire:form PostForm
~~~~~~
~~~~~~
// class form
class PostForm extends Form
{
#[Rule('required|min:5')]
public $title = '';
#[Rule('required|min:5')]
public $content = '';
}
//class createForm
public PostForm $form;
public function save()
{
$this->validate();
Post::create(
$this->form->all()
);
return $this->redirect('/posts');
}
//view
{{$form->title}}
~~~~~~
- :ok_hand: [URL Query Parameters | ](https://livewire.laravel.com/docs/url)
>
~~~~~~
#[Url(as: 'busca', keep: true, history: true)]
public $search = '';
~~~~~~
- :ok_hand: [Offline States | ]()
> Para você pode notificar os usuários caso eles estejam offline `wire:offline`.
~~~~~~
Voçê encontra-se offline! Por favor, tente esabelecer a conexão ou tenta mais tarde.
~~~~~~
- :ok_hand: [Wire:navigate | ](https://livewire.laravel.com/docs/wire-navigate)
>
~~~~~~
Dashboard
~~~~~~
- :ok_hand: [Lifecycle hooks | ](https://livewire.laravel.com/docs/lifecycle-hooks)
> Ciclo de vida dos hooks que permitem executar código em pontos específicos durante o ciclo de vida de um componente.
| Hook Method | Explicação |
| :--- | :--- |
| `mount()` | *É como se fosse o `__construct()` de uma classe. * _Chamado quando um componente é criado._ |
| `hydrate()` | _Chamado quando um componente é reidratado no início de uma solicitação subsequente._|
| `boot()` | *É um metodo que sempre é chamado sempre. * _Chamado no início de cada solicitação no backend. Tanto inicial quanto subsequente._|
| `updating()` | _Chamado antes de atualizar uma propriedade de componente._|
| `updated()` | _Chamado após atualizar uma propriedade._|
| `rendering()` | _Chamado antes `render()` é chamado._|
| `rendered()` | _Chamado depois `render()` é chamado._|
| `dehydrate()` | _Chamado no final de cada solicitação de componente._|
- :ok_hand: [Keyboard Shortcuts | ](https://livewire.laravel.com/docs/actions#listening-for-specific-keys)
> Os keywords são eventos de ações para o usuário.
~~~~~~
@csrf
//...
~~~~~~
- :ok_hand: [Magic Actions | ](https://livewire.laravel.com/docs/actions#magic-actions)
> Livewire fornece um conjunto de ações "mágicas" que permitem executar tarefas comuns em seus componentes sem definir métodos personalizados.
~~~~~~
//$parent
//$set | Modiica uma propriedade.
//$refresh | aciona uma nova renderização do seu componente
//$toggle
//$dispatch
//$event
//exemples
Refresh
Reset Set
Sort {{ $sortAsc ? 'Descending' : 'Ascending' }}
~~~~~~
## Contatos
- 👇🏼 [[email protected]]
[![Youtube Badge](https://img.shields.io/badge/-Youtube-FF0000?style=flat-square&labelColor=FF0000&logo=youtube&logoColor=white&link=https://www.youtube.com/channel/UCMvtn8HZ12Ud-sdkY5KzTog)](https://www.youtube.com/channel/UCMvtn8HZ12Ud-sdkY5KzTog)
[![Instagram Badge](https://img.shields.io/badge/-rafablum_-violet?style=flat-square&logo=Instagram&logoColor=white&link=https://www.instagram.com/rafablum_/)](https://www.instagram.com/rafablum_/)
[![Twitter: universoCode](https://img.shields.io/twitter/follow/universoCode?style=social)](https://twitter.com/universoCode)
[![Linkedin: RafaelBlum](https://img.shields.io/badge/-RafaelBlum-blue?style=flat-square&logo=Linkedin&logoColor=white&link=https://www.linkedin.com/in/rafael-blum-378656285/)](https://www.linkedin.com/in/rafael-blum-378656285/)
[![GitHub RafaelBlum](https://img.shields.io/github/followers/RafaelBlum?label=follow&style=social)](https://github.com/RafaelBlum)
Adoro me conectar com pessoas diferentes, então se você quiser dizer oi, ficarei feliz em conhecê-lo mais! :)