Skip to content

Kapitel 41: Projekt - User Management App

📙 Lernziel: Ein vollständiges User Management Projekt mit Vue 3 erstellen!


41.1 Projekt-Übersicht & Setup

Ziele:

  • ✅ User-Liste anzeigen
  • ✅ User erstellen/bearbeiten/löschen
  • ✅ Routing (Vue Router)
  • ✅ State Management (Pinia)
  • ✅ API-Anbindung (axios)

Projekt-Setup:

bash
# 1. Projekt erstellen
pnpm create vite@latest
# Framework: Vue
# Variant: JavaScript

# 2. In Projektordner wechseln
cd user-management

# 3. Abhängigkeiten installieren
pnpm install

# 4. Vue Router installieren
pnpm add vue-router@4

# 5. Pinia installieren
pnpm add pinia

# 6. Axios installieren
pnpm add axios

# 7. Dev-Server starten
pnpm run dev

Projekt-Struktur:

user-management/
├── src/
│   ├── components/
│   │   ├── UserForm.vue
│   │   ├── UserList.vue
│   │   └── NavBar.vue
│   ├── views/
│   │   ├── HomeView.vue
│   │   ├── UsersView.vue
│   │   ├── UserCreateView.vue
│   │   └── UserEditView.vue
│   ├── stores/
│   │   └── user.js
│   ├── router/
│   │   └── index.js
│   ├── utils/
│   │   └── apiClient.js
│   ├── App.vue
│   └── main.js
├── index.html
└── package.json

41.2 Router konfigurieren

src/router/index.js:

javascript
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import UsersView from '../views/UsersView.vue'
import UserCreateView from '../views/UserCreateView.vue'
import UserEditView from '../views/UserEditView.vue'

const routes = [
  {
    path: '/',
    component: HomeView,
    name: 'home'
  },
  {
    path: '/users',
    component: UsersView,
    name: 'users'
  },
  {
    path: '/users/create',
    component: UserCreateView,
    name: 'user-create'
  },
  {
    path: '/users/:id/edit',
    component: UserEditView,
    name: 'user-edit'
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

src/main.js:

javascript
// src/main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

const app = createApp(App)
const pinia = createPinia()

app.use(pinia)
app.use(router)
app.mount('#app')

41.3 Pinia Store erstellen

src/stores/user.js:

javascript
// src/stores/user.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import apiClient from '../utils/apiClient'

export const useUserStore = defineStore('user', () => {
  // State
  const users = ref([])
  const isLoading = ref(false)
  const error = ref(null)
  
  // Getters
  const userCount = computed(() => users.value.length)
  
  // Actions
  const fetchUsers = async () => {
    isLoading.value = true
    error.value = null
    
    try {
      const response = await apiClient.get('/users')
      users.value = response.data
    } catch (err) {
      error.value = err.message
    } finally {
      isLoading.value = false
    }
  }
  
  const createUser = async (userData) => {
    isLoading.value = true
    error.value = null
    
    try {
      const response = await apiClient.post('/users', userData)
      users.value.push(response.data)
      return response.data
    } catch (err) {
      error.value = err.message
      throw err
    } finally {
      isLoading.value = false
    }
  }
  
  const updateUser = async (id, userData) => {
    isLoading.value = true
    error.value = null
    
    try {
      const response = await apiClient.put(`/users/${id}`, userData)
      const index = users.value.findIndex(user => user.id === id)
      if (index !== -1) {
        users.value[index] = response.data
      }
      return response.data
    } catch (err) {
      error.value = err.message
      throw err
    } finally {
      isLoading.value = false
    }
  }
  
  const deleteUser = async (id) => {
    isLoading.value = true
    error.value = null
    
    try {
      await apiClient.delete(`/users/${id}`)
      users.value = users.value.filter(user => user.id !== id)
    } catch (err) {
      error.value = err.message
      throw err
    } finally {
      isLoading.value = false
    }
  }
  
  return {
    users,
    isLoading,
    error,
    userCount,
    fetchUsers,
    createUser,
    updateUser,
    deleteUser
  }
})

41.4 API Client mit Interceptors

src/utils/apiClient.js:

javascript
// src/utils/apiClient.js
import axios from 'axios'

const apiClient = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json'
  }
})

