feat: add multi-tenant system with properties, organizations, and public booking
Implement complete multi-property architecture: - Properties (groups of spaces) with public/private visibility - Property managers (many-to-many) with role-based permissions - Organizations with member management - Anonymous/guest booking support via public API (/api/public/*) - Property-scoped spaces, bookings, and settings - Frontend: property selector, organization management, public booking views - Migration script and updated seed data Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<div class="users">
|
||||
<Breadcrumb :items="breadcrumbItems" />
|
||||
<div class="page-header">
|
||||
<h2>Admin Dashboard - User Management</h2>
|
||||
<h2>User Management</h2>
|
||||
<button class="btn btn-primary" @click="openCreateModal">
|
||||
<UserPlus :size="16" />
|
||||
Create New User
|
||||
@@ -16,7 +16,8 @@
|
||||
<label for="filter-role">Filter by Role</label>
|
||||
<select id="filter-role" v-model="filterRole" @change="loadUsers">
|
||||
<option value="">All Roles</option>
|
||||
<option value="admin">Admin</option>
|
||||
<option value="admin">Superadmin</option>
|
||||
<option value="manager">Manager</option>
|
||||
<option value="user">User</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -57,8 +58,8 @@
|
||||
<td>{{ user.email }}</td>
|
||||
<td>{{ user.full_name }}</td>
|
||||
<td>
|
||||
<span :class="['badge', user.role === 'admin' ? 'badge-admin' : 'badge-user']">
|
||||
{{ user.role }}
|
||||
<span :class="['badge', user.role === 'admin' || user.role === 'superadmin' ? 'badge-admin' : user.role === 'manager' ? 'badge-manager' : 'badge-user']">
|
||||
{{ user.role === 'admin' ? 'superadmin' : user.role }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ user.organization || '-' }}</td>
|
||||
@@ -140,7 +141,8 @@
|
||||
<label for="role">Role *</label>
|
||||
<select id="role" v-model="formData.role" required>
|
||||
<option value="user">User</option>
|
||||
<option value="admin">Admin</option>
|
||||
<option value="manager">Manager</option>
|
||||
<option value="admin">Superadmin</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -268,7 +270,8 @@ const handleSubmit = async () => {
|
||||
full_name: formData.value.full_name,
|
||||
password: formData.value.password,
|
||||
role: formData.value.role,
|
||||
organization: formData.value.organization || undefined
|
||||
organization: formData.value.organization || undefined,
|
||||
timezone: 'UTC'
|
||||
})
|
||||
success.value = 'User created successfully!'
|
||||
}
|
||||
@@ -389,6 +392,8 @@ onMounted(() => {
|
||||
|
||||
.page-header h2 {
|
||||
margin: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
@@ -593,6 +598,11 @@ onMounted(() => {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.badge-manager {
|
||||
background: color-mix(in srgb, var(--color-warning) 15%, transparent);
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.badge-user {
|
||||
background: var(--color-bg-tertiary);
|
||||
color: var(--color-text-primary);
|
||||
@@ -619,15 +629,18 @@ onMounted(() => {
|
||||
|
||||
.modal-content {
|
||||
background: var(--color-surface);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 24px;
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 28px;
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.modal-content h3 {
|
||||
margin-bottom: 16px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user