Add Detailed Role Documentation and Update References
- Introduced comprehensive documentation for the role system in a new `docs/ROLES.md` file, covering role types, auto-assignment, product visibility, and menu visibility. - Updated `CLAUDE.md` and `docs/PRD.md` to reference the new roles documentation, enhancing clarity on role management and its implications for users. - Ensured all relevant documentation links are consistent and accessible for better user guidance.
This commit is contained in:
@@ -193,6 +193,8 @@ See `docs/ARCHITECTURE.md` for full schema. Key tables:
|
|||||||
- Opt-in visibility: No role assignment = invisible to everyone
|
- Opt-in visibility: No role assignment = invisible to everyone
|
||||||
- **Auto-assignment:** New users automatically receive `'private'` role on first login
|
- **Auto-assignment:** New users automatically receive `'private'` role on first login
|
||||||
|
|
||||||
|
**📖 Detaillierte Rollen-Dokumentation:** Siehe [`docs/ROLES.md`](./docs/ROLES.md) für vollständige Informationen zum Rollen-System (Auto-Assignment, Produktsichtbarkeit, Menüpunkt-Filterung, Session-Management, API-Endpoints, Code-Patterns).
|
||||||
|
|
||||||
Use Drizzle ORM for all database operations. Most tables use UUID primary keys (except `roles` which uses enum code as PK).
|
Use Drizzle ORM for all database operations. Most tables use UUID primary keys (except `roles` which uses enum code as PK).
|
||||||
|
|
||||||
## Development Commands (Once Set Up)
|
## Development Commands (Once Set Up)
|
||||||
@@ -1209,6 +1211,7 @@ For complete implementation with all utilities (PKCE generator, Cidaas API clien
|
|||||||
- **PRD:** See `docs/PRD.md` for complete requirements
|
- **PRD:** See `docs/PRD.md` for complete requirements
|
||||||
- **Tech Stack:** See `docs/TECH_STACK.md` for technology decisions
|
- **Tech Stack:** See `docs/TECH_STACK.md` for technology decisions
|
||||||
- **Architecture:** See `docs/ARCHITECTURE.md` for system design and data flows
|
- **Architecture:** See `docs/ARCHITECTURE.md` for system design and data flows
|
||||||
|
- **Roles:** See `docs/ROLES.md` for complete role system documentation (auto-assignment, visibility rules, API endpoints, code patterns)
|
||||||
- **experimenta Info:** See `docs/EXPERIMENTA_INFO.md` for company information (address, opening hours, legal links, contact details)
|
- **experimenta Info:** See `docs/EXPERIMENTA_INFO.md` for company information (address, opening hours, legal links, contact details)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ Eine spezialisierte E-Commerce-App, die es Besuchern des experimenta Science Cen
|
|||||||
- Multi-Payment-Provider
|
- Multi-Payment-Provider
|
||||||
- Laborkurse
|
- Laborkurse
|
||||||
|
|
||||||
|
**📖 Detaillierte Dokumentation:** Siehe [`docs/ROLES.md`](./ROLES.md) für vollständige Informationen zum Rollen-System (Auto-Assignment, Produktsichtbarkeit, Menüpunkt-Filterung, API-Endpoints, Code-Beispiele).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Zielgruppen
|
## 3. Zielgruppen
|
||||||
|
|||||||
524
docs/ROLES.md
Normal file
524
docs/ROLES.md
Normal file
@@ -0,0 +1,524 @@
|
|||||||
|
# Rollen-System Dokumentation
|
||||||
|
|
||||||
|
**Version:** 1.0
|
||||||
|
**Letztes Update:** Januar 2025
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Überblick
|
||||||
|
|
||||||
|
Das Rollen-System von my.experimenta.science ermöglicht es, Produkte und UI-Komponenten basierend auf der aktiven Rolle des Benutzers anzuzeigen oder zu verstecken. Dies ermöglicht rollenspezifische Preise, Produkte und Funktionen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Rollen-Typen
|
||||||
|
|
||||||
|
### 1.1 Verfügbare Rollen
|
||||||
|
|
||||||
|
| Code | Display Name | Beschreibung | Approval erforderlich |
|
||||||
|
|------|--------------|--------------|----------------------|
|
||||||
|
| `private` | Privatperson | Private Nutzung | Nein (auto-assigned) |
|
||||||
|
| `educator` | Pädagoge | Lehrkräfte und Schulen | Ja (Post-MVP) |
|
||||||
|
| `company` | Unternehmen | Geschäftskunden | Ja (Post-MVP) |
|
||||||
|
|
||||||
|
### 1.2 TypeScript Type Definition
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type RoleCode = 'private' | 'educator' | 'company'
|
||||||
|
|
||||||
|
interface Role {
|
||||||
|
code: RoleCode // Primary key
|
||||||
|
displayName: string // "Privatperson", "Pädagoge", "Unternehmen"
|
||||||
|
description: string
|
||||||
|
requiresApproval: boolean // false for 'private', true for others
|
||||||
|
sortOrder: number
|
||||||
|
active: boolean
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Automatische Rollen-Zuweisung
|
||||||
|
|
||||||
|
### 2.1 Auto-Assignment bei First Login (MVP)
|
||||||
|
|
||||||
|
Alle neuen Benutzer erhalten automatisch die Rolle `private` beim ersten Login:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// server/api/auth/login.post.ts
|
||||||
|
if (!user) {
|
||||||
|
// Neuer User - erstelle Profil
|
||||||
|
const [newUser] = await db.insert(users).values({...}).returning()
|
||||||
|
|
||||||
|
// Auto-assign 'private' role
|
||||||
|
await assignRoleToUser(newUser.id, 'private', {
|
||||||
|
adminNotes: 'Auto-assigned on first login',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Wichtig:**
|
||||||
|
- Status ist immer `approved` (kein Approval-Workflow in MVP)
|
||||||
|
- Jeder User hat mindestens eine Rolle
|
||||||
|
- Safety-Check: Existing users ohne Rollen bekommen auch `private` role
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Rollen-basierte Produktsichtbarkeit
|
||||||
|
|
||||||
|
### 3.1 Konzept
|
||||||
|
|
||||||
|
Produkte sind NUR sichtbar, wenn:
|
||||||
|
1. Das Produkt `product_role_visibility` Einträge hat
|
||||||
|
2. Der User eine genehmigte (`approved`) Rolle hat, die in `product_role_visibility` vorkommt
|
||||||
|
|
||||||
|
**Opt-in Visibility:**
|
||||||
|
- Produkt ohne `product_role_visibility` Einträge → Unsichtbar für ALLE
|
||||||
|
- User ohne genehmigte Rollen → Sieht KEINE Produkte
|
||||||
|
|
||||||
|
### 3.2 Database Schema
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Many-to-Many: Product ↔ Roles
|
||||||
|
CREATE TABLE product_role_visibility (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
product_id UUID NOT NULL REFERENCES products(id),
|
||||||
|
role_code TEXT NOT NULL REFERENCES roles(code),
|
||||||
|
UNIQUE(product_id, role_code)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 Automatische Zuordnung (ERP Import)
|
||||||
|
|
||||||
|
Beim Import aus NAV ERP werden Produkte automatisch Rollen zugeordnet:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// server/utils/roles.ts
|
||||||
|
const categoryRoleMapping = {
|
||||||
|
'makerspace-annual-pass': ['private', 'educator'],
|
||||||
|
'annual-pass': ['private'],
|
||||||
|
'educator-annual-pass': ['educator'],
|
||||||
|
'company-annual-pass': ['company']
|
||||||
|
}
|
||||||
|
|
||||||
|
// server/api/erp/products.post.ts
|
||||||
|
await assignRolesToProductByCategory(product.id, category)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 API Filtering Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// server/api/products/index.get.ts
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const { user } = await getUserSession(event)
|
||||||
|
|
||||||
|
// Unauthenticated users see NO products
|
||||||
|
if (!user) return []
|
||||||
|
|
||||||
|
// Get visible product IDs for user's roles
|
||||||
|
const visibleProductIds = await getVisibleProductIdsForUser(user.id)
|
||||||
|
|
||||||
|
// Fetch products with role filter
|
||||||
|
const products = await db.query.products.findMany({
|
||||||
|
where: and(
|
||||||
|
eq(products.active, true),
|
||||||
|
inArray(products.id, visibleProductIds)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return products
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Rollen-basierte Menüpunkt-Sichtbarkeit
|
||||||
|
|
||||||
|
### 4.1 Konzept
|
||||||
|
|
||||||
|
Navigation-Tabs können für bestimmte Rollen ein-/ausgeblendet werden:
|
||||||
|
- `roleVisibility: 'all'` → Sichtbar für alle Rollen
|
||||||
|
- `roleVisibility: ['educator']` → Nur für Pädagogen
|
||||||
|
- `roleVisibility: ['educator', 'company']` → Für mehrere Rollen
|
||||||
|
|
||||||
|
### 4.2 Implementation (AreaTabs.vue)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ProductArea {
|
||||||
|
id: string
|
||||||
|
label: string
|
||||||
|
icon: any
|
||||||
|
enabled: boolean
|
||||||
|
visible: boolean
|
||||||
|
badge?: string
|
||||||
|
route: string
|
||||||
|
roleVisibility?: 'all' | RoleCode[] // NEW
|
||||||
|
}
|
||||||
|
|
||||||
|
const areas: ProductArea[] = [
|
||||||
|
{ id: 'start', roleVisibility: 'all' }, // Alle Rollen
|
||||||
|
{ id: 'makerspace', roleVisibility: 'all' }, // Alle Rollen
|
||||||
|
{ id: 'educator', roleVisibility: ['educator'] }, // Nur Pädagogen
|
||||||
|
{ id: 'experimenta', roleVisibility: 'all' }, // Alle Rollen
|
||||||
|
]
|
||||||
|
|
||||||
|
const { activeRole } = useActiveRole()
|
||||||
|
|
||||||
|
const visibleAreas = computed(() => {
|
||||||
|
return areas.filter(area => {
|
||||||
|
if (!area.visible) return false
|
||||||
|
if (!area.roleVisibility) return true
|
||||||
|
if (area.roleVisibility === 'all') return true
|
||||||
|
return area.roleVisibility.includes(activeRole.value as RoleCode)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 Automatische Updates
|
||||||
|
|
||||||
|
Menüpunkte aktualisieren sich automatisch beim Rollenwechsel:
|
||||||
|
- ✅ Vue Computed Property reagiert auf `activeRole` Änderungen
|
||||||
|
- ✅ Keine manuellen Refresh-Calls nötig
|
||||||
|
- ✅ Sofortige UI-Updates
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Client-Side Composable
|
||||||
|
|
||||||
|
### 5.1 useActiveRole()
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// app/composables/useActiveRole.ts
|
||||||
|
export function useActiveRole() {
|
||||||
|
const activeRole = useState<string>('activeRole', () => 'private')
|
||||||
|
const roles = useState<RoleWithStatus[]>('roles', () => [])
|
||||||
|
|
||||||
|
// Fetch current role status from server
|
||||||
|
async function fetchRoleStatus() { ... }
|
||||||
|
|
||||||
|
// Switch to a different role
|
||||||
|
async function switchRole(roleCode: string) {
|
||||||
|
await $fetch('/api/user/active-role', {
|
||||||
|
method: 'PATCH',
|
||||||
|
body: { roleCode },
|
||||||
|
})
|
||||||
|
|
||||||
|
activeRole.value = roleCode
|
||||||
|
|
||||||
|
// Auto-refresh product pages
|
||||||
|
await Promise.all([
|
||||||
|
refreshNuxtData('products-list'),
|
||||||
|
refreshNuxtData('educator-products'),
|
||||||
|
refreshNuxtData('experimenta-products'),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
activeRole,
|
||||||
|
roles,
|
||||||
|
approvedRoles: computed(() => roles.value.filter(r => r.hasRole)),
|
||||||
|
hasMultipleRoles: computed(() => approvedRoles.value.length > 1),
|
||||||
|
fetchRoleStatus,
|
||||||
|
switchRole,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 Auto-Initialization
|
||||||
|
|
||||||
|
Rollen werden automatisch beim Login geladen:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const { loggedIn } = useUserSession()
|
||||||
|
if (loggedIn.value) {
|
||||||
|
callOnce('init-roles', () => fetchRoleStatus())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Server-Side Utilities
|
||||||
|
|
||||||
|
### 6.1 Wichtige Functions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// server/utils/roles.ts
|
||||||
|
|
||||||
|
// Get user's approved role codes
|
||||||
|
await getUserApprovedRoleCodes(userId)
|
||||||
|
// => ['private', 'educator']
|
||||||
|
|
||||||
|
// Get visible product IDs for user
|
||||||
|
await getVisibleProductIdsForUser(userId)
|
||||||
|
// => ['uuid-1', 'uuid-2', ...]
|
||||||
|
|
||||||
|
// Get visible product IDs for specific role
|
||||||
|
await getVisibleProductIdsForRole(userId, roleCode)
|
||||||
|
// => ['uuid-1', 'uuid-2', ...]
|
||||||
|
|
||||||
|
// Check if product is visible for user
|
||||||
|
await isProductVisibleForUser(productId, userId)
|
||||||
|
// => true/false
|
||||||
|
|
||||||
|
// Assign role to user (MVP: always approved)
|
||||||
|
await assignRoleToUser(userId, 'private', {
|
||||||
|
adminNotes: 'Auto-assigned',
|
||||||
|
})
|
||||||
|
|
||||||
|
// Auto-assign roles to product by category
|
||||||
|
await assignRolesToProductByCategory(productId, 'annual-pass')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Session Management
|
||||||
|
|
||||||
|
### 7.1 Active Role Session
|
||||||
|
|
||||||
|
Die aktive Rolle wird server-side in der Session gespeichert:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// server/utils/role-session.ts
|
||||||
|
|
||||||
|
// Get user's active role (with TTL validation)
|
||||||
|
const activeRole = await getUserActiveRole(event)
|
||||||
|
// => 'private' | 'educator' | 'company'
|
||||||
|
|
||||||
|
// Set user's active role in session + DB
|
||||||
|
await setUserActiveRole(event, userId, 'educator')
|
||||||
|
|
||||||
|
// Validate active role (TTL-based)
|
||||||
|
const isValid = await validateActiveRole(event, userId)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Session TTL:**
|
||||||
|
- Active role ist 30 Tage gültig
|
||||||
|
- Nach Ablauf: Fallback auf erste approved role
|
||||||
|
- Update bei jedem `switchRole()`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. API Endpoints
|
||||||
|
|
||||||
|
### 8.1 Role Management Endpoints
|
||||||
|
|
||||||
|
| Endpoint | Method | Beschreibung |
|
||||||
|
|----------|--------|--------------|
|
||||||
|
| `/api/user/role-status` | GET | Aktuellen Role-Status abrufen |
|
||||||
|
| `/api/user/active-role` | PATCH | Aktive Rolle wechseln |
|
||||||
|
|
||||||
|
#### GET /api/user/role-status
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"activeRoleCode": "private",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"code": "private",
|
||||||
|
"displayName": "Privatperson",
|
||||||
|
"description": "Private Nutzung",
|
||||||
|
"hasRole": true,
|
||||||
|
"requiresApproval": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "educator",
|
||||||
|
"displayName": "Pädagoge",
|
||||||
|
"description": "Lehrkräfte und Schulen",
|
||||||
|
"hasRole": true,
|
||||||
|
"requiresApproval": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"roleChangedByAdmin": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### PATCH /api/user/active-role
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"roleCode": "educator"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Validation:**
|
||||||
|
- ✅ User muss eingeloggt sein
|
||||||
|
- ✅ User muss die Rolle haben (approved status)
|
||||||
|
- ✅ Rolle muss existieren
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. UI Components
|
||||||
|
|
||||||
|
### 9.1 RoleSwitcher Component
|
||||||
|
|
||||||
|
Der RoleSwitcher zeigt die aktive Rolle an und ermöglicht Rollenwechsel:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- app/components/navigation/RoleSwitcher.vue -->
|
||||||
|
<template>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger>
|
||||||
|
Du kaufst als: {{ activeRoleDisplay }}
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent>
|
||||||
|
<DropdownMenuItem
|
||||||
|
v-for="role in approvedRoles"
|
||||||
|
@click="switchRole(role.code)"
|
||||||
|
>
|
||||||
|
{{ role.displayName }}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- ✅ Zeigt nur approved roles
|
||||||
|
- ✅ Markiert aktive Rolle mit Checkmark
|
||||||
|
- ✅ Disabled für roles die User nicht hat
|
||||||
|
- ✅ Triggert automatische Product-Refresh
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Testing
|
||||||
|
|
||||||
|
### 10.1 Test User Setup
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Test User mit multiple roles
|
||||||
|
const user = await createTestUser({
|
||||||
|
email: 'test@example.com',
|
||||||
|
roles: ['private', 'educator']
|
||||||
|
})
|
||||||
|
|
||||||
|
// Setze aktive Rolle
|
||||||
|
await setUserActiveRole(event, user.id, 'educator')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.2 Test Scenarios
|
||||||
|
|
||||||
|
**Scenario 1: Privatperson Login**
|
||||||
|
- ✅ User erhält `private` role
|
||||||
|
- ✅ Sieht nur Produkte mit `private` role
|
||||||
|
- ✅ Sieht Navigation: Start, Makerspace, experimenta
|
||||||
|
|
||||||
|
**Scenario 2: Pädagoge Login**
|
||||||
|
- ✅ User hat `private` + `educator` roles
|
||||||
|
- ✅ Kann zwischen Rollen wechseln
|
||||||
|
- ✅ Als Pädagoge: Zusätzliche Produkte sichtbar
|
||||||
|
- ✅ Als Pädagoge: "Bildung" Tab sichtbar
|
||||||
|
|
||||||
|
**Scenario 3: Rollenwechsel**
|
||||||
|
- ✅ Produktliste aktualisiert sich automatisch
|
||||||
|
- ✅ Navigation aktualisiert sich automatisch
|
||||||
|
- ✅ Session + DB werden aktualisiert
|
||||||
|
- ✅ Product detail page: 404 redirect wenn nicht sichtbar
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. MVP Limitations
|
||||||
|
|
||||||
|
### 11.1 Was NICHT implementiert ist (Post-MVP)
|
||||||
|
|
||||||
|
**Approval Workflow:**
|
||||||
|
- ❌ Keine UI für Rollen-Antrag (Pädagogen/Unternehmen)
|
||||||
|
- ❌ Kein Admin-Panel für Genehmigung
|
||||||
|
- ❌ Status bleibt immer `approved`
|
||||||
|
|
||||||
|
**Role Management:**
|
||||||
|
- ❌ Keine Self-Service Rollen-Verwaltung
|
||||||
|
- ❌ Keine Admin-Funktionen zum Hinzufügen/Entfernen von Rollen
|
||||||
|
- ❌ Keine Rollen-History für Admins
|
||||||
|
|
||||||
|
**Advanced Features:**
|
||||||
|
- ❌ Keine Organisation-Level Rollen (z.B. alle Lehrer einer Schule)
|
||||||
|
- ❌ Keine zeitlich begrenzte Rollen
|
||||||
|
- ❌ Keine Rollen-Hierarchien
|
||||||
|
|
||||||
|
### 11.2 Database prepared for Post-MVP
|
||||||
|
|
||||||
|
Trotz MVP Limitations ist die Datenbank bereits vorbereitet:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// user_roles table (prepared but status always 'approved' in MVP)
|
||||||
|
interface UserRole {
|
||||||
|
status: 'pending' | 'approved' | 'rejected' | 'revoked'
|
||||||
|
organizationName?: string // Prepared
|
||||||
|
requestMessage?: string // Prepared
|
||||||
|
proofDocument?: string // Prepared
|
||||||
|
adminNotes?: string // Prepared
|
||||||
|
statusHistory: StatusHistoryEntry[] // JSONB audit trail
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Best Practices
|
||||||
|
|
||||||
|
### 12.1 Beim Hinzufügen neuer Rollen
|
||||||
|
|
||||||
|
1. **Database:** Füge neue Rolle zu `roles` table hinzu
|
||||||
|
2. **Type:** Update `RoleCode` type in schema
|
||||||
|
3. **Mapping:** Update `categoryRoleMapping` in `server/utils/roles.ts`
|
||||||
|
4. **UI:** Update RoleSwitcher display names
|
||||||
|
5. **Navigation:** Update `roleVisibility` in AreaTabs.vue
|
||||||
|
|
||||||
|
### 12.2 Beim Hinzufügen neuer Produkte
|
||||||
|
|
||||||
|
1. **Category:** Definiere eine klare Kategorie
|
||||||
|
2. **Mapping:** Füge Kategorie zu `categoryRoleMapping` hinzu
|
||||||
|
3. **Visibility:** Produkt wird automatisch Rollen zugeordnet beim Import
|
||||||
|
|
||||||
|
### 12.3 Beim Hinzufügen neuer Navigation-Items
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
id: 'new-tab',
|
||||||
|
label: 'Neuer Tab',
|
||||||
|
roleVisibility: 'all' // oder ['educator', 'company']
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Troubleshooting
|
||||||
|
|
||||||
|
### Problem: User sieht keine Produkte
|
||||||
|
|
||||||
|
**Prüfen:**
|
||||||
|
1. Hat User eine approved Rolle? → `getUserApprovedRoleCodes(userId)`
|
||||||
|
2. Hat Produkt `product_role_visibility` Einträge?
|
||||||
|
3. Matchen Rolle und Produkt-Visibility?
|
||||||
|
|
||||||
|
### Problem: Menüpunkt erscheint nicht nach Rollenwechsel
|
||||||
|
|
||||||
|
**Prüfen:**
|
||||||
|
1. Ist `roleVisibility` korrekt gesetzt?
|
||||||
|
2. Ist `activeRole` korrekt aktualisiert? → Vue DevTools
|
||||||
|
3. Ist computed property `visibleAreas` reaktiv?
|
||||||
|
|
||||||
|
### Problem: Produkt bleibt sichtbar nach Rollenwechsel
|
||||||
|
|
||||||
|
**Prüfen:**
|
||||||
|
1. Wurde `refreshNuxtData()` aufgerufen in `switchRole()`?
|
||||||
|
2. Sind die richtigen keys verwendet? (`products-list`, etc.)
|
||||||
|
3. Hat API-Endpoint role-based filtering?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. Weitere Dokumentation
|
||||||
|
|
||||||
|
- **Architektur:** `docs/ARCHITECTURE.md` - Database Schema Details
|
||||||
|
- **PRD:** `docs/PRD.md` - Product Requirements
|
||||||
|
- **Testing:** `docs/TESTING.md` - Test Credentials & Scenarios
|
||||||
|
- **Cidaas Integration:** `docs/CIDAAS_INTEGRATION.md` - Auth Flow
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. Changelog
|
||||||
|
|
||||||
|
| Version | Datum | Änderung |
|
||||||
|
|---------|-------|----------|
|
||||||
|
| 1.0 | Jan 2025 | Initial documentation - MVP implementation |
|
||||||
Reference in New Issue
Block a user