diff --git a/AUTH_SETUP.md b/AUTH_SETUP.md new file mode 100644 index 0000000..0d0c616 --- /dev/null +++ b/AUTH_SETUP.md @@ -0,0 +1,328 @@ +# Authentication Setup Guide + +This document explains the authentication system that has been set up for your Laravel + Inertia.js + Vue 3 application. + +## πŸ“¦ What Was Installed/Created + +### Files Created: +1. **`resources/js/services/authService.ts`** - API service for authentication +2. **`resources/js/stores/auth.ts`** - Pinia store for auth state management +3. **`resources/js/middleware/auth.ts`** - Route guards for authentication +4. **`resources/js/composables/useAuthGuard.ts`** - Composables for protecting routes +5. **`resources/js/components/LoginExample.vue`** - Example login component + +### Files Modified: +- **`resources/js/app.ts`** - Integrated auth guards + +## πŸ”§ Setup + +### Note: Pinia instead of Vuex +Your project already has **Pinia** installed, which is the official state management solution for Vue 3 (and the successor to Vuex). The setup uses Pinia instead of Vuex as requested. + +If you specifically need Vuex 4, run: +```bash +npm install vuex@4 +``` + +However, Pinia is recommended for Vue 3 projects. + +## πŸš€ Usage + +### 1. Using the Auth Store + +The auth store provides all authentication functionality: + +```vue + +``` + +### 2. Protecting Routes with Composables + +#### Protect authenticated routes (dashboard, profile, etc.): + +```vue + + + +``` + +#### Protect guest routes (login, register): + +```vue + + + +``` + +### 3. Accessing User Data + +```vue + + + +``` + +### 4. Auth Store API + +The auth store (`useAuthStore()`) provides: + +**State:** +- `user` - Current user object or null +- `token` - Authentication token (if API returns one) +- `loading` - Loading state +- `error` - Error message + +**Getters:** +- `isAuthenticated` - Boolean indicating if user is logged in +- `currentUser` - Current user object + +**Actions:** +- `login(credentials)` - Login with email and password +- `logout()` - Logout current user +- `checkAuth()` - Check if user is authenticated +- `fetchUser()` - Fetch current user data +- `clearError()` - Clear error messages +- `setUser(user)` - Manually set user data + +## πŸ” API Endpoints + +The auth service expects these endpoints: + +### Login +``` +POST http://localhost:8000/api/auth/login +Body: { + "email": "user@example.com", + "password": "password", + "remember": true +} + +Response: { + "user": { + "id": 1, + "name": "John Doe", + "email": "user@example.com", + ... + }, + "token": "optional-auth-token" +} +``` + +### Logout +``` +POST http://localhost:8000/api/auth/logout +``` + +### Get Current User +``` +GET http://localhost:8000/api/auth/user + +Response: { + "user": { + "id": 1, + "name": "John Doe", + "email": "user@example.com", + ... + } +} +``` + +## πŸ› οΈ Backend Setup (Laravel) + +You need to create these API routes in Laravel. Here's an example: + +```php +// routes/api.php +use App\Http\Controllers\Auth\ApiAuthController; + +Route::prefix('auth')->group(function () { + Route::post('/login', [ApiAuthController::class, 'login']); + Route::post('/logout', [ApiAuthController::class, 'logout'])->middleware('auth:sanctum'); + Route::get('/user', [ApiAuthController::class, 'user'])->middleware('auth:sanctum'); +}); +``` + +Example controller: + +```php +// app/Http/Controllers/Auth/ApiAuthController.php +namespace App\Http\Controllers\Auth; + +use App\Http\Controllers\Controller; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; + +class ApiAuthController extends Controller +{ + public function login(Request $request) + { + $credentials = $request->validate([ + 'email' => 'required|email', + 'password' => 'required', + ]); + + if (Auth::attempt($credentials, $request->boolean('remember'))) { + $user = Auth::user(); + $token = $user->createToken('auth-token')->plainTextToken; + + return response()->json([ + 'user' => $user, + 'token' => $token, + ]); + } + + return response()->json([ + 'message' => 'Invalid credentials', + ], 401); + } + + public function logout(Request $request) + { + $request->user()->currentAccessToken()->delete(); + return response()->json(['message' => 'Logged out successfully']); + } + + public function user(Request $request) + { + return response()->json(['user' => $request->user()]); + } +} +``` + +## πŸ’Ύ Persistence + +The auth store automatically persists the `user` and `token` to localStorage using `pinia-plugin-persistedstate`. This means: +- User stays logged in after page refresh +- Auth state is restored on app load +- Logout clears the persisted data + +## 🎯 Example: Update Your Login Page + +Update your existing `resources/js/pages/auth/Login.vue`: + +```vue + +``` + +## 🎯 Example: Protect Dashboard + +Update your dashboard to require authentication: + +```vue + + + +``` + +## πŸ“ Notes + +1. **Axios is already installed** in your project at version `1.11.0` +2. **Pinia is already installed** and configured with persistence +3. The auth system works with your existing Inertia.js setup +4. CSRF tokens are automatically handled via the existing `resources/js/lib/http.ts` +5. Authentication state persists across page reloads + +## πŸ”„ Customization + +### Change API URLs +Edit `resources/js/services/authService.ts` to change the API endpoints. + +### Change Redirect Routes +Edit the composables in `resources/js/composables/useAuthGuard.ts` to change default redirect routes. + +### Add More User Fields +Update the `User` interface in `resources/js/services/authService.ts` to match your user model. diff --git a/QUICK_START_AUTH.md b/QUICK_START_AUTH.md new file mode 100644 index 0000000..3da790e --- /dev/null +++ b/QUICK_START_AUTH.md @@ -0,0 +1,293 @@ +# πŸš€ Quick Start - Authentication System + +## βœ… What's Been Set Up + +Your Laravel + Vue 3 + Inertia.js application now has a complete authentication system with: + +1. βœ… **Axios** - Already installed (v1.11.0) +2. βœ… **Pinia** - State management (already installed, replaces Vuex) +3. βœ… **Auth Service** - API calls to `http://localhost:8000/api/auth/login` +4. βœ… **Auth Store** - Centralized authentication state +5. βœ… **Route Guards** - Protect pages based on authentication +6. βœ… **Persistence** - Auth state survives page reloads + +## πŸ“ Files Created + +``` +resources/js/ +β”œβ”€β”€ services/ +β”‚ └── authService.ts ← API service for auth endpoints +β”œβ”€β”€ stores/ +β”‚ └── auth.ts ← Pinia store for auth state +β”œβ”€β”€ middleware/ +β”‚ └── auth.ts ← Route guard middleware +β”œβ”€β”€ composables/ +β”‚ └── useAuthGuard.ts ← Composables for protecting routes +└── components/ + └── LoginExample.vue ← Example login component +``` + +## 🎯 How to Use + +### 1. In Your Login Component + +```vue + + + +``` + +### 2. Protect Your Dashboard + +```vue + + + +``` + +### 3. Display User Info + +```vue + + + +``` + +## πŸ”§ Backend Requirements + +You need these Laravel API endpoints: + +### Login Endpoint +```php +// POST http://localhost:8000/api/auth/login +Route::post('api/auth/login', function(Request $request) { + $credentials = $request->validate([ + 'email' => 'required|email', + 'password' => 'required', + ]); + + if (Auth::attempt($credentials)) { + return response()->json([ + 'user' => Auth::user(), + 'token' => Auth::user()->createToken('auth')->plainTextToken + ]); + } + + return response()->json(['message' => 'Invalid credentials'], 401); +}); +``` + +### User Endpoint +```php +// GET http://localhost:8000/api/auth/user +Route::get('api/auth/user', function() { + return response()->json(['user' => Auth::user()]); +})->middleware('auth:sanctum'); +``` + +### Logout Endpoint +```php +// POST http://localhost:8000/api/auth/logout +Route::post('api/auth/logout', function(Request $request) { + $request->user()->currentAccessToken()->delete(); + return response()->json(['message' => 'Logged out']); +})->middleware('auth:sanctum'); +``` + +## 🎨 Complete Working Examples + +### Example 1: Simple Login Page + +```vue + + + +``` + +### Example 2: Protected Dashboard + +```vue + + + +``` + +## πŸ“‹ Auth Store API Reference + +```typescript +const authStore = useAuthStore(); + +// State +authStore.user // User object or null +authStore.token // Auth token or null +authStore.loading // Boolean: loading state +authStore.error // String: error message or null + +// Getters +authStore.isAuthenticated // Boolean: is user logged in? +authStore.currentUser // User object or null + +// Actions +await authStore.login({ email, password, remember }) // Returns boolean +await authStore.logout() // Returns void +await authStore.checkAuth() // Returns boolean +await authStore.fetchUser() // Returns void +authStore.clearError() // Returns void +authStore.setUser(userData) // Returns void +``` + +## ✨ Key Features + +- βœ… **Auto-persistence**: Auth state saved to localStorage +- βœ… **CSRF Protection**: Automatically handled +- βœ… **Error Handling**: Built-in error messages +- βœ… **Loading States**: Track async operations +- βœ… **TypeScript**: Full type safety +- βœ… **Inertia Compatible**: Works with your existing setup + +## πŸ› Troubleshooting + +### Issue: User not staying logged in +**Solution**: Make sure your Laravel API returns the user object on the `/api/auth/user` endpoint + +### Issue: CSRF token mismatch +**Solution**: Your existing `resources/js/lib/http.ts` handles this automatically + +### Issue: Redirect not working +**Solution**: Ensure you're using `router.get()` from `@inertiajs/vue3` + +## πŸ“š Next Steps + +1. Create your Laravel API endpoints (see examples above) +2. Update your login page component +3. Add `useAuthGuard()` to protected pages +4. Test the authentication flow + +For detailed documentation, see `AUTH_SETUP.md` diff --git a/resources/js/app.ts b/resources/js/app.ts index 71d8d1e..b7049ca 100644 --- a/resources/js/app.ts +++ b/resources/js/app.ts @@ -7,6 +7,7 @@ import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; import type { DefineComponent } from 'vue'; import { createApp, h } from 'vue'; import { initializeTheme } from './composables/useAppearance'; +import { setupAuthGuards } from './middleware/auth'; const appName = import.meta.env.VITE_APP_NAME || 'Laravel'; const pinia = createPinia(); @@ -16,10 +17,14 @@ createInertiaApp({ title: (title) => (title ? `${title} - ${appName}` : appName), resolve: (name) => resolvePageComponent(`./pages/${name}.vue`, import.meta.glob('./pages/**/*.vue')), setup({ el, App, props, plugin }) { - createApp({ render: () => h(App, props) }) + const app = createApp({ render: () => h(App, props) }) .use(pinia) - .use(plugin) - .mount(el); + .use(plugin); + + // Initialize auth guards after pinia is set up + setupAuthGuards(); + + app.mount(el); }, progress: { color: '#4B5563', diff --git a/resources/js/components/LoginExample.vue b/resources/js/components/LoginExample.vue new file mode 100644 index 0000000..04a9d8c --- /dev/null +++ b/resources/js/components/LoginExample.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/resources/js/components/landing/CallBookingSection.vue b/resources/js/components/landing/CallBookingSection.vue index ffa748a..e214215 100644 --- a/resources/js/components/landing/CallBookingSection.vue +++ b/resources/js/components/landing/CallBookingSection.vue @@ -3,7 +3,7 @@
Background -
+
diff --git a/resources/js/components/landing/HowSection.vue b/resources/js/components/landing/HowSection.vue index 8e4d601..c5c07b7 100644 --- a/resources/js/components/landing/HowSection.vue +++ b/resources/js/components/landing/HowSection.vue @@ -1,5 +1,5 @@