feat: add logout, updateProfile, updatePassword, deleteAccount to useAuth
This commit is contained in:
@@ -1,156 +0,0 @@
|
|||||||
---
|
|
||||||
name: livewire-development
|
|
||||||
description: "Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, wire:sort, or islands, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, drag-and-drop, loading states, migrating from Livewire 3 to 4, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire."
|
|
||||||
license: MIT
|
|
||||||
metadata:
|
|
||||||
author: laravel
|
|
||||||
---
|
|
||||||
|
|
||||||
# Livewire Development
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
Use `search-docs` for detailed Livewire 4 patterns and documentation.
|
|
||||||
|
|
||||||
## Basic Usage
|
|
||||||
|
|
||||||
### Creating Components
|
|
||||||
|
|
||||||
```bash
|
|
||||||
|
|
||||||
# Single-file component (default in v4)
|
|
||||||
|
|
||||||
php artisan make:livewire create-post
|
|
||||||
|
|
||||||
# Multi-file component
|
|
||||||
|
|
||||||
php artisan make:livewire create-post --mfc
|
|
||||||
|
|
||||||
# Class-based component (v3 style)
|
|
||||||
|
|
||||||
php artisan make:livewire create-post --class
|
|
||||||
|
|
||||||
# With namespace
|
|
||||||
|
|
||||||
php artisan make:livewire Posts/CreatePost
|
|
||||||
```
|
|
||||||
|
|
||||||
### Converting Between Formats
|
|
||||||
|
|
||||||
Use `php artisan livewire:convert create-post` to convert between single-file, multi-file, and class-based formats.
|
|
||||||
|
|
||||||
### Choosing a Component Format
|
|
||||||
|
|
||||||
Before creating a component, check `config/livewire.php` for directory overrides, which change where files are stored. Then, look at existing files in those directories (defaulting to `app/Livewire/` and `resources/views/livewire/`) to match the established convention.
|
|
||||||
|
|
||||||
### Component Format Reference
|
|
||||||
|
|
||||||
| Format | Flag | Class Path | View Path |
|
|
||||||
|--------|------|------------|-----------|
|
|
||||||
| Single-file (SFC) | default | — | `resources/views/livewire/create-post.blade.php` (PHP + Blade in one file) |
|
|
||||||
| Multi-file (MFC) | `--mfc` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
|
|
||||||
| Class-based | `--class` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
|
|
||||||
| View-based | ⚡ prefix | — | `resources/views/livewire/create-post.blade.php` (Blade-only with functional state) |
|
|
||||||
|
|
||||||
Namespaced components map to subdirectories: `make:livewire Posts/CreatePost` creates files at `app/Livewire/Posts/CreatePost.php` and `resources/views/livewire/posts/create-post.blade.php`.
|
|
||||||
|
|
||||||
### Single-File Component Example
|
|
||||||
|
|
||||||
<!-- Single-File Component Example -->
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
use Livewire\Component;
|
|
||||||
|
|
||||||
new class extends Component {
|
|
||||||
public int $count = 0;
|
|
||||||
|
|
||||||
public function increment(): void
|
|
||||||
{
|
|
||||||
$this->count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button wire:click="increment">Count: @{{ $count }}</button>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Livewire 4 Specifics
|
|
||||||
|
|
||||||
### Key Changes From Livewire 3
|
|
||||||
|
|
||||||
These things changed in Livewire 4, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.
|
|
||||||
|
|
||||||
- Use `Route::livewire()` for full-page components (e.g., `Route::livewire('/posts/create', CreatePost::class)`); config keys renamed: `layout` → `component_layout`, `lazy_placeholder` → `component_placeholder`.
|
|
||||||
- `wire:model` now ignores child events by default (use `wire:model.deep` for old behavior); `wire:scroll` renamed to `wire:navigate:scroll`.
|
|
||||||
- Component tags must be properly closed; `wire:transition` now uses View Transitions API (modifiers removed).
|
|
||||||
- JavaScript: `$wire.$js('name', fn)` → `$wire.$js.name = fn`; `commit`/`request` hooks → `interceptMessage()`/`interceptRequest()`.
|
|
||||||
|
|
||||||
### New Features
|
|
||||||
|
|
||||||
- Component formats: single-file (SFC), multi-file (MFC), view-based components.
|
|
||||||
- Islands (`@island`) for isolated updates; async actions (`wire:click.async`, `#[Async]`) for parallel execution.
|
|
||||||
- Deferred/bundled loading: `defer`, `lazy.bundle` for optimized component loading.
|
|
||||||
|
|
||||||
| Feature | Usage | Purpose |
|
|
||||||
|---------|-------|---------|
|
|
||||||
| Islands | `@island(name: 'stats')` | Isolated update regions |
|
|
||||||
| Async | `wire:click.async` or `#[Async]` | Non-blocking actions |
|
|
||||||
| Deferred | `defer` attribute | Load after page render |
|
|
||||||
| Bundled | `lazy.bundle` | Load multiple together |
|
|
||||||
|
|
||||||
### New Directives
|
|
||||||
|
|
||||||
- `wire:sort`, `wire:intersect`, `wire:ref`, `.renderless`, `.preserve-scroll` are available for use.
|
|
||||||
- `data-loading` attribute automatically added to elements triggering network requests.
|
|
||||||
|
|
||||||
| Directive | Purpose |
|
|
||||||
|-----------|---------|
|
|
||||||
| `wire:sort` | Drag-and-drop sorting |
|
|
||||||
| `wire:intersect` | Viewport intersection detection |
|
|
||||||
| `wire:ref` | Element references for JS |
|
|
||||||
| `.renderless` | Component without rendering |
|
|
||||||
| `.preserve-scroll` | Preserve scroll position |
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
- Always use `wire:key` in loops
|
|
||||||
- Use `wire:loading` for loading states
|
|
||||||
- Use `wire:model.live` for instant updates (default is debounced)
|
|
||||||
- Validate and authorize in actions (treat like HTTP requests)
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
- `smart_wire_keys` defaults to `true`; new configs: `component_locations`, `component_namespaces`, `make_command`, `csp_safe`.
|
|
||||||
|
|
||||||
## Alpine & JavaScript
|
|
||||||
|
|
||||||
- `wire:transition` uses browser View Transitions API; `$errors` and `$intercept` magic properties available.
|
|
||||||
- Non-blocking `wire:poll` and parallel `wire:model.live` updates improve performance.
|
|
||||||
|
|
||||||
For interceptors and hooks, see [reference/javascript-hooks.md](reference/javascript-hooks.md).
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
<!-- Testing Example -->
|
|
||||||
```php
|
|
||||||
Livewire::test(Counter::class)
|
|
||||||
->assertSet('count', 0)
|
|
||||||
->call('increment')
|
|
||||||
->assertSet('count', 1);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Verification
|
|
||||||
|
|
||||||
1. Browser console: Check for JS errors
|
|
||||||
2. Network tab: Verify Livewire requests return 200
|
|
||||||
3. Ensure `wire:key` on all `@foreach` loops
|
|
||||||
|
|
||||||
## Common Pitfalls
|
|
||||||
|
|
||||||
- Missing `wire:key` in loops → unexpected re-rendering
|
|
||||||
- Expecting `wire:model` real-time → use `wire:model.live`
|
|
||||||
- Unclosed component tags → syntax errors in v4
|
|
||||||
- Using deprecated config keys or JS hooks
|
|
||||||
- Including Alpine.js separately (already bundled in Livewire 4)
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Livewire 4 JavaScript Integration
|
|
||||||
|
|
||||||
## Interceptor System (v4)
|
|
||||||
|
|
||||||
### Intercept Messages
|
|
||||||
|
|
||||||
```js
|
|
||||||
Livewire.interceptMessage(({ component, message, onFinish, onSuccess, onError }) => {
|
|
||||||
onFinish(() => { /* After response, before processing */ });
|
|
||||||
onSuccess(({ payload }) => { /* payload.snapshot, payload.effects */ });
|
|
||||||
onError(() => { /* Server errors */ });
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Intercept Requests
|
|
||||||
|
|
||||||
```js
|
|
||||||
Livewire.interceptRequest(({ request, onResponse, onSuccess, onError, onFailure }) => {
|
|
||||||
onResponse(({ response }) => { /* When received */ });
|
|
||||||
onSuccess(({ response, responseJson }) => { /* Success */ });
|
|
||||||
onError(({ response, responseBody, preventDefault }) => { /* 4xx/5xx */ });
|
|
||||||
onFailure(({ error }) => { /* Network failures */ });
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Component-Scoped Interceptors
|
|
||||||
|
|
||||||
```blade
|
|
||||||
<script>
|
|
||||||
this.$intercept('save', ({ component, onSuccess }) => {
|
|
||||||
onSuccess(() => console.log('Saved!'));
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Magic Properties
|
|
||||||
|
|
||||||
- `$errors` - Access validation errors from JavaScript
|
|
||||||
- `$intercept` - Component-scoped interceptors
|
|
||||||
@@ -40,5 +40,39 @@ export function useAuth() {
|
|||||||
fetched.value = false
|
fetched.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
return { user, loading, isAuthenticated, userTier, isPaidTier, fetchUser, clearUser }
|
async function logout() {
|
||||||
|
try {
|
||||||
|
await api.post('/auth/logout')
|
||||||
|
} finally {
|
||||||
|
clearUser()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateProfile(data) {
|
||||||
|
const response = await api.put('/user/profile', data)
|
||||||
|
user.value = response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updatePassword(data) {
|
||||||
|
await api.put('/user/password', data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteAccount(password) {
|
||||||
|
await api.delete('/user', { data: { password } })
|
||||||
|
clearUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
user,
|
||||||
|
loading,
|
||||||
|
isAuthenticated,
|
||||||
|
userTier,
|
||||||
|
isPaidTier,
|
||||||
|
fetchUser,
|
||||||
|
clearUser,
|
||||||
|
logout,
|
||||||
|
updateProfile,
|
||||||
|
updatePassword,
|
||||||
|
deleteAccount,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user