// Request Interceptor
apiClient.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

// Response Interceptor
apiClient.interceptors.response.use(
  (response) => {
    return response
  },
  (error) => {
    if (error.response && error.response.status === 401) {
      localStorage.removeItem('token')
      window.location.href = '/login'
    }
    return Promise.reject(error)
  }
)

export default apiClient

41.5 App.vue erstellen

src/App.vue:

vue
<!-- src/App.vue -->
<script setup>
// Keine Importe nötig für Router-Links
</script>

<template>
  <div id="app">
    <header>
      <nav>
        <router-link to="/">Start</router-link> |
        <router-link to="/users">Benutzer</router-link>
      </nav>
    </header>
    
    <main>
      <router-view />
    </main>
    
    <footer>
      <p>&copy; 2026 User Management</p>
    </footer>
  </div>
</template>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: Arial, sans-serif;
  background-color: #f5f5f5;
}

#app {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

header {
  background: #42b883;
  padding: 20px;
  margin-bottom: 20px;
  border-radius: 8px;
}

nav a {
  color: white;
  text-decoration: none;
  margin: 0 10px;
  font-weight: bold;
}

nav a.router-link-active {
  text-decoration: underline;
}

main {
  min-height: 400px;
}

footer {
  background: #35495e;
  color: white;
  padding: 10px;
  text-align: center;
  margin-top: 20px;
  border-radius: 8px;
}
</style>

41.6 Übung: User Management Projekt starten

Aufgabe: Erstelle das Grundgerüst für das User Management Projekt.

Lösung:

1. Projekt erstellen:

bash
pnpm create vite@latest
# Name: user-management
# Framework: Vue
# Variant: JavaScript

cd user-management
pnpm install
pnpm add vue-router@4 pinia axios
pnpm run dev

2. Router konfigurieren (src/router/index.js):

javascript
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const routes = [
  {
    path: '/',
    component: HomeView,
    name: 'home'
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

3. main.js konfigurieren:

javascript
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

const app = createApp(App)
const pinia = createPinia()

app.use(pinia)
app.use(router)
app.mount('#app')

4. App.vue erstellen:

vue
<!-- src/App.vue -->
<template>
  <div id="app">
    <router-view />
  </div>
</template>

<style>
#app {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}
</style>

5. HomeView.vue erstellen:

vue
<!-- src/views/HomeView.vue -->
<template>
  <div class="home">
    <h1>Willkommen im User Management System</h1>
    <p>Nutze die Navigation, um Benutzer zu verwalten.</p>
  </div>
</template>

<script setup>
// Keine Logik nötig für Startseite
</script>

<style scoped>
.home {
  text-align: center;
  padding: 50px;
}

.home h1 {
  color: #42b883;
}

.home p {
  color: #666;
  margin-top: 20px;
}
</style>

Nächste Schritte:

  • ✅ Routing für User-Listen hinzufügen
  • ✅ Pinia Store für User-Daten erstellen
  • ✅ API-Anbindung mit axios
  • ✅ Formulare für Create/Update

✅ Zusammenfassung

In diesem Kapitel hast du gelernt:

  • ✅ User Management Projekt Setup
  • ✅ Vue Router konfigurieren
  • ✅ Pinia Store erstellen
  • ✅ API Client mit Interceptors
  • App.vue mit Navigation
  • ✅ Praxis: Projekt-Grundgerüst

🎯 Nächster Schritt: In Kapitel 42 lernst du das User Management Projekt (Teil 2) - User-Listen & Formulare!


← Zurück zu Kapitel 40: TodoList Projekt

Frei für alle Anfänger